Merge "Add missing parameters to notifyAcquired and notifyError"
diff --git a/apct-tests/perftests/windowmanager/README.md b/apct-tests/perftests/windowmanager/README.md
index 8b5292f..7a0019a 100644
--- a/apct-tests/perftests/windowmanager/README.md
+++ b/apct-tests/perftests/windowmanager/README.md
@@ -4,7 +4,7 @@
 To reduce the variance of the test, if `perf-setup.sh` (platform_testing/scripts/perf-setup)
 is available, it is better to use the following instructions to lock CPU and GPU frequencies.
 ```
-m perf-setup.sh
+m perf-setup
 PERF_SETUP_PATH=/data/local/tmp/perf-setup.sh
 adb push $OUT/$PERF_SETUP_PATH $PERF_SETUP_PATH
 adb shell chmod +x $PERF_SETUP_PATH
diff --git a/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java
index b11d7464..6f0001d 100644
--- a/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java
+++ b/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java
@@ -84,6 +84,7 @@
 
     private static class TestWindow extends BaseIWindow {
         final WindowManager.LayoutParams mLayoutParams = new WindowManager.LayoutParams();
+        final InsetsState mRequestedVisibility = new InsetsState();
         final Rect mOutFrame = new Rect();
         final Rect mOutContentInsets = new Rect();
         final Rect mOutStableInsets = new Rect();
@@ -108,7 +109,8 @@
 
                 long startTime = SystemClock.elapsedRealtimeNanos();
                 session.addToDisplay(this, mLayoutParams, View.VISIBLE,
-                        Display.DEFAULT_DISPLAY, mOutFrame, mOutContentInsets, mOutStableInsets,
+                        Display.DEFAULT_DISPLAY, mRequestedVisibility, mOutFrame,
+                        mOutContentInsets, mOutStableInsets,
                         mOutDisplayCutout, inputChannel, mOutInsetsState, mOutControls);
                 final long elapsedTimeNsOfAdd = SystemClock.elapsedRealtimeNanos() - startTime;
                 state.addExtraResult("add", elapsedTimeNsOfAdd);
diff --git a/apex/Android.bp b/apex/Android.bp
index 266e672..c5b4901 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -107,7 +107,7 @@
 
     // Hide impl library and stub sources
     impl_library_visibility: [
-        ":__package__",
+        ":__pkg__",
         "//frameworks/base", // For framework-all
     ],
     stubs_source_visibility: ["//visibility:private"],
diff --git a/apex/appsearch/framework/Android.bp b/apex/appsearch/framework/Android.bp
index e10fb07..12afde4 100644
--- a/apex/appsearch/framework/Android.bp
+++ b/apex/appsearch/framework/Android.bp
@@ -26,10 +26,8 @@
     srcs: [ ":framework-appsearch-sources" ],
     sdk_version: "core_platform", // TODO(b/146218515) should be module_current
     impl_only_libs: ["framework-minus-apex"], // TODO(b/146218515) should be removed
-    static_libs: ["icing-java-proto-lite"],
     defaults: ["framework-module-defaults"],
     permitted_packages: ["android.app.appsearch"],
-    jarjar_rules: "jarjar-rules.txt",
     aidl: {
         include_dirs: ["frameworks/base/core/java"], // TODO(b/146218515) should be removed
     },
diff --git a/apex/appsearch/framework/jarjar-rules.txt b/apex/appsearch/framework/jarjar-rules.txt
deleted file mode 100644
index acf759a..0000000
--- a/apex/appsearch/framework/jarjar-rules.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-rule com.google.protobuf.** android.app.appsearch.protobuf.@1
-rule com.google.android.icing.proto.** android.app.appsearch.proto.@1
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
index b38bb05..18bc59b 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
@@ -22,9 +22,9 @@
 import android.os.RemoteException;
 
 import com.android.internal.infra.AndroidFuture;
+import com.android.internal.util.Preconditions;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ExecutionException;
@@ -40,6 +40,7 @@
 // TODO(b/148046169): This class header needs a detailed example/tutorial.
 @SystemService(Context.APP_SEARCH_SERVICE)
 public class AppSearchManager {
+    private static final String DEFAULT_DATABASE = "";
     private final IAppSearchManager mService;
 
     /** @hide */
@@ -96,46 +97,23 @@
      * <p>It is a no-op to set the same schema as has been previously set; this is handled
      * efficiently.
      *
-     * @param schemas The schema configs for the types used by the calling app.
+     * @param request The schema update request.
      * @return the result of performing this operation.
      *
      * @hide
      */
     @NonNull
-    public AppSearchResult<Void> setSchema(@NonNull AppSearchSchema... schemas) {
-        return setSchema(Arrays.asList(schemas), /*forceOverride=*/false);
-    }
-
-    /**
-     * Sets the schema being used by documents provided to the {@link #putDocuments} method.
-     *
-     * <p>This method is similar to {@link #setSchema(AppSearchSchema...)}, except for the
-     * {@code forceOverride} parameter. If a backwards-incompatible schema is specified but the
-     * {@code forceOverride} parameter is set to {@code true}, instead of returning an
-     * {@link AppSearchResult} with the {@link AppSearchResult#RESULT_INVALID_SCHEMA} code, all
-     * documents which are not compatible with the new schema will be deleted and the incompatible
-     * schema will be applied.
-     *
-     * @param schemas The schema configs for the types used by the calling app.
-     * @param forceOverride Whether to force the new schema to be applied even if there are
-     *     incompatible changes versus the previously set schema. Documents which are incompatible
-     *     with the new schema will be deleted.
-     * @return the result of performing this operation.
-     *
-     * @hide
-     */
-    @NonNull
-    public AppSearchResult<Void> setSchema(
-            @NonNull List<AppSearchSchema> schemas, boolean forceOverride) {
+    public AppSearchResult<Void> setSchema(@NonNull SetSchemaRequest request) {
+        Preconditions.checkNotNull(request);
         // TODO: This should use com.android.internal.infra.RemoteStream or another mechanism to
         //  avoid binder limits.
-        List<Bundle> schemaBundles = new ArrayList<>(schemas.size());
-        for (AppSearchSchema schema : schemas) {
+        List<Bundle> schemaBundles = new ArrayList<>(request.getSchemas().size());
+        for (AppSearchSchema schema : request.getSchemas()) {
             schemaBundles.add(schema.getBundle());
         }
         AndroidFuture<AppSearchResult> future = new AndroidFuture<>();
         try {
-            mService.setSchema(schemaBundles, forceOverride, future);
+            mService.setSchema(DEFAULT_DATABASE, schemaBundles, request.isForceOverride(), future);
         } catch (RemoteException e) {
             future.completeExceptionally(e);
         }
@@ -151,23 +129,24 @@
      * <p>Each {@link GenericDocument}'s {@code schemaType} field must be set to the name of a
      * schema type previously registered via the {@link #setSchema} method.
      *
-     * @param documents {@link GenericDocument}s that need to be indexed.
-     * @return An {@link AppSearchBatchResult} mapping the document URIs to {@link Void} if they
-     *     were successfully indexed, or a {@link Throwable} describing the failure if they could
-     *     not be indexed.
+     * @param request {@link PutDocumentsRequest} containing documents to be indexed
+     * @return The pending result of performing this operation. The keys of the returned
+     * {@link AppSearchBatchResult} are the URIs of the input documents. The values are
+     * {@code null} if they were successfully indexed, or a failed {@link AppSearchResult}
+     * otherwise.
      * @hide
      */
-    public AppSearchBatchResult<String, Void> putDocuments(
-            @NonNull List<GenericDocument> documents) {
+    public AppSearchBatchResult<String, Void> putDocuments(@NonNull PutDocumentsRequest request) {
         // TODO(b/146386470): Transmit these documents as a RemoteStream instead of sending them in
         // one big list.
+        List<GenericDocument> documents = request.getDocuments();
         List<Bundle> documentBundles = new ArrayList<>(documents.size());
-        for (GenericDocument document : documents) {
-            documentBundles.add(document.getBundle());
+        for (int i = 0; i < documents.size(); i++) {
+            documentBundles.add(documents.get(i).getBundle());
         }
         AndroidFuture<AppSearchBatchResult> future = new AndroidFuture<>();
         try {
-            mService.putDocuments(documentBundles, future);
+            mService.putDocuments(DEFAULT_DATABASE, documentBundles, future);
         } catch (RemoteException e) {
             future.completeExceptionally(e);
         }
@@ -180,18 +159,21 @@
      * <p>You should not call this method directly; instead, use the
      * {@code AppSearch#getDocuments()} API provided by JetPack.
      *
-     * @param uris URIs of the documents to look up.
-     * @return An {@link AppSearchBatchResult} mapping the document URIs to
-     *     {@link GenericDocument} values if they were successfully retrieved, a {@code null}
-     *     failure if they were not found, or a {@link Throwable} failure describing the problem if
-     *     an error occurred.
+     * @param request {@link GetByUriRequest} containing URIs to be retrieved.
+     * @return The pending result of performing this operation. The keys of the returned
+     * {@link AppSearchBatchResult} are the input URIs. The values are the returned
+     * {@link GenericDocument}s on success, or a failed {@link AppSearchResult} otherwise.
+     * URIs that are not found will return a failed {@link AppSearchResult} with a result code
+     * of {@link AppSearchResult#RESULT_NOT_FOUND}.
      */
-    public AppSearchBatchResult<String, GenericDocument> getDocuments(@NonNull List<String> uris) {
+    public AppSearchBatchResult<String, GenericDocument> getByUri(
+            @NonNull GetByUriRequest request) {
         // TODO(b/146386470): Transmit the result documents as a RemoteStream instead of sending
         //     them in one big list.
+        List<String> uris = new ArrayList<>(request.getUris());
         AndroidFuture<AppSearchBatchResult> future = new AndroidFuture<>();
         try {
-            mService.getDocuments(uris, future);
+            mService.getDocuments(DEFAULT_DATABASE, request.getNamespace(), uris, future);
         } catch (RemoteException e) {
             future.completeExceptionally(e);
         }
@@ -279,7 +261,8 @@
         //     them in one big list.
         AndroidFuture<AppSearchResult> searchResultsFuture = new AndroidFuture<>();
         try {
-            mService.query(queryExpression, searchSpec.getBundle(), searchResultsFuture);
+            mService.query(DEFAULT_DATABASE, queryExpression,
+                    searchSpec.getBundle(), searchResultsFuture);
         } catch (RemoteException e) {
             searchResultsFuture.completeExceptionally(e);
         }
@@ -300,15 +283,18 @@
      * <p>You should not call this method directly; instead, use the {@code AppSearch#delete()} API
      * provided by JetPack.
      *
-     * @param uris URIs of the documents to delete
-     * @return An {@link AppSearchBatchResult} mapping each URI to a {@code null} success if
-     *     deletion was successful, to a {@code null} failure if the document did not exist, or to a
-     *     {@code throwable} failure if deletion failed for another reason.
+     * @param request Request containing URIs to be removed.
+     * @return The pending result of performing this operation. The keys of the returned
+     * {@link AppSearchBatchResult} are the input URIs. The values are {@code null} on success,
+     * or a failed {@link AppSearchResult} otherwise. URIs that are not found will return a
+     * failed {@link AppSearchResult} with a result code of
+     * {@link AppSearchResult#RESULT_NOT_FOUND}.
      */
-    public AppSearchBatchResult<String, Void> delete(@NonNull List<String> uris) {
+    public AppSearchBatchResult<String, Void> removeByUri(@NonNull RemoveByUriRequest request) {
+        List<String> uris = new ArrayList<>(request.getUris());
         AndroidFuture<AppSearchBatchResult> future = new AndroidFuture<>();
         try {
-            mService.delete(uris, future);
+            mService.delete(DEFAULT_DATABASE, request.getNamespace(), uris, future);
         } catch (RemoteException e) {
             future.completeExceptionally(e);
         }
@@ -316,7 +302,7 @@
     }
 
     /**
-     * Deletes {@link android.app.appsearch.AppSearch.Document}s by schema type.
+     * Deletes {@link android.app.appsearch.GenericDocument}s by schema type.
      *
      * <p>You should not call this method directly; instead, use the
      * {@code AppSearch#deleteByType()} API provided by JetPack.
@@ -329,7 +315,7 @@
     public AppSearchBatchResult<String, Void> deleteByTypes(@NonNull List<String> schemaTypes) {
         AndroidFuture<AppSearchBatchResult> future = new AndroidFuture<>();
         try {
-            mService.deleteByTypes(schemaTypes, future);
+            mService.deleteByTypes(DEFAULT_DATABASE, schemaTypes, future);
         } catch (RemoteException e) {
             future.completeExceptionally(e);
         }
@@ -340,7 +326,7 @@
     public AppSearchResult<Void> deleteAll() {
         AndroidFuture<AppSearchResult> future = new AndroidFuture<>();
         try {
-            mService.deleteAll(future);
+            mService.deleteAll(DEFAULT_DATABASE, future);
         } catch (RemoteException e) {
             future.completeExceptionally(e);
         }
diff --git a/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java b/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java
new file mode 100644
index 0000000..3c0e746
--- /dev/null
+++ b/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java
@@ -0,0 +1,100 @@
+/*
+ * 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 android.annotation.NonNull;
+
+import android.util.ArraySet;
+import com.android.internal.util.Preconditions;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * Encapsulates a request to retrieve documents by namespace and URI.
+ *
+ * @see AppSearchManager#getByUri
+ * @hide
+ */
+public final class GetByUriRequest {
+    private final String mNamespace;
+    private final Set<String> mUris;
+
+    GetByUriRequest(@NonNull String namespace, @NonNull Set<String> uris) {
+        mNamespace = namespace;
+        mUris = uris;
+    }
+
+    /** @hide */
+    
+    @NonNull
+    public String getNamespace() {
+        return mNamespace;
+    }
+
+    /** @hide */
+    
+    @NonNull
+    public Set<String> getUris() {
+        return mUris;
+    }
+
+    /** Builder for {@link GetByUriRequest} objects. */
+    public static final class Builder {
+        private String mNamespace = GenericDocument.DEFAULT_NAMESPACE;
+        private final Set<String> mUris = new ArraySet<>();
+        private boolean mBuilt = false;
+
+        /**
+         * Sets which namespace these documents will be retrieved from.
+         *
+         * <p>If this is not set, it defaults to {@link GenericDocument#DEFAULT_NAMESPACE}.
+         */
+        @NonNull
+        public Builder setNamespace(@NonNull String namespace) {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            Preconditions.checkNotNull(namespace);
+            mNamespace = namespace;
+            return this;
+        }
+
+        /** Adds one or more URIs to the request. */
+        @NonNull
+        public Builder addUris(@NonNull String... uris) {
+            Preconditions.checkNotNull(uris);
+            return addUris(Arrays.asList(uris));
+        }
+
+        /** Adds one or more URIs to the request. */
+        @NonNull
+        public Builder addUris(@NonNull Collection<String> uris) {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            Preconditions.checkNotNull(uris);
+            mUris.addAll(uris);
+            return this;
+        }
+
+        /** Builds a new {@link GetByUriRequest}. */
+        @NonNull
+        public GetByUriRequest build() {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            mBuilt = true;
+            return new GetByUriRequest(mNamespace, mUris);
+        }
+    }
+}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
index 8e18346..352a980 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
+++ b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
@@ -28,6 +28,7 @@
     /**
      * Sets the schema.
      *
+     * @param databaseName  The databaseName this document resides in.
      * @param schemaBundles List of AppSearchSchema bundles.
      * @param forceOverride Whether to apply the new schema even if it is incompatible. All
      *     incompatible documents will be deleted.
@@ -35,6 +36,7 @@
      *     The results of the call.
      */
     void setSchema(
+        in String databaseName,
         in List<Bundle> schemaBundles,
         boolean forceOverride,
         in AndroidFuture<AppSearchResult> callback);
@@ -42,6 +44,7 @@
     /**
      * Inserts documents into the index.
      *
+     * @param databaseName  The name of the database where this document lives.
      * @param documentBundes List of GenericDocument bundles.
      * @param callback
      *     {@link AndroidFuture}&lt;{@link AppSearchBatchResult}&lt;{@link String}, {@link Void}&gt;&gt;.
@@ -51,11 +54,15 @@
      *     where the keys are document URIs, and the values are {@code null}.
      */
     void putDocuments(
-        in List<Bundle> documentBundles, in AndroidFuture<AppSearchBatchResult> callback);
+        in String databaseName,
+        in List<Bundle> documentBundles,
+        in AndroidFuture<AppSearchBatchResult> callback);
 
     /**
      * Retrieves documents from the index.
      *
+     * @param databaseName  The databaseName this document resides in.
+     * @param namespace    The namespace this document resides in.
      * @param uris The URIs of the documents to retrieve
      * @param callback
      *     {@link AndroidFuture}&lt;{@link AppSearchBatchResult}&lt;{@link String}, {@link Bundle}&gt;&gt;.
@@ -64,16 +71,22 @@
      *     {@link AppSearchBatchResult}&lt;{@link String}, {@link Bundle}&gt;
      *     where the keys are document URIs, and the values are Document bundles.
      */
-    void getDocuments(in List<String> uris, in AndroidFuture<AppSearchBatchResult> callback);
+    void getDocuments(
+        in String databaseName,
+        in String namespace,
+        in List<String> uris,
+        in AndroidFuture<AppSearchBatchResult> callback);
 
     /**
      * Searches a document based on a given specifications.
      *
+     * @param databaseName The databaseName this query for.
      * @param queryExpression String to search for
      * @param searchSpecBundle SearchSpec bundle
      * @param callback {@link AndroidFuture}&lt;{@link AppSearchResult}&lt;{@link SearchResults}&gt;&gt;
      */
     void query(
+        in String databaseName,
         in String queryExpression,
         in Bundle searchSpecBundle,
         in AndroidFuture<AppSearchResult> callback);
@@ -81,6 +94,8 @@
     /**
      * Deletes documents by URI.
      *
+     * @param databaseName The databaseName the document is in.
+     * @param namespace    Namespace of the document to remove.
      * @param uris The URIs of the documents to delete
      * @param callback
      *     {@link AndroidFuture}&lt;{@link AppSearchBatchResult}&lt;{@link String}, {@link Void}&gt;&gt;.
@@ -90,11 +105,16 @@
      *     where the keys are document URIs. If a document doesn't exist, it will be reported as a
      *     failure where the {@code throwable} is {@code null}.
      */
-    void delete(in List<String> uris, in AndroidFuture<AppSearchBatchResult> callback);
+    void delete(
+        in String databaseName,
+        in String namespace,
+        in List<String> uris,
+        in AndroidFuture<AppSearchBatchResult> callback);
 
     /**
      * Deletes documents by schema type.
      *
+     * @param databaseName The databaseName the document is in.
      * @param schemaTypes The schema types of the documents to delete
      * @param callback
      *     {@link AndroidFuture}&lt;{@link AppSearchBatchResult}&lt;{@link String}, {@link Void}&gt;&gt;.
@@ -105,13 +125,16 @@
      *     failure where the {@code throwable} is {@code null}.
      */
     void deleteByTypes(
-        in List<String> schemaTypes, in AndroidFuture<AppSearchBatchResult> callback);
+        in String databaseName,
+        in List<String> schemaTypes,
+        in AndroidFuture<AppSearchBatchResult> callback);
 
     /**
      * Deletes all documents belonging to the calling app.
      *
+     * @param databaseName The databaseName to remove all documents from.
      * @param callback {@link AndroidFuture}&lt;{@link AppSearchResult}&lt;{@link Void}&gt;&gt;.
      *     Will be completed with the result of the call.
      */
-    void deleteAll(in AndroidFuture<AppSearchResult> callback);
+    void deleteAll(in String databaseName, in AndroidFuture<AppSearchResult> callback);
 }
diff --git a/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java b/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java
new file mode 100644
index 0000000..7e97542
--- /dev/null
+++ b/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java
@@ -0,0 +1,77 @@
+/*
+ * 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 android.annotation.NonNull;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Encapsulates a request to index a document into an {@link AppSearchManager} database.
+ *
+ * @see AppSearchManager#putDocuments
+ * @hide
+ */
+public final class PutDocumentsRequest {
+    private final List<GenericDocument> mDocuments;
+
+    PutDocumentsRequest(List<GenericDocument> documents) {
+        mDocuments = documents;
+    }
+
+    /** @hide */
+    
+    @NonNull
+    public List<GenericDocument> getDocuments() {
+        return mDocuments;
+    }
+
+    /** Builder for {@link PutDocumentsRequest} objects. */
+    public static final class Builder {
+        private final List<GenericDocument> mDocuments = new ArrayList<>();
+        private boolean mBuilt = false;
+
+        /** Adds one or more documents to the request. */
+        @NonNull
+        public Builder addGenericDocument(@NonNull GenericDocument... documents) {
+            Preconditions.checkNotNull(documents);
+            return addGenericDocument(Arrays.asList(documents));
+        }
+
+        /** Adds one or more documents to the request. */
+        @NonNull
+        public Builder addGenericDocument(@NonNull Collection<GenericDocument> documents) {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            Preconditions.checkNotNull(documents);
+            mDocuments.addAll(documents);
+            return this;
+        }
+
+        /** Builds a new {@link PutDocumentsRequest}. */
+        @NonNull
+        public PutDocumentsRequest build() {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            mBuilt = true;
+            return new PutDocumentsRequest(mDocuments);
+        }
+    }
+}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java b/apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java
new file mode 100644
index 0000000..a047041
--- /dev/null
+++ b/apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java
@@ -0,0 +1,100 @@
+/*
+ * 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 android.annotation.NonNull;
+
+import android.util.ArraySet;
+import com.android.internal.util.Preconditions;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * Encapsulates a request to remove documents by namespace and URI.
+ *
+ * @see AppSearchManager#removeByUri
+ * @hide
+ */
+public final class RemoveByUriRequest {
+    private final String mNamespace;
+    private final Set<String> mUris;
+
+    RemoveByUriRequest(String namespace, Set<String> uris) {
+        mNamespace = namespace;
+        mUris = uris;
+    }
+
+    /** @hide */
+    
+    @NonNull
+    public String getNamespace() {
+        return mNamespace;
+    }
+
+    /** @hide */
+    
+    @NonNull
+    public Set<String> getUris() {
+        return mUris;
+    }
+
+    /** Builder for {@link RemoveByUriRequest} objects. */
+    public static final class Builder {
+        private String mNamespace = GenericDocument.DEFAULT_NAMESPACE;
+        private final Set<String> mUris = new ArraySet<>();
+        private boolean mBuilt = false;
+
+        /**
+         * Sets which namespace these documents will be removed from.
+         *
+         * <p>If this is not set, it defaults to {@link GenericDocument#DEFAULT_NAMESPACE}.
+         */
+        @NonNull
+        public Builder setNamespace(@NonNull String namespace) {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            Preconditions.checkNotNull(namespace);
+            mNamespace = namespace;
+            return this;
+        }
+
+        /** Adds one or more URIs to the request. */
+        @NonNull
+        public Builder addUris(@NonNull String... uris) {
+            Preconditions.checkNotNull(uris);
+            return addUris(Arrays.asList(uris));
+        }
+
+        /** Adds one or more URIs to the request. */
+        @NonNull
+        public Builder addUris(@NonNull Collection<String> uris) {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            Preconditions.checkNotNull(uris);
+            mUris.addAll(uris);
+            return this;
+        }
+
+        /** Builds a new {@link RemoveByUriRequest}. */
+        @NonNull
+        public RemoveByUriRequest build() {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            mBuilt = true;
+            return new RemoveByUriRequest(mNamespace, mUris);
+        }
+    }
+}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java b/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java
new file mode 100644
index 0000000..b2e9d46
--- /dev/null
+++ b/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java
@@ -0,0 +1,101 @@
+/*
+ * 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 android.annotation.NonNull;
+import android.util.ArraySet;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * Encapsulates a request to update the schema of an {@link AppSearchManager} database.
+ *
+ * @see AppSearchManager#setSchema
+ * @hide
+ */
+public final class SetSchemaRequest {
+    private final Set<AppSearchSchema> mSchemas;
+    private final boolean mForceOverride;
+
+    SetSchemaRequest(Set<AppSearchSchema> schemas, boolean forceOverride) {
+        mSchemas = schemas;
+        mForceOverride = forceOverride;
+    }
+
+    /** @hide */
+    
+    @NonNull
+    public Set<AppSearchSchema> getSchemas() {
+        return mSchemas;
+    }
+
+    /** @hide */
+    
+    public boolean isForceOverride() {
+        return mForceOverride;
+    }
+
+    /** Builder for {@link SetSchemaRequest} objects. */
+    public static final class Builder {
+        private final Set<AppSearchSchema> mSchemas = new ArraySet<>();
+        private boolean mForceOverride = false;
+        private boolean mBuilt = false;
+
+        /** Adds one or more types to the schema. */
+        @NonNull
+        public Builder addSchema(@NonNull AppSearchSchema... schemas) {
+            Preconditions.checkNotNull(schemas);
+            return addSchema(Arrays.asList(schemas));
+        }
+
+        /** Adds one or more types to the schema. */
+        @NonNull
+        public Builder addSchema(@NonNull Collection<AppSearchSchema> schemas) {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            Preconditions.checkNotNull(schemas);
+            mSchemas.addAll(schemas);
+            return this;
+        }
+
+        /**
+         * Configures the {@link SetSchemaRequest} to delete any existing documents that don't
+         * follow the new schema.
+         *
+         * <p>By default, this is {@code false} and schema incompatibility causes the
+         * {@link AppSearchManager#setSchema} call to fail.
+         *
+         * @see AppSearchManager#setSchema
+         */
+        @NonNull
+        public Builder setForceOverride(boolean forceOverride) {
+            mForceOverride = forceOverride;
+            return this;
+        }
+
+        /** Builds a new {@link SetSchemaRequest}. */
+        @NonNull
+        public SetSchemaRequest build() {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            mBuilt = true;
+            return new SetSchemaRequest(mSchemas, mForceOverride);
+        }
+    }
+}
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 06612ac..7cd6ee2 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -53,6 +53,7 @@
  */
 public class AppSearchManagerService extends SystemService {
     private static final String TAG = "AppSearchManagerService";
+    private static final char CALLING_NAME_DATABASE_DELIMITER = '$';
 
     public AppSearchManagerService(Context context) {
         super(context);
@@ -66,6 +67,7 @@
     private class Stub extends IAppSearchManager.Stub {
         @Override
         public void setSchema(
+                @NonNull String databaseName,
                 @NonNull List<Bundle> schemaBundles,
                 boolean forceOverride,
                 @NonNull AndroidFuture<AppSearchResult> callback) {
@@ -82,7 +84,7 @@
                     schemaProtoBuilder.addTypes(schemaTypeProto);
                 }
                 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
-                String databaseName = makeDatabaseName(callingUid);
+                databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
                 impl.setSchema(databaseName, schemaProtoBuilder.build(), forceOverride);
                 callback.complete(AppSearchResult.newSuccessfulResult(/*result=*/ null));
             } catch (Throwable t) {
@@ -94,6 +96,7 @@
 
         @Override
         public void putDocuments(
+                @NonNull String databaseName,
                 @NonNull List<Bundle> documentBundles,
                 @NonNull AndroidFuture<AppSearchBatchResult> callback) {
             Preconditions.checkNotNull(documentBundles);
@@ -103,7 +106,7 @@
             final long callingIdentity = Binder.clearCallingIdentity();
             try {
                 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
-                String databaseName = makeDatabaseName(callingUid);
+                databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
                 AppSearchBatchResult.Builder<String, Void> resultBuilder =
                         new AppSearchBatchResult.Builder<>();
                 for (int i = 0; i < documentBundles.size(); i++) {
@@ -125,7 +128,7 @@
         }
 
         @Override
-        public void getDocuments(
+        public void getDocuments(@NonNull String databaseName, @NonNull String namespace,
                 @NonNull List<String> uris, @NonNull AndroidFuture<AppSearchBatchResult> callback) {
             Preconditions.checkNotNull(uris);
             Preconditions.checkNotNull(callback);
@@ -134,14 +137,14 @@
             final long callingIdentity = Binder.clearCallingIdentity();
             try {
                 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
-                String databaseName = makeDatabaseName(callingUid);
+                databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
                 AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
                         new AppSearchBatchResult.Builder<>();
                 for (int i = 0; i < uris.size(); i++) {
                     String uri = uris.get(i);
                     try {
                         DocumentProto documentProto = impl.getDocument(
-                                databaseName, GenericDocument.DEFAULT_NAMESPACE, uri);
+                                databaseName, namespace, uri);
                         if (documentProto == null) {
                             resultBuilder.setFailure(
                                     uri, AppSearchResult.RESULT_NOT_FOUND, /*errorMessage=*/ null);
@@ -165,6 +168,7 @@
         // TODO(sidchhabra): Do this in a threadpool.
         @Override
         public void query(
+                @NonNull String databaseName,
                 @NonNull String queryExpression,
                 @NonNull Bundle searchSpecBundle,
                 @NonNull AndroidFuture<AppSearchResult> callback) {
@@ -181,7 +185,7 @@
                 searchSpecProto = searchSpecProto.toBuilder()
                         .setQuery(queryExpression).build();
                 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
-                String databaseName = makeDatabaseName(callingUid);
+                databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
                 // TODO(adorokhine): handle pagination
                 SearchResultProto searchResultProto = impl.query(
                         databaseName,
@@ -201,7 +205,8 @@
         }
 
         @Override
-        public void delete(List<String> uris, AndroidFuture<AppSearchBatchResult> callback) {
+        public void delete(@NonNull String databaseName, @NonNull String namespace,
+                List<String> uris, AndroidFuture<AppSearchBatchResult> callback) {
             Preconditions.checkNotNull(uris);
             Preconditions.checkNotNull(callback);
             int callingUid = Binder.getCallingUidOrThrow();
@@ -209,13 +214,13 @@
             final long callingIdentity = Binder.clearCallingIdentity();
             try {
                 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
-                String databaseName = makeDatabaseName(callingUid);
+                databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
                 AppSearchBatchResult.Builder<String, Void> resultBuilder =
                         new AppSearchBatchResult.Builder<>();
                 for (int i = 0; i < uris.size(); i++) {
                     String uri = uris.get(i);
                     try {
-                        impl.remove(databaseName, GenericDocument.DEFAULT_NAMESPACE, uri);
+                        impl.remove(databaseName, namespace, uri);
                         resultBuilder.setSuccess(uri, /*result= */null);
                     } catch (Throwable t) {
                         resultBuilder.setResult(uri, throwableToFailedResult(t));
@@ -230,7 +235,7 @@
         }
 
         @Override
-        public void deleteByTypes(
+        public void deleteByTypes(@NonNull String databaseName,
                 List<String> schemaTypes, AndroidFuture<AppSearchBatchResult> callback) {
             Preconditions.checkNotNull(schemaTypes);
             Preconditions.checkNotNull(callback);
@@ -239,7 +244,7 @@
             final long callingIdentity = Binder.clearCallingIdentity();
             try {
                 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
-                String databaseName = makeDatabaseName(callingUid);
+                databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
                 AppSearchBatchResult.Builder<String, Void> resultBuilder =
                         new AppSearchBatchResult.Builder<>();
                 for (int i = 0; i < schemaTypes.size(); i++) {
@@ -260,14 +265,15 @@
         }
 
         @Override
-        public void deleteAll(@NonNull AndroidFuture<AppSearchResult> callback) {
+        public void deleteAll(@NonNull String databaseName,
+                @NonNull AndroidFuture<AppSearchResult> callback) {
             Preconditions.checkNotNull(callback);
             int callingUid = Binder.getCallingUidOrThrow();
             int callingUserId = UserHandle.getUserId(callingUid);
             final long callingIdentity = Binder.clearCallingIdentity();
             try {
                 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
-                String databaseName = makeDatabaseName(callingUid);
+                databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
                 impl.removeAll(databaseName);
                 callback.complete(AppSearchResult.newSuccessfulResult(null));
             } catch (Throwable t) {
@@ -278,13 +284,13 @@
         }
 
         /**
-         * Returns a unique database name for the given uid.
+         * Rewrites the database name by adding a prefix of unique name for the given uid.
          *
          * <p>The current implementation returns the package name of the app with this uid in a
          * format like {@code com.example.package} or {@code com.example.sharedname:5678}.
          */
         @NonNull
-        private String makeDatabaseName(int callingUid) {
+        private String rewriteDatabaseNameWithUid(String databaseName, int callingUid) {
             // For regular apps, this call will return the package name. If callingUid is an
             // android:sharedUserId, this value may be another type of name and have a :uid suffix.
             String callingUidName = getContext().getPackageManager().getNameForUid(callingUid);
@@ -293,7 +299,7 @@
                 throw new IllegalStateException(
                         "Failed to look up package name for uid " + callingUid);
             }
-            return callingUidName;
+            return callingUidName + CALLING_NAME_DATABASE_DELIMITER + databaseName;
         }
 
         private <ValueType> AppSearchResult<ValueType> throwableToFailedResult(
diff --git a/apex/jobscheduler/framework/java/android/os/DeviceIdleManager.java b/apex/jobscheduler/framework/java/android/os/DeviceIdleManager.java
index ada562e..752c36e 100644
--- a/apex/jobscheduler/framework/java/android/os/DeviceIdleManager.java
+++ b/apex/jobscheduler/framework/java/android/os/DeviceIdleManager.java
@@ -29,7 +29,6 @@
  *
  * @hide
  */
-@TestApi
 @SystemApi
 @SystemService(Context.DEVICE_IDLE_CONTROLLER)
 public class DeviceIdleManager {
diff --git a/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java b/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java
index 16dcd06..ab87222 100644
--- a/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java
+++ b/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java
@@ -21,7 +21,6 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
-import android.annotation.TestApi;
 import android.content.Context;
 
 import java.lang.annotation.Retention;
@@ -39,7 +38,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 @SystemService(Context.POWER_WHITELIST_MANAGER)
 public class PowerWhitelistManager {
     private final Context mContext;
diff --git a/api/current.txt b/api/current.txt
index 6b42af8..498d470 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -10668,12 +10668,15 @@
     field public static final String ACTION_PACKAGE_CHANGED = "android.intent.action.PACKAGE_CHANGED";
     field public static final String ACTION_PACKAGE_DATA_CLEARED = "android.intent.action.PACKAGE_DATA_CLEARED";
     field public static final String ACTION_PACKAGE_FIRST_LAUNCH = "android.intent.action.PACKAGE_FIRST_LAUNCH";
+    field public static final String ACTION_PACKAGE_FULLY_LOADED = "android.intent.action.PACKAGE_FULLY_LOADED";
     field public static final String ACTION_PACKAGE_FULLY_REMOVED = "android.intent.action.PACKAGE_FULLY_REMOVED";
     field @Deprecated public static final String ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL";
     field public static final String ACTION_PACKAGE_NEEDS_VERIFICATION = "android.intent.action.PACKAGE_NEEDS_VERIFICATION";
     field public static final String ACTION_PACKAGE_REMOVED = "android.intent.action.PACKAGE_REMOVED";
     field public static final String ACTION_PACKAGE_REPLACED = "android.intent.action.PACKAGE_REPLACED";
     field public static final String ACTION_PACKAGE_RESTARTED = "android.intent.action.PACKAGE_RESTARTED";
+    field public static final String ACTION_PACKAGE_STARTABLE = "android.intent.action.PACKAGE_STARTABLE";
+    field public static final String ACTION_PACKAGE_UNSTARTABLE = "android.intent.action.PACKAGE_UNSTARTABLE";
     field public static final String ACTION_PACKAGE_VERIFIED = "android.intent.action.PACKAGE_VERIFIED";
     field public static final String ACTION_PASTE = "android.intent.action.PASTE";
     field public static final String ACTION_PICK = "android.intent.action.PICK";
@@ -10838,6 +10841,7 @@
     field public static final String EXTRA_TIMEZONE = "time-zone";
     field public static final String EXTRA_TITLE = "android.intent.extra.TITLE";
     field public static final String EXTRA_UID = "android.intent.extra.UID";
+    field public static final String EXTRA_UNSTARTABLE_REASON = "android.intent.extra.UNSTARTABLE_REASON";
     field public static final String EXTRA_USER = "android.intent.extra.USER";
     field public static final int FILL_IN_ACTION = 1; // 0x1
     field public static final int FILL_IN_CATEGORIES = 4; // 0x4
@@ -12297,6 +12301,9 @@
     field public static final int SYNCHRONOUS = 2; // 0x2
     field @Nullable public static final java.util.List<java.security.cert.Certificate> TRUST_ALL;
     field @NonNull public static final java.util.List<java.security.cert.Certificate> TRUST_NONE;
+    field public static final int UNSTARTABLE_REASON_CONNECTION_ERROR = 1; // 0x1
+    field public static final int UNSTARTABLE_REASON_INSUFFICIENT_STORAGE = 2; // 0x2
+    field public static final int UNSTARTABLE_REASON_UNKNOWN = 0; // 0x0
     field public static final int VERIFICATION_ALLOW = 1; // 0x1
     field public static final int VERIFICATION_REJECT = -1; // 0xffffffff
     field public static final int VERSION_CODE_HIGHEST = -1; // 0xffffffff
@@ -31846,6 +31853,7 @@
     method public int getMaxServiceNameLength();
     method public int getMaxServiceSpecificInfoLength();
     method public int getSupportedCipherSuites();
+    method public boolean isInstantCommunicationModeSupported();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.aware.Characteristics> CREATOR;
     field public static final int WIFI_AWARE_CIPHER_SUITE_NCS_SK_128 = 1; // 0x1
@@ -31944,6 +31952,7 @@
     method public android.net.wifi.aware.Characteristics getCharacteristics();
     method public boolean isAvailable();
     method public boolean isDeviceAttached();
+    method public boolean isInstantCommunicationModeEnabled();
     field public static final String ACTION_WIFI_AWARE_STATE_CHANGED = "android.net.wifi.aware.action.WIFI_AWARE_STATE_CHANGED";
     field public static final int WIFI_AWARE_DATA_PATH_ROLE_INITIATOR = 0; // 0x0
     field public static final int WIFI_AWARE_DATA_PATH_ROLE_RESPONDER = 1; // 0x1
diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt
index e825b62..993d31f 100644
--- a/api/module-lib-current.txt
+++ b/api/module-lib-current.txt
@@ -103,6 +103,10 @@
     field public static final int RESULT_MEDIA_KEY_NOT_HANDLED = 0; // 0x0
   }
 
+  public final class PlaybackState implements android.os.Parcelable {
+    method public boolean isActiveState();
+  }
+
 }
 
 package android.net {
diff --git a/api/system-current.txt b/api/system-current.txt
index 25008f4..1da8c29 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -225,6 +225,7 @@
     field public static final String SET_WALLPAPER_COMPONENT = "android.permission.SET_WALLPAPER_COMPONENT";
     field public static final String SHOW_KEYGUARD_MESSAGE = "android.permission.SHOW_KEYGUARD_MESSAGE";
     field public static final String SHUTDOWN = "android.permission.SHUTDOWN";
+    field public static final String START_ACTIVITIES_FROM_BACKGROUND = "android.permission.START_ACTIVITIES_FROM_BACKGROUND";
     field public static final String STATUS_BAR_SERVICE = "android.permission.STATUS_BAR_SERVICE";
     field public static final String STOP_APP_SWITCHES = "android.permission.STOP_APP_SWITCHES";
     field public static final String SUBSTITUTE_NOTIFICATION_APP_NAME = "android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME";
@@ -594,7 +595,7 @@
 
   public class BroadcastOptions {
     method public static android.app.BroadcastOptions makeBasic();
-    method @RequiresPermission("android.permission.START_ACTIVITIES_FROM_BACKGROUND") public void setBackgroundActivityStartsAllowed(boolean);
+    method @RequiresPermission(android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND) public void setBackgroundActivityStartsAllowed(boolean);
     method public void setDontSendToRestrictedApps(boolean);
     method @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST) public void setTemporaryAppWhitelistDuration(long);
     method public android.os.Bundle toBundle();
@@ -1802,6 +1803,7 @@
     field public static final String APP_PREDICTION_SERVICE = "app_prediction";
     field public static final String BACKUP_SERVICE = "backup";
     field public static final String BATTERY_STATS_SERVICE = "batterystats";
+    field public static final int BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS = 1048576; // 0x100000
     field public static final String BUGREPORT_SERVICE = "bugreport";
     field public static final String CONTENT_SUGGESTIONS_SERVICE = "content_suggestions";
     field public static final String CONTEXTHUB_SERVICE = "contexthub";
@@ -5208,12 +5210,45 @@
 
   public class AvSettings extends android.media.tv.tuner.filter.Settings {
     method @NonNull public static android.media.tv.tuner.filter.AvSettings.Builder builder(int, boolean);
+    method public int getAudioStreamType();
+    method public int getVideoStreamType();
     method public boolean isPassthrough();
+    field public static final int AUDIO_STREAM_TYPE_AAC = 6; // 0x6
+    field public static final int AUDIO_STREAM_TYPE_AC3 = 7; // 0x7
+    field public static final int AUDIO_STREAM_TYPE_AC4 = 9; // 0x9
+    field public static final int AUDIO_STREAM_TYPE_DRA = 15; // 0xf
+    field public static final int AUDIO_STREAM_TYPE_DTS = 10; // 0xa
+    field public static final int AUDIO_STREAM_TYPE_DTS_HD = 11; // 0xb
+    field public static final int AUDIO_STREAM_TYPE_EAC3 = 8; // 0x8
+    field public static final int AUDIO_STREAM_TYPE_MP3 = 2; // 0x2
+    field public static final int AUDIO_STREAM_TYPE_MPEG1 = 3; // 0x3
+    field public static final int AUDIO_STREAM_TYPE_MPEG2 = 4; // 0x4
+    field public static final int AUDIO_STREAM_TYPE_MPEGH = 5; // 0x5
+    field public static final int AUDIO_STREAM_TYPE_OPUS = 13; // 0xd
+    field public static final int AUDIO_STREAM_TYPE_PCM = 1; // 0x1
+    field public static final int AUDIO_STREAM_TYPE_UNDEFINED = 0; // 0x0
+    field public static final int AUDIO_STREAM_TYPE_VORBIS = 14; // 0xe
+    field public static final int AUDIO_STREAM_TYPE_WMA = 12; // 0xc
+    field public static final int VIDEO_STREAM_TYPE_AV1 = 10; // 0xa
+    field public static final int VIDEO_STREAM_TYPE_AVC = 5; // 0x5
+    field public static final int VIDEO_STREAM_TYPE_AVS = 11; // 0xb
+    field public static final int VIDEO_STREAM_TYPE_AVS2 = 12; // 0xc
+    field public static final int VIDEO_STREAM_TYPE_HEVC = 6; // 0x6
+    field public static final int VIDEO_STREAM_TYPE_MPEG1 = 2; // 0x2
+    field public static final int VIDEO_STREAM_TYPE_MPEG2 = 3; // 0x3
+    field public static final int VIDEO_STREAM_TYPE_MPEG4P2 = 4; // 0x4
+    field public static final int VIDEO_STREAM_TYPE_RESERVED = 1; // 0x1
+    field public static final int VIDEO_STREAM_TYPE_UNDEFINED = 0; // 0x0
+    field public static final int VIDEO_STREAM_TYPE_VC1 = 7; // 0x7
+    field public static final int VIDEO_STREAM_TYPE_VP8 = 8; // 0x8
+    field public static final int VIDEO_STREAM_TYPE_VP9 = 9; // 0x9
   }
 
   public static class AvSettings.Builder {
     method @NonNull public android.media.tv.tuner.filter.AvSettings build();
+    method @NonNull public android.media.tv.tuner.filter.AvSettings.Builder setAudioStreamType(int);
     method @NonNull public android.media.tv.tuner.filter.AvSettings.Builder setPassthrough(boolean);
+    method @NonNull public android.media.tv.tuner.filter.AvSettings.Builder setVideoStreamType(int);
   }
 
   public class DownloadEvent extends android.media.tv.tuner.filter.FilterEvent {
@@ -5291,7 +5326,7 @@
     method @NonNull public static android.media.tv.tuner.filter.IpFilterConfiguration.Builder builder();
     method @NonNull @Size(min=4, max=16) public byte[] getDstIpAddress();
     method public int getDstPort();
-    method public int getIpFilterContextId();
+    method @IntRange(from=0, to=61439) public int getIpFilterContextId();
     method @NonNull @Size(min=4, max=16) public byte[] getSrcIpAddress();
     method public int getSrcPort();
     method public int getType();
@@ -5327,6 +5362,7 @@
     method public boolean isPrivateData();
     method public boolean isPtsPresent();
     method public boolean isSecureMemory();
+    method public void release();
   }
 
   public final class MmtpFilterConfiguration extends android.media.tv.tuner.filter.FilterConfiguration {
@@ -5833,6 +5869,7 @@
     method public int getSymbolRate();
     method public int getType();
     method public int getVcmMode();
+    method public boolean isDiseqcRxMessage();
     field public static final int MODULATION_AUTO = 1; // 0x1
     field public static final int MODULATION_MOD_128APSK = 2048; // 0x800
     field public static final int MODULATION_MOD_16APSK = 256; // 0x100
@@ -5876,6 +5913,7 @@
   public static class DvbsFrontendSettings.Builder {
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings build();
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setCodeRate(@Nullable android.media.tv.tuner.frontend.DvbsCodeRate);
+    method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setDiseqcRxMessage(boolean);
     method @IntRange(from=1) @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setFrequency(int);
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setInputStreamId(int);
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setModulation(int);
@@ -6077,14 +6115,21 @@
   public class FrontendStatus {
     method public int getAgc();
     method @NonNull public android.media.tv.tuner.frontend.FrontendStatus.Atsc3PlpTuningInfo[] getAtsc3PlpTuningInfo();
+    method public int getBandwidth();
     method public int getBer();
+    method @NonNull public int[] getBers();
+    method @NonNull public int[] getCodeRates();
     method public int getFreqOffset();
+    method public int getGuardInterval();
     method public int getHierarchy();
     method public long getInnerFec();
+    method @NonNull public int[] getInterleaving();
+    method @NonNull public int[] getIsdbtSegment();
     method @NonNull public boolean[] getLayerErrors();
     method public int getLnbVoltage();
     method public int getMer();
     method public int getModulation();
+    method @NonNull public int[] getModulationsExt();
     method public int getPer();
     method public int getPerBer();
     method public int getPlpId();
@@ -6093,23 +6138,34 @@
     method public int getSnr();
     method public int getSpectralInversion();
     method public int getSymbolRate();
+    method public int getSystemId();
+    method public int getTransmissionMode();
+    method @NonNull public int[] getTsDataRate();
+    method public int getUec();
     method public boolean isDemodLocked();
     method public boolean isEwbs();
     method public boolean isLnaOn();
     method public boolean isRfLocked();
     field public static final int FRONTEND_STATUS_TYPE_AGC = 14; // 0xe
     field public static final int FRONTEND_STATUS_TYPE_ATSC3_PLP_INFO = 21; // 0x15
+    field public static final int FRONTEND_STATUS_TYPE_BANDWIDTH = 25; // 0x19
     field public static final int FRONTEND_STATUS_TYPE_BER = 2; // 0x2
+    field public static final int FRONTEND_STATUS_TYPE_BERS = 23; // 0x17
+    field public static final int FRONTEND_STATUS_TYPE_CODERATES = 24; // 0x18
     field public static final int FRONTEND_STATUS_TYPE_DEMOD_LOCK = 0; // 0x0
     field public static final int FRONTEND_STATUS_TYPE_EWBS = 13; // 0xd
     field public static final int FRONTEND_STATUS_TYPE_FEC = 8; // 0x8
     field public static final int FRONTEND_STATUS_TYPE_FREQ_OFFSET = 18; // 0x12
+    field public static final int FRONTEND_STATUS_TYPE_GUARD_INTERVAL = 26; // 0x1a
     field public static final int FRONTEND_STATUS_TYPE_HIERARCHY = 19; // 0x13
+    field public static final int FRONTEND_STATUS_TYPE_INTERLEAVINGS = 30; // 0x1e
+    field public static final int FRONTEND_STATUS_TYPE_ISDBT_SEGMENTS = 31; // 0x1f
     field public static final int FRONTEND_STATUS_TYPE_LAYER_ERROR = 16; // 0x10
     field public static final int FRONTEND_STATUS_TYPE_LNA = 15; // 0xf
     field public static final int FRONTEND_STATUS_TYPE_LNB_VOLTAGE = 11; // 0xb
     field public static final int FRONTEND_STATUS_TYPE_MER = 17; // 0x11
     field public static final int FRONTEND_STATUS_TYPE_MODULATION = 9; // 0x9
+    field public static final int FRONTEND_STATUS_TYPE_MODULATIONS_EXT = 22; // 0x16
     field public static final int FRONTEND_STATUS_TYPE_PER = 3; // 0x3
     field public static final int FRONTEND_STATUS_TYPE_PLP_ID = 12; // 0xc
     field public static final int FRONTEND_STATUS_TYPE_PRE_BER = 4; // 0x4
@@ -6119,6 +6175,10 @@
     field public static final int FRONTEND_STATUS_TYPE_SNR = 1; // 0x1
     field public static final int FRONTEND_STATUS_TYPE_SPECTRAL = 10; // 0xa
     field public static final int FRONTEND_STATUS_TYPE_SYMBOL_RATE = 7; // 0x7
+    field public static final int FRONTEND_STATUS_TYPE_T2_SYSTEM_ID = 29; // 0x1d
+    field public static final int FRONTEND_STATUS_TYPE_TRANSMISSION_MODE = 27; // 0x1b
+    field public static final int FRONTEND_STATUS_TYPE_TS_DATA_RATES = 32; // 0x20
+    field public static final int FRONTEND_STATUS_TYPE_UEC = 28; // 0x1c
   }
 
   public static class FrontendStatus.Atsc3PlpTuningInfo {
@@ -6282,7 +6342,9 @@
     method public void onHierarchyReported(int);
     method public void onInputStreamIdsReported(@NonNull int[]);
     method public void onLocked();
+    method public default void onModulationReported(int);
     method public void onPlpIdsReported(@NonNull int[]);
+    method public default void onPriorityReported(boolean);
     method public void onProgress(@IntRange(from=0, to=100) int);
     method public void onScanStopped();
     method public void onSignalTypeReported(int);
@@ -8011,6 +8073,10 @@
     method @Deprecated public android.net.NetworkSpecifier createNetworkSpecifierPmk(@NonNull android.net.wifi.aware.PeerHandle, @NonNull byte[]);
   }
 
+  public class WifiAwareManager {
+    method public void enableInstantCommunicationMode(boolean);
+  }
+
   public class WifiAwareSession implements java.lang.AutoCloseable {
     method public android.net.NetworkSpecifier createNetworkSpecifierPmk(int, @NonNull byte[], @NonNull byte[]);
   }
@@ -11443,6 +11509,10 @@
     field public static final int ROAMING_TYPE_UNKNOWN = 1; // 0x1
   }
 
+  public class SignalStrength implements android.os.Parcelable {
+    ctor public SignalStrength(@NonNull android.telephony.SignalStrength);
+  }
+
   public final class SmsCbCmasInfo implements android.os.Parcelable {
     ctor public SmsCbCmasInfo(int, int, int, int, int, int);
     method public int describeContents();
diff --git a/api/test-current.txt b/api/test-current.txt
index 0492ce8..a165af7 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -81,21 +81,14 @@
 
   public class ActivityManager {
     method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void addHomeVisibilityListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.HomeVisibilityListener);
-    method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int);
     method public void alwaysShowUnsupportedCompileSdkWarning(android.content.ComponentName);
-    method @RequiresPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) public void forceStopPackage(String);
-    method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getPackageImportance(String);
     method public long getTotalRam();
-    method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getUidImportance(int);
     method @RequiresPermission(android.Manifest.permission.INJECT_EVENTS) public void holdLock(int);
     method public static boolean isHighEndGfx();
-    method @RequiresPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) public void killProcessesWhenImperceptible(@NonNull int[], @NonNull String);
     method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void removeHomeVisibilityListener(@NonNull android.app.HomeVisibilityListener);
-    method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener);
     method @RequiresPermission(android.Manifest.permission.RESET_APP_ERRORS) public void resetAppErrors();
     method public static void resumeAppSwitches() throws android.os.RemoteException;
     method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public void scheduleApplicationInfoChanged(java.util.List<java.lang.String>, int);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean switchUser(@NonNull android.os.UserHandle);
     field public static final int PROCESS_CAPABILITY_ALL = 7; // 0x7
     field public static final int PROCESS_CAPABILITY_ALL_EXPLICIT = 1; // 0x1
     field public static final int PROCESS_CAPABILITY_ALL_IMPLICIT = 6; // 0x6
@@ -105,10 +98,6 @@
     field public static final int PROCESS_CAPABILITY_NONE = 0; // 0x0
   }
 
-  public static interface ActivityManager.OnUidImportanceListener {
-    method public void onUidImportance(int, int);
-  }
-
   public static class ActivityManager.RunningAppProcessInfo implements android.os.Parcelable {
     field public static final int IMPORTANCE_CANT_SAVE_STATE_PRE_26 = 170; // 0xaa
   }
@@ -204,15 +193,10 @@
   public class AppOpsManager {
     method @RequiresPermission("android.permission.MANAGE_APPOPS") public void addHistoricalOps(@NonNull android.app.AppOpsManager.HistoricalOps);
     method @RequiresPermission("android.permission.MANAGE_APPOPS") public void clearHistory();
-    method @Nullable @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public android.app.RuntimeAppOpAccessMessage collectRuntimeAppOpAccessMessage();
-    method @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public void getHistoricalOps(@NonNull android.app.AppOpsManager.HistoricalOpsRequest, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.AppOpsManager.HistoricalOps>);
     method @RequiresPermission("android.permission.MANAGE_APPOPS") public void getHistoricalOpsFromDiskRaw(@NonNull android.app.AppOpsManager.HistoricalOpsRequest, @Nullable java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.AppOpsManager.HistoricalOps>);
     method public static int getNumOps();
-    method public static String[] getOpStrs();
-    method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, @NonNull String, @Nullable java.lang.String...);
     method public boolean isOperationActive(int, int, String);
     method @RequiresPermission("android.permission.MANAGE_APPOPS") public void offsetHistory(long);
-    method public static int opToDefaultMode(@NonNull String);
     method public static String opToPermission(int);
     method public static int permissionToOpCode(String);
     method @RequiresPermission("android.permission.MANAGE_APPOPS") public void rebootHistory(long);
@@ -220,8 +204,6 @@
     method @RequiresPermission("android.permission.MANAGE_APPOPS") public void resetHistoryParameters();
     method @RequiresPermission("android.permission.MANAGE_APPOPS") public void setHistoryParameters(int, long, int);
     method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(int, int, String, int);
-    method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(@NonNull String, int, @Nullable String, int);
-    method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setUidMode(@NonNull String, int, int);
     method public static int strOpToOp(@NonNull String);
     field public static final int HISTORICAL_MODE_DISABLED = 0; // 0x0
     field public static final int HISTORICAL_MODE_ENABLED_ACTIVE = 1; // 0x1
@@ -229,225 +211,19 @@
     field public static final String KEY_BG_STATE_SETTLE_TIME = "bg_state_settle_time";
     field public static final String KEY_FG_SERVICE_STATE_SETTLE_TIME = "fg_service_state_settle_time";
     field public static final String KEY_TOP_STATE_SETTLE_TIME = "top_state_settle_time";
-    field public static final String OPSTR_ACCEPT_HANDOVER = "android:accept_handover";
-    field public static final String OPSTR_ACCESS_NOTIFICATIONS = "android:access_notifications";
-    field public static final String OPSTR_ACTIVATE_VPN = "android:activate_vpn";
-    field public static final String OPSTR_ASSIST_SCREENSHOT = "android:assist_screenshot";
-    field public static final String OPSTR_ASSIST_STRUCTURE = "android:assist_structure";
-    field public static final String OPSTR_AUDIO_ACCESSIBILITY_VOLUME = "android:audio_accessibility_volume";
-    field public static final String OPSTR_AUDIO_ALARM_VOLUME = "android:audio_alarm_volume";
-    field public static final String OPSTR_AUDIO_BLUETOOTH_VOLUME = "android:audio_bluetooth_volume";
-    field public static final String OPSTR_AUDIO_MASTER_VOLUME = "android:audio_master_volume";
-    field public static final String OPSTR_AUDIO_MEDIA_VOLUME = "android:audio_media_volume";
-    field public static final String OPSTR_AUDIO_NOTIFICATION_VOLUME = "android:audio_notification_volume";
-    field public static final String OPSTR_AUDIO_RING_VOLUME = "android:audio_ring_volume";
-    field public static final String OPSTR_AUDIO_VOICE_VOLUME = "android:audio_voice_volume";
-    field public static final String OPSTR_BIND_ACCESSIBILITY_SERVICE = "android:bind_accessibility_service";
-    field public static final String OPSTR_CHANGE_WIFI_STATE = "android:change_wifi_state";
-    field public static final String OPSTR_GET_ACCOUNTS = "android:get_accounts";
-    field public static final String OPSTR_GPS = "android:gps";
-    field public static final String OPSTR_INSTANT_APP_START_FOREGROUND = "android:instant_app_start_foreground";
-    field public static final String OPSTR_LEGACY_STORAGE = "android:legacy_storage";
-    field public static final String OPSTR_MANAGE_EXTERNAL_STORAGE = "android:manage_external_storage";
-    field public static final String OPSTR_MANAGE_IPSEC_TUNNELS = "android:manage_ipsec_tunnels";
-    field public static final String OPSTR_MUTE_MICROPHONE = "android:mute_microphone";
-    field public static final String OPSTR_NEIGHBORING_CELLS = "android:neighboring_cells";
-    field public static final String OPSTR_PLAY_AUDIO = "android:play_audio";
-    field public static final String OPSTR_POST_NOTIFICATION = "android:post_notification";
-    field public static final String OPSTR_PROJECT_MEDIA = "android:project_media";
-    field public static final String OPSTR_READ_CLIPBOARD = "android:read_clipboard";
-    field public static final String OPSTR_READ_ICC_SMS = "android:read_icc_sms";
-    field public static final String OPSTR_READ_MEDIA_AUDIO = "android:read_media_audio";
-    field public static final String OPSTR_READ_MEDIA_IMAGES = "android:read_media_images";
-    field public static final String OPSTR_READ_MEDIA_VIDEO = "android:read_media_video";
-    field public static final String OPSTR_RECEIVE_EMERGENCY_BROADCAST = "android:receive_emergency_broadcast";
-    field public static final String OPSTR_REQUEST_DELETE_PACKAGES = "android:request_delete_packages";
-    field public static final String OPSTR_REQUEST_INSTALL_PACKAGES = "android:request_install_packages";
-    field public static final String OPSTR_RUN_ANY_IN_BACKGROUND = "android:run_any_in_background";
-    field public static final String OPSTR_RUN_IN_BACKGROUND = "android:run_in_background";
-    field public static final String OPSTR_START_FOREGROUND = "android:start_foreground";
-    field public static final String OPSTR_TAKE_AUDIO_FOCUS = "android:take_audio_focus";
-    field public static final String OPSTR_TAKE_MEDIA_BUTTONS = "android:take_media_buttons";
-    field public static final String OPSTR_TOAST_WINDOW = "android:toast_window";
-    field public static final String OPSTR_TURN_SCREEN_ON = "android:turn_screen_on";
-    field public static final String OPSTR_VIBRATE = "android:vibrate";
-    field public static final String OPSTR_WAKE_LOCK = "android:wake_lock";
-    field public static final String OPSTR_WIFI_SCAN = "android:wifi_scan";
-    field public static final String OPSTR_WRITE_CLIPBOARD = "android:write_clipboard";
-    field public static final String OPSTR_WRITE_ICC_SMS = "android:write_icc_sms";
-    field public static final String OPSTR_WRITE_MEDIA_AUDIO = "android:write_media_audio";
-    field public static final String OPSTR_WRITE_MEDIA_IMAGES = "android:write_media_images";
-    field public static final String OPSTR_WRITE_MEDIA_VIDEO = "android:write_media_video";
-    field public static final String OPSTR_WRITE_SMS = "android:write_sms";
-    field public static final String OPSTR_WRITE_WALLPAPER = "android:write_wallpaper";
     field public static final int OP_COARSE_LOCATION = 0; // 0x0
-    field public static final int OP_FLAGS_ALL = 31; // 0x1f
-    field public static final int OP_FLAG_SELF = 1; // 0x1
-    field public static final int OP_FLAG_TRUSTED_PROXIED = 8; // 0x8
-    field public static final int OP_FLAG_TRUSTED_PROXY = 2; // 0x2
-    field public static final int OP_FLAG_UNTRUSTED_PROXIED = 16; // 0x10
-    field public static final int OP_FLAG_UNTRUSTED_PROXY = 4; // 0x4
     field public static final int OP_RECORD_AUDIO = 27; // 0x1b
     field public static final int OP_START_FOREGROUND = 76; // 0x4c
     field public static final int OP_SYSTEM_ALERT_WINDOW = 24; // 0x18
     field public static final long SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE = 151105954L; // 0x901b1a2L
-    field public static final int UID_STATE_BACKGROUND = 600; // 0x258
-    field public static final int UID_STATE_CACHED = 700; // 0x2bc
-    field public static final int UID_STATE_FOREGROUND = 500; // 0x1f4
-    field public static final int UID_STATE_FOREGROUND_SERVICE = 400; // 0x190
-    field @Deprecated public static final int UID_STATE_FOREGROUND_SERVICE_LOCATION = 300; // 0x12c
-    field public static final int UID_STATE_PERSISTENT = 100; // 0x64
-    field public static final int UID_STATE_TOP = 200; // 0xc8
-  }
-
-  public static final class AppOpsManager.AttributedHistoricalOps implements android.os.Parcelable {
-    method public int describeContents();
-    method @Nullable public android.app.AppOpsManager.HistoricalOp getOp(@NonNull String);
-    method @NonNull public android.app.AppOpsManager.HistoricalOp getOpAt(@IntRange(from=0) int);
-    method @IntRange(from=0) public int getOpCount();
-    method @Nullable public String getTag();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.AttributedHistoricalOps> CREATOR;
-  }
-
-  public static final class AppOpsManager.AttributedOpEntry implements android.os.Parcelable {
-    method public int describeContents();
-    method public long getLastAccessBackgroundTime(int);
-    method public long getLastAccessForegroundTime(int);
-    method public long getLastAccessTime(int);
-    method public long getLastAccessTime(int, int, int);
-    method public long getLastBackgroundDuration(int);
-    method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastBackgroundProxyInfo(int);
-    method public long getLastDuration(int);
-    method public long getLastDuration(int, int, int);
-    method public long getLastForegroundDuration(int);
-    method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastForegroundProxyInfo(int);
-    method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastProxyInfo(int);
-    method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastProxyInfo(int, int, int);
-    method public long getLastRejectBackgroundTime(int);
-    method public long getLastRejectForegroundTime(int);
-    method public long getLastRejectTime(int);
-    method public long getLastRejectTime(int, int, int);
-    method public boolean isRunning();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.AttributedOpEntry> CREATOR;
-  }
-
-  public static final class AppOpsManager.HistoricalOp implements android.os.Parcelable {
-    method public int describeContents();
-    method public long getAccessCount(int, int, int);
-    method public long getAccessDuration(int, int, int);
-    method public long getBackgroundAccessCount(int);
-    method public long getBackgroundAccessDuration(int);
-    method public long getBackgroundRejectCount(int);
-    method public long getForegroundAccessCount(int);
-    method public long getForegroundAccessDuration(int);
-    method public long getForegroundRejectCount(int);
-    method @NonNull public String getOpName();
-    method public long getRejectCount(int, int, int);
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.HistoricalOp> CREATOR;
   }
 
   public static final class AppOpsManager.HistoricalOps implements android.os.Parcelable {
     ctor public AppOpsManager.HistoricalOps(long, long);
-    method public int describeContents();
-    method public long getBeginTimeMillis();
-    method public long getEndTimeMillis();
-    method @IntRange(from=0) public int getUidCount();
-    method @Nullable public android.app.AppOpsManager.HistoricalUidOps getUidOps(int);
-    method @NonNull public android.app.AppOpsManager.HistoricalUidOps getUidOpsAt(@IntRange(from=0) int);
     method public void increaseAccessCount(int, int, @NonNull String, @Nullable String, int, int, long);
     method public void increaseAccessDuration(int, int, @NonNull String, @Nullable String, int, int, long);
     method public void increaseRejectCount(int, int, @NonNull String, @Nullable String, int, int, long);
     method public void offsetBeginAndEndTime(long);
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.HistoricalOps> CREATOR;
-  }
-
-  public static final class AppOpsManager.HistoricalOpsRequest {
-  }
-
-  public static final class AppOpsManager.HistoricalOpsRequest.Builder {
-    ctor public AppOpsManager.HistoricalOpsRequest.Builder(long, long);
-    method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest build();
-    method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setAttributionTag(@Nullable String);
-    method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setFlags(int);
-    method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setOpNames(@Nullable java.util.List<java.lang.String>);
-    method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setPackageName(@Nullable String);
-    method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setUid(int);
-  }
-
-  public static final class AppOpsManager.HistoricalPackageOps implements android.os.Parcelable {
-    method public int describeContents();
-    method @Nullable public android.app.AppOpsManager.AttributedHistoricalOps getAttributedOps(@NonNull String);
-    method @NonNull public android.app.AppOpsManager.AttributedHistoricalOps getAttributedOpsAt(@IntRange(from=0) int);
-    method @IntRange(from=0) public int getAttributedOpsCount();
-    method @Nullable public android.app.AppOpsManager.HistoricalOp getOp(@NonNull String);
-    method @NonNull public android.app.AppOpsManager.HistoricalOp getOpAt(@IntRange(from=0) int);
-    method @IntRange(from=0) public int getOpCount();
-    method @NonNull public String getPackageName();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.HistoricalPackageOps> CREATOR;
-  }
-
-  public static final class AppOpsManager.HistoricalUidOps implements android.os.Parcelable {
-    method public int describeContents();
-    method @IntRange(from=0) public int getPackageCount();
-    method @Nullable public android.app.AppOpsManager.HistoricalPackageOps getPackageOps(@NonNull String);
-    method @NonNull public android.app.AppOpsManager.HistoricalPackageOps getPackageOpsAt(@IntRange(from=0) int);
-    method public int getUid();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.HistoricalUidOps> CREATOR;
-  }
-
-  public static final class AppOpsManager.OpEntry implements android.os.Parcelable {
-    method public int describeContents();
-    method @NonNull public java.util.Map<java.lang.String,android.app.AppOpsManager.AttributedOpEntry> getAttributedOpEntries();
-    method @Deprecated public long getDuration();
-    method public long getLastAccessBackgroundTime(int);
-    method public long getLastAccessForegroundTime(int);
-    method public long getLastAccessTime(int);
-    method public long getLastAccessTime(int, int, int);
-    method public long getLastBackgroundDuration(int);
-    method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastBackgroundProxyInfo(int);
-    method public long getLastDuration(int);
-    method public long getLastDuration(int, int, int);
-    method public long getLastForegroundDuration(int);
-    method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastForegroundProxyInfo(int);
-    method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastProxyInfo(int);
-    method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastProxyInfo(int, int, int);
-    method public long getLastRejectBackgroundTime(int);
-    method public long getLastRejectForegroundTime(int);
-    method public long getLastRejectTime(int);
-    method public long getLastRejectTime(int, int, int);
-    method public int getMode();
-    method @NonNull public String getOpStr();
-    method @Deprecated @Nullable public String getProxyPackageName();
-    method @Deprecated @Nullable public String getProxyPackageName(int, int);
-    method @Deprecated public int getProxyUid();
-    method @Deprecated public int getProxyUid(int, int);
-    method public boolean isRunning();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.OpEntry> CREATOR;
-  }
-
-  public static final class AppOpsManager.OpEventProxyInfo implements android.os.Parcelable {
-    method public int describeContents();
-    method @Nullable public String getAttributionTag();
-    method @Nullable public String getPackageName();
-    method @IntRange(from=0) public int getUid();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.OpEventProxyInfo> CREATOR;
-  }
-
-  public static final class AppOpsManager.PackageOps implements android.os.Parcelable {
-    method public int describeContents();
-    method @NonNull public java.util.List<android.app.AppOpsManager.OpEntry> getOps();
-    method @NonNull public String getPackageName();
-    method public int getUid();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.PackageOps> CREATOR;
   }
 
   public class DownloadManager {
@@ -472,7 +248,6 @@
     method public boolean isImportanceLockedByCriticalDeviceFunction();
     method public boolean isImportanceLockedByOEM();
     method public void lockFields(int);
-    method public void setBlockable(boolean);
     method public void setDeleted(boolean);
     method public void setDemoted(boolean);
     method public void setFgServiceShown(boolean);
@@ -480,7 +255,6 @@
     method public void setImportanceLockedByOEM(boolean);
     method public void setImportantConversation(boolean);
     method public void setOriginalImportance(int);
-    field public static final int USER_LOCKED_SOUND = 32; // 0x20
   }
 
   public final class NotificationChannelGroup implements android.os.Parcelable {
@@ -492,14 +266,8 @@
   public class NotificationManager {
     method public void allowAssistantAdjustment(String);
     method public void disallowAssistantAdjustment(String);
-    method @NonNull public java.util.List<java.lang.String> getAllowedAssistantAdjustments();
-    method @Nullable public android.content.ComponentName getAllowedNotificationAssistant();
     method public android.content.ComponentName getEffectsSuppressor();
-    method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public java.util.List<android.content.ComponentName> getEnabledNotificationListeners();
-    method public boolean isNotificationAssistantAccessGranted(@NonNull android.content.ComponentName);
     method public boolean matchesCallFilter(android.os.Bundle);
-    method public void setNotificationAssistantAccessGranted(@Nullable android.content.ComponentName, boolean);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public void setNotificationListenerAccessGranted(@NonNull android.content.ComponentName, boolean);
     method public void updateNotificationChannel(@NonNull String, int, @NonNull android.app.NotificationChannel);
   }
 
@@ -509,36 +277,12 @@
     method public android.graphics.Rect getSourceRectHint();
   }
 
-  public final class RuntimeAppOpAccessMessage implements android.os.Parcelable {
-    ctor public RuntimeAppOpAccessMessage(@IntRange(from=0L) int, @IntRange(from=0L) int, @NonNull String, @Nullable String, @NonNull String, int);
-    method public int describeContents();
-    method @Nullable public String getAttributionTag();
-    method @NonNull public String getMessage();
-    method @NonNull public String getOp();
-    method @NonNull public String getPackageName();
-    method public int getSamplingStrategy();
-    method @IntRange(from=0L) public int getUid();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.app.RuntimeAppOpAccessMessage> CREATOR;
-  }
-
   public class StatusBarManager {
     method public void collapsePanels();
     method public void expandNotificationsPanel();
-    method @NonNull @RequiresPermission(android.Manifest.permission.STATUS_BAR) public android.app.StatusBarManager.DisableInfo getDisableInfo();
-    method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setDisabledForSetup(boolean);
     method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setExpansionDisabledForSimNetworkLock(boolean);
   }
 
-  public static final class StatusBarManager.DisableInfo {
-    method public boolean areAllComponentsEnabled();
-    method public boolean isNavigateToHomeDisabled();
-    method public boolean isNotificationPeekingDisabled();
-    method public boolean isRecentsDisabled();
-    method public boolean isSearchDisabled();
-    method public boolean isStatusBarExpansionDisabled();
-  }
-
   public class TaskInfo {
     method @NonNull public android.content.res.Configuration getConfiguration();
     method @NonNull public android.window.WindowContainerToken getToken();
@@ -557,14 +301,12 @@
   }
 
   public class UiModeManager {
-    method @RequiresPermission(android.Manifest.permission.ENTER_CAR_MODE_PRIORITIZED) public void enableCarMode(@IntRange(from=0) int, int);
     method public boolean isNightModeLocked();
     method public boolean isUiModeLocked();
   }
 
   public class WallpaperManager {
     method @Nullable public android.graphics.Bitmap getBitmap();
-    method @RequiresPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT) public boolean setWallpaperComponent(android.content.ComponentName);
     method public boolean shouldEnableWideColorGamut();
     method @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) public boolean wallpaperSupportsWcg(int);
   }
@@ -609,18 +351,13 @@
 package android.app.admin {
 
   public class DevicePolicyManager {
-    method @Nullable public CharSequence getDeviceOwnerOrganizationName();
     method public long getLastBugReportRequestTime();
     method public long getLastNetworkLogRetrievalTime();
     method public long getLastSecurityLogRetrievalTime();
     method public java.util.List<java.lang.String> getOwnerInstalledCaCerts(@NonNull android.os.UserHandle);
     method public boolean isCurrentInputMethodSetByOwner();
-    method public boolean isDeviceManaged();
     method public boolean isFactoryResetProtectionPolicySupported();
-    field public static final String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_ALLOWED = "android.account.DEVICE_OR_PROFILE_OWNER_ALLOWED";
-    field public static final String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED = "android.account.DEVICE_OR_PROFILE_OWNER_DISALLOWED";
     field public static final String ACTION_DATA_SHARING_RESTRICTION_APPLIED = "android.app.action.DATA_SHARING_RESTRICTION_APPLIED";
-    field public static final String EXTRA_RESTRICTION = "android.app.extra.RESTRICTION";
   }
 
   public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
@@ -629,26 +366,6 @@
 
 }
 
-package android.app.assist {
-
-  public static class AssistStructure.ViewNode {
-    ctor public AssistStructure.ViewNode();
-  }
-
-}
-
-package android.app.backup {
-
-  public class BackupManager {
-    method @RequiresPermission(android.Manifest.permission.BACKUP) public android.content.Intent getConfigurationIntent(String);
-    method @RequiresPermission(android.Manifest.permission.BACKUP) public android.content.Intent getDataManagementIntent(String);
-    method @Nullable @RequiresPermission(android.Manifest.permission.BACKUP) public CharSequence getDataManagementIntentLabel(@NonNull String);
-    method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.BACKUP) public String getDataManagementLabel(@NonNull String);
-    method @RequiresPermission(android.Manifest.permission.BACKUP) public String getDestinationString(String);
-  }
-
-}
-
 package android.app.blob {
 
   public class BlobStoreManager {
@@ -671,150 +388,27 @@
 
 package android.app.prediction {
 
-  public final class AppPredictionContext implements android.os.Parcelable {
-    method public int describeContents();
-    method @Nullable public android.os.Bundle getExtras();
-    method @NonNull public String getPackageName();
-    method @IntRange(from=0) public int getPredictedTargetCount();
-    method @NonNull public String getUiSurface();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.app.prediction.AppPredictionContext> CREATOR;
-  }
-
-  public static final class AppPredictionContext.Builder {
-    ctor public AppPredictionContext.Builder(@NonNull android.content.Context);
-    method @NonNull public android.app.prediction.AppPredictionContext build();
-    method @NonNull public android.app.prediction.AppPredictionContext.Builder setExtras(@Nullable android.os.Bundle);
-    method @NonNull public android.app.prediction.AppPredictionContext.Builder setPredictedTargetCount(@IntRange(from=0) int);
-    method @NonNull public android.app.prediction.AppPredictionContext.Builder setUiSurface(@NonNull String);
-  }
-
-  public final class AppPredictionManager {
-    method @NonNull public android.app.prediction.AppPredictor createAppPredictionSession(@NonNull android.app.prediction.AppPredictionContext);
-  }
-
-  public final class AppPredictionSessionId implements android.os.Parcelable {
-    method public int describeContents();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.app.prediction.AppPredictionSessionId> CREATOR;
-  }
-
   public final class AppPredictor {
-    method public void destroy();
     method public android.app.prediction.AppPredictionSessionId getSessionId();
-    method public void notifyAppTargetEvent(@NonNull android.app.prediction.AppTargetEvent);
-    method public void notifyLaunchLocationShown(@NonNull String, @NonNull java.util.List<android.app.prediction.AppTargetId>);
-    method public void registerPredictionUpdates(@NonNull java.util.concurrent.Executor, @NonNull android.app.prediction.AppPredictor.Callback);
-    method public void requestPredictionUpdate();
-    method @Nullable public void sortTargets(@NonNull java.util.List<android.app.prediction.AppTarget>, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.util.List<android.app.prediction.AppTarget>>);
-    method public void unregisterPredictionUpdates(@NonNull android.app.prediction.AppPredictor.Callback);
-  }
-
-  public static interface AppPredictor.Callback {
-    method public void onTargetsAvailable(@NonNull java.util.List<android.app.prediction.AppTarget>);
-  }
-
-  public final class AppTarget implements android.os.Parcelable {
-    method public int describeContents();
-    method @Nullable public String getClassName();
-    method @NonNull public android.app.prediction.AppTargetId getId();
-    method @NonNull public String getPackageName();
-    method @IntRange(from=0) public int getRank();
-    method @Nullable public android.content.pm.ShortcutInfo getShortcutInfo();
-    method @NonNull public android.os.UserHandle getUser();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.app.prediction.AppTarget> CREATOR;
-  }
-
-  public static final class AppTarget.Builder {
-    ctor public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId, @NonNull String, @NonNull android.os.UserHandle);
-    ctor public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId, @NonNull android.content.pm.ShortcutInfo);
-    method @NonNull public android.app.prediction.AppTarget build();
-    method @NonNull public android.app.prediction.AppTarget.Builder setClassName(@NonNull String);
-    method @NonNull public android.app.prediction.AppTarget.Builder setRank(@IntRange(from=0) int);
-  }
-
-  public final class AppTargetEvent implements android.os.Parcelable {
-    method public int describeContents();
-    method public int getAction();
-    method @Nullable public String getLaunchLocation();
-    method @Nullable public android.app.prediction.AppTarget getTarget();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final int ACTION_DISMISS = 2; // 0x2
-    field public static final int ACTION_LAUNCH = 1; // 0x1
-    field public static final int ACTION_PIN = 3; // 0x3
-    field public static final int ACTION_UNPIN = 4; // 0x4
-    field @NonNull public static final android.os.Parcelable.Creator<android.app.prediction.AppTargetEvent> CREATOR;
-  }
-
-  public static final class AppTargetEvent.Builder {
-    ctor public AppTargetEvent.Builder(@Nullable android.app.prediction.AppTarget, int);
-    method @NonNull public android.app.prediction.AppTargetEvent build();
-    method @NonNull public android.app.prediction.AppTargetEvent.Builder setLaunchLocation(@Nullable String);
-  }
-
-  public final class AppTargetId implements android.os.Parcelable {
-    ctor public AppTargetId(@NonNull String);
-    method public int describeContents();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.app.prediction.AppTargetId> CREATOR;
   }
 
 }
 
 package android.app.role {
 
-  public interface OnRoleHoldersChangedListener {
-    method public void onRoleHoldersChanged(@NonNull String, @NonNull android.os.UserHandle);
-  }
-
   public class RoleControllerManager {
     method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void isApplicationVisibleForRole(@NonNull String, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
     method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void isRoleVisible(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
   }
 
   public final class RoleManager {
-    method @RequiresPermission(android.Manifest.permission.OBSERVE_ROLE_HOLDERS) public void addOnRoleHoldersChangedListenerAsUser(@NonNull java.util.concurrent.Executor, @NonNull android.app.role.OnRoleHoldersChangedListener, @NonNull android.os.UserHandle);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void addRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
-    method @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public boolean addRoleHolderFromController(@NonNull String, @NonNull String);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void clearRoleHoldersAsUser(@NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
-    method @NonNull @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public java.util.List<java.lang.String> getHeldRolesFromController(@NonNull String);
-    method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public java.util.List<java.lang.String> getRoleHolders(@NonNull String);
-    method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public java.util.List<java.lang.String> getRoleHoldersAsUser(@NonNull String, @NonNull android.os.UserHandle);
     method @Nullable public String getSmsRoleHolder(int);
-    method @RequiresPermission(android.Manifest.permission.OBSERVE_ROLE_HOLDERS) public void removeOnRoleHoldersChangedListenerAsUser(@NonNull android.app.role.OnRoleHoldersChangedListener, @NonNull android.os.UserHandle);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void removeRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
-    method @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public boolean removeRoleHolderFromController(@NonNull String, @NonNull String);
-    method @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public void setRoleNamesFromController(@NonNull java.util.List<java.lang.String>);
-    field public static final int MANAGE_HOLDERS_FLAG_DONT_KILL_APP = 1; // 0x1
   }
 
 }
 
 package android.app.usage {
 
-  public final class CacheQuotaHint implements android.os.Parcelable {
-    ctor public CacheQuotaHint(@NonNull android.app.usage.CacheQuotaHint.Builder);
-    method public int describeContents();
-    method public long getQuota();
-    method public int getUid();
-    method @Nullable public android.app.usage.UsageStats getUsageStats();
-    method @Nullable public String getVolumeUuid();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.app.usage.CacheQuotaHint> CREATOR;
-    field public static final long QUOTA_NOT_SET = -1L; // 0xffffffffffffffffL
-  }
-
-  public static final class CacheQuotaHint.Builder {
-    ctor public CacheQuotaHint.Builder();
-    ctor public CacheQuotaHint.Builder(@NonNull android.app.usage.CacheQuotaHint);
-    method @NonNull public android.app.usage.CacheQuotaHint build();
-    method @NonNull public android.app.usage.CacheQuotaHint.Builder setQuota(long);
-    method @NonNull public android.app.usage.CacheQuotaHint.Builder setUid(int);
-    method @NonNull public android.app.usage.CacheQuotaHint.Builder setUsageStats(@Nullable android.app.usage.UsageStats);
-    method @NonNull public android.app.usage.CacheQuotaHint.Builder setVolumeUuid(@Nullable String);
-  }
-
   public class NetworkStatsManager {
     method public void setPollForce(boolean);
   }
@@ -845,23 +439,8 @@
 
 }
 
-package android.companion {
-
-  public final class CompanionDeviceManager {
-    method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public boolean isDeviceAssociatedForWifiConnection(@NonNull String, @NonNull android.net.MacAddress, @NonNull android.os.UserHandle);
-  }
-
-}
-
 package android.content {
 
-  public class ApexEnvironment {
-    method @NonNull public static android.content.ApexEnvironment getApexEnvironment(@NonNull String);
-    method @NonNull public java.io.File getCredentialProtectedDataDirForUser(@NonNull android.os.UserHandle);
-    method @NonNull public java.io.File getDeviceProtectedDataDir();
-    method @NonNull public java.io.File getDeviceProtectedDataDirForUser(@NonNull android.os.UserHandle);
-  }
-
   public final class AutofillOptions implements android.os.Parcelable {
     ctor public AutofillOptions(int, boolean);
     method public int describeContents();
@@ -897,36 +476,21 @@
     method @NonNull public static android.os.UserHandle getUserHandleFromUri(@NonNull android.net.Uri);
   }
 
-  public class ContentProviderClient implements java.lang.AutoCloseable {
-    method @RequiresPermission(android.Manifest.permission.REMOVE_TASKS) public void setDetectNotResponding(long);
-  }
-
   public abstract class ContentResolver {
-    method @NonNull public static android.net.Uri decodeFromFile(@NonNull java.io.File);
-    method @NonNull public static java.io.File encodeToFile(@NonNull android.net.Uri);
     method public static String[] getSyncAdapterPackagesForAuthorityAsUser(String, int);
   }
 
   public abstract class Context {
-    method @NonNull public android.content.Context createContextAsUser(@NonNull android.os.UserHandle, int);
-    method @NonNull public android.content.Context createPackageContextAsUser(@NonNull String, int, @NonNull android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull public java.io.File getCrateDir(@NonNull String);
     method public abstract int getDisplayId();
     method public android.os.UserHandle getUser();
     method public int getUserId();
     method public void setAutofillOptions(@Nullable android.content.AutofillOptions);
     method public void setContentCaptureOptions(@Nullable android.content.ContentCaptureOptions);
-    method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public void startActivityAsUser(@NonNull @RequiresPermission android.content.Intent, @NonNull android.os.UserHandle);
-    field public static final String APP_INTEGRITY_SERVICE = "app_integrity";
-    field public static final String BUGREPORT_SERVICE = "bugreport";
     field public static final String CONTENT_CAPTURE_MANAGER_SERVICE = "content_capture";
     field public static final String DEVICE_IDLE_CONTROLLER = "deviceidle";
     field public static final String DREAM_SERVICE = "dream";
-    field public static final String ETHERNET_SERVICE = "ethernet";
-    field public static final String PERMISSION_SERVICE = "permission";
     field public static final String POWER_WHITELIST_MANAGER = "power_whitelist";
-    field public static final String ROLLBACK_SERVICE = "rollback";
-    field public static final String STATUS_BAR_SERVICE = "statusbar";
     field public static final String TEST_NETWORK_SERVICE = "test_network";
   }
 
@@ -934,75 +498,13 @@
     method public int getDisplayId();
   }
 
-  public class Intent implements java.lang.Cloneable android.os.Parcelable {
-    field @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public static final String ACTION_MANAGE_DEFAULT_APP = "android.intent.action.MANAGE_DEFAULT_APP";
-    field public static final String ACTION_ROLLBACK_COMMITTED = "android.intent.action.ROLLBACK_COMMITTED";
-    field public static final String EXTRA_ORIGINATING_UID = "android.intent.extra.ORIGINATING_UID";
-    field public static final String EXTRA_ROLE_NAME = "android.intent.extra.ROLE_NAME";
-  }
-
 }
 
 package android.content.integrity {
 
   public class AppIntegrityManager {
     method @NonNull public android.content.integrity.RuleSet getCurrentRuleSet();
-    method @NonNull public String getCurrentRuleSetProvider();
-    method @NonNull public String getCurrentRuleSetVersion();
     method @NonNull public java.util.List<java.lang.String> getWhitelistedRuleProviders();
-    method public void updateRuleSet(@NonNull android.content.integrity.RuleSet, @NonNull android.content.IntentSender);
-    field public static final String EXTRA_STATUS = "android.content.integrity.extra.STATUS";
-    field public static final int STATUS_FAILURE = 1; // 0x1
-    field public static final int STATUS_SUCCESS = 0; // 0x0
-  }
-
-  public abstract class IntegrityFormula {
-    method @NonNull public static android.content.integrity.IntegrityFormula all(@NonNull android.content.integrity.IntegrityFormula...);
-    method @NonNull public static android.content.integrity.IntegrityFormula any(@NonNull android.content.integrity.IntegrityFormula...);
-    method @NonNull public static android.content.integrity.IntegrityFormula not(@NonNull android.content.integrity.IntegrityFormula);
-  }
-
-  public static final class IntegrityFormula.Application {
-    method @NonNull public static android.content.integrity.IntegrityFormula certificatesContain(@NonNull String);
-    method @NonNull public static android.content.integrity.IntegrityFormula isPreInstalled();
-    method @NonNull public static android.content.integrity.IntegrityFormula packageNameEquals(@NonNull String);
-    method @NonNull public static android.content.integrity.IntegrityFormula versionCodeEquals(@NonNull long);
-    method @NonNull public static android.content.integrity.IntegrityFormula versionCodeGreaterThan(@NonNull long);
-    method @NonNull public static android.content.integrity.IntegrityFormula versionCodeGreaterThanOrEqualTo(@NonNull long);
-  }
-
-  public static final class IntegrityFormula.Installer {
-    method @NonNull public static android.content.integrity.IntegrityFormula certificatesContain(@NonNull String);
-    method @NonNull public static android.content.integrity.IntegrityFormula notAllowedByManifest();
-    method @NonNull public static android.content.integrity.IntegrityFormula packageNameEquals(@NonNull String);
-  }
-
-  public static final class IntegrityFormula.SourceStamp {
-    method @NonNull public static android.content.integrity.IntegrityFormula notTrusted();
-    method @NonNull public static android.content.integrity.IntegrityFormula stampCertificateHashEquals(@NonNull String);
-  }
-
-  public final class Rule implements android.os.Parcelable {
-    ctor public Rule(@NonNull android.content.integrity.IntegrityFormula, int);
-    method public int describeContents();
-    method public int getEffect();
-    method @NonNull public android.content.integrity.IntegrityFormula getFormula();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.content.integrity.Rule> CREATOR;
-    field public static final int DENY = 0; // 0x0
-    field public static final int FORCE_ALLOW = 1; // 0x1
-  }
-
-  public class RuleSet {
-    method @NonNull public java.util.List<android.content.integrity.Rule> getRules();
-    method @NonNull public String getVersion();
-  }
-
-  public static class RuleSet.Builder {
-    ctor public RuleSet.Builder();
-    method @NonNull public android.content.integrity.RuleSet.Builder addRules(@NonNull java.util.List<android.content.integrity.Rule>);
-    method @NonNull public android.content.integrity.RuleSet build();
-    method @NonNull public android.content.integrity.RuleSet.Builder setVersion(@NonNull String);
   }
 
 }
@@ -1019,95 +521,38 @@
     method public boolean isSystemApp();
     field public static final int PRIVATE_FLAG_PRIVILEGED = 8; // 0x8
     field public int privateFlags;
-    field public int targetSandboxVersion;
   }
 
   public class LauncherApps {
     ctor public LauncherApps(android.content.Context);
   }
 
-  public static class PackageInstaller.SessionInfo implements android.os.Parcelable {
-    method public int getAutoRevokePermissionsMode();
-    method public int getRollbackDataPolicy();
-    method @NonNull public java.util.Set<java.lang.String> getWhitelistedRestrictedPermissions();
-  }
-
   public static class PackageInstaller.SessionParams implements android.os.Parcelable {
-    method public void setEnableRollback(boolean);
-    method public void setEnableRollback(boolean, int);
-    method @RequiresPermission(android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS) public void setGrantedRuntimePermissions(String[]);
-    method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setInstallAsApex();
-    method public void setInstallAsInstantApp(boolean);
     method public void setInstallerPackageName(@Nullable String);
-    method public void setRequestDowngrade(boolean);
-    method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setStaged();
   }
 
   public abstract class PackageManager {
-    method @RequiresPermission("android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS") public abstract void addOnPermissionsChangeListener(@NonNull android.content.pm.PackageManager.OnPermissionsChangedListener);
-    method public abstract boolean arePermissionsIndividuallyControlled();
     method @Nullable public String getContentCaptureServicePackageName();
-    method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public abstract String getDefaultBrowserPackageNameAsUser(int);
     method @Nullable public String getDefaultTextClassifierPackageName();
-    method @Nullable public String getIncidentReportApproverPackageName();
     method public abstract int getInstallReason(@NonNull String, @NonNull android.os.UserHandle);
     method @NonNull public abstract java.util.List<android.content.pm.ApplicationInfo> getInstalledApplicationsAsUser(int, int);
-    method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(int, int);
     method @Nullable public abstract String[] getNamesForUids(int[]);
     method @NonNull public abstract String getPermissionControllerPackageName();
-    method @android.content.pm.PackageManager.PermissionFlags @RequiresPermission(anyOf={android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, android.Manifest.permission.GET_RUNTIME_PERMISSIONS}) public abstract int getPermissionFlags(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
     method @NonNull public abstract String getServicesSystemSharedLibraryPackageName();
     method @NonNull public abstract String getSharedSystemSharedLibraryPackageName();
     method @Nullable public String getSystemTextClassifierPackageName();
     method @Nullable public String getWellbeingPackageName();
-    method @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public abstract void grantRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
     method @RequiresPermission(android.Manifest.permission.INJECT_EVENTS) public void holdLock(int);
-    method @RequiresPermission("android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS") public abstract void removeOnPermissionsChangeListener(@NonNull android.content.pm.PackageManager.OnPermissionsChangedListener);
-    method @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) public abstract void revokeRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
-    method @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) public void revokeRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle, @NonNull String);
-    method @RequiresPermission(anyOf={android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS}) public abstract void updatePermissionFlags(@NonNull String, @NonNull String, @android.content.pm.PackageManager.PermissionFlags int, @android.content.pm.PackageManager.PermissionFlags int, @NonNull android.os.UserHandle);
     field public static final String FEATURE_ADOPTABLE_STORAGE = "android.software.adoptable_storage";
     field public static final String FEATURE_FILE_BASED_ENCRYPTION = "android.software.file_based_encryption";
-    field public static final int FLAG_PERMISSION_APPLY_RESTRICTION = 16384; // 0x4000
-    field public static final int FLAG_PERMISSION_GRANTED_BY_DEFAULT = 32; // 0x20
-    field public static final int FLAG_PERMISSION_GRANTED_BY_ROLE = 32768; // 0x8000
-    field public static final int FLAG_PERMISSION_ONE_TIME = 65536; // 0x10000
-    field public static final int FLAG_PERMISSION_POLICY_FIXED = 4; // 0x4
-    field public static final int FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT = 2048; // 0x800
-    field public static final int FLAG_PERMISSION_RESTRICTION_ROLE_EXEMPT = 262144; // 0x40000
-    field public static final int FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT = 4096; // 0x1000
-    field public static final int FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT = 8192; // 0x2000
-    field public static final int FLAG_PERMISSION_REVIEW_REQUIRED = 64; // 0x40
-    field public static final int FLAG_PERMISSION_REVOKED_COMPAT = 8; // 0x8
-    field @Deprecated public static final int FLAG_PERMISSION_REVOKE_ON_UPGRADE = 8; // 0x8
     field public static final int FLAG_PERMISSION_REVOKE_WHEN_REQUESTED = 128; // 0x80
-    field public static final int FLAG_PERMISSION_SYSTEM_FIXED = 16; // 0x10
-    field public static final int FLAG_PERMISSION_USER_FIXED = 2; // 0x2
-    field public static final int FLAG_PERMISSION_USER_SET = 1; // 0x1
-    field public static final int MATCH_FACTORY_ONLY = 2097152; // 0x200000
     field public static final int MATCH_KNOWN_PACKAGES = 4202496; // 0x402000
-    field public static final int MODULE_APEX_NAME = 1; // 0x1
     field public static final String SYSTEM_SHARED_LIBRARY_SERVICES = "android.ext.services";
     field public static final String SYSTEM_SHARED_LIBRARY_SHARED = "android.ext.shared";
   }
 
-  public static interface PackageManager.OnPermissionsChangedListener {
-    method public void onPermissionsChanged(int);
-  }
-
   public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
-    field public static final int FLAG_REMOVED = 2; // 0x2
-    field public static final int PROTECTION_FLAG_APP_PREDICTOR = 2097152; // 0x200000
-    field public static final int PROTECTION_FLAG_COMPANION = 8388608; // 0x800000
-    field public static final int PROTECTION_FLAG_CONFIGURATOR = 524288; // 0x80000
-    field public static final int PROTECTION_FLAG_DOCUMENTER = 262144; // 0x40000
-    field public static final int PROTECTION_FLAG_INCIDENT_REPORT_APPROVER = 1048576; // 0x100000
-    field public static final int PROTECTION_FLAG_OEM = 16384; // 0x4000
-    field public static final int PROTECTION_FLAG_RETAIL_DEMO = 16777216; // 0x1000000
-    field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000
     field public static final int PROTECTION_FLAG_VENDOR_PRIVILEGED = 32768; // 0x8000
-    field public static final int PROTECTION_FLAG_WELLBEING = 131072; // 0x20000
-    field @Nullable public final String backgroundPermission;
   }
 
   public final class ProviderInfoList implements android.os.Parcelable {
@@ -1146,40 +591,11 @@
 
 package android.content.rollback {
 
-  public final class PackageRollbackInfo implements android.os.Parcelable {
-    method public int describeContents();
-    method @NonNull public String getPackageName();
-    method @NonNull public android.content.pm.VersionedPackage getVersionRolledBackFrom();
-    method @NonNull public android.content.pm.VersionedPackage getVersionRolledBackTo();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.content.rollback.PackageRollbackInfo> CREATOR;
-  }
-
-  public final class RollbackInfo implements android.os.Parcelable {
-    method public int describeContents();
-    method @NonNull public java.util.List<android.content.pm.VersionedPackage> getCausePackages();
-    method public int getCommittedSessionId();
-    method @NonNull public java.util.List<android.content.rollback.PackageRollbackInfo> getPackages();
-    method public int getRollbackId();
-    method public boolean isStaged();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.content.rollback.RollbackInfo> CREATOR;
-  }
-
   public final class RollbackManager {
     method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void blockRollbackManager(long);
-    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) public void commitRollback(int, @NonNull java.util.List<android.content.pm.VersionedPackage>, @NonNull android.content.IntentSender);
     method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void expireRollbackForPackage(@NonNull String);
-    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks();
-    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) public java.util.List<android.content.rollback.RollbackInfo> getRecentlyCommittedRollbacks();
     method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void reloadPersistedData();
-    field public static final String EXTRA_STATUS = "android.content.rollback.extra.STATUS";
-    field public static final String EXTRA_STATUS_MESSAGE = "android.content.rollback.extra.STATUS_MESSAGE";
     field public static final String PROPERTY_ROLLBACK_LIFETIME_MILLIS = "rollback_lifetime_in_millis";
-    field public static final int STATUS_FAILURE = 1; // 0x1
-    field public static final int STATUS_FAILURE_INSTALL = 3; // 0x3
-    field public static final int STATUS_FAILURE_ROLLBACK_UNAVAILABLE = 2; // 0x2
-    field public static final int STATUS_SUCCESS = 0; // 0x0
   }
 
 }
@@ -1290,13 +706,6 @@
 
 package android.hardware.camera2 {
 
-  public abstract class CameraDevice implements java.lang.AutoCloseable {
-    method @Deprecated public abstract void createCustomCaptureSession(android.hardware.camera2.params.InputConfiguration, @NonNull java.util.List<android.hardware.camera2.params.OutputConfiguration>, int, @NonNull android.hardware.camera2.CameraCaptureSession.StateCallback, @Nullable android.os.Handler) throws android.hardware.camera2.CameraAccessException;
-    field public static final int SESSION_OPERATION_MODE_CONSTRAINED_HIGH_SPEED = 1; // 0x1
-    field public static final int SESSION_OPERATION_MODE_NORMAL = 0; // 0x0
-    field public static final int SESSION_OPERATION_MODE_VENDOR_START = 32768; // 0x8000
-  }
-
   public final class CameraManager {
     method public String[] getCameraIdListNoLazy() throws android.hardware.camera2.CameraAccessException;
   }
@@ -1305,15 +714,6 @@
 
 package android.hardware.display {
 
-  public final class AmbientBrightnessDayStats implements android.os.Parcelable {
-    method public int describeContents();
-    method public float[] getBucketBoundaries();
-    method public java.time.LocalDate getLocalDate();
-    method public float[] getStats();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.display.AmbientBrightnessDayStats> CREATOR;
-  }
-
   public class AmbientDisplayConfiguration {
     ctor public AmbientDisplayConfiguration(android.content.Context);
     method public boolean alwaysOnAvailable();
@@ -1321,70 +721,8 @@
     method public boolean alwaysOnEnabled(int);
   }
 
-  public final class BrightnessChangeEvent implements android.os.Parcelable {
-    method public int describeContents();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.display.BrightnessChangeEvent> CREATOR;
-    field public final float batteryLevel;
-    field public final float brightness;
-    field public final long colorSampleDuration;
-    field public final int colorTemperature;
-    field @Nullable public final long[] colorValueBuckets;
-    field public final boolean isDefaultBrightnessConfig;
-    field public final boolean isUserSetBrightness;
-    field public final float lastBrightness;
-    field public final long[] luxTimestamps;
-    field public final float[] luxValues;
-    field public final boolean nightMode;
-    field public final String packageName;
-    field public final float powerBrightnessFactor;
-    field public final long timeStamp;
-  }
-
-  public final class BrightnessConfiguration implements android.os.Parcelable {
-    method public int describeContents();
-    method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByCategory(int);
-    method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByPackageName(@NonNull String);
-    method public android.util.Pair<float[],float[]> getCurve();
-    method public float getShortTermModelLowerLuxMultiplier();
-    method public long getShortTermModelTimeoutMillis();
-    method public float getShortTermModelUpperLuxMultiplier();
-    method public boolean shouldCollectColorSamples();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.display.BrightnessConfiguration> CREATOR;
-    field public static final long SHORT_TERM_TIMEOUT_UNSET = -1L; // 0xffffffffffffffffL
-  }
-
-  public static class BrightnessConfiguration.Builder {
-    ctor public BrightnessConfiguration.Builder(float[], float[]);
-    method @NonNull public android.hardware.display.BrightnessConfiguration.Builder addCorrectionByCategory(int, @NonNull android.hardware.display.BrightnessCorrection);
-    method @NonNull public android.hardware.display.BrightnessConfiguration.Builder addCorrectionByPackageName(@NonNull String, @NonNull android.hardware.display.BrightnessCorrection);
-    method @NonNull public android.hardware.display.BrightnessConfiguration build();
-    method public int getMaxCorrectionsByCategory();
-    method public int getMaxCorrectionsByPackageName();
-    method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setDescription(@Nullable String);
-    method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelLowerLuxMultiplier(@FloatRange(from=0.0f) float);
-    method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelTimeoutMillis(long);
-    method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelUpperLuxMultiplier(@FloatRange(from=0.0f) float);
-    method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShouldCollectColorSamples(boolean);
-  }
-
-  public final class BrightnessCorrection implements android.os.Parcelable {
-    method @FloatRange(from=0.0) public float apply(@FloatRange(from=0.0) float);
-    method @NonNull public static android.hardware.display.BrightnessCorrection createScaleAndTranslateLog(float, float);
-    method public int describeContents();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.display.BrightnessCorrection> CREATOR;
-  }
-
   public final class DisplayManager {
-    method @RequiresPermission(android.Manifest.permission.ACCESS_AMBIENT_LIGHT_STATS) public java.util.List<android.hardware.display.AmbientBrightnessDayStats> getAmbientBrightnessStats();
-    method @RequiresPermission(android.Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) public android.hardware.display.BrightnessConfiguration getBrightnessConfiguration();
-    method @RequiresPermission(android.Manifest.permission.BRIGHTNESS_SLIDER_USAGE) public java.util.List<android.hardware.display.BrightnessChangeEvent> getBrightnessEvents();
-    method @Nullable @RequiresPermission(android.Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) public android.hardware.display.BrightnessConfiguration getDefaultBrightnessConfiguration();
-    method public android.graphics.Point getStableDisplaySize();
     method public boolean isMinimalPostProcessingRequested(int);
-    method @RequiresPermission(android.Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) public void setBrightnessConfiguration(android.hardware.display.BrightnessConfiguration);
     method @RequiresPermission(android.Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS) public void setShouldAlwaysRespectAppRequestedMode(boolean);
     method @RequiresPermission(android.Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS) public boolean shouldAlwaysRespectAppRequestedMode();
     field public static final int VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS = 512; // 0x200
@@ -1404,97 +742,6 @@
 
 package android.hardware.hdmi {
 
-  public final class HdmiControlManager {
-    method @Nullable public android.hardware.hdmi.HdmiSwitchClient getSwitchClient();
-    method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void setStandbyMode(boolean);
-    field public static final String ACTION_OSD_MESSAGE = "android.hardware.hdmi.action.OSD_MESSAGE";
-    field public static final int AVR_VOLUME_MUTED = 101; // 0x65
-    field public static final int CLEAR_TIMER_STATUS_CEC_DISABLE = 162; // 0xa2
-    field public static final int CLEAR_TIMER_STATUS_CHECK_RECORDER_CONNECTION = 160; // 0xa0
-    field public static final int CLEAR_TIMER_STATUS_FAIL_TO_CLEAR_SELECTED_SOURCE = 161; // 0xa1
-    field public static final int CLEAR_TIMER_STATUS_TIMER_CLEARED = 128; // 0x80
-    field public static final int CLEAR_TIMER_STATUS_TIMER_NOT_CLEARED_NO_INFO_AVAILABLE = 2; // 0x2
-    field public static final int CLEAR_TIMER_STATUS_TIMER_NOT_CLEARED_NO_MATCHING = 1; // 0x1
-    field public static final int CLEAR_TIMER_STATUS_TIMER_NOT_CLEARED_RECORDING = 0; // 0x0
-    field public static final int CONTROL_STATE_CHANGED_REASON_SETTING = 1; // 0x1
-    field public static final int CONTROL_STATE_CHANGED_REASON_STANDBY = 3; // 0x3
-    field public static final int CONTROL_STATE_CHANGED_REASON_START = 0; // 0x0
-    field public static final int CONTROL_STATE_CHANGED_REASON_WAKEUP = 2; // 0x2
-    field public static final int DEVICE_EVENT_ADD_DEVICE = 1; // 0x1
-    field public static final int DEVICE_EVENT_REMOVE_DEVICE = 2; // 0x2
-    field public static final int DEVICE_EVENT_UPDATE_DEVICE = 3; // 0x3
-    field public static final String EXTRA_MESSAGE_EXTRA_PARAM1 = "android.hardware.hdmi.extra.MESSAGE_EXTRA_PARAM1";
-    field public static final String EXTRA_MESSAGE_ID = "android.hardware.hdmi.extra.MESSAGE_ID";
-    field public static final int ONE_TOUCH_RECORD_ALREADY_RECORDING = 18; // 0x12
-    field public static final int ONE_TOUCH_RECORD_CEC_DISABLED = 51; // 0x33
-    field public static final int ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION = 49; // 0x31
-    field public static final int ONE_TOUCH_RECORD_DISALLOW_TO_COPY = 13; // 0xd
-    field public static final int ONE_TOUCH_RECORD_DISALLOW_TO_FUTHER_COPIES = 14; // 0xe
-    field public static final int ONE_TOUCH_RECORD_FAIL_TO_RECORD_DISPLAYED_SCREEN = 50; // 0x32
-    field public static final int ONE_TOUCH_RECORD_INVALID_EXTERNAL_PHYSICAL_ADDRESS = 10; // 0xa
-    field public static final int ONE_TOUCH_RECORD_INVALID_EXTERNAL_PLUG_NUMBER = 9; // 0x9
-    field public static final int ONE_TOUCH_RECORD_MEDIA_PROBLEM = 21; // 0x15
-    field public static final int ONE_TOUCH_RECORD_MEDIA_PROTECTED = 19; // 0x13
-    field public static final int ONE_TOUCH_RECORD_NOT_ENOUGH_SPACE = 22; // 0x16
-    field public static final int ONE_TOUCH_RECORD_NO_MEDIA = 16; // 0x10
-    field public static final int ONE_TOUCH_RECORD_NO_OR_INSUFFICIENT_CA_ENTITLEMENTS = 12; // 0xc
-    field public static final int ONE_TOUCH_RECORD_NO_SOURCE_SIGNAL = 20; // 0x14
-    field public static final int ONE_TOUCH_RECORD_OTHER_REASON = 31; // 0x1f
-    field public static final int ONE_TOUCH_RECORD_PARENT_LOCK_ON = 23; // 0x17
-    field public static final int ONE_TOUCH_RECORD_PLAYING = 17; // 0x11
-    field public static final int ONE_TOUCH_RECORD_PREVIOUS_RECORDING_IN_PROGRESS = 48; // 0x30
-    field public static final int ONE_TOUCH_RECORD_RECORDING_ALREADY_TERMINATED = 27; // 0x1b
-    field public static final int ONE_TOUCH_RECORD_RECORDING_ANALOGUE_SERVICE = 3; // 0x3
-    field public static final int ONE_TOUCH_RECORD_RECORDING_CURRENTLY_SELECTED_SOURCE = 1; // 0x1
-    field public static final int ONE_TOUCH_RECORD_RECORDING_DIGITAL_SERVICE = 2; // 0x2
-    field public static final int ONE_TOUCH_RECORD_RECORDING_EXTERNAL_INPUT = 4; // 0x4
-    field public static final int ONE_TOUCH_RECORD_RECORDING_TERMINATED_NORMALLY = 26; // 0x1a
-    field public static final int ONE_TOUCH_RECORD_UNABLE_ANALOGUE_SERVICE = 6; // 0x6
-    field public static final int ONE_TOUCH_RECORD_UNABLE_DIGITAL_SERVICE = 5; // 0x5
-    field public static final int ONE_TOUCH_RECORD_UNABLE_SELECTED_SERVICE = 7; // 0x7
-    field public static final int ONE_TOUCH_RECORD_UNSUPPORTED_CA = 11; // 0xb
-    field public static final int OSD_MESSAGE_ARC_CONNECTED_INVALID_PORT = 1; // 0x1
-    field public static final int OSD_MESSAGE_AVR_VOLUME_CHANGED = 2; // 0x2
-    field public static final int POWER_STATUS_ON = 0; // 0x0
-    field public static final int POWER_STATUS_STANDBY = 1; // 0x1
-    field public static final int POWER_STATUS_TRANSIENT_TO_ON = 2; // 0x2
-    field public static final int POWER_STATUS_TRANSIENT_TO_STANDBY = 3; // 0x3
-    field public static final int POWER_STATUS_UNKNOWN = -1; // 0xffffffff
-    field @Deprecated public static final int RESULT_ALREADY_IN_PROGRESS = 4; // 0x4
-    field public static final int RESULT_COMMUNICATION_FAILED = 7; // 0x7
-    field public static final int RESULT_EXCEPTION = 5; // 0x5
-    field public static final int RESULT_INCORRECT_MODE = 6; // 0x6
-    field public static final int RESULT_SOURCE_NOT_AVAILABLE = 2; // 0x2
-    field public static final int RESULT_SUCCESS = 0; // 0x0
-    field public static final int RESULT_TARGET_NOT_AVAILABLE = 3; // 0x3
-    field public static final int RESULT_TIMEOUT = 1; // 0x1
-    field public static final int TIMER_RECORDING_RESULT_EXTRA_CEC_DISABLED = 3; // 0x3
-    field public static final int TIMER_RECORDING_RESULT_EXTRA_CHECK_RECORDER_CONNECTION = 1; // 0x1
-    field public static final int TIMER_RECORDING_RESULT_EXTRA_FAIL_TO_RECORD_SELECTED_SOURCE = 2; // 0x2
-    field public static final int TIMER_RECORDING_RESULT_EXTRA_NO_ERROR = 0; // 0x0
-    field public static final int TIMER_RECORDING_TYPE_ANALOGUE = 2; // 0x2
-    field public static final int TIMER_RECORDING_TYPE_DIGITAL = 1; // 0x1
-    field public static final int TIMER_RECORDING_TYPE_EXTERNAL = 3; // 0x3
-    field public static final int TIMER_STATUS_MEDIA_INFO_NOT_PRESENT = 2; // 0x2
-    field public static final int TIMER_STATUS_MEDIA_INFO_PRESENT_NOT_PROTECTED = 0; // 0x0
-    field public static final int TIMER_STATUS_MEDIA_INFO_PRESENT_PROTECTED = 1; // 0x1
-    field public static final int TIMER_STATUS_NOT_PROGRAMMED_CA_NOT_SUPPORTED = 6; // 0x6
-    field public static final int TIMER_STATUS_NOT_PROGRAMMED_CLOCK_FAILURE = 10; // 0xa
-    field public static final int TIMER_STATUS_NOT_PROGRAMMED_DATE_OUT_OF_RANGE = 2; // 0x2
-    field public static final int TIMER_STATUS_NOT_PROGRAMMED_DUPLICATED = 14; // 0xe
-    field public static final int TIMER_STATUS_NOT_PROGRAMMED_INVALID_EXTERNAL_PHYSICAL_NUMBER = 5; // 0x5
-    field public static final int TIMER_STATUS_NOT_PROGRAMMED_INVALID_EXTERNAL_PLUG_NUMBER = 4; // 0x4
-    field public static final int TIMER_STATUS_NOT_PROGRAMMED_INVALID_SEQUENCE = 3; // 0x3
-    field public static final int TIMER_STATUS_NOT_PROGRAMMED_NO_CA_ENTITLEMENTS = 7; // 0x7
-    field public static final int TIMER_STATUS_NOT_PROGRAMMED_NO_FREE_TIME = 1; // 0x1
-    field public static final int TIMER_STATUS_NOT_PROGRAMMED_PARENTAL_LOCK_ON = 9; // 0x9
-    field public static final int TIMER_STATUS_NOT_PROGRAMMED_UNSUPPORTED_RESOLUTION = 8; // 0x8
-    field public static final int TIMER_STATUS_PROGRAMMED_INFO_ENOUGH_SPACE = 8; // 0x8
-    field public static final int TIMER_STATUS_PROGRAMMED_INFO_MIGHT_NOT_ENOUGH_SPACE = 11; // 0xb
-    field public static final int TIMER_STATUS_PROGRAMMED_INFO_NOT_ENOUGH_SPACE = 9; // 0x9
-    field public static final int TIMER_STATUS_PROGRAMMED_INFO_NO_MEDIA_INFO = 10; // 0xa
-  }
-
   public final class HdmiControlServiceWrapper {
     ctor public HdmiControlServiceWrapper();
     method @NonNull public android.hardware.hdmi.HdmiControlManager createHdmiControlManager();
@@ -1503,25 +750,6 @@
     field public static final int DEVICE_PURE_CEC_SWITCH = 6; // 0x6
   }
 
-  public final class HdmiPortInfo implements android.os.Parcelable {
-    ctor public HdmiPortInfo(int, int, int, boolean, boolean, boolean);
-    method public int describeContents();
-    method public int getAddress();
-    method public int getId();
-    method public int getType();
-    method public boolean isArcSupported();
-    method public boolean isCecSupported();
-    method public boolean isMhlSupported();
-    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.hdmi.HdmiPortInfo> CREATOR;
-    field public static final int PORT_INPUT = 0; // 0x0
-    field public static final int PORT_OUTPUT = 1; // 0x1
-  }
-
-  public class HdmiSwitchClient extends android.hardware.hdmi.HdmiClient {
-    method public int getDeviceType();
-    method @NonNull public java.util.List<android.hardware.hdmi.HdmiPortInfo> getPortInfo();
-  }
-
 }
 
 package android.hardware.input {
@@ -1538,43 +766,8 @@
 
 package android.hardware.lights {
 
-  public final class Light implements android.os.Parcelable {
-    method public int describeContents();
-    method public int getId();
-    method public int getOrdinal();
-    method public int getType();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.lights.Light> CREATOR;
-  }
-
-  public final class LightState implements android.os.Parcelable {
-    ctor public LightState(@ColorInt int);
-    method public int describeContents();
-    method @ColorInt public int getColor();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.lights.LightState> CREATOR;
-  }
-
   public final class LightsManager {
     method @NonNull @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS) public android.hardware.lights.LightState getLightState(@NonNull android.hardware.lights.Light);
-    method @NonNull @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS) public java.util.List<android.hardware.lights.Light> getLights();
-    method @NonNull @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS) public android.hardware.lights.LightsManager.LightsSession openSession();
-    field public static final int LIGHT_TYPE_MICROPHONE = 8; // 0x8
-  }
-
-  public final class LightsManager.LightsSession implements java.lang.AutoCloseable {
-    method @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS) public void close();
-    method @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS) public void requestLights(@NonNull android.hardware.lights.LightsRequest);
-  }
-
-  public final class LightsRequest {
-  }
-
-  public static final class LightsRequest.Builder {
-    ctor public LightsRequest.Builder();
-    method @NonNull public android.hardware.lights.LightsRequest build();
-    method @NonNull public android.hardware.lights.LightsRequest.Builder clearLight(@NonNull android.hardware.lights.Light);
-    method @NonNull public android.hardware.lights.LightsRequest.Builder setLight(@NonNull android.hardware.lights.Light, @NonNull android.hardware.lights.LightState);
   }
 
 }
@@ -1605,84 +798,16 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.hardware.soundtrigger.KeyphraseMetadata> CREATOR;
   }
 
-  public class SoundTrigger {
-    field public static final int RECOGNITION_MODE_GENERIC = 8; // 0x8
-    field public static final int RECOGNITION_MODE_USER_AUTHENTICATION = 4; // 0x4
-    field public static final int RECOGNITION_MODE_USER_IDENTIFICATION = 2; // 0x2
-    field public static final int RECOGNITION_MODE_VOICE_TRIGGER = 1; // 0x1
-    field public static final int STATUS_OK = 0; // 0x0
-  }
-
-  public static final class SoundTrigger.Keyphrase implements android.os.Parcelable {
-    ctor public SoundTrigger.Keyphrase(int, int, @NonNull java.util.Locale, @NonNull String, @Nullable int[]);
-    method public int getId();
-    method @NonNull public java.util.Locale getLocale();
-    method public int getRecognitionModes();
-    method @NonNull public String getText();
-    method @NonNull public int[] getUsers();
-    method @NonNull public static android.hardware.soundtrigger.SoundTrigger.Keyphrase readFromParcel(@NonNull android.os.Parcel);
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.soundtrigger.SoundTrigger.Keyphrase> CREATOR;
-  }
-
-  public static final class SoundTrigger.KeyphraseSoundModel extends android.hardware.soundtrigger.SoundTrigger.SoundModel implements android.os.Parcelable {
-    ctor public SoundTrigger.KeyphraseSoundModel(@NonNull java.util.UUID, @NonNull java.util.UUID, @Nullable byte[], @Nullable android.hardware.soundtrigger.SoundTrigger.Keyphrase[], int);
-    ctor public SoundTrigger.KeyphraseSoundModel(@NonNull java.util.UUID, @NonNull java.util.UUID, @Nullable byte[], @Nullable android.hardware.soundtrigger.SoundTrigger.Keyphrase[]);
-    method @NonNull public android.hardware.soundtrigger.SoundTrigger.Keyphrase[] getKeyphrases();
-    method @NonNull public static android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel readFromParcel(@NonNull android.os.Parcel);
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel> CREATOR;
-  }
-
   public static final class SoundTrigger.ModelParamRange implements android.os.Parcelable {
     ctor public SoundTrigger.ModelParamRange(int, int);
-    method public int getEnd();
-    method public int getStart();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.soundtrigger.SoundTrigger.ModelParamRange> CREATOR;
   }
 
   public static final class SoundTrigger.ModuleProperties implements android.os.Parcelable {
     ctor public SoundTrigger.ModuleProperties(int, @NonNull String, @NonNull String, @NonNull String, int, @NonNull String, int, int, int, int, boolean, int, boolean, int, boolean, int);
-    method public int describeContents();
-    method public int getAudioCapabilities();
-    method @NonNull public String getDescription();
-    method public int getId();
-    method @NonNull public String getImplementor();
-    method public int getMaxBufferMillis();
-    method public int getMaxKeyphrases();
-    method public int getMaxSoundModels();
-    method public int getMaxUsers();
-    method public int getPowerConsumptionMw();
-    method public int getRecognitionModes();
-    method @NonNull public String getSupportedModelArch();
-    method @NonNull public java.util.UUID getUuid();
-    method public int getVersion();
-    method public boolean isCaptureTransitionSupported();
-    method public boolean isConcurrentCaptureSupported();
-    method public boolean isTriggerReturnedInEvent();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final int AUDIO_CAPABILITY_ECHO_CANCELLATION = 1; // 0x1
-    field public static final int AUDIO_CAPABILITY_NOISE_SUPPRESSION = 2; // 0x2
-    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.soundtrigger.SoundTrigger.ModuleProperties> CREATOR;
   }
 
   public static class SoundTrigger.RecognitionEvent {
     ctor public SoundTrigger.RecognitionEvent(int, int, boolean, int, int, int, boolean, @NonNull android.media.AudioFormat, @Nullable byte[]);
-    method @Nullable public android.media.AudioFormat getCaptureFormat();
-    method public int getCaptureSession();
-    method public byte[] getData();
-    method public boolean isCaptureAvailable();
-  }
-
-  public static class SoundTrigger.SoundModel {
-    method @NonNull public byte[] getData();
-    method public int getType();
-    method @NonNull public java.util.UUID getUuid();
-    method @NonNull public java.util.UUID getVendorUuid();
-    method public int getVersion();
-    field public static final int TYPE_GENERIC_SOUND = 1; // 0x1
-    field public static final int TYPE_KEYPHRASE = 0; // 0x0
   }
 
 }
@@ -1781,59 +906,17 @@
     method public void setType(int);
   }
 
-  public class Location implements android.os.Parcelable {
-    method public void makeComplete();
-    field @Deprecated public static final String EXTRA_NO_GPS_LOCATION = "noGPSLocation";
-  }
-
   public class LocationManager {
     method @NonNull public String[] getBackgroundThrottlingWhitelist();
-    method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
     method @NonNull public String[] getIgnoreSettingsWhitelist();
     method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public java.util.List<java.lang.String> getProviderPackages(@NonNull String);
-    method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
-    method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
-    method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.app.PendingIntent);
-    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setLocationEnabledForUser(boolean, @NonNull android.os.UserHandle);
     field public static final String FUSED_PROVIDER = "fused";
   }
 
-  public final class LocationRequest implements android.os.Parcelable {
-    method @NonNull public android.os.WorkSource getWorkSource();
-    method public boolean isHiddenFromAppOps();
-    method public boolean isLocationSettingsIgnored();
-    method public boolean isLowPower();
-    field @Deprecated public static final int ACCURACY_BLOCK = 102; // 0x66
-    field @Deprecated public static final int ACCURACY_CITY = 104; // 0x68
-    field @Deprecated public static final int ACCURACY_FINE = 100; // 0x64
-    field @Deprecated public static final int POWER_HIGH = 203; // 0xcb
-    field @Deprecated public static final int POWER_LOW = 201; // 0xc9
-  }
-
-  public static final class LocationRequest.Builder {
-    method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LocationRequest.Builder setHiddenFromAppOps(boolean);
-    method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.location.LocationRequest.Builder setLocationSettingsIgnored(boolean);
-    method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.location.LocationRequest.Builder setLowPower(boolean);
-    method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.location.LocationRequest.Builder setWorkSource(@Nullable android.os.WorkSource);
-  }
-
 }
 
 package android.media {
 
-  public final class AudioFocusInfo implements android.os.Parcelable {
-    method public int describeContents();
-    method @NonNull public android.media.AudioAttributes getAttributes();
-    method @NonNull public String getClientId();
-    method public int getClientUid();
-    method public int getFlags();
-    method public int getGainRequest();
-    method public int getLossReceived();
-    method @NonNull public String getPackageName();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.media.AudioFocusInfo> CREATOR;
-  }
-
   public final class AudioFocusRequest {
     method @Nullable public android.media.AudioManager.OnAudioFocusChangeListener getOnAudioFocusChangeListener();
   }
@@ -1846,13 +929,7 @@
   }
 
   public class AudioManager {
-    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int dispatchAudioFocusChange(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
     method public boolean hasRegisteredDynamicPolicy();
-    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int registerAudioPolicy(@NonNull android.media.audiopolicy.AudioPolicy);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setFocusRequestResult(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void unregisterAudioPolicy(@NonNull android.media.audiopolicy.AudioPolicy);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void unregisterAudioPolicyAsync(@NonNull android.media.audiopolicy.AudioPolicy);
-    field public static final int SUCCESS = 0; // 0x0
   }
 
   public static final class AudioRecord.MetricsConstants {
@@ -1908,68 +985,6 @@
     method @NonNull public String getOriginalId();
   }
 
-  public final class MediaTranscodeManager {
-    method @NonNull public android.media.MediaTranscodeManager.TranscodingJob enqueueRequest(@NonNull android.media.MediaTranscodeManager.TranscodingRequest, @NonNull java.util.concurrent.Executor, @NonNull android.media.MediaTranscodeManager.OnTranscodingFinishedListener) throws java.io.FileNotFoundException, android.media.MediaTranscodingException.ServiceNotAvailableException;
-    field public static final int PRIORITY_REALTIME = 1; // 0x1
-    field public static final int TRANSCODING_TYPE_VIDEO = 1; // 0x1
-  }
-
-  @java.lang.FunctionalInterface public static interface MediaTranscodeManager.OnTranscodingFinishedListener {
-    method public void onTranscodingFinished(@NonNull android.media.MediaTranscodeManager.TranscodingJob);
-  }
-
-  public static final class MediaTranscodeManager.TranscodingJob {
-    method public void cancel();
-    method public int getJobId();
-    method @IntRange(from=0, to=100) public int getProgress();
-    method public int getResult();
-    method public int getStatus();
-    method public void setOnProgressUpdateListener(@NonNull java.util.concurrent.Executor, @Nullable android.media.MediaTranscodeManager.TranscodingJob.OnProgressUpdateListener);
-    method public void setOnProgressUpdateListener(int, @NonNull java.util.concurrent.Executor, @Nullable android.media.MediaTranscodeManager.TranscodingJob.OnProgressUpdateListener);
-    field public static final int RESULT_CANCELED = 4; // 0x4
-    field public static final int RESULT_ERROR = 3; // 0x3
-    field public static final int RESULT_NONE = 1; // 0x1
-    field public static final int RESULT_SUCCESS = 2; // 0x2
-    field public static final int STATUS_FINISHED = 3; // 0x3
-    field public static final int STATUS_PAUSED = 4; // 0x4
-    field public static final int STATUS_PENDING = 1; // 0x1
-    field public static final int STATUS_RUNNING = 2; // 0x2
-  }
-
-  @java.lang.FunctionalInterface public static interface MediaTranscodeManager.TranscodingJob.OnProgressUpdateListener {
-    method public void onProgressUpdate(@NonNull android.media.MediaTranscodeManager.TranscodingJob, @IntRange(from=0, to=100) int);
-  }
-
-  public static final class MediaTranscodeManager.TranscodingRequest {
-    method public int getClientPid();
-    method public int getClientUid();
-    method @NonNull public android.net.Uri getDestinationUri();
-    method public int getPriority();
-    method @NonNull public android.net.Uri getSourceUri();
-    method public int getType();
-    method @Nullable public android.media.MediaFormat getVideoTrackFormat();
-  }
-
-  public static final class MediaTranscodeManager.TranscodingRequest.Builder {
-    ctor public MediaTranscodeManager.TranscodingRequest.Builder();
-    method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest build();
-    method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setClientPid(int);
-    method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setClientUid(int);
-    method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setDestinationUri(@NonNull android.net.Uri);
-    method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setPriority(int);
-    method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setSourceUri(@NonNull android.net.Uri);
-    method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setType(int);
-    method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setVideoTrackFormat(@NonNull android.media.MediaFormat);
-  }
-
-  public static class MediaTranscodeManager.TranscodingRequest.MediaFormatResolver {
-    ctor public MediaTranscodeManager.TranscodingRequest.MediaFormatResolver();
-    method @Nullable public android.media.MediaFormat resolveVideoFormat();
-    method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.MediaFormatResolver setSourceVideoFormatHint(@NonNull android.media.MediaFormat);
-    method public boolean shouldTranscode();
-    field public static final String CAPS_SUPPORTS_HEVC = "support-hevc";
-  }
-
   public final class PlaybackParams implements android.os.Parcelable {
     method public int getAudioStretchMode();
     method public android.media.PlaybackParams setAudioStretchMode(int);
@@ -2018,141 +1033,8 @@
 
 package android.media.audiopolicy {
 
-  public class AudioMix {
-    method public int getMixState();
-    field public static final int MIX_STATE_DISABLED = -1; // 0xffffffff
-    field public static final int MIX_STATE_IDLE = 0; // 0x0
-    field public static final int MIX_STATE_MIXING = 1; // 0x1
-    field public static final int ROUTE_FLAG_LOOP_BACK = 2; // 0x2
-    field public static final int ROUTE_FLAG_RENDER = 1; // 0x1
-  }
-
-  public static class AudioMix.Builder {
-    ctor public AudioMix.Builder(android.media.audiopolicy.AudioMixingRule) throws java.lang.IllegalArgumentException;
-    method public android.media.audiopolicy.AudioMix build() throws java.lang.IllegalArgumentException;
-    method public android.media.audiopolicy.AudioMix.Builder setDevice(@NonNull android.media.AudioDeviceInfo) throws java.lang.IllegalArgumentException;
-    method public android.media.audiopolicy.AudioMix.Builder setFormat(android.media.AudioFormat) throws java.lang.IllegalArgumentException;
-    method public android.media.audiopolicy.AudioMix.Builder setRouteFlags(int) throws java.lang.IllegalArgumentException;
-  }
-
-  public class AudioMixingRule {
-    field public static final int RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET = 2; // 0x2
-    field public static final int RULE_MATCH_ATTRIBUTE_USAGE = 1; // 0x1
-    field public static final int RULE_MATCH_UID = 4; // 0x4
-    field public static final int RULE_MATCH_USERID = 8; // 0x8
-  }
-
-  public static class AudioMixingRule.Builder {
-    ctor public AudioMixingRule.Builder();
-    method public android.media.audiopolicy.AudioMixingRule.Builder addMixRule(int, Object) throws java.lang.IllegalArgumentException;
-    method public android.media.audiopolicy.AudioMixingRule.Builder addRule(android.media.AudioAttributes, int) throws java.lang.IllegalArgumentException;
-    method @NonNull public android.media.audiopolicy.AudioMixingRule.Builder allowPrivilegedPlaybackCapture(boolean);
-    method public android.media.audiopolicy.AudioMixingRule build();
-    method public android.media.audiopolicy.AudioMixingRule.Builder excludeMixRule(int, Object) throws java.lang.IllegalArgumentException;
-    method public android.media.audiopolicy.AudioMixingRule.Builder excludeRule(android.media.AudioAttributes, int) throws java.lang.IllegalArgumentException;
-  }
-
-  public class AudioPolicy {
-    method public int attachMixes(@NonNull java.util.List<android.media.audiopolicy.AudioMix>);
-    method public android.media.AudioRecord createAudioRecordSink(android.media.audiopolicy.AudioMix) throws java.lang.IllegalArgumentException;
-    method public android.media.AudioTrack createAudioTrackSource(android.media.audiopolicy.AudioMix) throws java.lang.IllegalArgumentException;
-    method public int detachMixes(@NonNull java.util.List<android.media.audiopolicy.AudioMix>);
-    method public int getFocusDuckingBehavior();
-    method public int getStatus();
-    method public boolean removeUidDeviceAffinity(int);
-    method public boolean removeUserIdDeviceAffinity(int);
-    method public int setFocusDuckingBehavior(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
-    method public void setRegistration(String);
-    method public boolean setUidDeviceAffinity(int, @NonNull java.util.List<android.media.AudioDeviceInfo>);
-    method public boolean setUserIdDeviceAffinity(int, @NonNull java.util.List<android.media.AudioDeviceInfo>);
-    method public String toLogFriendlyString();
-    field public static final int FOCUS_POLICY_DUCKING_DEFAULT = 0; // 0x0
-    field public static final int FOCUS_POLICY_DUCKING_IN_APP = 0; // 0x0
-    field public static final int FOCUS_POLICY_DUCKING_IN_POLICY = 1; // 0x1
-    field public static final int POLICY_STATUS_REGISTERED = 2; // 0x2
-    field public static final int POLICY_STATUS_UNREGISTERED = 1; // 0x1
-  }
-
-  public abstract static class AudioPolicy.AudioPolicyFocusListener {
-    ctor public AudioPolicy.AudioPolicyFocusListener();
-    method public void onAudioFocusAbandon(android.media.AudioFocusInfo);
-    method public void onAudioFocusGrant(android.media.AudioFocusInfo, int);
-    method public void onAudioFocusLoss(android.media.AudioFocusInfo, boolean);
-    method public void onAudioFocusRequest(android.media.AudioFocusInfo, int);
-  }
-
-  public abstract static class AudioPolicy.AudioPolicyStatusListener {
-    ctor public AudioPolicy.AudioPolicyStatusListener();
-    method public void onMixStateUpdate(android.media.audiopolicy.AudioMix);
-    method public void onStatusChange();
-  }
-
-  public abstract static class AudioPolicy.AudioPolicyVolumeCallback {
-    ctor public AudioPolicy.AudioPolicyVolumeCallback();
-    method public void onVolumeAdjustment(int);
-  }
-
   public static class AudioPolicy.Builder {
-    ctor public AudioPolicy.Builder(android.content.Context);
-    method @NonNull public android.media.audiopolicy.AudioPolicy.Builder addMix(@NonNull android.media.audiopolicy.AudioMix) throws java.lang.IllegalArgumentException;
-    method @NonNull public android.media.audiopolicy.AudioPolicy build();
-    method public void setAudioPolicyFocusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener);
-    method public void setAudioPolicyStatusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListener);
-    method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setAudioPolicyVolumeCallback(@NonNull android.media.audiopolicy.AudioPolicy.AudioPolicyVolumeCallback);
-    method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setIsAudioFocusPolicy(boolean);
     method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setIsTestFocusPolicy(boolean);
-    method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setLooper(@NonNull android.os.Looper) throws java.lang.IllegalArgumentException;
-  }
-
-}
-
-package android.media.musicrecognition {
-
-  public class MusicRecognitionManager {
-    field public static final int RECOGNITION_FAILED_AUDIO_UNAVAILABLE = 7; // 0x7
-    field public static final int RECOGNITION_FAILED_NOT_FOUND = 1; // 0x1
-    field public static final int RECOGNITION_FAILED_NO_CONNECTIVITY = 2; // 0x2
-    field public static final int RECOGNITION_FAILED_SERVICE_KILLED = 5; // 0x5
-    field public static final int RECOGNITION_FAILED_SERVICE_UNAVAILABLE = 3; // 0x3
-    field public static final int RECOGNITION_FAILED_TIMEOUT = 6; // 0x6
-    field public static final int RECOGNITION_FAILED_UNKNOWN = -1; // 0xffffffff
-  }
-
-  public static interface MusicRecognitionManager.RecognitionCallback {
-    method public void onAudioStreamClosed();
-    method public void onRecognitionFailed(@NonNull android.media.musicrecognition.RecognitionRequest, int);
-    method public void onRecognitionSucceeded(@NonNull android.media.musicrecognition.RecognitionRequest, @NonNull android.media.MediaMetadata, @Nullable android.os.Bundle);
-  }
-
-  public abstract class MusicRecognitionService extends android.app.Service {
-    ctor public MusicRecognitionService();
-    method public abstract void onRecognize(@NonNull android.os.ParcelFileDescriptor, @NonNull android.media.AudioFormat, @NonNull android.media.musicrecognition.MusicRecognitionService.Callback);
-  }
-
-  public static interface MusicRecognitionService.Callback {
-    method public void onRecognitionFailed(int);
-    method public void onRecognitionSucceeded(@NonNull android.media.MediaMetadata, @Nullable android.os.Bundle);
-  }
-
-  public final class RecognitionRequest implements android.os.Parcelable {
-    method public int describeContents();
-    method @NonNull public android.media.AudioAttributes getAudioAttributes();
-    method @NonNull public android.media.AudioFormat getAudioFormat();
-    method public int getCaptureSession();
-    method public int getIgnoreBeginningFrames();
-    method public int getMaxAudioLengthSeconds();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.media.musicrecognition.RecognitionRequest> CREATOR;
-  }
-
-  public static final class RecognitionRequest.Builder {
-    ctor public RecognitionRequest.Builder();
-    method @NonNull public android.media.musicrecognition.RecognitionRequest build();
-    method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setAudioAttributes(@NonNull android.media.AudioAttributes);
-    method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setAudioFormat(@NonNull android.media.AudioFormat);
-    method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setCaptureSession(int);
-    method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setIgnoreBeginningFrames(int);
-    method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setMaxAudioLengthSeconds(int);
   }
 
 }
@@ -2171,242 +1053,33 @@
   public final class TunerVersionChecker {
     method public static int getMajorVersion(int);
     method public static int getMinorVersion(int);
-    method public static int getTunerVersion();
     method public static boolean isHigherOrEqualVersionTo(int);
     method public static boolean supportTunerVersion(int);
-    field public static final int TUNER_VERSION_1_0 = 65536; // 0x10000
-    field public static final int TUNER_VERSION_1_1 = 65537; // 0x10001
-    field public static final int TUNER_VERSION_UNKNOWN = 0; // 0x0
-  }
-
-}
-
-package android.metrics {
-
-  public class LogMaker {
-    ctor public LogMaker(int);
-    ctor public LogMaker(Object[]);
-    method public android.metrics.LogMaker addTaggedData(int, Object);
-    method public android.metrics.LogMaker clearCategory();
-    method public android.metrics.LogMaker clearPackageName();
-    method public android.metrics.LogMaker clearSubtype();
-    method public android.metrics.LogMaker clearTaggedData(int);
-    method public android.metrics.LogMaker clearType();
-    method public void deserialize(Object[]);
-    method public int getCategory();
-    method public long getCounterBucket();
-    method public String getCounterName();
-    method public int getCounterValue();
-    method public String getPackageName();
-    method public int getProcessId();
-    method public int getSubtype();
-    method public Object getTaggedData(int);
-    method public long getTimestamp();
-    method public int getType();
-    method public int getUid();
-    method public boolean isLongCounterBucket();
-    method public boolean isSubsetOf(android.metrics.LogMaker);
-    method public boolean isValidValue(Object);
-    method public Object[] serialize();
-    method public android.metrics.LogMaker setCategory(int);
-    method public android.metrics.LogMaker setPackageName(String);
-    method public android.metrics.LogMaker setSubtype(int);
-    method public android.metrics.LogMaker setType(int);
-  }
-
-  public class MetricsReader {
-    ctor public MetricsReader();
-    method public void checkpoint();
-    method public boolean hasNext();
-    method public android.metrics.LogMaker next();
-    method public void read(long);
-    method public void reset();
   }
 
 }
 
 package android.net {
 
-  public class CaptivePortal implements android.os.Parcelable {
-    method public void logEvent(int, @NonNull String);
-    method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void reevaluateNetwork();
-    method public void useNetwork();
-    field public static final int APP_REQUEST_REEVALUATION_REQUIRED = 100; // 0x64
-    field public static final int APP_RETURN_DISMISSED = 0; // 0x0
-    field public static final int APP_RETURN_UNWANTED = 1; // 0x1
-    field public static final int APP_RETURN_WANTED_AS_IS = 2; // 0x2
-  }
-
-  public final class CaptivePortalData implements android.os.Parcelable {
-    method public int describeContents();
-    method public long getByteLimit();
-    method public long getExpiryTimeMillis();
-    method public long getRefreshTimeMillis();
-    method @Nullable public android.net.Uri getUserPortalUrl();
-    method @Nullable public android.net.Uri getVenueInfoUrl();
-    method public boolean isCaptive();
-    method public boolean isSessionExtendable();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.CaptivePortalData> CREATOR;
-  }
-
-  public static class CaptivePortalData.Builder {
-    ctor public CaptivePortalData.Builder();
-    ctor public CaptivePortalData.Builder(@Nullable android.net.CaptivePortalData);
-    method @NonNull public android.net.CaptivePortalData build();
-    method @NonNull public android.net.CaptivePortalData.Builder setBytesRemaining(long);
-    method @NonNull public android.net.CaptivePortalData.Builder setCaptive(boolean);
-    method @NonNull public android.net.CaptivePortalData.Builder setExpiryTime(long);
-    method @NonNull public android.net.CaptivePortalData.Builder setRefreshTime(long);
-    method @NonNull public android.net.CaptivePortalData.Builder setSessionExtendable(boolean);
-    method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri);
-    method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri);
-  }
-
   public class ConnectivityManager {
     method @RequiresPermission(anyOf={"android.permission.MANAGE_TEST_NETWORKS", android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle);
-    method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(@NonNull android.net.Network, @NonNull android.os.Bundle);
-    field public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC";
-    field public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = "android.net.extra.CAPTIVE_PORTAL_USER_AGENT";
   }
 
   public class EthernetManager {
-    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public android.net.EthernetManager.TetheredInterfaceRequest requestTetheredInterface(@NonNull java.util.concurrent.Executor, @NonNull android.net.EthernetManager.TetheredInterfaceCallback);
     method public void setIncludeTestInterfaces(boolean);
   }
 
-  public static interface EthernetManager.TetheredInterfaceCallback {
-    method public void onAvailable(@NonNull String);
-    method public void onUnavailable();
-  }
-
-  public static class EthernetManager.TetheredInterfaceRequest {
-    method public void release();
-  }
-
-  public final class IpPrefix implements android.os.Parcelable {
-    ctor public IpPrefix(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int);
-    ctor public IpPrefix(@NonNull String);
-  }
-
   public final class IpSecManager {
     field public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; // 0x0
   }
 
-  public class LinkAddress implements android.os.Parcelable {
-    ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int, int, int);
-    ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int, int, int, long, long);
-    ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int);
-    ctor public LinkAddress(@NonNull String);
-    ctor public LinkAddress(@NonNull String, int, int);
-    method public long getDeprecationTime();
-    method public long getExpirationTime();
-    method public boolean isGlobalPreferred();
-    method public boolean isIpv4();
-    method public boolean isIpv6();
-    method public boolean isSameAddressAs(@Nullable android.net.LinkAddress);
-  }
-
-  public final class LinkProperties implements android.os.Parcelable {
-    ctor public LinkProperties(@Nullable android.net.LinkProperties);
-    ctor public LinkProperties(@Nullable android.net.LinkProperties, boolean);
-    method public boolean addDnsServer(@NonNull java.net.InetAddress);
-    method public boolean addLinkAddress(@NonNull android.net.LinkAddress);
-    method @Nullable public android.net.Uri getCaptivePortalApiUrl();
-    method @Nullable public android.net.CaptivePortalData getCaptivePortalData();
-    method @NonNull public java.util.List<java.net.InetAddress> getPcscfServers();
-    method @Nullable public String getTcpBufferSizes();
-    method @NonNull public java.util.List<java.net.InetAddress> getValidatedPrivateDnsServers();
-    method public boolean hasGlobalIpv6Address();
-    method public boolean hasIpv4Address();
-    method public boolean hasIpv6DefaultRoute();
-    method public boolean isIpv4Provisioned();
-    method public boolean isIpv6Provisioned();
-    method public boolean isProvisioned();
-    method public boolean isReachable(@NonNull java.net.InetAddress);
-    method public boolean removeDnsServer(@NonNull java.net.InetAddress);
-    method public boolean removeLinkAddress(@NonNull android.net.LinkAddress);
-    method public boolean removeRoute(@NonNull android.net.RouteInfo);
-    method public void setCaptivePortalApiUrl(@Nullable android.net.Uri);
-    method public void setCaptivePortalData(@Nullable android.net.CaptivePortalData);
-    method public void setPcscfServers(@NonNull java.util.Collection<java.net.InetAddress>);
-    method public void setPrivateDnsServerName(@Nullable String);
-    method public void setTcpBufferSizes(@Nullable String);
-    method public void setUsePrivateDns(boolean);
-    method public void setValidatedPrivateDnsServers(@NonNull java.util.Collection<java.net.InetAddress>);
-  }
-
-  public class Network implements android.os.Parcelable {
-    ctor public Network(@NonNull android.net.Network);
-    method public int getNetId();
-    method @NonNull public android.net.Network getPrivateDnsBypassingCopy();
-  }
-
   public final class NetworkCapabilities implements android.os.Parcelable {
-    method @NonNull public int[] getAdministratorUids();
     method public int[] getCapabilities();
-    method @Nullable public String getSsid();
-    method @NonNull public int[] getTransportTypes();
-    method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities);
     field public static final int TRANSPORT_TEST = 7; // 0x7
   }
 
-  public static final class NetworkCapabilities.Builder {
-    ctor public NetworkCapabilities.Builder();
-    ctor public NetworkCapabilities.Builder(@NonNull android.net.NetworkCapabilities);
-    method @NonNull public android.net.NetworkCapabilities.Builder addCapability(int);
-    method @NonNull public android.net.NetworkCapabilities.Builder addTransportType(int);
-    method @NonNull public android.net.NetworkCapabilities build();
-    method @NonNull public android.net.NetworkCapabilities.Builder removeCapability(int);
-    method @NonNull public android.net.NetworkCapabilities.Builder removeTransportType(int);
-    method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setAdministratorUids(@NonNull int[]);
-    method @NonNull public android.net.NetworkCapabilities.Builder setLinkDownstreamBandwidthKbps(int);
-    method @NonNull public android.net.NetworkCapabilities.Builder setLinkUpstreamBandwidthKbps(int);
-    method @NonNull public android.net.NetworkCapabilities.Builder setNetworkSpecifier(@Nullable android.net.NetworkSpecifier);
-    method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setOwnerUid(int);
-    method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setRequestorPackageName(@Nullable String);
-    method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setRequestorUid(int);
-    method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) public android.net.NetworkCapabilities.Builder setSignalStrength(int);
-    method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setSsid(@Nullable String);
-    method @NonNull public android.net.NetworkCapabilities.Builder setTransportInfo(@Nullable android.net.TransportInfo);
-  }
-
   public class NetworkStack {
-    method @Nullable public static android.os.IBinder getService();
     method public static void setServiceForTest(@Nullable android.os.IBinder);
-    field public static final String PERMISSION_MAINLINE_NETWORK_STACK = "android.permission.MAINLINE_NETWORK_STACK";
-  }
-
-  public final class RouteInfo implements android.os.Parcelable {
-    ctor public RouteInfo(@Nullable android.net.IpPrefix, @Nullable java.net.InetAddress, @Nullable String, int);
-    method public int getType();
-    field public static final int RTN_THROW = 9; // 0x9
-    field public static final int RTN_UNICAST = 1; // 0x1
-    field public static final int RTN_UNREACHABLE = 7; // 0x7
-  }
-
-  public final class StaticIpConfiguration implements android.os.Parcelable {
-    ctor public StaticIpConfiguration();
-    ctor public StaticIpConfiguration(@Nullable android.net.StaticIpConfiguration);
-    method public void addDnsServer(@NonNull java.net.InetAddress);
-    method public void clear();
-    method public int describeContents();
-    method @NonNull public java.util.List<java.net.InetAddress> getDnsServers();
-    method @Nullable public String getDomains();
-    method @Nullable public java.net.InetAddress getGateway();
-    method @Nullable public android.net.LinkAddress getIpAddress();
-    method @NonNull public java.util.List<android.net.RouteInfo> getRoutes(@Nullable String);
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.StaticIpConfiguration> CREATOR;
-  }
-
-  public static final class StaticIpConfiguration.Builder {
-    ctor public StaticIpConfiguration.Builder();
-    method @NonNull public android.net.StaticIpConfiguration build();
-    method @NonNull public android.net.StaticIpConfiguration.Builder setDnsServers(@NonNull Iterable<java.net.InetAddress>);
-    method @NonNull public android.net.StaticIpConfiguration.Builder setDomains(@Nullable String);
-    method @NonNull public android.net.StaticIpConfiguration.Builder setGateway(@Nullable java.net.InetAddress);
-    method @NonNull public android.net.StaticIpConfiguration.Builder setIpAddress(@Nullable android.net.LinkAddress);
   }
 
   public final class TestNetworkInterface implements android.os.Parcelable {
@@ -2434,228 +1107,8 @@
 
 }
 
-package android.net.apf {
-
-  public final class ApfCapabilities implements android.os.Parcelable {
-    ctor public ApfCapabilities(int, int, int);
-    method public int describeContents();
-    method public static boolean getApfDrop8023Frames();
-    method @NonNull public static int[] getApfEtherTypeBlackList();
-    method public boolean hasDataAccess();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.net.apf.ApfCapabilities> CREATOR;
-    field public final int apfPacketFormat;
-    field public final int apfVersionSupported;
-    field public final int maximumApfProgramSize;
-  }
-
-}
-
-package android.net.metrics {
-
-  public final class ApfProgramEvent implements android.net.metrics.IpConnectivityLog.Event {
-  }
-
-  public static final class ApfProgramEvent.Builder {
-    ctor public ApfProgramEvent.Builder();
-    method @NonNull public android.net.metrics.ApfProgramEvent build();
-    method @NonNull public android.net.metrics.ApfProgramEvent.Builder setActualLifetime(long);
-    method @NonNull public android.net.metrics.ApfProgramEvent.Builder setCurrentRas(int);
-    method @NonNull public android.net.metrics.ApfProgramEvent.Builder setFilteredRas(int);
-    method @NonNull public android.net.metrics.ApfProgramEvent.Builder setFlags(boolean, boolean);
-    method @NonNull public android.net.metrics.ApfProgramEvent.Builder setLifetime(long);
-    method @NonNull public android.net.metrics.ApfProgramEvent.Builder setProgramLength(int);
-  }
-
-  public final class ApfStats implements android.net.metrics.IpConnectivityLog.Event {
-  }
-
-  public static final class ApfStats.Builder {
-    ctor public ApfStats.Builder();
-    method @NonNull public android.net.metrics.ApfStats build();
-    method @NonNull public android.net.metrics.ApfStats.Builder setDroppedRas(int);
-    method @NonNull public android.net.metrics.ApfStats.Builder setDurationMs(long);
-    method @NonNull public android.net.metrics.ApfStats.Builder setMatchingRas(int);
-    method @NonNull public android.net.metrics.ApfStats.Builder setMaxProgramSize(int);
-    method @NonNull public android.net.metrics.ApfStats.Builder setParseErrors(int);
-    method @NonNull public android.net.metrics.ApfStats.Builder setProgramUpdates(int);
-    method @NonNull public android.net.metrics.ApfStats.Builder setProgramUpdatesAll(int);
-    method @NonNull public android.net.metrics.ApfStats.Builder setProgramUpdatesAllowingMulticast(int);
-    method @NonNull public android.net.metrics.ApfStats.Builder setReceivedRas(int);
-    method @NonNull public android.net.metrics.ApfStats.Builder setZeroLifetimeRas(int);
-  }
-
-  public final class DhcpClientEvent implements android.net.metrics.IpConnectivityLog.Event {
-  }
-
-  public static final class DhcpClientEvent.Builder {
-    ctor public DhcpClientEvent.Builder();
-    method @NonNull public android.net.metrics.DhcpClientEvent build();
-    method @NonNull public android.net.metrics.DhcpClientEvent.Builder setDurationMs(int);
-    method @NonNull public android.net.metrics.DhcpClientEvent.Builder setMsg(String);
-  }
-
-  public final class DhcpErrorEvent implements android.net.metrics.IpConnectivityLog.Event {
-    ctor public DhcpErrorEvent(int);
-    method public static int errorCodeWithOption(int, int);
-    field public static final int BOOTP_TOO_SHORT = 67174400; // 0x4010000
-    field public static final int BUFFER_UNDERFLOW = 83951616; // 0x5010000
-    field public static final int DHCP_BAD_MAGIC_COOKIE = 67239936; // 0x4020000
-    field public static final int DHCP_ERROR = 4; // 0x4
-    field public static final int DHCP_INVALID_OPTION_LENGTH = 67305472; // 0x4030000
-    field public static final int DHCP_NO_COOKIE = 67502080; // 0x4060000
-    field public static final int DHCP_NO_MSG_TYPE = 67371008; // 0x4040000
-    field public static final int DHCP_UNKNOWN_MSG_TYPE = 67436544; // 0x4050000
-    field public static final int L2_ERROR = 1; // 0x1
-    field public static final int L2_TOO_SHORT = 16842752; // 0x1010000
-    field public static final int L2_WRONG_ETH_TYPE = 16908288; // 0x1020000
-    field public static final int L3_ERROR = 2; // 0x2
-    field public static final int L3_INVALID_IP = 33751040; // 0x2030000
-    field public static final int L3_NOT_IPV4 = 33685504; // 0x2020000
-    field public static final int L3_TOO_SHORT = 33619968; // 0x2010000
-    field public static final int L4_ERROR = 3; // 0x3
-    field public static final int L4_NOT_UDP = 50397184; // 0x3010000
-    field public static final int L4_WRONG_PORT = 50462720; // 0x3020000
-    field public static final int MISC_ERROR = 5; // 0x5
-    field public static final int PARSING_ERROR = 84082688; // 0x5030000
-    field public static final int RECEIVE_ERROR = 84017152; // 0x5020000
-  }
-
-  public class IpConnectivityLog {
-    ctor public IpConnectivityLog();
-    method public boolean log(long, @NonNull android.net.metrics.IpConnectivityLog.Event);
-    method public boolean log(@NonNull String, @NonNull android.net.metrics.IpConnectivityLog.Event);
-    method public boolean log(@NonNull android.net.Network, @NonNull int[], @NonNull android.net.metrics.IpConnectivityLog.Event);
-    method public boolean log(int, @NonNull int[], @NonNull android.net.metrics.IpConnectivityLog.Event);
-    method public boolean log(@NonNull android.net.metrics.IpConnectivityLog.Event);
-  }
-
-  public static interface IpConnectivityLog.Event extends android.os.Parcelable {
-  }
-
-  public final class IpManagerEvent implements android.net.metrics.IpConnectivityLog.Event {
-    ctor public IpManagerEvent(int, long);
-    field public static final int COMPLETE_LIFECYCLE = 3; // 0x3
-    field public static final int ERROR_INTERFACE_NOT_FOUND = 8; // 0x8
-    field public static final int ERROR_INVALID_PROVISIONING = 7; // 0x7
-    field public static final int ERROR_STARTING_IPREACHABILITYMONITOR = 6; // 0x6
-    field public static final int ERROR_STARTING_IPV4 = 4; // 0x4
-    field public static final int ERROR_STARTING_IPV6 = 5; // 0x5
-    field public static final int PROVISIONING_FAIL = 2; // 0x2
-    field public static final int PROVISIONING_OK = 1; // 0x1
-  }
-
-  public final class IpReachabilityEvent implements android.net.metrics.IpConnectivityLog.Event {
-    ctor public IpReachabilityEvent(int);
-    field public static final int NUD_FAILED = 512; // 0x200
-    field public static final int NUD_FAILED_ORGANIC = 1024; // 0x400
-    field public static final int PROBE = 256; // 0x100
-    field public static final int PROVISIONING_LOST = 768; // 0x300
-    field public static final int PROVISIONING_LOST_ORGANIC = 1280; // 0x500
-  }
-
-  public final class NetworkEvent implements android.net.metrics.IpConnectivityLog.Event {
-    ctor public NetworkEvent(int, long);
-    ctor public NetworkEvent(int);
-    field public static final int NETWORK_CAPTIVE_PORTAL_FOUND = 4; // 0x4
-    field public static final int NETWORK_CONNECTED = 1; // 0x1
-    field public static final int NETWORK_CONSECUTIVE_DNS_TIMEOUT_FOUND = 12; // 0xc
-    field public static final int NETWORK_DISCONNECTED = 7; // 0x7
-    field public static final int NETWORK_FIRST_VALIDATION_PORTAL_FOUND = 10; // 0xa
-    field public static final int NETWORK_FIRST_VALIDATION_SUCCESS = 8; // 0x8
-    field public static final int NETWORK_LINGER = 5; // 0x5
-    field public static final int NETWORK_PARTIAL_CONNECTIVITY = 13; // 0xd
-    field public static final int NETWORK_REVALIDATION_PORTAL_FOUND = 11; // 0xb
-    field public static final int NETWORK_REVALIDATION_SUCCESS = 9; // 0x9
-    field public static final int NETWORK_UNLINGER = 6; // 0x6
-    field public static final int NETWORK_VALIDATED = 2; // 0x2
-    field public static final int NETWORK_VALIDATION_FAILED = 3; // 0x3
-  }
-
-  public final class RaEvent implements android.net.metrics.IpConnectivityLog.Event {
-  }
-
-  public static final class RaEvent.Builder {
-    ctor public RaEvent.Builder();
-    method @NonNull public android.net.metrics.RaEvent build();
-    method @NonNull public android.net.metrics.RaEvent.Builder updateDnsslLifetime(long);
-    method @NonNull public android.net.metrics.RaEvent.Builder updatePrefixPreferredLifetime(long);
-    method @NonNull public android.net.metrics.RaEvent.Builder updatePrefixValidLifetime(long);
-    method @NonNull public android.net.metrics.RaEvent.Builder updateRdnssLifetime(long);
-    method @NonNull public android.net.metrics.RaEvent.Builder updateRouteInfoLifetime(long);
-    method @NonNull public android.net.metrics.RaEvent.Builder updateRouterLifetime(long);
-  }
-
-  public final class ValidationProbeEvent implements android.net.metrics.IpConnectivityLog.Event {
-    method @NonNull public static String getProbeName(int);
-    field public static final int DNS_FAILURE = 0; // 0x0
-    field public static final int DNS_SUCCESS = 1; // 0x1
-    field public static final int PROBE_DNS = 0; // 0x0
-    field public static final int PROBE_FALLBACK = 4; // 0x4
-    field public static final int PROBE_HTTP = 1; // 0x1
-    field public static final int PROBE_HTTPS = 2; // 0x2
-    field public static final int PROBE_PAC = 3; // 0x3
-    field public static final int PROBE_PRIVDNS = 5; // 0x5
-  }
-
-  public static final class ValidationProbeEvent.Builder {
-    ctor public ValidationProbeEvent.Builder();
-    method @NonNull public android.net.metrics.ValidationProbeEvent build();
-    method @NonNull public android.net.metrics.ValidationProbeEvent.Builder setDurationMs(long);
-    method @NonNull public android.net.metrics.ValidationProbeEvent.Builder setProbeType(int, boolean);
-    method @NonNull public android.net.metrics.ValidationProbeEvent.Builder setReturnCode(int);
-  }
-
-}
-
-package android.net.util {
-
-  public final class SocketUtils {
-    method public static void bindSocketToInterface(@NonNull java.io.FileDescriptor, @NonNull String) throws android.system.ErrnoException;
-    method public static void closeSocket(@Nullable java.io.FileDescriptor) throws java.io.IOException;
-    method @NonNull public static java.net.SocketAddress makeNetlinkSocketAddress(int, int);
-    method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int);
-    method @Deprecated @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, @NonNull byte[]);
-    method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int, @NonNull byte[]);
-  }
-
-}
-
 package android.os {
 
-  public class BatteryManager {
-    method @RequiresPermission(android.Manifest.permission.POWER_SAVER) public boolean setChargingStateUpdateDelayMillis(int);
-  }
-
-  public final class BugreportManager {
-    method @RequiresPermission(android.Manifest.permission.DUMP) public void cancelBugreport();
-    method @RequiresPermission(android.Manifest.permission.DUMP) public void requestBugreport(@NonNull android.os.BugreportParams, @Nullable CharSequence, @Nullable CharSequence);
-    method @RequiresPermission(android.Manifest.permission.DUMP) public void startBugreport(@NonNull android.os.ParcelFileDescriptor, @Nullable android.os.ParcelFileDescriptor, @NonNull android.os.BugreportParams, @NonNull java.util.concurrent.Executor, @NonNull android.os.BugreportManager.BugreportCallback);
-  }
-
-  public abstract static class BugreportManager.BugreportCallback {
-    ctor public BugreportManager.BugreportCallback();
-    method public void onError(int);
-    method public void onFinished();
-    method public void onProgress(@FloatRange(from=0.0f, to=100.0f) float);
-    field public static final int BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS = 5; // 0x5
-    field public static final int BUGREPORT_ERROR_INVALID_INPUT = 1; // 0x1
-    field public static final int BUGREPORT_ERROR_RUNTIME = 2; // 0x2
-    field public static final int BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT = 4; // 0x4
-    field public static final int BUGREPORT_ERROR_USER_DENIED_CONSENT = 3; // 0x3
-  }
-
-  public final class BugreportParams {
-    ctor public BugreportParams(int);
-    method public int getMode();
-    field public static final int BUGREPORT_MODE_FULL = 0; // 0x0
-    field public static final int BUGREPORT_MODE_INTERACTIVE = 1; // 0x1
-    field public static final int BUGREPORT_MODE_REMOTE = 2; // 0x2
-    field public static final int BUGREPORT_MODE_TELEPHONY = 4; // 0x4
-    field public static final int BUGREPORT_MODE_WEAR = 3; // 0x3
-    field public static final int BUGREPORT_MODE_WIFI = 5; // 0x5
-  }
-
   public class Build {
     method public static boolean is64BitAbi(String);
     field public static final boolean IS_EMULATOR;
@@ -2668,18 +1121,12 @@
   }
 
   public class DeviceIdleManager {
-    method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void endIdle(@NonNull String);
     method @NonNull public String[] getSystemPowerWhitelist();
     method @NonNull public String[] getSystemPowerWhitelistExceptIdle();
   }
 
   public class Environment {
     method public static java.io.File buildPath(java.io.File, java.lang.String...);
-    method @NonNull public static java.io.File getOdmDirectory();
-    method @NonNull public static java.io.File getOemDirectory();
-    method @NonNull public static java.io.File getProductDirectory();
-    method @NonNull public static java.io.File getSystemExtDirectory();
-    method @NonNull public static java.io.File getVendorDirectory();
   }
 
   public final class FileUtils {
@@ -2688,228 +1135,11 @@
     method @NonNull public static byte[] digest(@NonNull java.io.InputStream, @NonNull String) throws java.io.IOException, java.security.NoSuchAlgorithmException;
   }
 
-  public class HidlMemory implements java.io.Closeable {
-    ctor public HidlMemory(@NonNull String, @IntRange(from=0) long, @Nullable android.os.NativeHandle);
-    method public void close() throws java.io.IOException;
-    method @NonNull public android.os.HidlMemory dup() throws java.io.IOException;
-    method protected void finalize();
-    method @Nullable public android.os.NativeHandle getHandle();
-    method @NonNull public String getName();
-    method public long getSize();
-    method @Nullable public android.os.NativeHandle releaseHandle();
-  }
-
-  public abstract class HwBinder implements android.os.IHwBinder {
-    ctor public HwBinder();
-    method public static final void configureRpcThreadpool(long, boolean);
-    method public static void enableInstrumentation();
-    method public static final android.os.IHwBinder getService(String, String) throws java.util.NoSuchElementException, android.os.RemoteException;
-    method public static final android.os.IHwBinder getService(String, String, boolean) throws java.util.NoSuchElementException, android.os.RemoteException;
-    method public static final void joinRpcThreadpool();
-    method public abstract void onTransact(int, android.os.HwParcel, android.os.HwParcel, int) throws android.os.RemoteException;
-    method public final void registerService(String) throws android.os.RemoteException;
-    method public final void transact(int, android.os.HwParcel, android.os.HwParcel, int) throws android.os.RemoteException;
-  }
-
-  public class HwBlob {
-    ctor public HwBlob(int);
-    method public final void copyToBoolArray(long, boolean[], int);
-    method public final void copyToDoubleArray(long, double[], int);
-    method public final void copyToFloatArray(long, float[], int);
-    method public final void copyToInt16Array(long, short[], int);
-    method public final void copyToInt32Array(long, int[], int);
-    method public final void copyToInt64Array(long, long[], int);
-    method public final void copyToInt8Array(long, byte[], int);
-    method public final boolean getBool(long);
-    method public final double getDouble(long);
-    method public final long getFieldHandle(long);
-    method public final float getFloat(long);
-    method public final short getInt16(long);
-    method public final int getInt32(long);
-    method public final long getInt64(long);
-    method public final byte getInt8(long);
-    method public final String getString(long);
-    method public final long handle();
-    method public final void putBlob(long, android.os.HwBlob);
-    method public final void putBool(long, boolean);
-    method public final void putBoolArray(long, boolean[]);
-    method public final void putDouble(long, double);
-    method public final void putDoubleArray(long, double[]);
-    method public final void putFloat(long, float);
-    method public final void putFloatArray(long, float[]);
-    method public final void putHidlMemory(long, @NonNull android.os.HidlMemory);
-    method public final void putInt16(long, short);
-    method public final void putInt16Array(long, short[]);
-    method public final void putInt32(long, int);
-    method public final void putInt32Array(long, int[]);
-    method public final void putInt64(long, long);
-    method public final void putInt64Array(long, long[]);
-    method public final void putInt8(long, byte);
-    method public final void putInt8Array(long, byte[]);
-    method public final void putNativeHandle(long, @Nullable android.os.NativeHandle);
-    method public final void putString(long, String);
-    method public static Boolean[] wrapArray(@NonNull boolean[]);
-    method public static Long[] wrapArray(@NonNull long[]);
-    method public static Byte[] wrapArray(@NonNull byte[]);
-    method public static Short[] wrapArray(@NonNull short[]);
-    method public static Integer[] wrapArray(@NonNull int[]);
-    method public static Float[] wrapArray(@NonNull float[]);
-    method public static Double[] wrapArray(@NonNull double[]);
-  }
-
-  public class HwParcel {
-    ctor public HwParcel();
-    method public final void enforceInterface(String);
-    method public final boolean readBool();
-    method public final java.util.ArrayList<java.lang.Boolean> readBoolVector();
-    method public final android.os.HwBlob readBuffer(long);
-    method public final double readDouble();
-    method public final java.util.ArrayList<java.lang.Double> readDoubleVector();
-    method public final android.os.HwBlob readEmbeddedBuffer(long, long, long, boolean);
-    method @NonNull @Nullable public final android.os.HidlMemory readEmbeddedHidlMemory(long, long, long);
-    method @Nullable public final android.os.NativeHandle readEmbeddedNativeHandle(long, long);
-    method public final float readFloat();
-    method public final java.util.ArrayList<java.lang.Float> readFloatVector();
-    method @NonNull public final android.os.HidlMemory readHidlMemory();
-    method public final short readInt16();
-    method public final java.util.ArrayList<java.lang.Short> readInt16Vector();
-    method public final int readInt32();
-    method public final java.util.ArrayList<java.lang.Integer> readInt32Vector();
-    method public final long readInt64();
-    method public final java.util.ArrayList<java.lang.Long> readInt64Vector();
-    method public final byte readInt8();
-    method public final java.util.ArrayList<java.lang.Byte> readInt8Vector();
-    method @Nullable public final android.os.NativeHandle readNativeHandle();
-    method @NonNull public final java.util.ArrayList<android.os.NativeHandle> readNativeHandleVector();
-    method public final String readString();
-    method public final java.util.ArrayList<java.lang.String> readStringVector();
-    method public final android.os.IHwBinder readStrongBinder();
-    method public final void release();
-    method public final void releaseTemporaryStorage();
-    method public final void send();
-    method public final void verifySuccess();
-    method public final void writeBool(boolean);
-    method public final void writeBoolVector(java.util.ArrayList<java.lang.Boolean>);
-    method public final void writeBuffer(android.os.HwBlob);
-    method public final void writeDouble(double);
-    method public final void writeDoubleVector(java.util.ArrayList<java.lang.Double>);
-    method public final void writeFloat(float);
-    method public final void writeFloatVector(java.util.ArrayList<java.lang.Float>);
-    method public final void writeHidlMemory(@NonNull android.os.HidlMemory);
-    method public final void writeInt16(short);
-    method public final void writeInt16Vector(java.util.ArrayList<java.lang.Short>);
-    method public final void writeInt32(int);
-    method public final void writeInt32Vector(java.util.ArrayList<java.lang.Integer>);
-    method public final void writeInt64(long);
-    method public final void writeInt64Vector(java.util.ArrayList<java.lang.Long>);
-    method public final void writeInt8(byte);
-    method public final void writeInt8Vector(java.util.ArrayList<java.lang.Byte>);
-    method public final void writeInterfaceToken(String);
-    method public final void writeNativeHandle(@Nullable android.os.NativeHandle);
-    method public final void writeNativeHandleVector(@NonNull java.util.ArrayList<android.os.NativeHandle>);
-    method public final void writeStatus(int);
-    method public final void writeString(String);
-    method public final void writeStringVector(java.util.ArrayList<java.lang.String>);
-    method public final void writeStrongBinder(android.os.IHwBinder);
-    field public static final int STATUS_SUCCESS = 0; // 0x0
-  }
-
-  public interface IHwBinder {
-    method public boolean linkToDeath(android.os.IHwBinder.DeathRecipient, long);
-    method public android.os.IHwInterface queryLocalInterface(String);
-    method public void transact(int, android.os.HwParcel, android.os.HwParcel, int) throws android.os.RemoteException;
-    method public boolean unlinkToDeath(android.os.IHwBinder.DeathRecipient);
-  }
-
-  public static interface IHwBinder.DeathRecipient {
-    method public void serviceDied(long);
-  }
-
-  public interface IHwInterface {
-    method public android.os.IHwBinder asBinder();
-  }
-
-  public class IncidentManager {
-    method @RequiresPermission(android.Manifest.permission.APPROVE_INCIDENT_REPORTS) public void approveReport(android.net.Uri);
-    method @RequiresPermission("android.permission.REQUEST_INCIDENT_REPORT_APPROVAL") public void cancelAuthorization(android.os.IncidentManager.AuthListener);
-    method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void deleteIncidentReports(android.net.Uri);
-    method @RequiresPermission(android.Manifest.permission.APPROVE_INCIDENT_REPORTS) public void denyReport(android.net.Uri);
-    method @Nullable @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public android.os.IncidentManager.IncidentReport getIncidentReport(android.net.Uri);
-    method @NonNull @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public java.util.List<android.net.Uri> getIncidentReportList(String);
-    method @RequiresPermission(android.Manifest.permission.APPROVE_INCIDENT_REPORTS) public java.util.List<android.os.IncidentManager.PendingReport> getPendingReports();
-    method public void registerSection(int, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.os.IncidentManager.DumpCallback);
-    method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void reportIncident(android.os.IncidentReportArgs);
-    method @RequiresPermission("android.permission.REQUEST_INCIDENT_REPORT_APPROVAL") public void requestAuthorization(int, String, int, android.os.IncidentManager.AuthListener);
-    method public void unregisterSection(int);
-    field public static final int FLAG_CONFIRMATION_DIALOG = 1; // 0x1
-    field public static final int PRIVACY_POLICY_AUTO = 200; // 0xc8
-    field public static final int PRIVACY_POLICY_EXPLICIT = 100; // 0x64
-    field public static final int PRIVACY_POLICY_LOCAL = 0; // 0x0
-  }
-
-  public static class IncidentManager.AuthListener {
-    ctor public IncidentManager.AuthListener();
-    method public void onReportApproved();
-    method public void onReportDenied();
-  }
-
-  public static class IncidentManager.DumpCallback {
-    ctor public IncidentManager.DumpCallback();
-    method public void onDumpSection(int, @NonNull java.io.OutputStream);
-  }
-
-  public static class IncidentManager.IncidentReport implements java.io.Closeable android.os.Parcelable {
-    ctor public IncidentManager.IncidentReport(android.os.Parcel);
-    method public void close();
-    method public int describeContents();
-    method public java.io.InputStream getInputStream() throws java.io.IOException;
-    method public long getPrivacyPolicy();
-    method public long getTimestamp();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.os.IncidentManager.IncidentReport> CREATOR;
-  }
-
-  public static class IncidentManager.PendingReport {
-    ctor public IncidentManager.PendingReport(@NonNull android.net.Uri);
-    method public int getFlags();
-    method @NonNull public String getRequestingPackage();
-    method public long getTimestamp();
-    method @NonNull public android.net.Uri getUri();
-  }
-
-  public final class IncidentReportArgs implements android.os.Parcelable {
-    ctor public IncidentReportArgs();
-    ctor public IncidentReportArgs(android.os.Parcel);
-    method public void addHeader(byte[]);
-    method public void addSection(int);
-    method public boolean containsSection(int);
-    method public int describeContents();
-    method public boolean isAll();
-    method public void readFromParcel(android.os.Parcel);
-    method public int sectionCount();
-    method public void setAll(boolean);
-    method public void setPrivacyPolicy(int);
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.os.IncidentReportArgs> CREATOR;
-  }
-
   public final class MessageQueue {
     method public int postSyncBarrier();
     method public void removeSyncBarrier(int);
   }
 
-  public final class NativeHandle implements java.io.Closeable {
-    ctor public NativeHandle();
-    ctor public NativeHandle(@NonNull java.io.FileDescriptor, boolean);
-    ctor public NativeHandle(@NonNull java.io.FileDescriptor[], @NonNull int[], boolean);
-    method public void close() throws java.io.IOException;
-    method @NonNull public android.os.NativeHandle dup() throws java.io.IOException;
-    method @NonNull public java.io.FileDescriptor getFileDescriptor();
-    method @NonNull public java.io.FileDescriptor[] getFileDescriptors();
-    method @NonNull public int[] getInts();
-    method public boolean hasSingleFileDescriptor();
-  }
-
   public final class Parcel {
     method public boolean allowSquashing();
     method public int readExceptionCode();
@@ -2921,24 +1151,7 @@
   }
 
   public final class PowerManager {
-    method @RequiresPermission(android.Manifest.permission.POWER_SAVER) public int getPowerSaveModeTrigger();
-    method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void setBatteryDischargePrediction(@NonNull java.time.Duration, boolean);
-    method @RequiresPermission(android.Manifest.permission.POWER_SAVER) public boolean setDynamicPowerSaveHint(boolean, int);
-    method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setPowerSaveModeEnabled(boolean);
     field public static final String ACTION_ENHANCED_DISCHARGE_PREDICTION_CHANGED = "android.os.action.ENHANCED_DISCHARGE_PREDICTION_CHANGED";
-    field public static final int POWER_SAVE_MODE_TRIGGER_DYNAMIC = 1; // 0x1
-    field public static final int POWER_SAVE_MODE_TRIGGER_PERCENTAGE = 0; // 0x0
-  }
-
-  public class PowerWhitelistManager {
-    method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void addToWhitelist(@NonNull String);
-    method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void addToWhitelist(@NonNull java.util.List<java.lang.String>);
-    method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void removeFromWhitelist(@NonNull String);
-    method @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST) public void whitelistAppTemporarily(@NonNull String, long);
-    method @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST) public long whitelistAppTemporarilyForEvent(@NonNull String, int, @NonNull String);
-    field public static final int EVENT_MMS = 2; // 0x2
-    field public static final int EVENT_SMS = 1; // 0x1
-    field public static final int EVENT_UNSPECIFIED = 0; // 0x0
   }
 
   public class Process {
@@ -2950,19 +1163,6 @@
     field public static final int NUM_UIDS_PER_APP_ZYGOTE = 100; // 0x64
   }
 
-  public final class RemoteCallback implements android.os.Parcelable {
-    ctor public RemoteCallback(android.os.RemoteCallback.OnResultListener);
-    ctor public RemoteCallback(@NonNull android.os.RemoteCallback.OnResultListener, @Nullable android.os.Handler);
-    method public int describeContents();
-    method public void sendResult(@Nullable android.os.Bundle);
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.os.RemoteCallback> CREATOR;
-  }
-
-  public static interface RemoteCallback.OnResultListener {
-    method public void onResult(@Nullable android.os.Bundle);
-  }
-
   public final class StrictMode {
     method public static void conditionallyCheckInstanceCounts();
     method public static void setViolationLogger(android.os.StrictMode.ViolationLogger);
@@ -3000,31 +1200,11 @@
     method @NonNull public android.os.StrictMode.VmPolicy.Builder permitIncorrectContextUse();
   }
 
-  public class SystemConfigManager {
-    method @NonNull @RequiresPermission(android.Manifest.permission.READ_CARRIER_APP_INFO) public java.util.Set<java.lang.String> getDisabledUntilUsedPreinstalledCarrierApps();
-    method @NonNull @RequiresPermission(android.Manifest.permission.READ_CARRIER_APP_INFO) public java.util.Map<java.lang.String,java.util.List<java.lang.String>> getDisabledUntilUsedPreinstalledCarrierAssociatedApps();
-  }
-
-  public class SystemProperties {
-    method @NonNull public static String get(@NonNull String);
-    method @NonNull public static String get(@NonNull String, @Nullable String);
-    method public static boolean getBoolean(@NonNull String, boolean);
-    method public static int getInt(@NonNull String, int);
-    method public static long getLong(@NonNull String, long);
-  }
-
   public final class UserHandle implements android.os.Parcelable {
-    method public static int getAppId(int);
-    method public int getIdentifier();
     method public static int getUid(int, int);
     method public static int getUserId(int);
     method public static boolean isApp(int);
-    method public static int myUserId();
-    method public static android.os.UserHandle of(int);
-    field @NonNull public static final android.os.UserHandle ALL;
-    field @NonNull public static final android.os.UserHandle CURRENT;
     field public static final int MIN_SECONDARY_USER_ID = 10; // 0xa
-    field @NonNull public static final android.os.UserHandle SYSTEM;
     field public static final int USER_ALL = -1; // 0xffffffff
     field public static final int USER_NULL = -10000; // 0xffffd8f0
     field public static final int USER_SYSTEM = 0; // 0x0
@@ -3033,7 +1213,6 @@
   public class UserManager {
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean hasBaseUserRestriction(@NonNull String, @NonNull android.os.UserHandle);
     method public static boolean isSplitSystemUser();
-    field public static final String ACTION_USER_RESTRICTIONS_CHANGED = "android.os.action.USER_RESTRICTIONS_CHANGED";
   }
 
   public final class VibrationAttributes implements android.os.Parcelable {
@@ -3090,17 +1269,6 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.os.VibrationEffect.Waveform> CREATOR;
   }
 
-  public abstract class Vibrator {
-    method @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE) public void addVibratorStateListener(@NonNull android.os.Vibrator.OnVibratorStateChangedListener);
-    method @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE) public void addVibratorStateListener(@NonNull java.util.concurrent.Executor, @NonNull android.os.Vibrator.OnVibratorStateChangedListener);
-    method @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE) public boolean isVibrating();
-    method @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE) public void removeVibratorStateListener(@NonNull android.os.Vibrator.OnVibratorStateChangedListener);
-  }
-
-  public static interface Vibrator.OnVibratorStateChangedListener {
-    method public void onVibratorStateChanged(boolean);
-  }
-
   public class VintfObject {
     method public static String[] getHalNamesAndVersions();
     method public static String getSepolicyVersion();
@@ -3120,16 +1288,10 @@
   }
 
   public class WorkSource implements android.os.Parcelable {
-    ctor public WorkSource(int);
     method public boolean add(int);
     method public boolean add(int, String);
     method @Deprecated public android.os.WorkSource addReturningNewbs(android.os.WorkSource);
-    method @Nullable public String getPackageName(int);
-    method public int getUid(int);
-    method public boolean isEmpty();
     method @Deprecated public android.os.WorkSource[] setReturningDiffs(android.os.WorkSource);
-    method public int size();
-    method @NonNull public android.os.WorkSource withoutNames();
   }
 
 }
@@ -3189,36 +1351,6 @@
 
 }
 
-package android.os.image {
-
-  public class DynamicSystemClient {
-    ctor public DynamicSystemClient(@NonNull android.content.Context);
-    method @RequiresPermission(android.Manifest.permission.INSTALL_DYNAMIC_SYSTEM) public void bind();
-    method public void setOnStatusChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.os.image.DynamicSystemClient.OnStatusChangedListener);
-    method public void setOnStatusChangedListener(@NonNull android.os.image.DynamicSystemClient.OnStatusChangedListener);
-    method @RequiresPermission(android.Manifest.permission.INSTALL_DYNAMIC_SYSTEM) public void start(@NonNull android.net.Uri, long);
-    method @RequiresPermission(android.Manifest.permission.INSTALL_DYNAMIC_SYSTEM) public void start(@NonNull android.net.Uri, long, long);
-    method @RequiresPermission(android.Manifest.permission.INSTALL_DYNAMIC_SYSTEM) public void unbind();
-    field public static final int CAUSE_ERROR_EXCEPTION = 6; // 0x6
-    field public static final int CAUSE_ERROR_INVALID_URL = 4; // 0x4
-    field public static final int CAUSE_ERROR_IO = 3; // 0x3
-    field public static final int CAUSE_ERROR_IPC = 5; // 0x5
-    field public static final int CAUSE_INSTALL_CANCELLED = 2; // 0x2
-    field public static final int CAUSE_INSTALL_COMPLETED = 1; // 0x1
-    field public static final int CAUSE_NOT_SPECIFIED = 0; // 0x0
-    field public static final int STATUS_IN_PROGRESS = 2; // 0x2
-    field public static final int STATUS_IN_USE = 4; // 0x4
-    field public static final int STATUS_NOT_STARTED = 1; // 0x1
-    field public static final int STATUS_READY = 3; // 0x3
-    field public static final int STATUS_UNKNOWN = 0; // 0x0
-  }
-
-  public static interface DynamicSystemClient.OnStatusChangedListener {
-    method public void onStatusChanged(int, int, long, @Nullable Throwable);
-  }
-
-}
-
 package android.os.storage {
 
   public final class CrateInfo implements android.os.Parcelable {
@@ -3232,10 +1364,6 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.os.storage.CrateInfo> CREATOR;
   }
 
-  public class StorageManager {
-    method public static boolean hasIsolatedStorage();
-  }
-
   public final class StorageVolume implements android.os.Parcelable {
     method public String getPath();
   }
@@ -3252,17 +1380,9 @@
 package android.permission {
 
   public final class PermissionControllerManager {
-    method @RequiresPermission(anyOf={android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.RESTORE_RUNTIME_PERMISSIONS}) public void applyStagedRuntimePermissionBackup(@NonNull String, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
     method @RequiresPermission(android.Manifest.permission.GET_RUNTIME_PERMISSIONS) public void countPermissionApps(@NonNull java.util.List<java.lang.String>, int, @NonNull android.permission.PermissionControllerManager.OnCountPermissionAppsResultCallback, @Nullable android.os.Handler);
     method @RequiresPermission(android.Manifest.permission.GET_RUNTIME_PERMISSIONS) public void getAppPermissions(@NonNull String, @NonNull android.permission.PermissionControllerManager.OnGetAppPermissionResultCallback, @Nullable android.os.Handler);
-    method @RequiresPermission(android.Manifest.permission.GET_RUNTIME_PERMISSIONS) public void getRuntimePermissionBackup(@NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<byte[]>);
     method @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) public void revokeRuntimePermission(@NonNull String, @NonNull String);
-    method @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) public void revokeRuntimePermissions(@NonNull java.util.Map<java.lang.String,java.util.List<java.lang.String>>, boolean, int, @NonNull java.util.concurrent.Executor, @NonNull android.permission.PermissionControllerManager.OnRevokeRuntimePermissionsCallback);
-    method @RequiresPermission(anyOf={android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.RESTORE_RUNTIME_PERMISSIONS}) public void stageAndApplyRuntimePermissionsBackup(@NonNull byte[], @NonNull android.os.UserHandle);
-    field public static final int COUNT_ONLY_WHEN_GRANTED = 1; // 0x1
-    field public static final int COUNT_WHEN_SYSTEM = 2; // 0x2
-    field public static final int REASON_INSTALLER_POLICY_VIOLATION = 2; // 0x2
-    field public static final int REASON_MALWARE = 1; // 0x1
   }
 
   public static interface PermissionControllerManager.OnCountPermissionAppsResultCallback {
@@ -3273,33 +1393,6 @@
     method public void onGetAppPermissions(@NonNull java.util.List<android.permission.RuntimePermissionPresentationInfo>);
   }
 
-  public abstract static class PermissionControllerManager.OnRevokeRuntimePermissionsCallback {
-    ctor public PermissionControllerManager.OnRevokeRuntimePermissionsCallback();
-    method public abstract void onRevokeRuntimePermissions(@NonNull java.util.Map<java.lang.String,java.util.List<java.lang.String>>);
-  }
-
-  public final class PermissionManager {
-    method @IntRange(from=0) @RequiresPermission(anyOf={android.Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY, android.Manifest.permission.UPGRADE_RUNTIME_PERMISSIONS}) public int getRuntimePermissionsVersion();
-    method @NonNull public java.util.List<android.permission.PermissionManager.SplitPermissionInfo> getSplitPermissions();
-    method @RequiresPermission(anyOf={android.Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY, android.Manifest.permission.UPGRADE_RUNTIME_PERMISSIONS}) public void setRuntimePermissionsVersion(@IntRange(from=0) int);
-  }
-
-  public static final class PermissionManager.SplitPermissionInfo {
-    method @NonNull public java.util.List<java.lang.String> getNewPermissions();
-    method @NonNull public String getSplitPermission();
-    method public int getTargetSdk();
-  }
-
-  public final class RuntimePermissionPresentationInfo implements android.os.Parcelable {
-    ctor public RuntimePermissionPresentationInfo(@NonNull CharSequence, boolean, boolean);
-    method public int describeContents();
-    method @NonNull public CharSequence getLabel();
-    method public boolean isGranted();
-    method public boolean isStandard();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.permission.RuntimePermissionPresentationInfo> CREATOR;
-  }
-
 }
 
 package android.print {
@@ -3347,75 +1440,18 @@
   }
 
   public final class DeviceConfig {
-    method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static void addOnPropertiesChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
-    method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static boolean getBoolean(@NonNull String, @NonNull String, boolean);
-    method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static float getFloat(@NonNull String, @NonNull String, float);
-    method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static int getInt(@NonNull String, @NonNull String, int);
-    method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static long getLong(@NonNull String, @NonNull String, long);
-    method @NonNull @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static android.provider.DeviceConfig.Properties getProperties(@NonNull String, @NonNull java.lang.String...);
-    method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static String getProperty(@NonNull String, @NonNull String);
-    method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static String getString(@NonNull String, @NonNull String, @Nullable String);
-    method public static void removeOnPropertiesChangedListener(@NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
-    method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static void resetToDefaults(int, @Nullable String);
-    method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setProperties(@NonNull android.provider.DeviceConfig.Properties) throws android.provider.DeviceConfig.BadConfigException;
-    method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setProperty(@NonNull String, @NonNull String, @Nullable String, boolean);
     field public static final String NAMESPACE_ALARM_MANAGER = "alarm_manager";
     field public static final String NAMESPACE_ANDROID = "android";
-    field public static final String NAMESPACE_AUTOFILL = "autofill";
-    field public static final String NAMESPACE_BIOMETRICS = "biometrics";
-    field public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture";
     field public static final String NAMESPACE_DEVICE_IDLE = "device_idle";
     field public static final String NAMESPACE_JOB_SCHEDULER = "jobscheduler";
-    field public static final String NAMESPACE_PERMISSIONS = "permissions";
-    field public static final String NAMESPACE_PRIVACY = "privacy";
-    field public static final String NAMESPACE_ROLLBACK = "rollback";
-    field public static final String NAMESPACE_ROLLBACK_BOOT = "rollback_boot";
-  }
-
-  public static class DeviceConfig.BadConfigException extends java.lang.Exception {
-    ctor public DeviceConfig.BadConfigException();
-  }
-
-  public static interface DeviceConfig.OnPropertiesChangedListener {
-    method public void onPropertiesChanged(@NonNull android.provider.DeviceConfig.Properties);
-  }
-
-  public static class DeviceConfig.Properties {
-    method public boolean getBoolean(@NonNull String, boolean);
-    method public float getFloat(@NonNull String, float);
-    method public int getInt(@NonNull String, int);
-    method @NonNull public java.util.Set<java.lang.String> getKeyset();
-    method public long getLong(@NonNull String, long);
-    method @NonNull public String getNamespace();
-    method @Nullable public String getString(@NonNull String, @Nullable String);
-  }
-
-  public static final class DeviceConfig.Properties.Builder {
-    ctor public DeviceConfig.Properties.Builder(@NonNull String);
-    method @NonNull public android.provider.DeviceConfig.Properties build();
-    method @NonNull public android.provider.DeviceConfig.Properties.Builder setBoolean(@NonNull String, boolean);
-    method @NonNull public android.provider.DeviceConfig.Properties.Builder setFloat(@NonNull String, float);
-    method @NonNull public android.provider.DeviceConfig.Properties.Builder setInt(@NonNull String, int);
-    method @NonNull public android.provider.DeviceConfig.Properties.Builder setLong(@NonNull String, long);
-    method @NonNull public android.provider.DeviceConfig.Properties.Builder setString(@NonNull String, @Nullable String);
-  }
-
-  public final class DocumentsContract {
-    method public static boolean isManageMode(@NonNull android.net.Uri);
-    method @NonNull public static android.net.Uri setManageMode(@NonNull android.net.Uri);
   }
 
   public final class Settings {
-    field public static final String ACTION_ENTERPRISE_PRIVACY_SETTINGS = "android.settings.ENTERPRISE_PRIVACY_SETTINGS";
-    field public static final String ACTION_MANAGE_APP_OVERLAY_PERMISSION = "android.settings.MANAGE_APP_OVERLAY_PERMISSION";
-    field public static final String ACTION_REQUEST_ENABLE_CONTENT_CAPTURE = "android.settings.REQUEST_ENABLE_CONTENT_CAPTURE";
-    field public static final String ACTION_TETHER_PROVISIONING_UI = "android.settings.TETHER_PROVISIONING_UI";
     field public static final int RESET_MODE_PACKAGE_DEFAULTS = 1; // 0x1
   }
 
   public static final class Settings.Global extends android.provider.Settings.NameValueTable {
     field public static final String APP_OPS_CONSTANTS = "app_ops_constants";
-    field public static final String AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "autofill_compat_mode_allowed_packages";
     field public static final String AUTOMATIC_POWER_SAVE_MODE = "automatic_power_save_mode";
     field public static final String BATTERY_SAVER_CONSTANTS = "battery_saver_constants";
     field public static final String DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD = "dynamic_power_savings_disable_threshold";
@@ -3430,12 +1466,10 @@
     field public static final String NOTIFICATION_BUBBLES = "notification_bubbles";
     field public static final String OVERLAY_DISPLAY_DEVICES = "overlay_display_devices";
     field public static final String SHOW_FIRST_CRASH_DIALOG = "show_first_crash_dialog";
-    field public static final String TETHER_OFFLOAD_DISABLED = "tether_offload_disabled";
     field public static final String USE_OPEN_WIFI_PACKAGE = "use_open_wifi_package";
   }
 
   public static final class Settings.Secure extends android.provider.Settings.NameValueTable {
-    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public static void resetToDefaults(@NonNull android.content.ContentResolver, @Nullable String);
     field public static final String ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED = "accessibility_display_magnification_enabled";
     field public static final String ACCESSIBILITY_MAGNIFICATION_CAPABILITY = "accessibility_magnification_capability";
     field public static final String ACCESSIBILITY_MAGNIFICATION_MODE = "accessibility_magnification_mode";
@@ -3444,23 +1478,12 @@
     field public static final int ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW = 2; // 0x2
     field public static final String ACCESSIBILITY_SHORTCUT_TARGET_SERVICE = "accessibility_shortcut_target_service";
     field public static final String ANR_SHOW_BACKGROUND = "anr_show_background";
-    field public static final String AUTOFILL_FEATURE_FIELD_CLASSIFICATION = "autofill_field_classification";
     field public static final String AUTOFILL_SERVICE = "autofill_service";
-    field public static final String AUTOFILL_USER_DATA_MAX_CATEGORY_COUNT = "autofill_user_data_max_category_count";
-    field public static final String AUTOFILL_USER_DATA_MAX_FIELD_CLASSIFICATION_IDS_SIZE = "autofill_user_data_max_field_classification_size";
-    field public static final String AUTOFILL_USER_DATA_MAX_USER_DATA_SIZE = "autofill_user_data_max_user_data_size";
-    field public static final String AUTOFILL_USER_DATA_MAX_VALUE_LENGTH = "autofill_user_data_max_value_length";
-    field public static final String AUTOFILL_USER_DATA_MIN_VALUE_LENGTH = "autofill_user_data_min_value_length";
     field public static final String CONTENT_CAPTURE_ENABLED = "content_capture_enabled";
     field public static final String DISABLED_PRINT_SERVICES = "disabled_print_services";
-    field public static final String DOZE_ALWAYS_ON = "doze_always_on";
     field @Deprecated public static final String ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES = "enabled_notification_policy_access_packages";
     field public static final String ENABLED_VR_LISTENERS = "enabled_vr_listeners";
     field public static final String IMMERSIVE_MODE_CONFIRMATIONS = "immersive_mode_confirmations";
-    field public static final String LOCATION_ACCESS_CHECK_DELAY_MILLIS = "location_access_check_delay_millis";
-    field public static final String LOCATION_ACCESS_CHECK_INTERVAL_MILLIS = "location_access_check_interval_millis";
-    field public static final String LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS = "lock_screen_allow_private_notifications";
-    field public static final String LOCK_SCREEN_SHOW_NOTIFICATIONS = "lock_screen_show_notifications";
     field public static final String NFC_PAYMENT_DEFAULT_COMPONENT = "nfc_payment_default_component";
     field public static final String NOTIFICATION_BADGING = "notification_badging";
     field public static final String POWER_MENU_LOCKED_SHOW_CONTENT = "power_menu_locked_show_content";
@@ -3469,45 +1492,9 @@
     field public static final String SHOW_FIRST_CRASH_DIALOG_DEV_OPTION = "show_first_crash_dialog_dev_option";
     field public static final String SHOW_IME_WITH_HARD_KEYBOARD = "show_ime_with_hard_keyboard";
     field @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public static final String SYNC_PARENT_SOUNDS = "sync_parent_sounds";
-    field public static final String USER_SETUP_COMPLETE = "user_setup_complete";
     field public static final String VOICE_INTERACTION_SERVICE = "voice_interaction_service";
   }
 
-  public static final class Telephony.CellBroadcasts implements android.provider.BaseColumns {
-    field public static final String CID = "cid";
-    field public static final String CMAS_CATEGORY = "cmas_category";
-    field public static final String CMAS_CERTAINTY = "cmas_certainty";
-    field public static final String CMAS_MESSAGE_CLASS = "cmas_message_class";
-    field public static final String CMAS_RESPONSE_TYPE = "cmas_response_type";
-    field public static final String CMAS_SEVERITY = "cmas_severity";
-    field public static final String CMAS_URGENCY = "cmas_urgency";
-    field @NonNull public static final android.net.Uri CONTENT_URI;
-    field public static final String DATA_CODING_SCHEME = "dcs";
-    field public static final String DEFAULT_SORT_ORDER = "date DESC";
-    field public static final String DELIVERY_TIME = "date";
-    field public static final String ETWS_IS_PRIMARY = "etws_is_primary";
-    field public static final String ETWS_WARNING_TYPE = "etws_warning_type";
-    field public static final String GEOGRAPHICAL_SCOPE = "geo_scope";
-    field public static final String GEOMETRIES = "geometries";
-    field public static final String LAC = "lac";
-    field public static final String LANGUAGE_CODE = "language";
-    field public static final String LOCATION_CHECK_TIME = "location_check_time";
-    field public static final String MAXIMUM_WAIT_TIME = "maximum_wait_time";
-    field public static final String MESSAGE_BODY = "body";
-    field public static final String MESSAGE_BROADCASTED = "message_broadcasted";
-    field public static final String MESSAGE_DISPLAYED = "message_displayed";
-    field public static final String MESSAGE_FORMAT = "format";
-    field @NonNull @RequiresPermission(android.Manifest.permission.READ_CELL_BROADCASTS) public static final android.net.Uri MESSAGE_HISTORY_URI;
-    field public static final String MESSAGE_PRIORITY = "priority";
-    field public static final String MESSAGE_READ = "read";
-    field public static final String PLMN = "plmn";
-    field public static final String RECEIVED_TIME = "received_time";
-    field public static final String SERIAL_NUMBER = "serial_number";
-    field public static final String SERVICE_CATEGORY = "service_category";
-    field public static final String SLOT_INDEX = "slot_index";
-    field public static final String SUBSCRIPTION_ID = "sub_id";
-  }
-
   public static final class Telephony.Sms.Intents {
     field public static final String SMS_CARRIER_PROVISION_ACTION = "android.provider.Telephony.SMS_CARRIER_PROVISION";
   }
@@ -3529,19 +1516,6 @@
 
 package android.security.keystore {
 
-  public abstract class AttestationUtils {
-    method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static java.security.cert.X509Certificate[] attestDeviceIds(android.content.Context, @NonNull int[], @NonNull byte[]) throws android.security.keystore.DeviceIdAttestationException;
-    field public static final int ID_TYPE_IMEI = 2; // 0x2
-    field public static final int ID_TYPE_MEID = 3; // 0x3
-    field public static final int ID_TYPE_SERIAL = 1; // 0x1
-    field public static final int USE_INDIVIDUAL_ATTESTATION = 4; // 0x4
-  }
-
-  public class DeviceIdAttestationException extends java.lang.Exception {
-    ctor public DeviceIdAttestationException(@Nullable String);
-    ctor public DeviceIdAttestationException(@Nullable String, @Nullable Throwable);
-  }
-
   public static final class KeyGenParameterSpec.Builder {
     method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setUniqueIdIncluded(boolean);
   }
@@ -3556,37 +1530,8 @@
 
 }
 
-package android.service.appprediction {
-
-  public abstract class AppPredictionService extends android.app.Service {
-    ctor public AppPredictionService();
-    method @MainThread public abstract void onAppTargetEvent(@NonNull android.app.prediction.AppPredictionSessionId, @NonNull android.app.prediction.AppTargetEvent);
-    method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
-    method public void onCreatePredictionSession(@NonNull android.app.prediction.AppPredictionContext, @NonNull android.app.prediction.AppPredictionSessionId);
-    method @MainThread public void onDestroyPredictionSession(@NonNull android.app.prediction.AppPredictionSessionId);
-    method @MainThread public abstract void onLaunchLocationShown(@NonNull android.app.prediction.AppPredictionSessionId, @NonNull String, @NonNull java.util.List<android.app.prediction.AppTargetId>);
-    method @MainThread public abstract void onRequestPredictionUpdate(@NonNull android.app.prediction.AppPredictionSessionId);
-    method @MainThread public abstract void onSortAppTargets(@NonNull android.app.prediction.AppPredictionSessionId, @NonNull java.util.List<android.app.prediction.AppTarget>, @NonNull android.os.CancellationSignal, @NonNull java.util.function.Consumer<java.util.List<android.app.prediction.AppTarget>>);
-    method @MainThread public void onStartPredictionUpdates();
-    method @MainThread public void onStopPredictionUpdates();
-    method public final void updatePredictions(@NonNull android.app.prediction.AppPredictionSessionId, @NonNull java.util.List<android.app.prediction.AppTarget>);
-  }
-
-}
-
 package android.service.autofill {
 
-  public abstract class AutofillFieldClassificationService extends android.app.Service {
-    ctor public AutofillFieldClassificationService();
-    method public android.os.IBinder onBind(android.content.Intent);
-    field public static final String REQUIRED_ALGORITHM_CREDIT_CARD = "CREDIT_CARD";
-    field public static final String REQUIRED_ALGORITHM_EDIT_DISTANCE = "EDIT_DISTANCE";
-    field public static final String REQUIRED_ALGORITHM_EXACT_MATCH = "EXACT_MATCH";
-    field public static final String SERVICE_INTERFACE = "android.service.autofill.AutofillFieldClassificationService";
-    field public static final String SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS = "android.autofill.field_classification.available_algorithms";
-    field public static final String SERVICE_META_DATA_KEY_DEFAULT_ALGORITHM = "android.autofill.field_classification.default_algorithm";
-  }
-
   public final class CharSequenceTransformation extends android.service.autofill.InternalTransformation implements android.os.Parcelable android.service.autofill.Transformation {
     method public void apply(@NonNull android.service.autofill.ValueFinder, @NonNull android.widget.RemoteViews, int) throws java.lang.Exception;
   }
@@ -3609,11 +1554,6 @@
     method @Nullable public android.util.SparseArray<android.service.autofill.InternalOnClickAction> getActions();
   }
 
-  public static final class Dataset.Builder {
-    ctor public Dataset.Builder(@NonNull android.service.autofill.InlinePresentation);
-    method @NonNull public android.service.autofill.Dataset.Builder setFieldInlinePresentation(@NonNull android.view.autofill.AutofillId, @Nullable android.view.autofill.AutofillValue, @Nullable java.util.regex.Pattern, @NonNull android.service.autofill.InlinePresentation);
-  }
-
   public final class DateTransformation extends android.service.autofill.InternalTransformation implements android.os.Parcelable android.service.autofill.Transformation {
     method public void apply(@NonNull android.service.autofill.ValueFinder, @NonNull android.widget.RemoteViews, int) throws java.lang.Exception;
   }
@@ -3630,15 +1570,6 @@
     method public void apply(@NonNull android.service.autofill.ValueFinder, @NonNull android.widget.RemoteViews, int) throws java.lang.Exception;
   }
 
-  public abstract class InlineSuggestionRenderService extends android.app.Service {
-    ctor public InlineSuggestionRenderService();
-    method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
-    method @NonNull public android.os.Bundle onGetInlineSuggestionsRendererInfo();
-    method @Nullable public android.view.View onRenderSuggestion(@NonNull android.service.autofill.InlinePresentation, int, int);
-    method public final void startIntentSender(@NonNull android.content.IntentSender);
-    field public static final String SERVICE_INTERFACE = "android.service.autofill.InlineSuggestionRenderService";
-  }
-
   public abstract class InternalOnClickAction implements android.service.autofill.OnClickAction android.os.Parcelable {
     ctor public InternalOnClickAction();
     method public abstract void onClick(@NonNull android.view.ViewGroup);
@@ -3688,26 +1619,6 @@
 
 package android.service.autofill.augmented {
 
-  public abstract class AugmentedAutofillService extends android.app.Service {
-    ctor public AugmentedAutofillService();
-    method protected final void dump(java.io.FileDescriptor, java.io.PrintWriter, String[]);
-    method protected void dump(@NonNull java.io.PrintWriter, @NonNull String[]);
-    method @Nullable public final android.service.autofill.FillEventHistory getFillEventHistory();
-    method public void onConnected();
-    method public void onDisconnected();
-    method public void onFillRequest(@NonNull android.service.autofill.augmented.FillRequest, @NonNull android.os.CancellationSignal, @NonNull android.service.autofill.augmented.FillController, @NonNull android.service.autofill.augmented.FillCallback);
-    method public final boolean requestAutofill(@NonNull android.content.ComponentName, @NonNull android.view.autofill.AutofillId);
-    field public static final String SERVICE_INTERFACE = "android.service.autofill.augmented.AugmentedAutofillService";
-  }
-
-  public final class FillCallback {
-    method public void onSuccess(@Nullable android.service.autofill.augmented.FillResponse);
-  }
-
-  public final class FillController {
-    method public void autofill(@NonNull java.util.List<android.util.Pair<android.view.autofill.AutofillId,android.view.autofill.AutofillValue>>);
-  }
-
   public final class FillRequest {
     method @NonNull public android.content.ComponentName getActivityComponent();
     method @NonNull public android.view.autofill.AutofillId getFocusedId();
@@ -3717,181 +1628,14 @@
     method public int getTaskId();
   }
 
-  public final class FillResponse {
-  }
-
-  public static final class FillResponse.Builder {
-    ctor public FillResponse.Builder();
-    method @NonNull public android.service.autofill.augmented.FillResponse build();
-    method @NonNull public android.service.autofill.augmented.FillResponse.Builder setClientState(@NonNull android.os.Bundle);
-    method @NonNull public android.service.autofill.augmented.FillResponse.Builder setFillWindow(@NonNull android.service.autofill.augmented.FillWindow);
-    method @NonNull public android.service.autofill.augmented.FillResponse.Builder setInlineSuggestions(@NonNull java.util.List<android.service.autofill.Dataset>);
-  }
-
-  public final class FillWindow implements java.lang.AutoCloseable {
-    ctor public FillWindow();
-    method public void destroy();
-    method public boolean update(@NonNull android.service.autofill.augmented.PresentationParams.Area, @NonNull android.view.View, long);
-  }
-
-  public abstract class PresentationParams {
-    method @Nullable public android.service.autofill.augmented.PresentationParams.Area getSuggestionArea();
-  }
-
-  public abstract static class PresentationParams.Area {
-    method @NonNull public android.graphics.Rect getBounds();
-  }
-
-}
-
-package android.service.contentcapture {
-
-  public final class ActivityEvent implements android.os.Parcelable {
-    method public int describeContents();
-    method @NonNull public android.content.ComponentName getComponentName();
-    method public int getEventType();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.service.contentcapture.ActivityEvent> CREATOR;
-    field public static final int TYPE_ACTIVITY_DESTROYED = 24; // 0x18
-    field public static final int TYPE_ACTIVITY_PAUSED = 2; // 0x2
-    field public static final int TYPE_ACTIVITY_RESUMED = 1; // 0x1
-    field public static final int TYPE_ACTIVITY_STOPPED = 23; // 0x17
-  }
-
-  public abstract class ContentCaptureService extends android.app.Service {
-    ctor public ContentCaptureService();
-    method public final void disableSelf();
-    method public void onActivityEvent(@NonNull android.service.contentcapture.ActivityEvent);
-    method public void onActivitySnapshot(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.service.contentcapture.SnapshotData);
-    method public void onConnected();
-    method public void onContentCaptureEvent(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.view.contentcapture.ContentCaptureEvent);
-    method public void onCreateContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureContext, @NonNull android.view.contentcapture.ContentCaptureSessionId);
-    method public void onDataRemovalRequest(@NonNull android.view.contentcapture.DataRemovalRequest);
-    method public void onDataShareRequest(@NonNull android.view.contentcapture.DataShareRequest, @NonNull android.service.contentcapture.DataShareCallback);
-    method public void onDestroyContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureSessionId);
-    method public void onDisconnected();
-    method public final void setContentCaptureConditions(@NonNull String, @Nullable java.util.Set<android.view.contentcapture.ContentCaptureCondition>);
-    method public final void setContentCaptureWhitelist(@Nullable java.util.Set<java.lang.String>, @Nullable java.util.Set<android.content.ComponentName>);
-    field public static final String SERVICE_INTERFACE = "android.service.contentcapture.ContentCaptureService";
-    field public static final String SERVICE_META_DATA = "android.content_capture";
-  }
-
-  public interface DataShareCallback {
-    method public void onAccept(@NonNull java.util.concurrent.Executor, @NonNull android.service.contentcapture.DataShareReadAdapter);
-    method public void onReject();
-  }
-
-  public interface DataShareReadAdapter {
-    method public void onError(int);
-    method public void onStart(@NonNull android.os.ParcelFileDescriptor);
-  }
-
-  public final class SnapshotData implements android.os.Parcelable {
-    method public int describeContents();
-    method @Nullable public android.app.assist.AssistContent getAssistContent();
-    method @NonNull public android.os.Bundle getAssistData();
-    method @NonNull public android.app.assist.AssistStructure getAssistStructure();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.service.contentcapture.SnapshotData> CREATOR;
-  }
-
 }
 
 package android.service.notification {
 
-  public final class Adjustment implements android.os.Parcelable {
-    ctor public Adjustment(String, String, android.os.Bundle, CharSequence, int);
-    ctor public Adjustment(@NonNull String, @NonNull String, @NonNull android.os.Bundle, @NonNull CharSequence, @NonNull android.os.UserHandle);
-    method public int describeContents();
-    method @NonNull public CharSequence getExplanation();
-    method @NonNull public String getKey();
-    method @NonNull public String getPackage();
-    method @NonNull public android.os.Bundle getSignals();
-    method public int getUser();
-    method @NonNull public android.os.UserHandle getUserHandle();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.service.notification.Adjustment> CREATOR;
-    field public static final String KEY_CONTEXTUAL_ACTIONS = "key_contextual_actions";
-    field public static final String KEY_IMPORTANCE = "key_importance";
-    field public static final String KEY_RANKING_SCORE = "key_ranking_score";
-    field public static final String KEY_SNOOZE_CRITERIA = "key_snooze_criteria";
-    field public static final String KEY_TEXT_REPLIES = "key_text_replies";
-    field public static final String KEY_USER_SENTIMENT = "key_user_sentiment";
-  }
-
   @Deprecated public abstract class ConditionProviderService extends android.app.Service {
     method @Deprecated public boolean isBound();
   }
 
-  public abstract class NotificationAssistantService extends android.service.notification.NotificationListenerService {
-    ctor public NotificationAssistantService();
-    method public final void adjustNotification(@NonNull android.service.notification.Adjustment);
-    method public final void adjustNotifications(@NonNull java.util.List<android.service.notification.Adjustment>);
-    method public void onActionInvoked(@NonNull String, @NonNull android.app.Notification.Action, int);
-    method public void onAllowedAdjustmentsChanged();
-    method @NonNull public final android.os.IBinder onBind(@Nullable android.content.Intent);
-    method public void onNotificationDirectReplied(@NonNull String);
-    method @Nullable public abstract android.service.notification.Adjustment onNotificationEnqueued(@NonNull android.service.notification.StatusBarNotification);
-    method @Nullable public android.service.notification.Adjustment onNotificationEnqueued(@NonNull android.service.notification.StatusBarNotification, @NonNull android.app.NotificationChannel);
-    method public void onNotificationExpansionChanged(@NonNull String, boolean, boolean);
-    method public abstract void onNotificationSnoozedUntilContext(@NonNull android.service.notification.StatusBarNotification, @NonNull String);
-    method public void onNotificationVisibilityChanged(@NonNull String, boolean);
-    method public void onNotificationsSeen(@NonNull java.util.List<java.lang.String>);
-    method public void onPanelHidden();
-    method public void onPanelRevealed(int);
-    method public void onSuggestedReplySent(@NonNull String, @NonNull CharSequence, int);
-    method public final void unsnoozeNotification(@NonNull String);
-    field public static final String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
-    field public static final int SOURCE_FROM_APP = 0; // 0x0
-    field public static final int SOURCE_FROM_ASSISTANT = 1; // 0x1
-  }
-
-  public abstract class NotificationListenerService extends android.app.Service {
-    method public void onNotificationRemoved(@NonNull android.service.notification.StatusBarNotification, @NonNull android.service.notification.NotificationListenerService.RankingMap, @NonNull android.service.notification.NotificationStats, int);
-  }
-
-  public final class NotificationStats implements android.os.Parcelable {
-    ctor public NotificationStats();
-    method public int describeContents();
-    method public int getDismissalSentiment();
-    method public int getDismissalSurface();
-    method public boolean hasDirectReplied();
-    method public boolean hasExpanded();
-    method public boolean hasInteracted();
-    method public boolean hasSeen();
-    method public boolean hasSnoozed();
-    method public boolean hasViewedSettings();
-    method public void setDirectReplied();
-    method public void setDismissalSentiment(int);
-    method public void setDismissalSurface(int);
-    method public void setExpanded();
-    method public void setSeen();
-    method public void setSnoozed();
-    method public void setViewedSettings();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.service.notification.NotificationStats> CREATOR;
-    field public static final int DISMISSAL_AOD = 2; // 0x2
-    field public static final int DISMISSAL_NOT_DISMISSED = -1; // 0xffffffff
-    field public static final int DISMISSAL_OTHER = 0; // 0x0
-    field public static final int DISMISSAL_PEEK = 1; // 0x1
-    field public static final int DISMISSAL_SHADE = 3; // 0x3
-    field public static final int DISMISS_SENTIMENT_NEGATIVE = 0; // 0x0
-    field public static final int DISMISS_SENTIMENT_NEUTRAL = 1; // 0x1
-    field public static final int DISMISS_SENTIMENT_POSITIVE = 2; // 0x2
-    field public static final int DISMISS_SENTIMENT_UNKNOWN = -1000; // 0xfffffc18
-  }
-
-  public final class SnoozeCriterion implements android.os.Parcelable {
-    ctor public SnoozeCriterion(String, CharSequence, CharSequence);
-    ctor protected SnoozeCriterion(android.os.Parcel);
-    method public int describeContents();
-    method public CharSequence getConfirmation();
-    method public CharSequence getExplanation();
-    method public String getId();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.service.notification.SnoozeCriterion> CREATOR;
-  }
-
 }
 
 package android.service.quickaccesswallet {
@@ -3932,67 +1676,16 @@
 
 }
 
-package android.service.textclassifier {
-
-  public abstract class TextClassifierService extends android.app.Service {
-    ctor public TextClassifierService();
-    method @NonNull public static android.view.textclassifier.TextClassifier getDefaultTextClassifierImplementation(@NonNull android.content.Context);
-    method @Deprecated public final android.view.textclassifier.TextClassifier getLocalTextClassifier();
-    method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
-    method @MainThread public abstract void onClassifyText(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.TextClassification.Request, @NonNull android.os.CancellationSignal, @NonNull android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.TextClassification>);
-    method public void onConnected();
-    method @MainThread public void onCreateTextClassificationSession(@NonNull android.view.textclassifier.TextClassificationContext, @NonNull android.view.textclassifier.TextClassificationSessionId);
-    method @MainThread public void onDestroyTextClassificationSession(@NonNull android.view.textclassifier.TextClassificationSessionId);
-    method @MainThread public void onDetectLanguage(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.TextLanguage.Request, @NonNull android.os.CancellationSignal, @NonNull android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.TextLanguage>);
-    method public void onDisconnected();
-    method @MainThread public abstract void onGenerateLinks(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.TextLinks.Request, @NonNull android.os.CancellationSignal, @NonNull android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.TextLinks>);
-    method @Deprecated @MainThread public void onSelectionEvent(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.SelectionEvent);
-    method @MainThread public void onSuggestConversationActions(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.ConversationActions.Request, @NonNull android.os.CancellationSignal, @NonNull android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.ConversationActions>);
-    method @MainThread public abstract void onSuggestSelection(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.TextSelection.Request, @NonNull android.os.CancellationSignal, @NonNull android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.TextSelection>);
-    method @MainThread public void onTextClassifierEvent(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.TextClassifierEvent);
-    field public static final String SERVICE_INTERFACE = "android.service.textclassifier.TextClassifierService";
-  }
-
-  public static interface TextClassifierService.Callback<T> {
-    method public void onFailure(@NonNull CharSequence);
-    method public void onSuccess(T);
-  }
-
-}
-
 package android.service.watchdog {
 
   public abstract class ExplicitHealthCheckService extends android.app.Service {
-    ctor public ExplicitHealthCheckService();
-    method public final void notifyHealthCheckPassed(@NonNull String);
-    method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
-    method public abstract void onCancelHealthCheck(@NonNull String);
-    method @NonNull public abstract java.util.List<java.lang.String> onGetRequestedPackages();
-    method @NonNull public abstract java.util.List<android.service.watchdog.ExplicitHealthCheckService.PackageConfig> onGetSupportedPackages();
-    method public abstract void onRequestHealthCheck(@NonNull String);
     method public void setCallback(@Nullable android.os.RemoteCallback);
-    field public static final String BIND_PERMISSION = "android.permission.BIND_EXPLICIT_HEALTH_CHECK_SERVICE";
-    field public static final String SERVICE_INTERFACE = "android.service.watchdog.ExplicitHealthCheckService";
-  }
-
-  public static final class ExplicitHealthCheckService.PackageConfig implements android.os.Parcelable {
-    ctor public ExplicitHealthCheckService.PackageConfig(@NonNull String, long);
-    method public int describeContents();
-    method public long getHealthCheckTimeoutMillis();
-    method @NonNull public String getPackageName();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.service.watchdog.ExplicitHealthCheckService.PackageConfig> CREATOR;
   }
 
 }
 
 package android.telecom {
 
-  public final class Call {
-    method public void enterBackgroundAudioProcessing();
-    method public void exitBackgroundAudioProcessing(boolean);
-  }
-
   public static class Call.Details {
     method public String getTelecomCallId();
   }
@@ -4001,42 +1694,6 @@
     ctor public CallAudioState(boolean, int, int, @Nullable android.bluetooth.BluetoothDevice, @NonNull java.util.Collection<android.bluetooth.BluetoothDevice>);
   }
 
-  public static class CallScreeningService.CallResponse.Builder {
-    method @NonNull @RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_OUTPUT) public android.telecom.CallScreeningService.CallResponse.Builder setShouldScreenCallViaAudioProcessing(boolean);
-  }
-
-  public abstract class Conference extends android.telecom.Conferenceable {
-    method public android.telecom.Connection getPrimaryConnection();
-    method @NonNull public final String getTelecomCallId();
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public final void setAddress(@NonNull android.net.Uri, int);
-    method public final void setCallerDisplayName(@NonNull String, int);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setConferenceState(boolean);
-  }
-
-  public abstract class Connection extends android.telecom.Conferenceable {
-    method @IntRange(from=0) public final long getConnectTimeMillis();
-    method public final long getConnectionStartElapsedRealtimeMillis();
-    method @Nullable public android.telecom.PhoneAccountHandle getPhoneAccountHandle();
-    method @Nullable public final String getTelecomCallId();
-    method public final void resetConnectionTime();
-    method public void setCallDirection(int);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public final void setConnectTimeMillis(@IntRange(from=0) long);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public final void setConnectionStartElapsedRealtimeMillis(long);
-    method public void setPhoneAccountHandle(@NonNull android.telecom.PhoneAccountHandle);
-    method public void setTelecomCallId(@NonNull String);
-    field public static final int CAPABILITY_CONFERENCE_HAS_NO_CHILDREN = 2097152; // 0x200000
-    field public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 262144; // 0x40000
-    field public static final String EXTRA_DISABLE_ADD_CALL = "android.telecom.extra.DISABLE_ADD_CALL";
-    field public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 1; // 0x1
-    field public static final int PROPERTY_GENERIC_CONFERENCE = 2; // 0x2
-    field public static final int PROPERTY_IS_DOWNGRADED_CONFERENCE = 64; // 0x40
-    field public static final int PROPERTY_REMOTELY_HOSTED = 2048; // 0x800
-  }
-
-  public final class ConnectionRequest implements android.os.Parcelable {
-    method @Nullable public String getTelecomCallId();
-  }
-
   public static final class ConnectionRequest.Builder {
     ctor public ConnectionRequest.Builder();
     method @NonNull public android.telecom.ConnectionRequest build();
@@ -4052,53 +1709,11 @@
     method @NonNull public android.telecom.ConnectionRequest.Builder setVideoState(int);
   }
 
-  public static class PhoneAccount.Builder {
-    method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telecom.PhoneAccount.Builder setGroupId(@NonNull String);
-  }
-
-  public class PhoneAccountSuggestionService extends android.app.Service {
-    ctor public PhoneAccountSuggestionService();
-    method public void onAccountSuggestionRequest(@NonNull String);
-    method public android.os.IBinder onBind(android.content.Intent);
-    method public final void suggestPhoneAccounts(@NonNull String, @NonNull java.util.List<android.telecom.PhoneAccountSuggestion>);
-    field public static final String SERVICE_INTERFACE = "android.telecom.PhoneAccountSuggestionService";
-  }
-
-  public class TelecomManager {
-    method @NonNull public android.content.Intent createLaunchEmergencyDialerIntent(@Nullable String);
-    method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.telecom.PhoneAccountHandle> getCallCapablePhoneAccounts(boolean);
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCurrentTtyMode();
-    method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDefaultDialerPackage(@NonNull android.os.UserHandle);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean isInEmergencyCall();
-    method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRinging();
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUserSelectedOutgoingPhoneAccount(@Nullable android.telecom.PhoneAccountHandle);
-    field public static final String ACTION_CURRENT_TTY_MODE_CHANGED = "android.telecom.action.CURRENT_TTY_MODE_CHANGED";
-    field public static final String ACTION_TTY_PREFERRED_MODE_CHANGED = "android.telecom.action.TTY_PREFERRED_MODE_CHANGED";
-    field public static final String EXTRA_CURRENT_TTY_MODE = "android.telecom.extra.CURRENT_TTY_MODE";
-    field public static final String EXTRA_TTY_PREFERRED_MODE = "android.telecom.extra.TTY_PREFERRED_MODE";
-    field public static final int TTY_MODE_FULL = 1; // 0x1
-    field public static final int TTY_MODE_HCO = 2; // 0x2
-    field public static final int TTY_MODE_OFF = 0; // 0x0
-    field public static final int TTY_MODE_VCO = 3; // 0x3
-  }
-
 }
 
 package android.telephony {
 
-  public final class AccessNetworkConstants {
-    field public static final int TRANSPORT_TYPE_INVALID = -1; // 0xffffffff
-  }
-
-  public static final class AccessNetworkConstants.NgranBands {
-    method public static int getFrequencyRangeGroup(int);
-    field public static final int FREQUENCY_RANGE_GROUP_1 = 1; // 0x1
-    field public static final int FREQUENCY_RANGE_GROUP_2 = 2; // 0x2
-    field public static final int FREQUENCY_RANGE_GROUP_UNKNOWN = 0; // 0x0
-  }
-
   public final class BarringInfo implements android.os.Parcelable {
-    ctor public BarringInfo();
     ctor public BarringInfo(@Nullable android.telephony.CellIdentity, @NonNull android.util.SparseArray<android.telephony.BarringInfo.BarringServiceInfo>);
   }
 
@@ -4106,57 +1721,6 @@
     ctor public BarringInfo.BarringServiceInfo(int, boolean, int, int);
   }
 
-  public final class CallQuality implements android.os.Parcelable {
-    ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int);
-    ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int, boolean, boolean, boolean);
-    method public int describeContents();
-    method public int getAverageRelativeJitter();
-    method public int getAverageRoundTripTime();
-    method public int getCallDuration();
-    method public int getCodecType();
-    method public int getDownlinkCallQualityLevel();
-    method public int getMaxRelativeJitter();
-    method public int getNumRtpPacketsNotReceived();
-    method public int getNumRtpPacketsReceived();
-    method public int getNumRtpPacketsTransmitted();
-    method public int getNumRtpPacketsTransmittedLost();
-    method public int getUplinkCallQualityLevel();
-    method public boolean isIncomingSilenceDetectedAtCallSetup();
-    method public boolean isOutgoingSilenceDetectedAtCallSetup();
-    method public boolean isRtpInactivityDetected();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final int CALL_QUALITY_BAD = 4; // 0x4
-    field public static final int CALL_QUALITY_EXCELLENT = 0; // 0x0
-    field public static final int CALL_QUALITY_FAIR = 2; // 0x2
-    field public static final int CALL_QUALITY_GOOD = 1; // 0x1
-    field public static final int CALL_QUALITY_NOT_AVAILABLE = 5; // 0x5
-    field public static final int CALL_QUALITY_POOR = 3; // 0x3
-    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallQuality> CREATOR;
-  }
-
-  public class CarrierConfigManager {
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void overrideConfig(int, @Nullable android.os.PersistableBundle);
-  }
-
-  public final class DataSpecificRegistrationInfo implements android.os.Parcelable {
-    method public int describeContents();
-    method @NonNull public android.telephony.LteVopsSupportInfo getLteVopsSupportInfo();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.DataSpecificRegistrationInfo> CREATOR;
-  }
-
-  public final class LteVopsSupportInfo implements android.os.Parcelable {
-    ctor public LteVopsSupportInfo(int, int);
-    method public int describeContents();
-    method public int getEmcBearerSupport();
-    method public int getVopsSupport();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.LteVopsSupportInfo> CREATOR;
-    field public static final int LTE_STATUS_NOT_AVAILABLE = 1; // 0x1
-    field public static final int LTE_STATUS_NOT_SUPPORTED = 3; // 0x3
-    field public static final int LTE_STATUS_SUPPORTED = 2; // 0x2
-  }
-
   public class MbmsDownloadSession implements java.lang.AutoCloseable {
     field public static final String MBMS_DOWNLOAD_SERVICE_OVERRIDE_METADATA = "mbms-download-service-override";
   }
@@ -4171,71 +1735,14 @@
 
   public final class ModemActivityInfo implements android.os.Parcelable {
     ctor public ModemActivityInfo(long, int, int, @NonNull int[], int);
-    method public int describeContents();
-    method @NonNull public android.telephony.ModemActivityInfo getDelta(@NonNull android.telephony.ModemActivityInfo);
-    method public long getIdleTimeMillis();
-    method public static int getNumTxPowerLevels();
-    method public long getReceiveTimeMillis();
-    method public long getSleepTimeMillis();
-    method public long getTimestampMillis();
-    method public long getTransmitDurationMillisAtPowerLevel(int);
-    method @NonNull public android.util.Range<java.lang.Integer> getTransmitPowerRange(int);
     method public boolean isValid();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ModemActivityInfo> CREATOR;
-    field public static final int TX_POWER_LEVEL_0 = 0; // 0x0
-    field public static final int TX_POWER_LEVEL_1 = 1; // 0x1
-    field public static final int TX_POWER_LEVEL_2 = 2; // 0x2
-    field public static final int TX_POWER_LEVEL_3 = 3; // 0x3
-    field public static final int TX_POWER_LEVEL_4 = 4; // 0x4
-  }
-
-  public final class NetworkRegistrationInfo implements android.os.Parcelable {
-    method @Nullable public android.telephony.DataSpecificRegistrationInfo getDataSpecificInfo();
-    method public int getRegistrationState();
-    method public int getRejectCause();
-    method public int getRoamingType();
-    method public boolean isEmergencyEnabled();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final int REGISTRATION_STATE_DENIED = 3; // 0x3
-    field public static final int REGISTRATION_STATE_HOME = 1; // 0x1
-    field public static final int REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING = 0; // 0x0
-    field public static final int REGISTRATION_STATE_NOT_REGISTERED_SEARCHING = 2; // 0x2
-    field public static final int REGISTRATION_STATE_ROAMING = 5; // 0x5
-    field public static final int REGISTRATION_STATE_UNKNOWN = 4; // 0x4
-  }
-
-  public static final class NetworkRegistrationInfo.Builder {
-    ctor public NetworkRegistrationInfo.Builder();
-    method @NonNull public android.telephony.NetworkRegistrationInfo build();
-    method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setAccessNetworkTechnology(int);
-    method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setAvailableServices(@NonNull java.util.List<java.lang.Integer>);
-    method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setCellIdentity(@Nullable android.telephony.CellIdentity);
-    method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setDomain(int);
-    method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setEmergencyOnly(boolean);
-    method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRegisteredPlmn(@Nullable String);
-    method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRegistrationState(int);
-    method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRejectCause(int);
-    method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setTransportType(int);
   }
 
   public class PhoneNumberUtils {
     method public static int getMinMatchForTest();
-    method @NonNull public static String getUsernameFromUriNumber(@NonNull String);
-    method public static boolean isUriNumber(@Nullable String);
-    method public static boolean isVoiceMailNumber(@NonNull android.content.Context, int, @Nullable String);
     method public static void setMinMatchForTest(int);
   }
 
-  public class PhoneStateListener {
-    method @Deprecated public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber);
-    method public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber, int);
-    method @Deprecated public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber);
-    method public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber, int);
-    field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_CALL = 268435456; // 0x10000000
-    field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 536870912; // 0x20000000
-  }
-
   public final class PreciseDataConnectionState implements android.os.Parcelable {
     ctor @Deprecated public PreciseDataConnectionState(int, int, int, @NonNull String, @Nullable android.net.LinkProperties, int);
   }
@@ -4261,44 +1768,16 @@
     field public static final int SMS_CATEGORY_STANDARD_SHORT_CODE = 2; // 0x2
   }
 
-  public class SubscriptionManager {
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultVoiceSubscriptionId(int);
-    field @NonNull public static final android.net.Uri ADVANCED_CALLING_ENABLED_CONTENT_URI;
-    field @NonNull public static final android.net.Uri VT_ENABLED_CONTENT_URI;
-    field @NonNull public static final android.net.Uri WFC_ENABLED_CONTENT_URI;
-    field @NonNull public static final android.net.Uri WFC_MODE_CONTENT_URI;
-    field @NonNull public static final android.net.Uri WFC_ROAMING_ENABLED_CONTENT_URI;
-    field @NonNull public static final android.net.Uri WFC_ROAMING_MODE_CONTENT_URI;
-  }
-
   public class TelephonyManager {
     method public int addDevicePolicyOverrideApn(@NonNull android.content.Context, @NonNull android.telephony.data.ApnSetting);
-    method public int checkCarrierPrivilegesForPackage(String);
-    method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getAndUpdateDefaultRespondViaMessageApplication();
     method public int getCarrierIdListVersion();
-    method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
-    method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getDefaultRespondViaMessageApplication();
     method @NonNull public java.util.List<android.telephony.data.ApnSetting> getDevicePolicyOverrideApns(@NonNull android.content.Context);
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEmergencyNumberDbVersion();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getLine1AlphaTag();
     method public android.util.Pair<java.lang.Integer,java.lang.Integer> getRadioHalVersion();
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isMobileDataPolicyEnabled(int);
     method public boolean modifyDevicePolicyOverrideApn(@NonNull android.content.Context, int, @NonNull android.telephony.data.ApnSetting);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void refreshUiccProfile();
-    method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void resetOtaEmergencyNumberDbFilePath();
     method @Deprecated public void setCarrierTestOverride(String, String, String, String, String, String, String);
     method public void setCarrierTestOverride(String, String, String, String, String, String, String, String, String);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMobileDataPolicyEnabledStatus(int, boolean);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>);
-    method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateOtaEmergencyNumberDbFilePath(@NonNull android.os.ParcelFileDescriptor);
-    field public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; // 0xfffffffe
-    field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1
-    field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0
-    field public static final int CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED = -1; // 0xffffffff
-    field public static final int INVALID_EMERGENCY_NUMBER_DB_VERSION = -1; // 0xffffffff
-    field public static final int MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL = 1; // 0x1
-    field public static final int MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED = 2; // 0x2
     field public static final int UNKNOWN_CARRIER_ID_LIST_VERSION = -1; // 0xffffffff
   }
 
@@ -4314,835 +1793,18 @@
 
 package android.telephony.ims {
 
-  public final class ImsCallForwardInfo implements android.os.Parcelable {
-    ctor public ImsCallForwardInfo(int, int, int, int, @NonNull String, int);
-    method public int describeContents();
-    method public int getCondition();
-    method public String getNumber();
-    method public int getServiceClass();
-    method public int getStatus();
-    method public int getTimeSeconds();
-    method public int getToA();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final int CDIV_CF_REASON_ALL = 4; // 0x4
-    field public static final int CDIV_CF_REASON_ALL_CONDITIONAL = 5; // 0x5
-    field public static final int CDIV_CF_REASON_BUSY = 1; // 0x1
-    field public static final int CDIV_CF_REASON_NOT_LOGGED_IN = 6; // 0x6
-    field public static final int CDIV_CF_REASON_NOT_REACHABLE = 3; // 0x3
-    field public static final int CDIV_CF_REASON_NO_REPLY = 2; // 0x2
-    field public static final int CDIV_CF_REASON_UNCONDITIONAL = 0; // 0x0
-    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsCallForwardInfo> CREATOR;
-    field public static final int STATUS_ACTIVE = 1; // 0x1
-    field public static final int STATUS_NOT_ACTIVE = 0; // 0x0
-    field public static final int TYPE_OF_ADDRESS_INTERNATIONAL = 145; // 0x91
-    field public static final int TYPE_OF_ADDRESS_UNKNOWN = 129; // 0x81
-  }
-
   public final class ImsCallProfile implements android.os.Parcelable {
-    ctor public ImsCallProfile();
-    ctor public ImsCallProfile(int, int);
-    ctor public ImsCallProfile(int, int, android.os.Bundle, android.telephony.ims.ImsStreamMediaProfile);
-    method public int describeContents();
-    method public String getCallExtra(String);
-    method public String getCallExtra(String, String);
-    method public boolean getCallExtraBoolean(String);
-    method public boolean getCallExtraBoolean(String, boolean);
-    method public int getCallExtraInt(String);
-    method public int getCallExtraInt(String, int);
-    method public android.os.Bundle getCallExtras();
-    method public int getCallType();
-    method public static int getCallTypeFromVideoState(int);
-    method public int getCallerNumberVerificationStatus();
-    method public int getEmergencyCallRouting();
-    method public int getEmergencyServiceCategories();
-    method @NonNull public java.util.List<java.lang.String> getEmergencyUrns();
-    method public android.telephony.ims.ImsStreamMediaProfile getMediaProfile();
-    method @NonNull public android.os.Bundle getProprietaryCallExtras();
-    method public int getRestrictCause();
-    method public int getServiceType();
-    method public static int getVideoStateFromCallType(int);
-    method public static int getVideoStateFromImsCallProfile(android.telephony.ims.ImsCallProfile);
-    method public boolean hasKnownUserIntentEmergency();
-    method public boolean isEmergencyCallTesting();
-    method public boolean isVideoCall();
-    method public boolean isVideoPaused();
-    method public static int presentationToOir(int);
-    method public void setCallExtra(String, String);
-    method public void setCallExtraBoolean(String, boolean);
-    method public void setCallExtraInt(String, int);
-    method public void setCallRestrictCause(int);
-    method public void setCallerNumberVerificationStatus(int);
-    method public void setEmergencyCallRouting(int);
-    method public void setEmergencyCallTesting(boolean);
-    method public void setEmergencyServiceCategories(int);
-    method public void setEmergencyUrns(@NonNull java.util.List<java.lang.String>);
-    method public void setHasKnownUserIntentEmergency(boolean);
-    method public void updateCallExtras(android.telephony.ims.ImsCallProfile);
-    method public void updateCallType(android.telephony.ims.ImsCallProfile);
-    method public void updateMediaProfile(android.telephony.ims.ImsCallProfile);
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final int CALL_RESTRICT_CAUSE_DISABLED = 2; // 0x2
-    field public static final int CALL_RESTRICT_CAUSE_HD = 3; // 0x3
-    field public static final int CALL_RESTRICT_CAUSE_NONE = 0; // 0x0
-    field public static final int CALL_RESTRICT_CAUSE_RAT = 1; // 0x1
-    field public static final int CALL_TYPE_VIDEO_N_VOICE = 3; // 0x3
-    field public static final int CALL_TYPE_VOICE = 2; // 0x2
-    field public static final int CALL_TYPE_VOICE_N_VIDEO = 1; // 0x1
-    field public static final int CALL_TYPE_VS = 8; // 0x8
-    field public static final int CALL_TYPE_VS_RX = 10; // 0xa
-    field public static final int CALL_TYPE_VS_TX = 9; // 0x9
-    field public static final int CALL_TYPE_VT = 4; // 0x4
-    field public static final int CALL_TYPE_VT_NODIR = 7; // 0x7
-    field public static final int CALL_TYPE_VT_RX = 6; // 0x6
-    field public static final int CALL_TYPE_VT_TX = 5; // 0x5
-    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsCallProfile> CREATOR;
-    field public static final int DIALSTRING_NORMAL = 0; // 0x0
-    field public static final int DIALSTRING_SS_CONF = 1; // 0x1
-    field public static final int DIALSTRING_USSD = 2; // 0x2
-    field public static final String EXTRA_ADDITIONAL_CALL_INFO = "AdditionalCallInfo";
-    field public static final String EXTRA_ADDITIONAL_SIP_INVITE_FIELDS = "android.telephony.ims.extra.ADDITIONAL_SIP_INVITE_FIELDS";
-    field public static final String EXTRA_CALL_DISCONNECT_CAUSE = "android.telephony.ims.extra.CALL_DISCONNECT_CAUSE";
-    field public static final String EXTRA_CALL_NETWORK_TYPE = "android.telephony.ims.extra.CALL_NETWORK_TYPE";
-    field @Deprecated public static final String EXTRA_CALL_RAT_TYPE = "CallRadioTech";
-    field public static final String EXTRA_CHILD_NUMBER = "ChildNum";
-    field public static final String EXTRA_CNA = "cna";
-    field public static final String EXTRA_CNAP = "cnap";
-    field public static final String EXTRA_CODEC = "Codec";
-    field public static final String EXTRA_DIALSTRING = "dialstring";
-    field public static final String EXTRA_DISPLAY_TEXT = "DisplayText";
-    field public static final String EXTRA_EMERGENCY_CALL = "e_call";
-    field public static final String EXTRA_FORWARDED_NUMBER = "android.telephony.ims.extra.FORWARDED_NUMBER";
-    field public static final String EXTRA_IS_CALL_PULL = "CallPull";
     field public static final String EXTRA_OEM_EXTRAS = "android.telephony.ims.extra.OEM_EXTRAS";
-    field public static final String EXTRA_OI = "oi";
-    field public static final String EXTRA_OIR = "oir";
-    field public static final String EXTRA_REMOTE_URI = "remote_uri";
-    field public static final String EXTRA_USSD = "ussd";
-    field public static final int OIR_DEFAULT = 0; // 0x0
-    field public static final int OIR_PRESENTATION_NOT_RESTRICTED = 2; // 0x2
-    field public static final int OIR_PRESENTATION_PAYPHONE = 4; // 0x4
-    field public static final int OIR_PRESENTATION_RESTRICTED = 1; // 0x1
-    field public static final int OIR_PRESENTATION_UNKNOWN = 3; // 0x3
-    field public static final int SERVICE_TYPE_EMERGENCY = 2; // 0x2
-    field public static final int SERVICE_TYPE_NONE = 0; // 0x0
-    field public static final int SERVICE_TYPE_NORMAL = 1; // 0x1
-    field public static final int VERIFICATION_STATUS_FAILED = 2; // 0x2
-    field public static final int VERIFICATION_STATUS_NOT_VERIFIED = 0; // 0x0
-    field public static final int VERIFICATION_STATUS_PASSED = 1; // 0x1
-  }
-
-  public class ImsCallSessionListener {
-    method public void callQualityChanged(@NonNull android.telephony.CallQuality);
-    method public void callSessionConferenceExtendFailed(android.telephony.ims.ImsReasonInfo);
-    method public void callSessionConferenceExtendReceived(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
-    method public void callSessionConferenceExtended(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
-    method public void callSessionConferenceStateUpdated(android.telephony.ims.ImsConferenceState);
-    method @Deprecated public void callSessionHandover(int, int, android.telephony.ims.ImsReasonInfo);
-    method @Deprecated public void callSessionHandoverFailed(int, int, android.telephony.ims.ImsReasonInfo);
-    method public void callSessionHeld(android.telephony.ims.ImsCallProfile);
-    method public void callSessionHoldFailed(android.telephony.ims.ImsReasonInfo);
-    method public void callSessionHoldReceived(android.telephony.ims.ImsCallProfile);
-    method public void callSessionInitiated(android.telephony.ims.ImsCallProfile);
-    method public void callSessionInitiatedFailed(android.telephony.ims.ImsReasonInfo);
-    method public void callSessionInviteParticipantsRequestDelivered();
-    method public void callSessionInviteParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo);
-    method @Deprecated public void callSessionMayHandover(int, int);
-    method public void callSessionMergeComplete(android.telephony.ims.stub.ImsCallSessionImplBase);
-    method public void callSessionMergeFailed(android.telephony.ims.ImsReasonInfo);
-    method public void callSessionMergeStarted(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
-    method public void callSessionMultipartyStateChanged(boolean);
-    method public void callSessionProgressing(android.telephony.ims.ImsStreamMediaProfile);
-    method public void callSessionRemoveParticipantsRequestDelivered();
-    method public void callSessionRemoveParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo);
-    method public void callSessionResumeFailed(android.telephony.ims.ImsReasonInfo);
-    method public void callSessionResumeReceived(android.telephony.ims.ImsCallProfile);
-    method public void callSessionResumed(android.telephony.ims.ImsCallProfile);
-    method public void callSessionRttAudioIndicatorChanged(@NonNull android.telephony.ims.ImsStreamMediaProfile);
-    method public void callSessionRttMessageReceived(String);
-    method public void callSessionRttModifyRequestReceived(android.telephony.ims.ImsCallProfile);
-    method public void callSessionRttModifyResponseReceived(int);
-    method public void callSessionSuppServiceReceived(android.telephony.ims.ImsSuppServiceNotification);
-    method public void callSessionTerminated(android.telephony.ims.ImsReasonInfo);
-    method public void callSessionTtyModeReceived(int);
-    method public void callSessionUpdateFailed(android.telephony.ims.ImsReasonInfo);
-    method public void callSessionUpdateReceived(android.telephony.ims.ImsCallProfile);
-    method public void callSessionUpdated(android.telephony.ims.ImsCallProfile);
-    method public void callSessionUssdMessageReceived(int, String);
-    method public void onHandover(int, int, @Nullable android.telephony.ims.ImsReasonInfo);
-    method public void onHandoverFailed(int, int, @NonNull android.telephony.ims.ImsReasonInfo);
-    method public void onMayHandover(int, int);
-  }
-
-  public final class ImsConferenceState implements android.os.Parcelable {
-    method public int describeContents();
-    method public static int getConnectionStateForStatus(String);
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsConferenceState> CREATOR;
-    field public static final String DISPLAY_TEXT = "display-text";
-    field public static final String ENDPOINT = "endpoint";
-    field public static final String SIP_STATUS_CODE = "sipstatuscode";
-    field public static final String STATUS = "status";
-    field public static final String STATUS_ALERTING = "alerting";
-    field public static final String STATUS_CONNECTED = "connected";
-    field public static final String STATUS_CONNECT_FAIL = "connect-fail";
-    field public static final String STATUS_DIALING_IN = "dialing-in";
-    field public static final String STATUS_DIALING_OUT = "dialing-out";
-    field public static final String STATUS_DISCONNECTED = "disconnected";
-    field public static final String STATUS_DISCONNECTING = "disconnecting";
-    field public static final String STATUS_MUTED_VIA_FOCUS = "muted-via-focus";
-    field public static final String STATUS_ON_HOLD = "on-hold";
-    field public static final String STATUS_PENDING = "pending";
-    field public static final String STATUS_SEND_ONLY = "sendonly";
-    field public static final String STATUS_SEND_RECV = "sendrecv";
-    field public static final String USER = "user";
-    field public final java.util.HashMap<java.lang.String,android.os.Bundle> mParticipants;
-  }
-
-  public final class ImsException extends java.lang.Exception {
-    ctor public ImsException(@Nullable String);
-    ctor public ImsException(@Nullable String, int);
-    ctor public ImsException(@Nullable String, int, @Nullable Throwable);
-  }
-
-  public final class ImsExternalCallState implements android.os.Parcelable {
-    ctor public ImsExternalCallState(@NonNull String, @NonNull android.net.Uri, @Nullable android.net.Uri, boolean, int, int, boolean);
-    method public int describeContents();
-    method @NonNull public android.net.Uri getAddress();
-    method public int getCallId();
-    method public int getCallState();
-    method public int getCallType();
-    method @Nullable public android.net.Uri getLocalAddress();
-    method public boolean isCallHeld();
-    method public boolean isCallPullable();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final int CALL_STATE_CONFIRMED = 1; // 0x1
-    field public static final int CALL_STATE_TERMINATED = 2; // 0x2
-    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsExternalCallState> CREATOR;
-  }
-
-  public class ImsMmTelManager implements android.telephony.ims.RegistrationManager {
-    method @Deprecated @NonNull @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws android.telephony.ims.ImsException;
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiRoamingModeSetting();
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAvailable(int, int);
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isCapable(int, int);
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void isSupported(int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>) throws android.telephony.ims.ImsException;
-    method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException;
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAdvancedCallingSettingEnabled(boolean);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRttCapabilitySetting(boolean);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiModeSetting(int);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiNonPersistent(boolean, int);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingModeSetting(int);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingSettingEnabled(boolean);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiSettingEnabled(boolean);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVtSettingEnabled(boolean);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback);
-  }
-
-  @Deprecated public static class ImsMmTelManager.RegistrationCallback extends android.telephony.ims.RegistrationManager.RegistrationCallback {
-    ctor @Deprecated public ImsMmTelManager.RegistrationCallback();
-  }
-
-  public class ImsService extends android.app.Service {
-    ctor public ImsService();
-    method public android.telephony.ims.feature.MmTelFeature createMmTelFeature(int);
-    method public android.telephony.ims.feature.RcsFeature createRcsFeature(int);
-    method public void disableIms(int);
-    method public void enableIms(int);
-    method public android.telephony.ims.stub.ImsConfigImplBase getConfig(int);
-    method public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int);
-    method public final void onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) throws android.os.RemoteException;
-    method public android.telephony.ims.stub.ImsFeatureConfiguration querySupportedImsFeatures();
-    method public void readyForFeatureCreation();
-  }
-
-  public final class ImsSsData implements android.os.Parcelable {
-    ctor public ImsSsData(int, int, int, int, int);
-    method public int describeContents();
-    method @Nullable public java.util.List<android.telephony.ims.ImsCallForwardInfo> getCallForwardInfo();
-    method public int getRequestType();
-    method public int getResult();
-    method public int getServiceClass();
-    method public int getServiceType();
-    method @NonNull public java.util.List<android.telephony.ims.ImsSsInfo> getSuppServiceInfo();
-    method public int getTeleserviceType();
-    method public boolean isTypeBarring();
-    method public boolean isTypeCf();
-    method public boolean isTypeClip();
-    method public boolean isTypeClir();
-    method public boolean isTypeColp();
-    method public boolean isTypeColr();
-    method public boolean isTypeCw();
-    method public boolean isTypeIcb();
-    method public boolean isTypeInterrogation();
-    method public boolean isTypeUnConditional();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSsData> CREATOR;
-    field public static final int RESULT_SUCCESS = 0; // 0x0
-    field public static final int SERVICE_CLASS_DATA = 2; // 0x2
-    field public static final int SERVICE_CLASS_DATA_CIRCUIT_ASYNC = 32; // 0x20
-    field public static final int SERVICE_CLASS_DATA_CIRCUIT_SYNC = 16; // 0x10
-    field public static final int SERVICE_CLASS_DATA_PACKET_ACCESS = 64; // 0x40
-    field public static final int SERVICE_CLASS_DATA_PAD = 128; // 0x80
-    field public static final int SERVICE_CLASS_FAX = 4; // 0x4
-    field public static final int SERVICE_CLASS_NONE = 0; // 0x0
-    field public static final int SERVICE_CLASS_SMS = 8; // 0x8
-    field public static final int SERVICE_CLASS_VOICE = 1; // 0x1
-    field public static final int SS_ACTIVATION = 0; // 0x0
-    field public static final int SS_ALL_BARRING = 18; // 0x12
-    field public static final int SS_ALL_DATA_TELESERVICES = 3; // 0x3
-    field public static final int SS_ALL_TELESERVICES_EXCEPT_SMS = 5; // 0x5
-    field public static final int SS_ALL_TELESEVICES = 1; // 0x1
-    field public static final int SS_ALL_TELE_AND_BEARER_SERVICES = 0; // 0x0
-    field public static final int SS_BAIC = 16; // 0x10
-    field public static final int SS_BAIC_ROAMING = 17; // 0x11
-    field public static final int SS_BAOC = 13; // 0xd
-    field public static final int SS_BAOIC = 14; // 0xe
-    field public static final int SS_BAOIC_EXC_HOME = 15; // 0xf
-    field public static final int SS_CFU = 0; // 0x0
-    field public static final int SS_CFUT = 6; // 0x6
-    field public static final int SS_CF_ALL = 4; // 0x4
-    field public static final int SS_CF_ALL_CONDITIONAL = 5; // 0x5
-    field public static final int SS_CF_BUSY = 1; // 0x1
-    field public static final int SS_CF_NOT_REACHABLE = 3; // 0x3
-    field public static final int SS_CF_NO_REPLY = 2; // 0x2
-    field public static final int SS_CLIP = 7; // 0x7
-    field public static final int SS_CLIR = 8; // 0x8
-    field public static final int SS_CNAP = 11; // 0xb
-    field public static final int SS_COLP = 9; // 0x9
-    field public static final int SS_COLR = 10; // 0xa
-    field public static final int SS_DEACTIVATION = 1; // 0x1
-    field public static final int SS_ERASURE = 4; // 0x4
-    field public static final int SS_INCOMING_BARRING = 20; // 0x14
-    field public static final int SS_INCOMING_BARRING_ANONYMOUS = 22; // 0x16
-    field public static final int SS_INCOMING_BARRING_DN = 21; // 0x15
-    field public static final int SS_INTERROGATION = 2; // 0x2
-    field public static final int SS_OUTGOING_BARRING = 19; // 0x13
-    field public static final int SS_REGISTRATION = 3; // 0x3
-    field public static final int SS_SMS_SERVICES = 4; // 0x4
-    field public static final int SS_TELEPHONY = 2; // 0x2
-    field public static final int SS_WAIT = 12; // 0xc
-  }
-
-  public static final class ImsSsData.Builder {
-    ctor public ImsSsData.Builder(int, int, int, int, int);
-    method @NonNull public android.telephony.ims.ImsSsData build();
-    method @NonNull public android.telephony.ims.ImsSsData.Builder setCallForwardingInfo(@NonNull java.util.List<android.telephony.ims.ImsCallForwardInfo>);
-    method @NonNull public android.telephony.ims.ImsSsData.Builder setSuppServiceInfo(@NonNull java.util.List<android.telephony.ims.ImsSsInfo>);
-  }
-
-  public final class ImsSsInfo implements android.os.Parcelable {
-    ctor @Deprecated public ImsSsInfo(int, @Nullable String);
-    method public int describeContents();
-    method public int getClirInterrogationStatus();
-    method public int getClirOutgoingState();
-    method @Deprecated public String getIcbNum();
-    method @Nullable public String getIncomingCommunicationBarringNumber();
-    method public int getProvisionStatus();
-    method public int getStatus();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final int CLIR_OUTGOING_DEFAULT = 0; // 0x0
-    field public static final int CLIR_OUTGOING_INVOCATION = 1; // 0x1
-    field public static final int CLIR_OUTGOING_SUPPRESSION = 2; // 0x2
-    field public static final int CLIR_STATUS_NOT_PROVISIONED = 0; // 0x0
-    field public static final int CLIR_STATUS_PROVISIONED_PERMANENT = 1; // 0x1
-    field public static final int CLIR_STATUS_TEMPORARILY_ALLOWED = 4; // 0x4
-    field public static final int CLIR_STATUS_TEMPORARILY_RESTRICTED = 3; // 0x3
-    field public static final int CLIR_STATUS_UNKNOWN = 2; // 0x2
-    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSsInfo> CREATOR;
-    field public static final int DISABLED = 0; // 0x0
-    field public static final int ENABLED = 1; // 0x1
-    field public static final int NOT_REGISTERED = -1; // 0xffffffff
-    field public static final int SERVICE_NOT_PROVISIONED = 0; // 0x0
-    field public static final int SERVICE_PROVISIONED = 1; // 0x1
-    field public static final int SERVICE_PROVISIONING_UNKNOWN = -1; // 0xffffffff
-  }
-
-  public static final class ImsSsInfo.Builder {
-    ctor public ImsSsInfo.Builder(int);
-    method @NonNull public android.telephony.ims.ImsSsInfo build();
-    method @NonNull public android.telephony.ims.ImsSsInfo.Builder setClirInterrogationStatus(int);
-    method @NonNull public android.telephony.ims.ImsSsInfo.Builder setClirOutgoingState(int);
-    method @NonNull public android.telephony.ims.ImsSsInfo.Builder setIncomingCommunicationBarringNumber(@NonNull String);
-    method @NonNull public android.telephony.ims.ImsSsInfo.Builder setProvisionStatus(int);
-  }
-
-  public final class ImsStreamMediaProfile implements android.os.Parcelable {
-    ctor public ImsStreamMediaProfile(int, int, int, int, int);
-    method public void copyFrom(android.telephony.ims.ImsStreamMediaProfile);
-    method public int describeContents();
-    method public int getAudioDirection();
-    method public int getAudioQuality();
-    method public int getRttMode();
-    method public int getVideoDirection();
-    method public int getVideoQuality();
-    method public boolean isReceivingRttAudio();
-    method public boolean isRttCall();
-    method public void setReceivingRttAudio(boolean);
-    method public void setRttMode(int);
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final int AUDIO_QUALITY_AMR = 1; // 0x1
-    field public static final int AUDIO_QUALITY_AMR_WB = 2; // 0x2
-    field public static final int AUDIO_QUALITY_EVRC = 4; // 0x4
-    field public static final int AUDIO_QUALITY_EVRC_B = 5; // 0x5
-    field public static final int AUDIO_QUALITY_EVRC_NW = 7; // 0x7
-    field public static final int AUDIO_QUALITY_EVRC_WB = 6; // 0x6
-    field public static final int AUDIO_QUALITY_EVS_FB = 20; // 0x14
-    field public static final int AUDIO_QUALITY_EVS_NB = 17; // 0x11
-    field public static final int AUDIO_QUALITY_EVS_SWB = 19; // 0x13
-    field public static final int AUDIO_QUALITY_EVS_WB = 18; // 0x12
-    field public static final int AUDIO_QUALITY_G711A = 13; // 0xd
-    field public static final int AUDIO_QUALITY_G711AB = 15; // 0xf
-    field public static final int AUDIO_QUALITY_G711U = 11; // 0xb
-    field public static final int AUDIO_QUALITY_G722 = 14; // 0xe
-    field public static final int AUDIO_QUALITY_G723 = 12; // 0xc
-    field public static final int AUDIO_QUALITY_G729 = 16; // 0x10
-    field public static final int AUDIO_QUALITY_GSM_EFR = 8; // 0x8
-    field public static final int AUDIO_QUALITY_GSM_FR = 9; // 0x9
-    field public static final int AUDIO_QUALITY_GSM_HR = 10; // 0xa
-    field public static final int AUDIO_QUALITY_NONE = 0; // 0x0
-    field public static final int AUDIO_QUALITY_QCELP13K = 3; // 0x3
-    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsStreamMediaProfile> CREATOR;
-    field public static final int DIRECTION_INACTIVE = 0; // 0x0
-    field public static final int DIRECTION_INVALID = -1; // 0xffffffff
-    field public static final int DIRECTION_RECEIVE = 1; // 0x1
-    field public static final int DIRECTION_SEND = 2; // 0x2
-    field public static final int DIRECTION_SEND_RECEIVE = 3; // 0x3
-    field public static final int RTT_MODE_DISABLED = 0; // 0x0
-    field public static final int RTT_MODE_FULL = 1; // 0x1
-    field public static final int VIDEO_QUALITY_NONE = 0; // 0x0
-    field public static final int VIDEO_QUALITY_QCIF = 1; // 0x1
-    field public static final int VIDEO_QUALITY_QVGA_LANDSCAPE = 2; // 0x2
-    field public static final int VIDEO_QUALITY_QVGA_PORTRAIT = 4; // 0x4
-    field public static final int VIDEO_QUALITY_VGA_LANDSCAPE = 8; // 0x8
-    field public static final int VIDEO_QUALITY_VGA_PORTRAIT = 16; // 0x10
-  }
-
-  public final class ImsSuppServiceNotification implements android.os.Parcelable {
-    ctor public ImsSuppServiceNotification(int, int, int, int, String, String[]);
-    method public int describeContents();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSuppServiceNotification> CREATOR;
-    field public final int code;
-    field public final String[] history;
-    field public final int index;
-    field public final int notificationType;
-    field public final String number;
-    field public final int type;
-  }
-
-  public class ImsUtListener {
-    method public void onLineIdentificationSupplementaryServiceResponse(int, @NonNull android.telephony.ims.ImsSsInfo);
-    method public void onSupplementaryServiceIndication(android.telephony.ims.ImsSsData);
-    method public void onUtConfigurationCallBarringQueried(int, android.telephony.ims.ImsSsInfo[]);
-    method public void onUtConfigurationCallForwardQueried(int, android.telephony.ims.ImsCallForwardInfo[]);
-    method public void onUtConfigurationCallWaitingQueried(int, android.telephony.ims.ImsSsInfo[]);
-    method @Deprecated public void onUtConfigurationQueried(int, android.os.Bundle);
-    method public void onUtConfigurationQueryFailed(int, android.telephony.ims.ImsReasonInfo);
-    method public void onUtConfigurationUpdateFailed(int, android.telephony.ims.ImsReasonInfo);
-    method public void onUtConfigurationUpdated(int);
-    field @Deprecated public static final String BUNDLE_KEY_CLIR = "queryClir";
-    field @Deprecated public static final String BUNDLE_KEY_SSINFO = "imsSsInfo";
-  }
-
-  public abstract class ImsVideoCallProvider {
-    ctor public ImsVideoCallProvider();
-    method public void changeCallDataUsage(long);
-    method public void changeCameraCapabilities(android.telecom.VideoProfile.CameraCapabilities);
-    method public void changePeerDimensions(int, int);
-    method public void changeVideoQuality(int);
-    method public void handleCallSessionEvent(int);
-    method public abstract void onRequestCallDataUsage();
-    method public abstract void onRequestCameraCapabilities();
-    method public abstract void onSendSessionModifyRequest(android.telecom.VideoProfile, android.telecom.VideoProfile);
-    method public abstract void onSendSessionModifyResponse(android.telecom.VideoProfile);
-    method public abstract void onSetCamera(String);
-    method public void onSetCamera(String, int);
-    method public abstract void onSetDeviceOrientation(int);
-    method public abstract void onSetDisplaySurface(android.view.Surface);
-    method public abstract void onSetPauseImage(android.net.Uri);
-    method public abstract void onSetPreviewSurface(android.view.Surface);
-    method public abstract void onSetZoom(float);
-    method public void receiveSessionModifyRequest(android.telecom.VideoProfile);
-    method public void receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile);
-  }
-
-  public class ProvisioningManager {
-    method @NonNull public static android.telephony.ims.ProvisioningManager createForSubscriptionId(int);
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public int getProvisioningIntValue(int);
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getProvisioningStatusForCapability(int, int);
-    method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public String getProvisioningStringValue(int);
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getRcsProvisioningStatusForCapability(int);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean);
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException;
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningIntValue(int, int);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(int, int, boolean);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean);
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback);
-    field public static final int KEY_VOICE_OVER_WIFI_ENTITLEMENT_ID = 67; // 0x43
-    field public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27; // 0x1b
-    field public static final int KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE = 26; // 0x1a
-    field public static final int PROVISIONING_VALUE_DISABLED = 0; // 0x0
-    field public static final int PROVISIONING_VALUE_ENABLED = 1; // 0x1
-    field public static final String STRING_QUERY_RESULT_ERROR_GENERIC = "STRING_QUERY_RESULT_ERROR_GENERIC";
-    field public static final String STRING_QUERY_RESULT_ERROR_NOT_READY = "STRING_QUERY_RESULT_ERROR_NOT_READY";
-  }
-
-  public static class ProvisioningManager.Callback {
-    ctor public ProvisioningManager.Callback();
-    method public void onProvisioningIntChanged(int, int);
-    method public void onProvisioningStringChanged(int, @NonNull String);
-  }
-
-  public class RcsUceAdapter {
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean) throws android.telephony.ims.ImsException;
   }
 
 }
 
 package android.telephony.ims.feature {
 
-  public final class CapabilityChangeRequest implements android.os.Parcelable {
-    method public void addCapabilitiesToDisableForTech(int, int);
-    method public void addCapabilitiesToEnableForTech(int, int);
-    method public int describeContents();
-    method public java.util.List<android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair> getCapabilitiesToDisable();
-    method public java.util.List<android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair> getCapabilitiesToEnable();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.feature.CapabilityChangeRequest> CREATOR;
-  }
-
-  public static class CapabilityChangeRequest.CapabilityPair {
-    ctor public CapabilityChangeRequest.CapabilityPair(int, int);
-    method public int getCapability();
-    method public int getRadioTech();
-  }
-
-  public abstract class ImsFeature {
-    ctor public ImsFeature();
-    method public abstract void changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
-    method public int getFeatureState();
-    method public final int getSlotIndex();
-    method public abstract void onFeatureReady();
-    method public abstract void onFeatureRemoved();
-    method public final void setFeatureState(int);
-    field public static final int CAPABILITY_ERROR_GENERIC = -1; // 0xffffffff
-    field public static final int CAPABILITY_SUCCESS = 0; // 0x0
-    field public static final int FEATURE_EMERGENCY_MMTEL = 0; // 0x0
-    field public static final int FEATURE_MMTEL = 1; // 0x1
-    field public static final int FEATURE_RCS = 2; // 0x2
-    field public static final int STATE_INITIALIZING = 1; // 0x1
-    field public static final int STATE_READY = 2; // 0x2
-    field public static final int STATE_UNAVAILABLE = 0; // 0x0
-  }
-
   @Deprecated public static class ImsFeature.Capabilities {
     field @Deprecated protected int mCapabilities;
   }
 
-  protected static class ImsFeature.CapabilityCallbackProxy {
-    method public void onChangeCapabilityConfigurationError(int, int, int);
-  }
-
-  public class MmTelFeature extends android.telephony.ims.feature.ImsFeature {
-    ctor public MmTelFeature();
-    method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
-    method @Nullable public android.telephony.ims.ImsCallProfile createCallProfile(int, int);
-    method @Nullable public android.telephony.ims.stub.ImsCallSessionImplBase createCallSession(@NonNull android.telephony.ims.ImsCallProfile);
-    method @NonNull public android.telephony.ims.stub.ImsEcbmImplBase getEcbm();
-    method @NonNull public android.telephony.ims.stub.ImsMultiEndpointImplBase getMultiEndpoint();
-    method @NonNull public android.telephony.ims.stub.ImsSmsImplBase getSmsImplementation();
-    method @NonNull public android.telephony.ims.stub.ImsUtImplBase getUt();
-    method public final void notifyCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.MmTelFeature.MmTelCapabilities);
-    method public final void notifyIncomingCall(@NonNull android.telephony.ims.stub.ImsCallSessionImplBase, @NonNull android.os.Bundle);
-    method public final void notifyRejectedCall(@NonNull android.telephony.ims.ImsCallProfile, @NonNull android.telephony.ims.ImsReasonInfo);
-    method public final void notifyVoiceMessageCountUpdate(int);
-    method public void onFeatureReady();
-    method public void onFeatureRemoved();
-    method public boolean queryCapabilityConfiguration(int, int);
-    method @NonNull public final android.telephony.ims.feature.MmTelFeature.MmTelCapabilities queryCapabilityStatus();
-    method public void setUiTtyMode(int, @Nullable android.os.Message);
-    method public int shouldProcessCall(@NonNull String[]);
-    field public static final String EXTRA_IS_UNKNOWN_CALL = "android.telephony.ims.feature.extra.IS_UNKNOWN_CALL";
-    field public static final String EXTRA_IS_USSD = "android.telephony.ims.feature.extra.IS_USSD";
-    field public static final int PROCESS_CALL_CSFB = 1; // 0x1
-    field public static final int PROCESS_CALL_IMS = 0; // 0x0
-  }
-
-  public static class MmTelFeature.MmTelCapabilities extends android.telephony.ims.feature.ImsFeature.Capabilities {
-    ctor public MmTelFeature.MmTelCapabilities();
-    ctor @Deprecated public MmTelFeature.MmTelCapabilities(android.telephony.ims.feature.ImsFeature.Capabilities);
-    ctor public MmTelFeature.MmTelCapabilities(int);
-    method public final void addCapabilities(int);
-    method public final void removeCapabilities(int);
-  }
-
-  public class RcsFeature extends android.telephony.ims.feature.ImsFeature {
-    ctor public RcsFeature();
-    method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
-    method public void onFeatureReady();
-    method public void onFeatureRemoved();
-  }
-
-}
-
-package android.telephony.ims.stub {
-
-  public class ImsCallSessionImplBase implements java.lang.AutoCloseable {
-    ctor public ImsCallSessionImplBase();
-    method public void accept(int, android.telephony.ims.ImsStreamMediaProfile);
-    method public void close();
-    method public void deflect(String);
-    method public void extendToConference(String[]);
-    method public String getCallId();
-    method public android.telephony.ims.ImsCallProfile getCallProfile();
-    method public android.telephony.ims.ImsVideoCallProvider getImsVideoCallProvider();
-    method public android.telephony.ims.ImsCallProfile getLocalCallProfile();
-    method public String getProperty(String);
-    method public android.telephony.ims.ImsCallProfile getRemoteCallProfile();
-    method public int getState();
-    method public void hold(android.telephony.ims.ImsStreamMediaProfile);
-    method public void inviteParticipants(String[]);
-    method public boolean isInCall();
-    method public boolean isMultiparty();
-    method public void merge();
-    method public void reject(int);
-    method public void removeParticipants(String[]);
-    method public void resume(android.telephony.ims.ImsStreamMediaProfile);
-    method public void sendDtmf(char, android.os.Message);
-    method public void sendRttMessage(String);
-    method public void sendRttModifyRequest(android.telephony.ims.ImsCallProfile);
-    method public void sendRttModifyResponse(boolean);
-    method public void sendUssd(String);
-    method public void setListener(android.telephony.ims.ImsCallSessionListener);
-    method public void setMute(boolean);
-    method public void start(String, android.telephony.ims.ImsCallProfile);
-    method public void startConference(String[], android.telephony.ims.ImsCallProfile);
-    method public void startDtmf(char);
-    method public void stopDtmf();
-    method public void terminate(int);
-    method public void update(int, android.telephony.ims.ImsStreamMediaProfile);
-    field public static final int USSD_MODE_NOTIFY = 0; // 0x0
-    field public static final int USSD_MODE_REQUEST = 1; // 0x1
-  }
-
-  public static class ImsCallSessionImplBase.State {
-    method public static String toString(int);
-    field public static final int ESTABLISHED = 4; // 0x4
-    field public static final int ESTABLISHING = 3; // 0x3
-    field public static final int IDLE = 0; // 0x0
-    field public static final int INITIATED = 1; // 0x1
-    field public static final int INVALID = -1; // 0xffffffff
-    field public static final int NEGOTIATING = 2; // 0x2
-    field public static final int REESTABLISHING = 6; // 0x6
-    field public static final int RENEGOTIATING = 5; // 0x5
-    field public static final int TERMINATED = 8; // 0x8
-    field public static final int TERMINATING = 7; // 0x7
-  }
-
-  public class ImsConfigImplBase {
-    ctor public ImsConfigImplBase();
-    method public int getConfigInt(int);
-    method public String getConfigString(int);
-    method public final void notifyProvisionedValueChanged(int, int);
-    method public final void notifyProvisionedValueChanged(int, String);
-    method public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean);
-    method public int setConfig(int, int);
-    method public int setConfig(int, String);
-    field public static final int CONFIG_RESULT_FAILED = 1; // 0x1
-    field public static final int CONFIG_RESULT_SUCCESS = 0; // 0x0
-    field public static final int CONFIG_RESULT_UNKNOWN = -1; // 0xffffffff
-  }
-
-  public class ImsEcbmImplBase {
-    ctor public ImsEcbmImplBase();
-    method public final void enteredEcbm();
-    method public void exitEmergencyCallbackMode();
-    method public final void exitedEcbm();
-  }
-
-  public final class ImsFeatureConfiguration implements android.os.Parcelable {
-    method public int describeContents();
-    method public java.util.Set<android.telephony.ims.stub.ImsFeatureConfiguration.FeatureSlotPair> getServiceFeatures();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.stub.ImsFeatureConfiguration> CREATOR;
-  }
-
-  public static class ImsFeatureConfiguration.Builder {
-    ctor public ImsFeatureConfiguration.Builder();
-    method public android.telephony.ims.stub.ImsFeatureConfiguration.Builder addFeature(int, int);
-    method public android.telephony.ims.stub.ImsFeatureConfiguration build();
-  }
-
-  public static final class ImsFeatureConfiguration.FeatureSlotPair {
-    ctor public ImsFeatureConfiguration.FeatureSlotPair(int, int);
-    field public final int featureType;
-    field public final int slotId;
-  }
-
-  public class ImsMultiEndpointImplBase {
-    ctor public ImsMultiEndpointImplBase();
-    method public final void onImsExternalCallStateUpdate(java.util.List<android.telephony.ims.ImsExternalCallState>);
-    method public void requestImsExternalCallStateInfo();
-  }
-
-  public class ImsRegistrationImplBase {
-    ctor public ImsRegistrationImplBase();
-    method public final void onDeregistered(android.telephony.ims.ImsReasonInfo);
-    method public final void onRegistered(int);
-    method public final void onRegistering(int);
-    method public final void onSubscriberAssociatedUriChanged(android.net.Uri[]);
-    method public final void onTechnologyChangeFailed(int, android.telephony.ims.ImsReasonInfo);
-    field public static final int REGISTRATION_TECH_IWLAN = 1; // 0x1
-    field public static final int REGISTRATION_TECH_LTE = 0; // 0x0
-    field public static final int REGISTRATION_TECH_NONE = -1; // 0xffffffff
-  }
-
-  public class ImsSmsImplBase {
-    ctor public ImsSmsImplBase();
-    method public void acknowledgeSms(int, @IntRange(from=0, to=65535) int, int);
-    method public void acknowledgeSmsReport(int, @IntRange(from=0, to=65535) int, int);
-    method public String getSmsFormat();
-    method public void onReady();
-    method @Deprecated public final void onSendSmsResult(int, @IntRange(from=0, to=65535) int, int, int) throws java.lang.RuntimeException;
-    method public final void onSendSmsResultError(int, @IntRange(from=0, to=65535) int, int, int, int) throws java.lang.RuntimeException;
-    method public final void onSendSmsResultSuccess(int, @IntRange(from=0, to=65535) int) throws java.lang.RuntimeException;
-    method public final void onSmsReceived(int, String, byte[]) throws java.lang.RuntimeException;
-    method @Deprecated public final void onSmsStatusReportReceived(int, @IntRange(from=0, to=65535) int, String, byte[]) throws java.lang.RuntimeException;
-    method public final void onSmsStatusReportReceived(int, String, byte[]) throws java.lang.RuntimeException;
-    method public void sendSms(int, @IntRange(from=0, to=65535) int, String, String, boolean, byte[]);
-    field public static final int DELIVER_STATUS_ERROR_GENERIC = 2; // 0x2
-    field public static final int DELIVER_STATUS_ERROR_NO_MEMORY = 3; // 0x3
-    field public static final int DELIVER_STATUS_ERROR_REQUEST_NOT_SUPPORTED = 4; // 0x4
-    field public static final int DELIVER_STATUS_OK = 1; // 0x1
-    field public static final int RESULT_NO_NETWORK_ERROR = -1; // 0xffffffff
-    field public static final int SEND_STATUS_ERROR = 2; // 0x2
-    field public static final int SEND_STATUS_ERROR_FALLBACK = 4; // 0x4
-    field public static final int SEND_STATUS_ERROR_RETRY = 3; // 0x3
-    field public static final int SEND_STATUS_OK = 1; // 0x1
-    field public static final int STATUS_REPORT_STATUS_ERROR = 2; // 0x2
-    field public static final int STATUS_REPORT_STATUS_OK = 1; // 0x1
-  }
-
-  public class ImsUtImplBase {
-    ctor public ImsUtImplBase();
-    method public void close();
-    method public int queryCallBarring(int);
-    method public int queryCallBarringForServiceClass(int, int);
-    method public int queryCallForward(int, String);
-    method public int queryCallWaiting();
-    method public int queryClip();
-    method public int queryClir();
-    method public int queryColp();
-    method public int queryColr();
-    method public void setListener(android.telephony.ims.ImsUtListener);
-    method public int transact(android.os.Bundle);
-    method public int updateCallBarring(int, int, String[]);
-    method public int updateCallBarringForServiceClass(int, int, String[], int);
-    method public int updateCallForward(int, int, String, int, int);
-    method public int updateCallWaiting(boolean, int);
-    method public int updateClip(boolean);
-    method public int updateClir(int);
-    method public int updateColp(boolean);
-    method public int updateColr(int);
-  }
-
-}
-
-package android.telephony.mbms {
-
-  public static class DownloadRequest.Builder {
-    method public android.telephony.mbms.DownloadRequest.Builder setServiceId(String);
-  }
-
-  public final class FileInfo implements android.os.Parcelable {
-    ctor public FileInfo(android.net.Uri, String);
-  }
-
-  public final class FileServiceInfo extends android.telephony.mbms.ServiceInfo implements android.os.Parcelable {
-    ctor public FileServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date, java.util.List<android.telephony.mbms.FileInfo>);
-  }
-
-  public final class StreamingServiceInfo extends android.telephony.mbms.ServiceInfo implements android.os.Parcelable {
-    ctor public StreamingServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date);
-  }
-
-  public final class UriPathPair implements android.os.Parcelable {
-    method public int describeContents();
-    method public android.net.Uri getContentUri();
-    method public android.net.Uri getFilePathUri();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.mbms.UriPathPair> CREATOR;
-  }
-
-}
-
-package android.telephony.mbms.vendor {
-
-  public class MbmsDownloadServiceBase extends android.os.Binder implements android.os.IInterface {
-    ctor public MbmsDownloadServiceBase();
-    method public int addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) throws android.os.RemoteException;
-    method public int addServiceAnnouncement(int, @NonNull byte[]);
-    method public int addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) throws android.os.RemoteException;
-    method public android.os.IBinder asBinder();
-    method public int cancelDownload(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException;
-    method public void dispose(int) throws android.os.RemoteException;
-    method public int download(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException;
-    method public int initialize(int, android.telephony.mbms.MbmsDownloadSessionCallback) throws android.os.RemoteException;
-    method @NonNull public java.util.List<android.telephony.mbms.DownloadRequest> listPendingDownloads(int) throws android.os.RemoteException;
-    method public void onAppCallbackDied(int, int);
-    method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException;
-    method public int removeProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) throws android.os.RemoteException;
-    method public int removeStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) throws android.os.RemoteException;
-    method public int requestDownloadState(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo) throws android.os.RemoteException;
-    method public int requestUpdateFileServices(int, java.util.List<java.lang.String>) throws android.os.RemoteException;
-    method public int resetDownloadKnowledge(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException;
-    method public int setTempFileRootDirectory(int, String) throws android.os.RemoteException;
-  }
-
-  public class MbmsGroupCallServiceBase extends android.app.Service {
-    ctor public MbmsGroupCallServiceBase();
-    method public void dispose(int) throws android.os.RemoteException;
-    method public int initialize(@NonNull android.telephony.mbms.MbmsGroupCallSessionCallback, int) throws android.os.RemoteException;
-    method public void onAppCallbackDied(int, int);
-    method public android.os.IBinder onBind(android.content.Intent);
-    method public int startGroupCall(int, long, @NonNull java.util.List<java.lang.Integer>, @NonNull java.util.List<java.lang.Integer>, @NonNull android.telephony.mbms.GroupCallCallback);
-    method public void stopGroupCall(int, long);
-    method public void updateGroupCall(int, long, @NonNull java.util.List<java.lang.Integer>, @NonNull java.util.List<java.lang.Integer>);
-  }
-
-  public class MbmsStreamingServiceBase extends android.os.Binder implements android.os.IInterface {
-    ctor public MbmsStreamingServiceBase();
-    method public android.os.IBinder asBinder();
-    method public void dispose(int) throws android.os.RemoteException;
-    method @Nullable public android.net.Uri getPlaybackUri(int, String) throws android.os.RemoteException;
-    method public int initialize(android.telephony.mbms.MbmsStreamingSessionCallback, int) throws android.os.RemoteException;
-    method public void onAppCallbackDied(int, int);
-    method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException;
-    method public int requestUpdateStreamingServices(int, java.util.List<java.lang.String>) throws android.os.RemoteException;
-    method public int startStreaming(int, String, android.telephony.mbms.StreamingServiceCallback) throws android.os.RemoteException;
-    method public void stopStreaming(int, String) throws android.os.RemoteException;
-  }
-
-  public class VendorUtils {
-    ctor public VendorUtils();
-    method public static android.content.ComponentName getAppReceiverFromPackageName(android.content.Context, String);
-    field public static final String ACTION_CLEANUP = "android.telephony.mbms.action.CLEANUP";
-    field public static final String ACTION_DOWNLOAD_RESULT_INTERNAL = "android.telephony.mbms.action.DOWNLOAD_RESULT_INTERNAL";
-    field public static final String ACTION_FILE_DESCRIPTOR_REQUEST = "android.telephony.mbms.action.FILE_DESCRIPTOR_REQUEST";
-    field public static final String EXTRA_FD_COUNT = "android.telephony.mbms.extra.FD_COUNT";
-    field public static final String EXTRA_FINAL_URI = "android.telephony.mbms.extra.FINAL_URI";
-    field public static final String EXTRA_FREE_URI_LIST = "android.telephony.mbms.extra.FREE_URI_LIST";
-    field public static final String EXTRA_PAUSED_LIST = "android.telephony.mbms.extra.PAUSED_LIST";
-    field public static final String EXTRA_PAUSED_URI_LIST = "android.telephony.mbms.extra.PAUSED_URI_LIST";
-    field public static final String EXTRA_SERVICE_ID = "android.telephony.mbms.extra.SERVICE_ID";
-    field public static final String EXTRA_TEMP_FILES_IN_USE = "android.telephony.mbms.extra.TEMP_FILES_IN_USE";
-    field public static final String EXTRA_TEMP_FILE_ROOT = "android.telephony.mbms.extra.TEMP_FILE_ROOT";
-    field public static final String EXTRA_TEMP_LIST = "android.telephony.mbms.extra.TEMP_LIST";
-  }
-
 }
 
 package android.text {
@@ -5396,10 +2058,7 @@
   public final class AccessibilityManager {
     method public void addAccessibilityServicesStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener, @Nullable android.os.Handler);
     method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY) public java.util.List<java.lang.String> getAccessibilityShortcutTargets(int);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY) public void performAccessibilityShortcut();
-    method @RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY) public void registerSystemAction(@NonNull android.app.RemoteAction, int);
     method public void removeAccessibilityServicesStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY) public void unregisterSystemAction(int);
   }
 
   public static interface AccessibilityManager.AccessibilityServicesStateChangeListener {
@@ -5445,7 +2104,6 @@
   }
 
   public final class AutofillManager {
-    method public void setAugmentedAutofillWhitelist(@Nullable java.util.Set<java.lang.String>, @Nullable java.util.Set<android.content.ComponentName>);
     field public static final String DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES = "smart_suggestion_supported_modes";
     field public static final int FLAG_SMART_SUGGESTION_OFF = 0; // 0x0
     field public static final int FLAG_SMART_SUGGESTION_SYSTEM = 1; // 0x1
@@ -5456,42 +2114,7 @@
 
 package android.view.contentcapture {
 
-  public final class ContentCaptureContext implements android.os.Parcelable {
-    method @Nullable public android.content.ComponentName getActivityComponent();
-    method public int getDisplayId();
-    method public int getFlags();
-    method @Nullable public android.view.contentcapture.ContentCaptureSessionId getParentSessionId();
-    method public int getTaskId();
-    field public static final int FLAG_DISABLED_BY_APP = 1; // 0x1
-    field public static final int FLAG_DISABLED_BY_FLAG_SECURE = 2; // 0x2
-    field public static final int FLAG_RECONNECTED = 4; // 0x4
-  }
-
-  public final class ContentCaptureEvent implements android.os.Parcelable {
-    method public int describeContents();
-    method @Nullable public android.view.contentcapture.ContentCaptureContext getContentCaptureContext();
-    method public long getEventTime();
-    method @Nullable public android.view.autofill.AutofillId getId();
-    method @Nullable public java.util.List<android.view.autofill.AutofillId> getIds();
-    method @Nullable public android.graphics.Insets getInsets();
-    method @Nullable public CharSequence getText();
-    method public int getType();
-    method @Nullable public android.view.contentcapture.ViewNode getViewNode();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.view.contentcapture.ContentCaptureEvent> CREATOR;
-    field public static final int TYPE_CONTEXT_UPDATED = 6; // 0x6
-    field public static final int TYPE_SESSION_PAUSED = 8; // 0x8
-    field public static final int TYPE_SESSION_RESUMED = 7; // 0x7
-    field public static final int TYPE_VIEW_APPEARED = 1; // 0x1
-    field public static final int TYPE_VIEW_DISAPPEARED = 2; // 0x2
-    field public static final int TYPE_VIEW_INSETS_CHANGED = 9; // 0x9
-    field public static final int TYPE_VIEW_TEXT_CHANGED = 3; // 0x3
-    field public static final int TYPE_VIEW_TREE_APPEARED = 5; // 0x5
-    field public static final int TYPE_VIEW_TREE_APPEARING = 4; // 0x4
-  }
-
   public final class ContentCaptureManager {
-    method public boolean isContentCaptureFeatureEnabled();
     field public static final String DEVICE_CONFIG_PROPERTY_IDLE_FLUSH_FREQUENCY = "idle_flush_frequency";
     field public static final String DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL = "logging_level";
     field public static final String DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE = "log_history_size";
@@ -5504,7 +2127,6 @@
   }
 
   public final class ViewNode extends android.app.assist.AssistStructure.ViewNode {
-    method @Nullable public android.view.autofill.AutofillId getParentAutofillId();
     method @Nullable public static android.view.contentcapture.ViewNode readFromParcel(@NonNull android.os.Parcel);
     method public static void writeToParcel(@NonNull android.os.Parcel, @Nullable android.view.contentcapture.ViewNode, int);
   }
diff --git a/api/test-removed.txt b/api/test-removed.txt
index e47f6ed..d802177 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -1,10 +1 @@
 // Signature format: 2.0
-package android.app.prediction {
-
-  public static final class AppTarget.Builder {
-    method @Deprecated @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull String, @NonNull android.os.UserHandle);
-    method @Deprecated @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull android.content.pm.ShortcutInfo);
-  }
-
-}
-
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.h b/cmds/idmap2/idmap2d/Idmap2Service.h
index 1a44519..1d2090c 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.h
+++ b/cmds/idmap2/idmap2d/Idmap2Service.h
@@ -22,6 +22,8 @@
 #include <android-base/unique_fd.h>
 #include <binder/BinderService.h>
 
+#include <string>
+
 #include "android/os/BnIdmap2.h"
 
 namespace android::os {
diff --git a/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h b/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h
index ff45b14..bf31cbf 100644
--- a/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h
+++ b/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h
@@ -36,12 +36,11 @@
   void visit(const IdmapData::Header& header) override;
 
  private:
-  void Write(const void* value, size_t length);
   void Write8(uint8_t value);
   void Write16(uint16_t value);
   void Write32(uint32_t value);
   void WriteString256(const StringPiece& value);
-  void WriteString(const std::string& value);
+  void WriteString(const StringPiece& value);
   std::ostream& stream_;
 };
 
diff --git a/cmds/idmap2/include/idmap2/Idmap.h b/cmds/idmap2/include/idmap2/Idmap.h
index 0f05592..a35fad9 100644
--- a/cmds/idmap2/include/idmap2/Idmap.h
+++ b/cmds/idmap2/include/idmap2/Idmap.h
@@ -17,48 +17,45 @@
 /*
  * # idmap file format (current version)
  *
- * idmap             := header data*
- * header            := magic version target_crc overlay_crc target_path overlay_path debug_info
- * data              := data_header data_block*
- * data_header       := target_package_id types_count
- * data_block        := target_type overlay_type entry_count entry_offset entry*
- * overlay_path      := string256
- * target_path       := string256
- * debug_info        := string
- * string            := <uint32_t> <uint8_t>+ '\0'+
- * entry             := <uint32_t>
- * entry_count       := <uint16_t>
- * entry_offset      := <uint16_t>
- * magic             := <uint32_t>
- * overlay_crc       := <uint32_t>
- * overlay_type      := <uint16_t>
- * string256         := <uint8_t>[256]
- * target_crc        := <uint32_t>
- * target_package_id := <uint16_t>
- * target_type       := <uint16_t>
- * types_count       := <uint16_t>
- * version           := <uint32_t>
+ * idmap                      := header data*
+ * header                     := magic version target_crc overlay_crc fulfilled_policies
+ *                               enforce_overlayable target_path overlay_path debug_info
+ * data                       := data_header target_entry* target_inline_entry* overlay_entry*
+ *                               string_pool
+ * data_header                := target_package_id overlay_package_id padding(2) target_entry_count
+ *                               target_inline_entry_count overlay_entry_count string_pool_index
+ * target_entry               := target_id overlay_id
+ * target_inline_entry        := target_id Res_value::size padding(1) Res_value::type
+ *                               Res_value::value
+ * overlay_entry              := overlay_id target_id
  *
- *
- * # idmap file format changelog
- * ## v1
- * - Identical to idmap v1.
- *
- * ## v2
- * - Entries are no longer separated by type into type specific data blocks.
- * - Added overlay-indexed target resource id lookup capabilities.
- * - Target and overlay entries are stored as a sparse array in the data block. The target entries
- *   array maps from target resource id to overlay data type and value and the array is sorted by
- *   target resource id. The overlay entries array maps from overlay resource id to target resource
- *   id and the array is sorted by overlay resource id. It is important for both arrays to be sorted
- *   to allow for O(log(number_of_overlaid_resources)) performance when looking up resource
- *   mappings at runtime.
- * - Idmap can now encode a type and value to override a resource without needing a table entry.
- * - A string pool block is included to retrieve the value of strings that do not have a resource
- *   table entry.
- *
- * ## v3
- * - Add 'debug' block to IdmapHeader.
+ * debug_info                 := string
+ * enforce_overlayable        := <uint32_t>
+ * fulfilled_policies         := <uint32_t>
+ * magic                      := <uint32_t>
+ * overlay_crc                := <uint32_t>
+ * overlay_entry_count        := <uint32_t>
+ * overlay_id                 := <uint32_t>
+ * overlay_package_id         := <uint8_t>
+ * overlay_path               := string256
+ * padding(n)                 := <uint8_t>[n]
+ * Res_value::size            := <uint16_t>
+ * Res_value::type            := <uint8_t>
+ * Res_value::value           := <uint32_t>
+ * string                     := <uint32_t> <uint8_t>+ padding(n)
+ * string256                  := <uint8_t>[256]
+ * string_pool                := string
+ * string_pool_index          := <uint32_t>
+ * string_pool_length         := <uint32_t>
+ * target_crc                 := <uint32_t>
+ * target_entry_count         := <uint32_t>
+ * target_inline_entry_count  := <uint32_t>
+ * target_id                  := <uint32_t>
+ * target_package_id          := <uint8_t>
+ * target_path                := string256
+ * value_type                 := <uint8_t>
+ * value_data                 := <uint32_t>
+ * version                    := <uint32_t>
  */
 
 #ifndef IDMAP2_INCLUDE_IDMAP2_IDMAP_H_
@@ -183,6 +180,10 @@
       return target_entry_count;
     }
 
+    inline uint32_t GetTargetInlineEntryCount() const {
+      return target_entry_inline_count;
+    }
+
     inline uint32_t GetOverlayEntryCount() const {
       return overlay_entry_count;
     }
@@ -191,19 +192,15 @@
       return string_pool_index_offset;
     }
 
-    inline uint32_t GetStringPoolLength() const {
-      return string_pool_len;
-    }
-
     void accept(Visitor* v) const;
 
    private:
     PackageId target_package_id_;
     PackageId overlay_package_id_;
     uint32_t target_entry_count;
+    uint32_t target_entry_inline_count;
     uint32_t overlay_entry_count;
     uint32_t string_pool_index_offset;
-    uint32_t string_pool_len;
     Header() = default;
 
     friend Idmap;
@@ -213,8 +210,12 @@
 
   struct TargetEntry {
     ResourceId target_id;
-    TargetValue::DataType data_type;
-    TargetValue::DataValue data_value;
+    ResourceId overlay_id;
+  };
+
+  struct TargetInlineEntry {
+    ResourceId target_id;
+    TargetValue value;
   };
 
   struct OverlayEntry {
@@ -227,20 +228,24 @@
   static Result<std::unique_ptr<const IdmapData>> FromResourceMapping(
       const ResourceMapping& resource_mapping);
 
-  inline const std::unique_ptr<const Header>& GetHeader() const {
+  const std::unique_ptr<const Header>& GetHeader() const {
     return header_;
   }
 
-  inline const std::vector<TargetEntry>& GetTargetEntries() const {
+  const std::vector<TargetEntry>& GetTargetEntries() const {
     return target_entries_;
   }
 
-  inline const std::vector<OverlayEntry>& GetOverlayEntries() const {
+  const std::vector<TargetInlineEntry>& GetTargetInlineEntries() const {
+    return target_inline_entries_;
+  }
+
+  const std::vector<OverlayEntry>& GetOverlayEntries() const {
     return overlay_entries_;
   }
 
-  inline const void* GetStringPoolData() const {
-    return string_pool_.get();
+  const std::string& GetStringPoolData() const {
+    return string_pool_data_;
   }
 
   void accept(Visitor* v) const;
@@ -251,8 +256,9 @@
 
   std::unique_ptr<const Header> header_;
   std::vector<TargetEntry> target_entries_;
+  std::vector<TargetInlineEntry> target_inline_entries_;
   std::vector<OverlayEntry> overlay_entries_;
-  std::unique_ptr<uint8_t[]> string_pool_;
+  std::string string_pool_data_;
 
   friend Idmap;
   DISALLOW_COPY_AND_ASSIGN(IdmapData);
@@ -304,6 +310,10 @@
   virtual void visit(const IdmapData::Header& header) = 0;
 };
 
+inline size_t CalculatePadding(size_t data_length) {
+  return (4 - (data_length % 4)) % 4;
+}
+
 }  // namespace android::idmap2
 
 #endif  // IDMAP2_INCLUDE_IDMAP2_IDMAP_H_
diff --git a/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h b/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
index 5dcf217..2b4c761 100644
--- a/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
+++ b/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
@@ -41,8 +41,9 @@
 
  private:
   std::ostream& stream_;
-  std::unique_ptr<const ApkAssets> target_apk_;
   AssetManager2 target_am_;
+  AssetManager2 overlay_am_;
+  std::vector<std::unique_ptr<const ApkAssets>> apk_assets_;
 };
 
 }  // namespace idmap2
diff --git a/cmds/idmap2/include/idmap2/RawPrintVisitor.h b/cmds/idmap2/include/idmap2/RawPrintVisitor.h
index 92c1864..58edc99 100644
--- a/cmds/idmap2/include/idmap2/RawPrintVisitor.h
+++ b/cmds/idmap2/include/idmap2/RawPrintVisitor.h
@@ -45,11 +45,9 @@
   void print(uint16_t value, const char* fmt, ...);
   void print(uint32_t value, const char* fmt, ...);
   void print(const std::string& value, size_t encoded_size, const char* fmt, ...);
-  void print_raw(uint32_t length, const char* fmt, ...);
 
   std::ostream& stream_;
-  std::unique_ptr<const ApkAssets> target_apk_;
-  std::unique_ptr<const ApkAssets> overlay_apk_;
+  std::vector<std::unique_ptr<const ApkAssets>> apk_assets_;
   AssetManager2 target_am_;
   AssetManager2 overlay_am_;
   size_t offset_;
diff --git a/cmds/idmap2/include/idmap2/ResourceMapping.h b/cmds/idmap2/include/idmap2/ResourceMapping.h
index 5869409..0a58ec4 100644
--- a/cmds/idmap2/include/idmap2/ResourceMapping.h
+++ b/cmds/idmap2/include/idmap2/ResourceMapping.h
@@ -41,7 +41,7 @@
   DataValue data_value;
 };
 
-using TargetResourceMap = std::map<ResourceId, TargetValue>;
+using TargetResourceMap = std::map<ResourceId, std::variant<ResourceId, TargetValue>>;
 using OverlayResourceMap = std::map<ResourceId, ResourceId>;
 
 class ResourceMapping {
@@ -56,7 +56,7 @@
                                                bool enforce_overlayable, LogInfo& log_info);
 
   // Retrieves the mapping of target resource id to overlay value.
-  inline TargetResourceMap GetTargetToOverlayMap() const {
+  inline const TargetResourceMap& GetTargetToOverlayMap() const {
     return target_map_;
   }
 
@@ -81,19 +81,24 @@
   }
 
   // Retrieves the raw string pool data from the xml referenced in android:resourcesMap.
-  inline const std::pair<const uint8_t*, uint32_t> GetStringPoolData() const {
-    return std::make_pair(string_pool_data_.get(), string_pool_data_length_);
+  inline const StringPiece GetStringPoolData() const {
+    return StringPiece(reinterpret_cast<const char*>(string_pool_data_.get()),
+                       string_pool_data_length_);
   }
 
  private:
   ResourceMapping() = default;
 
-  // Apps a mapping of target resource id to the type and value of the data that overlays the
-  // target resource. The data_type is the runtime format of the data value (see
-  // Res_value::dataType). If rewrite_overlay_reference is `true` then references to an overlay
+  // Maps a target resource id to an overlay resource id.
+  // If rewrite_overlay_reference is `true` then references to the overlay
   // resource should appear as a reference to its corresponding target resource at runtime.
+  Result<Unit> AddMapping(ResourceId target_resource, ResourceId overlay_resource,
+                          bool rewrite_overlay_reference);
+
+  // Maps a target resource id to a data type and value combination.
+  // The `data_type` is the runtime format of the data value (see Res_value::dataType).
   Result<Unit> AddMapping(ResourceId target_resource, TargetValue::DataType data_type,
-                          TargetValue::DataValue data_value, bool rewrite_overlay_reference);
+                          TargetValue::DataValue data_value);
 
   // Removes the overlay value mapping for the target resource.
   void RemoveMapping(ResourceId target_resource);
diff --git a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
index 255212a..726f6c5 100644
--- a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
+++ b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
@@ -24,10 +24,6 @@
 
 namespace android::idmap2 {
 
-void BinaryStreamVisitor::Write(const void* value, size_t length) {
-  stream_.write(reinterpret_cast<const char*>(value), length);
-}
-
 void BinaryStreamVisitor::Write8(uint8_t value) {
   stream_.write(reinterpret_cast<char*>(&value), sizeof(uint8_t));
 }
@@ -49,11 +45,11 @@
   stream_.write(buf, sizeof(buf));
 }
 
-void BinaryStreamVisitor::WriteString(const std::string& value) {
-  // pad with null to nearest word boundary; include at least one terminating null
-  size_t padding_size = 4 - (value.size() % 4);
-  Write32(value.size() + padding_size);
-  stream_.write(value.c_str(), value.size());
+void BinaryStreamVisitor::WriteString(const StringPiece& value) {
+  // pad with null to nearest word boundary;
+  size_t padding_size = CalculatePadding(value.size());
+  Write32(value.size());
+  stream_.write(value.data(), value.size());
   stream_.write("\0\0\0\0", padding_size);
 }
 
@@ -67,7 +63,7 @@
   Write32(header.GetTargetCrc());
   Write32(header.GetOverlayCrc());
   Write32(header.GetFulfilledPolicies());
-  Write8(static_cast<uint8_t>(header.GetEnforceOverlayable()));
+  Write32(static_cast<uint8_t>(header.GetEnforceOverlayable()));
   WriteString256(header.GetTargetPath());
   WriteString256(header.GetOverlayPath());
   WriteString(header.GetDebugInfo());
@@ -76,8 +72,16 @@
 void BinaryStreamVisitor::visit(const IdmapData& data) {
   for (const auto& target_entry : data.GetTargetEntries()) {
     Write32(target_entry.target_id);
-    Write8(target_entry.data_type);
-    Write32(target_entry.data_value);
+    Write32(target_entry.overlay_id);
+  }
+
+  static constexpr uint16_t kValueSize = 8U;
+  for (const auto& target_entry : data.GetTargetInlineEntries()) {
+    Write32(target_entry.target_id);
+    Write16(kValueSize);
+    Write8(0U);  // padding
+    Write8(target_entry.value.data_type);
+    Write32(target_entry.value.data_value);
   }
 
   for (const auto& overlay_entry : data.GetOverlayEntries()) {
@@ -85,16 +89,18 @@
     Write32(overlay_entry.target_id);
   }
 
-  Write(data.GetStringPoolData(), data.GetHeader()->GetStringPoolLength());
+  WriteString(data.GetStringPoolData());
 }
 
 void BinaryStreamVisitor::visit(const IdmapData::Header& header) {
   Write8(header.GetTargetPackageId());
   Write8(header.GetOverlayPackageId());
+  Write8(0U);  // padding
+  Write8(0U);  // padding
   Write32(header.GetTargetEntryCount());
+  Write32(header.GetTargetInlineEntryCount());
   Write32(header.GetOverlayEntryCount());
   Write32(header.GetStringPoolIndexOffset());
-  Write32(header.GetStringPoolLength());
 }
 
 }  // namespace android::idmap2
diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp
index 23c25a7..1129413 100644
--- a/cmds/idmap2/libidmap2/Idmap.cpp
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -51,19 +51,19 @@
   return false;
 }
 
-bool WARN_UNUSED Read32(std::istream& stream, uint32_t* out) {
-  uint32_t value;
-  if (stream.read(reinterpret_cast<char*>(&value), sizeof(uint32_t))) {
-    *out = dtohl(value);
+bool WARN_UNUSED Read16(std::istream& stream, uint16_t* out) {
+  uint16_t value;
+  if (stream.read(reinterpret_cast<char*>(&value), sizeof(uint16_t))) {
+    *out = dtohs(value);
     return true;
   }
   return false;
 }
 
-bool WARN_UNUSED ReadBuffer(std::istream& stream, std::unique_ptr<uint8_t[]>* out, size_t length) {
-  auto buffer = std::unique_ptr<uint8_t[]>(new uint8_t[length]);
-  if (stream.read(reinterpret_cast<char*>(buffer.get()), length)) {
-    *out = std::move(buffer);
+bool WARN_UNUSED Read32(std::istream& stream, uint32_t* out) {
+  uint32_t value;
+  if (stream.read(reinterpret_cast<char*>(&value), sizeof(uint32_t))) {
+    *out = dtohl(value);
     return true;
   }
   return false;
@@ -95,8 +95,11 @@
   if (!stream.read(buf.data(), size)) {
     return Error("failed to read string of size %u", size);
   }
-  // buf is guaranteed to be null terminated (with enough nulls to end on a word boundary)
-  buf.resize(strlen(buf.c_str()));
+  uint32_t padding_size = CalculatePadding(size);
+  std::string padding(padding_size, '\0');
+  if (!stream.read(padding.data(), padding_size)) {
+    return Error("failed to read string padding of size %u", padding_size);
+  }
   return buf;
 }
 
@@ -112,16 +115,16 @@
 
 std::unique_ptr<const IdmapHeader> IdmapHeader::FromBinaryStream(std::istream& stream) {
   std::unique_ptr<IdmapHeader> idmap_header(new IdmapHeader());
-  uint8_t enforce_overlayable;
+  uint32_t enforce_overlayable;
   if (!Read32(stream, &idmap_header->magic_) || !Read32(stream, &idmap_header->version_) ||
       !Read32(stream, &idmap_header->target_crc_) || !Read32(stream, &idmap_header->overlay_crc_) ||
-      !Read32(stream, &idmap_header->fulfilled_policies_) || !Read8(stream, &enforce_overlayable) ||
-      !ReadString256(stream, idmap_header->target_path_) ||
+      !Read32(stream, &idmap_header->fulfilled_policies_) ||
+      !Read32(stream, &enforce_overlayable) || !ReadString256(stream, idmap_header->target_path_) ||
       !ReadString256(stream, idmap_header->overlay_path_)) {
     return nullptr;
   }
 
-  idmap_header->enforce_overlayable_ = static_cast<bool>(enforce_overlayable);
+  idmap_header->enforce_overlayable_ = enforce_overlayable != 0U;
 
   auto debug_str = ReadString(stream);
   if (!debug_str) {
@@ -207,12 +210,13 @@
 std::unique_ptr<const IdmapData::Header> IdmapData::Header::FromBinaryStream(std::istream& stream) {
   std::unique_ptr<IdmapData::Header> idmap_data_header(new IdmapData::Header());
 
+  uint8_t padding;
   if (!Read8(stream, &idmap_data_header->target_package_id_) ||
-      !Read8(stream, &idmap_data_header->overlay_package_id_) ||
-      !Read32(stream, &idmap_data_header->target_entry_count) ||
+      !Read8(stream, &idmap_data_header->overlay_package_id_) || !Read8(stream, &padding) ||
+      !Read8(stream, &padding) || !Read32(stream, &idmap_data_header->target_entry_count) ||
+      !Read32(stream, &idmap_data_header->target_entry_inline_count) ||
       !Read32(stream, &idmap_data_header->overlay_entry_count) ||
-      !Read32(stream, &idmap_data_header->string_pool_index_offset) ||
-      !Read32(stream, &idmap_data_header->string_pool_len)) {
+      !Read32(stream, &idmap_data_header->string_pool_index_offset)) {
     return nullptr;
   }
 
@@ -225,14 +229,27 @@
   if (!data->header_) {
     return nullptr;
   }
+
   // Read the mapping of target resource id to overlay resource value.
   for (size_t i = 0; i < data->header_->GetTargetEntryCount(); i++) {
     TargetEntry target_entry{};
-    if (!Read32(stream, &target_entry.target_id) || !Read8(stream, &target_entry.data_type) ||
-        !Read32(stream, &target_entry.data_value)) {
+    if (!Read32(stream, &target_entry.target_id) || !Read32(stream, &target_entry.overlay_id)) {
       return nullptr;
     }
-    data->target_entries_.emplace_back(target_entry);
+    data->target_entries_.push_back(target_entry);
+  }
+
+  // Read the mapping of target resource id to inline overlay values.
+  uint8_t unused1;
+  uint16_t unused2;
+  for (size_t i = 0; i < data->header_->GetTargetInlineEntryCount(); i++) {
+    TargetInlineEntry target_entry{};
+    if (!Read32(stream, &target_entry.target_id) || !Read16(stream, &unused2) ||
+        !Read8(stream, &unused1) || !Read8(stream, &target_entry.value.data_type) ||
+        !Read32(stream, &target_entry.value.data_value)) {
+      return nullptr;
+    }
+    data->target_inline_entries_.push_back(target_entry);
   }
 
   // Read the mapping of overlay resource id to target resource id.
@@ -245,9 +262,11 @@
   }
 
   // Read raw string pool bytes.
-  if (!ReadBuffer(stream, &data->string_pool_, data->header_->string_pool_len)) {
+  auto string_pool_data = ReadString(stream);
+  if (!string_pool_data) {
     return nullptr;
   }
+  data->string_pool_data_ = std::move(*string_pool_data);
 
   return std::move(data);
 }
@@ -290,27 +309,28 @@
   }
 
   std::unique_ptr<IdmapData> data(new IdmapData());
-  for (const auto& mappings : resource_mapping.GetTargetToOverlayMap()) {
-    data->target_entries_.emplace_back(IdmapData::TargetEntry{
-        mappings.first, mappings.second.data_type, mappings.second.data_value});
+  data->string_pool_data_ = resource_mapping.GetStringPoolData().to_string();
+  for (const auto& mapping : resource_mapping.GetTargetToOverlayMap()) {
+    if (auto overlay_resource = std::get_if<ResourceId>(&mapping.second)) {
+      data->target_entries_.push_back({mapping.first, *overlay_resource});
+    } else {
+      data->target_inline_entries_.push_back(
+          {mapping.first, std::get<TargetValue>(mapping.second)});
+    }
   }
 
-  for (const auto& mappings : resource_mapping.GetOverlayToTargetMap()) {
-    data->overlay_entries_.emplace_back(IdmapData::OverlayEntry{mappings.first, mappings.second});
+  for (const auto& mapping : resource_mapping.GetOverlayToTargetMap()) {
+    data->overlay_entries_.emplace_back(IdmapData::OverlayEntry{mapping.first, mapping.second});
   }
 
   std::unique_ptr<IdmapData::Header> data_header(new IdmapData::Header());
   data_header->target_package_id_ = resource_mapping.GetTargetPackageId();
   data_header->overlay_package_id_ = resource_mapping.GetOverlayPackageId();
   data_header->target_entry_count = static_cast<uint32_t>(data->target_entries_.size());
+  data_header->target_entry_inline_count =
+      static_cast<uint32_t>(data->target_inline_entries_.size());
   data_header->overlay_entry_count = static_cast<uint32_t>(data->overlay_entries_.size());
   data_header->string_pool_index_offset = resource_mapping.GetStringPoolOffset();
-
-  const auto string_pool_data = resource_mapping.GetStringPoolData();
-  data_header->string_pool_len = string_pool_data.second;
-  data->string_pool_ = std::unique_ptr<uint8_t[]>(new uint8_t[data_header->string_pool_len]);
-  memcpy(data->string_pool_.get(), string_pool_data.first, data_header->string_pool_len);
-
   data->header_ = std::move(data_header);
   return {std::move(data)};
 }
diff --git a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
index 63ee8a6..a93202a 100644
--- a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
+++ b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
@@ -38,6 +38,7 @@
   stream_ << "Paths:" << std::endl
           << TAB "target apk path  : " << header.GetTargetPath() << std::endl
           << TAB "overlay apk path : " << header.GetOverlayPath() << std::endl;
+
   const std::string& debug = header.GetDebugInfo();
   if (!debug.empty()) {
     std::istringstream debug_stream(debug);
@@ -48,10 +49,16 @@
     }
   }
 
-  target_apk_ = ApkAssets::Load(header.GetTargetPath().to_string());
-  if (target_apk_) {
+  if (auto target_apk_ = ApkAssets::Load(header.GetTargetPath().to_string())) {
     target_am_.SetApkAssets({target_apk_.get()});
+    apk_assets_.push_back(std::move(target_apk_));
   }
+
+  if (auto overlay_apk = ApkAssets::Load(header.GetOverlayPath().to_string())) {
+    overlay_am_.SetApkAssets({overlay_apk.get()});
+    apk_assets_.push_back(std::move(overlay_apk));
+  }
+
   stream_ << "Mapping:" << std::endl;
 }
 
@@ -59,34 +66,56 @@
 }
 
 void PrettyPrintVisitor::visit(const IdmapData& data) {
+  static constexpr const char* kUnknownResourceName = "???";
+
   const bool target_package_loaded = !target_am_.GetApkAssets().empty();
-  const ResStringPool string_pool(data.GetStringPoolData(),
-                                  data.GetHeader()->GetStringPoolLength());
+  const bool overlay_package_loaded = !overlay_am_.GetApkAssets().empty();
+
+  const ResStringPool string_pool(data.GetStringPoolData().data(), data.GetStringPoolData().size());
   const size_t string_pool_offset = data.GetHeader()->GetStringPoolIndexOffset();
 
-  for (auto& target_entry : data.GetTargetEntries()) {
-    stream_ << TAB << base::StringPrintf("0x%08x ->", target_entry.target_id);
-
-    if (target_entry.data_type != Res_value::TYPE_REFERENCE &&
-        target_entry.data_type != Res_value::TYPE_DYNAMIC_REFERENCE) {
-      stream_ << " " << utils::DataTypeToString(target_entry.data_type);
-    }
-
-    if (target_entry.data_type == Res_value::TYPE_STRING) {
-      stream_ << " \""
-              << string_pool.string8ObjectAt(target_entry.data_value - string_pool_offset).c_str()
-              << "\"";
-    } else {
-      stream_ << " " << base::StringPrintf("0x%08x", target_entry.data_value);
-    }
-
+  for (const auto& target_entry : data.GetTargetEntries()) {
+    std::string target_name = kUnknownResourceName;
     if (target_package_loaded) {
-      Result<std::string> name = utils::ResToTypeEntryName(target_am_, target_entry.target_id);
-      if (name) {
-        stream_ << " " << *name;
+      if (auto name = utils::ResToTypeEntryName(target_am_, target_entry.target_id)) {
+        target_name = *name;
       }
     }
-    stream_ << std::endl;
+
+    std::string overlay_name = kUnknownResourceName;
+    if (overlay_package_loaded) {
+      if (auto name = utils::ResToTypeEntryName(overlay_am_, target_entry.overlay_id)) {
+        overlay_name = *name;
+      }
+    }
+
+    stream_ << TAB
+            << base::StringPrintf("0x%08x -> 0x%08x (%s -> %s)", target_entry.target_id,
+                                  target_entry.overlay_id, target_name.c_str(),
+                                  overlay_name.c_str())
+            << std::endl;
+  }
+
+  for (auto& target_entry : data.GetTargetInlineEntries()) {
+    stream_ << TAB << base::StringPrintf("0x%08x -> ", target_entry.target_id)
+            << utils::DataTypeToString(target_entry.value.data_type);
+
+    size_t unused;
+    if (target_entry.value.data_type == Res_value::TYPE_STRING) {
+      auto str = string_pool.stringAt(target_entry.value.data_value - string_pool_offset, &unused);
+      stream_ << " \"" << StringPiece16(str) << "\"";
+    } else {
+      stream_ << " " << base::StringPrintf("0x%08x", target_entry.value.data_value);
+    }
+
+    std::string target_name = kUnknownResourceName;
+    if (target_package_loaded) {
+      if (auto name = utils::ResToTypeEntryName(target_am_, target_entry.target_id)) {
+        target_name = *name;
+      }
+    }
+
+    stream_ << " (" << target_name << ")" << std::endl;
   }
 }
 
diff --git a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
index 3f62a2a..82f5d26 100644
--- a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
+++ b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
@@ -30,15 +30,6 @@
 using android::ApkAssets;
 using android::idmap2::policy::PoliciesToDebugString;
 
-namespace {
-
-size_t StringSizeWhenEncoded(const std::string& s) {
-  size_t null_bytes = 4 - (s.size() % 4);
-  return sizeof(uint32_t) + s.size() + null_bytes;
-}
-
-}  // namespace
-
 namespace android::idmap2 {
 
 void RawPrintVisitor::visit(const Idmap& idmap ATTRIBUTE_UNUSED) {
@@ -51,19 +42,24 @@
   print(header.GetOverlayCrc(), "overlay crc");
   print(header.GetFulfilledPolicies(), "fulfilled policies: %s",
         PoliciesToDebugString(header.GetFulfilledPolicies()).c_str());
-  print(static_cast<uint8_t>(header.GetEnforceOverlayable()), "enforce overlayable");
+  print(static_cast<uint32_t>(header.GetEnforceOverlayable()), "enforce overlayable");
   print(header.GetTargetPath().to_string(), kIdmapStringLength, "target path");
   print(header.GetOverlayPath().to_string(), kIdmapStringLength, "overlay path");
-  print("...", StringSizeWhenEncoded(header.GetDebugInfo()), "debug info");
 
-  target_apk_ = ApkAssets::Load(header.GetTargetPath().to_string());
+  uint32_t debug_info_size = header.GetDebugInfo().size();
+  print(debug_info_size, "debug info size");
+  print("...", debug_info_size + CalculatePadding(debug_info_size), "debug info");
+
+  auto target_apk_ = ApkAssets::Load(header.GetTargetPath().to_string());
   if (target_apk_) {
     target_am_.SetApkAssets({target_apk_.get()});
+    apk_assets_.push_back(std::move(target_apk_));
   }
 
-  overlay_apk_ = ApkAssets::Load(header.GetOverlayPath().to_string());
+  auto overlay_apk_ = ApkAssets::Load(header.GetOverlayPath().to_string());
   if (overlay_apk_) {
     overlay_am_.SetApkAssets({overlay_apk_.get()});
+    apk_assets_.push_back(std::move(overlay_apk_));
   }
 }
 
@@ -82,18 +78,44 @@
       print(target_entry.target_id, "target id");
     }
 
-    print(target_entry.data_type, "type: %s",
-          utils::DataTypeToString(target_entry.data_type).data());
-
     Result<std::string> overlay_name(Error(""));
-    if (overlay_package_loaded && (target_entry.data_type == Res_value::TYPE_REFERENCE ||
-                                   target_entry.data_type == Res_value::TYPE_DYNAMIC_REFERENCE)) {
-      overlay_name = utils::ResToTypeEntryName(overlay_am_, target_entry.data_value);
+    if (overlay_package_loaded) {
+      overlay_name = utils::ResToTypeEntryName(overlay_am_, target_entry.overlay_id);
     }
     if (overlay_name) {
-      print(target_entry.data_value, "value: %s", overlay_name->c_str());
+      print(target_entry.overlay_id, "overlay id: %s", overlay_name->c_str());
     } else {
-      print(target_entry.data_value, "value");
+      print(target_entry.overlay_id, "overlay id");
+    }
+  }
+
+  for (auto& target_entry : data.GetTargetInlineEntries()) {
+    Result<std::string> target_name(Error(""));
+    if (target_package_loaded) {
+      target_name = utils::ResToTypeEntryName(target_am_, target_entry.target_id);
+    }
+    if (target_name) {
+      print(target_entry.target_id, "target id: %s", target_name->c_str());
+    } else {
+      print(target_entry.target_id, "target id");
+    }
+
+    print("...", sizeof(Res_value::size) + sizeof(Res_value::res0), "padding");
+
+    print(target_entry.value.data_type, "type: %s",
+          utils::DataTypeToString(target_entry.value.data_type).data());
+
+    Result<std::string> overlay_name(Error(""));
+    if (overlay_package_loaded &&
+        (target_entry.value.data_value == Res_value::TYPE_REFERENCE ||
+         target_entry.value.data_value == Res_value::TYPE_DYNAMIC_REFERENCE)) {
+      overlay_name = utils::ResToTypeEntryName(overlay_am_, target_entry.value.data_value);
+    }
+
+    if (overlay_name) {
+      print(target_entry.value.data_value, "data: %s", overlay_name->c_str());
+    } else {
+      print(target_entry.value.data_value, "data");
     }
   }
 
@@ -121,19 +143,19 @@
     }
   }
 
-  const size_t string_pool_length = data.GetHeader()->GetStringPoolLength();
-  if (string_pool_length > 0) {
-    print_raw(string_pool_length, "%zu raw string pool bytes", string_pool_length);
-  }
+  uint32_t string_pool_size = data.GetStringPoolData().size();
+  print(string_pool_size, "string pool size");
+  print("...", string_pool_size + CalculatePadding(string_pool_size), "string pool");
 }
 
 void RawPrintVisitor::visit(const IdmapData::Header& header) {
   print(header.GetTargetPackageId(), "target package id");
   print(header.GetOverlayPackageId(), "overlay package id");
+  print("...", sizeof(Idmap_data_header::p0), "padding");
   print(header.GetTargetEntryCount(), "target entry count");
+  print(header.GetTargetInlineEntryCount(), "target inline entry count");
   print(header.GetOverlayEntryCount(), "overlay entry count");
   print(header.GetStringPoolIndexOffset(), "string pool index offset");
-  print(header.GetStringPoolLength(), "string pool byte length");
 }
 
 // NOLINTNEXTLINE(cert-dcl50-cpp)
@@ -190,17 +212,4 @@
   offset_ += encoded_size;
 }
 
-// NOLINTNEXTLINE(cert-dcl50-cpp)
-void RawPrintVisitor::print_raw(uint32_t length, const char* fmt, ...) {
-  va_list ap;
-  va_start(ap, fmt);
-  std::string comment;
-  base::StringAppendV(&comment, fmt, ap);
-  va_end(ap);
-
-  stream_ << base::StringPrintf("%08zx: ", offset_) << "........  " << comment << std::endl;
-
-  offset_ += length;
-}
-
 }  // namespace android::idmap2
diff --git a/cmds/idmap2/libidmap2/ResourceMapping.cpp b/cmds/idmap2/libidmap2/ResourceMapping.cpp
index fd8b4eb..31f1c16 100644
--- a/cmds/idmap2/libidmap2/ResourceMapping.cpp
+++ b/cmds/idmap2/libidmap2/ResourceMapping.cpp
@@ -71,9 +71,9 @@
   if (!target_package.DefinesOverlayable()) {
     return (sDefaultPolicies & fulfilled_policies) != 0
                ? Result<Unit>({})
-               : Error(
-                     "overlay must be preinstalled or signed with the same signature as the "
-                     "target");
+               : Error("overlay must be preinstalled, signed with the same signature as the target,"
+                       " or signed with the same signature as the package referenced through"
+                       " <overlay-config-signature>.");
   }
 
   const OverlayableInfo* overlayable_info = target_package.GetOverlayableInfo(target_resource);
@@ -205,19 +205,14 @@
       overlay_resource->data += string_pool_offset;
     }
 
-    // Only rewrite resources defined within the overlay package to their corresponding target
-    // resource ids at runtime.
-    bool rewrite_overlay_reference =
-        IsReference(overlay_resource->dataType)
-            ? overlay_package_id == EXTRACT_PACKAGE(overlay_resource->data)
-            : false;
-
-    if (rewrite_overlay_reference) {
-      overlay_resource->dataType = Res_value::TYPE_DYNAMIC_REFERENCE;
+    if (IsReference(overlay_resource->dataType)) {
+      // Only rewrite resources defined within the overlay package to their corresponding target
+      // resource ids at runtime.
+      bool rewrite_reference = overlay_package_id == EXTRACT_PACKAGE(overlay_resource->data);
+      resource_mapping.AddMapping(target_id, overlay_resource->data, rewrite_reference);
+    } else {
+      resource_mapping.AddMapping(target_id, overlay_resource->dataType, overlay_resource->data);
     }
-
-    resource_mapping.AddMapping(target_id, overlay_resource->dataType, overlay_resource->data,
-                                rewrite_overlay_reference);
   }
 
   return resource_mapping;
@@ -246,9 +241,8 @@
 
     // Retrieve the compile-time resource id of the target resource.
     target_resource = REWRITE_PACKAGE(target_resource, target_package_id);
-
-    resource_mapping.AddMapping(target_resource, Res_value::TYPE_REFERENCE, overlay_resid,
-                                /* rewrite_overlay_reference */ false);
+    resource_mapping.AddMapping(target_resource, overlay_resid,
+                                false /* rewrite_overlay_reference */);
   }
 
   return resource_mapping;
@@ -396,9 +390,7 @@
   return map;
 }
 
-Result<Unit> ResourceMapping::AddMapping(ResourceId target_resource,
-                                         TargetValue::DataType data_type,
-                                         TargetValue::DataValue data_value,
+Result<Unit> ResourceMapping::AddMapping(ResourceId target_resource, ResourceId overlay_resource,
                                          bool rewrite_overlay_reference) {
   if (target_map_.find(target_resource) != target_map_.end()) {
     return Error(R"(target resource id "0x%08x" mapped to multiple values)", target_resource);
@@ -407,13 +399,26 @@
   // TODO(141485591): Ensure that the overlay type is compatible with the target type. If the
   // runtime types are not compatible, it could cause runtime crashes when the resource is resolved.
 
-  target_map_.insert(std::make_pair(target_resource, TargetValue{data_type, data_value}));
+  target_map_.insert(std::make_pair(target_resource, overlay_resource));
 
-  if (rewrite_overlay_reference && IsReference(data_type)) {
-    overlay_map_.insert(std::make_pair(data_value, target_resource));
+  if (rewrite_overlay_reference) {
+    overlay_map_.insert(std::make_pair(overlay_resource, target_resource));
+  }
+  return Unit{};
+}
+
+Result<Unit> ResourceMapping::AddMapping(ResourceId target_resource,
+                                         TargetValue::DataType data_type,
+                                         TargetValue::DataValue data_value) {
+  if (target_map_.find(target_resource) != target_map_.end()) {
+    return Error(R"(target resource id "0x%08x" mapped to multiple values)", target_resource);
   }
 
-  return Result<Unit>({});
+  // TODO(141485591): Ensure that the overlay type is compatible with the target type. If the
+  // runtime types are not compatible, it could cause runtime crashes when the resource is resolved.
+
+  target_map_.insert(std::make_pair(target_resource, TargetValue{data_type, data_value}));
+  return Unit{};
 }
 
 void ResourceMapping::RemoveMapping(ResourceId target_resource) {
@@ -422,14 +427,15 @@
     return;
   }
 
-  const TargetValue value = target_iter->second;
+  const auto value = target_iter->second;
   target_map_.erase(target_iter);
 
-  if (!IsReference(value.data_type)) {
+  const ResourceId* overlay_resource = std::get_if<ResourceId>(&value);
+  if (overlay_resource == nullptr) {
     return;
   }
 
-  auto overlay_iter = overlay_map_.equal_range(value.data_value);
+  auto overlay_iter = overlay_map_.equal_range(*overlay_resource);
   for (auto i = overlay_iter.first; i != overlay_iter.second; ++i) {
     if (i->second == target_resource) {
       overlay_map_.erase(i);
diff --git a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
index 5fea7bc..c3a3e0b 100644
--- a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
+++ b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
@@ -72,13 +72,20 @@
   const auto& target_entries2 = data2->GetTargetEntries();
   ASSERT_EQ(target_entries1.size(), target_entries2.size());
   ASSERT_EQ(target_entries1[0].target_id, target_entries2[0].target_id);
-  ASSERT_EQ(target_entries1[0].data_value, target_entries2[0].data_value);
+  ASSERT_EQ(target_entries1[0].overlay_id, target_entries2[0].overlay_id);
 
   ASSERT_EQ(target_entries1[1].target_id, target_entries2[1].target_id);
-  ASSERT_EQ(target_entries1[1].data_value, target_entries2[1].data_value);
+  ASSERT_EQ(target_entries1[1].overlay_id, target_entries2[1].overlay_id);
 
   ASSERT_EQ(target_entries1[2].target_id, target_entries2[2].target_id);
-  ASSERT_EQ(target_entries1[2].data_value, target_entries2[2].data_value);
+  ASSERT_EQ(target_entries1[2].overlay_id, target_entries2[2].overlay_id);
+
+  const auto& target_inline_entries1 = data1->GetTargetInlineEntries();
+  const auto& target_inline_entries2 = data2->GetTargetInlineEntries();
+  ASSERT_EQ(target_inline_entries1.size(), target_inline_entries2.size());
+  ASSERT_EQ(target_inline_entries1[0].target_id, target_inline_entries2[0].target_id);
+  ASSERT_EQ(target_inline_entries1[0].value.data_type, target_inline_entries2[0].value.data_type);
+  ASSERT_EQ(target_inline_entries1[0].value.data_value, target_inline_entries2[0].value.data_value);
 
   const auto& overlay_entries1 = data1->GetOverlayEntries();
   const auto& overlay_entries2 = data2->GetOverlayEntries();
diff --git a/cmds/idmap2/tests/Idmap2BinaryTests.cpp b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
index 61751b3..e7e9e4c 100644
--- a/cmds/idmap2/tests/Idmap2BinaryTests.cpp
+++ b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
@@ -128,13 +128,13 @@
   // clang-format on
   ASSERT_THAT(result, NotNull());
   ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
-  ASSERT_NE(result->stdout.find(R::target::integer::literal::int1 + " -> 0x7f010000 integer/int1"),
+  ASSERT_NE(result->stdout.find(R::target::integer::literal::int1 + " -> 0x7f010000"),
             std::string::npos);
-  ASSERT_NE(result->stdout.find(R::target::string::literal::str1 + " -> 0x7f020000 string/str1"),
+  ASSERT_NE(result->stdout.find(R::target::string::literal::str1 + " -> 0x7f020000"),
             std::string::npos);
-  ASSERT_NE(result->stdout.find(R::target::string::literal::str3 + " -> 0x7f020001 string/str3"),
+  ASSERT_NE(result->stdout.find(R::target::string::literal::str3 + " -> 0x7f020001"),
             std::string::npos);
-  ASSERT_NE(result->stdout.find(R::target::string::literal::str4 + " -> 0x7f020002 string/str4"),
+  ASSERT_NE(result->stdout.find(R::target::string::literal::str4 + " -> 0x7f020002"),
             std::string::npos);
 
   // clang-format off
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index 6fab5e0..9b42a27 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -42,14 +42,18 @@
 
 namespace android::idmap2 {
 
-#define ASSERT_TARGET_ENTRY(entry, target_resid, type, value) \
-  ASSERT_EQ(entry.target_id, target_resid);                   \
-  ASSERT_EQ(entry.data_type, type);                           \
-  ASSERT_EQ(entry.data_value, value)
+#define ASSERT_TARGET_ENTRY(entry, target_resid, overlay_resid) \
+  ASSERT_EQ((entry).target_id, (target_resid));                 \
+  ASSERT_EQ((entry).overlay_id, (overlay_resid))
+
+#define ASSERT_TARGET_INLINE_ENTRY(entry, target_resid, expected_type, expected_value) \
+  ASSERT_EQ((entry).target_id, target_resid);                                          \
+  ASSERT_EQ((entry).value.data_type, (expected_type));                                 \
+  ASSERT_EQ((entry).value.data_value, (expected_value))
 
 #define ASSERT_OVERLAY_ENTRY(entry, overlay_resid, target_resid) \
-  ASSERT_EQ(entry.overlay_id, overlay_resid);                    \
-  ASSERT_EQ(entry.target_id, target_resid)
+  ASSERT_EQ((entry).overlay_id, (overlay_resid));                \
+  ASSERT_EQ((entry).target_id, (target_resid))
 
 TEST(IdmapTests, TestCanonicalIdmapPathFor) {
   ASSERT_EQ(Idmap::CanonicalIdmapPathFor("/foo", "/vendor/overlay/bar.apk"),
@@ -62,7 +66,7 @@
   std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream);
   ASSERT_THAT(header, NotNull());
   ASSERT_EQ(header->GetMagic(), 0x504d4449U);
-  ASSERT_EQ(header->GetVersion(), 0x04U);
+  ASSERT_EQ(header->GetVersion(), 0x05U);
   ASSERT_EQ(header->GetTargetCrc(), 0x1234U);
   ASSERT_EQ(header->GetOverlayCrc(), 0x5678U);
   ASSERT_EQ(header->GetFulfilledPolicies(), 0x11);
@@ -75,7 +79,7 @@
 TEST(IdmapTests, FailToCreateIdmapHeaderFromBinaryStreamIfPathTooLong) {
   std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len);
   // overwrite the target path string, including the terminating null, with '.'
-  for (size_t i = 0x15; i < 0x115; i++) {
+  for (size_t i = 0x18; i < 0x118; i++) {
     raw[i] = '.';
   }
   std::istringstream stream(raw);
@@ -84,7 +88,7 @@
 }
 
 TEST(IdmapTests, CreateIdmapDataHeaderFromBinaryStream) {
-  const size_t offset = 0x221;
+  const size_t offset = 0x224;
   std::string raw(reinterpret_cast<const char*>(idmap_raw_data + offset),
                   idmap_raw_data_len - offset);
   std::istringstream stream(raw);
@@ -96,7 +100,7 @@
 }
 
 TEST(IdmapTests, CreateIdmapDataFromBinaryStream) {
-  const size_t offset = 0x221;
+  const size_t offset = 0x224;
   std::string raw(reinterpret_cast<const char*>(idmap_raw_data + offset),
                   idmap_raw_data_len - offset);
   std::istringstream stream(raw);
@@ -106,12 +110,14 @@
 
   const auto& target_entries = data->GetTargetEntries();
   ASSERT_EQ(target_entries.size(), 3U);
-  ASSERT_TARGET_ENTRY(target_entries[0], 0x7f020000, 0x01 /* Res_value::TYPE_REFERENCE */,
-                      0x7f020000);
-  ASSERT_TARGET_ENTRY(target_entries[1], 0x7f030000, 0x01 /* Res_value::TYPE_REFERENCE */,
-                      0x7f030000);
-  ASSERT_TARGET_ENTRY(target_entries[2], 0x7f030002, 0x01 /* Res_value::TYPE_REFERENCE */,
-                      0x7f030001);
+  ASSERT_TARGET_ENTRY(target_entries[0], 0x7f020000, 0x7f020000);
+  ASSERT_TARGET_ENTRY(target_entries[1], 0x7f030000, 0x7f030000);
+  ASSERT_TARGET_ENTRY(target_entries[2], 0x7f030002, 0x7f030001);
+
+  const auto& target_inline_entries = data->GetTargetInlineEntries();
+  ASSERT_EQ(target_inline_entries.size(), 1U);
+  ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], 0x7f040000, Res_value::TYPE_INT_HEX,
+                             0x12345678);
 
   const auto& overlay_entries = data->GetOverlayEntries();
   ASSERT_EQ(target_entries.size(), 3U);
@@ -130,7 +136,7 @@
 
   ASSERT_THAT(idmap->GetHeader(), NotNull());
   ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
-  ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x04U);
+  ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x05U);
   ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x1234U);
   ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0x5678U);
   ASSERT_EQ(idmap->GetHeader()->GetFulfilledPolicies(), 0x11);
@@ -146,9 +152,14 @@
 
   const auto& target_entries = data->GetTargetEntries();
   ASSERT_EQ(target_entries.size(), 3U);
-  ASSERT_TARGET_ENTRY(target_entries[0], 0x7f020000, Res_value::TYPE_REFERENCE, 0x7f020000);
-  ASSERT_TARGET_ENTRY(target_entries[1], 0x7f030000, Res_value::TYPE_REFERENCE, 0x7f030000);
-  ASSERT_TARGET_ENTRY(target_entries[2], 0x7f030002, Res_value::TYPE_REFERENCE, 0x7f030001);
+  ASSERT_TARGET_ENTRY(target_entries[0], 0x7f020000, 0x7f020000);
+  ASSERT_TARGET_ENTRY(target_entries[1], 0x7f030000, 0x7f030000);
+  ASSERT_TARGET_ENTRY(target_entries[2], 0x7f030002, 0x7f030001);
+
+  const auto& target_inline_entries = data->GetTargetInlineEntries();
+  ASSERT_EQ(target_inline_entries.size(), 1U);
+  ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], 0x7f040000, Res_value::TYPE_INT_HEX,
+                             0x12345678);
 
   const auto& overlay_entries = data->GetOverlayEntries();
   ASSERT_EQ(target_entries.size(), 3U);
@@ -184,7 +195,7 @@
 
   ASSERT_THAT(idmap->GetHeader(), NotNull());
   ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
-  ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x04U);
+  ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x05U);
   ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), android::idmap2::TestConstants::TARGET_CRC);
   ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), android::idmap2::TestConstants::OVERLAY_CRC);
   ASSERT_EQ(idmap->GetHeader()->GetFulfilledPolicies(), PolicyFlags::PUBLIC);
@@ -244,14 +255,13 @@
 
   const auto& target_entries = data->GetTargetEntries();
   ASSERT_EQ(target_entries.size(), 4U);
-  ASSERT_TARGET_ENTRY(target_entries[0], R::target::integer::int1,
-                      Res_value::TYPE_DYNAMIC_REFERENCE, R::overlay::integer::int1);
-  ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str1, Res_value::TYPE_DYNAMIC_REFERENCE,
-                      R::overlay::string::str1);
-  ASSERT_TARGET_ENTRY(target_entries[2], R::target::string::str3, Res_value::TYPE_DYNAMIC_REFERENCE,
-                      R::overlay::string::str3);
-  ASSERT_TARGET_ENTRY(target_entries[3], R::target::string::str4, Res_value::TYPE_DYNAMIC_REFERENCE,
-                      R::overlay::string::str4);
+  ASSERT_TARGET_ENTRY(target_entries[0], R::target::integer::int1, R::overlay::integer::int1);
+  ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str1, R::overlay::string::str1);
+  ASSERT_TARGET_ENTRY(target_entries[2], R::target::string::str3, R::overlay::string::str3);
+  ASSERT_TARGET_ENTRY(target_entries[3], R::target::string::str4, R::overlay::string::str4);
+
+  const auto& target_inline_entries = data->GetTargetInlineEntries();
+  ASSERT_EQ(target_inline_entries.size(), 0U);
 
   const auto& overlay_entries = data->GetOverlayEntries();
   ASSERT_EQ(target_entries.size(), 4U);
@@ -286,13 +296,13 @@
   const auto& target_entries = data->GetTargetEntries();
   ASSERT_EQ(target_entries.size(), 4U);
   ASSERT_TARGET_ENTRY(target_entries[0], R::target::integer::int1,
-                      Res_value::TYPE_DYNAMIC_REFERENCE, R::overlay_shared::integer::int1);
-  ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str1, Res_value::TYPE_DYNAMIC_REFERENCE,
-                      R::overlay_shared::string::str1);
-  ASSERT_TARGET_ENTRY(target_entries[2], R::target::string::str3, Res_value::TYPE_DYNAMIC_REFERENCE,
-                      R::overlay_shared::string::str3);
-  ASSERT_TARGET_ENTRY(target_entries[3], R::target::string::str4, Res_value::TYPE_DYNAMIC_REFERENCE,
-                      R::overlay_shared::string::str4);
+                      R::overlay_shared::integer::int1);
+  ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str1, R::overlay_shared::string::str1);
+  ASSERT_TARGET_ENTRY(target_entries[2], R::target::string::str3, R::overlay_shared::string::str3);
+  ASSERT_TARGET_ENTRY(target_entries[3], R::target::string::str4, R::overlay_shared::string::str4);
+
+  const auto& target_inline_entries = data->GetTargetInlineEntries();
+  ASSERT_EQ(target_inline_entries.size(), 0U);
 
   const auto& overlay_entries = data->GetOverlayEntries();
   ASSERT_EQ(target_entries.size(), 4U);
@@ -320,10 +330,12 @@
 
   const auto& target_entries = data->GetTargetEntries();
   ASSERT_EQ(target_entries.size(), 2U);
-  ASSERT_TARGET_ENTRY(target_entries[0], R::target::string::str1, Res_value::TYPE_REFERENCE,
+  ASSERT_TARGET_ENTRY(target_entries[0], R::target::string::str1,
                       0x0104000a);  // -> android:string/ok
-  ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str3, Res_value::TYPE_DYNAMIC_REFERENCE,
-                      R::overlay::string::str3);
+  ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str3, R::overlay::string::str3);
+
+  const auto& target_inline_entries = data->GetTargetInlineEntries();
+  ASSERT_EQ(target_inline_entries.size(), 0U);
 
   const auto& overlay_entries = data->GetOverlayEntries();
   ASSERT_EQ(overlay_entries.size(), 1U);
@@ -342,13 +354,17 @@
   ASSERT_TRUE(idmap_data) << idmap_data.GetErrorMessage();
   auto& data = *idmap_data;
 
-  constexpr size_t overlay_string_pool_size = 8U;
   const auto& target_entries = data->GetTargetEntries();
-  ASSERT_EQ(target_entries.size(), 2U);
-  ASSERT_TARGET_ENTRY(target_entries[0], R::target::integer::int1, Res_value::TYPE_INT_DEC,
-                      73U);  // -> 73
-  ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str1, Res_value::TYPE_STRING,
-                      overlay_string_pool_size + 0U);  // -> "Hello World"
+  ASSERT_EQ(target_entries.size(), 0U);
+
+  constexpr size_t overlay_string_pool_size = 8U;
+  const auto& target_inline_entries = data->GetTargetInlineEntries();
+  ASSERT_EQ(target_inline_entries.size(), 2U);
+  ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], R::target::integer::int1,
+                             Res_value::TYPE_INT_DEC, 73U);  // -> 73
+  ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[1], R::target::string::str1,
+                             Res_value::TYPE_STRING,
+                             overlay_string_pool_size + 0U);  // -> "Hello World"
 
   const auto& overlay_entries = data->GetOverlayEntries();
   ASSERT_EQ(overlay_entries.size(), 0U);
@@ -479,9 +495,9 @@
   ASSERT_FALSE(bad_enforce_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(),
                                               PolicyFlags::PUBLIC, /* enforce_overlayable */ true));
 
-  // target path: bytes (0x15, 0x114)
+  // target path: bytes (0x18, 0x117)
   std::string bad_target_path_string(stream.str());
-  bad_target_path_string[0x15] = '\0';
+  bad_target_path_string[0x18] = '\0';
   std::stringstream bad_target_path_stream(bad_target_path_string);
   std::unique_ptr<const IdmapHeader> bad_target_path_header =
       IdmapHeader::FromBinaryStream(bad_target_path_stream);
@@ -490,9 +506,9 @@
   ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(),
                                             PolicyFlags::PUBLIC, /* enforce_overlayable */ true));
 
-  // overlay path: bytes (0x115, 0x214)
+  // overlay path: bytes (0x118, 0x217)
   std::string bad_overlay_path_string(stream.str());
-  bad_overlay_path_string[0x115] = '\0';
+  bad_overlay_path_string[0x118] = '\0';
   std::stringstream bad_overlay_path_stream(bad_overlay_path_string);
   std::unique_ptr<const IdmapHeader> bad_overlay_path_header =
       IdmapHeader::FromBinaryStream(bad_overlay_path_stream);
diff --git a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
index 9a10079..d30fbfc 100644
--- a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
@@ -56,7 +56,8 @@
 
   ASSERT_NE(stream.str().find("target apk path  : "), std::string::npos);
   ASSERT_NE(stream.str().find("overlay apk path : "), std::string::npos);
-  ASSERT_NE(stream.str().find(R::target::integer::literal::int1 + " -> 0x7f010000 integer/int1\n"),
+  ASSERT_NE(stream.str().find(R::target::integer::literal::int1 +
+                              " -> 0x7f010000 (integer/int1 -> integer/int1)\n"),
             std::string::npos);
 }
 
@@ -75,7 +76,7 @@
 
   ASSERT_NE(stream.str().find("target apk path  : "), std::string::npos);
   ASSERT_NE(stream.str().find("overlay apk path : "), std::string::npos);
-  ASSERT_NE(stream.str().find("0x7f020000 -> 0x7f020000\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("0x7f020000 -> 0x7f020000 (\?\?\? -> \?\?\?)\n"), std::string::npos);
 }
 
 }  // namespace android::idmap2
diff --git a/cmds/idmap2/tests/RawPrintVisitorTests.cpp b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
index b268d5a..95bd9473 100644
--- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
@@ -65,7 +65,7 @@
   (*idmap)->accept(&visitor);
 
   ASSERT_CONTAINS_REGEX(ADDRESS "504d4449  magic\n", stream.str());
-  ASSERT_CONTAINS_REGEX(ADDRESS "00000004  version\n", stream.str());
+  ASSERT_CONTAINS_REGEX(ADDRESS "00000005  version\n", stream.str());
   ASSERT_CONTAINS_REGEX(
       StringPrintf(ADDRESS "%s  target crc\n", android::idmap2::TestConstants::TARGET_CRC_STRING),
       stream.str());
@@ -73,19 +73,19 @@
       StringPrintf(ADDRESS "%s  overlay crc\n", android::idmap2::TestConstants::OVERLAY_CRC_STRING),
       stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "00000001  fulfilled policies: public\n", stream.str());
-  ASSERT_CONTAINS_REGEX(ADDRESS "      01  enforce overlayable\n", stream.str());
+  ASSERT_CONTAINS_REGEX(ADDRESS "00000001  enforce overlayable\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "      7f  target package id\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "      7f  overlay package id\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "00000004  target entry count\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "00000004  overlay entry count\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "00000004  overlay entry count\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "00000008  string pool index offset\n", stream.str());
-  ASSERT_CONTAINS_REGEX(ADDRESS "000000b4  string pool byte length\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "7f010000  target id: integer/int1\n", stream.str());
-  ASSERT_CONTAINS_REGEX(ADDRESS "      07  type: reference \\(dynamic\\)\n", stream.str());
-  ASSERT_CONTAINS_REGEX(ADDRESS "7f010000  value: integer/int1\n", stream.str());
+  ASSERT_CONTAINS_REGEX(ADDRESS "7f010000  overlay id: integer/int1\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "7f010000  overlay id: integer/int1\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "7f010000  target id: integer/int1\n", stream.str());
+  ASSERT_CONTAINS_REGEX(ADDRESS "000000b4  string pool size\n", stream.str());
+  ASSERT_CONTAINS_REGEX("000002bc: ........  string pool: ...\n", stream.str());
 }
 
 TEST(RawPrintVisitorTests, CreateRawPrintVisitorWithoutAccessToApks) {
@@ -102,22 +102,26 @@
   (*idmap)->accept(&visitor);
 
   ASSERT_CONTAINS_REGEX(ADDRESS "504d4449  magic\n", stream.str());
-  ASSERT_CONTAINS_REGEX(ADDRESS "00000004  version\n", stream.str());
+  ASSERT_CONTAINS_REGEX(ADDRESS "00000005  version\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "00001234  target crc\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "00005678  overlay crc\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "00000011  fulfilled policies: public|signature\n", stream.str());
-  ASSERT_CONTAINS_REGEX(ADDRESS "      01  enforce overlayable\n", stream.str());
+  ASSERT_CONTAINS_REGEX(ADDRESS "00000001  enforce overlayable\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "      7f  target package id\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "      7f  overlay package id\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "00000003  target entry count\n", stream.str());
+  ASSERT_CONTAINS_REGEX(ADDRESS "00000001  target inline entry count\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "00000003  overlay entry count\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "00000000  string pool index offset\n", stream.str());
-  ASSERT_CONTAINS_REGEX(ADDRESS "00000000  string pool byte length\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "7f020000  target id\n", stream.str());
-  ASSERT_CONTAINS_REGEX(ADDRESS "      01  type: reference\n", stream.str());
-  ASSERT_CONTAINS_REGEX(ADDRESS "7f020000  value\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "7f020000  overlay id\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "7f020000  target id\n", stream.str());
+  ASSERT_CONTAINS_REGEX(ADDRESS "      11  type: integer\n", stream.str());
+  ASSERT_CONTAINS_REGEX(ADDRESS "12345678  data\n", stream.str());
+  ASSERT_CONTAINS_REGEX(ADDRESS "7f020000  overlay id\n", stream.str());
+  ASSERT_CONTAINS_REGEX(ADDRESS "7f030002  target id\n", stream.str());
+  ASSERT_CONTAINS_REGEX(ADDRESS "00000004  string pool size\n", stream.str());
+  ASSERT_CONTAINS_REGEX("00000278: ........  string pool: ...\n", stream.str());
 }
 
 }  // namespace android::idmap2
diff --git a/cmds/idmap2/tests/ResourceMappingTests.cpp b/cmds/idmap2/tests/ResourceMappingTests.cpp
index 3ec6ac2..185e929 100644
--- a/cmds/idmap2/tests/ResourceMappingTests.cpp
+++ b/cmds/idmap2/tests/ResourceMappingTests.cpp
@@ -77,30 +77,61 @@
                                 fulfilled_policies, enforce_overlayable);
 }
 
-Result<Unit> MappingExists(const ResourceMapping& mapping, const ResourceId& target_resource,
-                           const uint8_t type, const uint32_t value, bool rewrite) {
+Result<Unit> MappingExists(const ResourceMapping& mapping, ResourceId target_resource,
+                           ResourceId overlay_resource, bool rewrite) {
   auto target_map = mapping.GetTargetToOverlayMap();
   auto entry_map = target_map.find(target_resource);
   if (entry_map == target_map.end()) {
     return Error("Failed to find mapping for target resource");
   }
 
-  if (entry_map->second.data_type != type) {
-    return Error(R"(Expected type: "0x%02x" Actual type: "0x%02x")", type,
-                 entry_map->second.data_type);
+  auto actual_overlay_resource = std::get_if<ResourceId>(&entry_map->second);
+  if (actual_overlay_resource == nullptr) {
+    return Error("Target resource is not mapped to an overlay resource id");
   }
 
-  if (entry_map->second.data_value != value) {
-    return Error(R"(Expected value: "0x%08x" Actual value: "0x%08x")", type,
-                 entry_map->second.data_value);
+  if (*actual_overlay_resource != overlay_resource) {
+    return Error(R"(Expected id: "0x%02x" Actual id: "0x%02x")", overlay_resource,
+                 *actual_overlay_resource);
   }
 
   auto overlay_map = mapping.GetOverlayToTargetMap();
-  auto overlay_iter = overlay_map.find(entry_map->second.data_value);
+  auto overlay_iter = overlay_map.find(overlay_resource);
   if ((overlay_iter != overlay_map.end()) != rewrite) {
     return Error(R"(Expected rewriting: "%s")", rewrite ? "true" : "false");
   }
 
+  if (rewrite && overlay_iter->second != target_resource) {
+    return Error(R"(Expected rewrite id: "0x%02x" Actual id: "0x%02x")", target_resource,
+                 overlay_iter->second);
+  }
+
+  return Result<Unit>({});
+}
+
+Result<Unit> MappingExists(const ResourceMapping& mapping, const ResourceId& target_resource,
+                           const uint8_t type, const uint32_t value) {
+  auto target_map = mapping.GetTargetToOverlayMap();
+  auto entry_map = target_map.find(target_resource);
+  if (entry_map == target_map.end()) {
+    return Error("Failed to find mapping for target resource");
+  }
+
+  auto actual_overlay_value = std::get_if<TargetValue>(&entry_map->second);
+  if (actual_overlay_value == nullptr) {
+    return Error("Target resource is not mapped to an inline value");
+  }
+
+  if (actual_overlay_value->data_type != type) {
+    return Error(R"(Expected type: "0x%02x" Actual type: "0x%02x")", type,
+                 actual_overlay_value->data_type);
+  }
+
+  if (actual_overlay_value->data_value != value) {
+    return Error(R"(Expected value: "0x%08x" Actual value: "0x%08x")", type,
+                 actual_overlay_value->data_value);
+  }
+
   return Result<Unit>({});
 }
 
@@ -116,14 +147,14 @@
   ASSERT_TRUE(resources) << resources.GetErrorMessage();
   auto& res = *resources;
   ASSERT_EQ(res.GetTargetToOverlayMap().size(), 4U);
-  ASSERT_RESULT(MappingExists(res, R::target::integer::int1, Res_value::TYPE_REFERENCE,
-                              R::overlay::integer::int1, false /* rewrite */));
-  ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_REFERENCE,
-                              R::overlay::string::str1, false /* rewrite */));
-  ASSERT_RESULT(MappingExists(res, R::target::string::str3, Res_value::TYPE_REFERENCE,
-                              R::overlay::string::str3, false /* rewrite */));
-  ASSERT_RESULT(MappingExists(res, R::target::string::str4, Res_value::TYPE_REFERENCE,
-                              R::overlay::string::str4, false /* rewrite */));
+  ASSERT_RESULT(
+      MappingExists(res, R::target::integer::int1, R::overlay::integer::int1, false /* rewrite */));
+  ASSERT_RESULT(
+      MappingExists(res, R::target::string::str1, R::overlay::string::str1, false /* rewrite */));
+  ASSERT_RESULT(
+      MappingExists(res, R::target::string::str3, R::overlay::string::str3, false /* rewrite */));
+  ASSERT_RESULT(
+      MappingExists(res, R::target::string::str4, R::overlay::string::str4, false /* rewrite */));
 }
 
 TEST(ResourceMappingTests, ResourcesFromApkAssetsNonMatchingNames) {
@@ -138,12 +169,12 @@
   ASSERT_TRUE(resources) << resources.GetErrorMessage();
   auto& res = *resources;
   ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U);
-  ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_DYNAMIC_REFERENCE,
-                              R::overlay::string::str4, true /* rewrite */));
-  ASSERT_RESULT(MappingExists(res, R::target::string::str3, Res_value::TYPE_DYNAMIC_REFERENCE,
-                              R::overlay::string::str1, true /* rewrite */));
-  ASSERT_RESULT(MappingExists(res, R::target::string::str4, Res_value::TYPE_DYNAMIC_REFERENCE,
-                              R::overlay::string::str3, true /* rewrite */));
+  ASSERT_RESULT(
+      MappingExists(res, R::target::string::str1, R::overlay::string::str4, true /* rewrite */));
+  ASSERT_RESULT(
+      MappingExists(res, R::target::string::str3, R::overlay::string::str1, true /* rewrite */));
+  ASSERT_RESULT(
+      MappingExists(res, R::target::string::str4, R::overlay::string::str3, true /* rewrite */));
 }
 
 TEST(ResourceMappingTests, DoNotRewriteNonOverlayResourceId) {
@@ -159,10 +190,9 @@
   auto& res = *resources;
   ASSERT_EQ(res.GetTargetToOverlayMap().size(), 2U);
   ASSERT_EQ(res.GetOverlayToTargetMap().size(), 1U);
-  ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_REFERENCE, 0x0104000a,
+  ASSERT_RESULT(MappingExists(res, R::target::string::str1, 0x0104000a,
                               false /* rewrite */));  // -> android:string/ok
-  ASSERT_RESULT(MappingExists(res, R::target::string::str3, Res_value::TYPE_DYNAMIC_REFERENCE,
-                              0x7f020001, true /* rewrite */));
+  ASSERT_RESULT(MappingExists(res, R::target::string::str3, 0x7f020001, true /* rewrite */));
 }
 
 TEST(ResourceMappingTests, InlineResources) {
@@ -180,10 +210,8 @@
   ASSERT_EQ(res.GetTargetToOverlayMap().size(), 2U);
   ASSERT_EQ(res.GetOverlayToTargetMap().size(), 0U);
   ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_STRING,
-                              overlay_string_pool_size + 0U,
-                              false /* rewrite */));  // -> "Hello World"
-  ASSERT_RESULT(MappingExists(res, R::target::integer::int1, Res_value::TYPE_INT_DEC, 73U,
-                              false /* rewrite */));  // -> 73
+                              overlay_string_pool_size + 0U));  // -> "Hello World"
+  ASSERT_RESULT(MappingExists(res, R::target::integer::int1, Res_value::TYPE_INT_DEC, 73U));
 }
 
 TEST(ResourceMappingTests, CreateIdmapFromApkAssetsPolicySystemPublic) {
@@ -195,13 +223,13 @@
   ASSERT_TRUE(resources) << resources.GetErrorMessage();
   auto& res = *resources;
   ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U);
-  ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE,
+  ASSERT_RESULT(MappingExists(res, R::target::string::policy_public,
                               R::system_overlay::string::policy_public, false /* rewrite */));
-  ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, Res_value::TYPE_REFERENCE,
+  ASSERT_RESULT(MappingExists(res, R::target::string::policy_system,
                               R::system_overlay::string::policy_system, false /* rewrite */));
-  ASSERT_RESULT(
-      MappingExists(res, R::target::string::policy_system_vendor, Res_value::TYPE_REFERENCE,
-                    R::system_overlay::string::policy_system_vendor, false /* rewrite */));
+  ASSERT_RESULT(MappingExists(res, R::target::string::policy_system_vendor,
+                              R::system_overlay::string::policy_system_vendor,
+                              false /* rewrite */));
 }
 
 // Resources that are not declared as overlayable and resources that a protected by policies the
@@ -215,15 +243,15 @@
   ASSERT_TRUE(resources) << resources.GetErrorMessage();
   auto& res = *resources;
   ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U);
-  ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE,
+  ASSERT_RESULT(MappingExists(res, R::target::string::policy_public,
                               R::system_overlay_invalid::string::policy_public,
                               false /* rewrite */));
-  ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, Res_value::TYPE_REFERENCE,
+  ASSERT_RESULT(MappingExists(res, R::target::string::policy_system,
                               R::system_overlay_invalid::string::policy_system,
                               false /* rewrite */));
-  ASSERT_RESULT(
-      MappingExists(res, R::target::string::policy_system_vendor, Res_value::TYPE_REFERENCE,
-                    R::system_overlay_invalid::string::policy_system_vendor, false /* rewrite */));
+  ASSERT_RESULT(MappingExists(res, R::target::string::policy_system_vendor,
+                              R::system_overlay_invalid::string::policy_system_vendor,
+                              false /* rewrite */));
 }
 
 // Resources that are not declared as overlayable and resources that a protected by policies the
@@ -238,37 +266,36 @@
   ASSERT_TRUE(resources) << resources.GetErrorMessage();
   auto& res = *resources;
   ASSERT_EQ(res.GetTargetToOverlayMap().size(), 11U);
-  ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, Res_value::TYPE_REFERENCE,
+  ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable,
                               R::system_overlay_invalid::string::not_overlayable,
                               false /* rewrite */));
-  ASSERT_RESULT(MappingExists(res, R::target::string::other, Res_value::TYPE_REFERENCE,
+  ASSERT_RESULT(MappingExists(res, R::target::string::other,
                               R::system_overlay_invalid::string::other, false /* rewrite */));
-  ASSERT_RESULT(MappingExists(res, R::target::string::policy_actor, Res_value::TYPE_REFERENCE,
+  ASSERT_RESULT(MappingExists(res, R::target::string::policy_actor,
                               R::system_overlay_invalid::string::policy_actor,
                               false /* rewrite */));
-  ASSERT_RESULT(MappingExists(res, R::target::string::policy_odm, Res_value::TYPE_REFERENCE,
+  ASSERT_RESULT(MappingExists(res, R::target::string::policy_odm,
                               R::system_overlay_invalid::string::policy_odm, false /* rewrite */));
-  ASSERT_RESULT(MappingExists(res, R::target::string::policy_oem, Res_value::TYPE_REFERENCE,
+  ASSERT_RESULT(MappingExists(res, R::target::string::policy_oem,
                               R::system_overlay_invalid::string::policy_oem, false /* rewrite */));
-  ASSERT_RESULT(MappingExists(res, R::target::string::policy_product, Res_value::TYPE_REFERENCE,
+  ASSERT_RESULT(MappingExists(res, R::target::string::policy_product,
                               R::system_overlay_invalid::string::policy_product,
                               false /* rewrite */));
-  ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE,
+  ASSERT_RESULT(MappingExists(res, R::target::string::policy_public,
                               R::system_overlay_invalid::string::policy_public,
                               false /* rewrite */));
   ASSERT_RESULT(MappingExists(res, R::target::string::policy_config_signature,
-                              Res_value::TYPE_REFERENCE,
                               R::system_overlay_invalid::string::policy_config_signature,
                               false /* rewrite */));
-  ASSERT_RESULT(MappingExists(res, R::target::string::policy_signature, Res_value::TYPE_REFERENCE,
+  ASSERT_RESULT(MappingExists(res, R::target::string::policy_signature,
                               R::system_overlay_invalid::string::policy_signature,
                               false /* rewrite */));
-  ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, Res_value::TYPE_REFERENCE,
+  ASSERT_RESULT(MappingExists(res, R::target::string::policy_system,
                               R::system_overlay_invalid::string::policy_system,
                               false /* rewrite */));
-  ASSERT_RESULT(
-      MappingExists(res, R::target::string::policy_system_vendor, Res_value::TYPE_REFERENCE,
-                    R::system_overlay_invalid::string::policy_system_vendor, false /* rewrite */));
+  ASSERT_RESULT(MappingExists(res, R::target::string::policy_system_vendor,
+                              R::system_overlay_invalid::string::policy_system_vendor,
+                              false /* rewrite */));
 }
 
 // Overlays that do not target an <overlayable> tag can overlay resources defined within any
@@ -281,14 +308,14 @@
   ASSERT_TRUE(resources) << resources.GetErrorMessage();
   auto& res = *resources;
   ASSERT_EQ(res.GetTargetToOverlayMap().size(), 4U);
-  ASSERT_RESULT(MappingExists(res, R::target::integer::int1, Res_value::TYPE_REFERENCE,
-                              R::overlay::integer::int1, false /* rewrite */));
-  ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_REFERENCE,
-                              R::overlay::string::str1, false /* rewrite */));
-  ASSERT_RESULT(MappingExists(res, R::target::string::str3, Res_value::TYPE_REFERENCE,
-                              R::overlay::string::str3, false /* rewrite */));
-  ASSERT_RESULT(MappingExists(res, R::target::string::str4, Res_value::TYPE_REFERENCE,
-                              R::overlay::string::str4, false /* rewrite */));
+  ASSERT_RESULT(
+      MappingExists(res, R::target::integer::int1, R::overlay::integer::int1, false /* rewrite */));
+  ASSERT_RESULT(
+      MappingExists(res, R::target::string::str1, R::overlay::string::str1, false /* rewrite */));
+  ASSERT_RESULT(
+      MappingExists(res, R::target::string::str3, R::overlay::string::str3, false /* rewrite */));
+  ASSERT_RESULT(
+      MappingExists(res, R::target::string::str4, R::overlay::string::str4, false /* rewrite */));
 }
 
 // Overlays that are neither pre-installed nor signed with the same signature as the target cannot
@@ -302,9 +329,9 @@
   ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 0U);
 }
 
-// Overlays that are pre-installed or are signed with the same signature as the target  or are signed
-// with the same signature as the reference package can overlay packages that have not defined
-// overlayable resources.
+// Overlays that are pre-installed or are signed with the same signature as the target  or are
+// signed with the same signature as the reference package can overlay packages that have not
+// defined overlayable resources.
 TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) {
   auto CheckEntries = [&](const PolicyBitmask& fulfilled_policies) -> void {
     auto resources = TestGetResourceMapping("/target/target-no-overlayable.apk",
@@ -315,39 +342,38 @@
     ASSERT_TRUE(resources) << resources.GetErrorMessage();
     auto& res = *resources;
     ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 11U);
-    ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, Res_value::TYPE_REFERENCE,
+    ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable,
                                 R::system_overlay_invalid::string::not_overlayable,
                                 false /* rewrite */));
-    ASSERT_RESULT(MappingExists(res, R::target::string::other, Res_value::TYPE_REFERENCE,
+    ASSERT_RESULT(MappingExists(res, R::target::string::other,
                                 R::system_overlay_invalid::string::other, false /* rewrite */));
-    ASSERT_RESULT(MappingExists(res, R::target::string::policy_actor, Res_value::TYPE_REFERENCE,
+    ASSERT_RESULT(MappingExists(res, R::target::string::policy_actor,
                                 R::system_overlay_invalid::string::policy_actor,
                                 false /* rewrite */));
-    ASSERT_RESULT(MappingExists(res, R::target::string::policy_odm, Res_value::TYPE_REFERENCE,
+    ASSERT_RESULT(MappingExists(res, R::target::string::policy_odm,
                                 R::system_overlay_invalid::string::policy_odm,
                                 false /* rewrite */));
-    ASSERT_RESULT(MappingExists(res, R::target::string::policy_oem, Res_value::TYPE_REFERENCE,
+    ASSERT_RESULT(MappingExists(res, R::target::string::policy_oem,
                                 R::system_overlay_invalid::string::policy_oem,
                                 false /* rewrite */));
-    ASSERT_RESULT(MappingExists(res, R::target::string::policy_product, Res_value::TYPE_REFERENCE,
+    ASSERT_RESULT(MappingExists(res, R::target::string::policy_product,
                                 R::system_overlay_invalid::string::policy_product,
                                 false /* rewrite */));
-    ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE,
+    ASSERT_RESULT(MappingExists(res, R::target::string::policy_public,
                                 R::system_overlay_invalid::string::policy_public,
                                 false /* rewrite */));
     ASSERT_RESULT(MappingExists(res, R::target::string::policy_config_signature,
-                                Res_value::TYPE_REFERENCE,
                                 R::system_overlay_invalid::string::policy_config_signature,
                                 false /* rewrite */));
-    ASSERT_RESULT(MappingExists(res, R::target::string::policy_signature, Res_value::TYPE_REFERENCE,
+    ASSERT_RESULT(MappingExists(res, R::target::string::policy_signature,
                                 R::system_overlay_invalid::string::policy_signature,
                                 false /* rewrite */));
-    ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, Res_value::TYPE_REFERENCE,
+    ASSERT_RESULT(MappingExists(res, R::target::string::policy_system,
                                 R::system_overlay_invalid::string::policy_system,
                                 false /* rewrite */));
-    ASSERT_RESULT(MappingExists(
-        res, R::target::string::policy_system_vendor, Res_value::TYPE_REFERENCE,
-        R::system_overlay_invalid::string::policy_system_vendor, false /* rewrite */));
+    ASSERT_RESULT(MappingExists(res, R::target::string::policy_system_vendor,
+                                R::system_overlay_invalid::string::policy_system_vendor,
+                                false /* rewrite */));
   };
 
   CheckEntries(PolicyFlags::SIGNATURE);
diff --git a/cmds/idmap2/tests/TestConstants.h b/cmds/idmap2/tests/TestConstants.h
index 9641f6b5..69575b8 100644
--- a/cmds/idmap2/tests/TestConstants.h
+++ b/cmds/idmap2/tests/TestConstants.h
@@ -19,7 +19,7 @@
 
 namespace android::idmap2::TestConstants {
 
-constexpr const auto TARGET_CRC =  0x7c2d4719;
+constexpr const auto TARGET_CRC = 0x7c2d4719;
 constexpr const auto TARGET_CRC_STRING = "7c2d4719";
 
 constexpr const auto OVERLAY_CRC = 0x5afff726;
diff --git a/cmds/idmap2/tests/TestHelpers.h b/cmds/idmap2/tests/TestHelpers.h
index b599dcb..d0a8e3d 100644
--- a/cmds/idmap2/tests/TestHelpers.h
+++ b/cmds/idmap2/tests/TestHelpers.h
@@ -30,7 +30,7 @@
     0x49, 0x44, 0x4d, 0x50,
 
     // 0x4: version
-    0x04, 0x00, 0x00, 0x00,
+    0x05, 0x00, 0x00, 0x00,
 
     // 0x8: target crc
     0x34, 0x12, 0x00, 0x00,
@@ -42,9 +42,9 @@
     0x11, 0x00, 0x00, 0x00,
 
     // 0x14: enforce overlayable
-    0x01,
+    0x01, 0x00, 0x00, 0x00,
 
-    // 0x15: target path "targetX.apk"
+    // 0x18: target path "targetX.apk"
     0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x58, 0x2e, 0x61, 0x70, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -62,7 +62,7 @@
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
-    // 0x115: overlay path "overlayX.apk"
+    // 0x118: overlay path "overlayX.apk"
     0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x58, 0x2e, 0x61, 0x70, 0x6b, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -80,71 +80,89 @@
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
-    // 0x215: debug string
-    // string length, including terminating null
-    0x08, 0x00, 0x00, 0x00,
+    // 0x218: debug string
+    // string length,
+    0x05, 0x00, 0x00, 0x00,
 
-    // string contents "debug\0\0\0" (padded to word alignment)
+    // 0x21c string contents "debug\0\0\0" (padded to word alignment)
     0x64, 0x65, 0x62, 0x75, 0x67, 0x00, 0x00, 0x00,
 
     // DATA HEADER
-    // 0x221: target_package_id
+    // 0x224: target_package_id
     0x7f,
 
-    // 0x222: overlay_package_id
+    // 0x225: overlay_package_id
     0x7f,
 
-    // 0x223: target_entry_count
+    // 0x226: padding
+    0x00, 0x00,
+
+    // 0x228: target_entry_count
     0x03, 0x00, 0x00, 0x00,
 
-    // 0x227: overlay_entry_count
+    // 0x22c: target_inline_entry_count
+    0x01, 0x00, 0x00, 0x00,
+
+    // 0x230: overlay_entry_count
     0x03, 0x00, 0x00, 0x00,
 
-    // 0x22b: string_pool_offset
-    0x00, 0x00, 0x00, 0x00,
-
-    // 0x22f: string_pool_byte_length
+    // 0x234: string_pool_offset
     0x00, 0x00, 0x00, 0x00,
 
     // TARGET ENTRIES
-    // 0x233: 0x7f020000
+    // 0x238: target id (0x7f020000)
     0x00, 0x00, 0x02, 0x7f,
 
-    // 0x237: TYPE_REFERENCE
-    0x01,
-
-    // 0x238: 0x7f020000
+    // 0x23c: overlay_id (0x7f020000)
     0x00, 0x00, 0x02, 0x7f,
 
-    // 0x23c: 0x7f030000
+    // 0x240: target id (0x7f030000)
     0x00, 0x00, 0x03, 0x7f,
 
-    // 0x240: TYPE_REFERENCE
-    0x01,
-
-    // 0x241: 0x7f030000
+    // 0x244: overlay_id (0x7f030000)
     0x00, 0x00, 0x03, 0x7f,
 
-    // 0x245: 0x7f030002
+    // 0x248: target id (0x7f030002)
     0x02, 0x00, 0x03, 0x7f,
 
-    // 0x249: TYPE_REFERENCE
-    0x01,
-
-    // 0x24a: 0x7f030001
+    // 0x24c: overlay_id (0x7f030001)
     0x01, 0x00, 0x03, 0x7f,
 
+    // INLINE TARGET ENTRIES
+
+    // 0x250: target_id
+    0x00, 0x00, 0x04, 0x7f,
+
+    // 0x254: Res_value::size (value ignored by idmap)
+    0x08, 0x00,
+
+    // 0x256: Res_value::res0 (value ignored by idmap)
+    0x00,
+
+    // 0x257: Res_value::dataType (TYPE_INT_HEX)
+    0x11,
+
+    // 0x258: Res_value::data
+    0x78, 0x56, 0x34, 0x12,
+
     // OVERLAY ENTRIES
-    // 0x24e: 0x7f020000 -> 0x7f020000
+    // 0x25c: 0x7f020000 -> 0x7f020000
     0x00, 0x00, 0x02, 0x7f, 0x00, 0x00, 0x02, 0x7f,
 
-    // 0x256: 0x7f030000 -> 0x7f030000
+    // 0x264: 0x7f030000 -> 0x7f030000
     0x00, 0x00, 0x03, 0x7f, 0x00, 0x00, 0x03, 0x7f,
 
-    // 0x25e: 0x7f030001 -> 0x7f030002
-    0x01, 0x00, 0x03, 0x7f, 0x02, 0x00, 0x03, 0x7f};
+    // 0x26c: 0x7f030001 -> 0x7f030002
+    0x01, 0x00, 0x03, 0x7f, 0x02, 0x00, 0x03, 0x7f,
 
-const unsigned int idmap_raw_data_len = 0x266;
+    // 0x274: string pool
+    // string length,
+    0x04, 0x00, 0x00, 0x00,
+
+    // 0x278 string contents "test" (padded to word alignment)
+    0x74, 0x65, 0x73, 0x74};
+
+const unsigned int idmap_raw_data_len = 0x27c;
 
 std::string GetTestDataPath();
 
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 88db1d8..012450d 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -430,6 +430,30 @@
     },
 }
 
+java_library {
+    name: "statsdprotonano",
+    sdk_version: "9",
+    proto: {
+        type: "nano",
+        output_params: ["store_unknown_fields=true"],
+        include_dirs: ["external/protobuf/src"],
+    },
+    srcs: [
+        "src/atoms.proto",
+        "src/shell/shell_config.proto",
+        "src/shell/shell_data.proto",
+        "src/stats_log.proto",
+        "src/statsd_config.proto",
+    ],
+    static_libs: [
+        "platformprotosnano",
+    ],
+    // Protos have lots of MissingOverride and similar.
+    errorprone: {
+        javacflags: ["-XepDisableAllChecks"],
+    },
+}
+
 // Filegroup for statsd config proto definition.
 filegroup {
     name: "statsd-config-proto-def",
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 6eba5c6..3d67e65 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -497,13 +497,14 @@
         ModemRestart modem_restart = 312 [(module) = "telephony"];
         CarrierIdMismatchEvent carrier_id_mismatch_event = 313 [(module) = "telephony"];
         CarrierIdMatchingTable carrier_id_table_update = 314 [(module) = "telephony"];
+        DataStallRecoveryReported data_stall_recovery_reported = 315 [(module) = "telephony"];
 
         // StatsdStats tracks platform atoms with ids upto 500.
         // Update StatsdStats::kMaxPushedAtomId when atom ids here approach that value.
     }
 
     // Pulled events will start at field 10000.
-    // Next: 10089
+    // Next: 10092
     oneof pulled {
         WifiBytesTransfer wifi_bytes_transfer = 10000 [(module) = "framework"];
         WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001 [(module) = "framework"];
@@ -605,6 +606,9 @@
         IncomingSms incoming_sms = 10086 [(module) = "telephony"];
         OutgoingSms outgoing_sms = 10087 [(module) = "telephony"];
         CarrierIdMatchingTable carrier_id_table_version = 10088 [(module) = "telephony"];
+        DataCallSession data_call_session = 10089 [(module) = "telephony"];
+        CellularServiceState cellular_service_state = 10090 [(module) = "telephony"];
+        CellularDataServiceSwitch cellular_data_service_switch = 10091 [(module) = "telephony"];
     }
 
     // DO NOT USE field numbers above 100,000 in AOSP.
@@ -10396,7 +10400,7 @@
     // Number of other calls going on during call termination, for the same SIM slot.
     optional int32 concurrent_call_count_at_end = 14;
 
-    // Index of the SIM is used, 0 for single-SIM devices.
+    // Index of the SIM used, 0 for single-SIM devices.
     optional int32 sim_slot_index = 15;
 
     // Whether the device was in multi-SIM mode (with multiple active SIM profiles).
@@ -10448,7 +10452,7 @@
     // Radio access technology.
     optional android.telephony.NetworkTypeEnum rat = 2;
 
-    // Total duration that voice calls spent on this carrier and RAT.
+    // Total duration that voice calls spent on this carrier and RAT, rounded to 5 minute.
     optional int64 total_duration_seconds = 3;
 
     // Total number of calls using this carrier and RAT.
@@ -10457,6 +10461,82 @@
 }
 
 /**
+ * Pulls amount of time spend in each cellular service state.
+ *
+ * Each pull creates multiple atoms, one for each SIM slot/carrier/RAT(including ENDC), the order of
+ * which is irrelevant to time. If multi SIM settings changes during the period, durations will be
+ * counted separately before and after the change. Airplane mode does not count towards durations.
+ *
+ * Pulled from:
+ *   frameworks/opt/telephony/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
+ */
+message CellularServiceState {
+    // Radio access technology (RAT) for voice.
+    // NETWORK_TYPE_UNKNOWN when the device is out of service.
+    // NETWORK_TYPE_IWLAN when the device is using VoWiFi.
+    optional android.telephony.NetworkTypeEnum voice_rat = 1;
+
+    // Radio access technology (RAT) for data.
+    // NETWORK_TYPE_UNKNOWN when the device is out of service.
+    // Only cellular RATs are valid and show where the device is camped.
+    optional android.telephony.NetworkTypeEnum data_rat = 2;
+
+    // Whether the device was in roaming (domestic or international) for voice.
+    optional android.telephony.RoamingTypeEnum voice_roaming_type = 3;
+
+    // Whether the device was in roaming (domestic or international) for data.
+    optional android.telephony.RoamingTypeEnum data_roaming_type = 4;
+
+    // Whether the device is on LTE and has access to NR NSA, i.e. cell supports 5G (ENDC) and UE
+    // registration (attach/TAU) indicates ENDC is not restricted.
+    optional bool is_endc = 5;
+
+    // Index of the SIM used, 0 for single-SIM devices.
+    optional int32 sim_slot_index = 6;
+
+    // Whether the device was in multi-SIM mode (with multiple active SIM profiles).
+    optional bool is_multi_sim = 7;
+
+    // Carrier ID of the SIM card.
+    // See https://source.android.com/devices/tech/config/carrierid.
+    optional int32 carrier_id = 8;
+
+    // Total time spent in this service state, rounded to 5 minutes.
+    optional int32 total_time_seconds = 9;
+}
+
+/**
+ * Pulls the number of times cellular data service state switches.
+ *
+ * Each pull creates multiple atoms, one for each RAT combination, the order of which is irrelevant
+ * to time. Switches for different SIM slots, carrier IDs, or multi-SIM settings are counted
+ * separately.
+ *
+ * Pulled from:
+ *   frameworks/opt/telephony/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
+ */
+message CellularDataServiceSwitch {
+    // Cellular RAT of the DATA domain from where the switch occurred.
+    optional android.telephony.NetworkTypeEnum rat_from = 1;
+
+    // Cellular RAT of the DATA domain to where the switch occurred.
+    optional android.telephony.NetworkTypeEnum rat_to = 2;
+
+    // Index of the SIM used, 0 for single-SIM devices.
+    optional int32 sim_slot_index = 3;
+
+    // Whether the device was in multi-SIM mode (with multiple active SIM profiles).
+    optional bool is_multi_sim = 4;
+
+    // Carrier ID of the SIM card.
+    // See https://source.android.com/devices/tech/config/carrierid.
+    optional int32 carrier_id = 5;
+
+    // Number of switches from rat_from to rat_to.
+    optional int32 switch_count = 6;
+}
+
+/**
  * Pulls the number of active SIM slots and SIMs/eSIM profiles.
  *
  * Pulled from:
@@ -10525,7 +10605,7 @@
     // Whether the SMS was received while roaming.
     optional bool is_roaming = 9;
 
-    // Index of the SIM is used, 0 for single-SIM devices.
+    // Index of the SIM used, 0 for single-SIM devices.
     optional int32 sim_slot_index = 10;
 
     // Whether the device was in multi-SIM mode (with multiple active SIM profiles).
@@ -10577,7 +10657,7 @@
     // Whether the default SMS application generated the SMS (regardless of which application).
     optional bool is_from_default_app = 7;
 
-    // Index of the SIM is used, 0 for single-SIM devices.
+    // Index of the SIM used, 0 for single-SIM devices.
     optional int32 sim_slot_index = 8;
 
     // Whether the device was in multi-SIM mode (with multiple active SIM profiles).
@@ -10672,6 +10752,104 @@
 }
 
 /**
+ * Pulls information for a single data call session
+ *
+ * Each pull creates multiple atoms, one for each data call session.
+ * The sequence is randomized when pulled.
+ *
+ * Pulled from:
+ *   frameworks/opt/telephony/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
+ */
+message DataCallSession {
+    // A random number to be used as dimension to capture multiple atoms
+    optional int32 dimension = 1;
+
+    // Whether the device was in multi-SIM mode (with multiple active SIM profiles).
+    optional bool is_multi_sim = 2;
+
+    // Whether the call was made with an eSIM profile.
+    optional bool is_esim = 3;
+
+    // Data profile of this call (for what purpose this call was made)
+    optional android.telephony.DataProfileEnum profile = 4;
+
+    // APN type bitmask of the APN used:
+    // @ApnType in frameworks/base/telephony/java/android/telephony/Annotation.java.
+    optional int32 apn_type_bitmask = 5;
+
+    // Carrier ID of the SIM
+    // See https://source.android.com/devices/tech/config/carrierid.
+    optional int32 carrier_id = 6;
+
+    // Whether the subscription is roaming
+    optional bool is_roaming = 7;
+
+    // Data RAT when the call ended, can be IWLAN for IMS/MMS, otherwise should be WWAN PS RAT.
+    // In the case that the connection hasn't ended yet, this field holds the current RAT.
+    // In the case the call ended due to Out Of Service (OOS),
+    // this field should be the last known RAT.
+    optional android.telephony.NetworkTypeEnum rat_at_end = 8;
+
+    // Was the data call ended due to OOS
+    optional bool oos_at_end = 9;
+
+    // Number of RAT switches during the data call
+    optional int64 rat_switch_count = 10;
+
+    // Whether the call is on an opportunistic subscription
+    optional bool is_opportunistic = 11;
+
+    // Packet data protocol used
+    optional android.telephony.ApnProtocolEnum ip_type = 12;
+
+    // Whether the data call terminated before being established
+    optional bool setup_failed = 13;
+
+    // Reason why the data call terminated, as in RIL_DataCallFailCause from ril.h
+    optional int32 failure_cause = 14;
+
+    // Suggested retry back-off timer value from RIL
+    optional int32 suggested_retry_millis = 15;
+
+    // Why the data call was deactivated
+    // Set by telephony for MO deactivations (unrelated to failure_cause)
+    optional android.telephony.DataDeactivateReasonEnum deactivate_reason = 16;
+
+    // Duration of the data call, rounded into the closest 5 minutes.
+    optional int64 duration_minutes = 17;
+
+    // Whether the data call is still connected when the atom is collected.
+    optional bool ongoing = 18;
+}
+
+/**
+ * Logs data stall recovery event
+ *
+ * Logged from:
+ *   frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
+ */
+message DataStallRecoveryReported {
+    // Carrier ID of the SIM
+    // See https://source.android.com/devices/tech/config/carrierid.
+    optional int32 carrier_id = 1;
+
+    // Data RAT when the stall happened
+    optional android.telephony.NetworkTypeEnum rat = 2;
+
+    // Signal strength when stall happened
+    optional android.telephony.SignalStrengthEnum signal_strength = 3;
+
+    // Action taken to recover
+    optional android.telephony.DataStallRecoveryActionEnum action = 4;
+
+    // Whether the subscription is opportunistic
+    optional bool is_opportunistic = 5;
+
+    // Whether the device is in multi-SIM mode
+    optional bool is_multi_sim = 6;
+}
+
+/**
  * Logs gnss stats from location service provider
  *
  * Pulled from:
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index 3acafaa..b2c0b32 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -17,14 +17,17 @@
 #define DEBUG false
 
 #include "Log.h"
+
 #include "DurationMetricProducer.h"
-#include "guardrail/StatsdStats.h"
-#include "stats_util.h"
-#include "stats_log_util.h"
 
 #include <limits.h>
 #include <stdlib.h>
 
+#include "guardrail/StatsdStats.h"
+#include "metrics/parsing_utils/metrics_manager_util.h"
+#include "stats_log_util.h"
+#include "stats_util.h"
+
 using android::util::FIELD_COUNT_REPEATED;
 using android::util::FIELD_TYPE_BOOL;
 using android::util::FIELD_TYPE_FLOAT;
@@ -64,8 +67,8 @@
 
 DurationMetricProducer::DurationMetricProducer(
         const ConfigKey& key, const DurationMetric& metric, const int conditionIndex,
-        const vector<ConditionState>& initialConditionCache, const size_t startIndex,
-        const size_t stopIndex, const size_t stopAllIndex, const bool nesting,
+        const vector<ConditionState>& initialConditionCache, const int startIndex,
+        const int stopIndex, const int stopAllIndex, const bool nesting,
         const sp<ConditionWizard>& wizard, const uint64_t protoHash,
         const FieldMatcher& internalDimensions, const int64_t timeBaseNs, const int64_t startTimeNs,
         const unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
@@ -143,6 +146,84 @@
     VLOG("~DurationMetric() called");
 }
 
+bool DurationMetricProducer::onConfigUpdatedLocked(
+        const StatsdConfig& config, const int configIndex, const int metricIndex,
+        const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+        const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+        const unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+        const sp<EventMatcherWizard>& matcherWizard,
+        const vector<sp<ConditionTracker>>& allConditionTrackers,
+        const unordered_map<int64_t, int>& conditionTrackerMap, const sp<ConditionWizard>& wizard,
+        const unordered_map<int64_t, int>& metricToActivationMap,
+        unordered_map<int, vector<int>>& trackerToMetricMap,
+        unordered_map<int, vector<int>>& conditionToMetricMap,
+        unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
+        unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
+        vector<int>& metricsWithActivation) {
+    if (!MetricProducer::onConfigUpdatedLocked(
+                config, configIndex, metricIndex, allAtomMatchingTrackers,
+                oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, matcherWizard,
+                allConditionTrackers, conditionTrackerMap, wizard, metricToActivationMap,
+                trackerToMetricMap, conditionToMetricMap, activationAtomTrackerToMetricMap,
+                deactivationAtomTrackerToMetricMap, metricsWithActivation)) {
+        return false;
+    }
+
+    const DurationMetric& metric = config.duration_metric(configIndex);
+    const auto& what_it = conditionTrackerMap.find(metric.what());
+    if (what_it == conditionTrackerMap.end()) {
+        ALOGE("DurationMetric's \"what\" is not present in the config");
+        return false;
+    }
+
+    const Predicate& durationWhat = config.predicate(what_it->second);
+    if (durationWhat.contents_case() != Predicate::ContentsCase::kSimplePredicate) {
+        ALOGE("DurationMetric's \"what\" must be a simple condition");
+        return false;
+    }
+
+    const SimplePredicate& simplePredicate = durationWhat.simple_predicate();
+
+    // Update indices: mStartIndex, mStopIndex, mStopAllIndex, mConditionIndex and MetricsManager
+    // maps.
+    if (!handleMetricWithAtomMatchingTrackers(simplePredicate.start(), metricIndex,
+                                              metric.has_dimensions_in_what(),
+                                              allAtomMatchingTrackers, newAtomMatchingTrackerMap,
+                                              trackerToMetricMap, mStartIndex)) {
+        ALOGE("Duration metrics must specify a valid start event matcher");
+        return false;
+    }
+
+    if (simplePredicate.has_stop() &&
+        !handleMetricWithAtomMatchingTrackers(simplePredicate.stop(), metricIndex,
+                                              metric.has_dimensions_in_what(),
+                                              allAtomMatchingTrackers, newAtomMatchingTrackerMap,
+                                              trackerToMetricMap, mStopIndex)) {
+        return false;
+    }
+
+    if (simplePredicate.has_stop_all() &&
+        !handleMetricWithAtomMatchingTrackers(simplePredicate.stop_all(), metricIndex,
+                                              metric.has_dimensions_in_what(),
+                                              allAtomMatchingTrackers, newAtomMatchingTrackerMap,
+                                              trackerToMetricMap, mStopAllIndex)) {
+        return false;
+    }
+
+    if (metric.has_condition() &&
+        !handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
+                                    metric.links(), allConditionTrackers, mConditionTrackerIndex,
+                                    conditionToMetricMap)) {
+        return false;
+    }
+
+    for (const auto& it : mCurrentSlicedDurationTrackerMap) {
+        it.second->onConfigUpdated(wizard, mConditionTrackerIndex);
+    }
+
+    return true;
+}
+
 sp<AnomalyTracker> DurationMetricProducer::addAnomalyTracker(
         const Alert &alert, const sp<AlarmMonitor>& anomalyAlarmMonitor) {
     std::lock_guard<std::mutex> lock(mMutex);
@@ -550,7 +631,7 @@
     }
 
     // Handles Stopall events.
-    if (matcherIndex == mStopAllIndex) {
+    if ((int)matcherIndex == mStopAllIndex) {
         for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
             whatIt.second->noteStopAll(event.GetElapsedTimestampNs());
         }
@@ -598,7 +679,7 @@
     }
 
     // Handles Stop events.
-    if (matcherIndex == mStopIndex) {
+    if ((int)matcherIndex == mStopIndex) {
         if (mUseWhatDimensionAsInternalDimension) {
             auto whatIt = mCurrentSlicedDurationTrackerMap.find(dimensionInWhat);
             if (whatIt != mCurrentSlicedDurationTrackerMap.end()) {
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index 3a94d9c..01198a9 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -40,8 +40,8 @@
 public:
     DurationMetricProducer(
             const ConfigKey& key, const DurationMetric& durationMetric, const int conditionIndex,
-            const vector<ConditionState>& initialConditionCache, const size_t startIndex,
-            const size_t stopIndex, const size_t stopAllIndex, const bool nesting,
+            const vector<ConditionState>& initialConditionCache, const int startIndex,
+            const int stopIndex, const int stopAllIndex, const bool nesting,
             const sp<ConditionWizard>& wizard, const uint64_t protoHash,
             const FieldMatcher& internalDimensions, const int64_t timeBaseNs,
             const int64_t startTimeNs,
@@ -112,16 +112,32 @@
     void flushCurrentBucketLocked(const int64_t& eventTimeNs,
                                   const int64_t& nextBucketStartTimeNs) override;
 
+    bool onConfigUpdatedLocked(
+            const StatsdConfig& config, const int configIndex, const int metricIndex,
+            const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+            const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+            const std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+            const sp<EventMatcherWizard>& matcherWizard,
+            const std::vector<sp<ConditionTracker>>& allConditionTrackers,
+            const std::unordered_map<int64_t, int>& conditionTrackerMap,
+            const sp<ConditionWizard>& wizard,
+            const std::unordered_map<int64_t, int>& metricToActivationMap,
+            std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
+            std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
+            std::unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
+            std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
+            std::vector<int>& metricsWithActivation) override;
+
     const DurationMetric_AggregationType mAggregationType;
 
     // Index of the SimpleAtomMatcher which defines the start.
-    const size_t mStartIndex;
+    int mStartIndex;
 
     // Index of the SimpleAtomMatcher which defines the stop.
-    const size_t mStopIndex;
+    int mStopIndex;
 
     // Index of the SimpleAtomMatcher which defines the stop all for all dimensions.
-    const size_t mStopAllIndex;
+    int mStopAllIndex;
 
     // nest counting -- for the same key, stops must match the number of starts to make real stop
     const bool mNested;
@@ -167,6 +183,8 @@
                 TestSumDurationWithSplitInFollowingBucket);
     FRIEND_TEST(DurationMetricProducerTest_PartialBucket, TestMaxDuration);
     FRIEND_TEST(DurationMetricProducerTest_PartialBucket, TestMaxDurationWithSplitInNextBucket);
+
+    FRIEND_TEST(ConfigUpdateTest, TestUpdateDurationMetrics);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index 18e62d2..92c1a6e 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -569,6 +569,7 @@
     FRIEND_TEST(ConfigUpdateTest, TestUpdateCountMetrics);
     FRIEND_TEST(ConfigUpdateTest, TestUpdateEventMetrics);
     FRIEND_TEST(ConfigUpdateTest, TestUpdateGaugeMetrics);
+    FRIEND_TEST(ConfigUpdateTest, TestUpdateDurationMetrics);
     FRIEND_TEST(ConfigUpdateTest, TestUpdateMetricsMultipleTypes);
 };
 
diff --git a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
index 8d59d13..657b2e4 100644
--- a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
@@ -89,6 +89,12 @@
 
     virtual ~DurationTracker(){};
 
+    void onConfigUpdated(const sp<ConditionWizard>& wizard, const int conditionTrackerIndex) {
+        sp<ConditionWizard> tmpWizard = mWizard;
+        mWizard = wizard;
+        mConditionTrackerIndex = conditionTrackerIndex;
+    };
+
     virtual void noteStart(const HashableDimensionKey& key, bool condition, const int64_t eventTime,
                            const ConditionKey& conditionKey) = 0;
     virtual void noteStop(const HashableDimensionKey& key, const int64_t eventTime,
@@ -191,7 +197,7 @@
 
     sp<ConditionWizard> mWizard;
 
-    const int mConditionTrackerIndex;
+    int mConditionTrackerIndex;
 
     const int64_t mBucketSizeNs;
 
@@ -217,6 +223,8 @@
     FRIEND_TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp);
     FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetectionExpiredAlarm);
     FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetectionFiredAlarm);
+
+    FRIEND_TEST(ConfigUpdateTest, TestUpdateDurationMetrics);
 };
 
 }  // namespace statsd
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 d32f5a9..cfc6e3f 100644
--- a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
+++ b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
@@ -697,6 +697,43 @@
         }
         newMetricProducers.push_back(producer.value());
     }
+    for (int i = 0; i < config.duration_metric_size(); i++, metricIndex++) {
+        const DurationMetric& metric = config.duration_metric(i);
+        newMetricProducerMap[metric.id()] = metricIndex;
+        optional<sp<MetricProducer>> producer;
+        switch (metricsToUpdate[metricIndex]) {
+            case UPDATE_PRESERVE: {
+                producer = updateMetric(
+                        config, i, metricIndex, metric.id(), allAtomMatchingTrackers,
+                        oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, matcherWizard,
+                        allConditionTrackers, conditionTrackerMap, wizard, oldMetricProducerMap,
+                        oldMetricProducers, metricToActivationMap, trackerToMetricMap,
+                        conditionToMetricMap, activationAtomTrackerToMetricMap,
+                        deactivationAtomTrackerToMetricMap, metricsWithActivation);
+                break;
+            }
+            case UPDATE_REPLACE:
+            case UPDATE_NEW: {
+                producer = createDurationMetricProducerAndUpdateMetadata(
+                        key, config, timeBaseNs, currentTimeNs, metric, metricIndex,
+                        allAtomMatchingTrackers, newAtomMatchingTrackerMap, allConditionTrackers,
+                        conditionTrackerMap, initialConditionCache, wizard, stateAtomIdMap,
+                        allStateGroupMaps, metricToActivationMap, trackerToMetricMap,
+                        conditionToMetricMap, activationAtomTrackerToMetricMap,
+                        deactivationAtomTrackerToMetricMap, metricsWithActivation);
+                break;
+            }
+            default: {
+                ALOGE("Metric \"%lld\" update state is unknown. This should never happen",
+                      (long long)metric.id());
+                return false;
+            }
+        }
+        if (!producer) {
+            return false;
+        }
+        newMetricProducers.push_back(producer.value());
+    }
     for (int i = 0; i < config.event_metric_size(); i++, metricIndex++) {
         newMetricProducerMap[config.event_metric(i).id()] = metricIndex;
         const EventMetric& metric = config.event_metric(i);
@@ -770,7 +807,7 @@
         }
         newMetricProducers.push_back(producer.value());
     }
-    // TODO: perform update for value, duration metric.
+    // TODO: perform update for value metric.
 
     const set<int> atomsAllowedFromAnyUid(config.whitelisted_atom_ids().begin(),
                                           config.whitelisted_atom_ids().end());
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 34e265c..b7dc2c7 100644
--- a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
@@ -365,7 +365,7 @@
         unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
         vector<int>& metricsWithActivation) {
     if (!metric.has_id() || !metric.has_what()) {
-        ALOGW("cannot find metric id or \"what\" in CountMetric \"%lld\"", (long long)metric.id());
+        ALOGE("cannot find metric id or \"what\" in CountMetric \"%lld\"", (long long)metric.id());
         return nullopt;
     }
     int trackerIndex;
@@ -423,6 +423,125 @@
                                     eventDeactivationMap, slicedStateAtoms, stateGroupMap)};
 }
 
+optional<sp<MetricProducer>> createDurationMetricProducerAndUpdateMetadata(
+        const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
+        const int64_t currentTimeNs, const DurationMetric& metric, const int metricIndex,
+        const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+        const unordered_map<int64_t, int>& atomMatchingTrackerMap,
+        vector<sp<ConditionTracker>>& allConditionTrackers,
+        const unordered_map<int64_t, int>& conditionTrackerMap,
+        const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
+        const unordered_map<int64_t, int>& stateAtomIdMap,
+        const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
+        const unordered_map<int64_t, int>& metricToActivationMap,
+        unordered_map<int, vector<int>>& trackerToMetricMap,
+        unordered_map<int, vector<int>>& conditionToMetricMap,
+        unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
+        unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
+        vector<int>& metricsWithActivation) {
+    if (!metric.has_id() || !metric.has_what()) {
+        ALOGE("cannot find metric id or \"what\" in DurationMetric \"%lld\"",
+              (long long)metric.id());
+        return nullopt;
+    }
+    const auto& what_it = conditionTrackerMap.find(metric.what());
+    if (what_it == conditionTrackerMap.end()) {
+        ALOGE("DurationMetric's \"what\" is not present in the condition trackers");
+        return nullopt;
+    }
+
+    const Predicate& durationWhat = config.predicate(what_it->second);
+    if (durationWhat.contents_case() != Predicate::ContentsCase::kSimplePredicate) {
+        ALOGE("DurationMetric's \"what\" must be a simple condition");
+        return nullopt;
+    }
+
+    const SimplePredicate& simplePredicate = durationWhat.simple_predicate();
+    bool nesting = simplePredicate.count_nesting();
+
+    int startIndex = -1, stopIndex = -1, stopAllIndex = -1;
+    if (!simplePredicate.has_start() ||
+        !handleMetricWithAtomMatchingTrackers(
+                simplePredicate.start(), metricIndex, metric.has_dimensions_in_what(),
+                allAtomMatchingTrackers, atomMatchingTrackerMap, trackerToMetricMap, startIndex)) {
+        ALOGE("Duration metrics must specify a valid start event matcher");
+        return nullopt;
+    }
+
+    if (simplePredicate.has_stop() &&
+        !handleMetricWithAtomMatchingTrackers(
+                simplePredicate.stop(), metricIndex, metric.has_dimensions_in_what(),
+                allAtomMatchingTrackers, atomMatchingTrackerMap, trackerToMetricMap, stopIndex)) {
+        return nullopt;
+    }
+
+    if (simplePredicate.has_stop_all() &&
+        !handleMetricWithAtomMatchingTrackers(simplePredicate.stop_all(), metricIndex,
+                                              metric.has_dimensions_in_what(),
+                                              allAtomMatchingTrackers, atomMatchingTrackerMap,
+                                              trackerToMetricMap, stopAllIndex)) {
+        return nullopt;
+    }
+
+    FieldMatcher internalDimensions = simplePredicate.dimensions();
+
+    int conditionIndex = -1;
+    if (metric.has_condition()) {
+        if (!handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
+                                        metric.links(), allConditionTrackers, conditionIndex,
+                                        conditionToMetricMap)) {
+            return nullopt;
+        }
+    } else if (metric.links_size() > 0) {
+        ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
+        return nullopt;
+    }
+
+    std::vector<int> slicedStateAtoms;
+    unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
+    if (metric.slice_by_state_size() > 0) {
+        if (metric.aggregation_type() == DurationMetric::MAX_SPARSE) {
+            ALOGE("DurationMetric with aggregation type MAX_SPARSE cannot be sliced by state");
+            return nullopt;
+        }
+        if (!handleMetricWithStates(config, metric.slice_by_state(), stateAtomIdMap,
+                                    allStateGroupMaps, slicedStateAtoms, stateGroupMap)) {
+            return nullopt;
+        }
+    } else if (metric.state_link_size() > 0) {
+        ALOGW("DurationMetric has a MetricStateLink but doesn't have a sliced state");
+        return nullopt;
+    }
+
+    // Check that all metric state links are a subset of dimensions_in_what fields.
+    std::vector<Matcher> dimensionsInWhat;
+    translateFieldMatcher(metric.dimensions_in_what(), &dimensionsInWhat);
+    for (const auto& stateLink : metric.state_link()) {
+        if (!handleMetricWithStateLink(stateLink.fields_in_what(), dimensionsInWhat)) {
+            return nullopt;
+        }
+    }
+
+    unordered_map<int, shared_ptr<Activation>> eventActivationMap;
+    unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
+    if (!handleMetricActivation(config, metric.id(), metricIndex, metricToActivationMap,
+                                atomMatchingTrackerMap, activationAtomTrackerToMetricMap,
+                                deactivationAtomTrackerToMetricMap, metricsWithActivation,
+                                eventActivationMap, eventDeactivationMap)) {
+        return nullopt;
+    }
+
+    uint64_t metricHash;
+    if (!getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash)) {
+        return nullopt;
+    }
+
+    return {new DurationMetricProducer(
+            key, metric, conditionIndex, initialConditionCache, startIndex, stopIndex, stopAllIndex,
+            nesting, wizard, metricHash, internalDimensions, timeBaseNs, currentTimeNs,
+            eventActivationMap, eventDeactivationMap, slicedStateAtoms, stateGroupMap)};
+}
+
 optional<sp<MetricProducer>> createEventMetricProducerAndUpdateMetadata(
         const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
         const EventMetric& metric, const int metricIndex,
@@ -438,7 +557,7 @@
         unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
         vector<int>& metricsWithActivation) {
     if (!metric.has_id() || !metric.has_what()) {
-        ALOGW("cannot find the metric name or what in config");
+        ALOGE("cannot find the metric name or what in config");
         return nullopt;
     }
     int trackerIndex;
@@ -497,7 +616,7 @@
         unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
         vector<int>& metricsWithActivation) {
     if (!metric.has_id() || !metric.has_what()) {
-        ALOGW("cannot find metric id or \"what\" in GaugeMetric \"%lld\"", (long long)metric.id());
+        ALOGE("cannot find metric id or \"what\" in GaugeMetric \"%lld\"", (long long)metric.id());
         return nullopt;
     }
 
@@ -760,114 +879,17 @@
         const DurationMetric& metric = config.duration_metric(i);
         metricMap.insert({metric.id(), metricIndex});
 
-        auto what_it = conditionTrackerMap.find(metric.what());
-        if (what_it == conditionTrackerMap.end()) {
-            ALOGE("DurationMetric's \"what\" is invalid");
-            return false;
-        }
-
-        const Predicate& durationWhat = config.predicate(what_it->second);
-
-        if (durationWhat.contents_case() != Predicate::ContentsCase::kSimplePredicate) {
-            ALOGE("DurationMetric's \"what\" must be a simple condition");
-            return false;
-        }
-
-        const auto& simplePredicate = durationWhat.simple_predicate();
-
-        bool nesting = simplePredicate.count_nesting();
-
-        int trackerIndices[3] = {-1, -1, -1};
-        if (!simplePredicate.has_start() ||
-            !handleMetricWithAtomMatchingTrackers(simplePredicate.start(), metricIndex,
-                                                  metric.has_dimensions_in_what(),
-                                                  allAtomMatchingTrackers, atomMatchingTrackerMap,
-                                                  trackerToMetricMap, trackerIndices[0])) {
-            ALOGE("Duration metrics must specify a valid the start event matcher");
-            return false;
-        }
-
-        if (simplePredicate.has_stop() &&
-            !handleMetricWithAtomMatchingTrackers(simplePredicate.stop(), metricIndex,
-                                                  metric.has_dimensions_in_what(),
-                                                  allAtomMatchingTrackers, atomMatchingTrackerMap,
-                                                  trackerToMetricMap, trackerIndices[1])) {
-            return false;
-        }
-
-        if (simplePredicate.has_stop_all() &&
-            !handleMetricWithAtomMatchingTrackers(simplePredicate.stop_all(), metricIndex,
-                                                  metric.has_dimensions_in_what(),
-                                                  allAtomMatchingTrackers, atomMatchingTrackerMap,
-                                                  trackerToMetricMap, trackerIndices[2])) {
-            return false;
-        }
-
-        FieldMatcher internalDimensions = simplePredicate.dimensions();
-
-        int conditionIndex = -1;
-
-        if (metric.has_condition()) {
-            bool good = handleMetricWithConditions(
-                    metric.condition(), metricIndex, conditionTrackerMap, metric.links(),
-                    allConditionTrackers, conditionIndex, conditionToMetricMap);
-            if (!good) {
-                return false;
-            }
-        } else {
-            if (metric.links_size() > 0) {
-                ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
-                return false;
-            }
-        }
-
-        std::vector<int> slicedStateAtoms;
-        unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
-        if (metric.slice_by_state_size() > 0) {
-            if (metric.aggregation_type() == DurationMetric::MAX_SPARSE) {
-                ALOGE("DurationMetric with aggregation type MAX_SPARSE cannot be sliced by state");
-                return false;
-            }
-            if (!handleMetricWithStates(config, metric.slice_by_state(), stateAtomIdMap,
-                                        allStateGroupMaps, slicedStateAtoms, stateGroupMap)) {
-                return false;
-            }
-        } else {
-            if (metric.state_link_size() > 0) {
-                ALOGW("DurationMetric has a MetricStateLink but doesn't have a sliced state");
-                return false;
-            }
-        }
-
-        // Check that all metric state links are a subset of dimensions_in_what fields.
-        std::vector<Matcher> dimensionsInWhat;
-        translateFieldMatcher(metric.dimensions_in_what(), &dimensionsInWhat);
-        for (const auto& stateLink : metric.state_link()) {
-            if (!handleMetricWithStateLink(stateLink.fields_in_what(), dimensionsInWhat)) {
-                return false;
-            }
-        }
-
-        unordered_map<int, shared_ptr<Activation>> eventActivationMap;
-        unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
-        bool success = handleMetricActivation(
-                config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
+        optional<sp<MetricProducer>> producer = createDurationMetricProducerAndUpdateMetadata(
+                key, config, timeBaseTimeNs, currentTimeNs, metric, metricIndex,
+                allAtomMatchingTrackers, atomMatchingTrackerMap, allConditionTrackers,
+                conditionTrackerMap, initialConditionCache, wizard, stateAtomIdMap,
+                allStateGroupMaps, metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
                 activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
-                metricsWithActivation, eventActivationMap, eventDeactivationMap);
-        if (!success) return false;
-
-        uint64_t metricHash;
-        if (!getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash)) {
+                metricsWithActivation);
+        if (!producer) {
             return false;
         }
-
-        sp<MetricProducer> durationMetric = new DurationMetricProducer(
-                key, metric, conditionIndex, initialConditionCache, trackerIndices[0],
-                trackerIndices[1], trackerIndices[2], nesting, wizard, metricHash,
-                internalDimensions, timeBaseTimeNs, currentTimeNs, eventActivationMap,
-                eventDeactivationMap, slicedStateAtoms, stateGroupMap);
-
-        allMetricProducers.push_back(durationMetric);
+        allMetricProducers.push_back(producer.value());
     }
 
     // build EventMetricProducer
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 f909aff..6d1e6dd 100644
--- a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
+++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
@@ -112,6 +112,25 @@
         std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
         std::vector<int>& metricsWithActivation);
 
+// Creates a DurationMetricProducer and updates the vectors/maps used by MetricsManager with
+// the appropriate indices. Returns an sp to the producer, or nullopt if there was an error.
+optional<sp<MetricProducer>> createDurationMetricProducerAndUpdateMetadata(
+        const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
+        const int64_t currentTimeNs, const DurationMetric& metric, const int metricIndex,
+        const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+        const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
+        std::vector<sp<ConditionTracker>>& allConditionTrackers,
+        const std::unordered_map<int64_t, int>& conditionTrackerMap,
+        const std::vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
+        const std::unordered_map<int64_t, int>& stateAtomIdMap,
+        const std::unordered_map<int64_t, std::unordered_map<int, int64_t>>& allStateGroupMaps,
+        const std::unordered_map<int64_t, int>& metricToActivationMap,
+        std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
+        std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
+        std::unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
+        std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
+        std::vector<int>& metricsWithActivation);
+
 // Creates an EventMetricProducer and updates the vectors/maps used by MetricsManager with
 // the appropriate indices. Returns an sp to the producer, or nullopt if there was an error.
 optional<sp<MetricProducer>> createEventMetricProducerAndUpdateMetadata(
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 a20be15..dc951be 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
@@ -27,6 +27,7 @@
 #include "src/condition/CombinationConditionTracker.h"
 #include "src/condition/SimpleConditionTracker.h"
 #include "src/matchers/CombinationAtomMatchingTracker.h"
+#include "src/metrics/DurationMetricProducer.h"
 #include "src/metrics/GaugeMetricProducer.h"
 #include "src/metrics/parsing_utils/metrics_manager_util.h"
 #include "tests/statsd_test_util.h"
@@ -2212,6 +2213,352 @@
     EXPECT_EQ(oldMatcherWizard->getStrongCount(), 1);
 }
 
+TEST_F(ConfigUpdateTest, TestUpdateDurationMetrics) {
+    StatsdConfig config;
+    // Add atom matchers/predicates/states. These are mostly needed for initStatsdConfig.
+    AtomMatcher matcher1 = CreateScreenTurnedOnAtomMatcher();
+    int64_t matcher1Id = matcher1.id();
+    *config.add_atom_matcher() = matcher1;
+
+    AtomMatcher matcher2 = CreateScreenTurnedOffAtomMatcher();
+    int64_t matcher2Id = matcher2.id();
+    *config.add_atom_matcher() = matcher2;
+
+    AtomMatcher matcher3 = CreateAcquireWakelockAtomMatcher();
+    int64_t matcher3Id = matcher3.id();
+    *config.add_atom_matcher() = matcher3;
+
+    AtomMatcher matcher4 = CreateReleaseWakelockAtomMatcher();
+    int64_t matcher4Id = matcher4.id();
+    *config.add_atom_matcher() = matcher4;
+
+    AtomMatcher matcher5 = CreateMoveToForegroundAtomMatcher();
+    int64_t matcher5Id = matcher5.id();
+    *config.add_atom_matcher() = matcher5;
+
+    AtomMatcher matcher6 = CreateMoveToBackgroundAtomMatcher();
+    int64_t matcher6Id = matcher6.id();
+    *config.add_atom_matcher() = matcher6;
+
+    AtomMatcher matcher7 = CreateBatteryStateNoneMatcher();
+    int64_t matcher7Id = matcher7.id();
+    *config.add_atom_matcher() = matcher7;
+
+    AtomMatcher matcher8 = CreateBatteryStateUsbMatcher();
+    int64_t matcher8Id = matcher8.id();
+    *config.add_atom_matcher() = matcher8;
+
+    Predicate predicate1 = CreateScreenIsOnPredicate();
+    int64_t predicate1Id = predicate1.id();
+    *config.add_predicate() = predicate1;
+
+    Predicate predicate2 = CreateScreenIsOffPredicate();
+    int64_t predicate2Id = predicate2.id();
+    *config.add_predicate() = predicate2;
+
+    Predicate predicate3 = CreateDeviceUnpluggedPredicate();
+    int64_t predicate3Id = predicate3.id();
+    *config.add_predicate() = predicate3;
+
+    Predicate predicate4 = CreateIsInBackgroundPredicate();
+    *predicate4.mutable_simple_predicate()->mutable_dimensions() =
+            CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1});
+    int64_t predicate4Id = predicate4.id();
+    *config.add_predicate() = predicate4;
+
+    Predicate predicate5 = CreateHoldingWakelockPredicate();
+    *predicate5.mutable_simple_predicate()->mutable_dimensions() =
+            CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+    predicate5.mutable_simple_predicate()->set_stop_all(matcher7Id);
+    int64_t predicate5Id = predicate5.id();
+    *config.add_predicate() = predicate5;
+
+    State state1 = CreateScreenStateWithOnOffMap(0x123, 0x321);
+    int64_t state1Id = state1.id();
+    *config.add_state() = state1;
+
+    State state2 = CreateScreenState();
+    int64_t state2Id = state2.id();
+    *config.add_state() = state2;
+
+    // Add a few duration metrics.
+    // Will be preserved.
+    DurationMetric duration1 =
+            createDurationMetric("DURATION1", predicate5Id, predicate4Id, {state2Id});
+    *duration1.mutable_dimensions_in_what() =
+            CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+    MetricConditionLink* link = duration1.add_links();
+    link->set_condition(predicate4Id);
+    *link->mutable_fields_in_what() =
+            CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+    *link->mutable_fields_in_condition() =
+            CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1} /*uid field*/);
+    int64_t duration1Id = duration1.id();
+    *config.add_duration_metric() = duration1;
+
+    // Will be replaced.
+    DurationMetric duration2 = createDurationMetric("DURATION2", predicate1Id, nullopt, {});
+    int64_t duration2Id = duration2.id();
+    *config.add_duration_metric() = duration2;
+
+    // Will be replaced.
+    DurationMetric duration3 = createDurationMetric("DURATION3", predicate3Id, nullopt, {state1Id});
+    int64_t duration3Id = duration3.id();
+    *config.add_duration_metric() = duration3;
+
+    // Will be replaced.
+    DurationMetric duration4 = createDurationMetric("DURATION4", predicate3Id, predicate2Id, {});
+    int64_t duration4Id = duration4.id();
+    *config.add_duration_metric() = duration4;
+
+    // Will be deleted.
+    DurationMetric duration5 = createDurationMetric("DURATION5", predicate2Id, nullopt, {});
+    int64_t duration5Id = duration5.id();
+    *config.add_duration_metric() = duration5;
+
+    EXPECT_TRUE(initConfig(config));
+
+    // Make some sliced conditions true.
+    int uid1 = 10;
+    int uid2 = 11;
+    vector<MatchingState> matchingStates(8, MatchingState::kNotMatched);
+    matchingStates[2] = kMatched;
+    vector<ConditionState> conditionCache(5, ConditionState::kNotEvaluated);
+    vector<bool> changedCache(5, false);
+    unique_ptr<LogEvent> event = CreateAcquireWakelockEvent(timeBaseNs + 3, {uid1}, {"tag"}, "wl1");
+    oldConditionTrackers[4]->evaluateCondition(*event.get(), matchingStates, oldConditionTrackers,
+                                               conditionCache, changedCache);
+    EXPECT_TRUE(oldConditionTrackers[4]->isSliced());
+    EXPECT_TRUE(changedCache[4]);
+    EXPECT_EQ(conditionCache[4], ConditionState::kTrue);
+    oldMetricProducers[0]->onMatchedLogEvent(2, *event.get());
+
+    fill(conditionCache.begin(), conditionCache.end(), ConditionState::kNotEvaluated);
+    fill(changedCache.begin(), changedCache.end(), false);
+    event = CreateAcquireWakelockEvent(timeBaseNs + 3, {uid2}, {"tag"}, "wl2");
+    oldConditionTrackers[4]->evaluateCondition(*event.get(), matchingStates, oldConditionTrackers,
+                                               conditionCache, changedCache);
+    EXPECT_TRUE(changedCache[4]);
+    EXPECT_EQ(conditionCache[4], ConditionState::kTrue);
+    oldMetricProducers[0]->onMatchedLogEvent(2, *event.get());
+
+    // Used later to ensure the condition wizard is replaced. Get it before doing the update.
+    // The duration trackers have a pointer to the wizard, and 2 trackers were created above.
+    sp<ConditionWizard> oldConditionWizard = oldMetricProducers[0]->mWizard;
+    EXPECT_EQ(oldConditionWizard->getStrongCount(), 8);
+
+    // Replace predicate1, predicate3, and state1. Causes duration2/3/4 to be replaced.
+    set<int64_t> replacedConditions({predicate1Id, predicate2Id});
+    set<int64_t> replacedStates({state1Id});
+
+    // New duration metric.
+    DurationMetric duration6 = createDurationMetric("DURATION6", predicate4Id, predicate5Id, {});
+    *duration6.mutable_dimensions_in_what() =
+            CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1} /*uid field*/);
+    link = duration6.add_links();
+    link->set_condition(predicate5Id);
+    *link->mutable_fields_in_what() =
+            CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1} /*uid field*/);
+    *link->mutable_fields_in_condition() =
+            CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+    int64_t duration6Id = duration6.id();
+
+    // Map the matchers and predicates in reverse order to force the indices to change.
+    const int matcher8Index = 0, matcher7Index = 1, matcher6Index = 2, matcher5Index = 3,
+              matcher4Index = 4, matcher3Index = 5, matcher2Index = 6, matcher1Index = 7;
+    std::unordered_map<int64_t, int> newAtomMatchingTrackerMap({{matcher8Id, matcher8Index},
+                                                                {matcher7Id, matcher7Index},
+                                                                {matcher6Id, matcher6Index},
+                                                                {matcher5Id, matcher5Index},
+                                                                {matcher4Id, matcher4Index},
+                                                                {matcher3Id, matcher3Index},
+                                                                {matcher2Id, matcher2Index},
+                                                                {matcher1Id, matcher1Index}});
+    // Use the existing matchers. A bit hacky, but saves code and we don't rely on them.
+    vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers(8);
+    reverse_copy(oldAtomMatchingTrackers.begin(), oldAtomMatchingTrackers.end(),
+                 newAtomMatchingTrackers.begin());
+
+    const int predicate5Index = 0, predicate4Index = 1, predicate3Index = 2, predicate2Index = 3,
+              predicate1Index = 4;
+    std::unordered_map<int64_t, int> newConditionTrackerMap({
+            {predicate5Id, predicate5Index},
+            {predicate4Id, predicate4Index},
+            {predicate3Id, predicate3Index},
+            {predicate2Id, predicate2Index},
+            {predicate1Id, predicate1Index},
+    });
+    // Use the existing conditionTrackers and reinitialize them to get the initial condition cache.
+    vector<sp<ConditionTracker>> newConditionTrackers(5);
+    reverse_copy(oldConditionTrackers.begin(), oldConditionTrackers.end(),
+                 newConditionTrackers.begin());
+    vector<Predicate> conditionProtos(5);
+    reverse_copy(config.predicate().begin(), config.predicate().end(), conditionProtos.begin());
+    for (int i = 0; i < newConditionTrackers.size(); i++) {
+        EXPECT_TRUE(newConditionTrackers[i]->onConfigUpdated(
+                conditionProtos, i, newConditionTrackers, newAtomMatchingTrackerMap,
+                newConditionTrackerMap));
+    }
+    vector<bool> cycleTracker(5, false);
+    fill(conditionCache.begin(), conditionCache.end(), ConditionState::kNotEvaluated);
+    for (int i = 0; i < newConditionTrackers.size(); i++) {
+        EXPECT_TRUE(newConditionTrackers[i]->init(conditionProtos, newConditionTrackers,
+                                                  newConditionTrackerMap, cycleTracker,
+                                                  conditionCache));
+    }
+    // Predicate5 should be true since 2 uids have wakelocks
+    EXPECT_EQ(conditionCache, vector({kTrue, kUnknown, kUnknown, kUnknown, kUnknown}));
+
+    StatsdConfig newConfig;
+    *newConfig.add_duration_metric() = duration6;
+    const int duration6Index = 0;
+    *newConfig.add_duration_metric() = duration3;
+    const int duration3Index = 1;
+    *newConfig.add_duration_metric() = duration1;
+    const int duration1Index = 2;
+    *newConfig.add_duration_metric() = duration4;
+    const int duration4Index = 3;
+    *newConfig.add_duration_metric() = duration2;
+    const int duration2Index = 4;
+
+    for (const Predicate& predicate : conditionProtos) {
+        *newConfig.add_predicate() = predicate;
+    }
+    *newConfig.add_state() = state1;
+    *newConfig.add_state() = state2;
+    unordered_map<int64_t, int> stateAtomIdMap;
+    unordered_map<int64_t, unordered_map<int, int64_t>> allStateGroupMaps;
+    map<int64_t, uint64_t> stateProtoHashes;
+    EXPECT_TRUE(initStates(newConfig, stateAtomIdMap, allStateGroupMaps, stateProtoHashes));
+
+    // Output data structures to validate.
+    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;
+    EXPECT_TRUE(updateMetrics(
+            key, newConfig, /*timeBaseNs=*/123, /*currentTimeNs=*/12345, new StatsPullerManager(),
+            oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, /*replacedMatchers=*/{},
+            newAtomMatchingTrackers, newConditionTrackerMap, replacedConditions,
+            newConditionTrackers, conditionCache, stateAtomIdMap, allStateGroupMaps, replacedStates,
+            oldMetricProducerMap, oldMetricProducers, newMetricProducerMap, newMetricProducers,
+            conditionToMetricMap, trackerToMetricMap, noReportMetricIds,
+            activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+            metricsWithActivation));
+
+    unordered_map<int64_t, int> expectedMetricProducerMap = {
+            {duration1Id, duration1Index}, {duration2Id, duration2Index},
+            {duration3Id, duration3Index}, {duration4Id, duration4Index},
+            {duration6Id, duration6Index},
+    };
+    EXPECT_THAT(newMetricProducerMap, ContainerEq(expectedMetricProducerMap));
+
+    // Make sure preserved metrics are the same.
+    ASSERT_EQ(newMetricProducers.size(), 5);
+    EXPECT_EQ(oldMetricProducers[oldMetricProducerMap.at(duration1Id)],
+              newMetricProducers[newMetricProducerMap.at(duration1Id)]);
+
+    // Make sure replaced metrics are different.
+    EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(duration2Id)],
+              newMetricProducers[newMetricProducerMap.at(duration2Id)]);
+    EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(duration3Id)],
+              newMetricProducers[newMetricProducerMap.at(duration3Id)]);
+    EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(duration4Id)],
+              newMetricProducers[newMetricProducerMap.at(duration4Id)]);
+
+    // Verify the conditionToMetricMap. Note that the "what" is not in this map.
+    ASSERT_EQ(conditionToMetricMap.size(), 3);
+    const vector<int>& condition2Metrics = conditionToMetricMap[predicate2Index];
+    EXPECT_THAT(condition2Metrics, UnorderedElementsAre(duration4Index));
+    const vector<int>& condition4Metrics = conditionToMetricMap[predicate4Index];
+    EXPECT_THAT(condition4Metrics, UnorderedElementsAre(duration1Index));
+    const vector<int>& condition5Metrics = conditionToMetricMap[predicate5Index];
+    EXPECT_THAT(condition5Metrics, UnorderedElementsAre(duration6Index));
+
+    // Verify the trackerToMetricMap. The start/stop/stopall indices from the "what" should be here.
+    ASSERT_EQ(trackerToMetricMap.size(), 8);
+    const vector<int>& matcher1Metrics = trackerToMetricMap[matcher1Index];
+    EXPECT_THAT(matcher1Metrics, UnorderedElementsAre(duration2Index));
+    const vector<int>& matcher2Metrics = trackerToMetricMap[matcher2Index];
+    EXPECT_THAT(matcher2Metrics, UnorderedElementsAre(duration2Index));
+    const vector<int>& matcher3Metrics = trackerToMetricMap[matcher3Index];
+    EXPECT_THAT(matcher3Metrics, UnorderedElementsAre(duration1Index));
+    const vector<int>& matcher4Metrics = trackerToMetricMap[matcher4Index];
+    EXPECT_THAT(matcher4Metrics, UnorderedElementsAre(duration1Index));
+    const vector<int>& matcher5Metrics = trackerToMetricMap[matcher5Index];
+    EXPECT_THAT(matcher5Metrics, UnorderedElementsAre(duration6Index));
+    const vector<int>& matcher6Metrics = trackerToMetricMap[matcher6Index];
+    EXPECT_THAT(matcher6Metrics, UnorderedElementsAre(duration6Index));
+    const vector<int>& matcher7Metrics = trackerToMetricMap[matcher7Index];
+    EXPECT_THAT(matcher7Metrics,
+                UnorderedElementsAre(duration1Index, duration3Index, duration4Index));
+    const vector<int>& matcher8Metrics = trackerToMetricMap[matcher8Index];
+    EXPECT_THAT(matcher8Metrics, UnorderedElementsAre(duration3Index, duration4Index));
+
+    // Verify event activation/deactivation maps.
+    ASSERT_EQ(activationAtomTrackerToMetricMap.size(), 0);
+    ASSERT_EQ(deactivationAtomTrackerToMetricMap.size(), 0);
+    ASSERT_EQ(metricsWithActivation.size(), 0);
+
+    // Verify tracker indices/ids/conditions are correct.
+    DurationMetricProducer* durationProducer1 =
+            static_cast<DurationMetricProducer*>(newMetricProducers[duration1Index].get());
+    EXPECT_EQ(durationProducer1->getMetricId(), duration1Id);
+    EXPECT_EQ(durationProducer1->mConditionTrackerIndex, predicate4Index);
+    EXPECT_EQ(durationProducer1->mCondition, ConditionState::kUnknown);
+    EXPECT_EQ(durationProducer1->mStartIndex, matcher3Index);
+    EXPECT_EQ(durationProducer1->mStopIndex, matcher4Index);
+    EXPECT_EQ(durationProducer1->mStopAllIndex, matcher7Index);
+    EXPECT_EQ(durationProducer1->mCurrentSlicedDurationTrackerMap.size(), 2);
+    for (const auto& durationTrackerIt : durationProducer1->mCurrentSlicedDurationTrackerMap) {
+        EXPECT_EQ(durationTrackerIt.second->mConditionTrackerIndex, predicate4Index);
+    }
+    DurationMetricProducer* durationProducer2 =
+            static_cast<DurationMetricProducer*>(newMetricProducers[duration2Index].get());
+    EXPECT_EQ(durationProducer2->getMetricId(), duration2Id);
+    EXPECT_EQ(durationProducer2->mConditionTrackerIndex, -1);
+    EXPECT_EQ(durationProducer2->mCondition, ConditionState::kTrue);
+    EXPECT_EQ(durationProducer2->mStartIndex, matcher1Index);
+    EXPECT_EQ(durationProducer2->mStopIndex, matcher2Index);
+    EXPECT_EQ(durationProducer2->mStopAllIndex, -1);
+    DurationMetricProducer* durationProducer3 =
+            static_cast<DurationMetricProducer*>(newMetricProducers[duration3Index].get());
+    EXPECT_EQ(durationProducer3->getMetricId(), duration3Id);
+    EXPECT_EQ(durationProducer3->mConditionTrackerIndex, -1);
+    EXPECT_EQ(durationProducer3->mCondition, ConditionState::kTrue);
+    EXPECT_EQ(durationProducer3->mStartIndex, matcher7Index);
+    EXPECT_EQ(durationProducer3->mStopIndex, matcher8Index);
+    EXPECT_EQ(durationProducer3->mStopAllIndex, -1);
+    DurationMetricProducer* durationProducer4 =
+            static_cast<DurationMetricProducer*>(newMetricProducers[duration4Index].get());
+    EXPECT_EQ(durationProducer4->getMetricId(), duration4Id);
+    EXPECT_EQ(durationProducer4->mConditionTrackerIndex, predicate2Index);
+    EXPECT_EQ(durationProducer4->mCondition, ConditionState::kUnknown);
+    EXPECT_EQ(durationProducer4->mStartIndex, matcher7Index);
+    EXPECT_EQ(durationProducer4->mStopIndex, matcher8Index);
+    EXPECT_EQ(durationProducer4->mStopAllIndex, -1);
+    DurationMetricProducer* durationProducer6 =
+            static_cast<DurationMetricProducer*>(newMetricProducers[duration6Index].get());
+    EXPECT_EQ(durationProducer6->getMetricId(), duration6Id);
+    EXPECT_EQ(durationProducer6->mConditionTrackerIndex, predicate5Index);
+    // TODO(b/167491517): should this be unknown since the condition is sliced?
+    EXPECT_EQ(durationProducer6->mCondition, ConditionState::kTrue);
+    EXPECT_EQ(durationProducer6->mStartIndex, matcher6Index);
+    EXPECT_EQ(durationProducer6->mStopIndex, matcher5Index);
+    EXPECT_EQ(durationProducer6->mStopAllIndex, -1);
+
+    sp<ConditionWizard> newConditionWizard = newMetricProducers[0]->mWizard;
+    EXPECT_NE(newConditionWizard, oldConditionWizard);
+    EXPECT_EQ(newConditionWizard->getStrongCount(), 8);
+    oldMetricProducers.clear();
+    // Only reference to the old wizard should be the one in the test.
+    EXPECT_EQ(oldConditionWizard->getStrongCount(), 1);
+}
+
 TEST_F(ConfigUpdateTest, TestUpdateMetricActivations) {
     StatsdConfig config;
     // Add atom matchers
@@ -2376,11 +2723,16 @@
     int64_t gaugeMetricId = gaugeMetric.id();
     *config.add_gauge_metric() = gaugeMetric;
 
+    // Preserved.
+    DurationMetric durationMetric = createDurationMetric("DURATION1", predicate1Id, nullopt, {});
+    int64_t durationMetricId = durationMetric.id();
+    *config.add_duration_metric() = durationMetric;
+
     EXPECT_TRUE(initConfig(config));
 
     // Used later to ensure the condition wizard is replaced. Get it before doing the update.
     sp<ConditionWizard> oldConditionWizard = oldMetricProducers[0]->mWizard;
-    EXPECT_EQ(oldConditionWizard->getStrongCount(), 4);
+    EXPECT_EQ(oldConditionWizard->getStrongCount(), 5);
 
     // Mark matcher 2 as replaced. Causes eventMetric to be replaced.
     set<int64_t> replacedMatchers;
@@ -2414,10 +2766,15 @@
     StatsdConfig newConfig;
     *newConfig.add_count_metric() = countMetric;
     const int countMetricIndex = 0;
+    *newConfig.add_duration_metric() = durationMetric;
+    const int durationMetricIndex = 1;
     *newConfig.add_event_metric() = eventMetric;
-    const int eventMetricIndex = 1;
+    const int eventMetricIndex = 2;
     *newConfig.add_gauge_metric() = gaugeMetric;
-    const int gaugeMetricIndex = 2;
+    const int gaugeMetricIndex = 3;
+
+    // Add the predicate since duration metric needs it.
+    *newConfig.add_predicate() = predicate1;
 
     // Output data structures to validate.
     unordered_map<int64_t, int> newMetricProducerMap;
@@ -2440,15 +2797,18 @@
 
     unordered_map<int64_t, int> expectedMetricProducerMap = {
             {countMetricId, countMetricIndex},
+            {durationMetricId, durationMetricIndex},
             {eventMetricId, eventMetricIndex},
             {gaugeMetricId, gaugeMetricIndex},
     };
     EXPECT_THAT(newMetricProducerMap, ContainerEq(expectedMetricProducerMap));
 
     // Make sure preserved metrics are the same.
-    ASSERT_EQ(newMetricProducers.size(), 3);
+    ASSERT_EQ(newMetricProducers.size(), 4);
     EXPECT_EQ(oldMetricProducers[oldMetricProducerMap.at(countMetricId)],
               newMetricProducers[newMetricProducerMap.at(countMetricId)]);
+    EXPECT_EQ(oldMetricProducers[oldMetricProducerMap.at(durationMetricId)],
+              newMetricProducers[newMetricProducerMap.at(durationMetricId)]);
 
     // Make sure replaced metrics are different.
     EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(eventMetricId)],
@@ -2464,9 +2824,9 @@
     // Verify the trackerToMetricMap.
     ASSERT_EQ(trackerToMetricMap.size(), 3);
     const vector<int>& matcher1Metrics = trackerToMetricMap[matcher1Index];
-    EXPECT_THAT(matcher1Metrics, UnorderedElementsAre(countMetricIndex));
+    EXPECT_THAT(matcher1Metrics, UnorderedElementsAre(countMetricIndex, durationMetricIndex));
     const vector<int>& matcher2Metrics = trackerToMetricMap[matcher2Index];
-    EXPECT_THAT(matcher2Metrics, UnorderedElementsAre(eventMetricIndex));
+    EXPECT_THAT(matcher2Metrics, UnorderedElementsAre(eventMetricIndex, durationMetricIndex));
     const vector<int>& matcher3Metrics = trackerToMetricMap[matcher3Index];
     EXPECT_THAT(matcher3Metrics, UnorderedElementsAre(gaugeMetricIndex));
 
@@ -2479,6 +2839,9 @@
     EXPECT_EQ(newMetricProducers[countMetricIndex]->getMetricId(), countMetricId);
     EXPECT_EQ(newMetricProducers[countMetricIndex]->mConditionTrackerIndex, predicate1Index);
     EXPECT_EQ(newMetricProducers[countMetricIndex]->mCondition, ConditionState::kUnknown);
+    EXPECT_EQ(newMetricProducers[durationMetricIndex]->getMetricId(), durationMetricId);
+    EXPECT_EQ(newMetricProducers[durationMetricIndex]->mConditionTrackerIndex, -1);
+    EXPECT_EQ(newMetricProducers[durationMetricIndex]->mCondition, ConditionState::kTrue);
     EXPECT_EQ(newMetricProducers[eventMetricIndex]->getMetricId(), eventMetricId);
     EXPECT_EQ(newMetricProducers[eventMetricIndex]->mConditionTrackerIndex, -1);
     EXPECT_EQ(newMetricProducers[eventMetricIndex]->mCondition, ConditionState::kTrue);
@@ -2488,7 +2851,7 @@
 
     sp<ConditionWizard> newConditionWizard = newMetricProducers[0]->mWizard;
     EXPECT_NE(newConditionWizard, oldConditionWizard);
-    EXPECT_EQ(newConditionWizard->getStrongCount(), 4);
+    EXPECT_EQ(newConditionWizard->getStrongCount(), 5);
     oldMetricProducers.clear();
     // Only reference to the old wizard should be the one in the test.
     EXPECT_EQ(oldConditionWizard->getStrongCount(), 1);
diff --git a/config/boot-image-profile.txt b/config/boot-image-profile.txt
index f43bd2b..01272c7 100644
--- a/config/boot-image-profile.txt
+++ b/config/boot-image-profile.txt
@@ -47131,8 +47131,8 @@
 Landroid/view/IRotationWatcher$Stub$Proxy;
 Landroid/view/IRotationWatcher$Stub;
 Landroid/view/IRotationWatcher;
-Landroid/view/IScrollCaptureController$Stub;
-Landroid/view/IScrollCaptureController;
+Landroid/view/IScrollCaptureCallbacks$Stub;
+Landroid/view/IScrollCaptureCallbacks;
 Landroid/view/ISystemGestureExclusionListener$Stub$Proxy;
 Landroid/view/ISystemGestureExclusionListener$Stub;
 Landroid/view/ISystemGestureExclusionListener;
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index cb98093..250f2f0 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -3608,7 +3608,7 @@
      * running its code, {@link RunningAppProcessInfo#IMPORTANCE_GONE} is returned.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS)
     public @RunningAppProcessInfo.Importance int getPackageImportance(String packageName) {
         try {
@@ -3628,7 +3628,7 @@
      * running its code, {@link RunningAppProcessInfo#IMPORTANCE_GONE} is returned.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS)
     public @RunningAppProcessInfo.Importance int getUidImportance(int uid) {
         try {
@@ -3645,7 +3645,7 @@
      * {@link #addOnUidImportanceListener}.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public interface OnUidImportanceListener {
         /**
          * The importance if a given uid has changed.  Will be one of the importance
@@ -3676,7 +3676,7 @@
      * {@link android.Manifest.permission#PACKAGE_USAGE_STATS}.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS)
     public void addOnUidImportanceListener(OnUidImportanceListener listener,
             @RunningAppProcessInfo.Importance int importanceCutpoint) {
@@ -3705,7 +3705,7 @@
      * @throws IllegalArgumentException If the listener is not registered.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS)
     public void removeOnUidImportanceListener(OnUidImportanceListener listener) {
         synchronized (this) {
@@ -3847,7 +3847,7 @@
      * @see #forceStopPackageAsUser(String, int)
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     @RequiresPermission(Manifest.permission.FORCE_STOP_PACKAGES)
     public void forceStopPackage(String packageName) {
         forceStopPackageAsUser(packageName, mContext.getUserId());
@@ -4186,7 +4186,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public boolean switchUser(@NonNull UserHandle user) {
         if (user == null) {
@@ -4619,7 +4618,7 @@
      *
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     @RequiresPermission(Manifest.permission.FORCE_STOP_PACKAGES)
     public void killProcessesWhenImperceptible(@NonNull int[] pids, @NonNull String reason) {
         try {
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index c5bc356..f3b3789 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -461,7 +461,6 @@
      * state the more important the UID is for the user.
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final int UID_STATE_PERSISTENT = 100;
 
@@ -470,7 +469,6 @@
      * state the more important the UID is for the user.
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final int UID_STATE_TOP = 200;
 
@@ -482,7 +480,6 @@
      * @hide
      * @deprecated
      */
-    @TestApi
     @SystemApi
     @Deprecated
     public static final int UID_STATE_FOREGROUND_SERVICE_LOCATION = 300;
@@ -492,7 +489,6 @@
      * state the more important the UID is for the user.
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final int UID_STATE_FOREGROUND_SERVICE = 400;
 
@@ -501,7 +497,6 @@
      * state the more important the UID is for the user.
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final int UID_STATE_FOREGROUND = 500;
 
@@ -517,7 +512,6 @@
      * state the more important the UID is for the user.
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final int UID_STATE_BACKGROUND = 600;
 
@@ -526,7 +520,6 @@
      * state the more important the UID is for the user.
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final int UID_STATE_CACHED = 700;
 
@@ -604,7 +597,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final int OP_FLAG_SELF = 0x1;
 
@@ -615,7 +607,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final int OP_FLAG_TRUSTED_PROXY = 0x2;
 
@@ -626,7 +617,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final int OP_FLAG_UNTRUSTED_PROXY = 0x4;
 
@@ -637,7 +627,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final int OP_FLAG_TRUSTED_PROXIED = 0x8;
 
@@ -648,7 +637,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final int OP_FLAG_UNTRUSTED_PROXIED = 0x10;
 
@@ -660,7 +648,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final int OP_FLAGS_ALL =
             OP_FLAG_SELF
@@ -1185,7 +1172,7 @@
     public static final String OPSTR_GET_USAGE_STATS
             = "android:get_usage_stats";
     /** Activate a VPN connection without user intervention. @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_ACTIVATE_VPN
             = "android:activate_vpn";
     /** Allows an application to read the user's contacts data. */
@@ -1267,7 +1254,7 @@
     public static final String OPSTR_WRITE_SETTINGS
             = "android:write_settings";
     /** @hide Get device accounts. */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_GET_ACCOUNTS
             = "android:get_accounts";
     public static final String OPSTR_READ_PHONE_NUMBERS
@@ -1276,7 +1263,7 @@
     public static final String OPSTR_PICTURE_IN_PICTURE
             = "android:picture_in_picture";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_INSTANT_APP_START_FOREGROUND
             = "android:instant_app_start_foreground";
     /** Answer incoming phone calls */
@@ -1286,129 +1273,129 @@
      * Accept call handover
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_ACCEPT_HANDOVER
             = "android:accept_handover";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_GPS = "android:gps";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_VIBRATE = "android:vibrate";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_WIFI_SCAN = "android:wifi_scan";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_POST_NOTIFICATION = "android:post_notification";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_NEIGHBORING_CELLS = "android:neighboring_cells";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_WRITE_SMS = "android:write_sms";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_RECEIVE_EMERGENCY_BROADCAST =
             "android:receive_emergency_broadcast";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_READ_ICC_SMS = "android:read_icc_sms";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_WRITE_ICC_SMS = "android:write_icc_sms";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_ACCESS_NOTIFICATIONS = "android:access_notifications";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_PLAY_AUDIO = "android:play_audio";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_READ_CLIPBOARD = "android:read_clipboard";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_WRITE_CLIPBOARD = "android:write_clipboard";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_TAKE_MEDIA_BUTTONS = "android:take_media_buttons";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_TAKE_AUDIO_FOCUS = "android:take_audio_focus";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_AUDIO_MASTER_VOLUME = "android:audio_master_volume";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_AUDIO_VOICE_VOLUME = "android:audio_voice_volume";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_AUDIO_RING_VOLUME = "android:audio_ring_volume";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_AUDIO_MEDIA_VOLUME = "android:audio_media_volume";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_AUDIO_ALARM_VOLUME = "android:audio_alarm_volume";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_AUDIO_NOTIFICATION_VOLUME =
             "android:audio_notification_volume";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_AUDIO_BLUETOOTH_VOLUME = "android:audio_bluetooth_volume";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_WAKE_LOCK = "android:wake_lock";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_MUTE_MICROPHONE = "android:mute_microphone";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_TOAST_WINDOW = "android:toast_window";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_PROJECT_MEDIA = "android:project_media";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_WRITE_WALLPAPER = "android:write_wallpaper";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_ASSIST_STRUCTURE = "android:assist_structure";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_ASSIST_SCREENSHOT = "android:assist_screenshot";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_TURN_SCREEN_ON = "android:turn_screen_on";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_RUN_IN_BACKGROUND = "android:run_in_background";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_AUDIO_ACCESSIBILITY_VOLUME =
             "android:audio_accessibility_volume";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_REQUEST_INSTALL_PACKAGES = "android:request_install_packages";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_RUN_ANY_IN_BACKGROUND = "android:run_any_in_background";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_CHANGE_WIFI_STATE = "android:change_wifi_state";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_REQUEST_DELETE_PACKAGES = "android:request_delete_packages";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_BIND_ACCESSIBILITY_SERVICE =
             "android:bind_accessibility_service";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_MANAGE_IPSEC_TUNNELS = "android:manage_ipsec_tunnels";
     /** @hide */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_START_FOREGROUND = "android:start_foreground";
     /** @hide */
     public static final String OPSTR_BLUETOOTH_SCAN = "android:bluetooth_scan";
@@ -1424,25 +1411,25 @@
             "android:sms_financial_transactions";
 
     /** @hide Read media of audio type. */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_READ_MEDIA_AUDIO = "android:read_media_audio";
     /** @hide Write media of audio type. */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_WRITE_MEDIA_AUDIO = "android:write_media_audio";
     /** @hide Read media of video type. */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_READ_MEDIA_VIDEO = "android:read_media_video";
     /** @hide Write media of video type. */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_WRITE_MEDIA_VIDEO = "android:write_media_video";
     /** @hide Read media of image type. */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_READ_MEDIA_IMAGES = "android:read_media_images";
     /** @hide Write media of image type. */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_WRITE_MEDIA_IMAGES = "android:write_media_images";
     /** @hide Has a legacy (non-isolated) view of storage. */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String OPSTR_LEGACY_STORAGE = "android:legacy_storage";
     /** @hide Read location metadata from media */
     public static final String OPSTR_ACCESS_MEDIA_LOCATION = "android:access_media_location";
@@ -1456,7 +1443,6 @@
     public static final String OPSTR_QUERY_ALL_PACKAGES = "android:query_all_packages";
     /** @hide Access all external storage */
     @SystemApi
-    @TestApi
     public static final String OPSTR_MANAGE_EXTERNAL_STORAGE =
             "android:manage_external_storage";
 
@@ -2683,7 +2669,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public static int opToDefaultMode(@NonNull String appOp) {
         return opToDefaultMode(strOpToOp(appOp));
@@ -2775,7 +2760,6 @@
      * Class holding all of the operation information associated with an app.
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final class PackageOps implements Parcelable {
         private final String mPackageName;
@@ -2854,7 +2838,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     // @DataClass(genHiddenConstructor = true, genHiddenCopyConstructor = true)
     // genHiddenCopyConstructor does not work for @hide @SystemApi classes
@@ -3222,7 +3205,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     @Immutable
     // @DataClass(genHiddenConstructor = true) codegen verifier is broken
@@ -3796,7 +3778,6 @@
      *
      * @hide
      */
-    @TestApi
     @Immutable
     @SystemApi
     // @DataClass(genHiddenConstructor = true) codegen verifier is broken
@@ -4474,7 +4455,6 @@
      * @hide
      */
     @Immutable
-    @TestApi
     @SystemApi
     public static final class HistoricalOpsRequest {
         private final int mUid;
@@ -4505,7 +4485,6 @@
          *
          * @hide
          */
-        @TestApi
         @SystemApi
         public static final class Builder {
             private int mUid = Process.INVALID_UID;
@@ -4643,7 +4622,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final class HistoricalOps implements Parcelable {
         private long mBeginTimeMillis;
@@ -5079,7 +5057,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final class HistoricalUidOps implements Parcelable {
         private final int mUid;
@@ -5333,7 +5310,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final class HistoricalPackageOps implements Parcelable {
         private final @NonNull String mPackageName;
@@ -5664,7 +5640,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     /* codegen verifier cannot deal with nested class parameters
     @DataClass(genHiddenConstructor = true,
@@ -5975,7 +5950,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final class HistoricalOp implements Parcelable {
         private final int mOp;
@@ -6612,7 +6586,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS)
     public @NonNull List<AppOpsManager.PackageOps> getOpsForPackage(int uid,
@@ -6647,7 +6620,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS)
     public void getHistoricalOps(@NonNull HistoricalOpsRequest request,
@@ -6756,7 +6728,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
     public void setUidMode(@NonNull String appOp, int uid, @Mode int mode) {
         try {
@@ -6810,7 +6781,6 @@
      * be changed.
      * @hide
      */
-    @TestApi
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
     public void setMode(@NonNull String op, int uid, @Nullable String packageName,
@@ -8773,7 +8743,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(Manifest.permission.GET_APP_OPS_STATS)
     public @Nullable RuntimeAppOpAccessMessage collectRuntimeAppOpAccessMessage() {
         try {
@@ -8788,7 +8757,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static String[] getOpStrs() {
         return Arrays.copyOf(sOpToString, sOpToString.length);
     }
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 5438062..60e7f0b 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -8457,9 +8457,7 @@
                 Action action, StandardTemplateParams p) {
             final boolean tombstone = (action.actionIntent == null);
             container.setViewVisibility(buttonId, View.VISIBLE);
-            if (buttonId != R.id.media_seamless) {
-                container.setImageViewIcon(buttonId, action.getIcon());
-            }
+            container.setImageViewIcon(buttonId, action.getIcon());
 
             // If the action buttons should not be tinted, then just use the default
             // notification color. Otherwise, just use the passed-in color.
@@ -8513,10 +8511,6 @@
                     view.setViewVisibility(MEDIA_BUTTON_IDS[i], View.GONE);
                 }
             }
-            bindMediaActionButton(view, R.id.media_seamless, new Action(
-                    R.drawable.ic_media_seamless, mBuilder.mContext.getString(
-                            com.android.internal.R.string.ext_media_seamless_action), null), p);
-            view.setViewVisibility(R.id.media_seamless, View.GONE);
             handleImage(view);
             // handle the content margin
             int endMargin = R.dimen.notification_content_margin_end;
@@ -8553,10 +8547,6 @@
                     big.setViewVisibility(MEDIA_BUTTON_IDS[i], View.GONE);
                 }
             }
-            bindMediaActionButton(big, R.id.media_seamless, new Action(R.drawable.ic_media_seamless,
-                    mBuilder.mContext.getString(
-                            com.android.internal.R.string.ext_media_seamless_action), null), p);
-            big.setViewVisibility(R.id.media_seamless, View.GONE);
             handleImage(big);
             return big;
         }
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 1bfdaf5..f0e457e 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -134,7 +134,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int USER_LOCKED_SOUND = 0x00000020;
 
     /**
@@ -391,7 +390,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public void setBlockable(boolean blockable) {
         mBlockableSystem = blockable;
     }
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index aefaf78..f3bd04cd 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -1430,7 +1430,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public boolean isNotificationAssistantAccessGranted(@NonNull ComponentName assistant) {
         INotificationManager service = getService();
         try {
@@ -1466,7 +1465,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public @NonNull @Adjustment.Keys List<String> getAllowedAssistantAdjustments() {
         INotificationManager service = getService();
         try {
@@ -1577,7 +1575,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS)
     public void setNotificationListenerAccessGranted(
             @NonNull ComponentName listener, boolean granted) {
@@ -1611,7 +1608,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public void setNotificationAssistantAccessGranted(@Nullable ComponentName assistant,
             boolean granted) {
         INotificationManager service = getService();
@@ -1631,7 +1627,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS)
     public @NonNull List<ComponentName> getEnabledNotificationListeners() {
         return getEnabledNotificationListeners(mContext.getUserId());
@@ -1649,7 +1644,6 @@
 
     /** @hide */
     @SystemApi
-    @TestApi
     public @Nullable ComponentName getAllowedNotificationAssistant() {
         INotificationManager service = getService();
         try {
diff --git a/core/java/android/app/RuntimeAppOpAccessMessage.java b/core/java/android/app/RuntimeAppOpAccessMessage.java
index a19f815..db3ba4a 100644
--- a/core/java/android/app/RuntimeAppOpAccessMessage.java
+++ b/core/java/android/app/RuntimeAppOpAccessMessage.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -32,7 +31,6 @@
  * @hide
  */
 @Immutable
-@TestApi
 @SystemApi
 /*@DataClass(genConstructor = false)
 @DataClass.Suppress("getOpCode")*/
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index 99d2127..864db27 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -374,7 +374,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.STATUS_BAR)
     public void setDisabledForSetup(boolean disabled) {
         try {
@@ -423,7 +422,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.STATUS_BAR)
     @NonNull
     public DisableInfo getDisableInfo() {
@@ -456,7 +454,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final class DisableInfo {
 
         private boolean mStatusBarExpansion;
@@ -489,7 +486,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public boolean isStatusBarExpansionDisabled() {
             return mStatusBarExpansion;
         }
@@ -505,7 +501,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public boolean isNavigateToHomeDisabled() {
             return mNavigateHome;
         }
@@ -521,7 +516,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public boolean isNotificationPeekingDisabled() {
             return mNotificationPeeking;
         }
@@ -537,7 +531,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public boolean isRecentsDisabled() {
             return mRecents;
         }
@@ -553,7 +546,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public boolean isSearchDisabled() {
             return mSearch;
         }
@@ -611,7 +603,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public boolean areAllComponentsEnabled() {
             return !mStatusBarExpansion && !mNavigateHome && !mNotificationPeeking && !mRecents
                     && !mSearch && !mSystemIcons && !mClock && !mNotificationIcons;
diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java
index 06d1b74..e2fc5db 100644
--- a/core/java/android/app/UiModeManager.java
+++ b/core/java/android/app/UiModeManager.java
@@ -314,7 +314,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.ENTER_CAR_MODE_PRIORITIZED)
     public void enableCarMode(@IntRange(from = 0) int priority, @EnableCarMode int flags) {
         if (mService != null) {
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 0a80ccc..54f3209 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -1766,7 +1766,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     @RequiresPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT)
     public boolean setWallpaperComponent(ComponentName name) {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index b74e18b..ad902a0 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1465,7 +1465,7 @@
      * @see #createAdminSupportIntent(String)
      * @hide
      */
-    @TestApi @SystemApi
+    @SystemApi
     public static final String EXTRA_RESTRICTION = "android.app.extra.RESTRICTION";
 
     /**
@@ -2688,13 +2688,11 @@
      * </ul>
      */
     @SystemApi
-    @TestApi
     public static final String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_ALLOWED =
             "android.account.DEVICE_OR_PROFILE_OWNER_ALLOWED";
 
     /** @hide See {@link #ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_ALLOWED} */
     @SystemApi
-    @TestApi
     public static final String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED =
             "android.account.DEVICE_OR_PROFILE_OWNER_DISALLOWED";
 
@@ -6671,7 +6669,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @SuppressLint("Doclava125")
     public boolean isDeviceManaged() {
         try {
@@ -10381,7 +10378,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @SuppressLint("Doclava125")
     public @Nullable CharSequence getDeviceOwnerOrganizationName() {
         try {
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index b5234f8..c15504c 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -3,7 +3,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.app.Activity;
 import android.content.ComponentName;
 import android.content.Context;
@@ -722,7 +721,6 @@
         // COntent Capture.
         /** @hide */
         @SystemApi
-        @TestApi
         public ViewNode() {
         }
 
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index 9b67587..0531359 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -21,7 +21,6 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
@@ -919,7 +918,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.BACKUP)
     public Intent getConfigurationIntent(String transportName) {
         checkServiceBinder();
@@ -941,7 +939,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.BACKUP)
     public String getDestinationString(String transportName) {
         checkServiceBinder();
@@ -963,7 +960,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.BACKUP)
     public Intent getDataManagementIntent(String transportName) {
         checkServiceBinder();
@@ -989,7 +985,6 @@
      */
     @Deprecated
     @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.BACKUP)
     @Nullable
     public String getDataManagementLabel(@NonNull String transportName) {
@@ -1006,7 +1001,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.BACKUP)
     @Nullable
     public CharSequence getDataManagementIntentLabel(@NonNull String transportName) {
diff --git a/core/java/android/app/prediction/AppPredictionContext.java b/core/java/android/app/prediction/AppPredictionContext.java
index d14238b..99fa869 100644
--- a/core/java/android/app/prediction/AppPredictionContext.java
+++ b/core/java/android/app/prediction/AppPredictionContext.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.content.Context;
 import android.os.Bundle;
 import android.os.Parcel;
@@ -32,7 +31,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class AppPredictionContext implements Parcelable {
 
     private final int mPredictedTargetCount;
@@ -129,7 +127,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final class Builder {
 
         @NonNull
@@ -147,7 +144,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public Builder(@NonNull Context context) {
             mPackageName = context.getPackageName();
         }
diff --git a/core/java/android/app/prediction/AppPredictionManager.java b/core/java/android/app/prediction/AppPredictionManager.java
index ca22721..5da7aa9 100644
--- a/core/java/android/app/prediction/AppPredictionManager.java
+++ b/core/java/android/app/prediction/AppPredictionManager.java
@@ -17,7 +17,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.content.Context;
 
 import java.util.Objects;
@@ -28,7 +27,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class AppPredictionManager {
 
     private final Context mContext;
diff --git a/core/java/android/app/prediction/AppPredictionSessionId.java b/core/java/android/app/prediction/AppPredictionSessionId.java
index 876bafd..6277a7d 100644
--- a/core/java/android/app/prediction/AppPredictionSessionId.java
+++ b/core/java/android/app/prediction/AppPredictionSessionId.java
@@ -18,7 +18,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -30,7 +29,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class AppPredictionSessionId implements Parcelable {
 
     private final String mId;
diff --git a/core/java/android/app/prediction/AppPredictor.java b/core/java/android/app/prediction/AppPredictor.java
index fa135b1..fd1b9e3 100644
--- a/core/java/android/app/prediction/AppPredictor.java
+++ b/core/java/android/app/prediction/AppPredictor.java
@@ -70,7 +70,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class AppPredictor {
 
     private static final String TAG = AppPredictor.class.getSimpleName();
diff --git a/core/java/android/app/prediction/AppTarget.java b/core/java/android/app/prediction/AppTarget.java
index 14e32b83..fef9e70 100644
--- a/core/java/android/app/prediction/AppTarget.java
+++ b/core/java/android/app/prediction/AppTarget.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.content.pm.ShortcutInfo;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -33,7 +32,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class AppTarget implements Parcelable {
 
     private final AppTargetId mId;
@@ -190,7 +188,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final class Builder {
 
         @NonNull
@@ -221,7 +218,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public Builder(@NonNull AppTargetId id, @NonNull String packageName,
                 @NonNull UserHandle user) {
             mId = Objects.requireNonNull(id);
@@ -235,7 +231,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public Builder(@NonNull AppTargetId id, @NonNull ShortcutInfo info) {
             mId = Objects.requireNonNull(id);
             mShortcutInfo = Objects.requireNonNull(info);
diff --git a/core/java/android/app/prediction/AppTargetEvent.java b/core/java/android/app/prediction/AppTargetEvent.java
index f519145..963e750 100644
--- a/core/java/android/app/prediction/AppTargetEvent.java
+++ b/core/java/android/app/prediction/AppTargetEvent.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -32,7 +31,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class AppTargetEvent implements Parcelable {
 
     /**
@@ -141,7 +139,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final class Builder {
         private AppTarget mTarget;
         private String mLocation;
diff --git a/core/java/android/app/prediction/AppTargetId.java b/core/java/android/app/prediction/AppTargetId.java
index 052fdc1..048e12c 100644
--- a/core/java/android/app/prediction/AppTargetId.java
+++ b/core/java/android/app/prediction/AppTargetId.java
@@ -18,7 +18,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -28,7 +27,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class AppTargetId implements Parcelable {
 
     @NonNull
@@ -40,7 +38,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public AppTargetId(@NonNull String id) {
         mId = id;
     }
diff --git a/core/java/android/app/role/OnRoleHoldersChangedListener.java b/core/java/android/app/role/OnRoleHoldersChangedListener.java
index d6f7679..5958deb 100644
--- a/core/java/android/app/role/OnRoleHoldersChangedListener.java
+++ b/core/java/android/app/role/OnRoleHoldersChangedListener.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.UserHandle;
 
 /**
@@ -27,7 +26,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public interface OnRoleHoldersChangedListener {
 
     /**
diff --git a/core/java/android/app/role/RoleManager.java b/core/java/android/app/role/RoleManager.java
index 8215923..408ce0f 100644
--- a/core/java/android/app/role/RoleManager.java
+++ b/core/java/android/app/role/RoleManager.java
@@ -144,7 +144,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int MANAGE_HOLDERS_FLAG_DONT_KILL_APP = 1;
 
     /**
@@ -255,7 +254,6 @@
     @NonNull
     @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
     @SystemApi
-    @TestApi
     public List<String> getRoleHolders(@NonNull String roleName) {
         return getRoleHoldersAsUser(roleName, Process.myUserHandle());
     }
@@ -281,7 +279,6 @@
     @NonNull
     @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
     @SystemApi
-    @TestApi
     public List<String> getRoleHoldersAsUser(@NonNull String roleName, @NonNull UserHandle user) {
         Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
         Objects.requireNonNull(user, "user cannot be null");
@@ -315,7 +312,6 @@
      */
     @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
     @SystemApi
-    @TestApi
     public void addRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
             @ManageHoldersFlags int flags, @NonNull UserHandle user,
             @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback) {
@@ -354,7 +350,6 @@
      */
     @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
     @SystemApi
-    @TestApi
     public void removeRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
             @ManageHoldersFlags int flags, @NonNull UserHandle user,
             @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback) {
@@ -392,7 +387,6 @@
      */
     @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
     @SystemApi
-    @TestApi
     public void clearRoleHoldersAsUser(@NonNull String roleName, @ManageHoldersFlags int flags,
             @NonNull UserHandle user, @CallbackExecutor @NonNull Executor executor,
             @NonNull Consumer<Boolean> callback) {
@@ -439,7 +433,6 @@
      */
     @RequiresPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS)
     @SystemApi
-    @TestApi
     public void addOnRoleHoldersChangedListenerAsUser(@CallbackExecutor @NonNull Executor executor,
             @NonNull OnRoleHoldersChangedListener listener, @NonNull UserHandle user) {
         Objects.requireNonNull(executor, "executor cannot be null");
@@ -485,7 +478,6 @@
      */
     @RequiresPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS)
     @SystemApi
-    @TestApi
     public void removeOnRoleHoldersChangedListenerAsUser(
             @NonNull OnRoleHoldersChangedListener listener, @NonNull UserHandle user) {
         Objects.requireNonNull(listener, "listener cannot be null");
@@ -527,7 +519,6 @@
      */
     @RequiresPermission(PERMISSION_MANAGE_ROLES_FROM_CONTROLLER)
     @SystemApi
-    @TestApi
     public void setRoleNamesFromController(@NonNull List<String> roleNames) {
         Objects.requireNonNull(roleNames, "roleNames cannot be null");
         try {
@@ -558,7 +549,6 @@
      */
     @RequiresPermission(PERMISSION_MANAGE_ROLES_FROM_CONTROLLER)
     @SystemApi
-    @TestApi
     public boolean addRoleHolderFromController(@NonNull String roleName,
             @NonNull String packageName) {
         Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
@@ -591,7 +581,6 @@
      */
     @RequiresPermission(PERMISSION_MANAGE_ROLES_FROM_CONTROLLER)
     @SystemApi
-    @TestApi
     public boolean removeRoleHolderFromController(@NonNull String roleName,
             @NonNull String packageName) {
         Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
@@ -614,7 +603,6 @@
     @NonNull
     @RequiresPermission(PERMISSION_MANAGE_ROLES_FROM_CONTROLLER)
     @SystemApi
-    @TestApi
     public List<String> getHeldRolesFromController(@NonNull String packageName) {
         Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
         try {
diff --git a/core/java/android/app/slice/SliceProvider.java b/core/java/android/app/slice/SliceProvider.java
index cef6ab0..0589f4a 100644
--- a/core/java/android/app/slice/SliceProvider.java
+++ b/core/java/android/app/slice/SliceProvider.java
@@ -519,7 +519,7 @@
         intent.setData(sliceUri.buildUpon().appendQueryParameter("package", callingPackage)
                 .build());
 
-        return PendingIntent.getActivity(context, 0, intent, 0);
+        return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE);
     }
 
     /**
diff --git a/core/java/android/app/usage/CacheQuotaHint.java b/core/java/android/app/usage/CacheQuotaHint.java
index d5c72f2..0ccb058 100644
--- a/core/java/android/app/usage/CacheQuotaHint.java
+++ b/core/java/android/app/usage/CacheQuotaHint.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -33,7 +32,6 @@
  * allows apps to understand how much cache to use.
  * {@hide}
  */
-@TestApi
 @SystemApi
 public final class CacheQuotaHint implements Parcelable {
     public static final long QUOTA_NOT_SET = -1;
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index e94556b..c3c270e 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -21,7 +21,6 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
-import android.annotation.TestApi;
 import android.app.Activity;
 import android.app.Application;
 import android.app.PendingIntent;
@@ -285,7 +284,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.MANAGE_COMPANION_DEVICES)
     public boolean isDeviceAssociatedForWifiConnection(
             @NonNull String packageName,
diff --git a/core/java/android/content/ApexEnvironment.java b/core/java/android/content/ApexEnvironment.java
index 9f15a42..b4cc3c2 100644
--- a/core/java/android/content/ApexEnvironment.java
+++ b/core/java/android/content/ApexEnvironment.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Environment;
 import android.os.UserHandle;
 
@@ -31,7 +30,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public class ApexEnvironment {
 
     private static final String APEX_DATA = "apexdata";
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index d0f5ec4..5af7861 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -21,7 +21,6 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.res.AssetFileDescriptor;
 import android.database.CrossProcessCursorWrapper;
@@ -123,7 +122,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.REMOVE_TASKS)
     public void setDetectNotResponding(@DurationMillisLong long timeoutMillis) {
         synchronized (ContentProviderClient.class) {
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index c39f176..fd7074c 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -4098,7 +4098,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     // We can't accept an already-opened FD here, since these methods are
     // rewriting actual filesystem paths
     @SuppressLint("StreamFiles")
@@ -4118,7 +4117,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     // We can't accept an already-opened FD here, since these methods are
     // rewriting actual filesystem paths
     @SuppressLint("StreamFiles")
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index c4157cf..42fe0e1 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -382,6 +382,7 @@
      * {@link android.Manifest.permission#START_ACTIVITIES_FROM_BACKGROUND}.
      * @hide
      */
+    @SystemApi
     public static final int BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS = 0x00100000;
 
     /**
@@ -1848,7 +1849,6 @@
      */
     @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     @SystemApi
-    @TestApi
     public void startActivityAsUser(@RequiresPermission @NonNull Intent intent,
             @NonNull UserHandle user) {
         throw new RuntimeException("Not implemented. Must override in a subclass.");
@@ -3981,7 +3981,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @SuppressLint("ServiceName")
     public static final String STATUS_BAR_SERVICE = "statusbar";
 
@@ -4193,7 +4192,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final String ETHERNET_SERVICE = "ethernet";
 
     /**
@@ -4516,7 +4514,6 @@
      * @see #getSystemService(String)
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final String PERMISSION_SERVICE = "permission";
 
@@ -4547,7 +4544,7 @@
      * @see #getSystemService(String)
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String ROLLBACK_SERVICE = "rollback";
 
     /**
@@ -5021,7 +5018,7 @@
      * @see android.os.BugreportManager
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String BUGREPORT_SERVICE = "bugreport";
 
     /**
@@ -5183,7 +5180,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final String APP_INTEGRITY_SERVICE = "app_integrity";
 
     /**
@@ -5755,7 +5751,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @NonNull
     public Context createPackageContextAsUser(
             @NonNull String packageName, @CreatePackageOptions int flags, @NonNull UserHandle user)
@@ -5774,7 +5769,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @NonNull
     public Context createContextAsUser(@NonNull UserHandle user, @CreatePackageOptions int flags) {
         if (Build.IS_ENG) {
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 5622cca..c62194b 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -28,7 +28,6 @@
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.app.AppGlobals;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo;
@@ -1748,7 +1747,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final String EXTRA_ORIGINATING_UID
             = "android.intent.extra.ORIGINATING_UID";
 
@@ -1979,7 +1977,6 @@
     @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS)
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     @SystemApi
-    @TestApi
     public static final String ACTION_MANAGE_DEFAULT_APP =
             "android.intent.action.MANAGE_DEFAULT_APP";
 
@@ -1994,7 +1991,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final String EXTRA_ROLE_NAME = "android.intent.extra.ROLE_NAME";
 
     /**
@@ -2541,7 +2537,7 @@
      *
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_ROLLBACK_COMMITTED =
             "android.intent.action.ROLLBACK_COMMITTED";
@@ -2744,7 +2740,6 @@
      * </ul>
      *
      * <p class="note">This is a protected intent that can only be sent by the system.
-     * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_PACKAGE_STARTABLE = "android.intent.action.PACKAGE_STARTABLE";
@@ -2755,13 +2750,13 @@
      * <ul>
      * <li> {@link #EXTRA_UID} containing the integer uid assigned to the package. </li>
      * <li> {@link #EXTRA_PACKAGE_NAME} containing the package name. </li>
-     * <li> {@link #EXTRA_REASON} containing the integer indicating the reason for the state change,
+     * <li> {@link #EXTRA_UNSTARTABLE_REASON} containing the integer indicating the reason for
+     * the state change,
      * @see PackageManager.UnstartableReason
      * </li>
      * </ul>
      *
      * <p class="note">This is a protected intent that can only be sent by the system.
-     * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_PACKAGE_UNSTARTABLE =
@@ -2776,7 +2771,6 @@
      * </ul>
      *
      * <p class="note">This is a protected intent that can only be sent by the system.
-     * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_PACKAGE_FULLY_LOADED =
@@ -6015,6 +6009,13 @@
      */
     public static final String EXTRA_LOCUS_ID = "android.intent.extra.LOCUS_ID";
 
+    /**
+     * Intent extra: the reason that the package associated with this intent has become unstartable.
+     *
+     * <p>Type: String
+     */
+    public static final String EXTRA_UNSTARTABLE_REASON = "android.intent.extra.UNSTARTABLE_REASON";
+
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     // Intent flags (see mFlags variable).
diff --git a/core/java/android/content/integrity/AppIntegrityManager.java b/core/java/android/content/integrity/AppIntegrityManager.java
index 4db4c73..1196064 100644
--- a/core/java/android/content/integrity/AppIntegrityManager.java
+++ b/core/java/android/content/integrity/AppIntegrityManager.java
@@ -36,7 +36,6 @@
  *
  * @hide
  */
-@TestApi
 @SystemApi
 @SystemService(Context.APP_INTEGRITY_SERVICE)
 public class AppIntegrityManager {
diff --git a/core/java/android/content/integrity/IntegrityFormula.java b/core/java/android/content/integrity/IntegrityFormula.java
index fc177721..d965ef5 100644
--- a/core/java/android/content/integrity/IntegrityFormula.java
+++ b/core/java/android/content/integrity/IntegrityFormula.java
@@ -19,7 +19,6 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.content.integrity.AtomicFormula.BooleanAtomicFormula;
 import android.content.integrity.AtomicFormula.LongAtomicFormula;
 import android.content.integrity.AtomicFormula.StringAtomicFormula;
@@ -38,7 +37,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 @VisibleForTesting
 public abstract class IntegrityFormula {
 
diff --git a/core/java/android/content/integrity/Rule.java b/core/java/android/content/integrity/Rule.java
index 8f6d73f..391d1d0 100644
--- a/core/java/android/content/integrity/Rule.java
+++ b/core/java/android/content/integrity/Rule.java
@@ -22,7 +22,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -39,7 +38,6 @@
  *
  * @hide
  */
-@TestApi
 @SystemApi
 @VisibleForTesting
 public final class Rule implements Parcelable {
diff --git a/core/java/android/content/integrity/RuleSet.java b/core/java/android/content/integrity/RuleSet.java
index e121ff8..b423b54 100644
--- a/core/java/android/content/integrity/RuleSet.java
+++ b/core/java/android/content/integrity/RuleSet.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -30,7 +29,6 @@
  *
  * @hide
  */
-@TestApi
 @SystemApi
 public class RuleSet {
     private final String mVersion;
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index d5f2c12..8f4fc26 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -1141,7 +1141,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public int targetSandboxVersion;
 
     /**
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index f03425b..e2f8528 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1722,7 +1722,6 @@
          *
          * @hide
          */
-        @TestApi
         @SystemApi
         @RequiresPermission(android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS)
         public void setGrantedRuntimePermissions(String[] permissions) {
@@ -1794,7 +1793,7 @@
          * @see SessionParams#setEnableRollback(boolean, int)
          * @hide
          */
-        @SystemApi @TestApi
+        @SystemApi
         public void setEnableRollback(boolean enable) {
             if (enable) {
                 installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
@@ -1818,7 +1817,7 @@
          * @param dataPolicy the rollback data policy for this session
          * @hide
          */
-        @SystemApi @TestApi
+        @SystemApi
         public void setEnableRollback(boolean enable,
                 @PackageManager.RollbackDataPolicy int dataPolicy) {
             if (enable) {
@@ -1841,7 +1840,7 @@
         }
 
         /** {@hide} */
-        @SystemApi @TestApi
+        @SystemApi
         public void setRequestDowngrade(boolean requestDowngrade) {
             if (requestDowngrade) {
                 installFlags |= PackageManager.INSTALL_REQUEST_DOWNGRADE;
@@ -1880,7 +1879,6 @@
 
         /** {@hide} */
         @SystemApi
-        @TestApi
         public void setInstallAsInstantApp(boolean isInstantApp) {
             if (isInstantApp) {
                 installFlags |= PackageManager.INSTALL_INSTANT_APP;
@@ -1965,7 +1963,7 @@
          *
          * {@hide}
          */
-        @SystemApi @TestApi
+        @SystemApi
         @RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
         public void setStaged() {
             this.isStaged = true;
@@ -1976,7 +1974,7 @@
          *
          * {@hide}
          */
-        @SystemApi @TestApi
+        @SystemApi
         @RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
         public void setInstallAsApex() {
             installFlags |= PackageManager.INSTALL_APEX;
@@ -2480,7 +2478,6 @@
          *
          * @hide
          */
-        @TestApi
         @SystemApi
         public @NonNull Set<String> getWhitelistedRestrictedPermissions() {
             if ((installFlags & PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS) != 0) {
@@ -2504,7 +2501,6 @@
          *
          * @hide
          */
-        @TestApi
         @SystemApi
         public int getAutoRevokePermissionsMode() {
             return autoRevokePermissionsMode;
@@ -2633,7 +2629,7 @@
          *
          * @hide
          */
-        @SystemApi @TestApi
+        @SystemApi
         @PackageManager.RollbackDataPolicy
         public int getRollbackDataPolicy() {
             return rollbackDataPolicy;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 72499d5..fc7b3e0 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -120,7 +120,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public interface OnPermissionsChangedListener {
 
         /**
@@ -479,7 +478,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int MATCH_FACTORY_ONLY = 0x00200000;
 
     /**
@@ -611,7 +609,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int MODULE_APEX_NAME = 0x00000001;
 
     /** @hide */
@@ -3319,7 +3316,6 @@
     * @hide
     */
     @SystemApi
-    @TestApi
     public static final int FLAG_PERMISSION_USER_SET = 1 << 0;
 
     /**
@@ -3330,7 +3326,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int FLAG_PERMISSION_USER_FIXED =  1 << 1;
 
     /**
@@ -3341,7 +3336,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int FLAG_PERMISSION_POLICY_FIXED =  1 << 2;
 
     /**
@@ -3358,7 +3352,6 @@
      */
     @Deprecated
     @SystemApi
-    @TestApi
     public static final int FLAG_PERMISSION_REVOKE_ON_UPGRADE =  1 << 3;
 
     /**
@@ -3368,7 +3361,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int FLAG_PERMISSION_SYSTEM_FIXED =  1 << 4;
 
     /**
@@ -3380,7 +3372,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int FLAG_PERMISSION_GRANTED_BY_DEFAULT =  1 << 5;
 
     /**
@@ -3390,7 +3381,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int FLAG_PERMISSION_REVIEW_REQUIRED =  1 << 6;
 
     /**
@@ -3428,7 +3418,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final int FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT =  1 << 11;
 
@@ -3440,7 +3429,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final int FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT =  1 << 12;
 
@@ -3453,7 +3441,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final int FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT =  1 << 13;
 
@@ -3466,7 +3453,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final int FLAG_PERMISSION_APPLY_RESTRICTION =  1 << 14;
 
@@ -3476,7 +3462,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int FLAG_PERMISSION_GRANTED_BY_ROLE =  1 << 15;
 
     /**
@@ -3488,7 +3473,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int FLAG_PERMISSION_REVOKED_COMPAT =  FLAG_PERMISSION_REVOKE_ON_UPGRADE;
 
     /**
@@ -3498,7 +3482,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int FLAG_PERMISSION_ONE_TIME = 1 << 16;
 
     /**
@@ -3516,7 +3499,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final int FLAG_PERMISSION_RESTRICTION_ROLE_EXEMPT =  1 << 18;
 
@@ -3790,8 +3772,8 @@
      * @hide
      */
     @IntDef({UNSTARTABLE_REASON_UNKNOWN,
-            UNSTARTABLE_REASON_DATALOADER_TRANSPORT,
-            UNSTARTABLE_REASON_DATALOADER_STORAGE
+            UNSTARTABLE_REASON_CONNECTION_ERROR,
+            UNSTARTABLE_REASON_INSUFFICIENT_STORAGE
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface UnstartableReason {}
@@ -3800,23 +3782,20 @@
      * Unstartable state with no root cause specified. E.g., data loader seeing missing pages but
      * unclear about the cause. This corresponds to a generic alert window shown to the user when
      * the user attempts to launch the app.
-     * @hide
      */
     public static final int UNSTARTABLE_REASON_UNKNOWN = 0;
 
     /**
-     * Unstartable state after hint from dataloader of issues with the transport layer.
-     * This corresponds to an alert window shown to the user indicating network errors.
-     * @hide
+     * Unstartable state due to connection issues that interrupt package loading.
+     * This corresponds to an alert window shown to the user indicating connection errors.
      */
-    public static final int UNSTARTABLE_REASON_DATALOADER_TRANSPORT = 1;
+    public static final int UNSTARTABLE_REASON_CONNECTION_ERROR = 1;
 
     /**
      * Unstartable state after encountering storage limitations.
      * This corresponds to an alert window indicating limited storage.
-     * @hide
      */
-    public static final int UNSTARTABLE_REASON_DATALOADER_STORAGE = 2;
+    public static final int UNSTARTABLE_REASON_INSUFFICIENT_STORAGE = 2;
 
     /** {@hide} */
     public int getUserId() {
@@ -4086,7 +4065,7 @@
      *
      * @hide
      */
-    @TestApi @SystemApi
+    @SystemApi
     public abstract boolean arePermissionsIndividuallyControlled();
 
     /**
@@ -4337,7 +4316,6 @@
      * @hide
      */
     @NonNull
-    @TestApi
     @SystemApi
     @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
     public abstract List<PackageInfo> getInstalledPackagesAsUser(@PackageInfoFlags int flags,
@@ -4498,7 +4476,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
     public abstract void grantRuntimePermission(@NonNull String packageName,
@@ -4525,7 +4502,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
     public abstract void revokeRuntimePermission(@NonNull String packageName,
@@ -4553,7 +4529,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
     public void revokeRuntimePermission(@NonNull String packageName,
@@ -4572,7 +4547,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(anyOf = {
             android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
             android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
@@ -4595,7 +4569,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(anyOf = {
             android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
             android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS
@@ -6443,7 +6416,6 @@
      * @hide
      */
     @Nullable
-    @TestApi
     @SystemApi
     @RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL)
     public abstract String getDefaultBrowserPackageNameAsUser(@UserIdInt int userId);
@@ -7097,7 +7069,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS)
     public abstract void addOnPermissionsChangeListener(
             @NonNull OnPermissionsChangedListener listener);
@@ -7110,7 +7081,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS)
     public abstract void removeOnPermissionsChangeListener(
             @NonNull OnPermissionsChangedListener listener);
@@ -8129,7 +8099,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @Nullable
     public String getIncidentReportApproverPackageName() {
         throw new UnsupportedOperationException(
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index 5d4c843..e730fee 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -160,7 +160,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int PROTECTION_FLAG_OEM = 0x4000;
 
     /**
@@ -181,7 +180,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 0x10000;
 
     /**
@@ -192,7 +190,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int PROTECTION_FLAG_WELLBEING = 0x20000;
 
     /**
@@ -202,7 +199,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int PROTECTION_FLAG_DOCUMENTER = 0x40000;
 
     /**
@@ -212,7 +208,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int PROTECTION_FLAG_CONFIGURATOR = 0x80000;
 
     /**
@@ -223,7 +218,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int PROTECTION_FLAG_INCIDENT_REPORT_APPROVER = 0x100000;
 
     /**
@@ -234,7 +228,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int PROTECTION_FLAG_APP_PREDICTOR = 0x200000;
 
     /**
@@ -245,7 +238,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int PROTECTION_FLAG_COMPANION = 0x800000;
 
     /**
@@ -256,7 +248,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int PROTECTION_FLAG_RETAIL_DEMO = 0x1000000;
 
     /** @hide */
@@ -340,7 +331,6 @@
      * value of {@link android.R.attr#permissionFlags}.
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final int FLAG_REMOVED = 1<<1;
 
@@ -436,7 +426,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public final @Nullable String backgroundPermission;
 
     /**
diff --git a/core/java/android/content/rollback/PackageRollbackInfo.java b/core/java/android/content/rollback/PackageRollbackInfo.java
index 642a76b..0140280 100644
--- a/core/java/android/content/rollback/PackageRollbackInfo.java
+++ b/core/java/android/content/rollback/PackageRollbackInfo.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.content.pm.PackageManager;
 import android.content.pm.VersionedPackage;
 import android.os.Parcel;
@@ -32,7 +31,7 @@
  *
  * @hide
  */
-@SystemApi @TestApi
+@SystemApi
 public final class PackageRollbackInfo implements Parcelable {
 
     private final VersionedPackage mVersionRolledBackFrom;
diff --git a/core/java/android/content/rollback/RollbackInfo.java b/core/java/android/content/rollback/RollbackInfo.java
index c09cfd5..a363718 100644
--- a/core/java/android/content/rollback/RollbackInfo.java
+++ b/core/java/android/content/rollback/RollbackInfo.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.content.pm.VersionedPackage;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -31,7 +30,7 @@
  *
  * @hide
  */
-@SystemApi @TestApi
+@SystemApi
 public final class RollbackInfo implements Parcelable {
 
     /**
diff --git a/core/java/android/content/rollback/RollbackManager.java b/core/java/android/content/rollback/RollbackManager.java
index 7ebeb21..3636222 100644
--- a/core/java/android/content/rollback/RollbackManager.java
+++ b/core/java/android/content/rollback/RollbackManager.java
@@ -24,7 +24,6 @@
 import android.annotation.TestApi;
 import android.content.Context;
 import android.content.IntentSender;
-import android.content.pm.PackageInstaller;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.VersionedPackage;
 import android.os.RemoteException;
@@ -43,7 +42,7 @@
  * @see PackageInstaller.SessionParams#setEnableRollback(boolean)
  * @hide
  */
-@SystemApi @TestApi
+@SystemApi
 @SystemService(Context.ROLLBACK_SERVICE)
 public final class RollbackManager {
     private final String mCallerPackageName;
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index a6e8c13..0f3cdfc 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -616,7 +616,7 @@
     public static final String STRING_TYPE_MOTION_DETECT = "android.sensor.motion_detect";
 
     /**
-     * A constant describing a motion detect sensor.
+     * A constant describing a heart beat sensor.
      *
      * See {@link android.hardware.SensorEvent#values SensorEvent.values} for more details.
      *
diff --git a/core/java/android/hardware/SensorEvent.java b/core/java/android/hardware/SensorEvent.java
index 9906331..236fab0 100644
--- a/core/java/android/hardware/SensorEvent.java
+++ b/core/java/android/hardware/SensorEvent.java
@@ -550,7 +550,7 @@
      *   <h4>{@link android.hardware.Sensor#TYPE_HEART_BEAT
      * Sensor.TYPE_HEART_BEAT}:</h4>
      *
-     * A sensor of this type returns an event everytime a hear beat peak is
+     * A sensor of this type returns an event everytime a heart beat peak is
      * detected.
      *
      * Peak here ideally corresponds to the positive peak in the QRS complex of
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index decf053..cd13707 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.hardware.camera2.params.InputConfiguration;
 import android.hardware.camera2.params.OutputConfiguration;
 import android.hardware.camera2.params.SessionConfiguration;
@@ -358,7 +357,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int SESSION_OPERATION_MODE_NORMAL =
             0; // ICameraDeviceUser.NORMAL_MODE;
 
@@ -369,7 +367,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int SESSION_OPERATION_MODE_CONSTRAINED_HIGH_SPEED =
             1; // ICameraDeviceUser.CONSTRAINED_HIGH_SPEED_MODE;
 
@@ -380,7 +377,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int SESSION_OPERATION_MODE_VENDOR_START =
             0x8000; // ICameraDeviceUser.VENDOR_MODE_START;
 
@@ -423,7 +419,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @Deprecated
     public abstract void createCustomCaptureSession(
             InputConfiguration inputConfig,
diff --git a/core/java/android/hardware/display/AmbientBrightnessDayStats.java b/core/java/android/hardware/display/AmbientBrightnessDayStats.java
index 26fd265..8aff911 100644
--- a/core/java/android/hardware/display/AmbientBrightnessDayStats.java
+++ b/core/java/android/hardware/display/AmbientBrightnessDayStats.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -36,7 +35,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class AmbientBrightnessDayStats implements Parcelable {
 
     /** The localdate for which brightness stats are being tracked */
diff --git a/core/java/android/hardware/display/BrightnessChangeEvent.java b/core/java/android/hardware/display/BrightnessChangeEvent.java
index a6a44be..e2d836c 100644
--- a/core/java/android/hardware/display/BrightnessChangeEvent.java
+++ b/core/java/android/hardware/display/BrightnessChangeEvent.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -32,7 +31,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class BrightnessChangeEvent implements Parcelable {
     /** Brightness in nits */
     public final float brightness;
diff --git a/core/java/android/hardware/display/BrightnessConfiguration.java b/core/java/android/hardware/display/BrightnessConfiguration.java
index 6412a0c..d9c1063 100644
--- a/core/java/android/hardware/display/BrightnessConfiguration.java
+++ b/core/java/android/hardware/display/BrightnessConfiguration.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.content.pm.ApplicationInfo;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -44,7 +43,6 @@
 
 /** @hide */
 @SystemApi
-@TestApi
 public final class BrightnessConfiguration implements Parcelable {
     private static final String TAG_BRIGHTNESS_CURVE = "brightness-curve";
     private static final String TAG_BRIGHTNESS_POINT = "brightness-point";
diff --git a/core/java/android/hardware/display/BrightnessCorrection.java b/core/java/android/hardware/display/BrightnessCorrection.java
index 0879787..bbfc45e 100644
--- a/core/java/android/hardware/display/BrightnessCorrection.java
+++ b/core/java/android/hardware/display/BrightnessCorrection.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.MathUtils;
@@ -44,7 +43,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class BrightnessCorrection implements Parcelable {
 
     private static final int SCALE_AND_TRANSLATE_LOG = 1;
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index fc14b89..68b9d52 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -699,7 +699,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public Point getStableDisplaySize() {
         return mGlobal.getStableDisplaySize();
     }
@@ -709,7 +708,6 @@
      * @hide until we make it a system api.
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(Manifest.permission.BRIGHTNESS_SLIDER_USAGE)
     public List<BrightnessChangeEvent> getBrightnessEvents() {
         return mGlobal.getBrightnessEvents(mContext.getOpPackageName());
@@ -721,7 +719,6 @@
      * @hide until we make it a system api
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(Manifest.permission.ACCESS_AMBIENT_LIGHT_STATS)
     public List<AmbientBrightnessDayStats> getAmbientBrightnessStats() {
         return mGlobal.getAmbientBrightnessStats();
@@ -733,7 +730,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS)
     public void setBrightnessConfiguration(BrightnessConfiguration c) {
         setBrightnessConfigurationForUser(c, mContext.getUserId(), mContext.getPackageName());
@@ -758,7 +754,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS)
     public BrightnessConfiguration getBrightnessConfiguration() {
         return getBrightnessConfigurationForUser(mContext.getUserId());
@@ -784,7 +779,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS)
     @Nullable
     public BrightnessConfiguration getDefaultBrightnessConfiguration() {
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index a86c5cb..defcab7 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -267,12 +267,6 @@
     public abstract void ignoreProximitySensorUntilChanged();
 
     /**
-     * Sets the folded state of the device.
-     * TODO: b/168208522 - Remove in favor of DisplayStatePolicy when that is available.
-     */
-    public abstract void setDeviceFolded(boolean isFolded);
-
-    /**
      * Describes the requested power state of the display.
      *
      * This object is intended to describe the general characteristics of the
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index e5e7320..5b186c7 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -28,7 +28,6 @@
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
-import android.annotation.TestApi;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.os.Binder;
@@ -60,7 +59,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 @SystemService(Context.HDMI_CONTROL_SERVICE)
 @RequiresFeature(PackageManager.FEATURE_HDMI_CEC)
 public final class HdmiControlManager {
diff --git a/core/java/android/hardware/hdmi/HdmiPortInfo.java b/core/java/android/hardware/hdmi/HdmiPortInfo.java
index 52c3628..e97e120 100644
--- a/core/java/android/hardware/hdmi/HdmiPortInfo.java
+++ b/core/java/android/hardware/hdmi/HdmiPortInfo.java
@@ -18,7 +18,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -29,7 +28,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class HdmiPortInfo implements Parcelable {
     /** HDMI port type: Input */
     public static final int PORT_INPUT = 0;
diff --git a/core/java/android/hardware/hdmi/HdmiSwitchClient.java b/core/java/android/hardware/hdmi/HdmiSwitchClient.java
index 4685e1e..cbfbe39 100644
--- a/core/java/android/hardware/hdmi/HdmiSwitchClient.java
+++ b/core/java/android/hardware/hdmi/HdmiSwitchClient.java
@@ -18,7 +18,6 @@
 import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.hardware.hdmi.HdmiControlManager.ControlCallbackResult;
 import android.os.Binder;
 import android.os.RemoteException;
@@ -39,7 +38,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public class HdmiSwitchClient extends HdmiClient {
 
     private static final String TAG = "HdmiSwitchClient";
diff --git a/core/java/android/hardware/lights/Light.java b/core/java/android/hardware/lights/Light.java
index 1c95fb6..da27018 100644
--- a/core/java/android/hardware/lights/Light.java
+++ b/core/java/android/hardware/lights/Light.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -29,7 +28,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class Light implements Parcelable {
     private final int mId;
     private final int mOrdinal;
diff --git a/core/java/android/hardware/lights/LightState.java b/core/java/android/hardware/lights/LightState.java
index e55aa70..cd39e6d 100644
--- a/core/java/android/hardware/lights/LightState.java
+++ b/core/java/android/hardware/lights/LightState.java
@@ -19,7 +19,6 @@
 import android.annotation.ColorInt;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -36,7 +35,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class LightState implements Parcelable {
     private final int mColor;
 
diff --git a/core/java/android/hardware/lights/LightsManager.java b/core/java/android/hardware/lights/LightsManager.java
index 8cd2312..33e5fca 100644
--- a/core/java/android/hardware/lights/LightsManager.java
+++ b/core/java/android/hardware/lights/LightsManager.java
@@ -45,7 +45,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 @SystemService(Context.LIGHTS_SERVICE)
 public final class LightsManager {
     private static final String TAG = "LightsManager";
diff --git a/core/java/android/hardware/lights/LightsRequest.java b/core/java/android/hardware/lights/LightsRequest.java
index 5c4fc67..a318992 100644
--- a/core/java/android/hardware/lights/LightsRequest.java
+++ b/core/java/android/hardware/lights/LightsRequest.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.util.SparseArray;
 
 import com.android.internal.util.Preconditions;
@@ -29,7 +28,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class LightsRequest {
 
     /** Visible to {@link LightsManager.Session}. */
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index ecdbf4c..e58403f 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -67,7 +67,6 @@
  *
  * @hide
  */
-@TestApi
 @SystemApi
 public class SoundTrigger {
     private static final String TAG = "SoundTrigger";
diff --git a/core/java/android/metrics/LogMaker.java b/core/java/android/metrics/LogMaker.java
index d8a2082..a19eb56 100644
--- a/core/java/android/metrics/LogMaker.java
+++ b/core/java/android/metrics/LogMaker.java
@@ -16,7 +16,6 @@
 package android.metrics;
 
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.content.ComponentName;
 import android.util.Log;
 import android.util.SparseArray;
@@ -32,7 +31,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public class LogMaker {
     private static final String TAG = "LogBuilder";
 
diff --git a/core/java/android/metrics/MetricsReader.java b/core/java/android/metrics/MetricsReader.java
index 27f9a5d..5f356ca 100644
--- a/core/java/android/metrics/MetricsReader.java
+++ b/core/java/android/metrics/MetricsReader.java
@@ -16,7 +16,6 @@
 package android.metrics;
 
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.util.EventLog;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -36,7 +35,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public class MetricsReader {
     private Queue<LogMaker> mPendingQueue = new LinkedList<>();
     private Queue<LogMaker> mSeenQueue = new LinkedList<>();
diff --git a/core/java/android/net/CaptivePortal.java b/core/java/android/net/CaptivePortal.java
index 8afeb30..c2586fa 100644
--- a/core/java/android/net/CaptivePortal.java
+++ b/core/java/android/net/CaptivePortal.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -42,7 +41,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int APP_RETURN_DISMISSED    = 0;
     /**
      * Response code from the captive portal application, indicating that the user did not login and
@@ -52,7 +50,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int APP_RETURN_UNWANTED     = 1;
     /**
      * Response code from the captive portal application, indicating that the user does not wish to
@@ -62,7 +59,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int APP_RETURN_WANTED_AS_IS = 2;
     /** Event offset of request codes from captive portal application. */
     private static final int APP_REQUEST_BASE = 100;
@@ -74,7 +70,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int APP_REQUEST_REEVALUATION_REQUIRED = APP_REQUEST_BASE + 0;
 
     private final IBinder mBinder;
@@ -154,7 +149,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public void useNetwork() {
         try {
             ICaptivePortal.Stub.asInterface(mBinder).appResponse(APP_RETURN_WANTED_AS_IS);
@@ -167,7 +161,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
     public void reevaluateNetwork() {
         try {
@@ -183,7 +176,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public void logEvent(@EventId int eventId, @NonNull String packageName) {
         try {
             ICaptivePortal.Stub.asInterface(mBinder).logEvent(eventId, packageName);
diff --git a/core/java/android/net/CaptivePortalData.java b/core/java/android/net/CaptivePortalData.java
index 09f4762..59e62a6 100644
--- a/core/java/android/net/CaptivePortalData.java
+++ b/core/java/android/net/CaptivePortalData.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -30,7 +29,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class CaptivePortalData implements Parcelable {
     private final long mRefreshTimeMillis;
     @Nullable
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index b2eba63..1012f47 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -269,7 +269,6 @@
      * {@hide}
      */
     @SystemApi
-    @TestApi
     public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC =
             "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC";
 
@@ -278,7 +277,6 @@
      * {@hide}
      */
     @SystemApi
-    @TestApi
     public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT =
             "android.net.extra.CAPTIVE_PORTAL_USER_AGENT";
 
@@ -4413,7 +4411,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK)
     public void startCaptivePortalApp(@NonNull Network network, @NonNull Bundle appExtras) {
         try {
diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java
index d975017..5860e20 100644
--- a/core/java/android/net/EthernetManager.java
+++ b/core/java/android/net/EthernetManager.java
@@ -37,7 +37,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 @SystemService(Context.ETHERNET_SERVICE)
 public class EthernetManager {
     private static final String TAG = "EthernetManager";
diff --git a/core/java/android/net/IpPrefix.java b/core/java/android/net/IpPrefix.java
index 06f5f27..bcb65fa 100644
--- a/core/java/android/net/IpPrefix.java
+++ b/core/java/android/net/IpPrefix.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Pair;
@@ -89,7 +88,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public IpPrefix(@NonNull InetAddress address, @IntRange(from = 0, to = 128) int prefixLength) {
         // We don't reuse the (byte[], int) constructor because it calls clone() on the byte array,
         // which is unnecessary because getAddress() already returns a clone.
@@ -108,7 +106,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public IpPrefix(@NonNull String prefix) {
         // We don't reuse the (InetAddress, int) constructor because "error: call to this must be
         // first statement in constructor". We could factor out setting the member variables to an
diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java
index 772c685..d1bdaa0 100644
--- a/core/java/android/net/LinkAddress.java
+++ b/core/java/android/net/LinkAddress.java
@@ -30,7 +30,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Build;
 import android.os.Parcel;
@@ -158,7 +157,6 @@
      * @return true if the address is IPv6.
      * @hide
      */
-    @TestApi
     @SystemApi
     public boolean isIpv6() {
         return address instanceof Inet6Address;
@@ -180,7 +178,6 @@
      * @return true if the address is IPv4 or is a mapped IPv4 address.
      * @hide
      */
-    @TestApi
     @SystemApi
     public boolean isIpv4() {
         return address instanceof Inet4Address;
@@ -243,7 +240,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public LinkAddress(@NonNull InetAddress address, @IntRange(from = 0, to = 128) int prefixLength,
             int flags, int scope) {
         init(address, prefixLength, flags, scope, LIFETIME_UNKNOWN, LIFETIME_UNKNOWN);
@@ -275,7 +271,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public LinkAddress(@NonNull InetAddress address, @IntRange(from = 0, to = 128) int prefixLength,
                        int flags, int scope, long deprecationTime, long expirationTime) {
         init(address, prefixLength, flags, scope, deprecationTime, expirationTime);
@@ -289,7 +284,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public LinkAddress(@NonNull InetAddress address,
             @IntRange(from = 0, to = 128) int prefixLength) {
         this(address, prefixLength, 0, 0);
@@ -314,7 +308,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public LinkAddress(@NonNull String address) {
         this(address, 0, 0);
         this.scope = scopeForUnicastAddress(this.address);
@@ -329,7 +322,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public LinkAddress(@NonNull String address, int flags, int scope) {
         // This may throw an IllegalArgumentException; catching it is the caller's responsibility.
         // TODO: consider rejecting mapped IPv4 addresses such as "::ffff:192.0.2.5/24".
@@ -389,7 +381,6 @@
      * otherwise.
      * @hide
      */
-    @TestApi
     @SystemApi
     public boolean isSameAddressAs(@Nullable LinkAddress other) {
         if (other == null) {
@@ -469,7 +460,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public long getDeprecationTime() {
         return deprecationTime;
     }
@@ -485,7 +475,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public long getExpirationTime() {
         return expirationTime;
     }
@@ -496,7 +485,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public boolean isGlobalPreferred() {
         /**
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 555d710..25a76f4 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -19,10 +19,8 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.net.util.LinkPropertiesUtils;
-import android.net.util.LinkPropertiesUtils.CompareResult;
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -162,7 +160,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public LinkProperties(@Nullable LinkProperties source) {
         this(source, false /* parcelSensitiveFields */);
     }
@@ -178,7 +175,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public LinkProperties(@Nullable LinkProperties source, boolean parcelSensitiveFields) {
         mParcelSensitiveFields = parcelSensitiveFields;
         if (source == null) return;
@@ -293,7 +289,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public boolean addLinkAddress(@NonNull LinkAddress address) {
         if (address == null) {
             return false;
@@ -322,7 +317,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public boolean removeLinkAddress(@NonNull LinkAddress toRemove) {
         int i = findLinkAddressIndex(toRemove);
         if (i >= 0) {
@@ -376,7 +370,6 @@
      * @return true if the DNS server was added, false if it was already present.
      * @hide
      */
-    @TestApi
     @SystemApi
     public boolean addDnsServer(@NonNull InetAddress dnsServer) {
         if (dnsServer != null && !mDnses.contains(dnsServer)) {
@@ -393,7 +386,6 @@
      * @return true if the DNS server was removed, false if it did not exist.
      * @hide
      */
-    @TestApi
     @SystemApi
     public boolean removeDnsServer(@NonNull InetAddress dnsServer) {
         return mDnses.remove(dnsServer);
@@ -428,7 +420,6 @@
      * @param usePrivateDns The private DNS state.
      * @hide
      */
-    @TestApi
     @SystemApi
     public void setUsePrivateDns(boolean usePrivateDns) {
         mUsePrivateDns = usePrivateDns;
@@ -455,7 +446,6 @@
      * @param privateDnsServerName The private DNS server name.
      * @hide
      */
-    @TestApi
     @SystemApi
     public void setPrivateDnsServerName(@Nullable String privateDnsServerName) {
         mPrivateDnsServerName = privateDnsServerName;
@@ -534,7 +524,6 @@
      *        object.
      * @hide
      */
-    @TestApi
     @SystemApi
     public void setValidatedPrivateDnsServers(@NonNull Collection<InetAddress> dnsServers) {
         mValidatedPrivateDnses.clear();
@@ -551,7 +540,6 @@
      *         DNS servers on this link.
      * @hide
      */
-    @TestApi
     @SystemApi
     public @NonNull List<InetAddress> getValidatedPrivateDnsServers() {
         return Collections.unmodifiableList(mValidatedPrivateDnses);
@@ -592,7 +580,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public void setPcscfServers(@NonNull Collection<InetAddress> pcscfServers) {
         mPcscfs.clear();
         for (InetAddress pcscfServer: pcscfServers) {
@@ -608,7 +595,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public @NonNull List<InetAddress> getPcscfServers() {
         return Collections.unmodifiableList(mPcscfs);
     }
@@ -662,7 +648,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public void setTcpBufferSizes(@Nullable String tcpBufferSizes) {
         mTcpBufferSizes = tcpBufferSizes;
@@ -675,7 +660,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public @Nullable String getTcpBufferSizes() {
         return mTcpBufferSizes;
@@ -744,7 +728,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public boolean removeRoute(@NonNull RouteInfo route) {
         return Objects.equals(mIfaceName, route.getInterface()) && mRoutes.remove(route);
@@ -1021,7 +1004,6 @@
      * @return {@code true} if there is an IPv4 address, {@code false} otherwise.
      * @hide
      */
-    @TestApi
     @SystemApi
     public boolean hasIpv4Address() {
         for (LinkAddress address : mLinkAddresses) {
@@ -1062,7 +1044,6 @@
      * @return {@code true} if there is a global preferred IPv6 address, {@code false} otherwise.
      * @hide
      */
-    @TestApi
     @SystemApi
     public boolean hasGlobalIpv6Address() {
         for (LinkAddress address : mLinkAddresses) {
@@ -1149,7 +1130,6 @@
      * @return {@code true} if there is an IPv6 default route, {@code false} otherwise.
      * @hide
      */
-    @TestApi
     @SystemApi
     public boolean hasIpv6DefaultRoute() {
         for (RouteInfo r : mRoutes) {
@@ -1265,7 +1245,6 @@
      * @return {@code true} if the link is provisioned, {@code false} otherwise.
      * @hide
      */
-    @TestApi
     @SystemApi
     public boolean isIpv4Provisioned() {
         return (hasIpv4Address()
@@ -1280,7 +1259,6 @@
      * @return {@code true} if the link is provisioned, {@code false} otherwise.
      * @hide
      */
-    @TestApi
     @SystemApi
     public boolean isIpv6Provisioned() {
         return (hasGlobalIpv6Address()
@@ -1308,7 +1286,6 @@
      * @return {@code true} if the link is provisioned, {@code false} otherwise.
      * @hide
      */
-    @TestApi
     @SystemApi
     public boolean isProvisioned() {
         return (isIpv4Provisioned() || isIpv6Provisioned());
@@ -1321,7 +1298,6 @@
      *         {@code false} otherwise.
      * @hide
      */
-    @TestApi
     @SystemApi
     public boolean isReachable(@NonNull InetAddress ip) {
         final List<RouteInfo> allRoutes = getAllRoutes();
@@ -1578,7 +1554,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public void setCaptivePortalApiUrl(@Nullable Uri url) {
         mCaptivePortalApiUrl = url;
     }
@@ -1593,7 +1568,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @Nullable
     public Uri getCaptivePortalApiUrl() {
         return mCaptivePortalApiUrl;
@@ -1604,7 +1578,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public void setCaptivePortalData(@Nullable CaptivePortalData data) {
         mCaptivePortalData = data;
     }
@@ -1618,7 +1591,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @Nullable
     public CaptivePortalData getCaptivePortalData() {
         return mCaptivePortalData;
@@ -1669,78 +1641,6 @@
     }
 
     /**
-     * Compares the DNS addresses in this LinkProperties with another
-     * LinkProperties, examining only DNS addresses on the base link.
-     *
-     * @param target a LinkProperties with the new list of dns addresses
-     * @return the differences between the DNS addresses.
-     * @hide
-     */
-    public @NonNull CompareResult<InetAddress> compareDnses(@Nullable LinkProperties target) {
-        /*
-         * Duplicate the InetAddresses into removed, we will be removing
-         * dns address which are common between mDnses and target
-         * leaving the addresses that are different. And dns address which
-         * are in target but not in mDnses are placed in the
-         * addedAddresses.
-         */
-        return new CompareResult<>(mDnses, target != null ? target.getDnsServers() : null);
-    }
-
-    /**
-     * Compares the validated private DNS addresses in this LinkProperties with another
-     * LinkProperties.
-     *
-     * @param target a LinkProperties with the new list of validated private dns addresses
-     * @return the differences between the DNS addresses.
-     * @hide
-     */
-    public @NonNull CompareResult<InetAddress> compareValidatedPrivateDnses(
-            @Nullable LinkProperties target) {
-        return new CompareResult<>(mValidatedPrivateDnses,
-                target != null ? target.getValidatedPrivateDnsServers() : null);
-    }
-
-    /**
-     * Compares all routes in this LinkProperties with another LinkProperties,
-     * examining both the the base link and all stacked links.
-     *
-     * @param target a LinkProperties with the new list of routes
-     * @return the differences between the routes.
-     * @hide
-     */
-    public @NonNull CompareResult<RouteInfo> compareAllRoutes(@Nullable LinkProperties target) {
-        /*
-         * Duplicate the RouteInfos into removed, we will be removing
-         * routes which are common between mRoutes and target
-         * leaving the routes that are different. And route address which
-         * are in target but not in mRoutes are placed in added.
-         */
-        return new CompareResult<>(getAllRoutes(), target != null ? target.getAllRoutes() : null);
-    }
-
-    /**
-     * Compares all interface names in this LinkProperties with another
-     * LinkProperties, examining both the the base link and all stacked links.
-     *
-     * @param target a LinkProperties with the new list of interface names
-     * @return the differences between the interface names.
-     * @hide
-     */
-    public @NonNull CompareResult<String> compareAllInterfaceNames(
-            @Nullable LinkProperties target) {
-        /*
-         * Duplicate the interface names into removed, we will be removing
-         * interface names which are common between this and target
-         * leaving the interface names that are different. And interface names which
-         * are in target but not in this are placed in added.
-         */
-        return new CompareResult<>(getAllInterfaceNames(),
-                target != null ? target.getAllInterfaceNames() : null);
-    }
-
-
-    /**
      * Generate hashcode based on significant fields
      *
      * Equal objects must produce the same hash code, while unequal objects
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index 10ee72e..3e4f735 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -128,7 +127,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public Network(@NonNull Network that) {
         this(that.netId, that.mPrivateDnsBypass);
     }
@@ -165,7 +163,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public @NonNull Network getPrivateDnsBypassingCopy() {
         return new Network(netId, true);
@@ -176,7 +173,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public int getNetId() {
         return netId;
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 004f844..be33f4e 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -850,7 +850,6 @@
      * @return an array of transport type values for this instance.
      * @hide
      */
-    @TestApi
     @SystemApi
     @NonNull public @Transport int[] getTransportTypes() {
         return BitUtils.unpackBits(mTransportTypes);
@@ -1025,7 +1024,6 @@
      */
     @NonNull
     @SystemApi
-    @TestApi
     public int[] getAdministratorUids() {
         return Arrays.copyOf(mAdministratorUids, mAdministratorUids.length);
     }
@@ -1506,7 +1504,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public @Nullable String getSsid() {
         return mSSID;
     }
@@ -1590,7 +1587,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public boolean satisfiedByNetworkCapabilities(@Nullable NetworkCapabilities nc) {
         return satisfiedByNetworkCapabilities(nc, false);
@@ -2136,7 +2132,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final class Builder {
         private final NetworkCapabilities mCaps;
 
diff --git a/core/java/android/net/NetworkStack.java b/core/java/android/net/NetworkStack.java
index 86f3dfd..79f9e6e 100644
--- a/core/java/android/net/NetworkStack.java
+++ b/core/java/android/net/NetworkStack.java
@@ -33,7 +33,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public class NetworkStack {
     /**
      * Permission granted only to the NetworkStack APK, defined in NetworkStackStub with signature
@@ -41,7 +40,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final String PERMISSION_MAINLINE_NETWORK_STACK =
             "android.permission.MAINLINE_NETWORK_STACK";
 
@@ -54,7 +52,6 @@
      */
     @Nullable
     @SystemApi
-    @TestApi
     public static IBinder getService() {
         final IBinder mockService = sMockService;
         if (mockService != null) return mockService;
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index d956875..93ad41f7 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.net.util.NetUtils;
 import android.os.Build;
@@ -87,17 +86,14 @@
 
     /** Unicast route. @hide */
     @SystemApi
-    @TestApi
     public static final int RTN_UNICAST = 1;
 
     /** Unreachable route. @hide */
     @SystemApi
-    @TestApi
     public static final int RTN_UNREACHABLE = 7;
 
     /** Throw route. @hide */
     @SystemApi
-    @TestApi
     public static final int RTN_THROW = 9;
 
     /**
@@ -135,7 +131,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway,
             @Nullable String iface, @RouteType int type) {
         this(destination, gateway, iface, type, 0);
@@ -397,7 +392,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     @RouteType
     public int getType() {
diff --git a/core/java/android/net/StaticIpConfiguration.java b/core/java/android/net/StaticIpConfiguration.java
index a973455..f56d656 100644
--- a/core/java/android/net/StaticIpConfiguration.java
+++ b/core/java/android/net/StaticIpConfiguration.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -52,7 +51,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class StaticIpConfiguration implements Parcelable {
     /** @hide */
     @UnsupportedAppUsage
diff --git a/core/java/android/net/apf/ApfCapabilities.java b/core/java/android/net/apf/ApfCapabilities.java
index 92c5432..bf5b26e 100644
--- a/core/java/android/net/apf/ApfCapabilities.java
+++ b/core/java/android/net/apf/ApfCapabilities.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.content.res.Resources;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -36,7 +35,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class ApfCapabilities implements Parcelable {
     /**
      * Version of APF instruction set supported for packet filtering. 0 indicates no support for
diff --git a/core/java/android/net/metrics/ApfProgramEvent.java b/core/java/android/net/metrics/ApfProgramEvent.java
index f93907a..c50bae9 100644
--- a/core/java/android/net/metrics/ApfProgramEvent.java
+++ b/core/java/android/net/metrics/ApfProgramEvent.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -40,7 +39,6 @@
  * the APF program in place with a new APF program.
  * {@hide}
  */
-@TestApi
 @SystemApi
 public final class ApfProgramEvent implements IpConnectivityLog.Event {
 
diff --git a/core/java/android/net/metrics/ApfStats.java b/core/java/android/net/metrics/ApfStats.java
index b221cb9..2a601b2 100644
--- a/core/java/android/net/metrics/ApfStats.java
+++ b/core/java/android/net/metrics/ApfStats.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -29,7 +28,6 @@
  * {@hide}
  */
 @SystemApi
-@TestApi
 public final class ApfStats implements IpConnectivityLog.Event {
 
     /**
@@ -126,7 +124,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final class Builder {
         private long mDurationMs;
         private int mReceivedRas;
diff --git a/core/java/android/net/metrics/DhcpClientEvent.java b/core/java/android/net/metrics/DhcpClientEvent.java
index 8fc1ef8..e0a93dd 100644
--- a/core/java/android/net/metrics/DhcpClientEvent.java
+++ b/core/java/android/net/metrics/DhcpClientEvent.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -30,7 +29,6 @@
  * {@hide}
  */
 @SystemApi
-@TestApi
 public final class DhcpClientEvent implements IpConnectivityLog.Event {
 
     // Names for recording DhcpClient pseudo-state transitions.
diff --git a/core/java/android/net/metrics/DhcpErrorEvent.java b/core/java/android/net/metrics/DhcpErrorEvent.java
index 32efb5a..de3129d 100644
--- a/core/java/android/net/metrics/DhcpErrorEvent.java
+++ b/core/java/android/net/metrics/DhcpErrorEvent.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.SparseArray;
@@ -30,7 +29,6 @@
  * {@hide}
  */
 @SystemApi
-@TestApi
 public final class DhcpErrorEvent implements IpConnectivityLog.Event {
     public static final int L2_ERROR   = 1;
     public static final int L3_ERROR   = 2;
diff --git a/core/java/android/net/metrics/IpConnectivityLog.java b/core/java/android/net/metrics/IpConnectivityLog.java
index 680c015..a008d85 100644
--- a/core/java/android/net/metrics/IpConnectivityLog.java
+++ b/core/java/android/net/metrics/IpConnectivityLog.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.net.ConnectivityMetricsEvent;
 import android.net.IIpConnectivityMetrics;
 import android.net.Network;
@@ -35,7 +34,6 @@
  * {@hide}
  */
 @SystemApi
-@TestApi
 public class IpConnectivityLog {
     private static final String TAG = IpConnectivityLog.class.getSimpleName();
     private static final boolean DBG = false;
@@ -52,7 +50,6 @@
 
     /** @hide */
     @SystemApi
-    @TestApi
     public IpConnectivityLog() {
     }
 
diff --git a/core/java/android/net/metrics/IpManagerEvent.java b/core/java/android/net/metrics/IpManagerEvent.java
index f14abb8..4f7f326 100644
--- a/core/java/android/net/metrics/IpManagerEvent.java
+++ b/core/java/android/net/metrics/IpManagerEvent.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.SparseArray;
@@ -36,7 +35,6 @@
  * {@hide}
  */
 @SystemApi
-@TestApi
 public final class IpManagerEvent implements IpConnectivityLog.Event {
 
     public static final int PROVISIONING_OK                       = 1;
diff --git a/core/java/android/net/metrics/IpReachabilityEvent.java b/core/java/android/net/metrics/IpReachabilityEvent.java
index 79e01d7..d5003ba 100644
--- a/core/java/android/net/metrics/IpReachabilityEvent.java
+++ b/core/java/android/net/metrics/IpReachabilityEvent.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.SparseArray;
@@ -32,7 +31,6 @@
  * {@hide}
  */
 @SystemApi
-@TestApi
 public final class IpReachabilityEvent implements IpConnectivityLog.Event {
 
     // Event types.
diff --git a/core/java/android/net/metrics/NetworkEvent.java b/core/java/android/net/metrics/NetworkEvent.java
index fe603cf..8c28f7a 100644
--- a/core/java/android/net/metrics/NetworkEvent.java
+++ b/core/java/android/net/metrics/NetworkEvent.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.SparseArray;
@@ -34,7 +33,6 @@
  * {@hide}
  */
 @SystemApi
-@TestApi
 public final class NetworkEvent implements IpConnectivityLog.Event {
 
     public static final int NETWORK_CONNECTED            = 1;
diff --git a/core/java/android/net/metrics/RaEvent.java b/core/java/android/net/metrics/RaEvent.java
index 661f648..b54874f 100644
--- a/core/java/android/net/metrics/RaEvent.java
+++ b/core/java/android/net/metrics/RaEvent.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -28,7 +27,6 @@
  * {@hide}
  */
 @SystemApi
-@TestApi
 public final class RaEvent implements IpConnectivityLog.Event {
 
     private static final long NO_LIFETIME = -1L;
diff --git a/core/java/android/net/metrics/ValidationProbeEvent.java b/core/java/android/net/metrics/ValidationProbeEvent.java
index 8fab64a..7f4e4a7 100644
--- a/core/java/android/net/metrics/ValidationProbeEvent.java
+++ b/core/java/android/net/metrics/ValidationProbeEvent.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.SparseArray;
@@ -35,7 +34,6 @@
  * {@hide}
  */
 @SystemApi
-@TestApi
 public final class ValidationProbeEvent implements IpConnectivityLog.Event {
 
     public static final int PROBE_DNS       = 0;
diff --git a/core/java/android/net/util/SocketUtils.java b/core/java/android/net/util/SocketUtils.java
index 6967084..e64060f 100644
--- a/core/java/android/net/util/SocketUtils.java
+++ b/core/java/android/net/util/SocketUtils.java
@@ -22,7 +22,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.net.NetworkUtils;
 import android.system.ErrnoException;
 import android.system.NetlinkSocketAddress;
@@ -40,7 +39,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class SocketUtils {
     /**
      * Create a raw datagram socket that is bound to an interface.
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 12ec0a0..9a16d3f 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -20,7 +20,6 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
-import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.Intent;
@@ -392,7 +391,6 @@
      */
     @RequiresPermission(permission.POWER_SAVER)
     @SystemApi
-    @TestApi
     public boolean setChargingStateUpdateDelayMillis(int delayMillis) {
         try {
             return mBatteryStats.setChargingStateUpdateDelayMillis(delayMillis);
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index d492e08..fce3437 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -379,6 +379,7 @@
      *
      * @see #clearCallingIdentity
      */
+    @CriticalNative
     public static final native void restoreCallingIdentity(long token);
 
     /**
diff --git a/core/java/android/os/BugreportManager.java b/core/java/android/os/BugreportManager.java
index 9e996d1..fe4d729 100644
--- a/core/java/android/os/BugreportManager.java
+++ b/core/java/android/os/BugreportManager.java
@@ -24,13 +24,13 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
-import android.annotation.TestApi;
 import android.app.ActivityManager;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Handler;
 import android.util.Log;
 import android.widget.Toast;
+
 import com.android.internal.R;
 import com.android.internal.util.Preconditions;
 
@@ -48,7 +48,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 @SystemService(Context.BUGREPORT_SERVICE)
 public final class BugreportManager {
 
diff --git a/core/java/android/os/BugreportParams.java b/core/java/android/os/BugreportParams.java
index c8347813..279ccae 100644
--- a/core/java/android/os/BugreportParams.java
+++ b/core/java/android/os/BugreportParams.java
@@ -18,7 +18,6 @@
 
 import android.annotation.IntDef;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -29,7 +28,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class BugreportParams {
     private final int mMode;
 
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 085681d..5745187 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -256,7 +256,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static @NonNull File getOemDirectory() {
         return DIR_OEM_ROOT;
     }
@@ -268,7 +267,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static @NonNull File getOdmDirectory() {
         return DIR_ODM_ROOT;
     }
@@ -279,7 +277,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static @NonNull File getVendorDirectory() {
         return DIR_VENDOR_ROOT;
     }
@@ -291,7 +288,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static @NonNull File getProductDirectory() {
         return DIR_PRODUCT_ROOT;
     }
@@ -318,7 +314,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static @NonNull File getSystemExtDirectory() {
         return DIR_SYSTEM_EXT_ROOT;
     }
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index 6ba1627..be21fea 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -109,11 +109,11 @@
     private static final int UPDATABLE_DRIVER_GLOBAL_OPT_IN_PRERELEASE_DRIVER = 2;
     private static final int UPDATABLE_DRIVER_GLOBAL_OPT_IN_OFF = 3;
 
-    // Values for GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE
+    // Values for ANGLE_GL_DRIVER_ALL_ANGLE
     private static final int ANGLE_GL_DRIVER_ALL_ANGLE_ON = 1;
     private static final int ANGLE_GL_DRIVER_ALL_ANGLE_OFF = 0;
 
-    // Values for GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES
+    // Values for ANGLE_GL_DRIVER_SELECTION_VALUES
     private static final String ANGLE_GL_DRIVER_CHOICE_DEFAULT = "default";
     private static final String ANGLE_GL_DRIVER_CHOICE_ANGLE = "angle";
     private static final String ANGLE_GL_DRIVER_CHOICE_NATIVE = "native";
@@ -382,11 +382,11 @@
         final int allUseAngle;
         if (bundle != null) {
             allUseAngle =
-                    bundle.getInt(Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE);
+                    bundle.getInt(Settings.Global.ANGLE_GL_DRIVER_ALL_ANGLE);
         } else {
             ContentResolver contentResolver = context.getContentResolver();
             allUseAngle = Settings.Global.getInt(contentResolver,
-                    Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE,
+                    Settings.Global.ANGLE_GL_DRIVER_ALL_ANGLE,
                     ANGLE_GL_DRIVER_ALL_ANGLE_OFF);
         }
         if (allUseAngle == ANGLE_GL_DRIVER_ALL_ANGLE_ON) {
@@ -402,10 +402,10 @@
         final ContentResolver contentResolver = context.getContentResolver();
         final List<String> optInPackages =
                 getGlobalSettingsString(contentResolver, bundle,
-                        Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS);
+                        Settings.Global.ANGLE_GL_DRIVER_SELECTION_PKGS);
         final List<String> optInValues =
                 getGlobalSettingsString(contentResolver, bundle,
-                        Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES);
+                        Settings.Global.ANGLE_GL_DRIVER_SELECTION_VALUES);
 
         // Make sure we have good settings to use
         if (optInPackages.size() != optInValues.size()) {
@@ -462,11 +462,11 @@
 
         if (coreSettings != null) {
             debugPackage =
-                    coreSettings.getString(Settings.Global.GLOBAL_SETTINGS_ANGLE_DEBUG_PACKAGE);
+                    coreSettings.getString(Settings.Global.ANGLE_DEBUG_PACKAGE);
         } else {
             ContentResolver contentResolver = context.getContentResolver();
             debugPackage = Settings.Global.getString(contentResolver,
-                    Settings.Global.GLOBAL_SETTINGS_ANGLE_DEBUG_PACKAGE);
+                    Settings.Global.ANGLE_DEBUG_PACKAGE);
         }
         if (TextUtils.isEmpty(debugPackage)) {
             return "";
@@ -578,7 +578,7 @@
         final ContentResolver contentResolver = context.getContentResolver();
         final List<String> angleAllowlist =
                 getGlobalSettingsString(contentResolver, bundle,
-                    Settings.Global.GLOBAL_SETTINGS_ANGLE_ALLOWLIST);
+                    Settings.Global.ANGLE_ALLOWLIST);
 
         if (DEBUG) Log.v(TAG, "ANGLE allowlist: " + angleAllowlist);
 
@@ -678,7 +678,7 @@
         try {
             ContentResolver contentResolver = context.getContentResolver();
             final int showDialogBox = Settings.Global.getInt(contentResolver,
-                    Settings.Global.GLOBAL_SETTINGS_SHOW_ANGLE_IN_USE_DIALOG_BOX);
+                    Settings.Global.SHOW_ANGLE_IN_USE_DIALOG_BOX);
 
             return (showDialogBox == 1);
         } catch (Settings.SettingNotFoundException | SecurityException e) {
diff --git a/core/java/android/os/HidlMemory.java b/core/java/android/os/HidlMemory.java
index 02d1e0c..26fc6f0 100644
--- a/core/java/android/os/HidlMemory.java
+++ b/core/java/android/os/HidlMemory.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 
 import java.io.Closeable;
 import java.io.IOException;
@@ -41,7 +40,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public class HidlMemory implements Closeable {
     private final @NonNull String mName;
     private final long mSize;
diff --git a/core/java/android/os/HwBinder.java b/core/java/android/os/HwBinder.java
index 64ab1d7..0d2bfdf 100644
--- a/core/java/android/os/HwBinder.java
+++ b/core/java/android/os/HwBinder.java
@@ -17,7 +17,6 @@
 package android.os;
 
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 
 import libcore.util.NativeAllocationRegistry;
@@ -26,7 +25,6 @@
 
 /** @hide */
 @SystemApi
-@TestApi
 public abstract class HwBinder implements IHwBinder {
     private static final String TAG = "HwBinder";
 
diff --git a/core/java/android/os/HwBlob.java b/core/java/android/os/HwBlob.java
index 154227b2..a43fbdb 100644
--- a/core/java/android/os/HwBlob.java
+++ b/core/java/android/os/HwBlob.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 
 import libcore.util.NativeAllocationRegistry;
 
@@ -30,7 +29,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public class HwBlob {
     private static final String TAG = "HwBlob";
 
diff --git a/core/java/android/os/HwParcel.java b/core/java/android/os/HwParcel.java
index 228548a..9fd37d4 100644
--- a/core/java/android/os/HwParcel.java
+++ b/core/java/android/os/HwParcel.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 
 import dalvik.annotation.optimization.FastNative;
@@ -34,7 +33,6 @@
 
 /** @hide */
 @SystemApi
-@TestApi
 public class HwParcel {
     private static final String TAG = "HwParcel";
 
diff --git a/core/java/android/os/IHwBinder.java b/core/java/android/os/IHwBinder.java
index 46fa6ef..249eb3a 100644
--- a/core/java/android/os/IHwBinder.java
+++ b/core/java/android/os/IHwBinder.java
@@ -17,11 +17,9 @@
 package android.os;
 
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 
 /** @hide */
 @SystemApi
-@TestApi
 public interface IHwBinder {
     /**
      * Process a hwbinder transaction.
diff --git a/core/java/android/os/IHwInterface.java b/core/java/android/os/IHwInterface.java
index 0a5a715..f21f6e3 100644
--- a/core/java/android/os/IHwInterface.java
+++ b/core/java/android/os/IHwInterface.java
@@ -17,11 +17,9 @@
 package android.os;
 
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 
 /** @hide */
 @SystemApi
-@TestApi
 public interface IHwInterface {
     /**
      * @return the binder object that corresponds to this interface.
diff --git a/core/java/android/os/IncidentManager.java b/core/java/android/os/IncidentManager.java
index 565d31a..a543a2d 100644
--- a/core/java/android/os/IncidentManager.java
+++ b/core/java/android/os/IncidentManager.java
@@ -23,7 +23,6 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
-import android.annotation.TestApi;
 import android.content.Context;
 import android.net.Uri;
 import android.util.Slog;
@@ -45,7 +44,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 @SystemService(Context.INCIDENT_SERVICE)
 public class IncidentManager {
     private static final String TAG = "IncidentManager";
@@ -159,7 +157,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static class PendingReport {
         /**
          * Encoded data.
@@ -277,7 +274,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static class IncidentReport implements Parcelable, Closeable {
         private final long mTimestampNs;
         private final int mPrivacyPolicy;
diff --git a/core/java/android/os/IncidentReportArgs.java b/core/java/android/os/IncidentReportArgs.java
index 7e858e1..73e4914 100644
--- a/core/java/android/os/IncidentReportArgs.java
+++ b/core/java/android/os/IncidentReportArgs.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.IntArray;
@@ -30,7 +29,6 @@
  * {@hide}
  */
 @SystemApi
-@TestApi
 public final class IncidentReportArgs implements Parcelable {
 
     private final IntArray mSections = new IntArray();
diff --git a/core/java/android/os/NativeHandle.java b/core/java/android/os/NativeHandle.java
index 8d341b6..a26873a 100644
--- a/core/java/android/os/NativeHandle.java
+++ b/core/java/android/os/NativeHandle.java
@@ -20,7 +20,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.system.ErrnoException;
 import android.system.Os;
 
@@ -33,7 +32,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class NativeHandle implements Closeable {
     // whether this object owns mFds
     private boolean mOwn = false;
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 50f0c28..000b23f 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -1565,7 +1565,6 @@
      * @see #isPowerSaveMode()
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(anyOf = {
             android.Manifest.permission.DEVICE_POWER,
             android.Manifest.permission.POWER_SAVER
@@ -1610,7 +1609,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(permission.POWER_SAVER)
     public boolean setDynamicPowerSaveHint(boolean powerSaveHint, int disableThreshold) {
         try {
@@ -1670,7 +1668,6 @@
      *  @hide
      */
     @SystemApi
-    @TestApi
     public static final int POWER_SAVE_MODE_TRIGGER_PERCENTAGE = 0;
 
     /**
@@ -1683,7 +1680,6 @@
      *  @hide
      */
     @SystemApi
-    @TestApi
     public static final int POWER_SAVE_MODE_TRIGGER_DYNAMIC = 1;
 
     /** @hide */
@@ -1708,7 +1704,6 @@
      */
     @AutoPowerSaveModeTriggers
     @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.POWER_SAVER)
     public int getPowerSaveModeTrigger() {
         try {
@@ -1732,7 +1727,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.DEVICE_POWER)
     public void setBatteryDischargePrediction(@NonNull Duration timeRemaining,
             boolean isPersonalized) {
diff --git a/core/java/android/os/RemoteCallback.java b/core/java/android/os/RemoteCallback.java
index 373060f..49f84adf 100644
--- a/core/java/android/os/RemoteCallback.java
+++ b/core/java/android/os/RemoteCallback.java
@@ -19,14 +19,12 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 
 /**
  * @hide
  */
 @SystemApi
-@TestApi
 public final class RemoteCallback implements Parcelable {
 
     public interface OnResultListener {
diff --git a/core/java/android/os/SystemConfigManager.java b/core/java/android/os/SystemConfigManager.java
index 12a1ffa..3f0632b 100644
--- a/core/java/android/os/SystemConfigManager.java
+++ b/core/java/android/os/SystemConfigManager.java
@@ -20,7 +20,6 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
-import android.annotation.TestApi;
 import android.content.Context;
 import android.util.ArraySet;
 import android.util.Log;
@@ -40,7 +39,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 @SystemService(Context.SYSTEM_CONFIG_SERVICE)
 public class SystemConfigManager {
     private static final String TAG = SystemConfigManager.class.getSimpleName();
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index c5e5cc4..a164527 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.util.Log;
 import android.util.MutableInt;
@@ -52,7 +51,6 @@
  * {@hide}
  */
 @SystemApi
-@TestApi
 public class SystemProperties {
     private static final String TAG = "SystemProperties";
     private static final boolean TRACK_KEY_ACCESS = false;
@@ -146,7 +144,6 @@
      */
     @NonNull
     @SystemApi
-    @TestApi
     public static String get(@NonNull String key) {
         if (TRACK_KEY_ACCESS) onKeyAccess(key);
         return native_get(key);
@@ -163,7 +160,6 @@
      */
     @NonNull
     @SystemApi
-    @TestApi
     public static String get(@NonNull String key, @Nullable String def) {
         if (TRACK_KEY_ACCESS) onKeyAccess(key);
         return native_get(key, def);
@@ -179,7 +175,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static int getInt(@NonNull String key, int def) {
         if (TRACK_KEY_ACCESS) onKeyAccess(key);
         return native_get_int(key, def);
@@ -195,7 +190,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static long getLong(@NonNull String key, long def) {
         if (TRACK_KEY_ACCESS) onKeyAccess(key);
         return native_get_long(key, def);
@@ -216,7 +210,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static boolean getBoolean(@NonNull String key, boolean def) {
         if (TRACK_KEY_ACCESS) onKeyAccess(key);
         return native_get_boolean(key, def);
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 60447e7..d39c532 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -47,7 +47,6 @@
 
     /** @hide A user handle to indicate all users on the device */
     @SystemApi
-    @TestApi
     public static final @NonNull UserHandle ALL = new UserHandle(USER_ALL);
 
     /** @hide A user id to indicate the currently active user */
@@ -56,7 +55,6 @@
 
     /** @hide A user handle to indicate the current user of the device */
     @SystemApi
-    @TestApi
     public static final @NonNull UserHandle CURRENT = new UserHandle(USER_CURRENT);
 
     /** @hide A user id to indicate that we would like to send to the current
@@ -107,7 +105,6 @@
 
     /** @hide A user handle to indicate the "system" user of the device */
     @SystemApi
-    @TestApi
     public static final @NonNull UserHandle SYSTEM = new UserHandle(USER_SYSTEM);
 
     /**
@@ -280,7 +277,6 @@
     }
 
     /** @hide */
-    @TestApi
     @SystemApi
     public static UserHandle of(@UserIdInt int userId) {
         if (userId == USER_SYSTEM) {
@@ -325,7 +321,6 @@
      * Returns the app id (or base uid) for a given uid, stripping out the user id from it.
      * @hide
      */
-    @TestApi
     @SystemApi
     public static @AppIdInt int getAppId(int uid) {
         return uid % PER_USER_RANGE;
@@ -483,7 +478,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static @UserIdInt int myUserId() {
         return getUserId(Process.myUid());
     }
@@ -522,7 +516,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public @UserIdInt int getIdentifier() {
         return mHandle;
     }
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 42ae930..b0e76e3 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1407,8 +1407,7 @@
      *
      * @hide
      */
-    @SystemApi
-    @TestApi // To allow seeing it from CTS.
+    @SystemApi // To allow seeing it from CTS.
     public static final String ACTION_USER_RESTRICTIONS_CHANGED =
             "android.os.action.USER_RESTRICTIONS_CHANGED";
 
@@ -1468,6 +1467,48 @@
     public @interface UserSwitchabilityResult {}
 
     /**
+     * A response code from {@link #removeUserOrSetEphemeral(int)} indicating that the specified
+     * user has been successfully removed.
+     * @hide
+     */
+    public static final int REMOVE_RESULT_REMOVED = 0;
+
+    /**
+     * A response code from {@link #removeUserOrSetEphemeral(int)} indicating that the specified
+     * user has had its {@link UserInfo#FLAG_EPHEMERAL} flag set to {@code true}, so that it will be
+     * removed when the user is stopped or on boot.
+     * @hide
+     */
+    public static final int REMOVE_RESULT_SET_EPHEMERAL = 1;
+
+    /**
+     * A response code from {@link #removeUserOrSetEphemeral(int)} indicating that the specified
+     * user is already in the process of being removed.
+     * @hide
+     */
+    public static final int REMOVE_RESULT_ALREADY_BEING_REMOVED = 2;
+
+    /**
+     * A response code from {@link #removeUserOrSetEphemeral(int)} indicating that an error occurred
+     * that prevented the user from being removed or set as ephemeral.
+     * @hide
+     */
+    public static final int REMOVE_RESULT_ERROR = 3;
+
+    /**
+     * Possible response codes from {@link #removeUserOrSetEphemeral(int)}.
+     * @hide
+     */
+    @IntDef(prefix = { "REMOVE_RESULT_" }, value = {
+            REMOVE_RESULT_REMOVED,
+            REMOVE_RESULT_SET_EPHEMERAL,
+            REMOVE_RESULT_ALREADY_BEING_REMOVED,
+            REMOVE_RESULT_ERROR,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface RemoveResult {}
+
+    /**
      * Indicates user operation is successful.
      */
     public static final int USER_OPERATION_SUCCESS = 0;
@@ -3982,11 +4023,11 @@
      * the current user, then set the user as ephemeral so that it will be removed when it is
      * stopped.
      *
-     * @return the {@link com.android.server.pm.UserManagerService.RemoveResult} code
+     * @return the {@link RemoveResult} code
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
-    public int removeUserOrSetEphemeral(@UserIdInt int userId) {
+    public @RemoveResult int removeUserOrSetEphemeral(@UserIdInt int userId) {
         try {
             return mService.removeUserOrSetEphemeral(userId);
         } catch (RemoteException re) {
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index 0c0e6b5..7d85d13 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -23,7 +23,6 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
-import android.annotation.TestApi;
 import android.app.ActivityThread;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
@@ -469,7 +468,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
     public boolean isVibrating() {
         return false;
@@ -483,7 +481,6 @@
     * @hide
     */
     @SystemApi
-    @TestApi
     public interface OnVibratorStateChangedListener  {
         /**
          * Called when the vibrator state has changed.
@@ -502,7 +499,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
     public void addVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) {
     }
@@ -516,7 +512,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
     public void addVibratorStateListener(
             @NonNull @CallbackExecutor Executor executor,
@@ -531,7 +526,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
     public void removeVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) {
     }
diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java
index a1b4dc3..e0927eb 100644
--- a/core/java/android/os/WorkSource.java
+++ b/core/java/android/os/WorkSource.java
@@ -98,7 +98,6 @@
      * @param uid the uid performing the work
      * @hide
      */
-    @TestApi
     @SystemApi
     public WorkSource(int uid) {
         mNum = 1;
@@ -152,7 +151,6 @@
      * Returns the number of uids in this work source.
      * @hide
      */
-    @TestApi
     @SystemApi
     public int size() {
         return mNum;
@@ -173,7 +171,6 @@
      * If {@code index} < 0 or {@code index} >= {@link #size() N}, then the behavior is undefined.
      * @hide
      */
-    @TestApi
     @SystemApi
     public int getUid(int index) {
         return mUids[index];
@@ -209,7 +206,6 @@
      * If {@code index} < 0 or {@code index} >= {@link #size() N}, then the behavior is undefined.
      * @hide
      */
-    @TestApi
     @SystemApi
     @Nullable
     public String getPackageName(int index) {
@@ -455,7 +451,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @NonNull
     public WorkSource withoutNames() {
         final WorkSource copy = new WorkSource(this);
@@ -582,7 +577,6 @@
      * @hide for internal use only.
      */
     @SystemApi
-    @TestApi
     public boolean isEmpty() {
         return mNum == 0 && (mChains == null || mChains.isEmpty());
     }
diff --git a/core/java/android/os/image/DynamicSystemClient.java b/core/java/android/os/image/DynamicSystemClient.java
index 50d8d80..58268e2 100644
--- a/core/java/android/os/image/DynamicSystemClient.java
+++ b/core/java/android/os/image/DynamicSystemClient.java
@@ -22,7 +22,6 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -68,7 +67,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public class DynamicSystemClient {
     /** @hide */
     @IntDef(prefix = { "STATUS_" }, value = {
@@ -286,7 +284,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public DynamicSystemClient(@NonNull Context context) {
         mContext = context;
         mConnection = new DynSystemServiceConnection();
@@ -322,7 +319,6 @@
      */
     @RequiresPermission(android.Manifest.permission.INSTALL_DYNAMIC_SYSTEM)
     @SystemApi
-    @TestApi
     public void bind() {
         if (!featureFlagEnabled()) {
             Slog.w(TAG, FeatureFlagUtils.DYNAMIC_SYSTEM + " not enabled; bind() aborted.");
@@ -345,7 +341,6 @@
      */
     @RequiresPermission(android.Manifest.permission.INSTALL_DYNAMIC_SYSTEM)
     @SystemApi
-    @TestApi
     public void unbind() {
         if (!mBound) {
             return;
@@ -381,7 +376,6 @@
      */
     @RequiresPermission(android.Manifest.permission.INSTALL_DYNAMIC_SYSTEM)
     @SystemApi
-    @TestApi
     public void start(@NonNull Uri systemUrl, @BytesLong long systemSize) {
         start(systemUrl, systemSize, 0 /* Use the default userdata size */);
     }
diff --git a/core/java/android/os/incremental/IIncrementalService.aidl b/core/java/android/os/incremental/IIncrementalService.aidl
index 52475e9..ca92ad5 100644
--- a/core/java/android/os/incremental/IIncrementalService.aidl
+++ b/core/java/android/os/incremental/IIncrementalService.aidl
@@ -144,4 +144,14 @@
      * Stop listening for the loading progress change for a storage.
      */
     boolean unregisterLoadingProgressListener(int storageId);
+
+    /**
+     * Register storage health status listener.
+     */
+    boolean registerStorageHealthListener(int storageId, in StorageHealthCheckParams params, in IStorageHealthListener listener);
+
+    /**
+     * Register storage health status listener.
+     */
+    void unregisterStorageHealthListener(int storageId);
 }
diff --git a/core/java/android/os/incremental/IStorageHealthListener.aidl b/core/java/android/os/incremental/IStorageHealthListener.aidl
index 9f93ede..c71e73f 100644
--- a/core/java/android/os/incremental/IStorageHealthListener.aidl
+++ b/core/java/android/os/incremental/IStorageHealthListener.aidl
@@ -26,9 +26,15 @@
     /** There are reads pending for params.blockedTimeoutMs, waiting till
     *   params.unhealthyTimeoutMs to confirm unhealthy state. */
     const int HEALTH_STATUS_BLOCKED = 2;
-    /** There are reads pending for params.unhealthyTimeoutMs>,
-    *   marking storage as unhealthy. */
+    /** There are reads pending for params.unhealthyTimeoutMs,
+    *   marking storage as unhealthy due to unknown issues. */
     const int HEALTH_STATUS_UNHEALTHY = 3;
+    /** There are reads pending for params.unhealthyTimeoutMs,
+     *  due to data transportation issues. */
+    const int HEALTH_STATUS_UNHEALTHY_TRANSPORT = 4;
+    /** There are reads pending for params.unhealthyTimeoutMs,
+     *  due to limited storage space. */
+    const int HEALTH_STATUS_UNHEALTHY_STORAGE = 5;
 
     /** Health status callback. */
     void onHealthStatus(in int storageId, in int status);
diff --git a/core/java/android/os/incremental/IncrementalManager.java b/core/java/android/os/incremental/IncrementalManager.java
index 768ef97..fb47ef0 100644
--- a/core/java/android/os/incremental/IncrementalManager.java
+++ b/core/java/android/os/incremental/IncrementalManager.java
@@ -283,6 +283,7 @@
                 return;
             }
             mLoadingProgressCallbacks.cleanUpCallbacks(storage);
+            unregisterHealthListener(codePath);
             mService.deleteStorage(storage.getId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -297,7 +298,7 @@
      * @param callback To report loading progress to.
      * @return True if the package name and associated storage id are valid. False otherwise.
      */
-    public boolean registerCallback(@NonNull String codePath,
+    public boolean registerLoadingProgressCallback(@NonNull String codePath,
             @NonNull IPackageLoadingProgressCallback callback) {
         final IncrementalStorage storage = openStorage(codePath);
         if (storage == null) {
@@ -314,7 +315,7 @@
      * @param codePath Path of the installed package
      * @return True if the package name and associated storage id are valid. False otherwise.
      */
-    public boolean unregisterCallback(@NonNull String codePath,
+    public boolean unregisterLoadingProgressCallback(@NonNull String codePath,
             @NonNull IPackageLoadingProgressCallback callback) {
         final IncrementalStorage storage = openStorage(codePath);
         if (storage == null) {
@@ -414,6 +415,38 @@
         }
     }
 
+    /**
+     * Specify the health check params and listener for listening to Incremental Storage health
+     * status changes. Notice that this will overwrite the previously registered listener.
+     * @param codePath Path of the installed package. This path is on an Incremental Storage.
+     * @param healthCheckParams The params for health state change timeouts.
+     * @param listener To report health status change.
+     * @return True if listener was successfully registered.
+     */
+    public boolean registerHealthListener(@NonNull String codePath,
+            @NonNull StorageHealthCheckParams healthCheckParams,
+            @NonNull IStorageHealthListener.Stub listener) {
+        final IncrementalStorage storage = openStorage(codePath);
+        if (storage == null) {
+            // storage does not exist, package not installed
+            return false;
+        }
+        return storage.registerStorageHealthListener(healthCheckParams, listener);
+    }
+
+    /**
+     * Stop listening to health status changes on an Incremental Storage.
+     * @param codePath Path of the installed package. This path is on an Incremental Storage.
+     */
+    public void unregisterHealthListener(@NonNull String codePath) {
+        final IncrementalStorage storage = openStorage(codePath);
+        if (storage == null) {
+            // storage does not exist, package not installed
+            return;
+        }
+        storage.unregisterStorageHealthListener();
+    }
+
     /* Native methods */
     private static native boolean nativeIsEnabled();
     private static native boolean nativeIsIncrementalPath(@NonNull String path);
diff --git a/core/java/android/os/incremental/IncrementalStorage.java b/core/java/android/os/incremental/IncrementalStorage.java
index a1c3cc6..b913faf 100644
--- a/core/java/android/os/incremental/IncrementalStorage.java
+++ b/core/java/android/os/incremental/IncrementalStorage.java
@@ -545,4 +545,31 @@
             return false;
         }
     }
+
+    /**
+     * Register to listen to the status changes of the storage health.
+     * @param healthCheckParams Params to specify status change timeouts.
+     * @param listener To report health status change from Incremental Service to the caller.
+     */
+    public boolean registerStorageHealthListener(StorageHealthCheckParams healthCheckParams,
+            IStorageHealthListener listener) {
+        try {
+            return mService.registerStorageHealthListener(mId, healthCheckParams, listener);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+            return false;
+        }
+    }
+
+    /**
+     * Stops listening to the status changes of the storage health.
+     */
+    public void unregisterStorageHealthListener() {
+        try {
+            mService.unregisterStorageHealthListener(mId);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+            return;
+        }
+    }
 }
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 6b5eb16..270115b 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -43,7 +43,6 @@
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
-import android.annotation.TestApi;
 import android.annotation.WorkerThread;
 import android.app.Activity;
 import android.app.ActivityThread;
@@ -1701,7 +1700,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static boolean hasIsolatedStorage() {
         // Prefer to use snapshot for current boot when available
         return SystemProperties.getBoolean(PROP_ISOLATED_STORAGE_SNAPSHOT,
diff --git a/core/java/android/permission/PermissionControllerManager.java b/core/java/android/permission/PermissionControllerManager.java
index d6c95db..0ba09fd 100644
--- a/core/java/android/permission/PermissionControllerManager.java
+++ b/core/java/android/permission/PermissionControllerManager.java
@@ -79,7 +79,6 @@
  *
  * @hide
  */
-@TestApi
 @SystemApi
 @SystemService(Context.PERMISSION_CONTROLLER_SERVICE)
 public final class PermissionControllerManager {
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index 70b536d..c319e85 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -24,7 +24,6 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
-import android.annotation.TestApi;
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.app.ActivityThread;
@@ -57,7 +56,6 @@
  *
  * @hide
  */
-@TestApi
 @SystemApi
 @SystemService(Context.PERMISSION_SERVICE)
 public final class PermissionManager {
@@ -115,7 +113,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     @RequiresPermission(anyOf = {
             Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY,
@@ -136,7 +133,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     @RequiresPermission(anyOf = {
             Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY,
diff --git a/core/java/android/permission/RuntimePermissionPresentationInfo.java b/core/java/android/permission/RuntimePermissionPresentationInfo.java
index d696fea..4fce14c 100644
--- a/core/java/android/permission/RuntimePermissionPresentationInfo.java
+++ b/core/java/android/permission/RuntimePermissionPresentationInfo.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -33,7 +32,6 @@
  *
  * @hide
  */
-@TestApi
 @SystemApi
 public final class RuntimePermissionPresentationInfo implements Parcelable {
     private static final int FLAG_GRANTED = 1 << 0;
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 99ffee3..0315b56 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -55,7 +55,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class DeviceConfig {
     /**
      * The content:// style URL for the config table.
@@ -116,7 +115,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final String NAMESPACE_AUTOFILL = "autofill";
 
     /**
@@ -150,7 +148,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture";
 
     /**
@@ -250,7 +247,7 @@
      *
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String NAMESPACE_ROLLBACK = "rollback";
 
     /**
@@ -258,7 +255,7 @@
      *
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String NAMESPACE_ROLLBACK_BOOT = "rollback_boot";
 
     /**
@@ -403,7 +400,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final String NAMESPACE_PRIVACY = "privacy";
 
     /**
@@ -412,7 +408,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final String NAMESPACE_BIOMETRICS = "biometrics";
 
     /**
@@ -421,7 +416,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final String NAMESPACE_PERMISSIONS = "permissions";
 
     /**
@@ -467,7 +461,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(READ_DEVICE_CONFIG)
     public static String getProperty(@NonNull String namespace, @NonNull String name) {
         // Fetch all properties for the namespace at once and cache them in the local process, so we
@@ -496,7 +489,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @NonNull
     @RequiresPermission(READ_DEVICE_CONFIG)
     public static Properties getProperties(@NonNull String namespace, @NonNull String ... names) {
@@ -516,7 +508,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(READ_DEVICE_CONFIG)
     public static String getString(@NonNull String namespace, @NonNull String name,
             @Nullable String defaultValue) {
@@ -535,7 +526,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(READ_DEVICE_CONFIG)
     public static boolean getBoolean(@NonNull String namespace, @NonNull String name,
             boolean defaultValue) {
@@ -554,7 +544,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(READ_DEVICE_CONFIG)
     public static int getInt(@NonNull String namespace, @NonNull String name, int defaultValue) {
         String value = getProperty(namespace, name);
@@ -580,7 +569,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(READ_DEVICE_CONFIG)
     public static long getLong(@NonNull String namespace, @NonNull String name, long defaultValue) {
         String value = getProperty(namespace, name);
@@ -606,7 +594,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(READ_DEVICE_CONFIG)
     public static float getFloat(@NonNull String namespace, @NonNull String name,
             float defaultValue) {
@@ -642,7 +629,6 @@
      * @see #resetToDefaults(int, String).
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(WRITE_DEVICE_CONFIG)
     public static boolean setProperty(@NonNull String namespace, @NonNull String name,
             @Nullable String value, boolean makeDefault) {
@@ -666,7 +652,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(WRITE_DEVICE_CONFIG)
     public static boolean setProperties(@NonNull Properties properties) throws BadConfigException {
         ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver();
@@ -686,7 +671,6 @@
      * @see #setProperty(String, String, String, boolean)
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(WRITE_DEVICE_CONFIG)
     public static void resetToDefaults(@ResetMode int resetMode, @Nullable String namespace) {
         ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver();
@@ -708,7 +692,6 @@
      * @see #removeOnPropertiesChangedListener(OnPropertiesChangedListener)
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(READ_DEVICE_CONFIG)
     public static void addOnPropertiesChangedListener(
             @NonNull String namespace,
@@ -743,7 +726,6 @@
      * @see #addOnPropertiesChangedListener(String, Executor, OnPropertiesChangedListener)
      */
     @SystemApi
-    @TestApi
     public static void removeOnPropertiesChangedListener(
             @NonNull OnPropertiesChangedListener onPropertiesChangedListener) {
         Preconditions.checkNotNull(onPropertiesChangedListener);
@@ -878,7 +860,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public interface OnPropertiesChangedListener {
         /**
          * Called when one or more properties have changed, providing a Properties object with all
@@ -899,7 +880,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static class BadConfigException extends Exception {}
 
     /**
@@ -908,7 +888,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static class Properties {
         private final String mNamespace;
         private final HashMap<String, String> mMap;
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 8f69edb..062d929 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -22,7 +22,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ContentProvider;
 import android.content.ContentResolver;
@@ -1304,7 +1303,6 @@
      * {@hide}
      */
     @SystemApi
-    @TestApi
     public static @NonNull Uri setManageMode(@NonNull Uri uri) {
         Preconditions.checkNotNull(uri, "uri can not be null");
         return uri.buildUpon().appendQueryParameter(PARAM_MANAGE, "true").build();
@@ -1316,7 +1314,6 @@
      * {@hide}
      */
     @SystemApi
-    @TestApi
     public static boolean isManageMode(@NonNull Uri uri) {
         Preconditions.checkNotNull(uri, "uri can not be null");
         return uri.getBooleanQueryParameter(PARAM_MANAGE, false);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 68d8d82..0e3708e 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -229,7 +229,6 @@
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     @SystemApi
-    @TestApi
     public static final String ACTION_TETHER_PROVISIONING_UI =
             "android.settings.TETHER_PROVISIONING_UI";
 
@@ -1053,7 +1052,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_MANAGE_APP_OVERLAY_PERMISSION =
@@ -2017,7 +2015,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_ENTERPRISE_PRIVACY_SETTINGS
             = "android.settings.ENTERPRISE_PRIVACY_SETTINGS";
@@ -2100,7 +2097,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_REQUEST_ENABLE_CONTENT_CAPTURE =
             "android.settings.REQUEST_ENABLE_CONTENT_CAPTURE";
@@ -5580,7 +5576,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
         public static void resetToDefaults(@NonNull ContentResolver resolver,
                 @Nullable String tag) {
@@ -6051,7 +6046,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public static final String AUTOFILL_FEATURE_FIELD_CLASSIFICATION =
                 "autofill_field_classification";
 
@@ -6085,7 +6079,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public static final String AUTOFILL_USER_DATA_MAX_USER_DATA_SIZE =
                 "autofill_user_data_max_user_data_size";
 
@@ -6096,7 +6089,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public static final String AUTOFILL_USER_DATA_MAX_FIELD_CLASSIFICATION_IDS_SIZE =
                 "autofill_user_data_max_field_classification_size";
 
@@ -6107,7 +6099,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public static final String AUTOFILL_USER_DATA_MAX_CATEGORY_COUNT =
                 "autofill_user_data_max_category_count";
 
@@ -6117,7 +6108,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public static final String AUTOFILL_USER_DATA_MAX_VALUE_LENGTH =
                 "autofill_user_data_max_value_length";
 
@@ -6127,7 +6117,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public static final String AUTOFILL_USER_DATA_MIN_VALUE_LENGTH =
                 "autofill_user_data_min_value_length";
 
@@ -6177,7 +6166,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public static final String USER_SETUP_COMPLETE = "user_setup_complete";
 
         /**
@@ -6553,7 +6541,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public static final String LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS =
                 "lock_screen_allow_private_notifications";
 
@@ -7841,7 +7828,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public static final String DOZE_ALWAYS_ON = "doze_always_on";
 
         /**
@@ -8274,7 +8260,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public static final String LOCK_SCREEN_SHOW_NOTIFICATIONS =
                 "lock_screen_show_notifications";
 
@@ -8961,7 +8946,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public static final String LOCATION_ACCESS_CHECK_INTERVAL_MILLIS =
                 "location_access_check_interval_millis";
 
@@ -8970,7 +8954,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public static final String LOCATION_ACCESS_CHECK_DELAY_MILLIS =
                 "location_access_check_delay_millis";
 
@@ -10391,7 +10374,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public static final String TETHER_OFFLOAD_DISABLED = "tether_offload_disabled";
 
         /**
@@ -12367,37 +12349,34 @@
          * to dumpable apps that opt-in.
          * @hide
          */
-        public static final String GLOBAL_SETTINGS_ANGLE_DEBUG_PACKAGE =
-                "angle_debug_package";
+        public static final String ANGLE_DEBUG_PACKAGE = "angle_debug_package";
 
         /**
          * Force all PKGs to use ANGLE, regardless of any other settings
          * The value is a boolean (1 or 0).
          * @hide
          */
-        public static final String GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE =
-                "angle_gl_driver_all_angle";
+        public static final String ANGLE_GL_DRIVER_ALL_ANGLE = "angle_gl_driver_all_angle";
 
         /**
          * List of PKGs that have an OpenGL driver selected
          * @hide
          */
-        public static final String GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS =
+        public static final String ANGLE_GL_DRIVER_SELECTION_PKGS =
                 "angle_gl_driver_selection_pkgs";
 
         /**
          * List of selected OpenGL drivers, corresponding to the PKGs in GLOBAL_SETTINGS_DRIVER_PKGS
          * @hide
          */
-        public static final String GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES =
+        public static final String ANGLE_GL_DRIVER_SELECTION_VALUES =
                 "angle_gl_driver_selection_values";
 
         /**
          * List of package names that should check ANGLE rules
          * @hide
          */
-        public static final String GLOBAL_SETTINGS_ANGLE_ALLOWLIST =
-                "angle_allowlist";
+        public static final String ANGLE_ALLOWLIST = "angle_allowlist";
 
         /**
          * Lists of ANGLE EGL features for debugging.
@@ -12413,8 +12392,7 @@
          * The value is a boolean (1 or 0).
          * @hide
          */
-        public static final String GLOBAL_SETTINGS_SHOW_ANGLE_IN_USE_DIALOG_BOX =
-                "show_angle_in_use_dialog_box";
+        public static final String SHOW_ANGLE_IN_USE_DIALOG_BOX = "show_angle_in_use_dialog_box";
 
         /**
          * Updatable driver global preference for all Apps.
@@ -13373,7 +13351,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public static final String AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES =
                 "autofill_compat_mode_allowed_packages";
 
@@ -14551,6 +14528,16 @@
         public static final String SHOW_PEOPLE_SPACE = "show_people_space";
 
         /**
+         * Which types of conversations to show in People Space.
+         * Values are:
+         * 0: All conversations (default)
+         * 1: Priority conversations only
+         * @hide
+         */
+        public static final String PEOPLE_SPACE_CONVERSATION_TYPE =
+                "people_space_conversation_type";
+
+        /**
          * Whether to show new lockscreen & AOD UI.
          * Values are:
          * 0: Disabled (default)
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 79d6bb4..2c735fd 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -4045,7 +4045,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final class CellBroadcasts implements BaseColumns {
 
         /**
diff --git a/core/java/android/service/appprediction/AppPredictionService.java b/core/java/android/service/appprediction/AppPredictionService.java
index be20570..2d8aee5 100644
--- a/core/java/android/service/appprediction/AppPredictionService.java
+++ b/core/java/android/service/appprediction/AppPredictionService.java
@@ -22,7 +22,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.app.Service;
 import android.app.prediction.AppPredictionContext;
 import android.app.prediction.AppPredictionSessionId;
@@ -52,7 +51,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public abstract class AppPredictionService extends Service {
 
     private static final String TAG = "AppPredictionService";
diff --git a/core/java/android/service/autofill/AutofillFieldClassificationService.java b/core/java/android/service/autofill/AutofillFieldClassificationService.java
index 28842a7..9d9b881 100644
--- a/core/java/android/service/autofill/AutofillFieldClassificationService.java
+++ b/core/java/android/service/autofill/AutofillFieldClassificationService.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.app.Service;
 import android.content.Intent;
 import android.os.Bundle;
@@ -53,7 +52,6 @@
  * {@hide}
  */
 @SystemApi
-@TestApi
 public abstract class AutofillFieldClassificationService extends Service {
 
     private static final String TAG = "AutofillFieldClassificationService";
@@ -121,7 +119,6 @@
 
     /** @hide */
     @SystemApi
-    @TestApi
     public AutofillFieldClassificationService() {
     }
 
diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java
index 2d99c41..18d7992 100644
--- a/core/java/android/service/autofill/Dataset.java
+++ b/core/java/android/service/autofill/Dataset.java
@@ -21,7 +21,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.content.IntentSender;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -249,7 +248,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public Builder(@NonNull InlinePresentation inlinePresentation) {
             Preconditions.checkNotNull(inlinePresentation, "inlinePresentation must be non-null");
             mInlinePresentation = inlinePresentation;
@@ -604,7 +602,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public @NonNull Builder setFieldInlinePresentation(@NonNull AutofillId id,
                 @Nullable AutofillValue value, @Nullable Pattern filter,
                 @NonNull InlinePresentation inlinePresentation) {
diff --git a/core/java/android/service/autofill/InlineSuggestionRenderService.java b/core/java/android/service/autofill/InlineSuggestionRenderService.java
index 839caff..cdcd6591 100644
--- a/core/java/android/service/autofill/InlineSuggestionRenderService.java
+++ b/core/java/android/service/autofill/InlineSuggestionRenderService.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.app.Service;
 import android.content.Intent;
 import android.content.IntentSender;
@@ -51,7 +50,6 @@
  * {@hide}
  */
 @SystemApi
-@TestApi
 public abstract class InlineSuggestionRenderService extends Service {
 
     private static final String TAG = "InlineSuggestionRenderService";
diff --git a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
index 620c457..b34c2dc 100644
--- a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
+++ b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
@@ -25,7 +25,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.app.Service;
 import android.content.ComponentName;
 import android.content.Intent;
@@ -70,7 +69,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public abstract class AugmentedAutofillService extends Service {
 
     private static final String TAG = AugmentedAutofillService.class.getSimpleName();
diff --git a/core/java/android/service/autofill/augmented/FillCallback.java b/core/java/android/service/autofill/augmented/FillCallback.java
index fc3baf1..9fc7f34 100644
--- a/core/java/android/service/autofill/augmented/FillCallback.java
+++ b/core/java/android/service/autofill/augmented/FillCallback.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Bundle;
 import android.service.autofill.Dataset;
 import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
@@ -34,7 +33,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class FillCallback {
 
     private static final String TAG = FillCallback.class.getSimpleName();
diff --git a/core/java/android/service/autofill/augmented/FillController.java b/core/java/android/service/autofill/augmented/FillController.java
index 7d552d6..7cd674e 100644
--- a/core/java/android/service/autofill/augmented/FillController.java
+++ b/core/java/android/service/autofill/augmented/FillController.java
@@ -19,7 +19,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.RemoteException;
 import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
 import android.util.Log;
@@ -37,7 +36,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class FillController {
     private static final String TAG = FillController.class.getSimpleName();
 
diff --git a/core/java/android/service/autofill/augmented/FillResponse.java b/core/java/android/service/autofill/augmented/FillResponse.java
index f72eb78..53484cf 100644
--- a/core/java/android/service/autofill/augmented/FillResponse.java
+++ b/core/java/android/service/autofill/augmented/FillResponse.java
@@ -18,7 +18,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Bundle;
 import android.service.autofill.Dataset;
 
@@ -33,7 +32,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 @DataClass(
         genBuilder = true,
         genHiddenGetters = true)
diff --git a/core/java/android/service/autofill/augmented/FillWindow.java b/core/java/android/service/autofill/augmented/FillWindow.java
index 8e86646..d4f7e11 100644
--- a/core/java/android/service/autofill/augmented/FillWindow.java
+++ b/core/java/android/service/autofill/augmented/FillWindow.java
@@ -23,7 +23,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.graphics.Rect;
 import android.os.Handler;
 import android.os.Looper;
@@ -64,7 +63,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class FillWindow implements AutoCloseable {
     private static final String TAG = FillWindow.class.getSimpleName();
 
diff --git a/core/java/android/service/autofill/augmented/PresentationParams.java b/core/java/android/service/autofill/augmented/PresentationParams.java
index 8b3a001..fe78d22 100644
--- a/core/java/android/service/autofill/augmented/PresentationParams.java
+++ b/core/java/android/service/autofill/augmented/PresentationParams.java
@@ -18,7 +18,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.graphics.Rect;
 import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
 import android.view.View;
@@ -36,7 +35,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public abstract class PresentationParams {
 
     // /** @hide */
@@ -61,7 +59,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public abstract static class Area {
 
         /** @hide */
diff --git a/core/java/android/service/contentcapture/ActivityEvent.java b/core/java/android/service/contentcapture/ActivityEvent.java
index b741cff..1188a3f 100644
--- a/core/java/android/service/contentcapture/ActivityEvent.java
+++ b/core/java/android/service/contentcapture/ActivityEvent.java
@@ -19,7 +19,6 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.app.usage.UsageEvents.Event;
 import android.content.ComponentName;
 import android.os.Parcel;
@@ -34,7 +33,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class ActivityEvent implements Parcelable {
 
     /**
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index 84f6028..3c44cfd 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -26,7 +26,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.app.Service;
 import android.content.ComponentName;
 import android.content.ContentCaptureOptions;
@@ -74,7 +73,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public abstract class ContentCaptureService extends Service {
 
     private static final String TAG = ContentCaptureService.class.getSimpleName();
@@ -344,7 +342,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public void onDataShareRequest(@NonNull DataShareRequest request,
             @NonNull DataShareCallback callback) {
         if (sVerbose) Log.v(TAG, "onDataShareRequest()");
diff --git a/core/java/android/service/contentcapture/DataShareCallback.java b/core/java/android/service/contentcapture/DataShareCallback.java
index 5df8a4b..e3c7bb3 100644
--- a/core/java/android/service/contentcapture/DataShareCallback.java
+++ b/core/java/android/service/contentcapture/DataShareCallback.java
@@ -19,7 +19,6 @@
 import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 
 import java.util.concurrent.Executor;
 
@@ -33,7 +32,6 @@
  * @hide
  **/
 @SystemApi
-@TestApi
 public interface DataShareCallback {
 
     /** Accept the data share.
diff --git a/core/java/android/service/contentcapture/DataShareReadAdapter.java b/core/java/android/service/contentcapture/DataShareReadAdapter.java
index 8cd9eea..4526aba 100644
--- a/core/java/android/service/contentcapture/DataShareReadAdapter.java
+++ b/core/java/android/service/contentcapture/DataShareReadAdapter.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.ParcelFileDescriptor;
 import android.view.contentcapture.ContentCaptureManager.DataShareError;
 
@@ -29,7 +28,6 @@
  * @hide
  **/
 @SystemApi
-@TestApi
 public interface DataShareReadAdapter {
 
     /**
diff --git a/core/java/android/service/contentcapture/SnapshotData.java b/core/java/android/service/contentcapture/SnapshotData.java
index 5b3930a..bf469b4 100644
--- a/core/java/android/service/contentcapture/SnapshotData.java
+++ b/core/java/android/service/contentcapture/SnapshotData.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.app.assist.AssistContent;
 import android.app.assist.AssistStructure;
 import android.os.Bundle;
@@ -32,7 +31,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class SnapshotData implements Parcelable {
 
     private final @NonNull Bundle mAssistData;
diff --git a/core/java/android/service/notification/Adjustment.java b/core/java/android/service/notification/Adjustment.java
index 8464c6d..4b25c88 100644
--- a/core/java/android/service/notification/Adjustment.java
+++ b/core/java/android/service/notification/Adjustment.java
@@ -19,7 +19,6 @@
 import android.annotation.Nullable;
 import android.annotation.StringDef;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.app.Notification;
 import android.os.Bundle;
 import android.os.Parcel;
@@ -42,7 +41,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class Adjustment implements Parcelable {
     private final String mPackage;
     private final String mKey;
@@ -148,7 +146,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public Adjustment(String pkg, String key, Bundle signals, CharSequence explanation, int user) {
         mPackage = pkg;
         mKey = key;
@@ -232,7 +229,6 @@
 
     /** @hide */
     @SystemApi
-    @TestApi
     public int getUser() {
         return mUser;
     }
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index 975e75c..6320149 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -23,7 +23,6 @@
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.app.Notification;
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
@@ -66,7 +65,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public abstract class NotificationAssistantService extends NotificationListenerService {
     private static final String TAG = "NotificationAssistants";
 
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index e1b2dfb..25f140f 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -22,7 +22,6 @@
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.app.ActivityManager;
 import android.app.INotificationManager;
 import android.app.Notification;
@@ -452,7 +451,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public void onNotificationRemoved(@NonNull StatusBarNotification sbn,
             @NonNull RankingMap rankingMap, @NonNull NotificationStats stats, int reason) {
diff --git a/core/java/android/service/notification/NotificationStats.java b/core/java/android/service/notification/NotificationStats.java
index 2cd8b8b..206e4fa 100644
--- a/core/java/android/service/notification/NotificationStats.java
+++ b/core/java/android/service/notification/NotificationStats.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.app.RemoteInput;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -31,7 +30,6 @@
  * Information about how the user has interacted with a given notification.
  * @hide
  */
-@TestApi
 @SystemApi
 public final class NotificationStats implements Parcelable {
 
diff --git a/core/java/android/service/notification/SnoozeCriterion.java b/core/java/android/service/notification/SnoozeCriterion.java
index eb624c9..d3da07a 100644
--- a/core/java/android/service/notification/SnoozeCriterion.java
+++ b/core/java/android/service/notification/SnoozeCriterion.java
@@ -17,7 +17,6 @@
 
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -27,7 +26,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class SnoozeCriterion implements Parcelable {
     private final String mId;
     private final CharSequence mExplanation;
diff --git a/core/java/android/service/textclassifier/TextClassifierService.java b/core/java/android/service/textclassifier/TextClassifierService.java
index 93faa58..1fb18fa 100644
--- a/core/java/android/service/textclassifier/TextClassifierService.java
+++ b/core/java/android/service/textclassifier/TextClassifierService.java
@@ -22,7 +22,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.app.Service;
 import android.content.ComponentName;
 import android.content.Context;
@@ -88,7 +87,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public abstract class TextClassifierService extends Service {
 
     private static final String LOG_TAG = "TextClassifierService";
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 4d1337b..6a70a85 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -877,9 +877,10 @@
                         InputChannel inputChannel = new InputChannel();
 
                         if (mSession.addToDisplay(mWindow, mLayout, View.VISIBLE,
-                                mDisplay.getDisplayId(), mWinFrames.frame, mWinFrames.contentInsets,
-                                mWinFrames.stableInsets, mWinFrames.displayCutout, inputChannel,
-                                mInsetsState, mTempControls) < 0) {
+                                mDisplay.getDisplayId(), mInsetsState, mWinFrames.frame,
+                                mWinFrames.contentInsets, mWinFrames.stableInsets,
+                                mWinFrames.displayCutout, inputChannel, mInsetsState,
+                                mTempControls) < 0) {
                             Log.w(TAG, "Failed to add window while updating wallpaper surface.");
                             return;
                         }
diff --git a/core/java/android/service/watchdog/ExplicitHealthCheckService.java b/core/java/android/service/watchdog/ExplicitHealthCheckService.java
index b1647fe..49e00d6 100644
--- a/core/java/android/service/watchdog/ExplicitHealthCheckService.java
+++ b/core/java/android/service/watchdog/ExplicitHealthCheckService.java
@@ -66,7 +66,6 @@
  * </pre>
  * @hide
  */
-@TestApi
 @SystemApi
 public abstract class ExplicitHealthCheckService extends Service {
 
@@ -195,7 +194,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final class PackageConfig implements Parcelable {
         private static final long DEFAULT_HEALTH_CHECK_TIMEOUT_MILLIS = TimeUnit.HOURS.toMillis(1);
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index 70c11f2..6a5d5c6 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Binder;
@@ -437,7 +436,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
     public static final int LISTEN_OUTGOING_EMERGENCY_CALL                  = 0x10000000;
 
@@ -450,7 +448,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
     public static final int LISTEN_OUTGOING_EMERGENCY_SMS                   = 0x20000000;
 
@@ -969,7 +966,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @Deprecated
     public void onOutgoingEmergencyCall(@NonNull EmergencyNumber placedEmergencyNumber) {
         // default implementation empty
@@ -994,7 +990,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public void onOutgoingEmergencyCall(@NonNull EmergencyNumber placedEmergencyNumber,
             int subscriptionId) {
         // Default implementation for backwards compatibility
@@ -1011,7 +1006,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @Deprecated
     public void onOutgoingEmergencySms(@NonNull EmergencyNumber sentEmergencyNumber) {
         // default implementation empty
@@ -1033,7 +1027,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public void onOutgoingEmergencySms(@NonNull EmergencyNumber sentEmergencyNumber,
             int subscriptionId) {
         // Default implementation for backwards compatibility
diff --git a/core/java/android/uwb/AngleMeasurement.java b/core/java/android/uwb/AngleMeasurement.java
new file mode 100644
index 0000000..7ef145c
--- /dev/null
+++ b/core/java/android/uwb/AngleMeasurement.java
@@ -0,0 +1,65 @@
+/*
+ * 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.uwb;
+
+import android.annotation.FloatRange;
+
+/**
+ * Angle measurement
+ *
+ * <p>The actual angle is interpreted as:
+ *   {@link #getRadians()} +/- {@link #getErrorRadians()} ()} at {@link #getConfidenceLevel()}
+ *
+ * @hide
+ */
+public final class AngleMeasurement {
+    /**
+     * Angle measurement in radians
+    *
+     * @return angle in radians
+     */
+    @FloatRange(from = -Math.PI, to = +Math.PI)
+    public double getRadians() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Error of angle measurement in radians
+     *
+     * <p>Must be a positive value
+     *
+     * @return angle measurement error in radians
+     */
+    @FloatRange(from = 0.0, to = +Math.PI)
+    public double getErrorRadians() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Angle measurement confidence level expressed as a value between
+     * 0.0 to 1.0.
+     *
+     * <p>A value of 0.0 indicates there is no confidence in the measurement. A value of 1.0
+     * indicates there is maximum confidence in the measurement.
+     *
+     * @return the confidence level of the angle measurement
+     */
+    @FloatRange(from = 0.0, to = 1.0)
+    public double getConfidenceLevel() {
+        throw new UnsupportedOperationException();
+    }
+}
diff --git a/core/java/android/uwb/AngleOfArrivalMeasurement.java b/core/java/android/uwb/AngleOfArrivalMeasurement.java
new file mode 100644
index 0000000..030d529
--- /dev/null
+++ b/core/java/android/uwb/AngleOfArrivalMeasurement.java
@@ -0,0 +1,63 @@
+/*
+ * 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.uwb;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+/**
+ * Represents an angle of arrival measurement between two devices using Ultra Wideband
+ *
+ * @hide
+ */
+public final class AngleOfArrivalMeasurement {
+    /**
+     * Azimuth angle measurement
+     * <p>Azimuth {@link AngleMeasurement} of remote device in horizontal coordinate system, this is
+     * the angle clockwise from the meridian when viewing above the north pole.
+     *
+     * <p>See: https://en.wikipedia.org/wiki/Horizontal_coordinate_system
+     *
+     * <p>On an Android device, azimuth north is defined as the angle perpendicular away from the
+     * back of the device when holding it in portrait mode upright.
+     *
+     * <p>Azimuth angle must be supported when Angle of Arrival is supported
+     *
+     * @return the azimuth {@link AngleMeasurement}
+     */
+    @NonNull
+    public AngleMeasurement getAzimuth() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Altitude angle measurement
+     * <p>Altitude {@link AngleMeasurement} of remote device in horizontal coordinate system, this
+     * is the angle above the equator when the north pole is up.
+     *
+     * <p>See: https://en.wikipedia.org/wiki/Horizontal_coordinate_system
+     *
+     * <p>On an Android device, altitude is defined as the angle vertical from ground when holding
+     * the device in portrait mode upright.
+     *
+     * @return altitude {@link AngleMeasurement} or null when this is not available
+     */
+    @Nullable
+    public AngleMeasurement getAltitude() {
+        throw new UnsupportedOperationException();
+    }
+}
diff --git a/core/java/android/uwb/DistanceMeasurement.java b/core/java/android/uwb/DistanceMeasurement.java
new file mode 100644
index 0000000..f4e6d3e
--- /dev/null
+++ b/core/java/android/uwb/DistanceMeasurement.java
@@ -0,0 +1,61 @@
+/*
+ * 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.uwb;
+
+import android.annotation.FloatRange;
+
+/**
+ * A data point for the distance measurement
+ *
+ * <p>The actual distance is interpreted as:
+ *   {@link #getMeters()} +/- {@link #getErrorMeters()} at {@link #getConfidenceLevel()}
+ *
+ * @hide
+ */
+public final class DistanceMeasurement {
+    /**
+     * Distance measurement in meters
+     *
+     * @return distance in meters
+     */
+    public double getMeters() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Error of distance measurement in meters
+     * <p>Must be positive
+     *
+     * @return error of distance measurement in meters
+     */
+    public double getErrorMeters() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Distance measurement confidence level expressed as a value between 0.0 to 1.0.
+     *
+     * <p>A value of 0.0 indicates no confidence in the measurement. A value of 1.0 represents
+     * maximum confidence in the measurement
+     *
+     * @return confidence level
+     */
+    @FloatRange(from = 0.0, to = 1.0)
+    public double getConfidenceLevel() {
+        throw new UnsupportedOperationException();
+    }
+}
diff --git a/core/java/android/uwb/RangingMeasurement.java b/core/java/android/uwb/RangingMeasurement.java
new file mode 100644
index 0000000..a249802
--- /dev/null
+++ b/core/java/android/uwb/RangingMeasurement.java
@@ -0,0 +1,113 @@
+/*
+ * 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.uwb;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.os.SystemClock;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Representation of a ranging measurement between the local device and a remote device
+ *
+ * @hide
+ */
+public final class RangingMeasurement {
+    /**
+     * Get the remote device's {@link UwbAddress}
+     *
+     * @return the remote device's {@link UwbAddress}
+     */
+    @NonNull
+    public UwbAddress getRemoteDeviceAddress() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(value = {
+            RANGING_STATUS_SUCCESS,
+            RANGING_STATUS_FAILURE_OUT_OF_RANGE,
+            RANGING_STATUS_FAILURE_UNKNOWN_ERROR})
+    public @interface Status {}
+
+    /**
+     * Ranging attempt was successful for this device
+     */
+    public static final int RANGING_STATUS_SUCCESS = 0;
+
+    /**
+     * Ranging failed for this device because it is out of range
+     */
+    public static final int RANGING_STATUS_FAILURE_OUT_OF_RANGE = 1;
+
+    /**
+     * Ranging failed for this device because of unknown error
+     */
+    public static final int RANGING_STATUS_FAILURE_UNKNOWN_ERROR = -1;
+
+    /**
+     * Get the status of this ranging measurement
+     *
+     * <p>Possible values are
+     * {@link #RANGING_STATUS_SUCCESS},
+     * {@link #RANGING_STATUS_FAILURE_OUT_OF_RANGE},
+     * {@link #RANGING_STATUS_FAILURE_UNKNOWN_ERROR}.
+     *
+     * @return the status of the ranging measurement
+     */
+    @Status
+    public int getStatus() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Timestamp of this ranging measurement in time since boot nanos in the same namespace as
+     * {@link SystemClock#elapsedRealtimeNanos()}
+     *
+     * @return timestamp of ranging measurement in nanoseconds
+     */
+    @SuppressLint("MethodNameUnits")
+    public long getElapsedRealtimeNanos() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Get the distance measurement
+     *
+     * @return a {@link DistanceMeasurement} or null if {@link #getStatus()} !=
+     *         {@link #RANGING_STATUS_SUCCESS}
+     */
+    @Nullable
+    public DistanceMeasurement getDistance() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Get the angle of arrival measurement
+     *
+     * @return an {@link AngleOfArrivalMeasurement} or null if {@link #getStatus()} !=
+     *         {@link #RANGING_STATUS_SUCCESS}
+     */
+    @Nullable
+    public AngleOfArrivalMeasurement getAngleOfArrival() {
+        throw new UnsupportedOperationException();
+    }
+}
diff --git a/core/java/android/uwb/RangingParams.java b/core/java/android/uwb/RangingParams.java
new file mode 100644
index 0000000..9727696
--- /dev/null
+++ b/core/java/android/uwb/RangingParams.java
@@ -0,0 +1,175 @@
+/*
+ * 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.uwb;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.PersistableBundle;
+import android.util.Duration;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+
+/**
+ * An object used when requesting to open a new {@link RangingSession}.
+ * <p>Use {@link RangingParams.Builder} to create an instance of this class.
+ *
+ *  @hide
+ */
+public final class RangingParams {
+    /**
+     * Standard builder interface as the class is not modifiable
+     */
+    public static class Builder {
+        // TODO implement
+    }
+
+    /**
+     * Get if the local device is the initiator
+     *
+     * @return true if the device is the initiator
+     */
+    public boolean isInitiator() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Get if the local device is the controller
+     *
+     * @return true if the device is the controller
+     */
+    public boolean isController() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * The desired amount of time between two adjacent samples of measurement
+     *
+     * @return the ranging sample period
+     */
+    @NonNull
+    public Duration getSamplingPeriod() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Local device's {@link UwbAddress}
+     *
+     * <p>Simultaneous {@link RangingSession}s on the same device can have different results for
+     * {@link #getLocalDeviceAddress()}.
+     *
+     * @return the local device's {@link UwbAddress}
+     */
+    @NonNull
+    public UwbAddress getLocalDeviceAddress() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Gets a list of all remote device's {@link UwbAddress}
+     *
+     * @return a {@link List} of {@link UwbAddress} representing the remote devices
+     */
+    @NonNull
+    public List<UwbAddress> getRemoteDeviceAddresses() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Channel number used between this device pair as defined by 802.15.4z
+     *
+     * Range: -1, 0-15
+     *
+     * @return the channel to use
+     */
+    public int getChannelNumber() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Preamble index used between this device pair as defined by 802.15.4z
+     *
+     * Range: 0, 0-32
+     *
+     * @return the preamble index to use for transmitting
+     */
+    public int getTxPreambleIndex() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * preamble index used between this device pair as defined by 802.15.4z
+     *
+     * Range: 0, 13-16, 21-32
+     *
+     * @return the preamble index to use for receiving
+     */
+    public int getRxPreambleIndex() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(value = {
+            STS_PHY_PACKET_TYPE_SP0,
+            STS_PHY_PACKET_TYPE_SP1,
+            STS_PHY_PACKET_TYPE_SP2,
+            STS_PHY_PACKET_TYPE_SP3})
+    public @interface StsPhyPacketType {}
+
+    /**
+     * PHY packet type SP0 when STS is used as defined by 802.15.4z
+     */
+    public static final int STS_PHY_PACKET_TYPE_SP0 = 0;
+
+    /**
+     * PHY packet type SP1 when STS is used as defined by 802.15.4z
+     */
+    public static final int STS_PHY_PACKET_TYPE_SP1 = 1;
+
+    /**
+     * PHY packet type SP2 when STS is used as defined by 802.15.4z
+     */
+    public static final int STS_PHY_PACKET_TYPE_SP2 = 2;
+
+    /**
+     * PHY packet type SP3 when STS is used as defined by 802.15.4z
+     */
+    public static final int STS_PHY_PACKET_TYPE_SP3 = 3;
+
+    /**
+     * Get the type of PHY packet when STS is used as defined by 802.15.4z
+     *
+     * @return the {@link StsPhyPacketType} to use
+     */
+    @StsPhyPacketType
+    public int getStsPhyPacketType() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Parameters for a specific UWB protocol constructed using a support library.
+     *
+     * <p>Android reserves the '^android.*' namespace
+     *
+     * @return a {@link PersistableBundle} of protocol specific parameters
+     */
+    public @Nullable PersistableBundle getSpecificationParameters() {
+        throw new UnsupportedOperationException();
+    }
+}
diff --git a/core/java/android/uwb/RangingReport.java b/core/java/android/uwb/RangingReport.java
new file mode 100644
index 0000000..037bdfd
--- /dev/null
+++ b/core/java/android/uwb/RangingReport.java
@@ -0,0 +1,44 @@
+/*
+ * 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.uwb;
+
+import android.annotation.NonNull;
+
+import java.util.List;
+
+/**
+ * This class contains the UWB ranging data
+ *
+ * @hide
+ */
+public final class RangingReport {
+    /**
+     * Get a {@link List} of {@link RangingMeasurement} objects in the last measurement interval
+     * <p>The underlying UWB adapter may choose to do multiple measurements in each ranging
+     * interval.
+     *
+     * <p>The entries in the {@link List} are ordered in ascending order based on
+     * {@link RangingMeasurement#getElapsedRealtimeNanos()}
+     *
+     * @return a {@link List} of {@link RangingMeasurement} objects
+     */
+    @NonNull
+    public List<RangingMeasurement> getMeasurements() {
+        throw new UnsupportedOperationException();
+    }
+}
+
diff --git a/core/java/android/view/IScrollCaptureController.aidl b/core/java/android/view/IScrollCaptureCallbacks.aidl
similarity index 67%
rename from core/java/android/view/IScrollCaptureController.aidl
rename to core/java/android/view/IScrollCaptureCallbacks.aidl
index 8474a00..d97e3c6 100644
--- a/core/java/android/view/IScrollCaptureController.aidl
+++ b/core/java/android/view/IScrollCaptureCallbacks.aidl
@@ -20,32 +20,31 @@
 import android.graphics.Rect;
 import android.view.Surface;
 
-import android.view.IScrollCaptureClient;
+import android.view.IScrollCaptureConnection;
 
 /**
- * Interface to a controller passed to the {@link IScrollCaptureClient} which provides the client an
- * asynchronous callback channel for responses.
+ * Asynchronous callback channel for responses to scroll capture requests.
  *
  * {@hide}
  */
-interface IScrollCaptureController {
+interface IScrollCaptureCallbacks {
     /**
-     * Scroll capture is available, and a client connect has been returned.
+     * Scroll capture is available, and a connection has been provided.
      *
-     * @param client interface to a ScrollCaptureCallback in the window process
+     * @param connection a connection to a window process and scrollable content
      * @param scrollAreaInWindow the location of scrolling in global (window) coordinate space
      */
-    oneway void onClientConnected(in IScrollCaptureClient client, in Rect scrollBounds,
+    oneway void onConnected(in IScrollCaptureConnection connection, in Rect scrollBounds,
             in Point positionInWindow);
 
     /**
-     * Nothing in the window can be scrolled, scroll capture not offered.
+     * The window does not support scroll capture.
      */
-    oneway void onClientUnavailable();
+    oneway void onUnavailable();
 
     /**
-     * Notifies the system that the client has confirmed the request and is ready to begin providing
-     * image requests.
+     * Called when the remote end has confirmed the request and is ready to begin providing image
+     * requests.
      */
     oneway void onCaptureStarted();
 
diff --git a/core/java/android/view/IScrollCaptureClient.aidl b/core/java/android/view/IScrollCaptureConnection.aidl
similarity index 97%
rename from core/java/android/view/IScrollCaptureClient.aidl
rename to core/java/android/view/IScrollCaptureConnection.aidl
index 5f135a37..63a4f48 100644
--- a/core/java/android/view/IScrollCaptureClient.aidl
+++ b/core/java/android/view/IScrollCaptureConnection.aidl
@@ -26,7 +26,7 @@
    *
    * {@hide}
    */
-interface IScrollCaptureClient {
+interface IScrollCaptureConnection {
 
     /**
      * Informs the client that it has been selected for scroll capture and should prepare to
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 193e674..e685b30 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -26,7 +26,7 @@
 import android.view.DragEvent;
 import android.view.InsetsSourceControl;
 import android.view.InsetsState;
-import android.view.IScrollCaptureController;
+import android.view.IScrollCaptureCallbacks;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.window.ClientWindowFrames;
@@ -137,7 +137,7 @@
     /**
      * Called when Scroll Capture support is requested for a window.
      *
-     * @param controller the controller to receive responses
+     * @param callbacks to receive responses
      */
-    void requestScrollCapture(in IScrollCaptureController controller);
+    void requestScrollCapture(in IScrollCaptureCallbacks callbacks);
 }
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index c460f74..3c5d336 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -42,7 +42,7 @@
 import android.view.IDisplayWindowRotationController;
 import android.view.IOnKeyguardExitResult;
 import android.view.IPinnedStackListener;
-import android.view.IScrollCaptureController;
+import android.view.IScrollCaptureCallbacks;
 import android.view.RemoteAnimationAdapter;
 import android.view.IRotationWatcher;
 import android.view.ISystemGestureExclusionListener;
@@ -751,12 +751,10 @@
      * @param behindClient token for a window, used to filter the search to windows behind it, or
      *                     {@code null} to accept a window at any zOrder
      * @param taskId specifies the id of a task the result must belong to, or -1 to ignore task ids
-     * @param controller the controller to receive results, a call to either
-     *      {@link IScrollCaptureController#onClientConnected} or
-     *      {@link IScrollCaptureController#onClientUnavailable}.
+     * @param callbacks the object to receive replies
      */
     void requestScrollCapture(int displayId, IBinder behindClient, int taskId,
-            IScrollCaptureController controller);
+            IScrollCaptureCallbacks callbacks);
 
     /**
      * Holds the WM lock for the specified amount of milliseconds.
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 910fd90..7f36169 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -45,12 +45,13 @@
  */
 interface IWindowSession {
     int addToDisplay(IWindow window, in WindowManager.LayoutParams attrs,
-            in int viewVisibility, in int layerStackId, out Rect outFrame,
-            out Rect outContentInsets, out Rect outStableInsets,
+            in int viewVisibility, in int layerStackId, in InsetsState requestedVisibility,
+            out Rect outFrame, out Rect outContentInsets, out Rect outStableInsets,
             out DisplayCutout.ParcelableWrapper displayCutout, out InputChannel outInputChannel,
             out InsetsState insetsState, out InsetsSourceControl[] activeControls);
     int addToDisplayAsUser(IWindow window, in WindowManager.LayoutParams attrs,
                 in int viewVisibility, in int layerStackId, in int userId,
+                in InsetsState requestedVisibility,
                 out Rect outFrame, out Rect outContentInsets, out Rect outStableInsets,
                 out DisplayCutout.ParcelableWrapper displayCutout, out InputChannel outInputChannel,
                 out InsetsState insetsState, out InsetsSourceControl[] activeControls);
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index 71899fa..878583b 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -212,21 +212,21 @@
     /**
      * @return Whether the finish callback of this animation should be invoked.
      */
-    public boolean applyChangeInsets(InsetsState state) {
+    public boolean applyChangeInsets(@Nullable InsetsState outState) {
         if (mCancelled) {
             if (DEBUG) Log.d(TAG, "applyChangeInsets canceled");
             return false;
         }
         final Insets offset = Insets.subtract(mShownInsets, mPendingInsets);
         ArrayList<SurfaceParams> params = new ArrayList<>();
-        updateLeashesForSide(ISIDE_LEFT, offset.left, mShownInsets.left, mPendingInsets.left,
-                params, state, mPendingAlpha);
-        updateLeashesForSide(ISIDE_TOP, offset.top, mShownInsets.top, mPendingInsets.top, params,
-                state, mPendingAlpha);
-        updateLeashesForSide(ISIDE_RIGHT, offset.right, mShownInsets.right, mPendingInsets.right,
-                params, state, mPendingAlpha);
-        updateLeashesForSide(ISIDE_BOTTOM, offset.bottom, mShownInsets.bottom,
-                mPendingInsets.bottom, params, state, mPendingAlpha);
+        updateLeashesForSide(ISIDE_LEFT, offset.left, mPendingInsets.left, params, outState,
+                mPendingAlpha);
+        updateLeashesForSide(ISIDE_TOP, offset.top, mPendingInsets.top, params, outState,
+                mPendingAlpha);
+        updateLeashesForSide(ISIDE_RIGHT, offset.right, mPendingInsets.right, params, outState,
+                mPendingAlpha);
+        updateLeashesForSide(ISIDE_BOTTOM, offset.bottom, mPendingInsets.bottom, params, outState,
+                mPendingAlpha);
 
         mController.applySurfaceParams(params.toArray(new SurfaceParams[params.size()]));
         mCurrentInsets = mPendingInsets;
@@ -357,8 +357,8 @@
         return alpha >= 1 ? 1 : (alpha <= 0 ? 0 : alpha);
     }
 
-    private void updateLeashesForSide(@InternalInsetsSide int side, int offset, int maxInset,
-            int inset, ArrayList<SurfaceParams> surfaceParams, InsetsState state, Float alpha) {
+    private void updateLeashesForSide(@InternalInsetsSide int side, int offset, int inset,
+            ArrayList<SurfaceParams> surfaceParams, @Nullable InsetsState outState, float alpha) {
         ArraySet<InsetsSourceControl> items = mSideSourceMap.get(side);
         if (items == null) {
             return;
@@ -377,8 +377,10 @@
                     ? (mAnimationType == ANIMATION_TYPE_SHOW ? true : !mFinished)
                     : inset != 0;
 
-            state.getSource(source.getType()).setVisible(visible);
-            state.getSource(source.getType()).setFrame(mTmpFrame);
+            if (outState != null) {
+                outState.getSource(source.getType()).setVisible(visible);
+                outState.getSource(source.getType()).setFrame(mTmpFrame);
+            }
 
             // If the system is controlling the insets source, the leash can be null.
             if (leash != null) {
diff --git a/core/java/android/view/InsetsAnimationThreadControlRunner.java b/core/java/android/view/InsetsAnimationThreadControlRunner.java
index cc3cd27..1307052 100644
--- a/core/java/android/view/InsetsAnimationThreadControlRunner.java
+++ b/core/java/android/view/InsetsAnimationThreadControlRunner.java
@@ -44,7 +44,6 @@
     private final InsetsAnimationControlImpl mControl;
     private final InsetsAnimationControlCallbacks mOuterCallbacks;
     private final Handler mMainThreadHandler;
-    private final InsetsState mState = new InsetsState();
     private final InsetsAnimationControlCallbacks mCallbacks =
             new InsetsAnimationControlCallbacks() {
 
@@ -60,7 +59,7 @@
 
         @Override
         public void scheduleApplyChangeInsets(InsetsAnimationControlRunner runner) {
-            mControl.applyChangeInsets(mState);
+            mControl.applyChangeInsets(null /* outState */);
         }
 
         @Override
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 652781a..5037d9e 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -484,7 +484,9 @@
     /** The state dispatched from server */
     private final InsetsState mLastDispatchedState = new InsetsState();
 
-    /** The state sent to server */
+    // TODO: Use other class to represent the requested visibility of each type, because the
+    //       display frame and the frame in each source are not used.
+    /** The requested visibilities sent to server */
     private final InsetsState mRequestedState = new InsetsState();
 
     private final Rect mFrame = new Rect();
@@ -499,6 +501,7 @@
     private final List<WindowInsetsAnimation> mUnmodifiableTmpRunningAnims =
             Collections.unmodifiableList(mTmpRunningAnims);
     private final ArrayList<InsetsAnimationControlImpl> mTmpFinishedControls = new ArrayList<>();
+    private final ArraySet<InsetsSourceConsumer> mRequestedVisibilityChanged = new ArraySet<>();
     private WindowInsets mLastInsets;
 
     private boolean mAnimCallbackScheduled;
@@ -640,11 +643,6 @@
             if (DEBUG) Log.d(TAG, "onStateChanged, notifyInsetsChanged");
             mHost.notifyInsetsChanged();
         }
-        if (!mState.equals(mLastDispatchedState, true /* excludingCaptionInsets */,
-                true /* excludeInvisibleIme */)) {
-            if (DEBUG) Log.d(TAG, "onStateChanged, send state to WM: " + mState);
-            updateRequestedState();
-        }
         return true;
     }
 
@@ -808,9 +806,9 @@
         if (hideTypes[0] != 0) {
             applyAnimation(hideTypes[0], false /* show */, false /* fromIme */);
         }
-        if (requestedStateStale) {
-            updateRequestedState();
-        }
+
+        // InsetsSourceConsumer#setControl might change the requested visibility.
+        updateRequestedVisibility();
     }
 
     @Override
@@ -945,6 +943,7 @@
         if (types == 0) {
             // nothing to animate.
             listener.onCancelled(null);
+            updateRequestedVisibility();
             if (DEBUG) Log.d(TAG, "no types to animate in controlAnimationUnchecked");
             return;
         }
@@ -980,12 +979,14 @@
                     }
                 });
             }
+            updateRequestedVisibility();
             return;
         }
 
         if (typesReady == 0) {
             if (DEBUG) Log.d(TAG, "No types ready. onCancelled()");
             listener.onCancelled(null);
+            updateRequestedVisibility();
             return;
         }
 
@@ -1010,6 +1011,7 @@
         } else {
             hideDirectly(types, false /* animationFinished */, animationType);
         }
+        updateRequestedVisibility();
     }
 
     /**
@@ -1177,7 +1179,6 @@
         }
         if (stateChanged) {
             mHost.notifyInsetsChanged();
-            updateRequestedState();
         }
     }
 
@@ -1202,7 +1203,6 @@
     @VisibleForTesting
     public void notifyVisibilityChanged() {
         mHost.notifyInsetsChanged();
-        updateRequestedState();
     }
 
     /**
@@ -1251,38 +1251,39 @@
         return ANIMATION_TYPE_NONE;
     }
 
+    @VisibleForTesting
+    public void onRequestedVisibilityChanged(InsetsSourceConsumer consumer) {
+        mRequestedVisibilityChanged.add(consumer);
+    }
+
     /**
-     * Sends the local visibility state back to window manager if it is changed.
+     * Sends the requested visibilities to window manager if any of them is changed.
      */
-    private void updateRequestedState() {
+    private void updateRequestedVisibility() {
         boolean changed = false;
-        for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
-            final InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
+        for (int i = mRequestedVisibilityChanged.size() - 1; i >= 0; i--) {
+            final InsetsSourceConsumer consumer = mRequestedVisibilityChanged.valueAt(i);
             final @InternalInsetsType int type = consumer.getType();
             if (type == ITYPE_CAPTION_BAR) {
                 continue;
             }
-            if (consumer.getControl() != null) {
-                final InsetsSource localSource = mState.getSource(type);
-                if (!localSource.equals(mRequestedState.peekSource(type))) {
-                    // Our requested state is stale. Update it here and send it to window manager.
-                    mRequestedState.addSource(new InsetsSource(localSource));
-                    changed = true;
-                }
-                if (!localSource.equals(mLastDispatchedState.peekSource(type))) {
-                    // The server state is not what we expected. This can happen while we don't have
-                    // the control. Since we have the control now, we need to send our request again
-                    // to modify the server state.
-                    changed = true;
-                }
+            final boolean requestedVisible = consumer.isRequestedVisible();
+            if (requestedVisible != mRequestedState.getSourceOrDefaultVisibility(type)) {
+                mRequestedState.getSource(type).setVisible(requestedVisible);
+                changed = true;
             }
         }
+        mRequestedVisibilityChanged.clear();
         if (!changed) {
             return;
         }
         mHost.onInsetsModified(mRequestedState);
     }
 
+    InsetsState getRequestedVisibility() {
+        return mRequestedState;
+    }
+
     @VisibleForTesting
     public void applyAnimation(@InsetsType final int types, boolean show, boolean fromIme) {
         if (types == 0) {
@@ -1316,6 +1317,7 @@
         for (int i = internalTypes.size() - 1; i >= 0; i--) {
             getSourceConsumer(internalTypes.valueAt(i)).hide(animationFinished, animationType);
         }
+        updateRequestedVisibility();
     }
 
     private void showDirectly(@InsetsType int types) {
@@ -1326,6 +1328,7 @@
         for (int i = internalTypes.size() - 1; i >= 0; i--) {
             getSourceConsumer(internalTypes.valueAt(i)).show(false /* fromIme */);
         }
+        updateRequestedVisibility();
     }
 
     /**
diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java
index d7ceaf7..e4a24eb 100644
--- a/core/java/android/view/InsetsSourceConsumer.java
+++ b/core/java/android/view/InsetsSourceConsumer.java
@@ -350,6 +350,7 @@
         if (mRequestedVisible != requestedVisible) {
             mRequestedVisible = requestedVisible;
             mIsAnimationPending = false;
+            mController.onRequestedVisibilityChanged(this);
             if (DEBUG) Log.d(TAG, "setRequestedVisible: " + requestedVisible);
         }
         if (applyLocalVisibilityOverride()) {
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 38441d1..b9f1f6a 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -63,8 +63,6 @@
  */
 public class InsetsState implements Parcelable {
 
-    public static final InsetsState EMPTY = new InsetsState();
-
     /**
      * Internal representation of inset source types. This is different from the public API in
      * {@link WindowInsets.Type} as one type from the public API might indicate multiple windows
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index 0c3d61f..8b0de08 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -28,7 +28,6 @@
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.widget.ImageView;
-import android.widget.LinearLayout;
 import android.widget.RemoteViews;
 
 import com.android.internal.R;
@@ -54,7 +53,6 @@
     private OnClickListener mExpandClickListener;
     private OnClickListener mFeedbackListener;
     private HeaderTouchListener mTouchListener = new HeaderTouchListener();
-    private LinearLayout mTransferChip;
     private NotificationExpandButton mExpandButton;
     private CachingIconView mIcon;
     private View mProfileBadge;
@@ -111,7 +109,6 @@
         mAppName = findViewById(com.android.internal.R.id.app_name_text);
         mHeaderText = findViewById(com.android.internal.R.id.header_text);
         mSecondaryHeaderText = findViewById(com.android.internal.R.id.header_text_secondary);
-        mTransferChip = findViewById(com.android.internal.R.id.media_seamless);
         mExpandButton = findViewById(com.android.internal.R.id.expand_button);
         mIcon = findViewById(com.android.internal.R.id.icon);
         mProfileBadge = findViewById(com.android.internal.R.id.profile_badge);
@@ -143,8 +140,7 @@
             // Icons that should go at the end
             if ((child == mExpandButton && mShowExpandButtonAtEnd)
                     || child == mProfileBadge
-                    || child == mFeedbackIcon
-                    || child == mTransferChip) {
+                    || child == mFeedbackIcon) {
                 iconWidth += lp.leftMargin + lp.rightMargin + child.getMeasuredWidth();
             } else {
                 totalWidth += lp.leftMargin + lp.rightMargin + child.getMeasuredWidth();
@@ -208,8 +204,7 @@
             // Icons that should go at the end
             if ((child == mExpandButton && mShowExpandButtonAtEnd)
                     || child == mProfileBadge
-                    || child == mFeedbackIcon
-                    || child == mTransferChip) {
+                    || child == mFeedbackIcon) {
                 if (end == getMeasuredWidth()) {
                     layoutRight = end - mContentEndMargin;
                 } else {
diff --git a/core/java/android/view/ScrollCaptureCallback.java b/core/java/android/view/ScrollCaptureCallback.java
index e1a4e74..d3aad2c 100644
--- a/core/java/android/view/ScrollCaptureCallback.java
+++ b/core/java/android/view/ScrollCaptureCallback.java
@@ -29,8 +29,8 @@
  * callbacks registered within the window.
  * <p>
  * A callback is assigned to a View using {@link View#setScrollCaptureCallback}, or to the window as
- * {@link Window#addScrollCaptureCallback}. The point where the callback is registered defines the
- * frame of reference for the bounds measurements used.
+ * {@link Window#registerScrollCaptureCallback}. The point where the callback is registered defines
+ * the frame of reference for the bounds measurements used.
  * <p>
  * <b>Terminology</b>
  * <dl>
@@ -39,9 +39,9 @@
  * is assigned  directly to a window.</dd>
  *
  * <dt>Scroll Bounds</dt>
- * <dd>A rectangle which describes an area within the containing view where scrolling content may
- * be positioned. This may be the Containing View bounds itself, or any rectangle within.
- * Requested by {@link #onScrollCaptureSearch}.</dd>
+ * <dd>A rectangle which describes an area within the containing view where scrolling content
+ * appears. This may be the entire view or any rectangle within. This defines a frame of reference
+ * for requests as well as the width and maximum height of a single request.</dd>
  *
  * <dt>Scroll Delta</dt>
  * <dd>The distance the scroll position has moved since capture started. Implementations are
@@ -57,7 +57,7 @@
  *
  * @see View#setScrollCaptureHint(int)
  * @see View#setScrollCaptureCallback(ScrollCaptureCallback)
- * @see Window#addScrollCaptureCallback(ScrollCaptureCallback)
+ * @see Window#registerScrollCaptureCallback(ScrollCaptureCallback)
  *
  * @hide
  */
diff --git a/core/java/android/view/ScrollCaptureClient.java b/core/java/android/view/ScrollCaptureConnection.java
similarity index 87%
rename from core/java/android/view/ScrollCaptureClient.java
rename to core/java/android/view/ScrollCaptureConnection.java
index f163124..0e6cdd1d 100644
--- a/core/java/android/view/ScrollCaptureClient.java
+++ b/core/java/android/view/ScrollCaptureConnection.java
@@ -19,7 +19,6 @@
 import static java.util.Objects.requireNonNull;
 
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.annotation.UiThread;
 import android.annotation.WorkerThread;
 import android.graphics.Point;
@@ -33,15 +32,15 @@
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
- * A client of the system providing Scroll Capture capability on behalf of a Window.
+ * Mediator between a selected scroll capture target view and a remote process.
  * <p>
  * An instance is created to wrap the selected {@link ScrollCaptureCallback}.
  *
  * @hide
  */
-public class ScrollCaptureClient extends IScrollCaptureClient.Stub {
+public class ScrollCaptureConnection extends IScrollCaptureConnection.Stub {
 
-    private static final String TAG = "ScrollCaptureClient";
+    private static final String TAG = "ScrollCaptureConnection";
     private static final int DEFAULT_TIMEOUT = 1000;
 
     private final Handler mHandler;
@@ -49,7 +48,7 @@
     private int mTimeoutMillis = DEFAULT_TIMEOUT;
 
     protected Surface mSurface;
-    private IScrollCaptureController mController;
+    private IScrollCaptureCallbacks mCallbacks;
 
     private final Rect mScrollBounds;
     private final Point mPositionInWindow;
@@ -62,18 +61,18 @@
     private DelayedAction mTimeoutAction;
 
     /**
-     * Constructs a ScrollCaptureClient.
+     * Constructs a ScrollCaptureConnection.
      *
      * @param selectedTarget  the target the client is controlling
-     * @param controller the callbacks to reply to system requests
+     * @param callbacks the callbacks to reply to system requests
      *
      * @hide
      */
-    public ScrollCaptureClient(
+    public ScrollCaptureConnection(
             @NonNull ScrollCaptureTarget selectedTarget,
-            @NonNull IScrollCaptureController controller) {
+            @NonNull IScrollCaptureCallbacks callbacks) {
         requireNonNull(selectedTarget, "<selectedTarget> must non-null");
-        requireNonNull(controller, "<controller> must non-null");
+        requireNonNull(callbacks, "<callbacks> must non-null");
         final Rect scrollBounds = requireNonNull(selectedTarget.getScrollBounds(),
                 "target.getScrollBounds() must be non-null to construct a client");
 
@@ -82,7 +81,7 @@
         mScrollBounds = new Rect(scrollBounds);
         mPositionInWindow = new Point(selectedTarget.getPositionInWindow());
 
-        mController = controller;
+        mCallbacks = callbacks;
         mCloseGuard = new CloseGuard();
         mCloseGuard.open("close");
 
@@ -106,14 +105,13 @@
         mTimeoutMillis = timeoutMillis;
     }
 
-    @Nullable
     @VisibleForTesting
     public DelayedAction getTimeoutAction() {
         return mTimeoutAction;
     }
 
     private void checkConnected() {
-        if (mSelectedTarget == null || mController == null) {
+        if (mSelectedTarget == null || mCallbacks == null) {
             throw new IllegalStateException("This client has been disconnected.");
         }
     }
@@ -124,7 +122,7 @@
         }
     }
 
-    @WorkerThread // IScrollCaptureClient
+    @WorkerThread // IScrollCaptureConnection
     @Override
     public void startCapture(Surface surface) throws RemoteException {
         checkConnected();
@@ -140,7 +138,7 @@
         if (cancelTimeout()) {
             mHandler.post(() -> {
                 try {
-                    mController.onCaptureStarted();
+                    mCallbacks.onCaptureStarted();
                 } catch (RemoteException e) {
                     doShutdown();
                 }
@@ -153,7 +151,7 @@
         endCapture();
     }
 
-    @WorkerThread // IScrollCaptureClient
+    @WorkerThread // IScrollCaptureConnection
     @Override
     public void requestImage(Rect requestRect) {
         checkConnected();
@@ -170,7 +168,7 @@
         if (cancelTimeout()) {
             mHandler.post(() -> {
                 try {
-                    mController.onCaptureBufferSent(frameNumber, finalCapturedArea);
+                    mCallbacks.onCaptureBufferSent(frameNumber, finalCapturedArea);
                 } catch (RemoteException e) {
                     doShutdown();
                 }
@@ -183,7 +181,7 @@
         endCapture();
     }
 
-    @WorkerThread // IScrollCaptureClient
+    @WorkerThread // IScrollCaptureConnection
     @Override
     public void endCapture() {
         if (isStarted()) {
@@ -196,7 +194,7 @@
     }
 
     private boolean isStarted() {
-        return mController != null && mSelectedTarget != null;
+        return mCallbacks != null && mSelectedTarget != null;
     }
 
     @UiThread
@@ -214,8 +212,8 @@
 
     private void doShutdown() {
         try {
-            if (mController != null) {
-                mController.onConnectionClosed();
+            if (mCallbacks != null) {
+                mCallbacks.onConnectionClosed();
             }
         } catch (RemoteException e) {
             // Ignore
@@ -235,15 +233,15 @@
         }
 
         mSelectedTarget = null;
-        mController = null;
+        mCallbacks = null;
     }
 
     /** @return a string representation of the state of this client */
     public String toString() {
-        return "ScrollCaptureClient{"
+        return "ScrollCaptureConnection{"
                 + ", session=" + mSession
                 + ", selectedTarget=" + mSelectedTarget
-                + ", clientCallbacks=" + mController
+                + ", clientCallbacks=" + mCallbacks
                 + "}";
     }
 
diff --git a/core/java/android/view/ScrollCaptureSession.java b/core/java/android/view/ScrollCaptureSession.java
index 628e23f..92617a3 100644
--- a/core/java/android/view/ScrollCaptureSession.java
+++ b/core/java/android/view/ScrollCaptureSession.java
@@ -36,15 +36,15 @@
     private final Point mPositionInWindow;
 
     @Nullable
-    private ScrollCaptureClient mClient;
+    private ScrollCaptureConnection mConnection;
 
     /** @hide */
     public ScrollCaptureSession(Surface surface, Rect scrollBounds, Point positionInWindow,
-            ScrollCaptureClient client) {
+            ScrollCaptureConnection connection) {
         mSurface = surface;
         mScrollBounds = scrollBounds;
         mPositionInWindow = positionInWindow;
-        mClient = client;
+        mConnection = connection;
     }
 
     /**
@@ -88,8 +88,8 @@
      * @param capturedArea the area captured, relative to scroll bounds
      */
     public void notifyBufferSent(long frameNumber, @NonNull Rect capturedArea) {
-        if (mClient != null) {
-            mClient.onRequestImageCompleted(frameNumber, capturedArea);
+        if (mConnection != null) {
+            mConnection.onRequestImageCompleted(frameNumber, capturedArea);
         }
     }
 
@@ -97,7 +97,7 @@
      * @hide
      */
     public void disconnect() {
-        mClient = null;
+        mConnection = null;
         if (mSurface.isValid()) {
             mSurface.release();
         }
diff --git a/core/java/android/view/ScrollCaptureTargetResolver.java b/core/java/android/view/ScrollCaptureTargetResolver.java
index 71e82c5..5106534 100644
--- a/core/java/android/view/ScrollCaptureTargetResolver.java
+++ b/core/java/android/view/ScrollCaptureTargetResolver.java
@@ -57,7 +57,6 @@
 @UiThread
 public class ScrollCaptureTargetResolver {
     private static final String TAG = "ScrollCaptureTargetRes";
-    private static final boolean DEBUG = true;
 
     private final Object mLock = new Object();
 
@@ -86,18 +85,11 @@
      * Binary operator which selects the best {@link ScrollCaptureTarget}.
      */
     private static ScrollCaptureTarget chooseTarget(ScrollCaptureTarget a, ScrollCaptureTarget b) {
-        Log.d(TAG, "chooseTarget: " + a + " or " + b);
-        // Nothing plus nothing is still nothing.
         if (a == null && b == null) {
-            Log.d(TAG, "chooseTarget: (both null) return " + null);
             return null;
-        }
-        // Prefer non-null.
-        if (a == null || b == null) {
+        } else if (a == null || b == null) {
             ScrollCaptureTarget c = (a == null) ? b : a;
-            Log.d(TAG, "chooseTarget: (other is null) return " + c);
             return c;
-
         }
 
         boolean emptyScrollBoundsA = nullOrEmpty(a.getScrollBounds());
@@ -155,8 +147,7 @@
      *
      * @param targets   a list of {@link ScrollCaptureTarget} as collected by {@link
      *                  View#dispatchScrollCaptureSearch}.
-     * @param uiHandler the UI thread handler for the view tree
-     * @see #start(long, Consumer)
+     * @see #start(Handler, long, Consumer)
      */
     public ScrollCaptureTargetResolver(Queue<ScrollCaptureTarget> targets) {
         mTargets = targets;
@@ -184,7 +175,6 @@
         return mResult;
     }
 
-
     private void supplyResult(ScrollCaptureTarget target) {
         checkThread();
         if (mFinished) {
@@ -232,12 +222,11 @@
                 return;
             }
             mStarted = true;
-            uiHandler.post(() -> run(timeLimitMillis, resultConsumer));
+            uiHandler.post(this::run);
         }
     }
 
-
-    private void run(long timeLimitMillis, Consumer<ScrollCaptureTarget> resultConsumer) {
+    private void run() {
         checkThread();
 
         mPendingBoundsRequests = mTargets.size();
@@ -248,15 +237,11 @@
         mHandler.postAtTime(mTimeoutRunnable, mDeadlineMillis);
     }
 
-    private final Runnable mTimeoutRunnable = new Runnable() {
-        @Override
-        public void run() {
-            checkThread();
-            supplyResult(null);
-        }
+    private final Runnable mTimeoutRunnable = () -> {
+        checkThread();
+        supplyResult(null);
     };
 
-
     /**
      * Adds a target to the list and requests {@link ScrollCaptureCallback#onScrollCaptureSearch}
      * scrollBounds} from it. Results are returned by a call to {@link #onScrollBoundsProvided}.
@@ -274,7 +259,6 @@
                         // Queue and consume on the UI thread
                         ((scrollBounds) -> mHandler.post(
                                 () -> onScrollBoundsProvided(target, scrollBounds)))));
-
     }
 
     @UiThread
@@ -300,14 +284,8 @@
             supplyResult(target);
         }
 
-        System.err.println("mPendingBoundsRequests: " + mPendingBoundsRequests);
-        System.err.println("mDeadlineMillis: " + mDeadlineMillis);
-        System.err.println("SystemClock.elapsedRealtime(): " + SystemClock.elapsedRealtime());
-
         if (!mFinished) {
             // Reschedule the timeout.
-            System.err.println(
-                    "We think we're NOT done yet and will check back at " + mDeadlineMillis);
             mHandler.postAtTime(mTimeoutRunnable, mDeadlineMillis);
         }
     }
@@ -334,44 +312,17 @@
         return otherParent == view;
     }
 
-    private static int findRelation(@NonNull View a, @NonNull View b) {
-        if (a == b) {
-            return 0;
-        }
-
-        ViewParent parentA = a.getParent();
-        ViewParent parentB = b.getParent();
-
-        while (parentA != null || parentB != null) {
-            if (parentA == parentB) {
-                return 0;
-            }
-            if (parentA == b) {
-                return 1; // A is descendant of B
-            }
-            if (parentB == a) {
-                return -1; // B is descendant of A
-            }
-            if (parentA != null) {
-                parentA = parentA.getParent();
-            }
-            if (parentB != null) {
-                parentB = parentB.getParent();
-            }
-        }
-        return 0;
-    }
-
     /**
      * A safe wrapper for a consumer callbacks intended to accept a single value. It ensures
      * that the receiver of the consumer does not retain a reference to {@code target} after use nor
      * cause race conditions by invoking {@link Consumer#accept accept} more than once.
-     *
-     * @param target the target consumer
      */
     static class SingletonConsumer<T> implements Consumer<T> {
         final AtomicReference<Consumer<T>> mAtomicRef;
 
+        /**
+         * @param target the target consumer
+         **/
         SingletonConsumer(Consumer<T> target) {
             mAtomicRef = new AtomicReference<>(target);
         }
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 7b6a4f8..432d927 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -1849,7 +1849,7 @@
         // If developers explicitly set the important mode for it, don't change the mode.
         // Only change the mode to important when this SurfaceView isn't explicitly set and has
         // an embedded hierarchy.
-        if (!mRemoteAccessibilityController.connected()
+        if ((mRemoteAccessibilityController!= null && !mRemoteAccessibilityController.connected())
                 || mode != IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
             return mode;
         }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 77626c2..f0203011 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -649,7 +649,7 @@
     private final InsetsController mInsetsController;
     private final ImeFocusController mImeFocusController;
 
-    private ScrollCaptureClient mScrollCaptureClient;
+    private ScrollCaptureConnection mScrollCaptureConnection;
 
     /**
      * @return {@link ImeFocusController} for this instance.
@@ -659,10 +659,10 @@
         return mImeFocusController;
     }
 
-    /** @return The current {@link ScrollCaptureClient} for this instance, if any is active. */
+    /** @return The current {@link ScrollCaptureConnection} for this instance, if any is active. */
     @Nullable
-    public ScrollCaptureClient getScrollCaptureClient() {
-        return mScrollCaptureClient;
+    public ScrollCaptureConnection getScrollCaptureConnection() {
+        return mScrollCaptureConnection;
     }
 
     private final GestureExclusionTracker mGestureExclusionTracker = new GestureExclusionTracker();
@@ -1021,8 +1021,10 @@
                     mAttachInfo.mRecomputeGlobalAttributes = true;
                     collectViewAttributes();
                     adjustLayoutParamsForCompatibility(mWindowAttributes);
+                    controlInsetsForCompatibility(mWindowAttributes);
                     res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,
-                            getHostVisibility(), mDisplay.getDisplayId(), userId, mTmpFrames.frame,
+                            getHostVisibility(), mDisplay.getDisplayId(), userId,
+                            mInsetsController.getRequestedVisibility(), mTmpFrames.frame,
                             mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                             mAttachInfo.mDisplayCutout, inputChannel,
                             mTempInsets, mTempControls);
@@ -5190,7 +5192,7 @@
                     updateLocationInParentDisplay(msg.arg1, msg.arg2);
                 } break;
                 case MSG_REQUEST_SCROLL_CAPTURE:
-                    handleScrollCaptureRequest((IScrollCaptureController) msg.obj);
+                    handleScrollCaptureRequest((IScrollCaptureCallbacks) msg.obj);
                     break;
             }
         }
@@ -8977,10 +8979,10 @@
     /**
      * Dispatches a scroll capture request to the view hierarchy on the ui thread.
      *
-     * @param controller the controller to receive replies
+     * @param callbacks for replies
      */
-    public void dispatchScrollCaptureRequest(@NonNull IScrollCaptureController controller) {
-        mHandler.obtainMessage(MSG_REQUEST_SCROLL_CAPTURE, controller).sendToTarget();
+    public void dispatchScrollCaptureRequest(@NonNull IScrollCaptureCallbacks callbacks) {
+        mHandler.obtainMessage(MSG_REQUEST_SCROLL_CAPTURE, callbacks).sendToTarget();
     }
 
     /**
@@ -9005,14 +9007,14 @@
      * Handles an inbound request for scroll capture from the system. If a client is not already
      * active, a search will be dispatched through the view tree to locate scrolling content.
      * <p>
-     * Either {@link IScrollCaptureController#onClientConnected(IScrollCaptureClient, Rect,
-     * Point)} or {@link IScrollCaptureController#onClientUnavailable()} will be returned
+     * Either {@link IScrollCaptureCallbacks#onClientConnected(IScrollCaptureConnection, Rect,
+     * Point)} or {@link IScrollCaptureCallbacks#onUnavailable()} will be returned
      * depending on the results of the search.
      *
-     * @param controller the interface to the system controller
+     * @param callbacks to receive responses
      * @see ScrollCaptureTargetResolver
      */
-    private void handleScrollCaptureRequest(@NonNull IScrollCaptureController controller) {
+    private void handleScrollCaptureRequest(@NonNull IScrollCaptureCallbacks callbacks) {
         LinkedList<ScrollCaptureTarget> targetList = new LinkedList<>();
 
         // Window (root) level callbacks
@@ -9027,7 +9029,7 @@
 
         // No-op path. Scroll capture not offered for this window.
         if (targetList.isEmpty()) {
-            dispatchScrollCaptureSearchResult(controller, null);
+            dispatchScrollCaptureSearchResult(callbacks, null);
             return;
         }
 
@@ -9035,12 +9037,12 @@
         // Continues with the consumer once all responses are consumed, or the timeout expires.
         ScrollCaptureTargetResolver resolver = new ScrollCaptureTargetResolver(targetList);
         resolver.start(mHandler, 1000,
-                (selected) -> dispatchScrollCaptureSearchResult(controller, selected));
+                (selected) -> dispatchScrollCaptureSearchResult(callbacks, selected));
     }
 
     /** Called by {@link #handleScrollCaptureRequest} when a result is returned */
     private void dispatchScrollCaptureSearchResult(
-            @NonNull IScrollCaptureController controller,
+            @NonNull IScrollCaptureCallbacks callbacks,
             @Nullable ScrollCaptureTarget selectedTarget) {
 
         // If timeout or no eligible targets found.
@@ -9049,31 +9051,31 @@
                 if (DEBUG_SCROLL_CAPTURE) {
                     Log.d(TAG, "scrollCaptureSearch returned no targets available.");
                 }
-                controller.onClientUnavailable();
+                callbacks.onUnavailable();
             } catch (RemoteException e) {
                 if (DEBUG_SCROLL_CAPTURE) {
-                    Log.w(TAG, "Failed to notify controller of scroll capture search result.", e);
+                    Log.w(TAG, "Failed to send scroll capture search result.", e);
                 }
             }
             return;
         }
 
         // Create a client instance and return it to the caller
-        mScrollCaptureClient = new ScrollCaptureClient(selectedTarget, controller);
+        mScrollCaptureConnection = new ScrollCaptureConnection(selectedTarget, callbacks);
         try {
             if (DEBUG_SCROLL_CAPTURE) {
-                Log.d(TAG, "scrollCaptureSearch returning client: " + getScrollCaptureClient());
+                Log.d(TAG, "scrollCaptureSearch returning client: " + getScrollCaptureConnection());
             }
-            controller.onClientConnected(
-                    mScrollCaptureClient,
+            callbacks.onConnected(
+                    mScrollCaptureConnection,
                     selectedTarget.getScrollBounds(),
                     selectedTarget.getPositionInWindow());
         } catch (RemoteException e) {
             if (DEBUG_SCROLL_CAPTURE) {
-                Log.w(TAG, "Failed to notify controller of scroll capture search result.", e);
+                Log.w(TAG, "Failed to send scroll capture search result.", e);
             }
-            mScrollCaptureClient.disconnect();
-            mScrollCaptureClient = null;
+            mScrollCaptureConnection.disconnect();
+            mScrollCaptureConnection = null;
         }
     }
 
@@ -9371,10 +9373,10 @@
         }
 
         @Override
-        public void requestScrollCapture(IScrollCaptureController controller) {
+        public void requestScrollCapture(IScrollCaptureCallbacks callbacks) {
             final ViewRootImpl viewAncestor = mViewAncestor.get();
             if (viewAncestor != null) {
-                viewAncestor.dispatchScrollCaptureRequest(controller);
+                viewAncestor.dispatchScrollCaptureRequest(callbacks);
             }
         }
     }
diff --git a/core/java/android/view/ViewRootInsetsControllerHost.java b/core/java/android/view/ViewRootInsetsControllerHost.java
index 90a80ce..8f58df4 100644
--- a/core/java/android/view/ViewRootInsetsControllerHost.java
+++ b/core/java/android/view/ViewRootInsetsControllerHost.java
@@ -144,7 +144,9 @@
     @Override
     public void onInsetsModified(InsetsState insetsState) {
         try {
-            mViewRoot.mWindowSession.insetsModified(mViewRoot.mWindow, insetsState);
+            if (mViewRoot.mAdded) {
+                mViewRoot.mWindowSession.insetsModified(mViewRoot.mWindow, insetsState);
+            }
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to call insetsModified", e);
         }
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 1dbf37a..5331a1b 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -2560,19 +2560,20 @@
     /**
      * System request to begin scroll capture.
      *
-     * @param controller the controller to receive responses
+     * @param callbacks to receive responses
      * @hide
      */
-    public void requestScrollCapture(IScrollCaptureController controller) {
+    public void requestScrollCapture(IScrollCaptureCallbacks callbacks) {
     }
 
     /**
-     * Registers a {@link ScrollCaptureCallback} with the root of this window.
+     * Used to provide scroll capture support for an arbitrary window. This registeres the given
+     * callback with the root view of the window.
      *
      * @param callback the callback to add
      * @hide
      */
-    public void addScrollCaptureCallback(@NonNull ScrollCaptureCallback callback) {
+    public void registerScrollCaptureCallback(@NonNull ScrollCaptureCallback callback) {
     }
 
     /**
@@ -2581,7 +2582,7 @@
      * @param callback the callback to remove
      * @hide
      */
-    public void removeScrollCaptureCallback(@NonNull ScrollCaptureCallback callback) {
+    public void unregisterScrollCaptureCallback(@NonNull ScrollCaptureCallback callback) {
     }
 
     /** @hide */
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index e96e98b..964ea34 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -224,12 +224,6 @@
     int TRANSIT_ACTIVITY_RELAUNCH = 18;
 
     /**
-     * A task is being docked from recents.
-     * @hide
-     */
-    int TRANSIT_DOCK_TASK_FROM_RECENTS = 19;
-
-    /**
      * Keyguard is going away.
      * @hide
      */
@@ -302,7 +296,6 @@
             TRANSIT_WALLPAPER_INTRA_CLOSE,
             TRANSIT_TASK_OPEN_BEHIND,
             TRANSIT_ACTIVITY_RELAUNCH,
-            TRANSIT_DOCK_TASK_FROM_RECENTS,
             TRANSIT_KEYGUARD_GOING_AWAY,
             TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER,
             TRANSIT_KEYGUARD_OCCLUDE,
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 0c221ed..8147873 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -130,8 +130,8 @@
      */
     @Override
     public int addToDisplay(IWindow window, WindowManager.LayoutParams attrs,
-            int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
-            Rect outStableInsets,
+            int viewVisibility, int displayId, InsetsState requestedVisibility, Rect outFrame,
+            Rect outContentInsets, Rect outStableInsets,
             DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
             InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
         final SurfaceControl.Builder b = new SurfaceControl.Builder(mSurfaceSession)
@@ -166,11 +166,11 @@
      */
     @Override
     public int addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs,
-            int viewVisibility, int displayId, int userId, Rect outFrame,
-            Rect outContentInsets, Rect outStableInsets,
+            int viewVisibility, int displayId, int userId, InsetsState requestedVisibility,
+            Rect outFrame, Rect outContentInsets, Rect outStableInsets,
             DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
             InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
-        return addToDisplay(window, attrs, viewVisibility, displayId,
+        return addToDisplay(window, attrs, viewVisibility, displayId, requestedVisibility,
                 outFrame, outContentInsets, outStableInsets, outDisplayCutout, outInputChannel,
                 outInsetsState, outActiveControls);
     }
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index aed9b89..a9e8d54 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -1249,7 +1249,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
     public void performAccessibilityShortcut() {
         performAccessibilityShortcut(null);
@@ -1294,7 +1293,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
     public void registerSystemAction(@NonNull RemoteAction action, int actionId) {
         final IAccessibilityManager service;
@@ -1322,7 +1320,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
     public void unregisterSystemAction(int actionId) {
         final IAccessibilityManager service;
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 9ba886a..fb66b52 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -2076,7 +2076,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public void setAugmentedAutofillWhitelist(@Nullable Set<String> packages,
             @Nullable Set<ComponentName> activities) {
         if (!hasAutofillFeature()) {
diff --git a/core/java/android/view/contentcapture/ContentCaptureContext.java b/core/java/android/view/contentcapture/ContentCaptureContext.java
index b84cb88..9bf3626 100644
--- a/core/java/android/view/contentcapture/ContentCaptureContext.java
+++ b/core/java/android/view/contentcapture/ContentCaptureContext.java
@@ -21,7 +21,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.app.TaskInfo;
 import android.content.ComponentName;
 import android.content.Context;
@@ -58,7 +57,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int FLAG_DISABLED_BY_APP = 0x1;
 
     /**
@@ -69,7 +67,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int FLAG_DISABLED_BY_FLAG_SECURE = 0x2;
 
     /**
@@ -79,7 +76,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int FLAG_RECONNECTED = 0x4;
 
     /** @hide */
@@ -173,7 +169,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public int getTaskId() {
         return mTaskId;
     }
@@ -184,7 +179,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public @Nullable ComponentName getActivityComponent() {
         return mComponentName;
     }
@@ -197,7 +191,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public @Nullable ContentCaptureSessionId getParentSessionId() {
         return mParentSessionId == NO_SESSION_ID ? null
                 : new ContentCaptureSessionId(mParentSessionId);
@@ -215,7 +208,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public int getDisplayId() {
         return mDisplayId;
     }
@@ -229,7 +221,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public @ContextCreationFlags int getFlags() {
         return mFlags;
     }
diff --git a/core/java/android/view/contentcapture/ContentCaptureEvent.java b/core/java/android/view/contentcapture/ContentCaptureEvent.java
index f49b1be..2b12230 100644
--- a/core/java/android/view/contentcapture/ContentCaptureEvent.java
+++ b/core/java/android/view/contentcapture/ContentCaptureEvent.java
@@ -22,7 +22,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.graphics.Insets;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -39,7 +38,6 @@
 
 /** @hide */
 @SystemApi
-@TestApi
 public final class ContentCaptureEvent implements Parcelable {
 
     private static final String TAG = ContentCaptureEvent.class.getSimpleName();
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 029552d..10f6c61 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -644,7 +644,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public boolean isContentCaptureFeatureEnabled() {
         final SyncResultReceiver resultReceiver = syncRun(
                 (r) -> mService.isContentCaptureFeatureEnabled(r));
diff --git a/core/java/android/view/contentcapture/ViewNode.java b/core/java/android/view/contentcapture/ViewNode.java
index e035c62..e731d4b 100644
--- a/core/java/android/view/contentcapture/ViewNode.java
+++ b/core/java/android/view/contentcapture/ViewNode.java
@@ -42,7 +42,6 @@
 // instead
 /** @hide */
 @SystemApi
-@TestApi
 public final class ViewNode extends AssistStructure.ViewNode {
 
     private static final String TAG = ViewNode.class.getSimpleName();
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index eaa738d..f2955ac 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -206,6 +206,10 @@
         int TEXT_LINK = 2;
     }
 
+    // Default content insertion handler.
+    private final TextViewOnReceiveContentCallback mDefaultOnReceiveContentCallback =
+            new TextViewOnReceiveContentCallback();
+
     // Each Editor manages its own undo stack.
     private final UndoManager mUndoManager = new UndoManager();
     private UndoOwner mUndoOwner = mUndoManager.getOwner(UNDO_OWNER_TAG, this);
@@ -584,6 +588,11 @@
         mUndoOwner = mUndoManager.getOwner(UNDO_OWNER_TAG, this);
     }
 
+    @VisibleForTesting
+    public @NonNull TextViewOnReceiveContentCallback getDefaultOnReceiveContentCallback() {
+        return mDefaultOnReceiveContentCallback;
+    }
+
     /**
      * Forgets all undo and redo operations for this Editor.
      */
@@ -709,6 +718,8 @@
 
         hideCursorAndSpanControllers();
         stopTextActionModeWithPreservingSelection();
+
+        mDefaultOnReceiveContentCallback.clearInputConnectionInfo();
     }
 
     private void discardTextDisplayLists() {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 52a3f41..7bb2b7e 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -80,6 +80,7 @@
 import android.os.Build;
 import android.os.Build.VERSION_CODES;
 import android.os.Bundle;
+import android.os.Handler;
 import android.os.LocaleList;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -890,13 +891,6 @@
     @UnsupportedAppUsage
     private Editor mEditor;
 
-    /**
-     * The default content insertion callback used by {@link TextView}. See
-     * {@link #setOnReceiveContentCallback} for more info.
-     */
-    private static final TextViewOnReceiveContentCallback DEFAULT_ON_RECEIVE_CONTENT_CALLBACK =
-            new TextViewOnReceiveContentCallback();
-
     private static final int DEVICE_PROVISIONED_UNKNOWN = 0;
     private static final int DEVICE_PROVISIONED_NO = 1;
     private static final int DEVICE_PROVISIONED_YES = 2;
@@ -13723,6 +13717,23 @@
         }
     }
 
+    /** @hide */
+    @Override
+    public void onInputConnectionOpenedInternal(@NonNull InputConnection ic,
+            @NonNull EditorInfo editorInfo, @Nullable Handler handler) {
+        if (mEditor != null) {
+            mEditor.getDefaultOnReceiveContentCallback().setInputConnectionInfo(ic, editorInfo);
+        }
+    }
+
+    /** @hide */
+    @Override
+    public void onInputConnectionClosedInternal() {
+        if (mEditor != null) {
+            mEditor.getDefaultOnReceiveContentCallback().clearInputConnectionInfo();
+        }
+    }
+
     /**
      * Returns the callback used for handling insertion of content into this view. See
      * {@link #setOnReceiveContentCallback} for more info.
@@ -13773,8 +13784,8 @@
         ClipDescription description = payload.getClip().getDescription();
         if (receiver != null && receiver.supports(this, description)) {
             receiver.onReceiveContent(this, payload);
-        } else {
-            DEFAULT_ON_RECEIVE_CONTENT_CALLBACK.onReceiveContent(this, payload);
+        } else if (mEditor != null) {
+            mEditor.getDefaultOnReceiveContentCallback().onReceiveContent(this, payload);
         }
     }
 
diff --git a/core/java/android/widget/TextViewOnReceiveContentCallback.java b/core/java/android/widget/TextViewOnReceiveContentCallback.java
index 35618cb..d7c95b7 100644
--- a/core/java/android/widget/TextViewOnReceiveContentCallback.java
+++ b/core/java/android/widget/TextViewOnReceiveContentCallback.java
@@ -16,24 +16,44 @@
 
 package android.widget;
 
+import static android.content.ContentResolver.SCHEME_CONTENT;
 import static android.view.OnReceiveContentCallback.Payload.FLAG_CONVERT_TO_PLAIN_TEXT;
 import static android.view.OnReceiveContentCallback.Payload.SOURCE_AUTOFILL;
 import static android.view.OnReceiveContentCallback.Payload.SOURCE_DRAG_AND_DROP;
 
+import static java.util.Collections.singleton;
+
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SuppressLint;
+import android.compat.Compatibility;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
 import android.content.ClipData;
+import android.content.ClipDescription;
 import android.content.Context;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
 import android.text.Editable;
 import android.text.Selection;
 import android.text.SpannableStringBuilder;
 import android.text.Spanned;
+import android.util.ArraySet;
 import android.util.Log;
 import android.view.OnReceiveContentCallback;
 import android.view.OnReceiveContentCallback.Payload.Flags;
 import android.view.OnReceiveContentCallback.Payload.Source;
+import android.view.View;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputContentInfo;
 
-import java.util.Collections;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Set;
 
 /**
@@ -46,19 +66,26 @@
 public class TextViewOnReceiveContentCallback implements OnReceiveContentCallback<TextView> {
     private static final String LOG_TAG = "OnReceiveContent";
 
-    private static final Set<String> MIME_TYPES_ALL_TEXT = Collections.singleton("text/*");
+    private static final String MIME_TYPE_ALL_TEXT = "text/*";
+    private static final Set<String> MIME_TYPES_ALL_TEXT = singleton(MIME_TYPE_ALL_TEXT);
+
+    @Nullable private InputConnectionInfo mInputConnectionInfo;
+    @Nullable private ArraySet<String> mCachedSupportedMimeTypes;
 
     @SuppressLint("CallbackMethodName")
     @NonNull
     @Override
     public Set<String> getSupportedMimeTypes(@NonNull TextView view) {
-        return MIME_TYPES_ALL_TEXT;
+        if (!isUsageOfImeCommitContentEnabled(view)) {
+            return MIME_TYPES_ALL_TEXT;
+        }
+        return getSupportedMimeTypesAugmentedWithImeCommitContentMimeTypes();
     }
 
     @Override
     public boolean onReceiveContent(@NonNull TextView view, @NonNull Payload payload) {
         if (Log.isLoggable(LOG_TAG, Log.DEBUG)) {
-            Log.d(LOG_TAG, "onReceive:" + payload);
+            Log.d(LOG_TAG, "onReceive: " + payload);
         }
         ClipData clip = payload.getClip();
         @Source int source = payload.getSource();
@@ -109,13 +136,22 @@
         editable.replace(start, end, replacement);
     }
 
-    private static boolean onReceiveForAutofill(@NonNull TextView textView, @NonNull ClipData clip,
+    private boolean onReceiveForAutofill(@NonNull TextView view, @NonNull ClipData clip,
             @Flags int flags) {
-        final CharSequence text = coerceToText(clip, textView.getContext(), flags);
+        if (isUsageOfImeCommitContentEnabled(view)) {
+            clip = handleNonTextViaImeCommitContent(clip);
+            if (clip == null) {
+                if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
+                    Log.v(LOG_TAG, "onReceive: Handled via IME");
+                }
+                return true;
+            }
+        }
+        final CharSequence text = coerceToText(clip, view.getContext(), flags);
         // First autofill it...
-        textView.setText(text);
+        view.setText(text);
         // ...then move cursor to the end.
-        final Editable editable = (Editable) textView.getText();
+        final Editable editable = (Editable) view.getText();
         Selection.setSelection(editable, editable.length());
         return true;
     }
@@ -146,4 +182,250 @@
         }
         return ssb;
     }
+
+    /**
+     * On Android S and above, the platform can provide non-text suggestions (e.g. images) via the
+     * augmented autofill framework (see
+     * <a href="/guide/topics/text/autofill-services">autofill services</a>). In order for an app to
+     * be able to handle these suggestions, it must normally implement the
+     * {@link android.view.OnReceiveContentCallback} API. To make the adoption of this smoother for
+     * apps that have previously implemented the
+     * {@link android.view.inputmethod.InputConnection#commitContent(InputContentInfo, int, Bundle)}
+     * API, we reuse that API as a fallback if {@link android.view.OnReceiveContentCallback} is not
+     * yet implemented by the app. This fallback is only enabled on Android S. This change ID
+     * disables the fallback, such that apps targeting Android T and above must implement the
+     * {@link android.view.OnReceiveContentCallback} API in order to accept non-text suggestions.
+     */
+    @ChangeId
+    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S) // Enabled on Android T and higher
+    private static final long AUTOFILL_NON_TEXT_REQUIRES_ON_RECEIVE_CONTENT_CALLBACK = 163400105L;
+
+    /**
+     * Returns true if we can use the IME {@link InputConnection#commitContent} API in order handle
+     * non-text content.
+     */
+    private static boolean isUsageOfImeCommitContentEnabled(@NonNull View view) {
+        if (view.getOnReceiveContentCallback() != null) {
+            if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
+                Log.v(LOG_TAG, "Fallback to commitContent disabled (custom callback is set)");
+            }
+            return false;
+        }
+        if (Compatibility.isChangeEnabled(AUTOFILL_NON_TEXT_REQUIRES_ON_RECEIVE_CONTENT_CALLBACK)) {
+            if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
+                Log.v(LOG_TAG, "Fallback to commitContent disabled (target SDK is above S)");
+            }
+            return false;
+        }
+        return true;
+    }
+
+    private static final class InputConnectionInfo {
+        @NonNull private final WeakReference<InputConnection> mInputConnection;
+        @NonNull private final String[] mEditorInfoContentMimeTypes;
+
+        private InputConnectionInfo(@NonNull InputConnection inputConnection,
+                @NonNull String[] editorInfoContentMimeTypes) {
+            mInputConnection = new WeakReference<>(inputConnection);
+            mEditorInfoContentMimeTypes = editorInfoContentMimeTypes;
+        }
+
+        @Override
+        public String toString() {
+            return "InputConnectionInfo{"
+                    + "mimeTypes=" + Arrays.toString(mEditorInfoContentMimeTypes)
+                    + ", ic=" + mInputConnection
+                    + '}';
+        }
+    }
+
+    /**
+     * Invoked by the platform when an {@link InputConnection} is successfully created for the view
+     * that owns this callback instance.
+     */
+    void setInputConnectionInfo(@NonNull InputConnection ic, @NonNull EditorInfo editorInfo) {
+        if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
+            Log.v(LOG_TAG, "setInputConnectionInfo: "
+                    + Arrays.toString(editorInfo.contentMimeTypes));
+        }
+        String[] contentMimeTypes = editorInfo.contentMimeTypes;
+        if (contentMimeTypes == null || contentMimeTypes.length == 0) {
+            mInputConnectionInfo = null;
+        } else {
+            mInputConnectionInfo = new InputConnectionInfo(ic, contentMimeTypes);
+        }
+    }
+
+    /**
+     * Invoked by the platform when an {@link InputConnection} is closed for the view that owns this
+     * callback instance.
+     */
+    void clearInputConnectionInfo() {
+        if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
+            Log.v(LOG_TAG, "clearInputConnectionInfo: " + mInputConnectionInfo);
+        }
+        mInputConnectionInfo = null;
+    }
+
+    private Set<String> getSupportedMimeTypesAugmentedWithImeCommitContentMimeTypes() {
+        InputConnectionInfo icInfo = mInputConnectionInfo;
+        if (icInfo == null) {
+            if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
+                Log.v(LOG_TAG, "getSupportedMimeTypes: No usable EditorInfo/InputConnection");
+            }
+            return MIME_TYPES_ALL_TEXT;
+        }
+        String[] editorInfoContentMimeTypes = icInfo.mEditorInfoContentMimeTypes;
+        if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
+            Log.v(LOG_TAG, "getSupportedMimeTypes: Augmenting with EditorInfo.contentMimeTypes: "
+                    + Arrays.toString(editorInfoContentMimeTypes));
+        }
+        ArraySet<String> supportedMimeTypes = mCachedSupportedMimeTypes;
+        if (canReuse(supportedMimeTypes, editorInfoContentMimeTypes)) {
+            return supportedMimeTypes;
+        }
+        supportedMimeTypes = new ArraySet<>(editorInfoContentMimeTypes);
+        supportedMimeTypes.add(MIME_TYPE_ALL_TEXT);
+        mCachedSupportedMimeTypes = supportedMimeTypes;
+        return supportedMimeTypes;
+    }
+
+    /**
+     * We want to avoid creating a new set on every invocation of {@link #getSupportedMimeTypes}.
+     * This method will check if the cached set of MIME types matches the data in the given array
+     * from {@link EditorInfo} or if a new set should be created. The custom logic is needed for
+     * comparing the data because the set contains the additional "text/*" MIME type.
+     *
+     * @param cachedMimeTypes Previously cached set of MIME types.
+     * @param newEditorInfoMimeTypes MIME types from {@link EditorInfo}.
+     *
+     * @return Returns true if the data in the given cached set matches the data in the array.
+     *
+     * @hide
+     */
+    @VisibleForTesting
+    public static boolean canReuse(@Nullable ArraySet<String> cachedMimeTypes,
+            @NonNull String[] newEditorInfoMimeTypes) {
+        if (cachedMimeTypes == null) {
+            return false;
+        }
+        if (newEditorInfoMimeTypes.length != cachedMimeTypes.size()
+                && newEditorInfoMimeTypes.length != (cachedMimeTypes.size() - 1)) {
+            return false;
+        }
+        final boolean ignoreAllTextMimeType =
+                newEditorInfoMimeTypes.length == (cachedMimeTypes.size() - 1);
+        for (String mimeType : cachedMimeTypes) {
+            if (ignoreAllTextMimeType && mimeType.equals(MIME_TYPE_ALL_TEXT)) {
+                continue;
+            }
+            boolean present = false;
+            for (String editorInfoContentMimeType : newEditorInfoMimeTypes) {
+                if (editorInfoContentMimeType.equals(mimeType)) {
+                    present = true;
+                    break;
+                }
+            }
+            if (!present) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Tries to insert the content in the clip into the app via the image keyboard API. If all the
+     * items in the clip are successfully inserted, returns null. If one or more of the items in the
+     * clip cannot be inserted, returns a non-null clip that contains the items that were not
+     * inserted.
+     */
+    @Nullable
+    private ClipData handleNonTextViaImeCommitContent(@NonNull ClipData clip) {
+        ClipDescription description = clip.getDescription();
+        if (!containsUri(clip) || containsOnlyText(clip)) {
+            if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
+                Log.v(LOG_TAG, "onReceive: Clip doesn't contain any non-text URIs: "
+                        + description);
+            }
+            return clip;
+        }
+
+        InputConnectionInfo icInfo = mInputConnectionInfo;
+        InputConnection inputConnection = (icInfo != null) ? icInfo.mInputConnection.get() : null;
+        if (inputConnection == null) {
+            if (Log.isLoggable(LOG_TAG, Log.DEBUG)) {
+                Log.d(LOG_TAG, "onReceive: No usable EditorInfo/InputConnection");
+            }
+            return clip;
+        }
+        String[] editorInfoContentMimeTypes = icInfo.mEditorInfoContentMimeTypes;
+        if (!isClipMimeTypeSupported(editorInfoContentMimeTypes, clip.getDescription())) {
+            if (Log.isLoggable(LOG_TAG, Log.DEBUG)) {
+                Log.d(LOG_TAG,
+                        "onReceive: MIME type is not supported by the app's commitContent impl");
+            }
+            return clip;
+        }
+
+        if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
+            Log.v(LOG_TAG, "onReceive: Trying to insert via IME: " + description);
+        }
+        ArrayList<ClipData.Item> remainingItems = new ArrayList<>(0);
+        for (int i = 0; i < clip.getItemCount(); i++) {
+            ClipData.Item item = clip.getItemAt(i);
+            Uri uri = item.getUri();
+            if (uri == null || !SCHEME_CONTENT.equals(uri.getScheme())) {
+                if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
+                    Log.v(LOG_TAG, "onReceive: No content URI in item: uri=" + uri);
+                }
+                remainingItems.add(item);
+                continue;
+            }
+            if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
+                Log.v(LOG_TAG, "onReceive: Calling commitContent: uri=" + uri);
+            }
+            InputContentInfo contentInfo = new InputContentInfo(uri, description);
+            if (!inputConnection.commitContent(contentInfo, 0, null)) {
+                if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
+                    Log.v(LOG_TAG, "onReceive: Call to commitContent returned false: uri=" + uri);
+                }
+                remainingItems.add(item);
+            }
+        }
+        if (remainingItems.isEmpty()) {
+            return null;
+        }
+        return new ClipData(description, remainingItems);
+    }
+
+    private static boolean isClipMimeTypeSupported(@NonNull String[] supportedMimeTypes,
+            @NonNull ClipDescription description) {
+        for (String imeSupportedMimeType : supportedMimeTypes) {
+            if (description.hasMimeType(imeSupportedMimeType)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static boolean containsUri(@NonNull ClipData clip) {
+        for (int i = 0; i < clip.getItemCount(); i++) {
+            ClipData.Item item = clip.getItemAt(i);
+            if (item.getUri() != null) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static boolean containsOnlyText(@NonNull ClipData clip) {
+        ClipDescription description = clip.getDescription();
+        for (int i = 0; i < description.getMimeTypeCount(); i++) {
+            String mimeType = description.getMimeType(i);
+            if (!mimeType.startsWith("text/")) {
+                return false;
+            }
+        }
+        return true;
+    }
 }
diff --git a/core/java/com/android/internal/BrightnessSynchronizer.java b/core/java/com/android/internal/BrightnessSynchronizer.java
index 6b8cf63..c98477e 100644
--- a/core/java/com/android/internal/BrightnessSynchronizer.java
+++ b/core/java/com/android/internal/BrightnessSynchronizer.java
@@ -246,10 +246,12 @@
             }
             if (BRIGHTNESS_URI.equals(uri)) {
                 int currentBrightness = getScreenBrightnessInt(mContext);
+                mHandler.removeMessages(MSG_UPDATE_FLOAT);
                 mHandler.obtainMessage(MSG_UPDATE_FLOAT, currentBrightness, 0).sendToTarget();
             } else if (BRIGHTNESS_FLOAT_URI.equals(uri)) {
                 float currentFloat = getScreenBrightnessFloat(mContext);
                 int toSend = Float.floatToIntBits(currentFloat);
+                mHandler.removeMessages(MSG_UPDATE_INT);
                 mHandler.obtainMessage(MSG_UPDATE_INT, toSend, 0).sendToTarget();
             }
         }
diff --git a/core/java/com/android/internal/compat/CompatibilityChangeInfo.java b/core/java/com/android/internal/compat/CompatibilityChangeInfo.java
index 9ba0259..670ca9f 100644
--- a/core/java/com/android/internal/compat/CompatibilityChangeInfo.java
+++ b/core/java/com/android/internal/compat/CompatibilityChangeInfo.java
@@ -28,7 +28,7 @@
 public class CompatibilityChangeInfo implements Parcelable {
     private final long mChangeId;
     private final @Nullable String mName;
-    private final int mEnableAfterTargetSdk;
+    private final int mEnableSinceTargetSdk;
     private final boolean mDisabled;
     private final boolean mLoggingOnly;
     private final @Nullable String mDescription;
@@ -42,8 +42,8 @@
         return mName;
     }
 
-    public int getEnableAfterTargetSdk() {
-        return mEnableAfterTargetSdk;
+    public int getEnableSinceTargetSdk() {
+        return mEnableSinceTargetSdk;
     }
 
     public boolean getDisabled() {
@@ -59,20 +59,37 @@
     }
 
     public CompatibilityChangeInfo(
-            Long changeId, String name, int enableAfterTargetSdk, boolean disabled,
-            boolean loggingOnly, String description) {
+            Long changeId, String name, int enableAfterTargetSdk, int enableSinceTargetSdk,
+            boolean disabled, boolean loggingOnly, String description) {
         this.mChangeId = changeId;
         this.mName = name;
-        this.mEnableAfterTargetSdk = enableAfterTargetSdk;
+        if (enableAfterTargetSdk > 0) {
+            // Need to maintain support for @EnabledAfter(X), but make it equivalent to
+            // @EnabledSince(X+1)
+            this.mEnableSinceTargetSdk = enableAfterTargetSdk + 1;
+        } else if (enableSinceTargetSdk > 0) {
+            this.mEnableSinceTargetSdk = enableSinceTargetSdk;
+        } else {
+            this.mEnableSinceTargetSdk = -1;
+        }
         this.mDisabled = disabled;
         this.mLoggingOnly = loggingOnly;
         this.mDescription = description;
     }
 
+    public CompatibilityChangeInfo(CompatibilityChangeInfo other) {
+        this.mChangeId = other.mChangeId;
+        this.mName = other.mName;
+        this.mEnableSinceTargetSdk = other.mEnableSinceTargetSdk;
+        this.mDisabled = other.mDisabled;
+        this.mLoggingOnly = other.mLoggingOnly;
+        this.mDescription = other.mDescription;
+    }
+
     private CompatibilityChangeInfo(Parcel in) {
         mChangeId = in.readLong();
         mName = in.readString();
-        mEnableAfterTargetSdk = in.readInt();
+        mEnableSinceTargetSdk = in.readInt();
         mDisabled = in.readBoolean();
         mLoggingOnly = in.readBoolean();
         mDescription = in.readString();
@@ -87,7 +104,7 @@
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeLong(mChangeId);
         dest.writeString(mName);
-        dest.writeInt(mEnableAfterTargetSdk);
+        dest.writeInt(mEnableSinceTargetSdk);
         dest.writeBoolean(mDisabled);
         dest.writeBoolean(mLoggingOnly);
         dest.writeString(mDescription);
@@ -100,8 +117,8 @@
         if (getName() != null) {
             sb.append("; name=").append(getName());
         }
-        if (getEnableAfterTargetSdk() != -1) {
-            sb.append("; enableAfterTargetSdk=").append(getEnableAfterTargetSdk());
+        if (getEnableSinceTargetSdk() != -1) {
+            sb.append("; enableSinceTargetSdk=").append(getEnableSinceTargetSdk());
         }
         if (getDisabled()) {
             sb.append("; disabled");
@@ -123,7 +140,7 @@
         CompatibilityChangeInfo that = (CompatibilityChangeInfo) o;
         return this.mChangeId == that.mChangeId
                 && this.mName.equals(that.mName)
-                && this.mEnableAfterTargetSdk == that.mEnableAfterTargetSdk
+                && this.mEnableSinceTargetSdk == that.mEnableSinceTargetSdk
                 && this.mDisabled == that.mDisabled
                 && this.mLoggingOnly == that.mLoggingOnly
                 && this.mDescription.equals(that.mDescription);
diff --git a/core/java/com/android/internal/compat/IPlatformCompat.aidl b/core/java/com/android/internal/compat/IPlatformCompat.aidl
index 6408def..cc266d6 100644
--- a/core/java/com/android/internal/compat/IPlatformCompat.aidl
+++ b/core/java/com/android/internal/compat/IPlatformCompat.aidl
@@ -164,7 +164,7 @@
     boolean clearOverride(long changeId, String packageName);
 
     /**
-     * Enable all compatibility changes which have enabledAfterTargetSdk ==
+     * Enable all compatibility changes which have enabledSinceTargetSdk ==
      * {@param targetSdkVersion} for an app, subject to the policy. Kills the app to allow the
      * changes to take effect.
      *
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index d23ea3c..a2af4d6 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -132,6 +132,11 @@
      */
     public static final String PROPERTY_MIC_CAMERA_ENABLED = "camera_mic_icons_enabled";
 
+    /**
+     * Whether to show app ops chip for location.
+     */
+    public static final String PROPERTY_LOCATION_INDICATORS_ENABLED = "location_indicators_enabled";
+
     // Flags related to Assistant
 
     /**
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index dbe9796..b986463 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -195,7 +195,7 @@
     static final int MSG_REPORT_POWER_CHANGE = 2;
     static final int MSG_REPORT_CHARGING = 3;
     static final int MSG_REPORT_RESET_STATS = 4;
-    static final long DELAY_UPDATE_WAKELOCKS = 5*1000;
+    static final long DELAY_UPDATE_WAKELOCKS = 60 * 1000;
 
     private static final double MILLISECONDS_IN_HOUR = 3600 * 1000;
     private static final long MILLISECONDS_IN_YEAR = 365 * 24 * 3600 * 1000L;
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 50eed27..e848da9 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -77,7 +77,7 @@
 import android.view.ContextThemeWrapper;
 import android.view.Gravity;
 import android.view.IRotationWatcher.Stub;
-import android.view.IScrollCaptureController;
+import android.view.IScrollCaptureCallbacks;
 import android.view.IWindowManager;
 import android.view.InputDevice;
 import android.view.InputEvent;
@@ -1511,11 +1511,13 @@
         if (drawable != mBackgroundDrawable) {
             mBackgroundDrawable = drawable;
             if (mDecor != null) {
+                mDecor.startChanging();
                 mDecor.setWindowBackground(drawable);
                 if (mBackgroundFallbackDrawable != null) {
                     mDecor.setBackgroundFallback(drawable != null ? null :
                             mBackgroundFallbackDrawable);
                 }
+                mDecor.finishChanging();
             }
         }
     }
@@ -3910,12 +3912,12 @@
     /**
      * System request to begin scroll capture.
      *
-     * @param controller the controller to receive responses
+     * @param callbacks to receive responses
      * @hide
      */
     @Override
-    public void requestScrollCapture(IScrollCaptureController controller) {
-        getViewRootImpl().dispatchScrollCaptureRequest(controller);
+    public void requestScrollCapture(IScrollCaptureCallbacks callbacks) {
+        getViewRootImpl().dispatchScrollCaptureRequest(callbacks);
     }
 
     /**
@@ -3924,7 +3926,7 @@
      * @param callback the callback to add
      */
     @Override
-    public void addScrollCaptureCallback(@NonNull ScrollCaptureCallback callback) {
+    public void registerScrollCaptureCallback(@NonNull ScrollCaptureCallback callback) {
         getViewRootImpl().addScrollCaptureCallback(callback);
     }
 
@@ -3934,7 +3936,7 @@
      * @param callback the callback to remove
      */
     @Override
-    public void removeScrollCaptureCallback(@NonNull ScrollCaptureCallback callback) {
+    public void unregisterScrollCaptureCallback(@NonNull ScrollCaptureCallback callback) {
         getViewRootImpl().removeScrollCaptureCallback(callback);
     }
 
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index fff9ac9..8962dc3 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -24,7 +24,7 @@
 import android.os.RemoteException;
 import android.util.MergedConfiguration;
 import android.view.DragEvent;
-import android.view.IScrollCaptureController;
+import android.view.IScrollCaptureCallbacks;
 import android.view.IWindow;
 import android.view.IWindowSession;
 import android.view.InsetsSourceControl;
@@ -162,9 +162,9 @@
     }
 
     @Override
-    public void requestScrollCapture(IScrollCaptureController controller) {
+    public void requestScrollCapture(IScrollCaptureCallbacks callbacks) {
         try {
-            controller.onClientUnavailable();
+            callbacks.onUnavailable();
         } catch (RemoteException ex) {
             // ignore
         }
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index ed663cf..a761b4c 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -250,7 +250,7 @@
     // partition that is used to verify if an overlay package fulfills
     // the 'config_signature' policy by comparing their signatures:
     // if the overlay package is signed with the same certificate as
-    // the package declared in 'config-signature' tag, then the
+    // the package declared in 'overlay-config-signature' tag, then the
     // overlay package fulfills the 'config_signature' policy.
     private String mOverlayConfigSignaturePackage;
 
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index e118038..32b8fa6 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -960,17 +960,8 @@
     return IPCThreadState::self()->clearCallingIdentity();
 }
 
-static void android_os_Binder_restoreCallingIdentity(JNIEnv* env, jobject clazz, jlong token)
+static void android_os_Binder_restoreCallingIdentity(jlong token)
 {
-    // XXX temporary validation check to debug crashes.
-    int uid = (int)(token>>32);
-    if (uid > 0 && uid < 999) {
-        // In Android currently there are no uids in this range.
-        char buf[128];
-        sprintf(buf, "Restoring bad calling ident: 0x%" PRIx64, token);
-        jniThrowException(env, "java/lang/IllegalStateException", buf);
-        return;
-    }
     IPCThreadState::self()->restoreCallingIdentity(token);
 }
 
@@ -1064,6 +1055,7 @@
     { "isHandlingTransaction", "()Z", (void*)android_os_Binder_isHandlingTransaction },
     // @CriticalNative
     { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity },
+    // @CriticalNative
     { "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity },
     // @CriticalNative
     { "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy },
diff --git a/core/jni/core_jni_helpers.h b/core/jni/core_jni_helpers.h
index 013c65f..5268049 100644
--- a/core/jni/core_jni_helpers.h
+++ b/core/jni/core_jni_helpers.h
@@ -47,7 +47,7 @@
 static inline jfieldID GetFieldIDOrDie(JNIEnv* env, jclass clazz, const char* field_name,
                                        const char* field_signature) {
     jfieldID res = env->GetFieldID(clazz, field_name, field_signature);
-    LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find static field %s with signature %s", field_name,
+    LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find field %s with signature %s", field_name,
                         field_signature);
     return res;
 }
diff --git a/core/proto/android/telephony/enums.proto b/core/proto/android/telephony/enums.proto
index d2c0ed4..d2c0276 100644
--- a/core/proto/android/telephony/enums.proto
+++ b/core/proto/android/telephony/enums.proto
@@ -91,6 +91,14 @@
     NETWORK_TYPE_NR = 20;
 }
 
+// Roaming type enums, see android.telephony.ServiceState.RoamingType for definitions.
+enum RoamingTypeEnum {
+    ROAMING_TYPE_NOT_ROAMING = 0;
+    ROAMING_TYPE_ROAMING = 1;
+    ROAMING_TYPE_ROAMING_DOMESTIC = 2;
+    ROAMING_TYPE_ROAMING_INTERNATIONAL = 3;
+}
+
 // Signal strength levels, primarily used by android/telephony/SignalStrength.java.
 enum SignalStrengthEnum {
     SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0;
@@ -220,3 +228,43 @@
     // Error over IMS, retry on CS
     SMS_SEND_RESULT_ERROR_FALLBACK = 4;
 }
+
+// Data profile of the data call. From
+// frameworks/base/telephony/java/com/android/internal/telephony/RILConstants.java
+enum DataProfileEnum {
+    DATA_PROFILE_INVALID = -1;
+    DATA_PROFILE_DEFAULT = 0;
+    DATA_PROFILE_TETHERED = 1;
+    DATA_PROFILE_IMS = 2;
+    DATA_PROFILE_FOTA = 3;
+    DATA_PROFILE_CBS = 4;
+    DATA_PROFILE_OEM_BASE = 1000;
+}
+
+// Reason of data call deactivation. From
+// frameworks/base/telephony/java/android/telephony/data/DataService.java#DeactivateDataReason
+enum DataDeactivateReasonEnum {
+    DEACTIVATE_REASON_UNKNOWN = 0;
+    DEACTIVATE_REASON_NORMAL = 1;
+    DEACTIVATE_REASON_RADIO_OFF = 2;
+    DEACTIVATE_REASON_HANDOVER = 3;
+}
+
+// IP type of the data call
+// see frameworks/base/telephony/java/android/telephony/data/ApnSetting.java#ProtocolType
+enum ApnProtocolEnum {
+    APN_PROTOCOL_IPV4 = 0;
+    APN_PROTOCOL_IPV6 = 1;
+    APN_PROTOCOL_IPV4V6 = 2;
+    APN_PROTOCOL_PPP = 3;
+}
+
+// Action taken to recover a data call that is stalled. From
+// frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
+// #RecoveryAction
+enum DataStallRecoveryActionEnum {
+    RECOVERY_ACTION_GET_DATA_CALL_LIST = 0;
+    RECOVERY_ACTION_CLEANUP = 1;
+    RECOVERY_ACTION_REREGISTER = 2;
+    RECOVERY_ACTION_RADIO_RESTART = 3;
+}
\ No newline at end of file
diff --git a/core/proto/android/view/enums.proto b/core/proto/android/view/enums.proto
index 0172e78..a601abe 100644
--- a/core/proto/android/view/enums.proto
+++ b/core/proto/android/view/enums.proto
@@ -60,7 +60,7 @@
     TRANSIT_TASK_OPEN_BEHIND = 16;
     TRANSIT_TASK_IN_PLACE = 17;
     TRANSIT_ACTIVITY_RELAUNCH = 18;
-    TRANSIT_DOCK_TASK_FROM_RECENTS = 19;
+    TRANSIT_DOCK_TASK_FROM_RECENTS = 19 [deprecated=true];
     TRANSIT_KEYGUARD_GOING_AWAY = 20;
     TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER = 21;
     TRANSIT_KEYGUARD_OCCLUDE = 22;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 0a1b8e0..0195451 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2539,8 +2539,7 @@
     <permission android:name="android.permission.START_ANY_ACTIVITY"
         android:protectionLevel="signature" />
 
-    <!-- Allows an application to start activities from background
-         @hide -->
+    <!-- @SystemApi @hide Allows an application to start activities from background -->
     <permission android:name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"
         android:protectionLevel="signature|privileged|vendorPrivileged|oem|verifier" />
 
diff --git a/core/res/res/layout/notification_material_media_transfer_action.xml b/core/res/res/layout/notification_material_media_transfer_action.xml
deleted file mode 100644
index 98d8f1e..0000000
--- a/core/res/res/layout/notification_material_media_transfer_action.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2019 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License
-  -->
-<LinearLayout
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:orientation="horizontal"
-        android:visibility="gone"
-        android:padding="4dp"
-        android:layout_marginStart="10dp"
-        android:gravity="center"
-        android:background="@drawable/media_seamless_background">
-    <ImageView
-        android:layout_width="?attr/notificationHeaderIconSize"
-        android:layout_height="?attr/notificationHeaderIconSize"
-        android:src="@drawable/ic_media_seamless"
-        android:id="@+id/media_seamless_image" />
-    <TextView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textAppearance="?attr/notificationHeaderTextAppearance"
-        android:text="@string/ext_media_seamless_action"
-        android:id="@+id/media_seamless_text"
-        android:paddingEnd="2dp" />
-</LinearLayout>
\ No newline at end of file
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index 9a1b592..88493c9 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -160,9 +160,5 @@
         android:visibility="gone"
         android:contentDescription="@string/notification_work_profile_content_description"
         />
-    <include
-        layout="@layout/notification_material_media_transfer_action"
-        android:id="@+id/media_seamless"
-    />
 </NotificationHeaderView>
 
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index e944cd3..56ca128 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1654,8 +1654,7 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Използване на пряк път"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Инвертиране на цветовете"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Коригиране на цветовете"</string>
-    <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
-    <skip />
+    <string name="reduce_bright_colors_feature_name" msgid="6722364385073799185">"Намаляване на ярките цветове"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Задържахте бутоните за силата на звука. Услугата <xliff:g id="SERVICE_NAME">%1$s</xliff:g> е включена."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Задържахте бутоните за силата на звука. Услугата <xliff:g id="SERVICE_NAME">%1$s</xliff:g> е изключена."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"За да използвате <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, натиснете двата бутона за силата на звука и ги задръжте за 3 секунди"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 869a3bd..d439a7f 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1654,8 +1654,7 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Use Shortcut"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Colour Inversion"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Colour correction"</string>
-    <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
-    <skip />
+    <string name="reduce_bright_colors_feature_name" msgid="6722364385073799185">"Reduce bright colours"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 7738afb..8052ced 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -1654,8 +1654,7 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Use Shortcut"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Colour inversion"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Colour correction"</string>
-    <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
-    <skip />
+    <string name="reduce_bright_colors_feature_name" msgid="6722364385073799185">"Reduce bright colours"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 51b3a2c..45e15c9 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1654,8 +1654,7 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Use Shortcut"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Colour Inversion"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Colour correction"</string>
-    <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
-    <skip />
+    <string name="reduce_bright_colors_feature_name" msgid="6722364385073799185">"Reduce bright colours"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 0476351..9527921 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1654,8 +1654,7 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Use Shortcut"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Colour Inversion"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Color correction"</string>
-    <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
-    <skip />
+    <string name="reduce_bright_colors_feature_name" msgid="6722364385073799185">"Reduce bright colours"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 9c3bd6e..0bb1057 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -1654,8 +1654,7 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‏‏‏‎‏‎‏‏‎‎‎‏‎‎‏‎‎‎‎‎‏‎‏‎‎‎‏‎‎‏‎‏‏‏‎‏‎‎‎‏‏‏‏‎‎‏‎‏‏‏‏‎‎Use Shortcut‎‏‎‎‏‎"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‏‎‎‎‎‏‏‎‎‏‎‏‏‏‎‎‏‏‎‎‏‎‏‎‏‏‎‎‎‎‎‏‎‏‎‏‎‏‏‎‏‏‏‎‏‏‏‏‏‏‎‏‎‏‎‎‎Color Inversion‎‏‎‎‏‎"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‏‏‏‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‎‎‎‏‏‏‏‎‎‎‏‎‎‎‎‎‎‎‏‎‎‎‎‏‏‎‎‎‎‎‎‎‎‏‎‏‎Color Correction‎‏‎‎‏‎"</string>
-    <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
-    <skip />
+    <string name="reduce_bright_colors_feature_name" msgid="6722364385073799185">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‎‏‎‏‎‏‎‏‎‎‎‏‎‏‏‎‎‏‎‏‎‏‎‏‎‎‏‏‏‎‎‎‎‏‏‏‏‏‎‏‎‎‎‎‎‎‎‎‏‎‎‎‏‎Reduce Bright Colors‎‏‎‎‏‎"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‎‎‎‏‏‎‏‎‏‎‎‏‏‏‏‏‎‏‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‎‏‏‏‎Held volume keys. ‎‏‎‎‏‏‎<xliff:g id="SERVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ turned on.‎‏‎‎‏‎"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‏‎‎‏‎‏‎‏‎‎‎‏‎‎‏‏‎‏‎‏‏‎‎‏‏‏‎‎‏‎‏‎‏‏‏‏‎‏‎‏‏‏‎‎‏‎‎‏‎‏‏‎Held volume keys. ‎‏‎‎‏‏‎<xliff:g id="SERVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ turned off.‎‏‎‎‏‎"</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‏‏‎‎‎‎‎‏‏‎‏‎‏‎‎‏‏‎‎‏‏‏‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‏‎‏‎‎‏‎‏‏‏‏‎‎‏‎‎Press and hold both volume keys for three seconds to use ‎‏‎‎‏‏‎<xliff:g id="SERVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 4cba3c9..414addd 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -156,9 +156,9 @@
     <string name="httpErrorOk" msgid="6206751415788256357">"تأیید"</string>
     <string name="httpError" msgid="3406003584150566720">"خطایی در شبکه وجود داشت."</string>
     <string name="httpErrorLookup" msgid="3099834738227549349">"نشانی اینترنتی پیدا نشد."</string>
-    <string name="httpErrorUnsupportedAuthScheme" msgid="3976195595501606787">"‏طرح کلی احراز هویت سایت پشتیبانی نمی‌‎شود."</string>
+    <string name="httpErrorUnsupportedAuthScheme" msgid="3976195595501606787">"‏طرح کلی اصالت‌سنجی سایت پشتیبانی نمی‌‎شود."</string>
     <string name="httpErrorAuth" msgid="469553140922938968">"راستی‌آزمایی ناموفق بود."</string>
-    <string name="httpErrorProxyAuth" msgid="7229662162030113406">"احراز هویت از طریق سرور پروکسی انجام نشد."</string>
+    <string name="httpErrorProxyAuth" msgid="7229662162030113406">"اصالت‌سنجی از طریق سرور پروکسی انجام نشد."</string>
     <string name="httpErrorConnect" msgid="3295081579893205617">"اتصال به سرور انجام نشد."</string>
     <string name="httpErrorIO" msgid="3860318696166314490">"برقراری ارتباط با سرور ممکن نبود. بعداً دوباره امتحان کنید."</string>
     <string name="httpErrorTimeout" msgid="7446272815190334204">"زمان اتصال به سرور تمام شده است."</string>
@@ -529,11 +529,11 @@
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"درخواست پیچیدگی قفل صفحه"</string>
     <string name="permdesc_requestPasswordComplexity" msgid="1130556896836258567">"به برنامه اجازه می‌دهد سطح پیچیدگی قفل صفحه (بالا، متوسط، پایین، یا هیچ‌کدام) را بیاموزد که نشان‌دهنده بازه ممکن طول و نوع قفل صفحه است. همچنین برنامه می‌تواند به کاربران پیشنهاد دهد قفل صفحه را به سطح خاصی به‌روزرسانی کنند، اما کاربران می‌توانند آزادانه این پیشنهاد را نادیده بگیرند و به سطح دیگری بروند. توجه داشته باشید که قفل صفحه در قالب نوشتار ساده ذخیره نمی‌شود، بنابراین برنامه گذرواژه دقیق را نمی‌داند."</string>
     <string name="permlab_useBiometric" msgid="6314741124749633786">"استفاده از سخت‌افزار بیومتریک"</string>
-    <string name="permdesc_useBiometric" msgid="7502858732677143410">"به برنامه امکان می‌دهد از سخت‌افزار بیومتریک برای احراز هویت استفاده کند"</string>
+    <string name="permdesc_useBiometric" msgid="7502858732677143410">"به برنامه امکان می‌دهد از سخت‌افزار بیومتریک برای اصالت‌سنجی استفاده کند"</string>
     <string name="permlab_manageFingerprint" msgid="7432667156322821178">"مدیریت سخت‌افزار اثر انگشت"</string>
     <string name="permdesc_manageFingerprint" msgid="2025616816437339865">"به برنامه امکان می‌دهد روش‌هایی را برای افزودن و حذف الگوهای اثر انگشت جهت استفاده، فعال کند."</string>
     <string name="permlab_useFingerprint" msgid="1001421069766751922">"استفاده از سخت‌افزار اثر انگشت"</string>
-    <string name="permdesc_useFingerprint" msgid="412463055059323742">"به برنامه امکان می‌دهد از سخت‌افزار اثر انگشت برای احراز هویت استفاده کند"</string>
+    <string name="permdesc_useFingerprint" msgid="412463055059323742">"به برنامه امکان می‌دهد از سخت‌افزار اثر انگشت برای اصالت‌سنجی استفاده کند"</string>
     <string name="permlab_audioWrite" msgid="8501705294265669405">"تغییر مجموعه موسیقی شما"</string>
     <string name="permdesc_audioWrite" msgid="8057399517013412431">"به برنامه اجازه می‌دهد مجموعه موسیقی‌تان را تغییر دهد."</string>
     <string name="permlab_videoWrite" msgid="5940738769586451318">"تغییر مجموعه ویدیوی شما"</string>
@@ -544,11 +544,11 @@
     <string name="permdesc_mediaLocation" msgid="597912899423578138">"به برنامه اجازه می‌دهد مکان‌ها را از مجموعه رسانه‌تان بخواند."</string>
     <string name="biometric_dialog_default_title" msgid="55026799173208210">"تأیید کنید این شما هستید"</string>
     <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"سخت‌افزار زیست‌سنجی دردسترس نیست"</string>
-    <string name="biometric_error_user_canceled" msgid="6732303949695293730">"احراز هویت لغو شد"</string>
+    <string name="biometric_error_user_canceled" msgid="6732303949695293730">"اصالت‌سنجی لغو شد"</string>
     <string name="biometric_not_recognized" msgid="5106687642694635888">"شناسایی نشد"</string>
-    <string name="biometric_error_canceled" msgid="8266582404844179778">"احراز هویت لغو شد"</string>
+    <string name="biometric_error_canceled" msgid="8266582404844179778">"اصالت‌سنجی لغو شد"</string>
     <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"پین، الگو یا گذرواژه‌ای تنظیم نشده است"</string>
-    <string name="biometric_error_generic" msgid="6784371929985434439">"خطا هنگام احراز هویت"</string>
+    <string name="biometric_error_generic" msgid="6784371929985434439">"خطا هنگام اصالت‌سنجی"</string>
     <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"بخشی از اثر انگشت شناسایی شد. لطفاً دوباره امتحان کنید."</string>
     <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"اثرانگشت پردازش نشد. لطفاً دوباره امتحان کنید."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"حسگر اثر انگشت کثیف است. لطفاً آن را تمیز کنید و دوباره امتحان نمایید."</string>
@@ -556,9 +556,9 @@
     <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"حرکت انگشت خیلی آهسته بود. لطفاً دوباره امتحان کنید."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_authenticated" msgid="2024862866860283100">"اثر انگشت احراز هویت شد"</string>
-    <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"چهره احراز هویت شد"</string>
-    <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"چهره احراز هویت شد، لطفاً تأیید را فشار دهید"</string>
+    <string name="fingerprint_authenticated" msgid="2024862866860283100">"اثر انگشت اصالت‌سنجی شد"</string>
+    <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"چهره اصالت‌سنجی شد"</string>
+    <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"چهره اصالت‌سنجی شد، لطفاً تأیید را فشار دهید"</string>
     <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"سخت‌افزار اثرانگشت در دسترس نیست."</string>
     <string name="fingerprint_error_no_space" msgid="6126456006769817485">"ذخیره اثر انگشت ممکن نیست. لطفاً یک اثر انگشت موجود را حذف کنید."</string>
     <string name="fingerprint_error_timeout" msgid="2946635815726054226">"درنگ ثبت اثر انگشت به پایان رسید. دوباره امتحان کنید."</string>
@@ -577,7 +577,7 @@
     <string name="permlab_manageFace" msgid="4569549381889283282">"مدیریت سخت‌افزار «بازگشایی با چهره»"</string>
     <string name="permdesc_manageFace" msgid="6204569688492710471">"به برنامه امکان می‌دهد روش‌هایی را برای افزودن و حذف الگوهای چهره جهت استفاده فرابخواند."</string>
     <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"استفاده از سخت‌افزار «بازگشایی با چهره»"</string>
-    <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"به برنامه امکان می‌دهد از سخت‌افزار «بازگشایی با چهره» برای احراز هویت استفاده کند"</string>
+    <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"به برنامه امکان می‌دهد از سخت‌افزار «بازگشایی با چهره» برای اصالت‌سنجی استفاده کند"</string>
     <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"بازگشایی با چهره"</string>
     <string name="face_recalibrate_notification_title" msgid="5944930528030496897">"ثبت مجدد چهره"</string>
     <string name="face_recalibrate_notification_content" msgid="892757485125249962">"برای بهبود تشخیص، لطفاً چهره‌تان را دوباره ثبت کنید"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index ad6df06..1e1d1f9 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -1914,7 +1914,7 @@
     <string name="app_info" msgid="6113278084877079851">"Հավելվածի մասին"</string>
     <string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="demo_starting_message" msgid="6577581216125805905">"Ցուցադրական օգտատերը գործարկվում է…"</string>
-    <string name="demo_restarting_message" msgid="1160053183701746766">"Սարաքը վերակայվում է…"</string>
+    <string name="demo_restarting_message" msgid="1160053183701746766">"Սարքը վերակայվում է…"</string>
     <string name="suspended_widget_accessibility" msgid="6331451091851326101">"Անջատած <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="conference_call" msgid="5731633152336490471">"Կոնֆերանս զանգ"</string>
     <string name="tooltip_popup_title" msgid="7863719020269945722">"Հուշակ"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 1778f5e..060d727 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -1654,8 +1654,7 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"მალსახმობის გამოყენება"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"ფერთა ინვერსია"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"ფერთა კორექცია"</string>
-    <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
-    <skip />
+    <string name="reduce_bright_colors_feature_name" msgid="6722364385073799185">"კაშკაშა ფერების შემცირება"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ხანგრძლივად დააჭირეთ ხმის ღილაკებს. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ჩართულია."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ხანგრძლივად დააჭირეთ ხმის ღილაკებს. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> გამორთულია."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> რომ გამოიყენოთ, დააჭირეთ ხმის ორივე ღილაკზე 3 წამის განმავლობაში"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index b0e14a8..457b74e 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -1654,8 +1654,7 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ໃຊ້ປຸ່ມລັດ"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"ການປີ້ນສີ"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"ການແກ້ໄຂຄ່າສີ"</string>
-    <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
-    <skip />
+    <string name="reduce_bright_colors_feature_name" msgid="6722364385073799185">"ຫຼຸດສີສະຫວ່າງ"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ກົດປຸ່ມລະດັບສຽງຄ້າງໄວ້. ເປີດໃຊ້ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ແລ້ວ."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ກົດປຸ່ມລະດັບສຽງຄ້າງໄວ້. ປິດ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ໄວ້ແລ້ວ."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"ກົດປຸ່ມສຽງທັງສອງພ້ອມກັນຄ້າງໄວ້ສາມວິນາທີເພື່ອໃຊ້ <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index b05a5a4..b9ef667 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -197,7 +197,7 @@
     <string name="country_detector" msgid="7023275114706088854">"कंट्री डिटेक्टर"</string>
     <string name="location_service" msgid="2439187616018455546">"स्थान सेवा"</string>
     <string name="gnss_service" msgid="8907781262179951385">"GNSS सेवा"</string>
-    <string name="sensor_notification_service" msgid="7474531979178682676">"सेंसर सूचना सेवा"</string>
+    <string name="sensor_notification_service" msgid="7474531979178682676">"सेन्सर सूचना सेवा"</string>
     <string name="twilight_service" msgid="8964898045693187224">"ट्वायलाइट सेवा"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"तुमचे डिव्हाइस मिटविले जाईल"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"प्रशासक अ‍ॅप वापरता येणार नाही. तुमचे डिव्हाइस आता साफ केले जाईल.\n\nतुम्हाला कुठलेही प्रश्न असल्यास, तुमच्या संस्थेच्या प्रशासकाशी संपर्क साधा."</string>
@@ -316,7 +316,7 @@
     <string name="permgrouplab_phone" msgid="570318944091926620">"फोन"</string>
     <string name="permgroupdesc_phone" msgid="270048070781478204">"फोन कॉल आणि व्यवस्थापित"</string>
     <string name="permgrouplab_sensors" msgid="9134046949784064495">"शरीर सेन्सर"</string>
-    <string name="permgroupdesc_sensors" msgid="2610631290633747752">"आपल्‍या महत्त्वाच्या मापनांविषयी सेंसर डेटा अ‍ॅक्सेस करा"</string>
+    <string name="permgroupdesc_sensors" msgid="2610631290633747752">"आपल्‍या महत्त्वाच्या मापनांविषयी सेन्सर डेटा अ‍ॅक्सेस करा"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"विंडोमधील आशय पुन्हा मिळवा"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"तुम्ही वापरत असलेल्‍या विंडोमधील आशय तपासा."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"स्पर्श करून अन्वेषण सुरू करा"</string>
@@ -388,7 +388,7 @@
     <string name="permlab_getPackageSize" msgid="375391550792886641">"अ‍ॅप संचयन स्थान मोजा"</string>
     <string name="permdesc_getPackageSize" msgid="742743530909966782">"अ‍ॅप ला त्याचा कोड, डेटा आणि कॅशे    आकार पुनर्प्राप्त करण्यासाठी अनुमती देते"</string>
     <string name="permlab_writeSettings" msgid="8057285063719277394">"सिस्टम सेटिंग्ज सुधारित करा"</string>
-    <string name="permdesc_writeSettings" msgid="8293047411196067188">"सिस्टीमचा सेटिंग्ज डेटा सुधारित करण्यासाठी अ‍ॅप ला अनुमती देते. दुर्भावनापूर्ण अ‍ॅप्स आपल्या सिस्टीमचे कॉन्फिगरेशन दूषित करू शकतात."</string>
+    <string name="permdesc_writeSettings" msgid="8293047411196067188">"सिस्टीमचा सेटिंग्ज डेटा सुधारित करण्यासाठी अ‍ॅप ला अनुमती देते. दुर्भावनापूर्ण अ‍ॅप्स आपल्या सिस्टीमचे कॉंफिगरेशन दूषित करू शकतात."</string>
     <string name="permlab_receiveBootCompleted" msgid="6643339400247325379">"सुरूवातीस चालवा"</string>
     <string name="permdesc_receiveBootCompleted" product="tablet" msgid="5565659082718177484">"जसे सिस्टम बूट करणे समाप्त करते तसे अ‍ॅप ला स्वतः प्रारंभ करण्यास अनुमती देते. यामुळे टॅबलेट प्रारंभ करण्यास वेळ लागू शकतो आणि नेहमी सुरू राहून एकंदर टॅबलेटला धीमे करण्यास अ‍ॅप ला अनुमती देते."</string>
     <string name="permdesc_receiveBootCompleted" product="tv" msgid="4900842256047614307">"सिस्टम बूट होणे संपल्यावर ॲपला स्वतः सुरू होण्याची अनुमती देते. यामुळे तुमच्या Android TV डिव्हाइसला सुरू होण्यास वेळ लागू शकतो आणि नेहमी सुरू राहून एकंदर डिव्हाइसलाच धीमे करण्याची अनुमती ॲपला देते."</string>
@@ -411,7 +411,7 @@
     <string name="permdesc_writeCallLog" product="tablet" msgid="2657525794731690397">"येणार्‍या आणि केल्या जाणार्‍या कॉलविषयीच्या डेटासह, आपल्या टॅब्लेटचा कॉल लॉग सुधारित करण्यासाठी अ‍ॅप ला अनुमती देते. दुर्भावनापूर्ण अ‍ॅप्स तुमचा कॉल लॉग मिटवण्यासाठी किंवा सुधारित करण्यासाठी याचा वापर करू शकतात."</string>
     <string name="permdesc_writeCallLog" product="tv" msgid="3934939195095317432">"येणार्‍या आणि केल्या जाणार्‍या कॉलविषयीच्या डेटासह, तुमच्या Android TV डिव्हाइसचा कॉल लॉग सुधारित करण्यासाठी ॲपला अनुमती देते. दुर्भावनापूर्ण अ‍ॅप्स तुमचा कॉल लॉग मिटवण्यासाठी किंवा सुधारित करण्यासाठी याचा वापर करू शकतात."</string>
     <string name="permdesc_writeCallLog" product="default" msgid="5903033505665134802">"येणार्‍या आणि केल्या जाणार्‍या कॉलविषयीच्या डेटासह, आपल्या फोनचा कॉल लॉग सुधारित करण्यासाठी अ‍ॅप ला अनुमती देते. दुर्भावनापूर्ण अ‍ॅप्स तुमचा कॉल लॉग मिटवण्यासाठी किंवा सुधारित करण्यासाठी याचा वापर करू शकतात."</string>
-    <string name="permlab_bodySensors" msgid="3411035315357380862">"शरीर सेंसर (हृदय गती मॉनिटरसारखे) अ‍ॅक्सेस करा"</string>
+    <string name="permlab_bodySensors" msgid="3411035315357380862">"शरीर सेन्सर (हृदय गती मॉनिटरसारखे) अ‍ॅक्सेस करा"</string>
     <string name="permdesc_bodySensors" product="default" msgid="2365357960407973997">"हृदय गती सारख्या, आपल्या शारीरिक स्थितीचे नियंत्रण करणार्‍या सेन्सरवरून डेटामध्ये प्रवेश करण्यासाठी ॲपला अनुमती देते."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"कॅलेंडर इव्हेंट आणि तपशील वाचा"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"हा अ‍ॅप आपल्या टॅब्लेटवर स्टोअर केलेले सर्व कॅलेंडर इव्हेंट वाचू आणि शेअर करू शकतो किंवा तुमचा कॅलेंडर डेटा सेव्ह करू शकतो."</string>
@@ -565,7 +565,7 @@
     <string name="fingerprint_error_canceled" msgid="540026881380070750">"फिंगरप्रिंट ऑपरेशन रद्द झाले."</string>
     <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"वापरकर्त्याने फिंगरप्रिंट ऑपरेशन रद्द केले."</string>
     <string name="fingerprint_error_lockout" msgid="7853461265604738671">"खूप प्रयत्न केले. नंतर पुन्हा प्रयत्न करा."</string>
-    <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"खूप प्रयत्न करून झाले. फिंगरप्रिंट सेंसर बंद आहे."</string>
+    <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"खूप प्रयत्न करून झाले. फिंगरप्रिंट सेन्सर बंद आहे."</string>
     <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"पुन्हा प्रयत्न करा."</string>
     <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"कोणत्याही फिंगरप्रिंटची नोंद झाली नाही"</string>
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"या डिव्हाइसमध्ये फिंगरप्रिंट सेन्सर नाही."</string>
@@ -657,7 +657,7 @@
     <string name="permlab_bindDreamService" msgid="4776175992848982706">"स्‍वप्न सेवेवर प्रतिबद्ध करा"</string>
     <string name="permdesc_bindDreamService" msgid="9129615743300572973">"होल्‍डरला स्‍वप्नसेवेच्या शीर्ष-स्‍तराच्या इंटरफेसशी प्रतिबद्ध करण्‍यास अनुमती देते. सामान्‍य अ‍ॅप्‍सकरिता कधीही आवश्‍यक नसते."</string>
     <string name="permlab_invokeCarrierSetup" msgid="5098810760209818140">"वाहकाद्वारे-प्रदान केलेल्‍या कॉन्‍फिगरेशन अ‍ॅपची विनंती करा"</string>
-    <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"होल्‍डरला वाहकद्वारे-प्रदान केलेल्या कॉन्फिगरेशन अ‍ॅपची विनंती करण्‍याची अनुमती देते. सामान्‍य अ‍ॅप्‍ससाठी कधीही आवश्‍यक नसावे."</string>
+    <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"होल्‍डरला वाहकद्वारे-प्रदान केलेल्या कॉंफिगरेशन अ‍ॅपची विनंती करण्‍याची अनुमती देते. सामान्‍य अ‍ॅप्‍ससाठी कधीही आवश्‍यक नसावे."</string>
     <string name="permlab_accessNetworkConditions" msgid="1270732533356286514">"नेटवर्क स्‍थितींवरील निरीक्षणांसाठी ऐका"</string>
     <string name="permdesc_accessNetworkConditions" msgid="2959269186741956109">"अनु्प्रयोगाला नेटवर्क स्‍थितींवरील निरीक्षणे ऐकण्‍यासाठी अनुमती देते. सामान्‍य अ‍ॅप्‍ससाठी कधीही आवश्‍यक नसावे."</string>
     <string name="permlab_setInputCalibration" msgid="932069700285223434">"इनपुट डिव्हाइस कॅलिब्रेशन बदला"</string>
@@ -673,7 +673,7 @@
     <string name="permlab_bindCarrierServices" msgid="2395596978626237474">"वाहक सेवांवर प्रतिबद्ध करा"</string>
     <string name="permdesc_bindCarrierServices" msgid="9185614481967262900">"वाहक सेवांवर प्रतिबद्ध करण्यासाठी होल्डरला अनुमती देते. सामान्य ॲप्ससाठी कधीही आवश्यकता नसावी."</string>
     <string name="permlab_access_notification_policy" msgid="5524112842876975537">"व्यत्यय आणू नका अ‍ॅक्सेस करा"</string>
-    <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"व्यत्यय आणू नका कॉन्फिगरेशन वाचण्यासाठी आणि लिहिण्यासाठी ॲपला अनुमती देते."</string>
+    <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"व्यत्यय आणू नका कॉंफिगरेशन वाचण्यासाठी आणि लिहिण्यासाठी ॲपला अनुमती देते."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"व्ह्यू परवानगी वापर सुरू करा"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"धारकास अ‍ॅपसाठी परवानगी वापरणे सुरू करण्याची अनुमती देते. सामान्य अ‍ॅप्ससाठी कधीही आवश्यकता नसते."</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"पासवर्ड नियम सेट करा"</string>
@@ -752,7 +752,7 @@
   </string-array>
     <string name="phoneTypeCustom" msgid="5120365721260686814">"कस्टम"</string>
     <string name="phoneTypeHome" msgid="3880132427643623588">"घर"</string>
-    <string name="phoneTypeMobile" msgid="1178852541462086735">"मोबाईल"</string>
+    <string name="phoneTypeMobile" msgid="1178852541462086735">"मोबाइल"</string>
     <string name="phoneTypeWork" msgid="6604967163358864607">"कार्य"</string>
     <string name="phoneTypeFaxWork" msgid="6757519896109439123">"कार्य फॅक्स"</string>
     <string name="phoneTypeFaxHome" msgid="6678559953115904345">"निवास फॅक्स"</string>
@@ -767,7 +767,7 @@
     <string name="phoneTypeRadio" msgid="2637819130239264771">"रेडिओ"</string>
     <string name="phoneTypeTelex" msgid="2558783611711876562">"टेलेक्स"</string>
     <string name="phoneTypeTtyTdd" msgid="532038552105328779">"TTY TDD"</string>
-    <string name="phoneTypeWorkMobile" msgid="7522314392003565121">"कार्य मोबाईल"</string>
+    <string name="phoneTypeWorkMobile" msgid="7522314392003565121">"कार्य मोबाइल"</string>
     <string name="phoneTypeWorkPager" msgid="3748332310638505234">"कार्य पेजर"</string>
     <string name="phoneTypeAssistant" msgid="757550783842231039">"असिस्टंट"</string>
     <string name="phoneTypeMms" msgid="1799747455131365989">"MMS"</string>
@@ -779,7 +779,7 @@
     <string name="emailTypeHome" msgid="1597116303154775999">"घर"</string>
     <string name="emailTypeWork" msgid="2020095414401882111">"कार्य"</string>
     <string name="emailTypeOther" msgid="5131130857030897465">"अन्य"</string>
-    <string name="emailTypeMobile" msgid="787155077375364230">"मोबाईल"</string>
+    <string name="emailTypeMobile" msgid="787155077375364230">"मोबाइल"</string>
     <string name="postalTypeCustom" msgid="5645590470242939129">"कस्टम"</string>
     <string name="postalTypeHome" msgid="7562272480949727912">"घर"</string>
     <string name="postalTypeWork" msgid="8553425424652012826">"कार्य"</string>
@@ -1273,8 +1273,8 @@
     <string name="sms_control_yes" msgid="4858845109269524622">"अनुमती द्या"</string>
     <string name="sms_control_no" msgid="4845717880040355570">"नकार द्या"</string>
     <string name="sms_short_code_confirm_message" msgid="1385416688897538724">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; हा &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;वर एक मेसेज पाठवू इच्छितो."</string>
-    <string name="sms_short_code_details" msgid="2723725738333388351">"यामुळे आपल्या मोबाईल खात्यावर "<b>"शुल्क आकारले जाऊ शकते"</b>"."</string>
-    <string name="sms_premium_short_code_details" msgid="1400296309866638111"><b>"यामुळे आपल्या मोबाईल खात्यावर शुल्क आकारले जाऊ शकते."</b></string>
+    <string name="sms_short_code_details" msgid="2723725738333388351">"यामुळे आपल्या मोबाइल खात्यावर "<b>"शुल्क आकारले जाऊ शकते"</b>"."</string>
+    <string name="sms_premium_short_code_details" msgid="1400296309866638111"><b>"यामुळे आपल्या मोबाइल खात्यावर शुल्क आकारले जाऊ शकते."</b></string>
     <string name="sms_short_code_confirm_allow" msgid="920477594325526691">"पाठवा"</string>
     <string name="sms_short_code_confirm_deny" msgid="1356917469323768230">"रद्द करा"</string>
     <string name="sms_short_code_remember_choice" msgid="1374526438647744862">"माझी वड लक्षात ठेवा"</string>
@@ -1282,10 +1282,10 @@
     <string name="sms_short_code_confirm_always_allow" msgid="2223014893129755950">"नेहमी अनुमती द्या"</string>
     <string name="sms_short_code_confirm_never_allow" msgid="2688828813521652079">"कधीही अनुमती देऊ नका"</string>
     <string name="sim_removed_title" msgid="5387212933992546283">"सिम कार्ड काढले"</string>
-    <string name="sim_removed_message" msgid="9051174064474904617">"तुम्ही एक वैध सिम कार्ड घालून प्रारंभ करेपर्यंत मोबाईल नेटवर्क अनुपलब्ध असेल."</string>
+    <string name="sim_removed_message" msgid="9051174064474904617">"तुम्ही एक वैध सिम कार्ड घालून प्रारंभ करेपर्यंत मोबाइल नेटवर्क अनुपलब्ध असेल."</string>
     <string name="sim_done_button" msgid="6464250841528410598">"पूर्ण झाले"</string>
     <string name="sim_added_title" msgid="7930779986759414595">"सिम कार्ड जोडले"</string>
-    <string name="sim_added_message" msgid="6602906609509958680">"मोबाईल नेटवर्कवर अ‍ॅक्सेस करण्यासाठी तुमचे डिव्हाइस रीस्टार्ट करा."</string>
+    <string name="sim_added_message" msgid="6602906609509958680">"मोबाइल नेटवर्कवर अ‍ॅक्सेस करण्यासाठी तुमचे डिव्हाइस रीस्टार्ट करा."</string>
     <string name="sim_restart_button" msgid="8481803851341190038">"रीस्टार्ट"</string>
     <string name="install_carrier_app_notification_title" msgid="5712723402213090102">"मोबाइल सेवा अ‍ॅक्टिव्हेट करा"</string>
     <string name="install_carrier_app_notification_text" msgid="2781317581274192728">"तुमचे नवीन सिम अ‍ॅक्टिव्हेट करण्यासाठी वाहकाचे अ‍ॅप डाउनलोड करा"</string>
@@ -1336,7 +1336,7 @@
     <string name="select_input_method" msgid="3971267998568587025">"इनपुट पद्धत निवडा"</string>
     <string name="show_ime" msgid="6406112007347443383">"भौतिक कीबोर्ड सक्रिय असताना त्यास स्क्रीनवर ठेवा"</string>
     <string name="hardware" msgid="1800597768237606953">"व्हर्च्युअल कीबोर्ड दर्शवा"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"वास्तविक कीबोर्ड कॉन्फिगर करा"</string>
+    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"वास्तविक कीबोर्ड कॉंफिगर करा"</string>
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"भाषा आणि लेआउट निवडण्यासाठी टॅप करा"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1916,7 +1916,7 @@
     <string name="demo_starting_message" msgid="6577581216125805905">"डेमो प्रारंभ करत आहे..."</string>
     <string name="demo_restarting_message" msgid="1160053183701746766">"डिव्हाइस रीसेट करत आहे..."</string>
     <string name="suspended_widget_accessibility" msgid="6331451091851326101">"<xliff:g id="LABEL">%1$s</xliff:g> अक्षम केले"</string>
-    <string name="conference_call" msgid="5731633152336490471">"कॉन्फरन्स कॉल"</string>
+    <string name="conference_call" msgid="5731633152336490471">"कॉंफरन्स कॉल"</string>
     <string name="tooltip_popup_title" msgid="7863719020269945722">"टूलटिप"</string>
     <string name="app_category_game" msgid="4534216074910244790">"गेम"</string>
     <string name="app_category_audio" msgid="8296029904794676222">"संगीत आणि ऑडिओ"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index b353085..66a2956 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1654,8 +1654,7 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Usar atalho"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversão de cores"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Correção de cor"</string>
-    <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
-    <skip />
+    <string name="reduce_bright_colors_feature_name" msgid="6722364385073799185">"Reduzir cores brilhantes"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas de volume pressionadas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ativado."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume pressionadas. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desativado."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Toque nos dois botões de volume e os mantenha pressionados por três segundo para usar o <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 321c114..c40eca0 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1654,8 +1654,7 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utilizar atalho"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversão de cores"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Correção da cor"</string>
-    <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
-    <skip />
+    <string name="reduce_bright_colors_feature_name" msgid="6722364385073799185">"Reduzir cores brilhantes"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas do volume premidas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ativado."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume premidas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desativado."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Prima sem soltar as teclas de volume durante três segundos para utilizar o serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index b353085..66a2956 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1654,8 +1654,7 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Usar atalho"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversão de cores"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Correção de cor"</string>
-    <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
-    <skip />
+    <string name="reduce_bright_colors_feature_name" msgid="6722364385073799185">"Reduzir cores brilhantes"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas de volume pressionadas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ativado."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume pressionadas. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desativado."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Toque nos dois botões de volume e os mantenha pressionados por três segundo para usar o <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index bbe3f33..095be18 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -274,8 +274,8 @@
     <string name="notification_channel_security" msgid="8516754650348238057">"سیکیورٹی"</string>
     <string name="notification_channel_car_mode" msgid="2123919247040988436">"کار وضع"</string>
     <string name="notification_channel_account" msgid="6436294521740148173">"اکاؤنٹ اسٹیٹس"</string>
-    <string name="notification_channel_developer" msgid="1691059964407549150">"ڈیولپر کے پیغامات"</string>
-    <string name="notification_channel_developer_important" msgid="7197281908918789589">"اہم ڈیولپر پیغامات"</string>
+    <string name="notification_channel_developer" msgid="1691059964407549150">"ڈویلپر کے پیغامات"</string>
+    <string name="notification_channel_developer_important" msgid="7197281908918789589">"اہم ڈویلپر پیغامات"</string>
     <string name="notification_channel_updates" msgid="7907863984825495278">"اپ ڈیٹس"</string>
     <string name="notification_channel_network_status" msgid="2127687368725272809">"نیٹ ورک اسٹیٹس"</string>
     <string name="notification_channel_network_alerts" msgid="6312366315654526528">"نیٹ ورک الرٹس"</string>
@@ -1218,7 +1218,7 @@
     <string name="dump_heap_ready_notification" msgid="2302452262927390268">"<xliff:g id="PROC">%1$s</xliff:g> ہیپ ڈمپ تیار ہے"</string>
     <string name="dump_heap_notification_detail" msgid="8431586843001054050">"ہیپ ڈمپ جمع ہو گیا ہے۔ اشتراک کرنے کیلئے تھپتھپائیں۔"</string>
     <string name="dump_heap_title" msgid="4367128917229233901">"ہیپ ڈمپ کا اشتراک کریں؟"</string>
-    <string name="dump_heap_text" msgid="1692649033835719336">"<xliff:g id="PROC">%1$s</xliff:g> کارروائی اپنی میموری کی حد <xliff:g id="SIZE">%2$s</xliff:g> سے تجاوز کر گئی ہے۔ آپ کے لیے ایک ہیپ ڈمپ اس کے ڈیولپر کے ساتھ اشتراک کرنے کے لیے دستیاب ہے۔ محتاط رہیں: اس ہیپ ڈمپ میں آپ کی کوئی ایسی ذاتی معلومات بھی شامل ہو سکتی ہے جس تک ایپلیکیشن کو رسائی حاصل ہے۔"</string>
+    <string name="dump_heap_text" msgid="1692649033835719336">"<xliff:g id="PROC">%1$s</xliff:g> کارروائی اپنی میموری کی حد <xliff:g id="SIZE">%2$s</xliff:g> سے تجاوز کر گئی ہے۔ آپ کے لیے ایک ہیپ ڈمپ اس کے ڈویلپر کے ساتھ اشتراک کرنے کے لیے دستیاب ہے۔ محتاط رہیں: اس ہیپ ڈمپ میں آپ کی کوئی ایسی ذاتی معلومات بھی شامل ہو سکتی ہے جس تک ایپلیکیشن کو رسائی حاصل ہے۔"</string>
     <string name="dump_heap_system_text" msgid="6805155514925350849">"<xliff:g id="PROC">%1$s</xliff:g> پروسیس نے اپنی میموری کی حد <xliff:g id="SIZE">%2$s</xliff:g> سے بڑھا لی ہے۔ آپ کے اشتراک کرنے کے لیے ہیپ ڈمپ دستیاب ہے۔ محتاط رہیں: اس ہیپ ڈمپ میں حساس ذاتی معلومات ہو سکتی ہے، جس میں آپ کے ذریعے ٹائپ کردہ چیزیں شامل ہو سکتی ہیں، جس تک پروسیس کو رسائی حاصل ہو سکتی ہے۔"</string>
     <string name="dump_heap_ready_text" msgid="5849618132123045516">"<xliff:g id="PROC">%1$s</xliff:g> کے پروسیس کا ہیپ ڈمپ آپ کے اشتراک کے لیے دستیاب ہے۔ محتاط رہیں: اس ہیپ ڈمپ میں ممکنہ طور پر حساس ذاتی معلومات ہو سکتی ہے، جس میں آپ کے ذریعے ٹائپ کردہ چیزیں شامل ہو سکتی ہیں، جس تک پروسیس کو رسائی حاصل ہو سکتی ہے۔"</string>
     <string name="sendText" msgid="493003724401350724">"متن کیلئے ایک کارروائی منتخب کریں"</string>
@@ -1898,7 +1898,7 @@
     <string name="work_mode_turn_on" msgid="3662561662475962285">"آن کریں"</string>
     <string name="app_blocked_title" msgid="7353262160455028160">"ایپ دستیاب نہیں ہے"</string>
     <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ابھی دستیاب نہیں ہے۔"</string>
-    <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"‏یہ ایپ Android کے پرانے ورژن کے لئے بنائی گئی ہے اور ہو سکتا ہے صحیح طور پر کام نہ کرے۔ اپ ڈیٹس چیک کر کے آزمائیں یا ڈیولپر سے رابطہ کریں۔"</string>
+    <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"‏یہ ایپ Android کے پرانے ورژن کے لئے بنائی گئی ہے اور ہو سکتا ہے صحیح طور پر کام نہ کرے۔ اپ ڈیٹس چیک کر کے آزمائیں یا ڈویلپر سے رابطہ کریں۔"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"اپ ڈیٹ چیک کریں"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"آپ کے پاس نئے پیغامات ہیں"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"‏دیکھنے کیلئے SMS ایپ کھولیں"</string>
diff --git a/core/res/res/values/required_apps_managed_device.xml b/core/res/res/values/required_apps_managed_device.xml
index 40db9df..e17d214 100644
--- a/core/res/res/values/required_apps_managed_device.xml
+++ b/core/res/res/values/required_apps_managed_device.xml
@@ -21,6 +21,7 @@
             Takes precedence over the disallowed apps lists. -->
     <string-array translatable="false" name="required_apps_managed_device">
         <item>com.android.settings</item>
+        <item>com.android.systemui</item>
         <item>com.android.contacts</item>
         <item>com.android.dialer</item>
         <item>com.android.stk</item>  <!-- Required by com.android.phone by certain carriers -->
diff --git a/core/res/res/values/required_apps_managed_profile.xml b/core/res/res/values/required_apps_managed_profile.xml
index c6b37e8..6ed385a 100644
--- a/core/res/res/values/required_apps_managed_profile.xml
+++ b/core/res/res/values/required_apps_managed_profile.xml
@@ -22,6 +22,7 @@
     <string-array translatable="false" name="required_apps_managed_profile">
         <item>com.android.contacts</item>
         <item>com.android.settings</item>
+        <item>com.android.systemui</item>
         <item>com.android.providers.downloads</item>
         <item>com.android.providers.downloads.ui</item>
         <item>com.android.documentsui</item>
diff --git a/core/res/res/values/required_apps_managed_user.xml b/core/res/res/values/required_apps_managed_user.xml
index 8800e535..a6fc573 100644
--- a/core/res/res/values/required_apps_managed_user.xml
+++ b/core/res/res/values/required_apps_managed_user.xml
@@ -21,6 +21,7 @@
             Takes precedence over the disallowed apps lists. -->
     <string-array translatable="false" name="required_apps_managed_user">
         <item>com.android.settings</item>
+        <item>com.android.systemui</item>
         <item>com.android.contacts</item>
         <item>com.android.dialer</item>
         <item>com.android.stk</item>  <!-- Required by com.android.phone by certain carriers -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4ee9123..caa3dff 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -200,9 +200,6 @@
   <java-symbol type="id" name="action2" />
   <java-symbol type="id" name="action3" />
   <java-symbol type="id" name="action4" />
-  <java-symbol type="id" name="media_seamless" />
-  <java-symbol type="id" name="media_seamless_image" />
-  <java-symbol type="id" name="media_seamless_text" />
   <java-symbol type="id" name="notification_media_seekbar_container" />
   <java-symbol type="id" name="notification_media_content" />
   <java-symbol type="id" name="notification_media_progress" />
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index c6ef094..e2b975f 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -54,7 +54,6 @@
         "android.test.mock",
         "framework-atb-backward-compatibility",
         "framework",
-        "icing-java-proto-lite",
         "ext",
         "framework-res",
     ],
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 38dce15..bb826de 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -190,6 +190,17 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="android.widget.CustomInputConnectionEditTextActivity"
+                  android:label="CustomInputConnectionEditTextActivity"
+                  android:screenOrientation="portrait"
+                  android:exported="true"
+                  android:theme="@android:style/Theme.Material.Light">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
         <activity android:name="android.widget.TextViewActivity"
                 android:label="TextViewActivity"
                 android:screenOrientation="portrait"
diff --git a/core/tests/coretests/res/layout/activity_custom_input_connection_edit_text.xml b/core/tests/coretests/res/layout/activity_custom_input_connection_edit_text.xml
new file mode 100644
index 0000000..c4db8be
--- /dev/null
+++ b/core/tests/coretests/res/layout/activity_custom_input_connection_edit_text.xml
@@ -0,0 +1,33 @@
+<?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.
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="vertical"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent">
+
+    <android.widget.CustomInputConnectionEditText
+        android:id="@+id/edittext1"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+
+    <android.widget.CustomInputConnectionEditText
+        android:id="@+id/edittext2"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+
+</LinearLayout>
diff --git a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
index 8412e53..b98ce30 100644
--- a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
+++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
@@ -27,6 +27,7 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -89,6 +90,7 @@
         mInsetsState = new InsetsState();
         mInsetsState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 500, 100));
         mInsetsState.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(400, 0, 500, 500));
+        doNothing().when(mMockController).onRequestedVisibilityChanged(any());
         InsetsSourceConsumer topConsumer = new InsetsSourceConsumer(ITYPE_STATUS_BAR, mInsetsState,
                 () -> mMockTransaction, mMockController);
         topConsumer.setControl(
@@ -130,7 +132,7 @@
     public void testChangeInsets() {
         mController.setInsetsAndAlpha(Insets.of(0, 30, 40, 0), 1f /* alpha */,
                 0f /* fraction */);
-        mController.applyChangeInsets(new InsetsState());
+        mController.applyChangeInsets(null /* outState */);
         assertEquals(Insets.of(0, 30, 40, 0), mController.getCurrentInsets());
         assertEquals(1f, mController.getCurrentAlpha(), 1f - mController.getCurrentAlpha());
 
@@ -150,7 +152,7 @@
     public void testChangeAlphaNoInsets() {
         Insets initialInsets = mController.getCurrentInsets();
         mController.setInsetsAndAlpha(null, 0.5f, 0f /* fraction*/);
-        mController.applyChangeInsets(new InsetsState());
+        mController.applyChangeInsets(null /* outState */);
         assertEquals(0.5f, mController.getCurrentAlpha(), 0.5f - mController.getCurrentAlpha());
         assertEquals(initialInsets, mController.getCurrentInsets());
     }
@@ -158,7 +160,7 @@
     @Test
     public void testChangeInsetsAndAlpha() {
         mController.setInsetsAndAlpha(Insets.of(0, 30, 40, 0), 0.5f, 1f);
-        mController.applyChangeInsets(new InsetsState());
+        mController.applyChangeInsets(null /* outState */);
         assertEquals(0.5f, mController.getCurrentAlpha(), 0.5f - mController.getCurrentAlpha());
         assertEquals(Insets.of(0, 30, 40, 0), mController.getCurrentInsets());
     }
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index cc97eb5..7b84f68c 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -683,71 +683,15 @@
     @Test
     public void testRequestedState() {
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+            final InsetsState state = mTestHost.getRequestedState();
 
-            // The modified state can be controlled when we have control.
-            mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR));
-            mController.hide(statusBars());
-            assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible());
+            mController.hide(statusBars() | navigationBars());
+            assertFalse(state.getSourceOrDefaultVisibility(ITYPE_STATUS_BAR));
+            assertFalse(state.getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
 
-            // The modified state won't be changed while losing control.
-            mController.onControlsChanged(null /* activeControls */);
-            assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible());
-
-            // The modified state won't be changed while state changed while we don't have control.
-            InsetsState newState = new InsetsState(mController.getState(), true /* copySource */);
-            mController.onStateChanged(newState);
-            assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible());
-
-            // The modified state won't be changed while controlling an insets without having the
-            // control.
-            mController.show(statusBars());
-            assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible());
-
-            // The modified state can be updated while gaining control.
-            mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR));
-            assertTrue(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible());
-
-            // The modified state can still be updated if the local state and the requested state
-            // are the same.
-            mController.onControlsChanged(null /* activeControls */);
-            mController.hide(statusBars());
-            newState = new InsetsState(mController.getState(), true /* copySource */);
-            newState.getSource(ITYPE_STATUS_BAR).setVisible(false);
-            mController.onStateChanged(newState);
-            mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR));
-            assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible());
-
-            // The modified state will always be updated while receiving IME control if IME is
-            // requested visible.
-            mController.getSourceConsumer(ITYPE_IME).show(false /* fromIme */);
-            newState = new InsetsState(mController.getState(), true /* copySource */);
-            newState.getSource(ITYPE_IME).setVisible(true);
-            newState.getSource(ITYPE_IME).setFrame(1, 2, 3, 4);
-            mController.onStateChanged(newState);
-            mController.onControlsChanged(createSingletonControl(ITYPE_IME));
-            assertEquals(newState.getSource(ITYPE_IME),
-                    mTestHost.getModifiedState().peekSource(ITYPE_IME));
-            newState = new InsetsState(mController.getState(), true /* copySource */);
-            newState.getSource(ITYPE_IME).setVisible(true);
-            newState.getSource(ITYPE_IME).setFrame(5, 6, 7, 8);
-            mController.onStateChanged(newState);
-            mController.onControlsChanged(createSingletonControl(ITYPE_IME));
-            assertEquals(newState.getSource(ITYPE_IME),
-                    mTestHost.getModifiedState().peekSource(ITYPE_IME));
-
-            // The modified frames cannot be updated if there is an animation.
-            mController.onControlsChanged(createSingletonControl(ITYPE_NAVIGATION_BAR));
-            mController.hide(navigationBars());
-            newState = new InsetsState(mController.getState(), true /* copySource */);
-            newState.getSource(ITYPE_NAVIGATION_BAR).getFrame().top--;
-            mController.onStateChanged(newState);
-            assertNotEquals(newState.getSource(ITYPE_NAVIGATION_BAR),
-                    mTestHost.getModifiedState().peekSource(ITYPE_NAVIGATION_BAR));
-
-            // The modified frames can be updated while the animation is done.
-            mController.cancelExistingAnimations();
-            assertEquals(newState.getSource(ITYPE_NAVIGATION_BAR),
-                    mTestHost.getModifiedState().peekSource(ITYPE_NAVIGATION_BAR));
+            mController.show(statusBars() | navigationBars());
+            assertTrue(state.getSourceOrDefaultVisibility(ITYPE_STATUS_BAR));
+            assertTrue(state.getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
         });
     }
 
@@ -878,7 +822,7 @@
 
     public static class TestHost extends ViewRootInsetsControllerHost {
 
-        private InsetsState mModifiedState = new InsetsState();
+        private final InsetsState mRequestedState = new InsetsState();
 
         TestHost(ViewRootImpl viewRoot) {
             super(viewRoot);
@@ -886,12 +830,12 @@
 
         @Override
         public void onInsetsModified(InsetsState insetsState) {
-            mModifiedState = new InsetsState(insetsState, true /* copySource */);
+            mRequestedState.set(insetsState, true);
             super.onInsetsModified(insetsState);
         }
 
-        public InsetsState getModifiedState() {
-            return mModifiedState;
+        public InsetsState getRequestedState() {
+            return mRequestedState;
         }
     }
 }
diff --git a/core/tests/coretests/src/android/view/ScrollCaptureClientTest.java b/core/tests/coretests/src/android/view/ScrollCaptureConnectionTest.java
similarity index 73%
rename from core/tests/coretests/src/android/view/ScrollCaptureClientTest.java
rename to core/tests/coretests/src/android/view/ScrollCaptureConnectionTest.java
index e6ac2d6..b9cf1e4 100644
--- a/core/tests/coretests/src/android/view/ScrollCaptureClientTest.java
+++ b/core/tests/coretests/src/android/view/ScrollCaptureConnectionTest.java
@@ -47,11 +47,11 @@
 import org.mockito.stubbing.Answer;
 
 /**
- * Tests of {@link ScrollCaptureClient}.
+ * Tests of {@link ScrollCaptureConnection}.
  */
 @SuppressWarnings("UnnecessaryLocalVariable")
 @RunWith(AndroidJUnit4.class)
-public class ScrollCaptureClientTest {
+public class ScrollCaptureConnectionTest {
 
     private final Point mPositionInWindow = new Point(1, 2);
     private final Rect mLocalVisibleRect = new Rect(2, 3, 4, 5);
@@ -63,7 +63,7 @@
     @Mock
     private Surface mSurface;
     @Mock
-    private IScrollCaptureController mClientCallbacks;
+    private IScrollCaptureCallbacks mConnectionCallbacks;
     @Mock
     private View mMockView1;
     @Mock
@@ -86,8 +86,8 @@
     @Test
     public void testDelayedAction() {
         Runnable action = Mockito.mock(Runnable.class);
-        ScrollCaptureClient.DelayedAction delayed =
-                new ScrollCaptureClient.DelayedAction(mHandler, 100, action);
+        ScrollCaptureConnection.DelayedAction delayed =
+                new ScrollCaptureConnection.DelayedAction(mHandler, 100, action);
         try {
             Thread.sleep(200);
         } catch (InterruptedException ex) {
@@ -103,8 +103,8 @@
     @Test
     public void testDelayedAction_cancel() {
         Runnable action = Mockito.mock(Runnable.class);
-        ScrollCaptureClient.DelayedAction delayed =
-                new ScrollCaptureClient.DelayedAction(mHandler, 100, action);
+        ScrollCaptureConnection.DelayedAction delayed =
+                new ScrollCaptureConnection.DelayedAction(mHandler, 100, action);
         try {
             Thread.sleep(50);
         } catch (InterruptedException ex) {
@@ -125,8 +125,8 @@
     @Test
     public void testDelayedAction_timeoutNow() {
         Runnable action = Mockito.mock(Runnable.class);
-        ScrollCaptureClient.DelayedAction delayed =
-                new ScrollCaptureClient.DelayedAction(mHandler, 100, action);
+        ScrollCaptureConnection.DelayedAction delayed =
+                new ScrollCaptureConnection.DelayedAction(mHandler, 100, action);
         try {
             Thread.sleep(50);
         } catch (InterruptedException ex) {
@@ -141,7 +141,7 @@
     /** Test creating a client with valid info */
     @Test
     public void testConstruction() {
-        new ScrollCaptureClient(mTarget1, mClientCallbacks);
+        new ScrollCaptureConnection(mTarget1, mConnectionCallbacks);
     }
 
     /** Test creating a client fails if arguments are not valid. */
@@ -149,7 +149,7 @@
     public void testConstruction_requiresScrollBounds() {
         try {
             mTarget1.setScrollBounds(null);
-            new ScrollCaptureClient(mTarget1, mClientCallbacks);
+            new ScrollCaptureConnection(mTarget1, mConnectionCallbacks);
             fail("An exception was expected.");
         } catch (RuntimeException ex) {
             // Ignore, expected.
@@ -174,48 +174,51 @@
         };
     }
 
-    /** @see ScrollCaptureClient#startCapture(Surface) */
+    /** @see ScrollCaptureConnection#startCapture(Surface) */
     @Test
     public void testStartCapture() throws Exception {
-        final ScrollCaptureClient client = new ScrollCaptureClient(mTarget1, mClientCallbacks);
+        final ScrollCaptureConnection connection = new ScrollCaptureConnection(mTarget1,
+                mConnectionCallbacks);
 
         // Have the session start accepted immediately
         doAnswer(runRunnable(1)).when(mCallback1)
                 .onScrollCaptureStart(any(ScrollCaptureSession.class), any(Runnable.class));
-        client.startCapture(mSurface);
+        connection.startCapture(mSurface);
         getInstrumentation().waitForIdleSync();
 
         verify(mCallback1, times(1))
                 .onScrollCaptureStart(any(ScrollCaptureSession.class), any(Runnable.class));
-        verify(mClientCallbacks, times(1)).onCaptureStarted();
-        verifyNoMoreInteractions(mClientCallbacks);
+        verify(mConnectionCallbacks, times(1)).onCaptureStarted();
+        verifyNoMoreInteractions(mConnectionCallbacks);
     }
 
     @Test
     public void testStartCaptureTimeout() throws Exception {
-        final ScrollCaptureClient client = new ScrollCaptureClient(mTarget1, mClientCallbacks);
-        client.startCapture(mSurface);
+        final ScrollCaptureConnection connection = new ScrollCaptureConnection(mTarget1,
+                mConnectionCallbacks);
+        connection.startCapture(mSurface);
 
         // Force timeout to fire
-        client.getTimeoutAction().timeoutNow();
+        connection.getTimeoutAction().timeoutNow();
 
         getInstrumentation().waitForIdleSync();
         verify(mCallback1, times(1)).onScrollCaptureEnd(any(Runnable.class));
     }
 
-    private void startClient(ScrollCaptureClient client) throws Exception {
+    private void startCapture(ScrollCaptureConnection connection) throws Exception {
         doAnswer(runRunnable(1)).when(mCallback1)
                 .onScrollCaptureStart(any(ScrollCaptureSession.class), any(Runnable.class));
-        client.startCapture(mSurface);
+        connection.startCapture(mSurface);
         getInstrumentation().waitForIdleSync();
-        reset(mCallback1, mClientCallbacks);
+        reset(mCallback1, mConnectionCallbacks);
     }
 
-    /** @see ScrollCaptureClient#requestImage(Rect) */
+    /** @see ScrollCaptureConnection#requestImage(Rect) */
     @Test
     public void testRequestImage() throws Exception {
-        final ScrollCaptureClient client = new ScrollCaptureClient(mTarget1, mClientCallbacks);
-        startClient(client);
+        final ScrollCaptureConnection connection = new ScrollCaptureConnection(mTarget1,
+                mConnectionCallbacks);
+        startCapture(connection);
 
         // Stub the callback to complete the request immediately
         doAnswer(reportBufferSent(/* sessionArg */ 0, /* frameNum */ 1L, new Rect(1, 2, 3, 4)))
@@ -223,7 +226,7 @@
                 .onScrollCaptureImageRequest(any(ScrollCaptureSession.class), any(Rect.class));
 
         // Make the inbound binder call
-        client.requestImage(new Rect(1, 2, 3, 4));
+        connection.requestImage(new Rect(1, 2, 3, 4));
 
         // Wait for handler thread dispatch
         getInstrumentation().waitForIdleSync();
@@ -232,18 +235,20 @@
 
         // Wait for binder thread dispatch
         getInstrumentation().waitForIdleSync();
-        verify(mClientCallbacks, times(1)).onCaptureBufferSent(eq(1L), eq(new Rect(1, 2, 3, 4)));
+        verify(mConnectionCallbacks, times(1))
+                .onCaptureBufferSent(eq(1L), eq(new Rect(1, 2, 3, 4)));
 
-        verifyNoMoreInteractions(mCallback1, mClientCallbacks);
+        verifyNoMoreInteractions(mCallback1, mConnectionCallbacks);
     }
 
     @Test
     public void testRequestImageTimeout() throws Exception {
-        final ScrollCaptureClient client = new ScrollCaptureClient(mTarget1, mClientCallbacks);
-        startClient(client);
+        final ScrollCaptureConnection connection = new ScrollCaptureConnection(mTarget1,
+                mConnectionCallbacks);
+        startCapture(connection);
 
         // Make the inbound binder call
-        client.requestImage(new Rect(1, 2, 3, 4));
+        connection.requestImage(new Rect(1, 2, 3, 4));
 
         // Wait for handler thread dispatch
         getInstrumentation().waitForIdleSync();
@@ -251,20 +256,21 @@
                 any(ScrollCaptureSession.class), eq(new Rect(1, 2, 3, 4)));
 
         // Force timeout to fire
-        client.getTimeoutAction().timeoutNow();
+        connection.getTimeoutAction().timeoutNow();
         getInstrumentation().waitForIdleSync();
 
         // (callback not stubbed, does nothing)
         // Timeout triggers request to end capture
         verify(mCallback1, times(1)).onScrollCaptureEnd(any(Runnable.class));
-        verifyNoMoreInteractions(mCallback1, mClientCallbacks);
+        verifyNoMoreInteractions(mCallback1, mConnectionCallbacks);
     }
 
-    /** @see ScrollCaptureClient#endCapture() */
+    /** @see ScrollCaptureConnection#endCapture() */
     @Test
     public void testEndCapture() throws Exception {
-        final ScrollCaptureClient client = new ScrollCaptureClient(mTarget1, mClientCallbacks);
-        startClient(client);
+        final ScrollCaptureConnection connection = new ScrollCaptureConnection(mTarget1,
+                mConnectionCallbacks);
+        startCapture(connection);
 
         // Stub the callback to complete the request immediately
         doAnswer(runRunnable(0))
@@ -272,7 +278,7 @@
                 .onScrollCaptureEnd(any(Runnable.class));
 
         // Make the inbound binder call
-        client.endCapture();
+        connection.endCapture();
 
         // Wait for handler thread dispatch
         getInstrumentation().waitForIdleSync();
@@ -280,30 +286,31 @@
 
         // Wait for binder thread dispatch
         getInstrumentation().waitForIdleSync();
-        verify(mClientCallbacks, times(1)).onConnectionClosed();
+        verify(mConnectionCallbacks, times(1)).onConnectionClosed();
 
-        verifyNoMoreInteractions(mCallback1, mClientCallbacks);
+        verifyNoMoreInteractions(mCallback1, mConnectionCallbacks);
     }
 
     @Test
     public void testEndCaptureTimeout() throws Exception {
-        final ScrollCaptureClient client = new ScrollCaptureClient(mTarget1, mClientCallbacks);
-        startClient(client);
+        final ScrollCaptureConnection connection = new ScrollCaptureConnection(mTarget1,
+                mConnectionCallbacks);
+        startCapture(connection);
 
         // Make the inbound binder call
-        client.endCapture();
+        connection.endCapture();
 
         // Wait for handler thread dispatch
         getInstrumentation().waitForIdleSync();
         verify(mCallback1, times(1)).onScrollCaptureEnd(any(Runnable.class));
 
         // Force timeout to fire
-        client.getTimeoutAction().timeoutNow();
+        connection.getTimeoutAction().timeoutNow();
 
         // Wait for binder thread dispatch
         getInstrumentation().waitForIdleSync();
-        verify(mClientCallbacks, times(1)).onConnectionClosed();
+        verify(mConnectionCallbacks, times(1)).onConnectionClosed();
 
-        verifyNoMoreInteractions(mCallback1, mClientCallbacks);
+        verifyNoMoreInteractions(mCallback1, mConnectionCallbacks);
     }
 }
diff --git a/core/tests/coretests/src/android/widget/CustomInputConnectionEditText.java b/core/tests/coretests/src/android/widget/CustomInputConnectionEditText.java
new file mode 100644
index 0000000..2dfc53a
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/CustomInputConnectionEditText.java
@@ -0,0 +1,84 @@
+/*
+ * 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.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputConnectionWrapper;
+
+import java.util.Arrays;
+
+/**
+ * An {@link EditText} component that allows customizing its
+ * {@link android.view.inputmethod.InputConnection}.
+ */
+public class CustomInputConnectionEditText extends EditText {
+    private static final String LOG_TAG = "CustomInputConnectionEditText";
+
+    private String[] mContentMimeTypes;
+    private InputConnectionWrapper mInputConnectionWrapper;
+
+    public CustomInputConnectionEditText(Context context) {
+        super(context);
+    }
+
+    public CustomInputConnectionEditText(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public CustomInputConnectionEditText(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public CustomInputConnectionEditText(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    public void setContentMimeTypes(String[] contentMimeTypes) {
+        mContentMimeTypes = contentMimeTypes;
+    }
+
+    public void setInputConnectionWrapper(InputConnectionWrapper inputConnectionWrapper) {
+        mInputConnectionWrapper = inputConnectionWrapper;
+    }
+
+    @Override
+    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
+        InputConnection ic = super.onCreateInputConnection(outAttrs);
+        if (ic == null) {
+            Log.d(LOG_TAG, "Not wrapping InputConnection, because super returned null");
+            return null;
+        }
+        if (mInputConnectionWrapper == null) {
+            Log.d(LOG_TAG, "Not wrapping InputConnection, because wrapper is null");
+            return ic;
+        }
+
+        Log.d(LOG_TAG, "Wrapping InputConnection");
+        mInputConnectionWrapper.setTarget(ic);
+
+        Log.d(LOG_TAG,
+                "Setting EditorInfo.contentMimeTypes: " + Arrays.toString(mContentMimeTypes));
+        outAttrs.contentMimeTypes = mContentMimeTypes;
+
+        return mInputConnectionWrapper;
+    }
+}
diff --git a/core/tests/coretests/src/android/widget/CustomInputConnectionEditTextActivity.java b/core/tests/coretests/src/android/widget/CustomInputConnectionEditTextActivity.java
new file mode 100644
index 0000000..9328a50
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/CustomInputConnectionEditTextActivity.java
@@ -0,0 +1,34 @@
+/*
+ * 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.widget;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.frameworks.coretests.R;
+
+/**
+ * Activity that uses an {@link EditText} component that allows customizing its
+ * {@link android.view.inputmethod.InputConnection}.
+ */
+public class CustomInputConnectionEditTextActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_custom_input_connection_edit_text);
+    }
+}
diff --git a/core/tests/coretests/src/android/widget/TextViewOnReceiveContentCallbackTest.java b/core/tests/coretests/src/android/widget/TextViewOnReceiveContentCallbackTest.java
new file mode 100644
index 0000000..5112326
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/TextViewOnReceiveContentCallbackTest.java
@@ -0,0 +1,262 @@
+/*
+ * 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.widget;
+
+import static android.view.OnReceiveContentCallback.Payload.SOURCE_AUTOFILL;
+import static android.view.OnReceiveContentCallback.Payload.SOURCE_CLIPBOARD;
+import static android.view.OnReceiveContentCallback.Payload.SOURCE_DRAG_AND_DROP;
+import static android.view.OnReceiveContentCallback.Payload.SOURCE_INPUT_METHOD;
+import static android.view.OnReceiveContentCallback.Payload.SOURCE_PROCESS_TEXT;
+import static android.widget.TextViewOnReceiveContentCallback.canReuse;
+import static android.widget.espresso.TextViewActions.clickOnTextAtIndex;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.ClipData;
+import android.content.ClipDescription;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.ArraySet;
+import android.view.OnReceiveContentCallback;
+import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputConnectionWrapper;
+import android.view.inputmethod.InputContentInfo;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.frameworks.coretests.R;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+
+/**
+ * Tests for {@link TextViewOnReceiveContentCallback}. Most of the test cases are in the CTS test
+ * {@link android.widget.cts.TextViewOnReceiveContentCallbackTest}. This class tests some internal
+ * implementation details, e.g. fallback to the keyboard image API.
+ */
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+public class TextViewOnReceiveContentCallbackTest {
+    private static final Uri SAMPLE_CONTENT_URI = Uri.parse("content://com.example/path");
+
+    @Rule
+    public ActivityTestRule<CustomInputConnectionEditTextActivity> mActivityRule =
+            new ActivityTestRule<>(CustomInputConnectionEditTextActivity.class);
+
+    private Instrumentation mInstrumentation;
+    private Activity mActivity;
+    private CustomInputConnectionEditText mEditText;
+    private TextViewOnReceiveContentCallback mDefaultCallback;
+
+    @Before
+    public void before() {
+        mInstrumentation = InstrumentationRegistry.getInstrumentation();
+        mActivity = mActivityRule.getActivity();
+        mEditText = mActivity.findViewById(R.id.edittext2);
+        mDefaultCallback = mEditText.getEditorForTesting().getDefaultOnReceiveContentCallback();
+    }
+
+    @Test
+    public void testGetSupportedMimeTypes_fallbackToCommitContent() throws Throwable {
+        // Configure the EditText with an EditorInfo/InputConnection that supports some image MIME
+        // types.
+        mEditText.setContentMimeTypes(new String[] {"image/gif", "image/png"});
+        MyInputConnection ic = new MyInputConnection();
+        mEditText.setInputConnectionWrapper(ic);
+
+        // Focus into the EditText.
+        onView(withId(mEditText.getId())).perform(clickOnTextAtIndex(0));
+
+        // Assert that the callback returns the MIME types declared in the EditorInfo in addition to
+        // the default.
+        assertThat(mDefaultCallback.getSupportedMimeTypes(mEditText)).containsExactly(
+                "text/*", "image/gif", "image/png");
+    }
+
+    @Test
+    public void testGetSupportedMimeTypes_fallbackToCommitContent_noMimeTypesInEditorInfo()
+            throws Throwable {
+        // Configure the EditText with an EditorInfo/InputConnection that doesn't declare any MIME
+        // types.
+        mEditText.setContentMimeTypes(new String[0]);
+        MyInputConnection ic = new MyInputConnection();
+        mEditText.setInputConnectionWrapper(ic);
+
+        // Focus into the EditText.
+        onView(withId(mEditText.getId())).perform(clickOnTextAtIndex(0));
+
+        // Assert that the callback returns the default MIME types.
+        assertThat(mDefaultCallback.getSupportedMimeTypes(mEditText)).containsExactly("text/*");
+    }
+
+    @Test
+    public void testOnReceive_fallbackToCommitContent() throws Throwable {
+        // Configure the EditText with an EditorInfo/InputConnection that supports some image MIME
+        // types.
+        mEditText.setContentMimeTypes(new String[] {"image/gif", "image/png"});
+        MyInputConnection ic = new MyInputConnection();
+        mEditText.setInputConnectionWrapper(ic);
+
+        // Focus into the EditText.
+        onView(withId(mEditText.getId())).perform(clickOnTextAtIndex(0));
+
+        // Invoke the callback with SOURCE_AUTOFILL and assert that it triggers a call to
+        // InputConnection.commitContent.
+        ClipDescription description = new ClipDescription("", new String[] {"image/gif"});
+        ClipData clip = new ClipData(description, new ClipData.Item(SAMPLE_CONTENT_URI));
+        OnReceiveContentCallback.Payload payload =
+                new OnReceiveContentCallback.Payload.Builder(clip, SOURCE_AUTOFILL).build();
+        mDefaultCallback.onReceiveContent(mEditText, payload);
+        verify(ic.mMock, times(1))
+                .commitContent(any(InputContentInfo.class), eq(0), eq(null));
+        verifyNoMoreInteractions(ic.mMock);
+    }
+
+    @Test
+    public void testOnReceive_fallbackToCommitContent_noMimeTypesInEditorInfo() throws Throwable {
+        // Configure the EditText with an EditorInfo/InputConnection that doesn't declare any MIME
+        // types.
+        mEditText.setContentMimeTypes(new String[0]);
+        MyInputConnection ic = new MyInputConnection();
+        mEditText.setInputConnectionWrapper(ic);
+
+        // Focus into the EditText.
+        onView(withId(mEditText.getId())).perform(clickOnTextAtIndex(0));
+
+        // Invoke the callback and assert that the InputConnection is not invoked.
+        ClipDescription description = new ClipDescription("", new String[] {"image/gif"});
+        ClipData clip = new ClipData(description, new ClipData.Item(SAMPLE_CONTENT_URI));
+        OnReceiveContentCallback.Payload payload =
+                new OnReceiveContentCallback.Payload.Builder(clip, SOURCE_AUTOFILL).build();
+        mDefaultCallback.onReceiveContent(mEditText, payload);
+        verifyZeroInteractions(ic.mMock);
+    }
+
+    @Test
+    public void testOnReceive_fallbackToCommitContent_sourceOtherThanAutofill() throws Throwable {
+        // Configure the EditText with an EditorInfo/InputConnection that supports some image MIME
+        // types.
+        mEditText.setContentMimeTypes(new String[] {"image/gif", "image/png"});
+        MyInputConnection ic = new MyInputConnection();
+        mEditText.setInputConnectionWrapper(ic);
+
+        // Focus into the EditText.
+        onView(withId(mEditText.getId())).perform(clickOnTextAtIndex(0));
+
+        // Invoke the callback with sources other than SOURCE_AUTOFILL and assert that it does NOT
+        // trigger calls to InputConnection.commitContent.
+        ClipDescription description = new ClipDescription("", new String[] {"image/gif"});
+        ClipData clip = new ClipData(description, new ClipData.Item(SAMPLE_CONTENT_URI));
+        OnReceiveContentCallback.Payload payload =
+                new OnReceiveContentCallback.Payload.Builder(clip, SOURCE_CLIPBOARD).build();
+        mDefaultCallback.onReceiveContent(mEditText, payload);
+        verifyZeroInteractions(ic.mMock);
+
+        payload = new OnReceiveContentCallback.Payload.Builder(clip, SOURCE_INPUT_METHOD).build();
+        mDefaultCallback.onReceiveContent(mEditText, payload);
+        verifyZeroInteractions(ic.mMock);
+
+        payload = new OnReceiveContentCallback.Payload.Builder(clip, SOURCE_DRAG_AND_DROP).build();
+        mDefaultCallback.onReceiveContent(mEditText, payload);
+        verifyZeroInteractions(ic.mMock);
+
+        payload = new OnReceiveContentCallback.Payload.Builder(clip, SOURCE_PROCESS_TEXT).build();
+        mDefaultCallback.onReceiveContent(mEditText, payload);
+        verifyZeroInteractions(ic.mMock);
+    }
+
+    @Test
+    public void testCanReuse() throws Throwable {
+        ArraySet<String> mimeTypes = null;
+        String[] editorContentMimeTypes = new String[0];
+        assertThat(canReuse(mimeTypes, editorContentMimeTypes)).isFalse();
+
+        mimeTypes = new ArraySet<>();
+        editorContentMimeTypes = new String[0];
+        assertThat(canReuse(mimeTypes, editorContentMimeTypes)).isTrue();
+
+        mimeTypes = newArraySet("text/*");
+        editorContentMimeTypes = new String[0];
+        assertThat(canReuse(mimeTypes, editorContentMimeTypes)).isTrue();
+
+        mimeTypes = newArraySet("text/*");
+        editorContentMimeTypes = new String[] {"text/*"};
+        assertThat(canReuse(mimeTypes, editorContentMimeTypes)).isTrue();
+
+        mimeTypes = newArraySet("image/gif", "image/png", "text/*");
+        editorContentMimeTypes = new String[] {"image/gif", "image/png"};
+        assertThat(canReuse(mimeTypes, editorContentMimeTypes)).isTrue();
+
+        mimeTypes = newArraySet("image/gif", "image/png", "text/*");
+        editorContentMimeTypes = new String[] {"image/gif", "image/png", "text/*"};
+        assertThat(canReuse(mimeTypes, editorContentMimeTypes)).isTrue();
+
+        mimeTypes = newArraySet("image/gif", "image/png", "text/*");
+        editorContentMimeTypes = new String[] {"image/gif"};
+        assertThat(canReuse(mimeTypes, editorContentMimeTypes)).isFalse();
+
+        mimeTypes = newArraySet("image/gif", "image/png", "text/*");
+        editorContentMimeTypes = new String[] {"image/gif", "image/png", "image/jpg"};
+        assertThat(canReuse(mimeTypes, editorContentMimeTypes)).isFalse();
+
+        mimeTypes = newArraySet("image/gif", "image/png", "text/*");
+        editorContentMimeTypes = new String[] {"image/gif", "image/jpg"};
+        assertThat(canReuse(mimeTypes, editorContentMimeTypes)).isFalse();
+
+        mimeTypes = newArraySet("image/gif", "image/png", "text/*");
+        editorContentMimeTypes = new String[] {"image/gif", "image/jpg", "text/*"};
+        assertThat(canReuse(mimeTypes, editorContentMimeTypes)).isFalse();
+    }
+
+    private static class MyInputConnection extends InputConnectionWrapper {
+        public final InputConnection mMock;
+
+        MyInputConnection() {
+            super(null, true);
+            mMock = Mockito.mock(InputConnection.class);
+        }
+
+        @Override
+        public boolean commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) {
+            mMock.commitContent(inputContentInfo, flags, opts);
+            return true;
+        }
+    }
+
+    @SafeVarargs
+    private static <T> ArraySet<T> newArraySet(T ... elements) {
+        return new ArraySet<>(elements);
+    }
+}
diff --git a/data/etc/car/com.google.android.car.kitchensink.xml b/data/etc/car/com.google.android.car.kitchensink.xml
index 59aa45e..3a20a9c 100644
--- a/data/etc/car/com.google.android.car.kitchensink.xml
+++ b/data/etc/car/com.google.android.car.kitchensink.xml
@@ -44,5 +44,8 @@
         <!-- use for CarServiceTest -->
         <permission name="android.permission.SET_ACTIVITY_WATCHER"/>
         <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
+
+        <!-- use for rotary fragment to enable/disable packages related to rotary -->
+        <permission name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"/>
     </privapp-permissions>
 </permissions>
diff --git a/graphics/java/android/graphics/fonts/Font.java b/graphics/java/android/graphics/fonts/Font.java
index 97cd8ab..586c512 100644
--- a/graphics/java/android/graphics/fonts/Font.java
+++ b/graphics/java/android/graphics/fonts/Font.java
@@ -523,6 +523,9 @@
     /**
      * Returns a font file buffer.
      *
+     * Duplicate before reading values by {@link ByteBuffer#duplicate()} for avoiding unexpected
+     * reading position sharing.
+     *
      * @return a font buffer
      */
     public @NonNull ByteBuffer getBuffer() {
@@ -628,18 +631,49 @@
         if (o == this) {
             return true;
         }
-        if (o == null || !(o instanceof Font)) {
+        if (!(o instanceof Font)) {
             return false;
         }
         Font f = (Font) o;
-        return mFontStyle.equals(f.mFontStyle) && f.mTtcIndex == mTtcIndex
-                && Arrays.equals(f.mAxes, mAxes) && f.mBuffer.equals(mBuffer)
-                && Objects.equals(f.mLocaleList, mLocaleList);
+        boolean paramEqual = mFontStyle.equals(f.mFontStyle) && f.mTtcIndex == mTtcIndex
+                && Arrays.equals(f.mAxes, mAxes) && Objects.equals(f.mLocaleList, mLocaleList)
+                && Objects.equals(mFile, f.mFile);
+
+        if (!paramEqual) {
+            return false;
+        }
+
+        // Shortcut for different font buffer check by comparing size.
+        if (mBuffer.capacity() != f.mBuffer.capacity()) {
+            return false;
+        }
+
+        // ByteBuffer#equals compares all bytes which is not performant for e.g HashMap. Since
+        // underlying native font object holds buffer address, check if this buffer points exactly
+        // the same address as a shortcut of equality. For being compatible with of API30 or before,
+        // check buffer position even if the buffer points the same address.
+        if (nIsSameBufferAddress(mNativePtr, f.mNativePtr)
+                && mBuffer.position() == f.mBuffer.position()) {
+            return true;
+        }
+
+        // Unfortunately, need to compare bytes one-by-one since the buffer may be different font
+        // file but has the same file size, or two font has same content but they are allocated
+        // differently. For being compatible with API30 ore before, compare with ByteBuffer#equals.
+        return mBuffer.equals(f.mBuffer);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mFontStyle, mTtcIndex, Arrays.hashCode(mAxes), mBuffer, mLocaleList);
+        return Objects.hash(
+                mFontStyle,
+                mTtcIndex,
+                Arrays.hashCode(mAxes),
+                // Use Buffer size instead of ByteBuffer#hashCode since ByteBuffer#hashCode traverse
+                // data which is not performant e.g. for HashMap. The hash collision are less likely
+                // happens because it is unlikely happens the different font files has exactly the
+                // same size.
+                mLocaleList);
     }
 
     @Override
@@ -724,4 +758,7 @@
 
     @CriticalNative
     private static native long nGetNativeFontPtr(long ptr);
+
+    @CriticalNative
+    private static native boolean nIsSameBufferAddress(long lFontPtr, long rFontPtr);
 }
diff --git a/keystore/java/android/security/keystore/AttestationUtils.java b/keystore/java/android/security/keystore/AttestationUtils.java
index c8d4be3..f48da74 100644
--- a/keystore/java/android/security/keystore/AttestationUtils.java
+++ b/keystore/java/android/security/keystore/AttestationUtils.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.content.Context;
 import android.os.Build;
 import android.security.KeyStore;
@@ -44,7 +43,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public abstract class AttestationUtils {
     private AttestationUtils() {
     }
diff --git a/keystore/java/android/security/keystore/DeviceIdAttestationException.java b/keystore/java/android/security/keystore/DeviceIdAttestationException.java
index 8ba0317..4f9f9e6 100644
--- a/keystore/java/android/security/keystore/DeviceIdAttestationException.java
+++ b/keystore/java/android/security/keystore/DeviceIdAttestationException.java
@@ -18,7 +18,6 @@
 
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 
 /**
  * Thrown when {@link AttestationUtils} is unable to attest the given device ids.
@@ -26,7 +25,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public class DeviceIdAttestationException extends Exception {
     /**
      * Constructs a new {@code DeviceIdAttestationException} with the current stack trace and the
diff --git a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
index 44744bc..3f6ca0f 100644
--- a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
+++ b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
@@ -1,12 +1,6 @@
 {
   "version": "1.0.0",
   "messages": {
-    "-1823823103": {
-      "message": "Add listener for types=%s listener=%s",
-      "level": "VERBOSE",
-      "group": "WM_SHELL_TASK_ORG",
-      "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
-    },
     "-1683614271": {
       "message": "Existing task: id=%d component=%s",
       "level": "VERBOSE",
@@ -61,6 +55,12 @@
       "group": "WM_SHELL_TASK_ORG",
       "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
     },
+    "481673835": {
+      "message": "addListenerForTaskId taskId=%s",
+      "level": "VERBOSE",
+      "group": "WM_SHELL_TASK_ORG",
+      "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
+    },
     "564235578": {
       "message": "Fullscreen Task Vanished: #%d",
       "level": "VERBOSE",
@@ -78,6 +78,12 @@
       "level": "VERBOSE",
       "group": "WM_SHELL_TASK_ORG",
       "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
+    },
+    "1990759023": {
+      "message": "addListenerForType types=%s listener=%s",
+      "level": "VERBOSE",
+      "group": "WM_SHELL_TASK_ORG",
+      "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
     }
   },
   "groups": {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
index 9d6271b..4cb5fd1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
@@ -16,17 +16,24 @@
 
 package com.android.wm.shell;
 
+import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCREEN;
+import static com.android.wm.shell.ShellTaskOrganizer.taskListenerTypeToString;
+
 import android.app.ActivityManager;
 import android.util.ArraySet;
 import android.util.Slog;
 import android.view.SurfaceControl;
 
+import androidx.annotation.NonNull;
+
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.wm.shell.common.SyncTransactionQueue;
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
 
+import java.io.PrintWriter;
+
 class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
-    private static final String TAG = "FullscreenTaskOrg";
+    private static final String TAG = "FullscreenTaskListener";
 
     private final SyncTransactionQueue mSyncQueue;
 
@@ -74,6 +81,15 @@
     }
 
     @Override
-    public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
+    public void dump(@NonNull PrintWriter pw, String prefix) {
+        final String innerPrefix = prefix + "  ";
+        final String childPrefix = innerPrefix + "  ";
+        pw.println(prefix + this);
+        pw.println(innerPrefix + mTasks.size() + " Tasks");
+    }
+
+    @Override
+    public String toString() {
+        return TAG + ":" + taskListenerTypeToString(TASK_LISTENER_TYPE_FULLSCREEN);
     }
 }
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 d87de5a..9f3c83c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -24,9 +24,13 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 
+import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TASK_ORG;
+
 import android.annotation.IntDef;
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.WindowConfiguration.WindowingMode;
+import android.os.IBinder;
+import android.util.ArrayMap;
 import android.util.Log;
 import android.util.SparseArray;
 import android.view.SurfaceControl;
@@ -43,6 +47,8 @@
 import com.android.wm.shell.common.TransactionPool;
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
 
+import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
@@ -79,14 +85,23 @@
         default void onTaskInfoChanged(RunningTaskInfo taskInfo) {}
         default void onTaskVanished(RunningTaskInfo taskInfo) {}
         default void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {}
+        default void dump(@NonNull PrintWriter pw, String prefix) {};
     }
 
-    private final SparseArray<TaskListener> mTaskListenersByType = new SparseArray<>();
+    /**
+     * Keys map from either a task id or {@link TaskListenerType}.
+     * @see #addListenerForTaskId
+     * @see #addListenerForType
+     */
+    private final SparseArray<TaskListener> mTaskListeners = new SparseArray<>();
 
     // Keeps track of all the tasks reported to this organizer (changes in windowing mode will
     // require us to report to both old and new listeners)
     private final SparseArray<TaskAppearedInfo> mTasks = new SparseArray<>();
 
+    /** @see #setPendingLaunchCookieListener */
+    private final ArrayMap<IBinder, TaskListener> mLaunchCookieToListener = new ArrayMap<>();
+
     // TODO(shell-transitions): move to a more "global" Shell location as this isn't only for Tasks
     private final Transitions mTransitions;
 
@@ -100,7 +115,7 @@
             SyncTransactionQueue syncQueue, TransactionPool transactionPool,
             ShellExecutor mainExecutor, ShellExecutor animExecutor) {
         super(taskOrganizerController);
-        addListener(new FullscreenTaskListener(syncQueue), TASK_LISTENER_TYPE_FULLSCREEN);
+        addListenerForType(new FullscreenTaskListener(syncQueue), TASK_LISTENER_TYPE_FULLSCREEN);
         mTransitions = new Transitions(this, transactionPool, mainExecutor, animExecutor);
         if (Transitions.ENABLE_SHELL_TRANSITIONS) registerTransitionPlayer(mTransitions);
     }
@@ -119,26 +134,43 @@
     }
 
     /**
+     * Adds a listener for a specific task id.
+     */
+    public void addListenerForTaskId(TaskListener listener, int taskId) {
+        ProtoLog.v(WM_SHELL_TASK_ORG, "addListenerForTaskId taskId=%s", taskId);
+        if (mTaskListeners.get(taskId) != null) {
+            throw new IllegalArgumentException("Listener for taskId=" + taskId + " already exists");
+        }
+
+        final TaskAppearedInfo info = mTasks.get(taskId);
+        if (info == null) {
+            throw new IllegalArgumentException("addListenerForTaskId unknown taskId=" + taskId);
+        }
+
+        final TaskListener oldListener = getTaskListener(info.getTaskInfo());
+        mTaskListeners.put(taskId, listener);
+        updateTaskListenerIfNeeded(info.getTaskInfo(), info.getLeash(), oldListener, listener);
+    }
+
+    /**
      * Adds a listener for tasks with given types.
      */
-    public void addListener(TaskListener listener, @TaskListenerType int... taskListenerTypes) {
-        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Add listener for types=%s listener=%s",
-                Arrays.toString(taskListenerTypes), listener);
-        for (int listenerType : taskListenerTypes) {
-            if (mTaskListenersByType.get(listenerType) != null) {
+    public void addListenerForType(TaskListener listener, @TaskListenerType int... listenerTypes) {
+        ProtoLog.v(WM_SHELL_TASK_ORG, "addListenerForType types=%s listener=%s",
+                Arrays.toString(listenerTypes), listener);
+        for (int listenerType : listenerTypes) {
+            if (mTaskListeners.get(listenerType) != null) {
                 throw new IllegalArgumentException("Listener for listenerType=" + listenerType
                         + " already exists");
             }
-            mTaskListenersByType.put(listenerType, listener);
+            mTaskListeners.put(listenerType, listener);
 
             // Notify the listener of all existing tasks with the given type.
-            for (int i = mTasks.size() - 1; i >= 0; i--) {
-                TaskAppearedInfo data = mTasks.valueAt(i);
-                final @TaskListenerType int taskListenerType = getTaskListenerType(
-                        data.getTaskInfo());
-                if (taskListenerType == listenerType) {
-                    listener.onTaskAppeared(data.getTaskInfo(), data.getLeash());
-                }
+            for (int i = mTasks.size() - 1; i >= 0; --i) {
+                final TaskAppearedInfo data = mTasks.valueAt(i);
+                final TaskListener taskListener = getTaskListener(data.getTaskInfo());
+                if (taskListener != listener) continue;
+                listener.onTaskAppeared(data.getTaskInfo(), data.getLeash());
             }
         }
     }
@@ -147,21 +179,47 @@
      * Removes a registered listener.
      */
     public void removeListener(TaskListener listener) {
-        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Remove listener=%s", listener);
-        final int index = mTaskListenersByType.indexOfValue(listener);
+        ProtoLog.v(WM_SHELL_TASK_ORG, "Remove listener=%s", listener);
+        final int index = mTaskListeners.indexOfValue(listener);
         if (index == -1) {
             Log.w(TAG, "No registered listener found");
             return;
         }
-        mTaskListenersByType.removeAt(index);
+
+        // Collect tasks associated with the listener we are about to remove.
+        final ArrayList<TaskAppearedInfo> tasks = new ArrayList<>();
+        for (int i = mTasks.size() - 1; i >= 0; --i) {
+            final TaskAppearedInfo data = mTasks.valueAt(i);
+            final TaskListener taskListener = getTaskListener(data.getTaskInfo());
+            if (taskListener != listener) continue;
+            tasks.add(data);
+        }
+
+        // Remove listener
+        mTaskListeners.removeAt(index);
+
+        // Associate tasks with new listeners if needed.
+        for (int i = tasks.size() - 1; i >= 0; --i) {
+            final TaskAppearedInfo data = tasks.get(i);
+            updateTaskListenerIfNeeded(data.getTaskInfo(), data.getLeash(),
+                    null /* oldListener already removed*/, getTaskListener(data.getTaskInfo()));
+        }
+    }
+
+    /**
+     * Associated a listener to a pending launch cookie so we can route the task later once it
+     * appears.
+     */
+    public void setPendingLaunchCookieListener(IBinder cookie, TaskListener listener) {
+        mLaunchCookieToListener.put(cookie, listener);
     }
 
     @Override
     public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
-        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Task appeared taskId=%d",
-                taskInfo.taskId);
+        ProtoLog.v(WM_SHELL_TASK_ORG, "Task appeared taskId=%d", taskInfo.taskId);
         mTasks.put(taskInfo.taskId, new TaskAppearedInfo(taskInfo, leash));
-        final TaskListener listener = mTaskListenersByType.get(getTaskListenerType(taskInfo));
+        final TaskListener listener =
+                getTaskListener(taskInfo, true /*removeLaunchCookieIfNeeded*/);
         if (listener != null) {
             listener.onTaskAppeared(taskInfo, leash);
         }
@@ -169,37 +227,22 @@
 
     @Override
     public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
-        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Task info changed taskId=%d",
-                taskInfo.taskId);
+        ProtoLog.v(WM_SHELL_TASK_ORG, "Task info changed taskId=%d", taskInfo.taskId);
         final TaskAppearedInfo data = mTasks.get(taskInfo.taskId);
-        final @TaskListenerType int listenerType = getTaskListenerType(taskInfo);
-        final @TaskListenerType int prevListenerType = getTaskListenerType(data.getTaskInfo());
+        final TaskListener oldListener = getTaskListener(data.getTaskInfo());
+        final TaskListener newListener = getTaskListener(taskInfo);
         mTasks.put(taskInfo.taskId, new TaskAppearedInfo(taskInfo, data.getLeash()));
-        if (prevListenerType != listenerType) {
-            // TODO: We currently send vanished/appeared as the task moves between types, but
-            //       we should consider adding a different mode-changed callback
-            TaskListener listener = mTaskListenersByType.get(prevListenerType);
-            if (listener != null) {
-                listener.onTaskVanished(taskInfo);
-            }
-            listener = mTaskListenersByType.get(listenerType);
-            if (listener != null) {
-                SurfaceControl leash = data.getLeash();
-                listener.onTaskAppeared(taskInfo, leash);
-            }
-        } else {
-            final TaskListener listener = mTaskListenersByType.get(listenerType);
-            if (listener != null) {
-                listener.onTaskInfoChanged(taskInfo);
-            }
+        final boolean updated = updateTaskListenerIfNeeded(
+                taskInfo, data.getLeash(), oldListener, newListener);
+        if (!updated && newListener != null) {
+            newListener.onTaskInfoChanged(taskInfo);
         }
     }
 
     @Override
     public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
-        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Task root back pressed taskId=%d",
-                taskInfo.taskId);
-        final TaskListener listener = mTaskListenersByType.get(getTaskListenerType(taskInfo));
+        ProtoLog.v(WM_SHELL_TASK_ORG, "Task root back pressed taskId=%d", taskInfo.taskId);
+        final TaskListener listener = getTaskListener(taskInfo);
         if (listener != null) {
             listener.onBackPressedOnTaskRoot(taskInfo);
         }
@@ -207,22 +250,72 @@
 
     @Override
     public void onTaskVanished(RunningTaskInfo taskInfo) {
-        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Task vanished taskId=%d",
-                taskInfo.taskId);
-        final @TaskListenerType int prevListenerType =
-                getTaskListenerType(mTasks.get(taskInfo.taskId).getTaskInfo());
-        mTasks.remove(taskInfo.taskId);
-        final TaskListener listener = mTaskListenersByType.get(prevListenerType);
+        ProtoLog.v(WM_SHELL_TASK_ORG, "Task vanished taskId=%d", taskInfo.taskId);
+        final int taskId = taskInfo.taskId;
+        final TaskListener listener = getTaskListener(mTasks.get(taskId).getTaskInfo());
+        mTasks.remove(taskId);
         if (listener != null) {
             listener.onTaskVanished(taskInfo);
         }
     }
 
-    @TaskListenerType
-    private static int getTaskListenerType(RunningTaskInfo runningTaskInfo) {
-        // Right now it's N:1 mapping but in the future different task listerners
-        // may be triggered by one windowing mode depending on task parameters.
-        switch (getWindowingMode(runningTaskInfo)) {
+    private boolean updateTaskListenerIfNeeded(RunningTaskInfo taskInfo, SurfaceControl leash,
+            TaskListener oldListener, TaskListener newListener) {
+        if (oldListener == newListener) return false;
+        // TODO: We currently send vanished/appeared as the task moves between types, but
+        //       we should consider adding a different mode-changed callback
+        if (oldListener != null) {
+            oldListener.onTaskVanished(taskInfo);
+        }
+        if (newListener != null) {
+            newListener.onTaskAppeared(taskInfo, leash);
+        }
+        return true;
+    }
+
+    private TaskListener getTaskListener(RunningTaskInfo runningTaskInfo) {
+        return getTaskListener(runningTaskInfo, false /*removeLaunchCookieIfNeeded*/);
+    }
+
+    private TaskListener getTaskListener(RunningTaskInfo runningTaskInfo,
+            boolean removeLaunchCookieIfNeeded) {
+
+        final int taskId = runningTaskInfo.taskId;
+        TaskListener listener;
+
+        // First priority goes to listener that might be pending for this task.
+        final ArrayList<IBinder> launchCookies = runningTaskInfo.launchCookies;
+        for (int i = launchCookies.size() - 1; i >= 0; --i) {
+            final IBinder cookie = launchCookies.get(i);
+            listener = mLaunchCookieToListener.get(cookie);
+            if (listener == null) continue;
+
+            if (removeLaunchCookieIfNeeded) {
+                // Remove the cookie and add the listener.
+                mLaunchCookieToListener.remove(cookie);
+                mTaskListeners.put(taskId, listener);
+            }
+            return listener;
+        }
+
+        // Next priority goes to taskId specific listeners.
+        listener = mTaskListeners.get(taskId);
+        if (listener != null) return listener;
+
+        // Next we try type specific listeners.
+        final int windowingMode = getWindowingMode(runningTaskInfo);
+        final int taskListenerType = windowingModeToTaskListenerType(windowingMode);
+        return mTaskListeners.get(taskListenerType);
+    }
+
+    @WindowingMode
+    private static int getWindowingMode(RunningTaskInfo taskInfo) {
+        return taskInfo.configuration.windowConfiguration.getWindowingMode();
+    }
+
+    private static @TaskListenerType int windowingModeToTaskListenerType(
+            @WindowingMode int windowingMode) {
+        switch (windowingMode) {
             case WINDOWING_MODE_FULLSCREEN:
                 return TASK_LISTENER_TYPE_FULLSCREEN;
             case WINDOWING_MODE_MULTI_WINDOW:
@@ -239,8 +332,50 @@
         }
     }
 
-    @WindowingMode
-    private static int getWindowingMode(RunningTaskInfo taskInfo) {
-        return taskInfo.configuration.windowConfiguration.getWindowingMode();
+    public static String taskListenerTypeToString(@TaskListenerType int type) {
+        switch (type) {
+            case TASK_LISTENER_TYPE_FULLSCREEN:
+                return "TASK_LISTENER_TYPE_FULLSCREEN";
+            case TASK_LISTENER_TYPE_MULTI_WINDOW:
+                return "TASK_LISTENER_TYPE_MULTI_WINDOW";
+            case TASK_LISTENER_TYPE_SPLIT_SCREEN:
+                return "TASK_LISTENER_TYPE_SPLIT_SCREEN";
+            case TASK_LISTENER_TYPE_PIP:
+                return "TASK_LISTENER_TYPE_PIP";
+            case TASK_LISTENER_TYPE_UNDEFINED:
+                return "TASK_LISTENER_TYPE_UNDEFINED";
+            default:
+                return "taskId#" + type;
+        }
+    }
+
+    public void dump(@NonNull PrintWriter pw, String prefix) {
+        final String innerPrefix = prefix + "  ";
+        final String childPrefix = innerPrefix + "  ";
+        pw.println(prefix + TAG);
+        pw.println(innerPrefix + mTaskListeners.size() + " Listeners");
+        for (int i = mTaskListeners.size() - 1; i >= 0; --i) {
+            final int key = mTaskListeners.keyAt(i);
+            final TaskListener listener = mTaskListeners.valueAt(i);
+            pw.println(innerPrefix + "#" + i + " " + taskListenerTypeToString(key));
+            listener.dump(pw, childPrefix);
+        }
+
+        pw.println();
+        pw.println(innerPrefix + mTasks.size() + " Tasks");
+        for (int i = mTasks.size() - 1; i >= 0; --i) {
+            final int key = mTasks.keyAt(i);
+            final TaskAppearedInfo info = mTasks.valueAt(i);
+            final TaskListener listener = getTaskListener(info.getTaskInfo());
+            pw.println(innerPrefix + "#" + i + " task=" + key + " listener=" + listener);
+        }
+
+        pw.println();
+        pw.println(innerPrefix + mLaunchCookieToListener.size() + " Launch Cookies");
+        for (int i = mLaunchCookieToListener.size() - 1; i >= 0; --i) {
+            final IBinder key = mLaunchCookieToListener.keyAt(i);
+            final TaskListener listener = mLaunchCookieToListener.valueAt(i);
+            pw.println(innerPrefix + "#" + i + " cookie=" + key + " listener=" + listener);
+        }
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
index d810fb8..ea18a19 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
@@ -69,11 +69,6 @@
     private final SparseArray<PerDisplay> mImePerDisplay = new SparseArray<>();
     private final ArrayList<ImePositionProcessor> mPositionProcessors = new ArrayList<>();
 
-    @Deprecated
-    public DisplayImeController(IWindowManager wmService, DisplayController displayController,
-            Handler mainHandler, TransactionPool transactionPool) {
-        this(wmService, displayController, mainHandler::post, transactionPool);
-    }
 
     public DisplayImeController(IWindowManager wmService, DisplayController displayController,
             Executor mainExecutor, TransactionPool transactionPool) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
index 17fd16b..eaf5d79 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
@@ -32,7 +32,7 @@
 import android.util.SparseArray;
 import android.view.Display;
 import android.view.DragEvent;
-import android.view.IScrollCaptureController;
+import android.view.IScrollCaptureCallbacks;
 import android.view.IWindow;
 import android.view.IWindowManager;
 import android.view.IWindowSession;
@@ -373,9 +373,9 @@
         public void dispatchPointerCaptureChanged(boolean hasCapture) {}
 
         @Override
-        public void requestScrollCapture(IScrollCaptureController controller) {
+        public void requestScrollCapture(IScrollCaptureCallbacks callbacks) {
             try {
-                controller.onClientUnavailable();
+                callbacks.onUnavailable();
             } catch (RemoteException ex) {
                 // ignore
             }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java
index 488f909..3ded409 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java
@@ -98,7 +98,7 @@
     /**
      * Hides the PIP menu.
      */
-    void hidePipMenu(Runnable onStartCallback, Runnable onEndCallback);
+    default void hidePipMenu(Runnable onStartCallback, Runnable onEndCallback) {}
 
     /**
      * Returns {@code true} if PIP is shown.
@@ -226,7 +226,7 @@
     /**
      * Called when showing Pip menu.
      */
-    void showPictureInPictureMenu();
+    default void showPictureInPictureMenu() {}
 
     /**
      * Suspends resizing operation on the Pip until {@link #resumePipResizing} is called.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsHandler.java
index de3261b..2ab087c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsHandler.java
@@ -22,9 +22,9 @@
 import static android.view.Surface.ROTATION_0;
 import static android.view.Surface.ROTATION_180;
 
+import android.annotation.NonNull;
 import android.app.ActivityTaskManager;
 import android.app.ActivityTaskManager.RootTaskInfo;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Point;
@@ -52,14 +52,11 @@
     private static final String TAG = PipBoundsHandler.class.getSimpleName();
     private static final float INVALID_SNAP_FRACTION = -1f;
 
+    private final @NonNull PipBoundsState mPipBoundsState;
     private final PipSnapAlgorithm mSnapAlgorithm;
     private final DisplayInfo mDisplayInfo = new DisplayInfo();
     private DisplayLayout mDisplayLayout;
 
-    private ComponentName mLastPipComponentName;
-    private float mReentrySnapFraction = INVALID_SNAP_FRACTION;
-    private Size mReentrySize;
-
     private float mDefaultAspectRatio;
     private float mMinAspectRatio;
     private float mMaxAspectRatio;
@@ -75,7 +72,8 @@
     private boolean mIsShelfShowing;
     private int mShelfHeight;
 
-    public PipBoundsHandler(Context context) {
+    public PipBoundsHandler(Context context, @NonNull PipBoundsState pipBoundsState) {
+        mPipBoundsState = pipBoundsState;
         mSnapAlgorithm = new PipSnapAlgorithm(context);
         mDisplayLayout = new DisplayLayout();
         reloadResources(context);
@@ -175,40 +173,6 @@
     }
 
     /**
-     * Responds to IPinnedStackListener on saving reentry snap fraction and size
-     * for a given {@link ComponentName}.
-     */
-    public void onSaveReentryBounds(ComponentName componentName, Rect bounds) {
-        mReentrySnapFraction = getSnapFraction(bounds);
-        mReentrySize = new Size(bounds.width(), bounds.height());
-        mLastPipComponentName = componentName;
-    }
-
-    /**
-     * Responds to IPinnedStackListener on resetting reentry snap fraction and size
-     * for a given {@link ComponentName}.
-     */
-    public void onResetReentryBounds(ComponentName componentName) {
-        if (componentName.equals(mLastPipComponentName)) {
-            onResetReentryBoundsUnchecked();
-        }
-    }
-
-    private void onResetReentryBoundsUnchecked() {
-        mReentrySnapFraction = INVALID_SNAP_FRACTION;
-        mReentrySize = null;
-        mLastPipComponentName = null;
-    }
-
-    /**
-     * Returns ture if there's a valid snap fraction. This is used with {@link EXTRA_IS_FIRST_ENTRY}
-     * to see if this is the first time user has entered PIP for the component.
-     */
-    public boolean hasSaveReentryBounds() {
-        return mReentrySnapFraction != INVALID_SNAP_FRACTION;
-    }
-
-    /**
      * The {@link PipSnapAlgorithm} is couple on display bounds
      * @return {@link PipSnapAlgorithm}.
      */
@@ -250,37 +214,43 @@
     }
 
     /**
-     * See {@link #getDestinationBounds(ComponentName, float, Rect, Size, boolean)}
+     * See {@link #getDestinationBounds(float, Rect, Size, boolean)}
      */
-    public Rect getDestinationBounds(ComponentName componentName, float aspectRatio, Rect bounds,
-            Size minimalSize) {
-        return getDestinationBounds(componentName, aspectRatio, bounds, minimalSize,
+    public Rect getDestinationBounds(float aspectRatio, Rect bounds, Size minimalSize) {
+        return getDestinationBounds(aspectRatio, bounds, minimalSize,
                 false /* useCurrentMinEdgeSize */);
     }
 
     /**
      * @return {@link Rect} of the destination PiP window bounds.
      */
-    public Rect getDestinationBounds(ComponentName componentName, float aspectRatio, Rect bounds,
+    public Rect getDestinationBounds(float aspectRatio, Rect bounds,
             Size minimalSize, boolean useCurrentMinEdgeSize) {
-        if (!componentName.equals(mLastPipComponentName)) {
-            onResetReentryBoundsUnchecked();
-            mLastPipComponentName = componentName;
-        }
+        boolean isReentryBounds = false;
         final Rect destinationBounds;
         if (bounds == null) {
-            final Rect defaultBounds = getDefaultBounds(mReentrySnapFraction, mReentrySize);
-            destinationBounds = new Rect(defaultBounds);
-            if (mReentrySnapFraction == INVALID_SNAP_FRACTION && mReentrySize == null) {
+            // Calculating initial entry bounds
+            final PipBoundsState.PipReentryState state = mPipBoundsState.getReentryState();
+
+            final Rect defaultBounds;
+            if (state != null) {
+                // Restore to reentry bounds.
+                defaultBounds = getDefaultBounds(state.getSnapFraction(), state.getSize());
+                isReentryBounds = true;
+            } else {
+                // Get actual default bounds.
+                defaultBounds = getDefaultBounds(INVALID_SNAP_FRACTION, null /* size */);
                 mOverrideMinimalSize = minimalSize;
             }
+
+            destinationBounds = new Rect(defaultBounds);
         } else {
+            // Just adjusting bounds (e.g. on aspect ratio changed).
             destinationBounds = new Rect(bounds);
         }
         if (isValidPictureInPictureAspectRatio(aspectRatio)) {
-            boolean useCurrentSize = bounds == null && mReentrySize != null;
             transformBoundsToAspectRatio(destinationBounds, aspectRatio, useCurrentMinEdgeSize,
-                    useCurrentSize);
+                    isReentryBounds);
         }
         mAspectRatio = aspectRatio;
         return destinationBounds;
@@ -533,9 +503,6 @@
     public void dump(PrintWriter pw, String prefix) {
         final String innerPrefix = prefix + "  ";
         pw.println(prefix + TAG);
-        pw.println(innerPrefix + "mLastPipComponentName=" + mLastPipComponentName);
-        pw.println(innerPrefix + "mReentrySnapFraction=" + mReentrySnapFraction);
-        pw.println(innerPrefix + "mReentrySize=" + mReentrySize);
         pw.println(innerPrefix + "mDisplayInfo=" + mDisplayInfo);
         pw.println(innerPrefix + "mDefaultAspectRatio=" + mDefaultAspectRatio);
         pw.println(innerPrefix + "mMinAspectRatio=" + mMinAspectRatio);
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 10e5c3d..2625f16 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
@@ -17,9 +17,15 @@
 package com.android.wm.shell.pip;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
 import android.graphics.Rect;
+import android.util.Size;
+
+import com.android.internal.annotations.VisibleForTesting;
 
 import java.io.PrintWriter;
+import java.util.Objects;
 
 /**
  * Singleton source of truth for the current state of PIP bounds.
@@ -28,6 +34,8 @@
     private static final String TAG = PipBoundsState.class.getSimpleName();
 
     private final @NonNull Rect mBounds = new Rect();
+    private PipReentryState mPipReentryState;
+    private ComponentName mLastPipComponentName;
 
     void setBounds(@NonNull Rect bounds) {
         mBounds.set(bounds);
@@ -39,11 +47,83 @@
     }
 
     /**
+     * Save the reentry state to restore to when re-entering PIP mode.
+     *
+     * TODO(b/169373982): consider refactoring this so that this class alone can use mBounds and
+     * calculate the snap fraction to save for re-entry.
+     */
+    public void saveReentryState(@NonNull Rect bounds, float fraction) {
+        mPipReentryState = new PipReentryState(new Size(bounds.width(), bounds.height()), fraction);
+    }
+
+    /**
+     * Returns the saved reentry state.
+     */
+    @Nullable
+    public PipReentryState getReentryState() {
+        return mPipReentryState;
+    }
+
+    /**
+     * Set the last {@link ComponentName} to enter PIP mode.
+     */
+    public void setLastPipComponentName(ComponentName lastPipComponentName) {
+        final boolean changed = !Objects.equals(mLastPipComponentName, lastPipComponentName);
+        mLastPipComponentName = lastPipComponentName;
+        if (changed) {
+            clearReentryState();
+        }
+    }
+
+    public ComponentName getLastPipComponentName() {
+        return mLastPipComponentName;
+    }
+
+    @VisibleForTesting
+    void clearReentryState() {
+        mPipReentryState = null;
+    }
+
+    static final class PipReentryState {
+        private static final String TAG = PipReentryState.class.getSimpleName();
+
+        private final @NonNull Size mSize;
+        private final float mSnapFraction;
+
+        PipReentryState(@NonNull Size size, float snapFraction) {
+            mSize = size;
+            mSnapFraction = snapFraction;
+        }
+
+        @NonNull
+        Size getSize() {
+            return mSize;
+        }
+
+        float getSnapFraction() {
+            return mSnapFraction;
+        }
+
+        void dump(PrintWriter pw, String prefix) {
+            final String innerPrefix = prefix + "  ";
+            pw.println(prefix + TAG);
+            pw.println(innerPrefix + "mSize=" + mSize);
+            pw.println(innerPrefix + "mSnapFraction=" + mSnapFraction);
+        }
+    }
+
+    /**
      * Dumps internal state.
      */
     public void dump(PrintWriter pw, String prefix) {
         final String innerPrefix = prefix + "  ";
         pw.println(prefix + TAG);
         pw.println(innerPrefix + "mBounds=" + mBounds);
+        pw.println(innerPrefix + "mLastPipComponentName=" + mLastPipComponentName);
+        if (mPipReentryState == null) {
+            pw.println(innerPrefix + "mPipReentryState=null");
+        } else {
+            mPipReentryState.dump(pw, innerPrefix);
+        }
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index 15fd424..291af38 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -22,6 +22,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 
 import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_PIP;
+import static com.android.wm.shell.ShellTaskOrganizer.taskListenerTypeToString;
 import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_ALPHA;
 import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_BOUNDS;
 import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_LEAVE_PIP;
@@ -67,6 +68,7 @@
 import com.android.wm.shell.pip.phone.PipMenuActivityController;
 import com.android.wm.shell.pip.phone.PipMotionHelper;
 import com.android.wm.shell.pip.phone.PipUpdateThread;
+import com.android.wm.shell.pip.phone.PipUtils;
 import com.android.wm.shell.splitscreen.SplitScreen;
 
 import java.io.PrintWriter;
@@ -280,7 +282,7 @@
         mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new;
         mSplitScreenOptional = splitScreenOptional;
         mTaskOrganizer = shellTaskOrganizer;
-        mTaskOrganizer.addListener(this, TASK_LISTENER_TYPE_PIP);
+        mTaskOrganizer.addListenerForType(this, TASK_LISTENER_TYPE_PIP);
         displayController.addDisplayWindowListener(this);
     }
 
@@ -329,7 +331,8 @@
             PictureInPictureParams pictureInPictureParams) {
         mShouldIgnoreEnteringPipTransition = true;
         mState = State.ENTERING_PIP;
-        return mPipBoundsHandler.getDestinationBounds(componentName,
+        mPipBoundsState.setLastPipComponentName(componentName);
+        return mPipBoundsHandler.getDestinationBounds(
                 getAspectRatioOrDefault(pictureInPictureParams),
                 null /* bounds */, getMinimalSize(activityInfo));
     }
@@ -400,9 +403,13 @@
                 @Override
                 public void onTransactionReady(int id, SurfaceControl.Transaction t) {
                     t.apply();
-                    scheduleAnimateResizePip(mPipBoundsState.getBounds(),
-                            destinationBounds, getValidSourceHintRect(mTaskInfo, destinationBounds),
-                            direction, animationDurationMs, null /* updateBoundsCallback */);
+                    // Make sure to grab the latest source hint rect as it could have been updated
+                    // right after applying the windowing mode change.
+                    final Rect sourceHintRect = getValidSourceHintRect(mPictureInPictureParams,
+                            destinationBounds);
+                    scheduleAnimateResizePip(mPipBoundsState.getBounds(), destinationBounds,
+                            sourceHintRect, direction, animationDurationMs,
+                            null /* updateBoundsCallback */);
                     mState = State.EXITING_PIP;
                 }
             });
@@ -465,6 +472,7 @@
         mLeash = leash;
         mInitialState.put(mToken.asBinder(), new Configuration(mTaskInfo.configuration));
         mPictureInPictureParams = mTaskInfo.pictureInPictureParams;
+        mPipBoundsState.setLastPipComponentName(mTaskInfo.topActivity);
 
         mPipUiEventLoggerLogger.setTaskInfo(mTaskInfo);
         mPipUiEventLoggerLogger.log(PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_ENTER);
@@ -491,13 +499,14 @@
         }
 
         final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
-                mTaskInfo.topActivity, getAspectRatioOrDefault(mPictureInPictureParams),
+                getAspectRatioOrDefault(mPictureInPictureParams),
                 null /* bounds */, getMinimalSize(mTaskInfo.topActivityInfo));
         Objects.requireNonNull(destinationBounds, "Missing destination bounds");
         final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds();
 
         if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) {
-            final Rect sourceHintRect = getValidSourceHintRect(info, currentBounds);
+            final Rect sourceHintRect = getValidSourceHintRect(info.pictureInPictureParams,
+                    currentBounds);
             scheduleAnimateResizePip(currentBounds, destinationBounds, sourceHintRect,
                     TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration,
                     null /* updateBoundsCallback */);
@@ -514,10 +523,10 @@
      * Returns the source hint rect if it is valid (if provided and is contained by the current
      * task bounds).
      */
-    private Rect getValidSourceHintRect(ActivityManager.RunningTaskInfo info, Rect sourceBounds) {
-        final Rect sourceHintRect = info.pictureInPictureParams != null
-                && info.pictureInPictureParams.hasSourceBoundsHint()
-                ? info.pictureInPictureParams.getSourceRectHint()
+    private Rect getValidSourceHintRect(PictureInPictureParams params, Rect sourceBounds) {
+        final Rect sourceHintRect = params != null
+                && params.hasSourceBoundsHint()
+                ? params.getSourceRectHint()
                 : null;
         if (sourceHintRect != null && sourceBounds.contains(sourceHintRect)) {
             return sourceHintRect;
@@ -686,13 +695,14 @@
     @Override
     public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
         Objects.requireNonNull(mToken, "onTaskInfoChanged requires valid existing mToken");
+        mPipBoundsState.setLastPipComponentName(info.topActivity);
         final PictureInPictureParams newParams = info.pictureInPictureParams;
         if (newParams == null || !applyPictureInPictureParams(newParams)) {
             Log.d(TAG, "Ignored onTaskInfoChanged with PiP param: " + newParams);
             return;
         }
         final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
-                info.topActivity, getAspectRatioOrDefault(newParams),
+                getAspectRatioOrDefault(newParams),
                 mPipBoundsState.getBounds(), getMinimalSize(info.topActivityInfo),
                 true /* userCurrentMinEdgeSize */);
         Objects.requireNonNull(destinationBounds, "Missing destination bounds");
@@ -709,7 +719,7 @@
     public void onFixedRotationFinished(int displayId) {
         if (mShouldDeferEnteringPip && mState.isInPip()) {
             final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
-                    mTaskInfo.topActivity, getAspectRatioOrDefault(mPictureInPictureParams),
+                    getAspectRatioOrDefault(mPictureInPictureParams),
                     null /* bounds */, getMinimalSize(mTaskInfo.topActivityInfo));
             // schedule a regular animation to ensure all the callbacks are still being sent
             enterPipWithAlphaAnimation(destinationBounds, 0 /* durationMs */);
@@ -783,7 +793,7 @@
         }
 
         final Rect newDestinationBounds = mPipBoundsHandler.getDestinationBounds(
-                mTaskInfo.topActivity, getAspectRatioOrDefault(mPictureInPictureParams),
+                getAspectRatioOrDefault(mPictureInPictureParams),
                 null /* bounds */, getMinimalSize(mTaskInfo.topActivityInfo));
         if (newDestinationBounds.equals(currentDestinationBounds)) return;
         if (animator.getAnimationType() == ANIM_TYPE_BOUNDS) {
@@ -1123,6 +1133,7 @@
     /**
      * Dumps internal states.
      */
+    @Override
     public void dump(PrintWriter pw, String prefix) {
         final String innerPrefix = prefix + "  ";
         pw.println(prefix + TAG);
@@ -1140,6 +1151,11 @@
         }
     }
 
+    @Override
+    public String toString() {
+        return TAG + ":" + taskListenerTypeToString(TASK_LISTENER_TYPE_PIP);
+    }
+
     /**
      * Callback interface for PiP transitions (both from and to PiP mode)
      */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index 13f5ac3..a3d21f2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -173,7 +173,13 @@
 
         @Override
         public void onActivityHidden(ComponentName componentName) {
-            mHandler.post(() -> mPipBoundsHandler.onResetReentryBounds(componentName));
+            mHandler.post(() -> {
+                if (componentName.equals(mPipBoundsState.getLastPipComponentName())) {
+                    // The activity was removed, we don't want to restore to the reentry state
+                    // saved for this component anymore.
+                    mPipBoundsState.setLastPipComponentName(null);
+                }
+            });
         }
 
         @Override
@@ -384,7 +390,8 @@
         if (isOutPipDirection(direction)) {
             // Exiting PIP, save the reentry bounds to restore to when re-entering.
             updateReentryBounds(pipBounds);
-            mPipBoundsHandler.onSaveReentryBounds(activity, mReentryBounds);
+            final float snapFraction = mPipBoundsHandler.getSnapFraction(mReentryBounds);
+            mPipBoundsState.saveReentryState(mReentryBounds, snapFraction);
         }
         // Disable touches while the animation is running
         mTouchHandler.setTouchEnabled(false);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMediaController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMediaController.java
index 4a8db6b..22c05fb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMediaController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMediaController.java
@@ -28,7 +28,6 @@
 import android.content.IntentFilter;
 import android.graphics.drawable.Icon;
 import android.media.session.MediaController;
-import android.media.session.MediaSession;
 import android.media.session.MediaSessionManager;
 import android.media.session.PlaybackState;
 import android.os.UserHandle;
@@ -153,8 +152,7 @@
         }
 
         ArrayList<RemoteAction> mediaActions = new ArrayList<>();
-        int state = mMediaController.getPlaybackState().getState();
-        boolean isPlaying = MediaSession.isActiveState(state);
+        boolean isPlaying = mMediaController.getPlaybackState().isActiveState();
         long actions = mMediaController.getPlaybackState().getActions();
 
         // Prev action
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java
index 8660702..f763d6d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java
@@ -24,6 +24,7 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 
 import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_SPLIT_SCREEN;
+import static com.android.wm.shell.ShellTaskOrganizer.taskListenerTypeToString;
 
 import android.app.ActivityManager.RunningTaskInfo;
 import android.graphics.Rect;
@@ -33,8 +34,12 @@
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 
+import androidx.annotation.NonNull;
+
 import com.android.wm.shell.ShellTaskOrganizer;
 
+import java.io.PrintWriter;
+
 class SplitScreenTaskOrganizer implements ShellTaskOrganizer.TaskListener {
     private static final String TAG = "SplitScreenTaskOrg";
     private static final boolean DEBUG = SplitScreenController.DEBUG;
@@ -57,7 +62,7 @@
                     ShellTaskOrganizer shellTaskOrganizer) {
         mSplitScreenController = splitScreenController;
         mTaskOrganizer = shellTaskOrganizer;
-        mTaskOrganizer.addListener(this, TASK_LISTENER_TYPE_SPLIT_SCREEN);
+        mTaskOrganizer.addListenerForType(this, TASK_LISTENER_TYPE_SPLIT_SCREEN);
     }
 
     void init() throws RemoteException {
@@ -229,4 +234,16 @@
             mSplitScreenController.ensureNormalSplit();
         }
     }
+
+    @Override
+    public void dump(@NonNull PrintWriter pw, String prefix) {
+        final String innerPrefix = prefix + "  ";
+        final String childPrefix = innerPrefix + "  ";
+        pw.println(prefix + this);
+    }
+
+    @Override
+    public String toString() {
+        return TAG + ":" + taskListenerTypeToString(TASK_LISTENER_TYPE_SPLIT_SCREEN);
+    }
 }
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 5418a5b..07a6bda 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
@@ -24,8 +24,8 @@
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
 
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
@@ -34,6 +34,8 @@
 
 import android.app.ActivityManager.RunningTaskInfo;
 import android.content.pm.ParceledListSlice;
+import android.os.Binder;
+import android.os.IBinder;
 import android.os.RemoteException;
 import android.view.SurfaceControl;
 import android.window.ITaskOrganizer;
@@ -89,11 +91,6 @@
         public void onTaskVanished(RunningTaskInfo taskInfo) {
             vanished.add(taskInfo);
         }
-
-        @Override
-        public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
-            // Not currently used
-        }
     }
 
     @Before
@@ -116,9 +113,10 @@
 
     @Test
     public void testOneListenerPerType() {
-        mOrganizer.addListener(new TrackingTaskListener(), TASK_LISTENER_TYPE_MULTI_WINDOW);
+        mOrganizer.addListenerForType(new TrackingTaskListener(), TASK_LISTENER_TYPE_MULTI_WINDOW);
         try {
-            mOrganizer.addListener(new TrackingTaskListener(), TASK_LISTENER_TYPE_MULTI_WINDOW);
+            mOrganizer.addListenerForType(
+                    new TrackingTaskListener(), TASK_LISTENER_TYPE_MULTI_WINDOW);
             fail("Expected exception due to already registered listener");
         } catch (Exception e) {
             // Expected failure
@@ -141,7 +139,7 @@
 
         // Check that the tasks are next reported when the listener is added
         TrackingTaskListener listener = new TrackingTaskListener();
-        mOrganizer.addListener(listener, TASK_LISTENER_TYPE_MULTI_WINDOW);
+        mOrganizer.addListenerForType(listener, TASK_LISTENER_TYPE_MULTI_WINDOW);
         assertTrue(listener.appeared.contains(task1));
         assertTrue(listener.appeared.contains(task2));
     }
@@ -150,7 +148,7 @@
     public void testAppearedVanished() {
         RunningTaskInfo taskInfo = createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW);
         TrackingTaskListener listener = new TrackingTaskListener();
-        mOrganizer.addListener(listener, TASK_LISTENER_TYPE_MULTI_WINDOW);
+        mOrganizer.addListenerForType(listener, TASK_LISTENER_TYPE_MULTI_WINDOW);
         mOrganizer.onTaskAppeared(taskInfo, null);
         assertTrue(listener.appeared.contains(taskInfo));
 
@@ -164,7 +162,7 @@
         mOrganizer.onTaskAppeared(taskInfo, null);
 
         TrackingTaskListener listener = new TrackingTaskListener();
-        mOrganizer.addListener(listener, TASK_LISTENER_TYPE_MULTI_WINDOW);
+        mOrganizer.addListenerForType(listener, TASK_LISTENER_TYPE_MULTI_WINDOW);
         assertTrue(listener.appeared.contains(taskInfo));
     }
 
@@ -173,8 +171,8 @@
         RunningTaskInfo taskInfo = createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW);
         TrackingTaskListener mwListener = new TrackingTaskListener();
         TrackingTaskListener pipListener = new TrackingTaskListener();
-        mOrganizer.addListener(mwListener, TASK_LISTENER_TYPE_MULTI_WINDOW);
-        mOrganizer.addListener(pipListener, TASK_LISTENER_TYPE_PIP);
+        mOrganizer.addListenerForType(mwListener, TASK_LISTENER_TYPE_MULTI_WINDOW);
+        mOrganizer.addListenerForType(pipListener, TASK_LISTENER_TYPE_PIP);
         mOrganizer.onTaskAppeared(taskInfo, null);
         assertTrue(mwListener.appeared.contains(taskInfo));
         assertTrue(pipListener.appeared.isEmpty());
@@ -185,6 +183,65 @@
         assertTrue(pipListener.appeared.contains(taskInfo));
     }
 
+    @Test
+    public void testAddListenerForTaskId_afterTypeListener() {
+        RunningTaskInfo task1 = createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW);
+        TrackingTaskListener mwListener = new TrackingTaskListener();
+        TrackingTaskListener task1Listener = new TrackingTaskListener();
+        mOrganizer.addListenerForType(mwListener, TASK_LISTENER_TYPE_MULTI_WINDOW);
+        mOrganizer.onTaskAppeared(task1, null);
+        assertTrue(mwListener.appeared.contains(task1));
+
+        // Add task 1 specific listener
+        mOrganizer.addListenerForTaskId(task1Listener, 1);
+        assertTrue(mwListener.vanished.contains(task1));
+        assertTrue(task1Listener.appeared.contains(task1));
+    }
+
+    @Test
+    public void testAddListenerForTaskId_beforeTypeListener() {
+        RunningTaskInfo task1 = createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW);
+        TrackingTaskListener mwListener = new TrackingTaskListener();
+        TrackingTaskListener task1Listener = new TrackingTaskListener();
+        mOrganizer.onTaskAppeared(task1, null);
+        mOrganizer.addListenerForTaskId(task1Listener, 1);
+        assertTrue(task1Listener.appeared.contains(task1));
+
+        mOrganizer.addListenerForType(mwListener, TASK_LISTENER_TYPE_MULTI_WINDOW);
+        assertFalse(mwListener.appeared.contains(task1));
+    }
+
+    @Test
+    public void testGetTaskListener() {
+        RunningTaskInfo task1 = createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW);
+
+        TrackingTaskListener mwListener = new TrackingTaskListener();
+        mOrganizer.addListenerForType(mwListener, TASK_LISTENER_TYPE_MULTI_WINDOW);
+
+        TrackingTaskListener cookieListener = new TrackingTaskListener();
+        IBinder cookie = new Binder();
+        task1.addLaunchCookie(cookie);
+        mOrganizer.setPendingLaunchCookieListener(cookie, cookieListener);
+
+        // Priority goes to the cookie listener so we would expect the task appear to show up there
+        // instead of the multi-window type listener.
+        mOrganizer.onTaskAppeared(task1, null);
+        assertTrue(cookieListener.appeared.contains(task1));
+        assertFalse(mwListener.appeared.contains(task1));
+
+        TrackingTaskListener task1Listener = new TrackingTaskListener();
+
+        boolean gotException = false;
+        try {
+            mOrganizer.addListenerForTaskId(task1Listener, 1);
+        } catch (Exception e) {
+            gotException = true;
+        }
+        // It should not be possible to add a task id listener for a task already mapped to a
+        // listener through cookie.
+        assertTrue(gotException);
+    }
+
     private RunningTaskInfo createTaskInfo(int taskId, int windowingMode) {
         RunningTaskInfo taskInfo = new RunningTaskInfo();
         taskInfo.taskId = taskId;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsHandlerTest.java
index d9e3148..e0ac8e2 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsHandlerTest.java
@@ -20,7 +20,6 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-import android.content.ComponentName;
 import android.graphics.Rect;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -58,15 +57,13 @@
 
     private PipBoundsHandler mPipBoundsHandler;
     private DisplayInfo mDefaultDisplayInfo;
-    private ComponentName mTestComponentName1;
-    private ComponentName mTestComponentName2;
+    private PipBoundsState mPipBoundsState;
 
     @Before
     public void setUp() throws Exception {
         initializeMockResources();
-        mPipBoundsHandler = new PipBoundsHandler(mContext);
-        mTestComponentName1 = new ComponentName(mContext, "component1");
-        mTestComponentName2 = new ComponentName(mContext, "component2");
+        mPipBoundsState = new PipBoundsState();
+        mPipBoundsHandler = new PipBoundsHandler(mContext, mPipBoundsState);
 
         mPipBoundsHandler.onDisplayInfoChanged(mDefaultDisplayInfo);
     }
@@ -126,8 +123,8 @@
                 (MAX_ASPECT_RATIO + DEFAULT_ASPECT_RATIO) / 2
         };
         for (float aspectRatio : aspectRatios) {
-            final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
-                    mTestComponentName1, aspectRatio, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+            final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(aspectRatio,
+                    EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
             final float actualAspectRatio =
                     destinationBounds.width() / (destinationBounds.height() * 1f);
             assertEquals("Destination bounds matches the given aspect ratio",
@@ -142,8 +139,8 @@
                 MAX_ASPECT_RATIO * 2
         };
         for (float aspectRatio : invalidAspectRatios) {
-            final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
-                    mTestComponentName1, aspectRatio, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+            final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(aspectRatio,
+                    EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
             final float actualAspectRatio =
                     destinationBounds.width() / (destinationBounds.height() * 1f);
             assertEquals("Destination bounds fallbacks to default aspect ratio",
@@ -158,8 +155,8 @@
         final Rect currentBounds = new Rect(0, 0, 0, 100);
         currentBounds.right = (int) (currentBounds.height() * aspectRatio) + currentBounds.left;
 
-        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
-                mTestComponentName1, aspectRatio, currentBounds, EMPTY_MINIMAL_SIZE);
+        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(aspectRatio,
+                currentBounds, EMPTY_MINIMAL_SIZE);
 
         final float actualAspectRatio =
                 destinationBounds.width() / (destinationBounds.height() * 1f);
@@ -182,8 +179,8 @@
         for (int i = 0; i < aspectRatios.length; i++) {
             final float aspectRatio = aspectRatios[i];
             final Size minimalSize = minimalSizes[i];
-            final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
-                    mTestComponentName1, aspectRatio, EMPTY_CURRENT_BOUNDS, minimalSize);
+            final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(aspectRatio,
+                    EMPTY_CURRENT_BOUNDS, minimalSize);
             assertTrue("Destination bounds is no smaller than minimal requirement",
                     (destinationBounds.width() == minimalSize.getWidth()
                             && destinationBounds.height() >= minimalSize.getHeight())
@@ -203,8 +200,8 @@
         currentBounds.right = (int) (currentBounds.height() * aspectRatio) + currentBounds.left;
         final Size minSize = new Size(currentBounds.width() / 2, currentBounds.height() / 2);
 
-        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
-                mTestComponentName1, aspectRatio, currentBounds, minSize);
+        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(aspectRatio,
+                currentBounds, minSize);
 
         assertTrue("Destination bounds ignores minimal size",
                 destinationBounds.width() > minSize.getWidth()
@@ -212,28 +209,44 @@
     }
 
     @Test
-    public void getDestinationBounds_withDifferentComponentName_ignoreLastPosition() {
-        final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
-                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+    public void getDestinationBounds_reentryStateExists_restoreLastSize() {
+        final Rect reentryBounds = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+                EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+        reentryBounds.scale(1.25f);
+        final float reentrySnapFraction = mPipBoundsHandler.getSnapFraction(reentryBounds);
 
-        oldPosition.offset(0, -100);
-        mPipBoundsHandler.onSaveReentryBounds(mTestComponentName1, oldPosition);
+        mPipBoundsState.saveReentryState(reentryBounds, reentrySnapFraction);
+        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+                EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
 
-        final Rect newPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName2,
-                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+        assertEquals(reentryBounds.width(), destinationBounds.width());
+        assertEquals(reentryBounds.height(), destinationBounds.height());
+    }
 
-        assertNonBoundsInclusionWithMargin("ignore saved bounds", oldPosition, newPosition);
+    @Test
+    public void getDestinationBounds_reentryStateExists_restoreLastPosition() {
+        final Rect reentryBounds = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+                EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+        reentryBounds.offset(0, -100);
+        final float reentrySnapFraction = mPipBoundsHandler.getSnapFraction(reentryBounds);
+
+        mPipBoundsState.saveReentryState(reentryBounds, reentrySnapFraction);
+
+        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+                EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+
+        assertBoundsInclusionWithMargin("restoreLastPosition", reentryBounds, destinationBounds);
     }
 
     @Test
     public void setShelfHeight_offsetBounds() {
         final int shelfHeight = 100;
-        final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
-                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+        final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+                EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
 
         mPipBoundsHandler.setShelfHeight(true, shelfHeight);
-        final Rect newPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
-                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+        final Rect newPosition = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+                EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
 
         oldPosition.offset(0, -shelfHeight);
         assertBoundsInclusionWithMargin("offsetBounds by shelf", oldPosition, newPosition);
@@ -242,92 +255,30 @@
     @Test
     public void onImeVisibilityChanged_offsetBounds() {
         final int imeHeight = 100;
-        final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
-                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+        final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+                EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
 
         mPipBoundsHandler.onImeVisibilityChanged(true, imeHeight);
-        final Rect newPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
-                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+        final Rect newPosition = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+                EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
 
         oldPosition.offset(0, -imeHeight);
         assertBoundsInclusionWithMargin("offsetBounds by IME", oldPosition, newPosition);
     }
 
     @Test
-    public void onSaveReentryBounds_restoreLastPosition() {
-        final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
-                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+    public void getDestinationBounds_noReentryState_useDefaultBounds() {
+        final Rect defaultBounds = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+                EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
 
-        oldPosition.offset(0, -100);
-        mPipBoundsHandler.onSaveReentryBounds(mTestComponentName1, oldPosition);
+        mPipBoundsState.clearReentryState();
 
-        final Rect newPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
-                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
-
-        assertBoundsInclusionWithMargin("restoreLastPosition", oldPosition, newPosition);
-    }
-
-    @Test
-    public void onSaveReentryBounds_restoreLastSize() {
-        final Rect oldSize = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
-                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
-
-        oldSize.scale(1.25f);
-        mPipBoundsHandler.onSaveReentryBounds(mTestComponentName1, oldSize);
-
-        final Rect newSize = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
-                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
-
-        assertEquals(oldSize.width(), newSize.width());
-        assertEquals(oldSize.height(), newSize.height());
-    }
-
-    @Test
-    public void onResetReentryBounds_useDefaultBounds() {
-        final Rect defaultBounds = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
-                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
-        final Rect newBounds = new Rect(defaultBounds);
-        newBounds.offset(0, -100);
-        mPipBoundsHandler.onSaveReentryBounds(mTestComponentName1, newBounds);
-
-        mPipBoundsHandler.onResetReentryBounds(mTestComponentName1);
-        final Rect actualBounds = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
-                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+        final Rect actualBounds = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+                EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
 
         assertBoundsInclusionWithMargin("useDefaultBounds", defaultBounds, actualBounds);
     }
 
-    @Test
-    public void onResetReentryBounds_componentMismatch_restoreLastPosition() {
-        final Rect defaultBounds = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
-                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
-        final Rect newBounds = new Rect(defaultBounds);
-        newBounds.offset(0, -100);
-        mPipBoundsHandler.onSaveReentryBounds(mTestComponentName1, newBounds);
-
-        mPipBoundsHandler.onResetReentryBounds(mTestComponentName2);
-        final Rect actualBounds = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
-                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
-
-        assertBoundsInclusionWithMargin("restoreLastPosition", newBounds, actualBounds);
-    }
-
-    @Test
-    public void onSaveReentryBounds_componentMismatch_restoreLastSize() {
-        final Rect oldSize = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
-                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
-
-        oldSize.scale(1.25f);
-        mPipBoundsHandler.onSaveReentryBounds(mTestComponentName1, oldSize);
-
-        mPipBoundsHandler.onResetReentryBounds(mTestComponentName2);
-        final Rect newSize = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
-                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
-
-        assertEquals(oldSize.width(), newSize.width());
-        assertEquals(oldSize.height(), newSize.height());
-    }
-
     private void assertBoundsInclusionWithMargin(String from, Rect expected, Rect actual) {
         final Rect expectedWithMargin = new Rect(expected);
         expectedWithMargin.inset(-ROUNDING_ERROR_MARGIN, -ROUNDING_ERROR_MARGIN);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java
new file mode 100644
index 0000000..dc9399e
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.wm.shell.pip;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import android.content.ComponentName;
+import android.graphics.Rect;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.util.Size;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link PipBoundsState}.
+ */
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+@SmallTest
+public class PipBoundsStateTest extends PipTestCase {
+
+    private static final Rect DEFAULT_BOUNDS = new Rect(0, 0, 10, 10);
+    private static final float DEFAULT_SNAP_FRACTION = 1.0f;
+
+    private PipBoundsState mPipBoundsState;
+    private ComponentName mTestComponentName1;
+    private ComponentName mTestComponentName2;
+
+    @Before
+    public void setUp() {
+        mPipBoundsState = new PipBoundsState();
+        mTestComponentName1 = new ComponentName(mContext, "component1");
+        mTestComponentName2 = new ComponentName(mContext, "component2");
+    }
+
+    @Test
+    public void testSetBounds() {
+        final Rect bounds = new Rect(0, 0, 100, 100);
+        mPipBoundsState.setBounds(bounds);
+
+        assertEquals(bounds, mPipBoundsState.getBounds());
+    }
+
+    @Test
+    public void testSetReentryState() {
+        final Rect bounds = new Rect(0, 0, 100, 100);
+        final float snapFraction = 0.5f;
+
+        mPipBoundsState.saveReentryState(bounds, snapFraction);
+
+        final PipBoundsState.PipReentryState state = mPipBoundsState.getReentryState();
+        assertEquals(new Size(100, 100), state.getSize());
+        assertEquals(snapFraction, state.getSnapFraction(), 0.01);
+    }
+
+    @Test
+    public void testClearReentryState() {
+        final Rect bounds = new Rect(0, 0, 100, 100);
+        final float snapFraction = 0.5f;
+
+        mPipBoundsState.saveReentryState(bounds, snapFraction);
+        mPipBoundsState.clearReentryState();
+
+        assertNull(mPipBoundsState.getReentryState());
+    }
+
+    @Test
+    public void testSetLastPipComponentName_notChanged_doesNotClearReentryState() {
+        mPipBoundsState.setLastPipComponentName(mTestComponentName1);
+        mPipBoundsState.saveReentryState(DEFAULT_BOUNDS, DEFAULT_SNAP_FRACTION);
+
+        mPipBoundsState.setLastPipComponentName(mTestComponentName1);
+
+        final PipBoundsState.PipReentryState state = mPipBoundsState.getReentryState();
+        assertNotNull(state);
+        assertEquals(new Size(DEFAULT_BOUNDS.width(), DEFAULT_BOUNDS.height()), state.getSize());
+        assertEquals(DEFAULT_SNAP_FRACTION, state.getSnapFraction(), 0.01);
+    }
+
+    @Test
+    public void testSetLastPipComponentName_changed_clearReentryState() {
+        mPipBoundsState.setLastPipComponentName(mTestComponentName1);
+        mPipBoundsState.saveReentryState(DEFAULT_BOUNDS, DEFAULT_SNAP_FRACTION);
+
+        mPipBoundsState.setLastPipComponentName(mTestComponentName2);
+
+        assertNull(mPipBoundsState.getReentryState());
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTaskOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
similarity index 86%
rename from libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTaskOrganizerTest.java
rename to libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
index 46ebbf3..54543d2 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTaskOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wm.shell.pip.phone;
+package com.android.wm.shell.pip;
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -27,12 +27,6 @@
 
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.common.DisplayController;
-import com.android.wm.shell.pip.PipBoundsHandler;
-import com.android.wm.shell.pip.PipBoundsState;
-import com.android.wm.shell.pip.PipSurfaceTransactionHelper;
-import com.android.wm.shell.pip.PipTaskOrganizer;
-import com.android.wm.shell.pip.PipTestCase;
-import com.android.wm.shell.pip.PipUiEventLogger;
 import com.android.wm.shell.splitscreen.SplitScreen;
 
 import org.junit.Before;
@@ -70,7 +64,7 @@
 
     @Test
     public void instantiatePipTaskOrganizer_addsTaskListener() {
-        verify(mMockShellTaskOrganizer).addListener(any(), anyInt());
+        verify(mMockShellTaskOrganizer).addListenerForType(any(), anyInt());
     }
 
     @Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java
index 4713142..3f60cc0 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java
@@ -93,7 +93,7 @@
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
         mPipBoundsState = new PipBoundsState();
-        mPipBoundsHandler = new PipBoundsHandler(mContext);
+        mPipBoundsHandler = new PipBoundsHandler(mContext, mPipBoundsState);
         mPipSnapAlgorithm = mPipBoundsHandler.getSnapAlgorithm();
         mPipSnapAlgorithm = new PipSnapAlgorithm(mContext);
         mPipTouchHandler = new PipTouchHandler(mContext, mPipMenuActivityController,
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index 8ab7da5..903ca2a 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -155,11 +155,12 @@
         android: {
             srcs: [
                 "tests/BackupData_test.cpp",
-		"tests/BackupHelpers_test.cpp",
+                "tests/BackupHelpers_test.cpp",
+                "tests/CursorWindow_test.cpp",
                 "tests/ObbFile_test.cpp",
                 "tests/PosixUtils_test.cpp",
             ],
-            shared_libs: common_test_libs + ["libui"],
+            shared_libs: common_test_libs + ["libbinder", "liblog", "libui"],
         },
         host: {
             static_libs: common_test_libs + ["liblog", "libz"],
@@ -185,9 +186,28 @@
         // Actual benchmarks.
         "tests/AssetManager2_bench.cpp",
         "tests/AttributeResolution_bench.cpp",
+        "tests/CursorWindow_bench.cpp",
         "tests/SparseEntry_bench.cpp",
         "tests/Theme_bench.cpp",
     ],
     shared_libs: common_test_libs,
     data: ["tests/data/**/*.apk"],
 }
+
+cc_library {
+    name: "libandroidfw_fuzzer_lib",
+    defaults: ["libandroidfw_defaults"],
+    host_supported: true,
+    srcs: [
+        "CursorWindow.cpp",
+    ],
+    export_include_dirs: ["include"],
+    target: {
+        android: {
+            shared_libs: common_test_libs + ["libbinder", "liblog"],
+        },
+        host: {
+            static_libs: common_test_libs + ["libbinder", "liblog"],
+        },
+    },
+}
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index b9765ea..99dd313 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -39,10 +39,8 @@
 namespace android {
 
 struct FindEntryResult {
-  // A pointer to the resource table entry for this resource.
-  // If the size of the entry is > sizeof(ResTable_entry), it can be cast to
-  // a ResTable_map_entry and processed as a bag/map.
-  ResTable_entry_handle entry;
+  // A pointer to the value of the resource table entry.
+  std::variant<Res_value, const ResTable_map_entry*> entry;
 
   // The configuration for which the resulting entry was defined. This is already swapped to host
   // endianness.
@@ -554,11 +552,9 @@
       if (!overlay_entry) {
         // No id map entry exists for this target resource.
         continue;
-      }
-
-      if (overlay_entry.IsTableEntry()) {
+      } else if (overlay_entry.IsInlineValue()) {
         // The target resource is overlaid by an inline value not represented by a resource.
-        out_entry->entry = overlay_entry.GetTableEntry();
+        out_entry->entry = overlay_entry.GetInlineValue();
         out_entry->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable();
         cookie = id_map.cookie;
         continue;
@@ -580,7 +576,7 @@
       }
 
       cookie = overlay_cookie;
-      out_entry->entry = std::move(overlay_result.entry);
+      out_entry->entry = overlay_result.entry;
       out_entry->config = overlay_result.config;
       out_entry->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable();
       if (resource_resolution_logging_enabled_) {
@@ -761,7 +757,19 @@
     return kInvalidCookie;
   }
 
-  out_entry->entry = ResTable_entry_handle::unmanaged(best_entry);
+  const uint16_t entry_size = dtohs(best_entry->size);
+  if (entry_size >= sizeof(ResTable_map_entry) &&
+      (dtohs(best_entry->flags) & ResTable_entry::FLAG_COMPLEX)) {
+    // The entry represents a bag/map.
+    out_entry->entry = reinterpret_cast<const ResTable_map_entry*>(best_entry);
+  } else {
+    // The entry represents a value.
+    Res_value value;
+    value.copyFrom_dtoh(*reinterpret_cast<const Res_value*>(
+        reinterpret_cast<const uint8_t*>(best_entry) + entry_size));
+    out_entry->entry = value;
+  }
+
   out_entry->config = *best_config;
   out_entry->type_flags = type_flags;
   out_entry->package_name = &best_package->GetPackageName();
@@ -905,8 +913,8 @@
     return kInvalidCookie;
   }
 
-  const ResTable_entry* table_entry = *entry.entry;
-  if (dtohs(table_entry->flags) & ResTable_entry::FLAG_COMPLEX) {
+  auto result_map_entry = std::get_if<const ResTable_map_entry*>(&entry.entry);
+  if (result_map_entry != nullptr) {
     if (!may_be_bag) {
       LOG(ERROR) << base::StringPrintf("Resource %08x is a complex map type.", resid);
       return kInvalidCookie;
@@ -920,11 +928,8 @@
     return cookie;
   }
 
-  const Res_value* device_value = reinterpret_cast<const Res_value*>(
-      reinterpret_cast<const uint8_t*>(table_entry) + dtohs(table_entry->size));
-  out_value->copyFrom_dtoh(*device_value);
-
   // Convert the package ID to the runtime assigned package ID.
+  *out_value = std::get<Res_value>(entry.entry);
   entry.dynamic_ref_table->lookupResourceValue(out_value);
 
   *out_selected_config = entry.config;
@@ -1004,19 +1009,15 @@
     return nullptr;
   }
 
-  // Check that the size of the entry header is at least as big as
-  // the desired ResTable_map_entry. Also verify that the entry
-  // was intended to be a map.
-  const ResTable_entry* table_entry = *entry.entry;
-  if (dtohs(table_entry->size) < sizeof(ResTable_map_entry) ||
-      (dtohs(table_entry->flags) & ResTable_entry::FLAG_COMPLEX) == 0) {
+  auto result_map_entry = std::get_if<const ResTable_map_entry*>(&entry.entry);
+  if (result_map_entry == nullptr) {
     // Not a bag, nothing to do.
     return nullptr;
   }
 
-  const ResTable_map_entry* map = reinterpret_cast<const ResTable_map_entry*>(table_entry);
-  const ResTable_map* map_entry =
-      reinterpret_cast<const ResTable_map*>(reinterpret_cast<const uint8_t*>(map) + map->size);
+  auto map = reinterpret_cast<const ResTable_map_entry*>(*result_map_entry);
+  auto map_entry = reinterpret_cast<const ResTable_map*>(
+      reinterpret_cast<const uint8_t*>(map) + map->size);
   const ResTable_map* const map_entry_end = map_entry + dtohl(map->count);
 
   // Keep track of ids that have already been seen to prevent infinite loops caused by circular
diff --git a/libs/androidfw/CursorWindow.cpp b/libs/androidfw/CursorWindow.cpp
index 71c8e1f..915c0d7 100644
--- a/libs/androidfw/CursorWindow.cpp
+++ b/libs/androidfw/CursorWindow.cpp
@@ -14,19 +14,14 @@
  * limitations under the License.
  */
 
-#undef LOG_TAG
 #define LOG_TAG "CursorWindow"
 
 #include <androidfw/CursorWindow.h>
-#include <binder/Parcel.h>
-#include <utils/Log.h>
 
-#include <cutils/ashmem.h>
 #include <sys/mman.h>
 
-#include <assert.h>
-#include <string.h>
-#include <stdlib.h>
+#include "android-base/logging.h"
+#include "cutils/ashmem.h"
 
 namespace android {
 
@@ -36,11 +31,10 @@
  */
 static constexpr const size_t kInlineSize = 16384;
 
-CursorWindow::CursorWindow(const String8& name, int ashmemFd, void* data, size_t size,
-                           size_t inflatedSize, bool readOnly) :
-        mName(name), mAshmemFd(ashmemFd), mData(data), mSize(size),
-        mInflatedSize(inflatedSize), mReadOnly(readOnly) {
-    mHeader = static_cast<Header*>(mData);
+static constexpr const size_t kSlotShift = 4;
+static constexpr const size_t kSlotSizeBytes = 1 << kSlotShift;
+
+CursorWindow::CursorWindow() {
 }
 
 CursorWindow::~CursorWindow() {
@@ -52,234 +46,243 @@
     }
 }
 
-status_t CursorWindow::create(const String8& name, size_t inflatedSize,
-                              CursorWindow** outCursorWindow) {
-    *outCursorWindow = nullptr;
+status_t CursorWindow::create(const String8 &name, size_t inflatedSize, CursorWindow **outWindow) {
+    *outWindow = nullptr;
 
-    size_t size = std::min(kInlineSize, inflatedSize);
-    void* data = calloc(size, 1);
-    if (!data) return NO_MEMORY;
+    CursorWindow* window = new CursorWindow();
+    if (!window) goto fail;
 
-    CursorWindow* window = new CursorWindow(name, -1, data, size,
-                                            inflatedSize, false /*readOnly*/);
-    status_t result = window->clear();
-    if (!result) {
-        LOG_WINDOW("Created new CursorWindow: freeOffset=%d, "
-                "numRows=%d, numColumns=%d, mSize=%zu, mData=%p",
-                window->mHeader->freeOffset,
-                window->mHeader->numRows,
-                window->mHeader->numColumns,
-                window->mSize, window->mData);
-        *outCursorWindow = window;
-        return OK;
-    }
+    window->mName = name;
+    window->mSize = std::min(kInlineSize, inflatedSize);
+    window->mInflatedSize = inflatedSize;
+    window->mData = malloc(window->mSize);
+    if (!window->mData) goto fail;
+    window->mReadOnly = false;
+
+    window->clear();
+    window->updateSlotsData();
+
+    LOG(DEBUG) << "Created: " << window->toString();
+    *outWindow = window;
+    return OK;
+
+fail:
+    LOG(ERROR) << "Failed create";
+fail_silent:
     delete window;
-    return result;
+    return UNKNOWN_ERROR;
 }
 
-status_t CursorWindow::inflate() {
-    // Shortcut when we can't expand any further
-    if (mSize == mInflatedSize) return INVALID_OPERATION;
+status_t CursorWindow::maybeInflate() {
+    int ashmemFd = 0;
+    void* newData = nullptr;
+
+    // Bail early when we can't expand any further
+    if (mReadOnly || mSize == mInflatedSize) {
+        return INVALID_OPERATION;
+    }
 
     String8 ashmemName("CursorWindow: ");
     ashmemName.append(mName);
 
-    status_t result;
-    int ashmemFd = ashmem_create_region(ashmemName.string(), mInflatedSize);
+    ashmemFd = ashmem_create_region(ashmemName.string(), mInflatedSize);
     if (ashmemFd < 0) {
-        result = -errno;
-        ALOGE("CursorWindow: ashmem_create_region() failed: errno=%d.", errno);
-    } else {
-        result = ashmem_set_prot_region(ashmemFd, PROT_READ | PROT_WRITE);
-        if (result < 0) {
-            ALOGE("CursorWindow: ashmem_set_prot_region() failed: errno=%d",errno);
-        } else {
-            void* data = ::mmap(NULL, mInflatedSize, PROT_READ | PROT_WRITE,
-                                MAP_SHARED, ashmemFd, 0);
-            if (data == MAP_FAILED) {
-                result = -errno;
-                ALOGE("CursorWindow: mmap() failed: errno=%d.", errno);
-            } else {
-                result = ashmem_set_prot_region(ashmemFd, PROT_READ);
-                if (result < 0) {
-                    ALOGE("CursorWindow: ashmem_set_prot_region() failed: errno=%d.", errno);
-                } else {
-                    // Move inline contents into new ashmem region
-                    memcpy(data, mData, mSize);
-                    free(mData);
-                    mAshmemFd = ashmemFd;
-                    mData = data;
-                    mHeader = static_cast<Header*>(mData);
-                    mSize = mInflatedSize;
-                    LOG_WINDOW("Inflated CursorWindow: freeOffset=%d, "
-                            "numRows=%d, numColumns=%d, mSize=%zu, mData=%p",
-                            mHeader->freeOffset,
-                            mHeader->numRows,
-                            mHeader->numColumns,
-                            mSize, mData);
-                    return OK;
-                }
-            }
-            ::munmap(data, mInflatedSize);
-        }
-        ::close(ashmemFd);
+        PLOG(ERROR) << "Failed ashmem_create_region";
+        goto fail_silent;
     }
-    return result;
+
+    if (ashmem_set_prot_region(ashmemFd, PROT_READ | PROT_WRITE) < 0) {
+        PLOG(ERROR) << "Failed ashmem_set_prot_region";
+        goto fail_silent;
+    }
+
+    newData = ::mmap(nullptr, mInflatedSize, PROT_READ | PROT_WRITE, MAP_SHARED, ashmemFd, 0);
+    if (newData == MAP_FAILED) {
+        PLOG(ERROR) << "Failed mmap";
+        goto fail_silent;
+    }
+
+    if (ashmem_set_prot_region(ashmemFd, PROT_READ) < 0) {
+        PLOG(ERROR) << "Failed ashmem_set_prot_region";
+        goto fail_silent;
+    }
+
+    {
+        // Migrate existing contents into new ashmem region
+        uint32_t slotsSize = mSize - mSlotsOffset;
+        uint32_t newSlotsOffset = mInflatedSize - slotsSize;
+        memcpy(static_cast<uint8_t*>(newData),
+                static_cast<uint8_t*>(mData), mAllocOffset);
+        memcpy(static_cast<uint8_t*>(newData) + newSlotsOffset,
+                static_cast<uint8_t*>(mData) + mSlotsOffset, slotsSize);
+
+        free(mData);
+        mAshmemFd = ashmemFd;
+        mData = newData;
+        mSize = mInflatedSize;
+        mSlotsOffset = newSlotsOffset;
+
+        updateSlotsData();
+    }
+
+    LOG(DEBUG) << "Inflated: " << this->toString();
+    return OK;
+
+fail:
+    LOG(ERROR) << "Failed maybeInflate";
+fail_silent:
+    ::munmap(newData, mInflatedSize);
+    ::close(ashmemFd);
+    return UNKNOWN_ERROR;
 }
 
-status_t CursorWindow::createFromParcel(Parcel* parcel, CursorWindow** outCursorWindow) {
-    *outCursorWindow = nullptr;
+status_t CursorWindow::createFromParcel(Parcel* parcel, CursorWindow** outWindow) {
+    *outWindow = nullptr;
 
-    String8 name;
-    status_t result = parcel->readString8(&name);
-    if (result) return result;
+    CursorWindow* window = new CursorWindow();
+    if (!window) goto fail;
+
+    if (parcel->readString8(&window->mName)) goto fail;
+    if (parcel->readUint32(&window->mNumRows)) goto fail;
+    if (parcel->readUint32(&window->mNumColumns)) goto fail;
+    if (parcel->readUint32(&window->mSize)) goto fail;
+
+    if ((window->mNumRows * window->mNumColumns * kSlotSizeBytes) > window->mSize) {
+        LOG(ERROR) << "Unexpected size " << window->mSize << " for " << window->mNumRows
+                << " rows and " << window->mNumColumns << " columns";
+        goto fail_silent;
+    }
 
     bool isAshmem;
-    result = parcel->readBool(&isAshmem);
-    if (result) return result;
-
+    if (parcel->readBool(&isAshmem)) goto fail;
     if (isAshmem) {
-        return createFromParcelAshmem(parcel, name, outCursorWindow);
-    } else {
-        return createFromParcelInline(parcel, name, outCursorWindow);
-    }
-}
-
-status_t CursorWindow::createFromParcelAshmem(Parcel* parcel, String8& name,
-                                              CursorWindow** outCursorWindow) {
-    status_t result;
-    int actualSize;
-    int ashmemFd = parcel->readFileDescriptor();
-    if (ashmemFd == int(BAD_TYPE)) {
-        result = BAD_TYPE;
-        ALOGE("CursorWindow: readFileDescriptor() failed");
-    } else {
-        ssize_t size = ashmem_get_size_region(ashmemFd);
-        if (size < 0) {
-            result = UNKNOWN_ERROR;
-            ALOGE("CursorWindow: ashmem_get_size_region() failed: errno=%d.", errno);
-        } else {
-            int dupAshmemFd = ::fcntl(ashmemFd, F_DUPFD_CLOEXEC, 0);
-            if (dupAshmemFd < 0) {
-                result = -errno;
-                ALOGE("CursorWindow: fcntl() failed: errno=%d.", errno);
-            } else {
-                // the size of the ashmem descriptor can be modified between ashmem_get_size_region
-                // call and mmap, so we'll check again immediately after memory is mapped
-                void* data = ::mmap(NULL, size, PROT_READ, MAP_SHARED, dupAshmemFd, 0);
-                if (data == MAP_FAILED) {
-                    result = -errno;
-                    ALOGE("CursorWindow: mmap() failed: errno=%d.", errno);
-                } else if ((actualSize = ashmem_get_size_region(dupAshmemFd)) != size) {
-                    ::munmap(data, size);
-                    result = BAD_VALUE;
-                    ALOGE("CursorWindow: ashmem_get_size_region() returned %d, expected %d"
-                            " errno=%d",
-                            actualSize, (int) size, errno);
-                } else {
-                    CursorWindow* window = new CursorWindow(name, dupAshmemFd,
-                            data, size, size, true /*readOnly*/);
-                    LOG_WINDOW("Created CursorWindow from ashmem parcel: freeOffset=%d, "
-                            "numRows=%d, numColumns=%d, mSize=%zu, mData=%p",
-                            window->mHeader->freeOffset,
-                            window->mHeader->numRows,
-                            window->mHeader->numColumns,
-                            window->mSize, window->mData);
-                    *outCursorWindow = window;
-                    return OK;
-                }
-                ::close(dupAshmemFd);
-            }
+        window->mAshmemFd = parcel->readFileDescriptor();
+        if (window->mAshmemFd < 0) {
+            LOG(ERROR) << "Failed readFileDescriptor";
+            goto fail_silent;
         }
+
+        window->mAshmemFd = ::fcntl(window->mAshmemFd, F_DUPFD_CLOEXEC, 0);
+        if (window->mAshmemFd < 0) {
+            PLOG(ERROR) << "Failed F_DUPFD_CLOEXEC";
+            goto fail_silent;
+        }
+
+        window->mData = ::mmap(nullptr, window->mSize, PROT_READ, MAP_SHARED, window->mAshmemFd, 0);
+        if (window->mData == MAP_FAILED) {
+            PLOG(ERROR) << "Failed mmap";
+            goto fail_silent;
+        }
+    } else {
+        window->mAshmemFd = -1;
+
+        if (window->mSize > kInlineSize) {
+            LOG(ERROR) << "Unexpected size " << window->mSize << " for inline window";
+            goto fail_silent;
+        }
+
+        window->mData = malloc(window->mSize);
+        if (!window->mData) goto fail;
+
+        if (parcel->read(window->mData, window->mSize)) goto fail;
     }
-    *outCursorWindow = NULL;
-    return result;
-}
 
-status_t CursorWindow::createFromParcelInline(Parcel* parcel, String8& name,
-                                              CursorWindow** outCursorWindow) {
-    uint32_t sentSize;
-    status_t result = parcel->readUint32(&sentSize);
-    if (result) return result;
-    if (sentSize > kInlineSize) return NO_MEMORY;
+    // We just came from a remote source, so we're read-only
+    // and we can't inflate ourselves
+    window->mInflatedSize = window->mSize;
+    window->mReadOnly = true;
 
-    void* data = calloc(sentSize, 1);
-    if (!data) return NO_MEMORY;
+    window->updateSlotsData();
 
-    result = parcel->read(data, sentSize);
-    if (result) return result;
-
-    CursorWindow* window = new CursorWindow(name, -1, data, sentSize,
-                                            sentSize, true /*readOnly*/);
-    LOG_WINDOW("Created CursorWindow from inline parcel: freeOffset=%d, "
-            "numRows=%d, numColumns=%d, mSize=%zu, mData=%p",
-            window->mHeader->freeOffset,
-            window->mHeader->numRows,
-            window->mHeader->numColumns,
-            window->mSize, window->mData);
-    *outCursorWindow = window;
+    LOG(DEBUG) << "Created from parcel: " << window->toString();
+    *outWindow = window;
     return OK;
+
+fail:
+    LOG(ERROR) << "Failed createFromParcel";
+fail_silent:
+    delete window;
+    return UNKNOWN_ERROR;
 }
 
 status_t CursorWindow::writeToParcel(Parcel* parcel) {
-        LOG_WINDOW("Writing CursorWindow: freeOffset=%d, "
-                "numRows=%d, numColumns=%d, mSize=%zu, mData=%p",
-                mHeader->freeOffset,
-                mHeader->numRows,
-                mHeader->numColumns,
-                mSize, mData);
+    LOG(DEBUG) << "Writing to parcel: " << this->toString();
 
-    status_t result = parcel->writeString8(mName);
-    if (result) return result;
-
+    if (parcel->writeString8(mName)) goto fail;
+    if (parcel->writeUint32(mNumRows)) goto fail;
+    if (parcel->writeUint32(mNumColumns)) goto fail;
     if (mAshmemFd != -1) {
-        result = parcel->writeBool(true);
-        if (result) return result;
-        return writeToParcelAshmem(parcel);
+        if (parcel->writeUint32(mSize)) goto fail;
+        if (parcel->writeBool(true)) goto fail;
+        if (parcel->writeDupFileDescriptor(mAshmemFd)) goto fail;
     } else {
-        result = parcel->writeBool(false);
-        if (result) return result;
-        return writeToParcelInline(parcel);
+        // Since we know we're going to be read-only on the remote side,
+        // we can compact ourselves on the wire, with just enough padding
+        // to ensure our slots stay aligned
+        size_t slotsSize = mSize - mSlotsOffset;
+        size_t compactedSize = mAllocOffset + slotsSize;
+        compactedSize = (compactedSize + 3) & ~3;
+        if (parcel->writeUint32(compactedSize)) goto fail;
+        if (parcel->writeBool(false)) goto fail;
+        void* dest = parcel->writeInplace(compactedSize);
+        if (!dest) goto fail;
+        memcpy(static_cast<uint8_t*>(dest),
+                static_cast<uint8_t*>(mData), mAllocOffset);
+        memcpy(static_cast<uint8_t*>(dest) + compactedSize - slotsSize,
+                static_cast<uint8_t*>(mData) + mSlotsOffset, slotsSize);
     }
-}
+    return OK;
 
-status_t CursorWindow::writeToParcelAshmem(Parcel* parcel) {
-    return parcel->writeDupFileDescriptor(mAshmemFd);
-}
-
-status_t CursorWindow::writeToParcelInline(Parcel* parcel) {
-    status_t result = parcel->writeUint32(mHeader->freeOffset);
-    if (result) return result;
-
-    return parcel->write(mData, mHeader->freeOffset);
+fail:
+    LOG(ERROR) << "Failed writeToParcel";
+fail_silent:
+    return UNKNOWN_ERROR;
 }
 
 status_t CursorWindow::clear() {
     if (mReadOnly) {
         return INVALID_OPERATION;
     }
-
-    mHeader->freeOffset = sizeof(Header) + sizeof(RowSlotChunk);
-    mHeader->firstChunkOffset = sizeof(Header);
-    mHeader->numRows = 0;
-    mHeader->numColumns = 0;
-
-    RowSlotChunk* firstChunk = static_cast<RowSlotChunk*>(offsetToPtr(mHeader->firstChunkOffset));
-    firstChunk->nextChunkOffset = 0;
+    mAllocOffset = 0;
+    mSlotsOffset = mSize;
+    mNumRows = 0;
+    mNumColumns = 0;
     return OK;
 }
 
+void CursorWindow::updateSlotsData() {
+    mSlotsStart = static_cast<uint8_t*>(mData) + mSize - kSlotSizeBytes;
+    mSlotsEnd = static_cast<uint8_t*>(mData) + mSlotsOffset;
+}
+
+void* CursorWindow::offsetToPtr(uint32_t offset, uint32_t bufferSize = 0) {
+    if (offset > mSize) {
+        LOG(ERROR) << "Offset " << offset
+                << " out of bounds, max value " << mSize;
+        return nullptr;
+    }
+    if (offset + bufferSize > mSize) {
+        LOG(ERROR) << "End offset " << (offset + bufferSize)
+                << " out of bounds, max value " << mSize;
+        return nullptr;
+    }
+    return static_cast<uint8_t*>(mData) + offset;
+}
+
+uint32_t CursorWindow::offsetFromPtr(void* ptr) {
+    return static_cast<uint8_t*>(ptr) - static_cast<uint8_t*>(mData);
+}
+
 status_t CursorWindow::setNumColumns(uint32_t numColumns) {
     if (mReadOnly) {
         return INVALID_OPERATION;
     }
-
-    uint32_t cur = mHeader->numColumns;
-    if ((cur > 0 || mHeader->numRows > 0) && cur != numColumns) {
-        ALOGE("Trying to go from %d columns to %d", cur, numColumns);
+    uint32_t cur = mNumColumns;
+    if ((cur > 0 || mNumRows > 0) && cur != numColumns) {
+        LOG(ERROR) << "Trying to go from " << cur << " columns to " << numColumns;
         return INVALID_OPERATION;
     }
-    mHeader->numColumns = numColumns;
+    mNumColumns = numColumns;
     return OK;
 }
 
@@ -287,30 +290,19 @@
     if (mReadOnly) {
         return INVALID_OPERATION;
     }
-
-    // Fill in the row slot
-    RowSlot* rowSlot = allocRowSlot();
-    if (rowSlot == NULL) {
-        return NO_MEMORY;
+    size_t size = mNumColumns * kSlotSizeBytes;
+    off_t newOffset = mSlotsOffset - size;
+    if (newOffset < mAllocOffset) {
+        maybeInflate();
+        newOffset = mSlotsOffset - size;
+        if (newOffset < mAllocOffset) {
+            return NO_MEMORY;
+        }
     }
-    uint32_t rowSlotOffset = offsetFromPtr(rowSlot);
-
-    // Allocate the slots for the field directory
-    size_t fieldDirSize = mHeader->numColumns * sizeof(FieldSlot);
-    uint32_t fieldDirOffset = alloc(fieldDirSize, true /*aligned*/);
-    if (!fieldDirOffset) {
-        mHeader->numRows--;
-        LOG_WINDOW("The row failed, so back out the new row accounting "
-                "from allocRowSlot %d", mHeader->numRows);
-        return NO_MEMORY;
-    }
-    FieldSlot* fieldDir = static_cast<FieldSlot*>(offsetToPtr(fieldDirOffset));
-    memset(fieldDir, 0, fieldDirSize);
-
-    LOG_WINDOW("Allocated row %u, rowSlot is at offset %u, fieldDir is %zu bytes at offset %u\n",
-            mHeader->numRows - 1, rowSlotOffset, fieldDirSize, fieldDirOffset);
-    rowSlot = static_cast<RowSlot*>(offsetToPtr(rowSlotOffset));
-    rowSlot->offset = fieldDirOffset;
+    memset(offsetToPtr(newOffset), 0, size);
+    mSlotsOffset = newOffset;
+    updateSlotsData();
+    mNumRows++;
     return OK;
 }
 
@@ -318,90 +310,48 @@
     if (mReadOnly) {
         return INVALID_OPERATION;
     }
-
-    if (mHeader->numRows > 0) {
-        mHeader->numRows--;
+    size_t size = mNumColumns * kSlotSizeBytes;
+    off_t newOffset = mSlotsOffset + size;
+    if (newOffset > mSize) {
+        return NO_MEMORY;
     }
+    mSlotsOffset = newOffset;
+    updateSlotsData();
+    mNumRows--;
     return OK;
 }
 
-uint32_t CursorWindow::alloc(size_t size, bool aligned) {
-    uint32_t padding;
-    if (aligned) {
-        // 4 byte alignment
-        padding = (~mHeader->freeOffset + 1) & 3;
-    } else {
-        padding = 0;
+status_t CursorWindow::alloc(size_t size, uint32_t* outOffset) {
+    if (mReadOnly) {
+        return INVALID_OPERATION;
     }
-
-    uint32_t offset = mHeader->freeOffset + padding;
-    uint32_t nextFreeOffset = offset + size;
-    if (nextFreeOffset > mSize) {
-        // Try inflating to ashmem before finally giving up
-        inflate();
-        if (nextFreeOffset > mSize) {
-            ALOGW("Window is full: requested allocation %zu bytes, "
-                    "free space %zu bytes, window size %zu bytes",
-                    size, freeSpace(), mSize);
-            return 0;
+    size_t alignedSize = (size + 3) & ~3;
+    off_t newOffset = mAllocOffset + alignedSize;
+    if (newOffset > mSlotsOffset) {
+        maybeInflate();
+        newOffset = mAllocOffset + alignedSize;
+        if (newOffset > mSlotsOffset) {
+            return NO_MEMORY;
         }
     }
-
-    mHeader->freeOffset = nextFreeOffset;
-    return offset;
-}
-
-CursorWindow::RowSlot* CursorWindow::getRowSlot(uint32_t row) {
-    uint32_t chunkPos = row;
-    RowSlotChunk* chunk = static_cast<RowSlotChunk*>(
-            offsetToPtr(mHeader->firstChunkOffset));
-    while (chunkPos >= ROW_SLOT_CHUNK_NUM_ROWS) {
-        chunk = static_cast<RowSlotChunk*>(offsetToPtr(chunk->nextChunkOffset));
-        chunkPos -= ROW_SLOT_CHUNK_NUM_ROWS;
-    }
-    return &chunk->slots[chunkPos];
-}
-
-CursorWindow::RowSlot* CursorWindow::allocRowSlot() {
-    uint32_t chunkPos = mHeader->numRows;
-    RowSlotChunk* chunk = static_cast<RowSlotChunk*>(
-            offsetToPtr(mHeader->firstChunkOffset));
-    while (chunkPos > ROW_SLOT_CHUNK_NUM_ROWS) {
-        chunk = static_cast<RowSlotChunk*>(offsetToPtr(chunk->nextChunkOffset));
-        chunkPos -= ROW_SLOT_CHUNK_NUM_ROWS;
-    }
-    if (chunkPos == ROW_SLOT_CHUNK_NUM_ROWS) {
-        if (!chunk->nextChunkOffset) {
-            uint32_t chunkOffset = offsetFromPtr(chunk);
-            uint32_t newChunk = alloc(sizeof(RowSlotChunk), true /*aligned*/);
-            chunk = static_cast<RowSlotChunk*>(offsetToPtr(chunkOffset));
-            chunk->nextChunkOffset = newChunk;
-            if (!chunk->nextChunkOffset) {
-                return NULL;
-            }
-        }
-        chunk = static_cast<RowSlotChunk*>(offsetToPtr(chunk->nextChunkOffset));
-        chunk->nextChunkOffset = 0;
-        chunkPos = 0;
-    }
-    mHeader->numRows += 1;
-    return &chunk->slots[chunkPos];
+    *outOffset = mAllocOffset;
+    mAllocOffset = newOffset;
+    return OK;
 }
 
 CursorWindow::FieldSlot* CursorWindow::getFieldSlot(uint32_t row, uint32_t column) {
-    if (row >= mHeader->numRows || column >= mHeader->numColumns) {
-        ALOGE("Failed to read row %d, column %d from a CursorWindow which "
-                "has %d rows, %d columns.",
-                row, column, mHeader->numRows, mHeader->numColumns);
-        return NULL;
+    // This is carefully tuned to use as few cycles as
+    // possible, since this is an extremely hot code path;
+    // see CursorWindow_bench.cpp for more details
+    void *result = static_cast<uint8_t*>(mSlotsStart)
+            - (((row * mNumColumns) + column) << kSlotShift);
+    if (result < mSlotsEnd || column >= mNumColumns) {
+        LOG(ERROR) << "Failed to read row " << row << ", column " << column
+                << " from a window with " << mNumRows << " rows, " << mNumColumns << " columns";
+        return nullptr;
+    } else {
+        return static_cast<FieldSlot*>(result);
     }
-    RowSlot* rowSlot = getRowSlot(row);
-    if (!rowSlot) {
-        ALOGE("Failed to find rowSlot for row %d.", row);
-        return NULL;
-    }
-    FieldSlot* fieldDir = static_cast<FieldSlot*>(offsetToPtr(rowSlot->offset));
-    return &fieldDir[column];
 }
 
 status_t CursorWindow::putBlob(uint32_t row, uint32_t column, const void* value, size_t size) {
@@ -423,16 +373,15 @@
     if (!fieldSlot) {
         return BAD_VALUE;
     }
-    uint32_t fieldSlotOffset = offsetFromPtr(fieldSlot);
 
-    uint32_t offset = alloc(size);
-    if (!offset) {
+    uint32_t offset;
+    if (alloc(size, &offset)) {
         return NO_MEMORY;
     }
 
     memcpy(offsetToPtr(offset), value, size);
 
-    fieldSlot = static_cast<FieldSlot*>(offsetToPtr(fieldSlotOffset));
+    fieldSlot = getFieldSlot(row, column);
     fieldSlot->type = type;
     fieldSlot->data.buffer.offset = offset;
     fieldSlot->data.buffer.size = size;
diff --git a/libs/androidfw/Idmap.cpp b/libs/androidfw/Idmap.cpp
index 5f231ff..4e03ce5 100644
--- a/libs/androidfw/Idmap.cpp
+++ b/libs/androidfw/Idmap.cpp
@@ -36,16 +36,12 @@
 
 namespace android {
 
-static bool compare_target_entries(const Idmap_target_entry &e1, const uint32_t target_id) {
-  return dtohl(e1.target_id) < target_id;
-}
-
-static bool compare_overlay_entries(const Idmap_overlay_entry& e1, const uint32_t overlay_id) {
-  return dtohl(e1.overlay_id) < overlay_id;
+uint32_t round_to_4_bytes(uint32_t size) {
+  return size + (4U - (size % 4U)) % 4U;
 }
 
 size_t Idmap_header::Size() const {
-  return sizeof(Idmap_header) + sizeof(uint8_t) * dtohl(debug_info_size);
+  return sizeof(Idmap_header) + sizeof(uint8_t) * round_to_4_bytes(dtohl(debug_info_size));
 }
 
 OverlayStringPool::OverlayStringPool(const LoadedIdmap* loaded_idmap)
@@ -88,7 +84,10 @@
 status_t OverlayDynamicRefTable::lookupResourceId(uint32_t* resId) const {
   const Idmap_overlay_entry* first_entry = entries_;
   const Idmap_overlay_entry* end_entry = entries_ + dtohl(data_header_->overlay_entry_count);
-  auto entry = std::lower_bound(first_entry, end_entry, *resId, compare_overlay_entries);
+  auto entry = std::lower_bound(first_entry, end_entry, *resId,
+                                [](const Idmap_overlay_entry& e1, const uint32_t overlay_id) {
+    return dtohl(e1.overlay_id) < overlay_id;
+  });
 
   if (entry == end_entry || dtohl(entry->overlay_id) != *resId) {
     // A mapping for the target resource id could not be found.
@@ -96,7 +95,7 @@
   }
 
   *resId = (0x00FFFFFFU & dtohl(entry->target_id))
-      | (((uint32_t) target_assigned_package_id_) << 24);
+      | (((uint32_t) target_assigned_package_id_) << 24U);
   return NO_ERROR;
 }
 
@@ -106,62 +105,58 @@
 
 IdmapResMap::IdmapResMap(const Idmap_data_header* data_header,
                          const Idmap_target_entry* entries,
+                         const Idmap_target_entry_inline* inline_entries,
                          uint8_t target_assigned_package_id,
                          const OverlayDynamicRefTable* overlay_ref_table)
     : data_header_(data_header),
       entries_(entries),
+      inline_entries_(inline_entries),
       target_assigned_package_id_(target_assigned_package_id),
-      overlay_ref_table_(overlay_ref_table) { };
+      overlay_ref_table_(overlay_ref_table) { }
 
 IdmapResMap::Result IdmapResMap::Lookup(uint32_t target_res_id) const {
-  if ((target_res_id >> 24) != target_assigned_package_id_) {
+  if ((target_res_id >> 24U) != target_assigned_package_id_) {
     // The resource id must have the same package id as the target package.
     return {};
   }
 
   // The resource ids encoded within the idmap are build-time resource ids.
   target_res_id = (0x00FFFFFFU & target_res_id)
-      | (((uint32_t) data_header_->target_package_id) << 24);
+      | (((uint32_t) data_header_->target_package_id) << 24U);
 
-  const Idmap_target_entry* first_entry = entries_;
-  const Idmap_target_entry* end_entry = entries_ + dtohl(data_header_->target_entry_count);
-  auto entry = std::lower_bound(first_entry, end_entry, target_res_id, compare_target_entries);
+  // Check if the target resource is mapped to an overlay resource.
+  auto first_entry = entries_;
+  auto end_entry = entries_ + dtohl(data_header_->target_entry_count);
+  auto entry = std::lower_bound(first_entry, end_entry, target_res_id,
+                                [](const Idmap_target_entry &e, const uint32_t target_id) {
+    return dtohl(e.target_id) < target_id;
+  });
 
-  if (entry == end_entry || dtohl(entry->target_id) != target_res_id) {
-    // A mapping for the target resource id could not be found.
-    return {};
-  }
-
-  // A reference should be treated as an alias of the resource. Instead of returning the table
-  // entry, return the alias resource id to look up. The alias resource might not reside within the
-  // overlay package, so the resource id must be fixed with the dynamic reference table of the
-  // overlay before returning.
-  if (entry->type == Res_value::TYPE_REFERENCE
-      || entry->type == Res_value::TYPE_DYNAMIC_REFERENCE) {
-    uint32_t overlay_resource_id = dtohl(entry->value);
-
+  if (entry != end_entry && dtohl(entry->target_id) == target_res_id) {
+    uint32_t overlay_resource_id = dtohl(entry->overlay_id);
     // Lookup the resource without rewriting the overlay resource id back to the target resource id
     // being looked up.
     overlay_ref_table_->lookupResourceIdNoRewrite(&overlay_resource_id);
     return Result(overlay_resource_id);
   }
 
-  // Copy the type and value into the ResTable_entry structure needed by asset manager.
-  uint16_t malloc_size = sizeof(ResTable_entry) + sizeof(Res_value);
-  auto table_entry = reinterpret_cast<ResTable_entry*>(malloc(malloc_size));
-  memset(table_entry, 0, malloc_size);
-  table_entry->size = htods(sizeof(ResTable_entry));
+  // Check if the target resources is mapped to an inline table entry.
+  auto first_inline_entry = inline_entries_;
+  auto end_inline_entry = inline_entries_ + dtohl(data_header_->target_inline_entry_count);
+  auto inline_entry = std::lower_bound(first_inline_entry, end_inline_entry, target_res_id,
+                                       [](const Idmap_target_entry_inline &e,
+                                          const uint32_t target_id) {
+    return dtohl(e.target_id) < target_id;
+  });
 
-  auto table_value = reinterpret_cast<Res_value*>(reinterpret_cast<uint8_t*>(table_entry)
-      + sizeof(ResTable_entry));
-  table_value->dataType = entry->type;
-  table_value->data = entry->value;
-
-  return Result(ResTable_entry_handle::managed(table_entry, [](auto p) { free(p); }));
+  if (inline_entry != end_inline_entry && dtohl(inline_entry->target_id) == target_res_id) {
+    return Result(inline_entry->value);
+  }
+  return {};
 }
 
 static bool is_word_aligned(const void* data) {
-  return (reinterpret_cast<uintptr_t>(data) & 0x03) == 0;
+  return (reinterpret_cast<uintptr_t>(data) & 0x03U) == 0U;
 }
 
 static bool IsValidIdmapHeader(const StringPiece& data) {
@@ -175,7 +170,7 @@
     return false;
   }
 
-  const Idmap_header* header = reinterpret_cast<const Idmap_header*>(data.data());
+  auto header = reinterpret_cast<const Idmap_header*>(data.data());
   if (dtohl(header->magic) != kIdmapMagic) {
     LOG(ERROR) << StringPrintf("Invalid Idmap file: bad magic value (was 0x%08x, expected 0x%08x)",
                                dtohl(header->magic), kIdmapMagic);
@@ -198,11 +193,13 @@
                          const Idmap_header* header,
                          const Idmap_data_header* data_header,
                          const Idmap_target_entry* target_entries,
+                         const Idmap_target_entry_inline* target_inline_entries,
                          const Idmap_overlay_entry* overlay_entries,
                          ResStringPool* string_pool)
      : header_(header),
        data_header_(data_header),
        target_entries_(target_entries),
+       target_inline_entries_(target_inline_entries),
        overlay_entries_(overlay_entries),
        string_pool_(string_pool),
        idmap_path_(std::move(idmap_path)),
@@ -233,7 +230,7 @@
   data_ptr += sizeof(*data_header);
   data_size -= sizeof(*data_header);
 
-  // Make sure there is enough space for the target entries declared in the header.
+  // Make sure there is enough space for the target entries declared in the header
   const auto target_entries = reinterpret_cast<const Idmap_target_entry*>(data_ptr);
   if (data_size / sizeof(Idmap_target_entry) <
       static_cast<size_t>(dtohl(data_header->target_entry_count))) {
@@ -248,6 +245,21 @@
   data_ptr += target_entry_size_bytes;
   data_size -= target_entry_size_bytes;
 
+  // Make sure there is enough space for the target entries declared in the header.
+  const auto target_inline_entries = reinterpret_cast<const Idmap_target_entry_inline*>(data_ptr);
+  if (data_size / sizeof(Idmap_target_entry_inline) <
+      static_cast<size_t>(dtohl(data_header->target_inline_entry_count))) {
+    LOG(ERROR) << StringPrintf("Idmap too small for the number of target inline entries (%d)",
+                               (int)dtohl(data_header->target_inline_entry_count));
+    return {};
+  }
+
+  // Advance the data pointer past the target entries.
+  const size_t target_inline_entry_size_bytes =
+      (dtohl(data_header->target_inline_entry_count) * sizeof(Idmap_target_entry_inline));
+  data_ptr += target_inline_entry_size_bytes;
+  data_size -= target_inline_entry_size_bytes;
+
   // Make sure there is enough space for the overlay entries declared in the header.
   const auto overlay_entries = reinterpret_cast<const Idmap_overlay_entry*>(data_ptr);
   if (data_size / sizeof(Idmap_overlay_entry) <
@@ -257,22 +269,26 @@
     return {};
   }
 
-  // Advance the data pointer past the target entries.
+  // Advance the data pointer past the overlay entries.
   const size_t overlay_entry_size_bytes =
       (dtohl(data_header->overlay_entry_count) * sizeof(Idmap_overlay_entry));
   data_ptr += overlay_entry_size_bytes;
   data_size -= overlay_entry_size_bytes;
 
   // Read the idmap string pool that holds the value of inline string entries.
-  if (data_size < dtohl(data_header->string_pool_length)) {
+  uint32_t string_pool_size = dtohl(*reinterpret_cast<const uint32_t*>(data_ptr));
+  data_ptr += sizeof(uint32_t);
+  data_size -= sizeof(uint32_t);
+
+  if (data_size < string_pool_size) {
     LOG(ERROR) << StringPrintf("Idmap too small for string pool (length %d)",
-                               (int)dtohl(data_header->string_pool_length));
+                               (int)string_pool_size);
     return {};
   }
 
   auto idmap_string_pool = util::make_unique<ResStringPool>();
-  if (dtohl(data_header->string_pool_length) > 0) {
-    status_t err = idmap_string_pool->setTo(data_ptr, dtohl(data_header->string_pool_length));
+  if (string_pool_size > 0) {
+    status_t err = idmap_string_pool->setTo(data_ptr, string_pool_size);
     if (err != NO_ERROR) {
       LOG(ERROR) << "idmap string pool corrupt.";
       return {};
@@ -280,9 +296,10 @@
   }
 
   // Can't use make_unique because LoadedIdmap constructor is private.
-  std::unique_ptr<LoadedIdmap> loaded_idmap = std::unique_ptr<LoadedIdmap>(
+  auto loaded_idmap = std::unique_ptr<LoadedIdmap>(
       new LoadedIdmap(idmap_path.to_string(), getFileModDate(idmap_path.data()), header,
-                      data_header, target_entries, overlay_entries, idmap_string_pool.release()));
+                      data_header, target_entries, target_inline_entries, overlay_entries,
+                      idmap_string_pool.release()));
 
   return std::move(loaded_idmap);
 }
diff --git a/libs/androidfw/fuzz/cursorwindow_fuzzer/Android.bp b/libs/androidfw/fuzz/cursorwindow_fuzzer/Android.bp
new file mode 100644
index 0000000..2dac47b
--- /dev/null
+++ b/libs/androidfw/fuzz/cursorwindow_fuzzer/Android.bp
@@ -0,0 +1,31 @@
+cc_fuzz {
+    name: "cursorwindow_fuzzer",
+    srcs: [
+        "cursorwindow_fuzzer.cpp",
+    ],
+    host_supported: true,
+    corpus: ["corpus/*"],
+    static_libs: ["libgmock"],
+    target: {
+        android: {
+            shared_libs: [
+                "libandroidfw_fuzzer_lib",
+                "libbase",
+                "libbinder",
+                "libcutils",
+                "liblog",
+                "libutils",
+            ],
+        },
+        host: {
+            static_libs: [
+                "libandroidfw_fuzzer_lib",
+                "libbase",
+                "libbinder",
+                "libcutils",
+                "liblog",
+                "libutils",
+            ],
+        },
+    },
+}
diff --git a/libs/androidfw/fuzz/cursorwindow_fuzzer/corpus/typical.bin b/libs/androidfw/fuzz/cursorwindow_fuzzer/corpus/typical.bin
new file mode 100644
index 0000000..c7e22dd
--- /dev/null
+++ b/libs/androidfw/fuzz/cursorwindow_fuzzer/corpus/typical.bin
Binary files differ
diff --git a/libs/androidfw/fuzz/cursorwindow_fuzzer/cursorwindow_fuzzer.cpp b/libs/androidfw/fuzz/cursorwindow_fuzzer/cursorwindow_fuzzer.cpp
new file mode 100644
index 0000000..8dce212
--- /dev/null
+++ b/libs/androidfw/fuzz/cursorwindow_fuzzer/cursorwindow_fuzzer.cpp
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <string>
+#include <memory>
+
+#include "android-base/logging.h"
+#include "androidfw/CursorWindow.h"
+#include "binder/Parcel.h"
+
+#include <fuzzer/FuzzedDataProvider.h>
+
+using android::CursorWindow;
+using android::Parcel;
+
+extern "C" int LLVMFuzzerInitialize(int *, char ***) {
+    setenv("ANDROID_LOG_TAGS", "*:s", 1);
+    android::base::InitLogging(nullptr, &android::base::StderrLogger);
+    return 0;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+    Parcel p;
+    p.setData(data, size);
+
+    CursorWindow* w = nullptr;
+    if (!CursorWindow::createFromParcel(&p, &w)) {
+        LOG(WARNING) << "Valid cursor with " << w->getNumRows() << " rows, "
+                << w->getNumColumns() << " cols";
+
+        // Try obtaining heap allocations for most items; we trim the
+        // search space to speed things up
+        auto rows = std::min(w->getNumRows(), static_cast<uint32_t>(128));
+        auto cols = std::min(w->getNumColumns(), static_cast<uint32_t>(128));
+        for (auto row = 0; row < rows; row++) {
+            for (auto col = 0; col < cols; col++) {
+                auto field = w->getFieldSlot(row, col);
+                if (!field) continue;
+                switch (w->getFieldSlotType(field)) {
+                case CursorWindow::FIELD_TYPE_STRING: {
+                    size_t size;
+                    w->getFieldSlotValueString(field, &size);
+                    break;
+                }
+                case CursorWindow::FIELD_TYPE_BLOB: {
+                    size_t size;
+                    w->getFieldSlotValueBlob(field, &size);
+                    break;
+                }
+                }
+            }
+        }
+
+        // Finally, try obtaining the furthest valid field
+        if (rows > 0 && cols > 0) {
+            w->getFieldSlot(w->getNumRows() - 1, w->getNumColumns() - 1);
+        }
+    }
+    delete w;
+
+    return 0;
+}
diff --git a/libs/androidfw/include/androidfw/CursorWindow.h b/libs/androidfw/include/androidfw/CursorWindow.h
index 0bee609..6e55a9a 100644
--- a/libs/androidfw/include/androidfw/CursorWindow.h
+++ b/libs/androidfw/include/androidfw/CursorWindow.h
@@ -20,38 +20,36 @@
 #include <inttypes.h>
 #include <stddef.h>
 #include <stdint.h>
+#include <string>
 
-#include <binder/Parcel.h>
-#include <log/log.h>
-#include <utils/String8.h>
+#include "android-base/stringprintf.h"
+#include "binder/Parcel.h"
+#include "utils/String8.h"
 
-#if LOG_NDEBUG
-
-#define IF_LOG_WINDOW() if (false)
 #define LOG_WINDOW(...)
 
-#else
-
-#define IF_LOG_WINDOW() IF_ALOG(LOG_DEBUG, "CursorWindow")
-#define LOG_WINDOW(...) ALOG(LOG_DEBUG, "CursorWindow", __VA_ARGS__)
-
-#endif
-
 namespace android {
 
 /**
- * This class stores a set of rows from a database in a buffer. The begining of the
- * window has first chunk of RowSlots, which are offsets to the row directory, followed by
- * an offset to the next chunk in a linked-list of additional chunk of RowSlots in case
- * the pre-allocated chunk isn't big enough to refer to all rows. Each row directory has a
- * FieldSlot per column, which has the size, offset, and type of the data for that field.
- * Note that the data types come from sqlite3.h.
+ * This class stores a set of rows from a database in a buffer. Internally
+ * data is structured as a "heap" of string/blob allocations at the bottom
+ * of the memory region, and a "stack" of FieldSlot allocations at the top
+ * of the memory region. Here's an example visual representation:
+ *
+ *   +----------------------------------------------------------------+
+ *   |heap\0of\0strings\0                                 222211110000| ...
+ *   +-------------------+--------------------------------+-------+---+
+ *    ^                  ^                                ^       ^   ^     ^
+ *    |                  |                                |       |   |     |
+ *    |                  +- mAllocOffset    mSlotsOffset -+       |   |     |
+ *    +- mData                                       mSlotsStart -+   |     |
+ *                                                             mSize -+     |
+ *                                                           mInflatedSize -+
  *
  * Strings are stored in UTF-8.
  */
 class CursorWindow {
-    CursorWindow(const String8& name, int ashmemFd, void* data, size_t size,
-                 size_t inflatedSize, bool readOnly);
+    CursorWindow();
 
 public:
     /* Field types. */
@@ -88,9 +86,9 @@
 
     inline String8 name() { return mName; }
     inline size_t size() { return mSize; }
-    inline size_t freeSpace() { return mSize - mHeader->freeOffset; }
-    inline uint32_t getNumRows() { return mHeader->numRows; }
-    inline uint32_t getNumColumns() { return mHeader->numColumns; }
+    inline size_t freeSpace() { return mSlotsOffset - mAllocOffset; }
+    inline uint32_t getNumRows() { return mNumRows; }
+    inline uint32_t getNumColumns() { return mNumColumns; }
 
     status_t clear();
     status_t setNumColumns(uint32_t numColumns);
@@ -138,75 +136,57 @@
         return offsetToPtr(fieldSlot->data.buffer.offset, fieldSlot->data.buffer.size);
     }
 
+    inline std::string toString() const {
+        return android::base::StringPrintf("CursorWindow{name=%s, fd=%d, size=%d, inflatedSize=%d, "
+                "allocOffset=%d, slotsOffset=%d, numRows=%d, numColumns=%d}", mName.c_str(),
+                mAshmemFd, mSize, mInflatedSize, mAllocOffset, mSlotsOffset, mNumRows, mNumColumns);
+    }
+
 private:
-    static const size_t ROW_SLOT_CHUNK_NUM_ROWS = 100;
-
-    struct Header {
-        // Offset of the lowest unused byte in the window.
-        uint32_t freeOffset;
-
-        // Offset of the first row slot chunk.
-        uint32_t firstChunkOffset;
-
-        uint32_t numRows;
-        uint32_t numColumns;
-    };
-
-    struct RowSlot {
-        uint32_t offset;
-    };
-
-    struct RowSlotChunk {
-        RowSlot slots[ROW_SLOT_CHUNK_NUM_ROWS];
-        uint32_t nextChunkOffset;
-    };
-
     String8 mName;
-    int mAshmemFd;
-    void* mData;
-    size_t mSize;
-    size_t mInflatedSize;
-    bool mReadOnly;
-    Header* mHeader;
+    int mAshmemFd = -1;
+    void* mData = nullptr;
+    /**
+     * Pointer to the first FieldSlot, used to optimize the extremely
+     * hot code path of getFieldSlot().
+     */
+    void* mSlotsStart = nullptr;
+    void* mSlotsEnd = nullptr;
+    uint32_t mSize = 0;
+    /**
+     * When a window starts as lightweight inline allocation, this value
+     * holds the "full" size to be created after ashmem inflation.
+     */
+    uint32_t mInflatedSize = 0;
+    /**
+     * Offset to the top of the "heap" of string/blob allocations. By
+     * storing these allocations at the bottom of our memory region we
+     * avoid having to rewrite offsets when inflating.
+     */
+    uint32_t mAllocOffset = 0;
+    /**
+     * Offset to the bottom of the "stack" of FieldSlot allocations.
+     */
+    uint32_t mSlotsOffset = 0;
+    uint32_t mNumRows = 0;
+    uint32_t mNumColumns = 0;
+    bool mReadOnly = false;
 
-    inline void* offsetToPtr(uint32_t offset, uint32_t bufferSize = 0) {
-        if (offset > mSize) {
-            ALOGE("Offset %" PRIu32 " out of bounds, max value %zu", offset, mSize);
-            return NULL;
-        }
-        if (offset + bufferSize > mSize) {
-            ALOGE("End offset %" PRIu32 " out of bounds, max value %zu",
-                    offset + bufferSize, mSize);
-            return NULL;
-        }
-        return static_cast<uint8_t*>(mData) + offset;
-    }
+    void updateSlotsData();
 
-    inline uint32_t offsetFromPtr(void* ptr) {
-        return static_cast<uint8_t*>(ptr) - static_cast<uint8_t*>(mData);
-    }
-
-    static status_t createFromParcelAshmem(Parcel*, String8&, CursorWindow**);
-    static status_t createFromParcelInline(Parcel*, String8&, CursorWindow**);
-
-    status_t writeToParcelAshmem(Parcel*);
-    status_t writeToParcelInline(Parcel*);
+    void* offsetToPtr(uint32_t offset, uint32_t bufferSize);
+    uint32_t offsetFromPtr(void* ptr);
 
     /**
      * By default windows are lightweight inline allocations; this method
      * inflates the window into a larger ashmem region.
      */
-    status_t inflate();
+    status_t maybeInflate();
 
     /**
-     * Allocate a portion of the window. Returns the offset
-     * of the allocation, or 0 if there isn't enough space.
-     * If aligned is true, the allocation gets 4 byte alignment.
+     * Allocate a portion of the window.
      */
-    uint32_t alloc(size_t size, bool aligned = false);
-
-    RowSlot* getRowSlot(uint32_t row);
-    RowSlot* allocRowSlot();
+    status_t alloc(size_t size, uint32_t* outOffset);
 
     status_t putBlobOrString(uint32_t row, uint32_t column,
             const void* value, size_t size, int32_t type);
diff --git a/libs/androidfw/include/androidfw/Idmap.h b/libs/androidfw/include/androidfw/Idmap.h
index ecc1ce6..ab0f47f 100644
--- a/libs/androidfw/include/androidfw/Idmap.h
+++ b/libs/androidfw/include/androidfw/Idmap.h
@@ -77,40 +77,40 @@
 // A mapping of target resource ids to a values or resource ids that should overlay the target.
 class IdmapResMap {
  public:
-  // Represents the result of a idmap lookup. The result can be one of three possibillities:
+  // Represents the result of a idmap lookup. The result can be one of three possibilities:
   // 1) The result is a resource id which represents the overlay resource that should act as an
   //    alias of the target resource.
   // 2) The result is a table entry which overlays the type and value of the target resource.
   // 3) The result is neither and the target resource is not overlaid.
   class Result {
    public:
-    Result() : data_(nullptr) {};
+    Result() = default;
     explicit Result(uint32_t value) : data_(value) {};
-    explicit Result(ResTable_entry_handle&& value) : data_(value) { };
+    explicit Result(const Res_value& value) : data_(value) { };
 
     // Returns `true` if the resource is overlaid.
-    inline explicit operator bool() const {
-      return !std::get_if<nullptr_t>(&data_);
+    explicit operator bool() const {
+      return std::get_if<std::monostate>(&data_) == nullptr;
     }
 
-    inline bool IsResourceId() const {
-      return std::get_if<uint32_t>(&data_);
+    bool IsResourceId() const {
+      return std::get_if<uint32_t>(&data_) != nullptr;
     }
 
-    inline uint32_t GetResourceId() const {
-      return *std::get_if<uint32_t>(&data_);
+    uint32_t GetResourceId() const {
+      return std::get<uint32_t>(data_);
     }
 
-    inline bool IsTableEntry() const {
-      return std::get_if<ResTable_entry_handle>(&data_);
+    bool IsInlineValue() const {
+      return std::get_if<Res_value>(&data_) != nullptr;
     }
 
-    inline const ResTable_entry_handle& GetTableEntry() const {
-      return *std::get_if<ResTable_entry_handle>(&data_);
+    const Res_value& GetInlineValue() const {
+      return std::get<Res_value>(data_);
     }
 
    private:
-      std::variant<uint32_t, nullptr_t, ResTable_entry_handle> data_;
+      std::variant<std::monostate, uint32_t, Res_value> data_;
   };
 
   // Looks up the value that overlays the target resource id.
@@ -123,11 +123,13 @@
  private:
   explicit IdmapResMap(const Idmap_data_header* data_header,
                        const Idmap_target_entry* entries,
+                       const Idmap_target_entry_inline* inline_entries,
                        uint8_t target_assigned_package_id,
                        const OverlayDynamicRefTable* overlay_ref_table);
 
   const Idmap_data_header* data_header_;
   const Idmap_target_entry* entries_;
+  const Idmap_target_entry_inline* inline_entries_;
   const uint8_t target_assigned_package_id_;
   const OverlayDynamicRefTable* overlay_ref_table_;
 
@@ -163,8 +165,8 @@
   // Returns a mapping from target resource ids to overlay values.
   inline const IdmapResMap GetTargetResourcesMap(
       uint8_t target_assigned_package_id, const OverlayDynamicRefTable* overlay_ref_table) const {
-    return IdmapResMap(data_header_, target_entries_, target_assigned_package_id,
-                       overlay_ref_table);
+    return IdmapResMap(data_header_, target_entries_, target_inline_entries_,
+                       target_assigned_package_id, overlay_ref_table);
   }
 
   // Returns a dynamic reference table for a loaded overlay package.
@@ -184,6 +186,7 @@
   const Idmap_header* header_;
   const Idmap_data_header* data_header_;
   const Idmap_target_entry* target_entries_;
+  const Idmap_target_entry_inline* target_inline_entries_;
   const Idmap_overlay_entry* overlay_entries_;
   const std::unique_ptr<ResStringPool> string_pool_;
 
@@ -200,6 +203,7 @@
                        const Idmap_header* header,
                        const Idmap_data_header* data_header,
                        const Idmap_target_entry* target_entries,
+                       const Idmap_target_entry_inline* target_inline_entries,
                        const Idmap_overlay_entry* overlay_entries,
                        ResStringPool* string_pool);
 
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index e10a7f3..04ba78b 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -41,7 +41,7 @@
 namespace android {
 
 constexpr const static uint32_t kIdmapMagic = 0x504D4449u;
-constexpr const static uint32_t kIdmapCurrentVersion = 0x00000004u;
+constexpr const static uint32_t kIdmapCurrentVersion = 0x00000005u;
 
 /**
  * In C++11, char16_t is defined as *at least* 16 bits. We do a lot of
@@ -1476,7 +1476,7 @@
         // If set, this is a weak resource and may be overriden by strong
         // resources of the same name/type. This is only useful during
         // linking with other resource tables.
-        FLAG_WEAK = 0x0004
+        FLAG_WEAK = 0x0004,
     };
     uint16_t flags;
     
@@ -1586,50 +1586,6 @@
     Res_value value;
 };
 
-
-// A ResTable_entry variant that either holds an unmanaged pointer to a constant ResTable_entry or
-// holds a ResTable_entry which is tied to the lifetime of the handle.
-class ResTable_entry_handle {
- public:
-    ResTable_entry_handle() = default;
-
-    ResTable_entry_handle(const ResTable_entry_handle& handle) {
-      entry_ = handle.entry_;
-    }
-
-    ResTable_entry_handle(ResTable_entry_handle&& handle) noexcept {
-      entry_ = handle.entry_;
-    }
-
-    inline static ResTable_entry_handle managed(ResTable_entry* entry, void (*deleter)(void *)) {
-      return ResTable_entry_handle(std::shared_ptr<const ResTable_entry>(entry, deleter));
-    }
-
-    inline static ResTable_entry_handle unmanaged(const ResTable_entry* entry)  {
-      return ResTable_entry_handle(std::shared_ptr<const ResTable_entry>(entry, [](auto /*p */){}));
-    }
-
-    inline ResTable_entry_handle& operator=(const ResTable_entry_handle& handle) noexcept {
-      entry_ = handle.entry_;
-      return *this;
-    }
-
-    inline ResTable_entry_handle& operator=(ResTable_entry_handle&& handle) noexcept {
-      entry_ = handle.entry_;
-      return *this;
-    }
-
-    inline const ResTable_entry* operator*() & {
-      return entry_.get();
-    }
-
- private:
-    explicit ResTable_entry_handle(std::shared_ptr<const ResTable_entry> entry)
-        : entry_(std::move(entry)) { }
-
-    std::shared_ptr<const ResTable_entry> entry_;
-};
-
 /**
  * A package-id to package name mapping for any shared libraries used
  * in this resource table. The package-id's encoded in this resource
@@ -1740,7 +1696,6 @@
   return first;
 }
 
-#pragma pack(push, 1)
 struct Idmap_header {
   // Always 0x504D4449 ('IDMP')
   uint32_t magic;
@@ -1751,7 +1706,7 @@
   uint32_t overlay_crc32;
 
   uint32_t fulfilled_policies;
-  uint8_t enforce_overlayable;
+  uint32_t enforce_overlayable;
 
   uint8_t target_path[256];
   uint8_t overlay_path[256];
@@ -1765,23 +1720,31 @@
 struct Idmap_data_header {
   uint8_t target_package_id;
   uint8_t overlay_package_id;
+
+  // Padding to ensure 4 byte alignment for target_entry_count
+  uint16_t p0;
+
   uint32_t target_entry_count;
+  uint32_t target_inline_entry_count;
   uint32_t overlay_entry_count;
+
   uint32_t string_pool_index_offset;
-  uint32_t string_pool_length;
 };
 
 struct Idmap_target_entry {
   uint32_t target_id;
-  uint8_t type;
-  uint32_t value;
+  uint32_t overlay_id;
+};
+
+struct Idmap_target_entry_inline {
+  uint32_t target_id;
+  Res_value value;
 };
 
 struct Idmap_overlay_entry {
   uint32_t overlay_id;
   uint32_t target_id;
 };
-#pragma pack(pop)
 
 class AssetManager2;
 
diff --git a/libs/androidfw/tests/CursorWindow_bench.cpp b/libs/androidfw/tests/CursorWindow_bench.cpp
new file mode 100644
index 0000000..f1191c3
--- /dev/null
+++ b/libs/androidfw/tests/CursorWindow_bench.cpp
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+#include "benchmark/benchmark.h"
+
+#include "androidfw/CursorWindow.h"
+
+namespace android {
+
+static void BM_CursorWindowWrite(benchmark::State& state, size_t rows, size_t cols) {
+    CursorWindow* w;
+    CursorWindow::create(String8("test"), 1 << 21, &w);
+
+    while (state.KeepRunning()) {
+        w->clear();
+        w->setNumColumns(cols);
+        for (int row = 0; row < rows; row++) {
+            w->allocRow();
+            for (int col = 0; col < cols; col++) {
+                w->putLong(row, col, 0xcafe);
+            }
+        }
+    }
+}
+
+static void BM_CursorWindowWrite4x4(benchmark::State& state) {
+    BM_CursorWindowWrite(state, 4, 4);
+}
+BENCHMARK(BM_CursorWindowWrite4x4);
+
+static void BM_CursorWindowWrite1Kx4(benchmark::State& state) {
+    BM_CursorWindowWrite(state, 1024, 4);
+}
+BENCHMARK(BM_CursorWindowWrite1Kx4);
+
+static void BM_CursorWindowWrite16Kx4(benchmark::State& state) {
+    BM_CursorWindowWrite(state, 16384, 4);
+}
+BENCHMARK(BM_CursorWindowWrite16Kx4);
+
+static void BM_CursorWindowRead(benchmark::State& state, size_t rows, size_t cols) {
+    CursorWindow* w;
+    CursorWindow::create(String8("test"), 1 << 21, &w);
+    w->setNumColumns(cols);
+    for (int row = 0; row < rows; row++) {
+        w->allocRow();
+    }
+
+    while (state.KeepRunning()) {
+        for (int row = 0; row < rows; row++) {
+            for (int col = 0; col < cols; col++) {
+                w->getFieldSlot(row, col);
+            }
+        }
+    }
+}
+
+static void BM_CursorWindowRead4x4(benchmark::State& state) {
+    BM_CursorWindowRead(state, 4, 4);
+}
+BENCHMARK(BM_CursorWindowRead4x4);
+
+static void BM_CursorWindowRead1Kx4(benchmark::State& state) {
+    BM_CursorWindowRead(state, 1024, 4);
+}
+BENCHMARK(BM_CursorWindowRead1Kx4);
+
+static void BM_CursorWindowRead16Kx4(benchmark::State& state) {
+    BM_CursorWindowRead(state, 16384, 4);
+}
+BENCHMARK(BM_CursorWindowRead16Kx4);
+
+}  // namespace android
diff --git a/libs/androidfw/tests/CursorWindow_test.cpp b/libs/androidfw/tests/CursorWindow_test.cpp
new file mode 100644
index 0000000..dfcf76e
--- /dev/null
+++ b/libs/androidfw/tests/CursorWindow_test.cpp
@@ -0,0 +1,359 @@
+/*
+ * 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.
+ */
+
+#include <utility>
+
+#include "androidfw/CursorWindow.h"
+
+#include "TestHelpers.h"
+
+#define CREATE_WINDOW_1K \
+    CursorWindow* w; \
+    CursorWindow::create(String8("test"), 1 << 10, &w);
+
+#define CREATE_WINDOW_1K_3X3 \
+    CursorWindow* w; \
+    CursorWindow::create(String8("test"), 1 << 10, &w); \
+    ASSERT_EQ(w->setNumColumns(3), OK); \
+    ASSERT_EQ(w->allocRow(), OK); \
+    ASSERT_EQ(w->allocRow(), OK); \
+    ASSERT_EQ(w->allocRow(), OK);
+
+#define CREATE_WINDOW_2M \
+    CursorWindow* w; \
+    CursorWindow::create(String8("test"), 1 << 21, &w);
+
+static constexpr const size_t kHalfInlineSize = 8192;
+static constexpr const size_t kGiantSize = 1048576;
+
+namespace android {
+
+TEST(CursorWindowTest, Empty) {
+    CREATE_WINDOW_1K;
+
+    ASSERT_EQ(w->getNumRows(), 0);
+    ASSERT_EQ(w->getNumColumns(), 0);
+    ASSERT_EQ(w->size(), 1 << 10);
+    ASSERT_EQ(w->freeSpace(), 1 << 10);
+}
+
+TEST(CursorWindowTest, SetNumColumns) {
+    CREATE_WINDOW_1K;
+
+    // Once we've locked in columns, we can't adjust
+    ASSERT_EQ(w->getNumColumns(), 0);
+    ASSERT_EQ(w->setNumColumns(4), OK);
+    ASSERT_NE(w->setNumColumns(5), OK);
+    ASSERT_NE(w->setNumColumns(3), OK);
+    ASSERT_EQ(w->getNumColumns(), 4);
+}
+
+TEST(CursorWindowTest, SetNumColumnsAfterRow) {
+    CREATE_WINDOW_1K;
+
+    // Once we've locked in a row, we can't adjust columns
+    ASSERT_EQ(w->getNumColumns(), 0);
+    ASSERT_EQ(w->allocRow(), OK);
+    ASSERT_NE(w->setNumColumns(4), OK);
+    ASSERT_EQ(w->getNumColumns(), 0);
+}
+
+TEST(CursorWindowTest, AllocRow) {
+    CREATE_WINDOW_1K;
+
+    ASSERT_EQ(w->setNumColumns(4), OK);
+
+    // Rolling forward means we have less free space
+    ASSERT_EQ(w->getNumRows(), 0);
+    auto before = w->freeSpace();
+    ASSERT_EQ(w->allocRow(), OK);
+    ASSERT_LT(w->freeSpace(), before);
+    ASSERT_EQ(w->getNumRows(), 1);
+
+    // Verify we can unwind
+    ASSERT_EQ(w->freeLastRow(), OK);
+    ASSERT_EQ(w->freeSpace(), before);
+    ASSERT_EQ(w->getNumRows(), 0);
+
+    // Can't unwind when no rows left
+    ASSERT_NE(w->freeLastRow(), OK);
+}
+
+TEST(CursorWindowTest, AllocRowBounds) {
+    CREATE_WINDOW_1K;
+
+    // 60 columns is 960 bytes, which means only a single row can fit
+    ASSERT_EQ(w->setNumColumns(60), OK);
+    ASSERT_EQ(w->allocRow(), OK);
+    ASSERT_NE(w->allocRow(), OK);
+}
+
+TEST(CursorWindowTest, StoreNull) {
+    CREATE_WINDOW_1K_3X3;
+
+    ASSERT_EQ(w->putNull(1, 1), OK);
+    ASSERT_EQ(w->putNull(0, 0), OK);
+
+    {
+        auto field = w->getFieldSlot(1, 1);
+        ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_NULL);
+    }
+    {
+        auto field = w->getFieldSlot(0, 0);
+        ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_NULL);
+    }
+}
+
+TEST(CursorWindowTest, StoreLong) {
+    CREATE_WINDOW_1K_3X3;
+
+    ASSERT_EQ(w->putLong(1, 1, 0xf00d), OK);
+    ASSERT_EQ(w->putLong(0, 0, 0xcafe), OK);
+
+    {
+        auto field = w->getFieldSlot(1, 1);
+        ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_INTEGER);
+        ASSERT_EQ(w->getFieldSlotValueLong(field), 0xf00d);
+    }
+    {
+        auto field = w->getFieldSlot(0, 0);
+        ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_INTEGER);
+        ASSERT_EQ(w->getFieldSlotValueLong(field), 0xcafe);
+    }
+}
+
+TEST(CursorWindowTest, StoreString) {
+    CREATE_WINDOW_1K_3X3;
+
+    ASSERT_EQ(w->putString(1, 1, "food", 5), OK);
+    ASSERT_EQ(w->putString(0, 0, "cafe", 5), OK);
+
+    size_t size;
+    {
+        auto field = w->getFieldSlot(1, 1);
+        ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_STRING);
+        auto actual = w->getFieldSlotValueString(field, &size);
+        ASSERT_EQ(std::string(actual), "food");
+    }
+    {
+        auto field = w->getFieldSlot(0, 0);
+        ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_STRING);
+        auto actual = w->getFieldSlotValueString(field, &size);
+        ASSERT_EQ(std::string(actual), "cafe");
+    }
+}
+
+TEST(CursorWindowTest, StoreBounds) {
+    CREATE_WINDOW_1K_3X3;
+
+    // Can't work with values beyond bounds
+    ASSERT_NE(w->putLong(0, 3, 0xcafe), OK);
+    ASSERT_NE(w->putLong(3, 0, 0xcafe), OK);
+    ASSERT_NE(w->putLong(3, 3, 0xcafe), OK);
+    ASSERT_EQ(w->getFieldSlot(0, 3), nullptr);
+    ASSERT_EQ(w->getFieldSlot(3, 0), nullptr);
+    ASSERT_EQ(w->getFieldSlot(3, 3), nullptr);
+}
+
+TEST(CursorWindowTest, Inflate) {
+    CREATE_WINDOW_2M;
+
+    auto before = w->size();
+    ASSERT_EQ(w->setNumColumns(4), OK);
+    ASSERT_EQ(w->allocRow(), OK);
+
+    // Scratch buffer that will fit before inflation
+    void* buf = malloc(kHalfInlineSize);
+
+    // Store simple value
+    ASSERT_EQ(w->putLong(0, 0, 0xcafe), OK);
+
+    // Store first object that fits inside
+    memset(buf, 42, kHalfInlineSize);
+    ASSERT_EQ(w->putBlob(0, 1, buf, kHalfInlineSize), OK);
+    ASSERT_EQ(w->size(), before);
+
+    // Store second simple value
+    ASSERT_EQ(w->putLong(0, 2, 0xface), OK);
+
+    // Store second object that requires inflation
+    memset(buf, 84, kHalfInlineSize);
+    ASSERT_EQ(w->putBlob(0, 3, buf, kHalfInlineSize), OK);
+    ASSERT_GT(w->size(), before);
+
+    // Verify data is intact
+    {
+        auto field = w->getFieldSlot(0, 0);
+        ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_INTEGER);
+        ASSERT_EQ(w->getFieldSlotValueLong(field), 0xcafe);
+    }
+    {
+        auto field = w->getFieldSlot(0, 1);
+        ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_BLOB);
+        size_t actualSize;
+        auto actual = w->getFieldSlotValueBlob(field, &actualSize);
+        ASSERT_EQ(actualSize, kHalfInlineSize);
+        memset(buf, 42, kHalfInlineSize);
+        ASSERT_NE(actual, buf);
+        ASSERT_EQ(memcmp(buf, actual, kHalfInlineSize), 0);
+    }
+    {
+        auto field = w->getFieldSlot(0, 2);
+        ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_INTEGER);
+        ASSERT_EQ(w->getFieldSlotValueLong(field), 0xface);
+    }
+    {
+        auto field = w->getFieldSlot(0, 3);
+        ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_BLOB);
+        size_t actualSize;
+        auto actual = w->getFieldSlotValueBlob(field, &actualSize);
+        ASSERT_EQ(actualSize, kHalfInlineSize);
+        memset(buf, 84, kHalfInlineSize);
+        ASSERT_NE(actual, buf);
+        ASSERT_EQ(memcmp(buf, actual, kHalfInlineSize), 0);
+    }
+}
+
+TEST(CursorWindowTest, ParcelEmpty) {
+    CREATE_WINDOW_2M;
+
+    Parcel p;
+    w->writeToParcel(&p);
+    p.setDataPosition(0);
+    w = nullptr;
+
+    ASSERT_EQ(CursorWindow::createFromParcel(&p, &w), OK);
+    ASSERT_EQ(w->getNumRows(), 0);
+    ASSERT_EQ(w->getNumColumns(), 0);
+    ASSERT_EQ(w->size(), 0);
+    ASSERT_EQ(w->freeSpace(), 0);
+
+    // We can't mutate the window after parceling
+    ASSERT_NE(w->setNumColumns(4), OK);
+    ASSERT_NE(w->allocRow(), OK);
+}
+
+TEST(CursorWindowTest, ParcelSmall) {
+    CREATE_WINDOW_2M;
+
+    auto before = w->size();
+    ASSERT_EQ(w->setNumColumns(4), OK);
+    ASSERT_EQ(w->allocRow(), OK);
+
+    // Scratch buffer that will fit before inflation
+    void* buf = malloc(kHalfInlineSize);
+
+    // Store simple value
+    ASSERT_EQ(w->putLong(0, 0, 0xcafe), OK);
+
+    // Store first object that fits inside
+    memset(buf, 42, kHalfInlineSize);
+    ASSERT_EQ(w->putBlob(0, 1, buf, kHalfInlineSize), OK);
+    ASSERT_EQ(w->size(), before);
+
+    // Store second object with zero length
+    ASSERT_EQ(w->putBlob(0, 2, buf, 0), OK);
+    ASSERT_EQ(w->size(), before);
+
+    // Force through a parcel
+    Parcel p;
+    w->writeToParcel(&p);
+    p.setDataPosition(0);
+    w = nullptr;
+
+    ASSERT_EQ(CursorWindow::createFromParcel(&p, &w), OK);
+    ASSERT_EQ(w->getNumRows(), 1);
+    ASSERT_EQ(w->getNumColumns(), 4);
+
+    // Verify data is intact
+    {
+        auto field = w->getFieldSlot(0, 0);
+        ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_INTEGER);
+        ASSERT_EQ(w->getFieldSlotValueLong(field), 0xcafe);
+    }
+    {
+        auto field = w->getFieldSlot(0, 1);
+        ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_BLOB);
+        size_t actualSize;
+        auto actual = w->getFieldSlotValueBlob(field, &actualSize);
+        ASSERT_EQ(actualSize, kHalfInlineSize);
+        memset(buf, 42, kHalfInlineSize);
+        ASSERT_NE(actual, buf);
+        ASSERT_EQ(memcmp(buf, actual, kHalfInlineSize), 0);
+    }
+    {
+        auto field = w->getFieldSlot(0, 2);
+        ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_BLOB);
+        size_t actualSize;
+        auto actual = w->getFieldSlotValueBlob(field, &actualSize);
+        ASSERT_EQ(actualSize, 0);
+        ASSERT_NE(actual, nullptr);
+    }
+}
+
+TEST(CursorWindowTest, ParcelLarge) {
+    CREATE_WINDOW_2M;
+
+    ASSERT_EQ(w->setNumColumns(4), OK);
+    ASSERT_EQ(w->allocRow(), OK);
+
+    // Store simple value
+    ASSERT_EQ(w->putLong(0, 0, 0xcafe), OK);
+
+    // Store object that forces inflation
+    void* buf = malloc(kGiantSize);
+    memset(buf, 42, kGiantSize);
+    ASSERT_EQ(w->putBlob(0, 1, buf, kGiantSize), OK);
+
+    // Store second object with zero length
+    ASSERT_EQ(w->putBlob(0, 2, buf, 0), OK);
+
+    // Force through a parcel
+    Parcel p;
+    w->writeToParcel(&p);
+    p.setDataPosition(0);
+    w = nullptr;
+
+    ASSERT_EQ(CursorWindow::createFromParcel(&p, &w), OK);
+    ASSERT_EQ(w->getNumRows(), 1);
+    ASSERT_EQ(w->getNumColumns(), 4);
+
+    // Verify data is intact
+    {
+        auto field = w->getFieldSlot(0, 0);
+        ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_INTEGER);
+        ASSERT_EQ(w->getFieldSlotValueLong(field), 0xcafe);
+    }
+    {
+        auto field = w->getFieldSlot(0, 1);
+        ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_BLOB);
+        size_t actualSize;
+        auto actual = w->getFieldSlotValueBlob(field, &actualSize);
+        ASSERT_EQ(actualSize, kGiantSize);
+        memset(buf, 42, kGiantSize);
+        ASSERT_EQ(memcmp(buf, actual, kGiantSize), 0);
+    }
+    {
+        auto field = w->getFieldSlot(0, 2);
+        ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_BLOB);
+        size_t actualSize;
+        auto actual = w->getFieldSlotValueBlob(field, &actualSize);
+        ASSERT_EQ(actualSize, 0);
+        ASSERT_NE(actual, nullptr);
+    }
+}
+
+} // android
diff --git a/libs/androidfw/tests/data/overlay/overlay.apk b/libs/androidfw/tests/data/overlay/overlay.apk
index f1ed592..c9bf252 100644
--- a/libs/androidfw/tests/data/overlay/overlay.apk
+++ b/libs/androidfw/tests/data/overlay/overlay.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/overlay/overlay.idmap b/libs/androidfw/tests/data/overlay/overlay.idmap
index 29c5eb6..3ab244e 100644
--- a/libs/androidfw/tests/data/overlay/overlay.idmap
+++ b/libs/androidfw/tests/data/overlay/overlay.idmap
Binary files differ
diff --git a/libs/hwui/jni/fonts/Font.cpp b/libs/hwui/jni/fonts/Font.cpp
index aeb096d..4aee6b9 100644
--- a/libs/hwui/jni/fonts/Font.cpp
+++ b/libs/hwui/jni/fonts/Font.cpp
@@ -238,6 +238,16 @@
     return reinterpret_cast<jlong>(font->font.get());
 }
 
+// Critical Native
+static jboolean Font_isSameBufferAddress(CRITICAL_JNI_PARAMS_COMMA jlong lFontHandle,
+                                         jlong rFontHandle) {
+    FontWrapper* lFont = reinterpret_cast<FontWrapper*>(lFontHandle);
+    FontWrapper* rFont = reinterpret_cast<FontWrapper*>(rFontHandle);
+    const void* lBufferPtr = lFont->font->typeface()->GetFontData();
+    const void* rBufferPtr = rFont->font->typeface()->GetFontData();
+    return lBufferPtr == rBufferPtr;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 struct FontBufferWrapper {
@@ -287,6 +297,7 @@
     { "nGetAxisInfo", "(JI)J", (void*) Font_getAxisInfo },
     { "nGetFontPath", "(J)Ljava/lang/String;", (void*) Font_getFontPath },
     { "nGetNativeFontPtr", "(J)J", (void*) Font_getNativeFontPtr },
+    { "nIsSameBufferAddress", "(JJ)Z", (void*) Font_isSameBufferAddress },
 };
 
 static const JNINativeMethod gFontBufferHelperMethods[] = {
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index 46bd221..62b4bc1 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -19,7 +19,6 @@
 import static java.util.concurrent.TimeUnit.NANOSECONDS;
 
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Build;
 import android.os.Bundle;
@@ -75,7 +74,6 @@
      * gps locations separate from other locations for coarsening. Providers that do not need to
      * support platforms below Android R should not use this constant.
      */
-    @TestApi
     @SystemApi
     @Deprecated
     public static final String EXTRA_NO_GPS_LOCATION = "noGPSLocation";
@@ -1074,7 +1072,6 @@
      * @see #isComplete
      * @hide
      */
-    @TestApi
     @SystemApi
     public void makeComplete() {
         if (mProvider == null) mProvider = "?";
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 30a4ada..ac775ca 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -575,7 +575,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(WRITE_SECURE_SETTINGS)
     public void setLocationEnabledForUser(boolean enabled, @NonNull UserHandle userHandle) {
         try {
@@ -751,7 +750,6 @@
      */
     @Deprecated
     @SystemApi
-    @TestApi
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
     public void getCurrentLocation(@NonNull LocationRequest locationRequest,
             @Nullable CancellationSignal cancellationSignal,
@@ -1192,7 +1190,6 @@
      */
     @Deprecated
     @SystemApi
-    @TestApi
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
     public void requestLocationUpdates(
             @Nullable LocationRequest locationRequest,
@@ -1223,7 +1220,6 @@
      */
     @Deprecated
     @SystemApi
-    @TestApi
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
     public void requestLocationUpdates(
             @Nullable LocationRequest locationRequest,
@@ -1255,7 +1251,6 @@
      */
     @Deprecated
     @SystemApi
-    @TestApi
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
     public void requestLocationUpdates(
             @Nullable LocationRequest locationRequest,
diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java
index 4977c21..d0706c6 100644
--- a/location/java/android/location/LocationRequest.java
+++ b/location/java/android/location/LocationRequest.java
@@ -27,7 +27,6 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.EnabledAfter;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -75,19 +74,27 @@
 
     /**
      * A quality constant indicating a location provider may choose to satisfy this request by
-     * providing very accurate locations at the expense of potentially increased power usage.
+     * providing very accurate locations at the expense of potentially increased power usage. Each
+     * location provider may interpret this field differently, but as an example, the network
+     * provider may choose to return only wifi based locations rather than cell based locations in
+     * order to have greater accuracy when this flag is present.
      */
     public static final int QUALITY_HIGH_ACCURACY = 100;
 
     /**
      * A quality constant indicating a location provider may choose to satisfy this request by
-     * equally balancing power and accuracy constraints.
+     * equally balancing power and accuracy constraints. Each location provider may interpret this
+     * field differently, but location providers will generally use their default behavior when this
+     * flag is present.
      */
     public static final int QUALITY_BALANCED_POWER_ACCURACY = 102;
 
     /**
      * A quality constant indicating a location provider may choose to satisfy this request by
-     * providing less accurate locations in order to save power.
+     * providing less accurate locations in order to save power. Each location provider may
+     * interpret this field differently, but as an example, the network provider may choose to
+     * return cell based locations rather than wifi based locations in order to save power when this
+     * flag is present.
      */
     public static final int QUALITY_LOW_POWER = 104;
 
@@ -101,7 +108,6 @@
      */
     @Deprecated
     @SystemApi
-    @TestApi
     public static final int ACCURACY_FINE = QUALITY_HIGH_ACCURACY;
 
     /**
@@ -116,7 +122,6 @@
      */
     @Deprecated
     @SystemApi
-    @TestApi
     public static final int ACCURACY_BLOCK = QUALITY_BALANCED_POWER_ACCURACY;
 
     /**
@@ -131,7 +136,6 @@
      */
     @Deprecated
     @SystemApi
-    @TestApi
     public static final int ACCURACY_CITY = QUALITY_LOW_POWER;
 
     /**
@@ -159,7 +163,6 @@
      */
     @Deprecated
     @SystemApi
-    @TestApi
     public static final int POWER_LOW = 201;
 
     /**
@@ -172,7 +175,6 @@
      */
     @Deprecated
     @SystemApi
-    @TestApi
     public static final int POWER_HIGH = 203;
 
     private static final long IMPLICIT_MIN_UPDATE_INTERVAL = -1;
@@ -618,7 +620,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public boolean isHiddenFromAppOps() {
         return mHideFromAppOps;
@@ -644,7 +645,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public boolean isLocationSettingsIgnored() {
         return mLocationSettingsIgnored;
@@ -680,7 +680,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public boolean isLowPower() {
         return mLowPower;
@@ -707,7 +706,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public @NonNull WorkSource getWorkSource() {
         return mWorkSource;
@@ -1038,7 +1036,6 @@
          *
          * @hide
          */
-        @TestApi
         @SystemApi
         @RequiresPermission(Manifest.permission.UPDATE_APP_OPS_STATS)
         public @NonNull Builder setHiddenFromAppOps(boolean hiddenFromAppOps) {
@@ -1057,7 +1054,6 @@
          *
          * @hide
          */
-        @TestApi
         @SystemApi
         @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
         public @NonNull Builder setLocationSettingsIgnored(boolean locationSettingsIgnored) {
@@ -1075,7 +1071,6 @@
          *
          * @hide
          */
-        @TestApi
         @SystemApi
         @RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
         public @NonNull Builder setLowPower(boolean lowPower) {
@@ -1093,7 +1088,6 @@
          *
          * @hide
          */
-        @TestApi
         @SystemApi
         @RequiresPermission(Manifest.permission.UPDATE_DEVICE_STATS)
         public @NonNull Builder setWorkSource(@Nullable WorkSource workSource) {
diff --git a/media/OWNERS b/media/OWNERS
index 0fc781c..e741490 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -1,4 +1,3 @@
-andrewlewis@google.com
 chz@google.com
 elaurent@google.com
 essick@google.com
@@ -18,5 +17,12 @@
 nchalko@google.com
 philburk@google.com
 quxiangfang@google.com
-sungsoo@google.com
 wonsik@google.com
+
+# LON
+andrewlewis@google.com
+aquilescanta@google.com
+olly@google.com
+
+# SEO
+sungsoo@google.com
diff --git a/media/java/android/media/AudioFocusInfo.java b/media/java/android/media/AudioFocusInfo.java
index 675cf73..3647b6e 100644
--- a/media/java/android/media/AudioFocusInfo.java
+++ b/media/java/android/media/AudioFocusInfo.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -29,7 +28,6 @@
  * @hide
  * A class to encapsulate information about an audio focus owner or request.
  */
-@TestApi
 @SystemApi
 public final class AudioFocusInfo implements Parcelable {
 
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 22b5ca5..195122d 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3916,7 +3916,6 @@
      * @param requestResult the result to the focus request to be passed to the requester
      * @param ap a valid registered {@link AudioPolicy} configured as a focus policy.
      */
-    @TestApi
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
     public void setFocusRequestResult(@NonNull AudioFocusInfo afi,
@@ -3956,7 +3955,6 @@
      *     if there was an error sending the request.
      * @throws NullPointerException if the {@link AudioFocusInfo} or {@link AudioPolicy} are null.
      */
-    @TestApi
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
     public int dispatchAudioFocusChange(@NonNull AudioFocusInfo afi, int focusChange,
@@ -4219,7 +4217,6 @@
      *    {@link android.Manifest.permission#MODIFY_AUDIO_ROUTING} permission,
      *    {@link #SUCCESS} otherwise.
      */
-    @TestApi
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
     public int registerAudioPolicy(@NonNull AudioPolicy policy) {
@@ -4254,7 +4251,6 @@
      * Unregisters an {@link AudioPolicy} asynchronously.
      * @param policy the non-null {@link AudioPolicy} to unregister.
      */
-    @TestApi
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
     public void unregisterAudioPolicyAsync(@NonNull AudioPolicy policy) {
@@ -4281,7 +4277,6 @@
      * associated with mixes of this policy.
      * @param policy the non-null {@link AudioPolicy} to unregister.
      */
-    @TestApi
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
     public void unregisterAudioPolicy(@NonNull AudioPolicy policy) {
@@ -5619,7 +5614,6 @@
      */
 
     /** @hide */
-    @TestApi
     @SystemApi
     public static final int SUCCESS = AudioSystem.SUCCESS;
     /**
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 8845d69..f9cbdd4 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -70,7 +70,6 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.TimeZone;
-import java.util.UUID;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.zip.CRC32;
@@ -2088,28 +2087,18 @@
 
         FileInputStream in = null;
         FileOutputStream out = null;
-        File originalFile = null;
-        if (mFilename != null) {
-            originalFile = new File(mFilename);
-        }
         File tempFile = null;
         try {
-            // Move the original file to temporary file.
+            // Copy the original file to temporary file.
+            tempFile = File.createTempFile("temp", "tmp");
             if (mFilename != null) {
-                String parent = originalFile.getParent();
-                String name = originalFile.getName();
-                String tempPrefix = UUID.randomUUID().toString() + "_";
-                tempFile = new File(parent, tempPrefix + name);
-                if (!originalFile.renameTo(tempFile)) {
-                    throw new IOException("Couldn't rename to " + tempFile.getAbsolutePath());
-                }
+                in = new FileInputStream(mFilename);
             } else if (mSeekableFileDescriptor != null) {
-                tempFile = File.createTempFile("temp", "tmp");
                 Os.lseek(mSeekableFileDescriptor, 0, OsConstants.SEEK_SET);
                 in = new FileInputStream(mSeekableFileDescriptor);
-                out = new FileOutputStream(tempFile);
-                copy(in, out);
             }
+            out = new FileOutputStream(tempFile);
+            copy(in, out);
         } catch (Exception e) {
             throw new IOException("Failed to copy original file to temp file", e);
         } finally {
@@ -2139,12 +2128,23 @@
                 }
             }
         } catch (Exception e) {
+            // Restore original file
+            in = new FileInputStream(tempFile);
             if (mFilename != null) {
-                if (!tempFile.renameTo(originalFile)) {
-                    throw new IOException("Couldn't restore original file: "
-                            + originalFile.getAbsolutePath());
+                out = new FileOutputStream(mFilename);
+            } else if (mSeekableFileDescriptor != null) {
+                try {
+                    Os.lseek(mSeekableFileDescriptor, 0, OsConstants.SEEK_SET);
+                } catch (ErrnoException exception) {
+                    throw new IOException("Failed to save new file. Original file may be "
+                            + "corrupted since error occurred while trying to restore it.",
+                            exception);
                 }
+                out = new FileOutputStream(mSeekableFileDescriptor);
             }
+            copy(in, out);
+            closeQuietly(in);
+            closeQuietly(out);
             throw new IOException("Failed to save new file", e);
         } finally {
             closeQuietly(in);
diff --git a/media/java/android/media/MediaTranscodeManager.java b/media/java/android/media/MediaTranscodeManager.java
index 8676462..0464036 100644
--- a/media/java/android/media/MediaTranscodeManager.java
+++ b/media/java/android/media/MediaTranscodeManager.java
@@ -22,7 +22,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.res.AssetFileDescriptor;
@@ -101,7 +100,6 @@
  TODO(hkuang): Clarify whether supports framerate conversion.
  @hide
  */
-@TestApi
 @SystemApi
 public final class MediaTranscodeManager {
     private static final String TAG = "MediaTranscodeManager";
diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java
index 61113bc..4e451c6 100644
--- a/media/java/android/media/audiopolicy/AudioMix.java
+++ b/media/java/android/media/audiopolicy/AudioMix.java
@@ -19,7 +19,6 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.media.AudioDeviceInfo;
 import android.media.AudioFormat;
@@ -32,7 +31,6 @@
 /**
  * @hide
  */
-@TestApi
 @SystemApi
 public class AudioMix {
 
diff --git a/media/java/android/media/audiopolicy/AudioMixingRule.java b/media/java/android/media/audiopolicy/AudioMixingRule.java
index 68c9593..f6f982a 100644
--- a/media/java/android/media/audiopolicy/AudioMixingRule.java
+++ b/media/java/android/media/audiopolicy/AudioMixingRule.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.media.AudioAttributes;
 import android.os.Parcel;
@@ -42,7 +41,6 @@
  *         .build();
  * </pre>
  */
-@TestApi
 @SystemApi
 public class AudioMixingRule {
 
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 8a17465..3e8d76a 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -58,7 +58,6 @@
  * @hide
  * AudioPolicy provides access to the management of audio routing and audio focus.
  */
-@TestApi
 @SystemApi
 public class AudioPolicy {
 
@@ -418,7 +417,6 @@
      * @param devices list of devices to which the audio stream of the application may be routed.
      * @return true if the change was successful, false otherwise.
      */
-    @TestApi
     @SystemApi
     public boolean setUidDeviceAffinity(int uid, @NonNull List<AudioDeviceInfo> devices) {
         if (devices == null) {
@@ -460,7 +458,6 @@
      * @param uid UID of the application affected.
      * @return true if the change was successful, false otherwise.
      */
-    @TestApi
     @SystemApi
     public boolean removeUidDeviceAffinity(int uid) {
         synchronized (mLock) {
@@ -486,7 +483,6 @@
      * {@link UserHandle#getIdentifier}. Not to be confused with application uid.
      * @return true if the change was successful, false otherwise.
      */
-    @TestApi
     @SystemApi
     public boolean removeUserIdDeviceAffinity(@UserIdInt int userId) {
         synchronized (mLock) {
@@ -519,7 +515,6 @@
      * @param devices list of devices to which the audio stream of the application may be routed.
      * @return true if the change was successful, false otherwise.
      */
-    @TestApi
     @SystemApi
     public boolean setUserIdDeviceAffinity(@UserIdInt int userId,
             @NonNull List<AudioDeviceInfo> devices) {
diff --git a/media/java/android/media/musicrecognition/MusicRecognitionManager.java b/media/java/android/media/musicrecognition/MusicRecognitionManager.java
index c7f55df..6bbcfd3 100644
--- a/media/java/android/media/musicrecognition/MusicRecognitionManager.java
+++ b/media/java/android/media/musicrecognition/MusicRecognitionManager.java
@@ -25,7 +25,6 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
-import android.annotation.TestApi;
 import android.content.Context;
 import android.media.MediaMetadata;
 import android.os.Bundle;
@@ -41,7 +40,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 @SystemService(Context.MUSIC_RECOGNITION_SERVICE)
 public class MusicRecognitionManager {
 
diff --git a/media/java/android/media/musicrecognition/MusicRecognitionService.java b/media/java/android/media/musicrecognition/MusicRecognitionService.java
index b75d2c4..e2071b8 100644
--- a/media/java/android/media/musicrecognition/MusicRecognitionService.java
+++ b/media/java/android/media/musicrecognition/MusicRecognitionService.java
@@ -21,7 +21,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.app.Service;
 import android.content.Intent;
 import android.media.AudioFormat;
@@ -41,7 +40,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public abstract class MusicRecognitionService extends Service {
 
     private static final String TAG = MusicRecognitionService.class.getSimpleName();
diff --git a/media/java/android/media/musicrecognition/RecognitionRequest.java b/media/java/android/media/musicrecognition/RecognitionRequest.java
index 65b2ccd..e4f4848 100644
--- a/media/java/android/media/musicrecognition/RecognitionRequest.java
+++ b/media/java/android/media/musicrecognition/RecognitionRequest.java
@@ -23,7 +23,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.media.AudioAttributes;
 import android.media.AudioFormat;
 import android.media.AudioRecord;
@@ -37,7 +36,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class RecognitionRequest implements Parcelable {
     @NonNull private final AudioAttributes mAudioAttributes;
     @NonNull private final AudioFormat mAudioFormat;
@@ -82,7 +80,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final class Builder {
         private AudioFormat mAudioFormat = new AudioFormat.Builder()
                 .setSampleRate(16000)
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index e17e069..f582d2a 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -609,25 +609,6 @@
     }
 
     /**
-     * Return true if this is considered an active playback state.
-     *
-     * @hide
-     */
-    public static boolean isActiveState(int state) {
-        switch (state) {
-            case PlaybackState.STATE_FAST_FORWARDING:
-            case PlaybackState.STATE_REWINDING:
-            case PlaybackState.STATE_SKIPPING_TO_PREVIOUS:
-            case PlaybackState.STATE_SKIPPING_TO_NEXT:
-            case PlaybackState.STATE_BUFFERING:
-            case PlaybackState.STATE_CONNECTING:
-            case PlaybackState.STATE_PLAYING:
-                return true;
-        }
-        return false;
-    }
-
-    /**
      * Returns whether the given bundle includes non-framework Parcelables.
      */
     static boolean hasCustomParcelable(@Nullable Bundle bundle) {
diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java
index 8dd6127..b1a88ed 100644
--- a/media/java/android/media/session/PlaybackState.java
+++ b/media/java/android/media/session/PlaybackState.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.LongDef;
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -480,6 +481,25 @@
         return mExtras;
     }
 
+    /**
+     * Returns whether this is considered as an active playback state.
+     * @hide
+     */
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    public boolean isActiveState() {
+        switch (mState) {
+            case PlaybackState.STATE_FAST_FORWARDING:
+            case PlaybackState.STATE_REWINDING:
+            case PlaybackState.STATE_SKIPPING_TO_PREVIOUS:
+            case PlaybackState.STATE_SKIPPING_TO_NEXT:
+            case PlaybackState.STATE_BUFFERING:
+            case PlaybackState.STATE_CONNECTING:
+            case PlaybackState.STATE_PLAYING:
+                return true;
+        }
+        return false;
+    }
+
     public static final @android.annotation.NonNull Parcelable.Creator<PlaybackState> CREATOR =
             new Parcelable.Creator<PlaybackState>() {
         @Override
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 56499e2..1881e38 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -775,7 +775,8 @@
      *
      * <p>This retrieve the statuses of the frontend for given status types.
      *
-     * @param statusTypes an array of status types which the caller requests.
+     * @param statusTypes an array of status types which the caller requests. Any types that are not
+     *        in {@link FrontendInfo.getStatusCapabilities()} would be ignored.
      * @return statuses which response the caller's requests. {@code null} if the operation failed.
      */
     @Nullable
@@ -1047,6 +1048,20 @@
         }
     }
 
+    private void onModulationReported(int modulation) {
+        if (mScanCallbackExecutor != null && mScanCallback != null) {
+            mScanCallbackExecutor.execute(
+                    () -> mScanCallback.onModulationReported(modulation));
+        }
+    }
+
+    private void onPriorityReported(boolean isHighPriority) {
+        if (mScanCallbackExecutor != null && mScanCallback != null) {
+            mScanCallbackExecutor.execute(
+                    () -> mScanCallback.onPriorityReported(isHighPriority));
+        }
+    }
+
     /**
      * Opens a filter object based on the given types and buffer size.
      *
diff --git a/media/java/android/media/tv/tuner/TunerVersionChecker.java b/media/java/android/media/tv/tuner/TunerVersionChecker.java
index 739f87d..b40ba1e 100644
--- a/media/java/android/media/tv/tuner/TunerVersionChecker.java
+++ b/media/java/android/media/tv/tuner/TunerVersionChecker.java
@@ -31,7 +31,6 @@
  *
  * @hide
  */
-@TestApi
 @SystemApi
 public final class TunerVersionChecker {
     private static final String TAG = "TunerVersionChecker";
diff --git a/media/java/android/media/tv/tuner/filter/AvSettings.java b/media/java/android/media/tv/tuner/filter/AvSettings.java
index e9b3660..5d9d531 100644
--- a/media/java/android/media/tv/tuner/filter/AvSettings.java
+++ b/media/java/android/media/tv/tuner/filter/AvSettings.java
@@ -16,9 +16,15 @@
 
 package android.media.tv.tuner.filter;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.hardware.tv.tuner.V1_1.Constants;
 import android.media.tv.tuner.TunerUtils;
+import android.media.tv.tuner.TunerVersionChecker;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 
 /**
  * Filter Settings for a Video and Audio.
@@ -27,15 +33,160 @@
  */
 @SystemApi
 public class AvSettings extends Settings {
-    private final boolean mIsPassthrough;
+    /** @hide */
+    @IntDef(prefix = "VIDEO_STREAM_TYPE_",
+            value = {VIDEO_STREAM_TYPE_UNDEFINED, VIDEO_STREAM_TYPE_RESERVED,
+                    VIDEO_STREAM_TYPE_MPEG1, VIDEO_STREAM_TYPE_MPEG2,
+                    VIDEO_STREAM_TYPE_MPEG4P2, VIDEO_STREAM_TYPE_AVC, VIDEO_STREAM_TYPE_HEVC,
+                    VIDEO_STREAM_TYPE_VC1, VIDEO_STREAM_TYPE_VP8, VIDEO_STREAM_TYPE_VP9,
+                    VIDEO_STREAM_TYPE_AV1, VIDEO_STREAM_TYPE_AVS, VIDEO_STREAM_TYPE_AVS2})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface VideoStreamType {}
 
-    private AvSettings(int mainType, boolean isAudio, boolean isPassthrough) {
+    /*
+     * Undefined Video stream type
+     */
+    public static final int VIDEO_STREAM_TYPE_UNDEFINED = Constants.VideoStreamType.UNDEFINED;
+    /*
+     * ITU-T | ISO/IEC Reserved
+     */
+    public static final int VIDEO_STREAM_TYPE_RESERVED = Constants.VideoStreamType.RESERVED;
+    /*
+     * ISO/IEC 11172
+     */
+    public static final int VIDEO_STREAM_TYPE_MPEG1 = Constants.VideoStreamType.MPEG1;
+    /*
+     * ITU-T Rec.H.262 and ISO/IEC 13818-2
+     */
+    public static final int VIDEO_STREAM_TYPE_MPEG2 = Constants.VideoStreamType.MPEG2;
+    /*
+     * ISO/IEC 14496-2 (MPEG-4 H.263 based video)
+     */
+    public static final int VIDEO_STREAM_TYPE_MPEG4P2 = Constants.VideoStreamType.MPEG4P2;
+    /*
+     * ITU-T Rec.H.264 and ISO/IEC 14496-10
+     */
+    public static final int VIDEO_STREAM_TYPE_AVC = Constants.VideoStreamType.AVC;
+    /*
+     * ITU-T Rec. H.265 and ISO/IEC 23008-2
+     */
+    public static final int VIDEO_STREAM_TYPE_HEVC = Constants.VideoStreamType.HEVC;
+    /*
+     * Microsoft VC.1
+     */
+    public static final int VIDEO_STREAM_TYPE_VC1 = Constants.VideoStreamType.VC1;
+    /*
+     * Google VP8
+     */
+    public static final int VIDEO_STREAM_TYPE_VP8 = Constants.VideoStreamType.VP8;
+    /*
+     * Google VP9
+     */
+    public static final int VIDEO_STREAM_TYPE_VP9 = Constants.VideoStreamType.VP9;
+    /*
+     * AOMedia Video 1
+     */
+    public static final int VIDEO_STREAM_TYPE_AV1 = Constants.VideoStreamType.AV1;
+    /*
+     * Chinese Standard
+     */
+    public static final int VIDEO_STREAM_TYPE_AVS = Constants.VideoStreamType.AVS;
+    /*
+     * New Chinese Standard
+     */
+    public static final int VIDEO_STREAM_TYPE_AVS2 = Constants.VideoStreamType.AVS2;
+
+    /** @hide */
+    @IntDef(prefix = "AUDIO_STREAM_TYPE_",
+            value = {AUDIO_STREAM_TYPE_UNDEFINED, AUDIO_STREAM_TYPE_PCM, AUDIO_STREAM_TYPE_MP3,
+                    AUDIO_STREAM_TYPE_MPEG1, AUDIO_STREAM_TYPE_MPEG2, AUDIO_STREAM_TYPE_MPEGH,
+                    AUDIO_STREAM_TYPE_AAC, AUDIO_STREAM_TYPE_AC3, AUDIO_STREAM_TYPE_EAC3,
+                    AUDIO_STREAM_TYPE_AC4, AUDIO_STREAM_TYPE_DTS, AUDIO_STREAM_TYPE_DTS_HD,
+                    AUDIO_STREAM_TYPE_WMA, AUDIO_STREAM_TYPE_OPUS, AUDIO_STREAM_TYPE_VORBIS,
+                    AUDIO_STREAM_TYPE_DRA})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface AudioStreamType {}
+
+    /*
+     * Undefined Audio stream type
+     */
+    public static final int AUDIO_STREAM_TYPE_UNDEFINED = Constants.AudioStreamType.UNDEFINED;
+    /*
+     * Uncompressed Audio
+     */
+    public static final int AUDIO_STREAM_TYPE_PCM = Constants.AudioStreamType.PCM;
+    /*
+     * MPEG Audio Layer III versions
+     */
+    public static final int AUDIO_STREAM_TYPE_MP3 = Constants.AudioStreamType.MP3;
+    /*
+     * ISO/IEC 11172 Audio
+     */
+    public static final int AUDIO_STREAM_TYPE_MPEG1 = Constants.AudioStreamType.MPEG1;
+    /*
+     * ISO/IEC 13818-3
+     */
+    public static final int AUDIO_STREAM_TYPE_MPEG2 = Constants.AudioStreamType.MPEG2;
+    /*
+     * ISO/IEC 23008-3 (MPEG-H Part 3)
+     */
+    public static final int AUDIO_STREAM_TYPE_MPEGH = Constants.AudioStreamType.MPEGH;
+    /*
+     * ISO/IEC 14496-3
+     */
+    public static final int AUDIO_STREAM_TYPE_AAC = Constants.AudioStreamType.AAC;
+    /*
+     * Dolby Digital
+     */
+    public static final int AUDIO_STREAM_TYPE_AC3 = Constants.AudioStreamType.AC3;
+    /*
+     * Dolby Digital Plus
+     */
+    public static final int AUDIO_STREAM_TYPE_EAC3 = Constants.AudioStreamType.EAC3;
+    /*
+     * Dolby AC-4
+     */
+    public static final int AUDIO_STREAM_TYPE_AC4 = Constants.AudioStreamType.AC4;
+    /*
+     * Basic DTS
+     */
+    public static final int AUDIO_STREAM_TYPE_DTS = Constants.AudioStreamType.DTS;
+    /*
+     * High Resolution DTS
+     */
+    public static final int AUDIO_STREAM_TYPE_DTS_HD = Constants.AudioStreamType.DTS_HD;
+    /*
+     * Windows Media Audio
+     */
+    public static final int AUDIO_STREAM_TYPE_WMA = Constants.AudioStreamType.WMA;
+    /*
+     * Opus Interactive Audio Codec
+     */
+    public static final int AUDIO_STREAM_TYPE_OPUS = Constants.AudioStreamType.OPUS;
+    /*
+     * VORBIS Interactive Audio Codec
+     */
+    public static final int AUDIO_STREAM_TYPE_VORBIS = Constants.AudioStreamType.VORBIS;
+    /*
+     * SJ/T 11368-2006
+     */
+    public static final int AUDIO_STREAM_TYPE_DRA = Constants.AudioStreamType.DRA;
+
+
+    private final boolean mIsPassthrough;
+    private int mAudioStreamType = AUDIO_STREAM_TYPE_UNDEFINED;
+    private int mVideoStreamType = VIDEO_STREAM_TYPE_UNDEFINED;
+
+    private AvSettings(int mainType, boolean isAudio, boolean isPassthrough,
+            int audioStreamType, int videoStreamType) {
         super(TunerUtils.getFilterSubtype(
                 mainType,
                 isAudio
                         ? Filter.SUBTYPE_AUDIO
                         : Filter.SUBTYPE_VIDEO));
         mIsPassthrough = isPassthrough;
+        mAudioStreamType = audioStreamType;
+        mVideoStreamType = videoStreamType;
     }
 
     /**
@@ -46,6 +197,20 @@
     }
 
     /**
+     * Get the Audio Stream Type.
+     */
+    public int getAudioStreamType() {
+        return mAudioStreamType;
+    }
+
+    /**
+     * Get the Video Stream Type.
+     */
+    public int getVideoStreamType() {
+        return mVideoStreamType;
+    }
+
+    /**
      * Creates a builder for {@link AvSettings}.
      *
      * @param mainType the filter main type.
@@ -63,6 +228,8 @@
         private final int mMainType;
         private final boolean mIsAudio;
         private boolean mIsPassthrough;
+        private int mAudioStreamType = AUDIO_STREAM_TYPE_UNDEFINED;
+        private int mVideoStreamType = VIDEO_STREAM_TYPE_UNDEFINED;
 
         private Builder(int mainType, boolean isAudio) {
             mMainType = mainType;
@@ -79,11 +246,48 @@
         }
 
         /**
+         * Sets the Audio Stream Type.
+         *
+         * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
+         * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
+         *
+         * @param audioStreamType the {@link AudioStreamType} to set.
+         */
+        @NonNull
+        public Builder setAudioStreamType(@AudioStreamType int audioStreamType) {
+            if (TunerVersionChecker.checkHigherOrEqualVersionTo(
+                    TunerVersionChecker.TUNER_VERSION_1_1, "setAudioStreamType") && mIsAudio) {
+                mAudioStreamType = audioStreamType;
+                mVideoStreamType = VIDEO_STREAM_TYPE_UNDEFINED;
+            }
+            return this;
+        }
+
+        /**
+         * Sets the Video Stream Type.
+         *
+         * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
+         * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
+         *
+         * @param videoStreamType the {@link VideoStreamType} to set.
+         */
+        @NonNull
+        public Builder setVideoStreamType(@VideoStreamType int videoStreamType) {
+            if (TunerVersionChecker.checkHigherOrEqualVersionTo(
+                    TunerVersionChecker.TUNER_VERSION_1_1, "setVideoStreamType") && !mIsAudio) {
+                mVideoStreamType = videoStreamType;
+                mAudioStreamType = AUDIO_STREAM_TYPE_UNDEFINED;
+            }
+            return this;
+        }
+
+        /**
          * Builds a {@link AvSettings} object.
          */
         @NonNull
         public AvSettings build() {
-            return new AvSettings(mMainType, mIsAudio, mIsPassthrough);
+            return new AvSettings(mMainType, mIsAudio, mIsPassthrough,
+                    mAudioStreamType, mVideoStreamType);
         }
     }
 }
diff --git a/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java b/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java
index 2649fcf..62d55f5 100644
--- a/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java
+++ b/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java
@@ -16,6 +16,7 @@
 
 package android.media.tv.tuner.filter;
 
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.Size;
@@ -101,6 +102,7 @@
      * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would return
      * default value. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
      */
+    @IntRange(from = 0, to = 0xefff)
     public int getIpFilterContextId() {
         return mIpFilterContextId;
     }
diff --git a/media/java/android/media/tv/tuner/filter/MediaEvent.java b/media/java/android/media/tv/tuner/filter/MediaEvent.java
index 57a04fd..91be5c3 100644
--- a/media/java/android/media/tv/tuner/filter/MediaEvent.java
+++ b/media/java/android/media/tv/tuner/filter/MediaEvent.java
@@ -187,7 +187,6 @@
 
     /**
      * Releases the MediaEvent object.
-     * @hide
      */
     public void release() {
         synchronized (mLock) {
diff --git a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
index 343dbb1..fadc004 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
@@ -260,10 +260,12 @@
     private final int mVcmMode;
     // Dvbs scan type is only supported in Tuner 1.1 or higher.
     private final int mScanType;
+    // isDiseqcRxMessage is only supported in Tuner 1.1 or higher.
+    private final boolean mIsDiseqcRxMessage;
 
     private DvbsFrontendSettings(int frequency, int modulation, DvbsCodeRate codeRate,
             int symbolRate, int rolloff, int pilot, int inputStreamId, int standard, int vcm,
-            int scanType) {
+            int scanType, boolean isDiseqcRxMessage) {
         super(frequency);
         mModulation = modulation;
         mCodeRate = codeRate;
@@ -274,6 +276,7 @@
         mStandard = standard;
         mVcmMode = vcm;
         mScanType = scanType;
+        mIsDiseqcRxMessage = isDiseqcRxMessage;
     }
 
     /**
@@ -337,6 +340,15 @@
     public int getScanType() {
         return mScanType;
     }
+    /**
+     * To receive Diseqc Message or not. Default value is false.
+     *
+     * The setter {@link Builder#setDiseqcRxMessage(boolean)} is only supported with Tuner HAL 1.1
+     * or higher.
+     */
+    public boolean isDiseqcRxMessage() {
+        return mIsDiseqcRxMessage;
+    }
 
     /**
      * Creates a builder for {@link DvbsFrontendSettings}.
@@ -360,6 +372,7 @@
         private int mStandard = STANDARD_AUTO;
         private int mVcmMode = VCM_MODE_UNDEFINED;
         private int mScanType = SCAN_TYPE_UNDEFINED;
+        private boolean mIsDiseqcRxMessage = false;
 
         private Builder() {
         }
@@ -395,6 +408,21 @@
         }
 
         /**
+         * Set true to receive Diseqc Message.
+         *
+         * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
+         * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
+         */
+        @NonNull
+        public Builder setDiseqcRxMessage(boolean isDiseqcRxMessage) {
+            if (TunerVersionChecker.checkHigherOrEqualVersionTo(
+                        TunerVersionChecker.TUNER_VERSION_1_1, "setDiseqcRxMessage")) {
+                mIsDiseqcRxMessage = isDiseqcRxMessage;
+            }
+            return this;
+        }
+
+        /**
          * Sets Modulation.
          *
          * <p>Default value is {@link #MODULATION_UNDEFINED}.
@@ -481,7 +509,8 @@
         @NonNull
         public DvbsFrontendSettings build() {
             return new DvbsFrontendSettings(mFrequency, mModulation, mCodeRate, mSymbolRate,
-                    mRolloff, mPilot, mInputStreamId, mStandard, mVcmMode, mScanType);
+                    mRolloff, mPilot, mInputStreamId, mStandard, mVcmMode, mScanType,
+                    mIsDiseqcRxMessage);
         }
     }
 
diff --git a/media/java/android/media/tv/tuner/frontend/FrontendStatus.java b/media/java/android/media/tv/tuner/frontend/FrontendStatus.java
index c265bb9..dd9347c 100644
--- a/media/java/android/media/tv/tuner/frontend/FrontendStatus.java
+++ b/media/java/android/media/tv/tuner/frontend/FrontendStatus.java
@@ -21,6 +21,7 @@
 import android.annotation.SystemApi;
 import android.hardware.tv.tuner.V1_0.Constants;
 import android.media.tv.tuner.Lnb;
+import android.media.tv.tuner.TunerVersionChecker;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -43,7 +44,13 @@
             FRONTEND_STATUS_TYPE_EWBS, FRONTEND_STATUS_TYPE_AGC, FRONTEND_STATUS_TYPE_LNA,
             FRONTEND_STATUS_TYPE_LAYER_ERROR, FRONTEND_STATUS_TYPE_MER,
             FRONTEND_STATUS_TYPE_FREQ_OFFSET, FRONTEND_STATUS_TYPE_HIERARCHY,
-            FRONTEND_STATUS_TYPE_RF_LOCK, FRONTEND_STATUS_TYPE_ATSC3_PLP_INFO})
+            FRONTEND_STATUS_TYPE_RF_LOCK, FRONTEND_STATUS_TYPE_ATSC3_PLP_INFO,
+            FRONTEND_STATUS_TYPE_BERS, FRONTEND_STATUS_TYPE_CODERATES,
+            FRONTEND_STATUS_TYPE_BANDWIDTH, FRONTEND_STATUS_TYPE_GUARD_INTERVAL,
+            FRONTEND_STATUS_TYPE_TRANSMISSION_MODE, FRONTEND_STATUS_TYPE_UEC,
+            FRONTEND_STATUS_TYPE_T2_SYSTEM_ID, FRONTEND_STATUS_TYPE_INTERLEAVINGS,
+            FRONTEND_STATUS_TYPE_ISDBT_SEGMENTS, FRONTEND_STATUS_TYPE_TS_DATA_RATES,
+            FRONTEND_STATUS_TYPE_MODULATIONS_EXT})
     @Retention(RetentionPolicy.SOURCE)
     public @interface FrontendStatusType {}
 
@@ -145,10 +152,83 @@
      */
     public static final int FRONTEND_STATUS_TYPE_ATSC3_PLP_INFO =
             Constants.FrontendStatusType.ATSC3_PLP_INFO;
-
+    /**
+     * BERS Type. Only supported in Tuner HAL 1.1 or higher.
+     */
+    public static final int FRONTEND_STATUS_TYPE_BERS =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.BERS;
+    /**
+     * Coderate Type. Only supported in Tuner HAL 1.1 or higher.
+     */
+    public static final int FRONTEND_STATUS_TYPE_CODERATES =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.CODERATES;
+    /**
+     * Bandwidth Type. Only supported in Tuner HAL 1.1 or higher.
+     */
+    public static final int FRONTEND_STATUS_TYPE_BANDWIDTH =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.BANDWIDTH;
+    /**
+     * Guard Interval Type. Only supported in Tuner HAL 1.1 or higher.
+     */
+    public static final int FRONTEND_STATUS_TYPE_GUARD_INTERVAL =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.GUARD_INTERVAL;
+    /**
+     * Transmission Mode Type. Only supported in Tuner HAL 1.1 or higher.
+     */
+    public static final int FRONTEND_STATUS_TYPE_TRANSMISSION_MODE =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.TRANSMISSION_MODE;
+    /**
+     * UEC Type. Only supported in Tuner HAL 1.1 or higher.
+     */
+    public static final int FRONTEND_STATUS_TYPE_UEC =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.UEC;
+    /**
+     * T2 System Id Type. Only supported in Tuner HAL 1.1 or higher.
+     */
+    public static final int FRONTEND_STATUS_TYPE_T2_SYSTEM_ID =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.T2_SYSTEM_ID;
+    /**
+     * Interleavings Type. Only supported in Tuner HAL 1.1 or higher.
+     */
+    public static final int FRONTEND_STATUS_TYPE_INTERLEAVINGS =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.INTERLEAVINGS;
+    /**
+     * ISDBT Segments Type. Only supported in Tuner HAL 1.1 or higher.
+     */
+    public static final int FRONTEND_STATUS_TYPE_ISDBT_SEGMENTS =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.ISDBT_SEGMENTS;
+    /**
+     * TS Data Rates Type. Only supported in Tuner HAL 1.1 or higher.
+     */
+    public static final int FRONTEND_STATUS_TYPE_TS_DATA_RATES =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.TS_DATA_RATES;
+    /**
+     * Extended Modulations Type. Only supported in Tuner HAL 1.1 or higher.
+     */
+    public static final int FRONTEND_STATUS_TYPE_MODULATIONS_EXT =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.MODULATIONS;
 
     /** @hide */
     @IntDef(value = {
+            AtscFrontendSettings.MODULATION_UNDEFINED,
+            AtscFrontendSettings.MODULATION_AUTO,
+            AtscFrontendSettings.MODULATION_MOD_8VSB,
+            AtscFrontendSettings.MODULATION_MOD_16VSB,
+            Atsc3FrontendSettings.MODULATION_UNDEFINED,
+            Atsc3FrontendSettings.MODULATION_AUTO,
+            Atsc3FrontendSettings.MODULATION_MOD_QPSK,
+            Atsc3FrontendSettings.MODULATION_MOD_16QAM,
+            Atsc3FrontendSettings.MODULATION_MOD_64QAM,
+            Atsc3FrontendSettings.MODULATION_MOD_256QAM,
+            Atsc3FrontendSettings.MODULATION_MOD_1024QAM,
+            Atsc3FrontendSettings.MODULATION_MOD_4096QAM,
+            DtmbFrontendSettings.MODULATION_CONSTELLATION_UNDEFINED,
+            DtmbFrontendSettings.MODULATION_CONSTELLATION_AUTO,
+            DtmbFrontendSettings.MODULATION_CONSTELLATION_4QAM,
+            DtmbFrontendSettings.MODULATION_CONSTELLATION_4QAM_NR,
+            DtmbFrontendSettings.MODULATION_CONSTELLATION_16QAM,
+            DtmbFrontendSettings.MODULATION_CONSTELLATION_32QAM,
+            DtmbFrontendSettings.MODULATION_CONSTELLATION_64QAM,
             DvbcFrontendSettings.MODULATION_UNDEFINED,
             DvbcFrontendSettings.MODULATION_AUTO,
             DvbcFrontendSettings.MODULATION_MOD_16QAM,
@@ -171,6 +251,16 @@
             DvbsFrontendSettings.MODULATION_MOD_128APSK,
             DvbsFrontendSettings.MODULATION_MOD_256APSK,
             DvbsFrontendSettings.MODULATION_MOD_RESERVED,
+            DvbtFrontendSettings.CONSTELLATION_UNDEFINED,
+            DvbtFrontendSettings.CONSTELLATION_AUTO,
+            DvbtFrontendSettings.CONSTELLATION_QPSK,
+            DvbtFrontendSettings.CONSTELLATION_16QAM,
+            DvbtFrontendSettings.CONSTELLATION_64QAM,
+            DvbtFrontendSettings.CONSTELLATION_256QAM,
+            DvbtFrontendSettings.CONSTELLATION_QPSK_R,
+            DvbtFrontendSettings.CONSTELLATION_16QAM_R,
+            DvbtFrontendSettings.CONSTELLATION_64QAM_R,
+            DvbtFrontendSettings.CONSTELLATION_256QAM_R,
             IsdbsFrontendSettings.MODULATION_UNDEFINED,
             IsdbsFrontendSettings.MODULATION_AUTO,
             IsdbsFrontendSettings.MODULATION_MOD_BPSK,
@@ -192,6 +282,101 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface FrontendModulation {}
 
+    /** @hide */
+    @IntDef(value = {
+            Atsc3FrontendSettings.TIME_INTERLEAVE_MODE_UNDEFINED,
+            Atsc3FrontendSettings.TIME_INTERLEAVE_MODE_AUTO,
+            Atsc3FrontendSettings.TIME_INTERLEAVE_MODE_CTI,
+            Atsc3FrontendSettings.TIME_INTERLEAVE_MODE_HTI,
+            DtmbFrontendSettings.TIME_INTERLEAVE_MODE_UNDEFINED,
+            DtmbFrontendSettings.TIME_INTERLEAVE_MODE_AUTO,
+            DtmbFrontendSettings.TIME_INTERLEAVE_MODE_TIMER_INT_240,
+            DtmbFrontendSettings.TIME_INTERLEAVE_MODE_TIMER_INT_720,
+            DvbcFrontendSettings.TIME_INTERLEAVE_MODE_UNDEFINED,
+            DvbcFrontendSettings.TIME_INTERLEAVE_MODE_AUTO,
+            DvbcFrontendSettings.TIME_INTERLEAVE_MODE_128_1_0,
+            DvbcFrontendSettings.TIME_INTERLEAVE_MODE_128_1_1,
+            DvbcFrontendSettings.TIME_INTERLEAVE_MODE_64_2,
+            DvbcFrontendSettings.TIME_INTERLEAVE_MODE_32_4,
+            DvbcFrontendSettings.TIME_INTERLEAVE_MODE_16_8,
+            DvbcFrontendSettings.TIME_INTERLEAVE_MODE_8_16,
+            DvbcFrontendSettings.TIME_INTERLEAVE_MODE_128_2,
+            DvbcFrontendSettings.TIME_INTERLEAVE_MODE_128_3,
+            DvbcFrontendSettings.TIME_INTERLEAVE_MODE_128_4})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface FrontendInterleaveMode {}
+
+    /** @hide */
+    @IntDef(value = {
+            Atsc3FrontendSettings.BANDWIDTH_UNDEFINED,
+            Atsc3FrontendSettings.BANDWIDTH_AUTO,
+            Atsc3FrontendSettings.BANDWIDTH_BANDWIDTH_6MHZ,
+            Atsc3FrontendSettings.BANDWIDTH_BANDWIDTH_7MHZ,
+            Atsc3FrontendSettings.BANDWIDTH_BANDWIDTH_8MHZ,
+            DtmbFrontendSettings.BANDWIDTH_UNDEFINED,
+            DtmbFrontendSettings.BANDWIDTH_AUTO,
+            DtmbFrontendSettings.BANDWIDTH_6MHZ,
+            DtmbFrontendSettings.BANDWIDTH_8MHZ,
+            DvbtFrontendSettings.BANDWIDTH_UNDEFINED,
+            DvbtFrontendSettings.BANDWIDTH_AUTO,
+            DvbtFrontendSettings.BANDWIDTH_8MHZ,
+            DvbtFrontendSettings.BANDWIDTH_7MHZ,
+            DvbtFrontendSettings.BANDWIDTH_6MHZ,
+            DvbtFrontendSettings.BANDWIDTH_5MHZ,
+            DvbtFrontendSettings.BANDWIDTH_1_7MHZ,
+            DvbtFrontendSettings.BANDWIDTH_10MHZ,
+            IsdbtFrontendSettings.BANDWIDTH_UNDEFINED,
+            IsdbtFrontendSettings.BANDWIDTH_AUTO,
+            IsdbtFrontendSettings.BANDWIDTH_8MHZ,
+            IsdbtFrontendSettings.BANDWIDTH_7MHZ,
+            IsdbtFrontendSettings.BANDWIDTH_6MHZ})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface FrontendBandwidth {}
+
+    /** @hide */
+    @IntDef(value = {
+            DtmbFrontendSettings.TRANSMISSION_MODE_UNDEFINED,
+            DtmbFrontendSettings.TRANSMISSION_MODE_AUTO,
+            DtmbFrontendSettings.TRANSMISSION_MODE_C1,
+            DtmbFrontendSettings.TRANSMISSION_MODE_C3780,
+            DvbtFrontendSettings.TRANSMISSION_MODE_UNDEFINED,
+            DvbtFrontendSettings.TRANSMISSION_MODE_AUTO,
+            DvbtFrontendSettings.TRANSMISSION_MODE_2K,
+            DvbtFrontendSettings.TRANSMISSION_MODE_8K,
+            DvbtFrontendSettings.TRANSMISSION_MODE_4K,
+            DvbtFrontendSettings.TRANSMISSION_MODE_1K,
+            DvbtFrontendSettings.TRANSMISSION_MODE_16K,
+            DvbtFrontendSettings.TRANSMISSION_MODE_32K,
+            IsdbtFrontendSettings.MODE_UNDEFINED,
+            IsdbtFrontendSettings.MODE_AUTO,
+            IsdbtFrontendSettings.MODE_1,
+            IsdbtFrontendSettings.MODE_2,
+            IsdbtFrontendSettings.MODE_3})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface FrontendTransmissionMode {}
+
+    /** @hide */
+    @IntDef(value = {
+            DtmbFrontendSettings.GUARD_INTERVAL_UNDEFINED,
+            DtmbFrontendSettings.GUARD_INTERVAL_AUTO,
+            DtmbFrontendSettings.GUARD_INTERVAL_PN_420_VARIOUS,
+            DtmbFrontendSettings.GUARD_INTERVAL_PN_595_CONST,
+            DtmbFrontendSettings.GUARD_INTERVAL_PN_945_VARIOUS,
+            DtmbFrontendSettings.GUARD_INTERVAL_PN_420_CONST,
+            DtmbFrontendSettings.GUARD_INTERVAL_PN_945_CONST,
+            DtmbFrontendSettings.GUARD_INTERVAL_PN_RESERVED,
+            DvbtFrontendSettings.GUARD_INTERVAL_UNDEFINED,
+            DvbtFrontendSettings.GUARD_INTERVAL_AUTO,
+            DvbtFrontendSettings.GUARD_INTERVAL_1_32,
+            DvbtFrontendSettings.GUARD_INTERVAL_1_16,
+            DvbtFrontendSettings.GUARD_INTERVAL_1_8,
+            DvbtFrontendSettings.GUARD_INTERVAL_1_4,
+            DvbtFrontendSettings.GUARD_INTERVAL_1_128,
+            DvbtFrontendSettings.GUARD_INTERVAL_19_128,
+            DvbtFrontendSettings.GUARD_INTERVAL_19_256,
+            DvbtFrontendSettings.GUARD_INTERVAL_19_128})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface FrontendGuardInterval {}
 
     private Boolean mIsDemodLocked;
     private Integer mSnr;
@@ -215,6 +400,18 @@
     private Integer mHierarchy;
     private Boolean mIsRfLocked;
     private Atsc3PlpTuningInfo[] mPlpInfo;
+    private int[] mBers;
+    private int[] mCodeRates;
+    private Integer mBandwidth;
+    private Integer mGuardInterval;
+    private Integer mTransmissionMode;
+    private Integer mUec;
+    private Integer mSystemId;
+    private int[] mInterleaving;
+    private int[] mTsDataRate;
+    private int[] mIsdbtSegment;
+    private int[] mModulationsExt;
+
 
     // Constructed and fields set by JNI code.
     private FrontendStatus() {
@@ -323,7 +520,7 @@
     /**
      * Gets Spectral Inversion for DVBC.
      */
-    @DvbcFrontendSettings.SpectralInversion
+    @FrontendSettings.FrontendSpectralInversion
     public int getSpectralInversion() {
         if (mInversion == null) {
             throw new IllegalStateException();
@@ -437,6 +634,182 @@
     }
 
     /**
+     * Gets an array of BERS status.
+     *
+     * <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
+     * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     */
+    @NonNull
+    public int[] getBers() {
+        TunerVersionChecker.checkHigherOrEqualVersionTo(
+                TunerVersionChecker.TUNER_VERSION_1_1, "getBers status");
+        if (mBers == null) {
+            throw new IllegalStateException();
+        }
+        return mBers;
+    }
+
+    /**
+     * Gets an array of code rates status.
+     *
+     * <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
+     * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     */
+    @NonNull
+    public int[] getCodeRates() {
+        TunerVersionChecker.checkHigherOrEqualVersionTo(
+                TunerVersionChecker.TUNER_VERSION_1_1, "getCodeRates status");
+        if (mCodeRates == null) {
+            throw new IllegalStateException();
+        }
+        return mCodeRates;
+    }
+
+    /**
+     * Gets bandwidth status.
+     *
+     * <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
+     * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     */
+    @FrontendBandwidth
+    public int getBandwidth() {
+        TunerVersionChecker.checkHigherOrEqualVersionTo(
+                TunerVersionChecker.TUNER_VERSION_1_1, "getBandwidth status");
+        if (mBandwidth == null) {
+            throw new IllegalStateException();
+        }
+        return mBandwidth;
+    }
+
+    /**
+     * Gets guard interval status.
+     *
+     * <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
+     * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     */
+    @FrontendGuardInterval
+    public int getGuardInterval() {
+        TunerVersionChecker.checkHigherOrEqualVersionTo(
+                TunerVersionChecker.TUNER_VERSION_1_1, "getGuardInterval status");
+        if (mGuardInterval == null) {
+            throw new IllegalStateException();
+        }
+        return mGuardInterval;
+    }
+
+    /**
+     * Gets tansmission mode status.
+     *
+     * <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
+     * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     */
+    @FrontendTransmissionMode
+    public int getTransmissionMode() {
+        TunerVersionChecker.checkHigherOrEqualVersionTo(
+                TunerVersionChecker.TUNER_VERSION_1_1, "getTransmissionMode status");
+        if (mTransmissionMode == null) {
+            throw new IllegalStateException();
+        }
+        return mTransmissionMode;
+    }
+
+    /**
+     * Gets UEC status.
+     *
+     * <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
+     * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     */
+    public int getUec() {
+        TunerVersionChecker.checkHigherOrEqualVersionTo(
+                TunerVersionChecker.TUNER_VERSION_1_1, "getUec status");
+        if (mUec == null) {
+            throw new IllegalStateException();
+        }
+        return mUec;
+    }
+
+    /**
+     * Gets system id status.
+     *
+     * <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
+     * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     */
+    public int getSystemId() {
+        TunerVersionChecker.checkHigherOrEqualVersionTo(
+                TunerVersionChecker.TUNER_VERSION_1_1, "getSystemId status");
+        if (mSystemId == null) {
+            throw new IllegalStateException();
+        }
+        return mSystemId;
+    }
+
+    /**
+     * Gets an array of interleaving status. Array value should be withink {@link
+     * FrontendInterleaveMode}.
+     *
+     * <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
+     * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     */
+    @NonNull
+    public int[] getInterleaving() {
+        TunerVersionChecker.checkHigherOrEqualVersionTo(
+                TunerVersionChecker.TUNER_VERSION_1_1, "getInterleaving status");
+        if (mInterleaving == null) {
+            throw new IllegalStateException();
+        }
+        return mInterleaving;
+    }
+
+    /**
+     * Gets an array of isdbt segment status.
+     *
+     * <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
+     * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     */
+    @NonNull
+    public int[] getIsdbtSegment() {
+        TunerVersionChecker.checkHigherOrEqualVersionTo(
+                TunerVersionChecker.TUNER_VERSION_1_1, "getIsdbtSegment status");
+        if (mIsdbtSegment == null) {
+            throw new IllegalStateException();
+        }
+        return mIsdbtSegment;
+    }
+
+    /**
+     * Gets an array of TS data rate status.
+     *
+     * <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
+     * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     */
+    @NonNull
+    public int[] getTsDataRate() {
+        TunerVersionChecker.checkHigherOrEqualVersionTo(
+                TunerVersionChecker.TUNER_VERSION_1_1, "getTsDataRate status");
+        if (mTsDataRate == null) {
+            throw new IllegalStateException();
+        }
+        return mTsDataRate;
+    }
+
+    /**
+     * Gets an array of the extended modulations status. Array value should be withink {@link
+     * FrontendModulation}.
+     *
+     * <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
+     * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     */
+    @NonNull
+    public int[] getModulationsExt() {
+        TunerVersionChecker.checkHigherOrEqualVersionTo(
+                TunerVersionChecker.TUNER_VERSION_1_1, "getModulationsExt status");
+        if (mModulationsExt == null) {
+            throw new IllegalStateException();
+        }
+        return mModulationsExt;
+    }
+
+    /**
      * Status for each tuning Physical Layer Pipes.
      */
     public static class Atsc3PlpTuningInfo {
diff --git a/media/java/android/media/tv/tuner/frontend/ScanCallback.java b/media/java/android/media/tv/tuner/frontend/ScanCallback.java
index b0491fd..c1400c8 100644
--- a/media/java/android/media/tv/tuner/frontend/ScanCallback.java
+++ b/media/java/android/media/tv/tuner/frontend/ScanCallback.java
@@ -19,6 +19,7 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.util.Log;
 
 /**
  * Scan callback.
@@ -27,6 +28,8 @@
  */
 @SystemApi
 public interface ScanCallback {
+    /** @hide **/
+    String TAG = "ScanCallback";
 
     /** Scan locked the signal. */
     void onLocked();
@@ -70,4 +73,13 @@
     /** Frontend signal type. */
     void onSignalTypeReported(@AnalogFrontendSettings.SignalType int signalType);
 
+    /** Frontend modulation reported. */
+    default void onModulationReported(@FrontendStatus.FrontendModulation int modulation) {
+        Log.d(TAG, "Received modulation scan message");
+    }
+
+    /** Frontend scan message priority reported. */
+    default void onPriorityReported(boolean isHighPriority) {
+        Log.d(TAG, "Received priority scan message: isHighPriority=" + isHighPriority);
+    }
 }
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 6a1acede..1be0d44 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -132,10 +132,13 @@
 using ::android::hardware::tv::tuner::V1_0::LnbVoltage;
 using ::android::hardware::tv::tuner::V1_0::PlaybackSettings;
 using ::android::hardware::tv::tuner::V1_0::RecordSettings;
+using ::android::hardware::tv::tuner::V1_1::AudioStreamType;
+using ::android::hardware::tv::tuner::V1_1::AvStreamType;
 using ::android::hardware::tv::tuner::V1_1::Constant;
 using ::android::hardware::tv::tuner::V1_1::Constant64Bit;
 using ::android::hardware::tv::tuner::V1_1::FrontendAnalogAftFlag;
 using ::android::hardware::tv::tuner::V1_1::FrontendAnalogSettingsExt1_1;
+using ::android::hardware::tv::tuner::V1_1::FrontendBandwidth;
 using ::android::hardware::tv::tuner::V1_1::FrontendCableTimeInterleaveMode;
 using ::android::hardware::tv::tuner::V1_1::FrontendDvbsScanType;
 using ::android::hardware::tv::tuner::V1_1::FrontendDvbcSettingsExt1_1;
@@ -149,7 +152,14 @@
 using ::android::hardware::tv::tuner::V1_1::FrontendDtmbSettings;
 using ::android::hardware::tv::tuner::V1_1::FrontendDtmbTimeInterleaveMode;
 using ::android::hardware::tv::tuner::V1_1::FrontendDtmbTransmissionMode;
+using ::android::hardware::tv::tuner::V1_1::FrontendGuardInterval;
+using ::android::hardware::tv::tuner::V1_1::FrontendInterleaveMode;
+using ::android::hardware::tv::tuner::V1_1::FrontendModulation;
 using ::android::hardware::tv::tuner::V1_1::FrontendSpectralInversion;
+using ::android::hardware::tv::tuner::V1_1::FrontendStatusExt1_1;
+using ::android::hardware::tv::tuner::V1_1::FrontendStatusTypeExt1_1;
+using ::android::hardware::tv::tuner::V1_1::FrontendTransmissionMode;
+using ::android::hardware::tv::tuner::V1_1::VideoStreamType;
 
 struct fields_t {
     jfieldID tunerContext;
@@ -986,6 +996,77 @@
     return Void();
 }
 
+Return<void> FrontendCallback::onScanMessageExt1_1(FrontendScanMessageTypeExt1_1 type,
+        const FrontendScanMessageExt1_1& message) {
+    ALOGD("FrontendCallback::onScanMessageExt1_1, type=%d", type);
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    jclass clazz = env->FindClass("android/media/tv/tuner/Tuner");
+    switch(type) {
+        case FrontendScanMessageTypeExt1_1::MODULATION: {
+            jint modulation = -1;
+            switch (message.modulation().getDiscriminator()) {
+                case FrontendModulation::hidl_discriminator::dvbc: {
+                    modulation = (jint) message.modulation().dvbc();
+                    break;
+                }
+                case FrontendModulation::hidl_discriminator::dvbt: {
+                    modulation = (jint) message.modulation().dvbt();
+                    break;
+                }
+                case FrontendModulation::hidl_discriminator::dvbs: {
+                    modulation = (jint) message.modulation().dvbs();
+                    break;
+                }
+                case FrontendModulation::hidl_discriminator::isdbs: {
+                    modulation = (jint) message.modulation().isdbs();
+                    break;
+                }
+                case FrontendModulation::hidl_discriminator::isdbs3: {
+                    modulation = (jint) message.modulation().isdbs3();
+                    break;
+                }
+                case FrontendModulation::hidl_discriminator::isdbt: {
+                    modulation = (jint) message.modulation().isdbt();
+                    break;
+                }
+                case FrontendModulation::hidl_discriminator::atsc: {
+                    modulation = (jint) message.modulation().atsc();
+                    break;
+                }
+                case FrontendModulation::hidl_discriminator::atsc3: {
+                    modulation = (jint) message.modulation().atsc3();
+                    break;
+                }
+                case FrontendModulation::hidl_discriminator::dtmb: {
+                    modulation = (jint) message.modulation().dtmb();
+                    break;
+                }
+                default: {
+                    break;
+                }
+            }
+            if (modulation > 0) {
+                env->CallVoidMethod(
+                        mObject,
+                        env->GetMethodID(clazz, "onModulationReported", "(I)V"),
+                        modulation);
+            }
+            break;
+        }
+        case FrontendScanMessageTypeExt1_1::HIGH_PRIORITY: {
+            bool isHighPriority = message.isHighPriority();
+            env->CallVoidMethod(
+                    mObject,
+                    env->GetMethodID(clazz, "onPriorityReported", "([B)V"),
+                    isHighPriority);
+            break;
+        }
+        default:
+            break;
+    }
+    return Void();
+}
+
 /////////////// Tuner ///////////////////////
 
 sp<ITuner> JTuner::mTuner;
@@ -1862,18 +1943,49 @@
     }
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jsize size = env->GetArrayLength(types);
-    std::vector<FrontendStatusType> v(size);
-    env->GetIntArrayRegion(types, 0, size, reinterpret_cast<jint*>(&v[0]));
+    jint intTypes[size];
+    env->GetIntArrayRegion(types, 0, size, intTypes);
+    std::vector<FrontendStatusType> v;
+    std::vector<FrontendStatusTypeExt1_1> v_1_1;
+    for (int i = 0; i < size; i++) {
+        if (isV1_1ExtendedStatusType(intTypes[i])) {
+            v_1_1.push_back(static_cast<FrontendStatusTypeExt1_1>(intTypes[i]));
+        } else {
+            v.push_back(static_cast<FrontendStatusType>(intTypes[i]));
+        }
+    }
 
     Result res;
     hidl_vec<FrontendStatus> status;
-    mFe->getStatus(v,
-            [&](Result r, const hidl_vec<FrontendStatus>& s) {
-                res = r;
-                status = s;
-            });
-    if (res != Result::SUCCESS) {
-        return NULL;
+    hidl_vec<FrontendStatusExt1_1> status_1_1;
+
+    if (v.size() > 0) {
+        mFe->getStatus(v,
+                [&](Result r, const hidl_vec<FrontendStatus>& s) {
+                    res = r;
+                    status = s;
+                });
+        if (res != Result::SUCCESS) {
+            return NULL;
+        }
+    }
+
+    if (v_1_1.size() > 0) {
+        sp<::android::hardware::tv::tuner::V1_1::IFrontend> iFeSp_1_1;
+        iFeSp_1_1 = ::android::hardware::tv::tuner::V1_1::IFrontend::castFrom(mFe);
+
+        if (iFeSp_1_1 != NULL) {
+            iFeSp_1_1->getStatusExt1_1(v_1_1,
+                [&](Result r, const hidl_vec<FrontendStatusExt1_1>& s) {
+                    res = r;
+                    status_1_1 = s;
+                });
+            if (res != Result::SUCCESS) {
+                return NULL;
+            }
+        } else {
+            ALOGW("getStatusExt1_1 is not supported with the current HAL implementation.");
+        }
     }
 
     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendStatus");
@@ -2101,9 +2213,274 @@
         }
     }
 
+    for (auto s : status_1_1) {
+        switch(s.getDiscriminator()) {
+            case FrontendStatusExt1_1::hidl_discriminator::modulations: {
+                jfieldID field = env->GetFieldID(clazz, "mModulationsExt", "[I");
+                std::vector<FrontendModulation> v = s.modulations();
+
+                jintArray valObj = env->NewIntArray(v.size());
+                bool valid = false;
+                jint m[1];
+                for (int i = 0; i < v.size(); i++) {
+                    auto modulation = v[i];
+                    switch(modulation.getDiscriminator()) {
+                        case FrontendModulation::hidl_discriminator::dvbc: {
+                            m[0] = static_cast<jint>(modulation.dvbc());
+                            env->SetIntArrayRegion(valObj, i, 1, m);
+                            valid = true;
+                            break;
+                        }
+                        case FrontendModulation::hidl_discriminator::dvbs: {
+                            m[0] = static_cast<jint>(modulation.dvbs());
+                            env->SetIntArrayRegion(valObj, i, 1, m);
+                            valid = true;
+                           break;
+                        }
+                        case FrontendModulation::hidl_discriminator::dvbt: {
+                            m[0] = static_cast<jint>(modulation.dvbt());
+                            env->SetIntArrayRegion(valObj, i, 1, m);
+                            valid = true;
+                            break;
+                        }
+                        case FrontendModulation::hidl_discriminator::isdbs: {
+                            m[0] = static_cast<jint>(modulation.isdbs());
+                            env->SetIntArrayRegion(valObj, i, 1, m);
+                            valid = true;
+                            break;
+                        }
+                        case FrontendModulation::hidl_discriminator::isdbs3: {
+                            m[0] = static_cast<jint>(modulation.isdbs3());
+                            env->SetIntArrayRegion(valObj, i, 1, m);
+                            valid = true;
+                            break;
+                        }
+                        case FrontendModulation::hidl_discriminator::isdbt: {
+                            m[0] = static_cast<jint>(modulation.isdbt());
+                            env->SetIntArrayRegion(valObj, i, 1, m);
+                            valid = true;
+                            break;
+                        }
+                        case FrontendModulation::hidl_discriminator::atsc: {
+                            m[0] = static_cast<jint>(modulation.atsc());
+                            env->SetIntArrayRegion(valObj, i, 1, m);
+                            valid = true;
+                            break;
+                        }
+                        case FrontendModulation::hidl_discriminator::atsc3: {
+                            m[0] = static_cast<jint>(modulation.atsc3());
+                            env->SetIntArrayRegion(valObj, i, 1, m);
+                            valid = true;
+                            break;
+                        }
+                        case FrontendModulation::hidl_discriminator::dtmb: {
+                            m[0] = static_cast<jint>(modulation.dtmb());
+                            env->SetIntArrayRegion(valObj, i, 1, m);
+                            valid = true;
+                            break;
+                        }
+                        default:
+                            break;
+                    }
+                }
+                if (valid) {
+                    env->SetObjectField(statusObj, field, valObj);
+                }
+                break;
+            }
+            case FrontendStatusExt1_1::hidl_discriminator::bers: {
+                jfieldID field = env->GetFieldID(clazz, "mBers", "[I");
+                std::vector<uint32_t> v = s.bers();
+
+                jintArray valObj = env->NewIntArray(v.size());
+                env->SetIntArrayRegion(valObj, 0, v.size(), reinterpret_cast<jint*>(&v[0]));
+
+                env->SetObjectField(statusObj, field, valObj);
+                break;
+            }
+            case FrontendStatusExt1_1::hidl_discriminator::codeRates: {
+                jfieldID field = env->GetFieldID(clazz, "mCodeRates", "[I");
+                std::vector<::android::hardware::tv::tuner::V1_1::FrontendInnerFec> v
+                        = s.codeRates();
+
+                jintArray valObj = env->NewIntArray(v.size());
+                env->SetIntArrayRegion(valObj, 0, v.size(), reinterpret_cast<jint*>(&v[0]));
+
+                env->SetObjectField(statusObj, field, valObj);
+                break;
+            }
+            case FrontendStatusExt1_1::hidl_discriminator::bandwidth: {
+                jfieldID field = env->GetFieldID(clazz, "mBandwidth", "Ljava/lang/Integer;");
+                auto bandwidth = s.bandwidth();
+                jint intBandwidth;
+                bool valid = true;
+                switch(bandwidth.getDiscriminator()) {
+                    case FrontendBandwidth::hidl_discriminator::atsc3: {
+                        intBandwidth = static_cast<jint>(bandwidth.atsc3());
+                        break;
+                    }
+                    case FrontendBandwidth::hidl_discriminator::dvbt: {
+                        intBandwidth = static_cast<jint>(bandwidth.dvbt());
+                        break;
+                    }
+                    case FrontendBandwidth::hidl_discriminator::isdbt: {
+                        intBandwidth = static_cast<jint>(bandwidth.isdbt());
+                        break;
+                    }
+                    case FrontendBandwidth::hidl_discriminator::dtmb: {
+                        intBandwidth = static_cast<jint>(bandwidth.dtmb());
+                        break;
+                    }
+                    default:
+                        valid = false;
+                        break;
+                }
+                if (valid) {
+                    jobject newIntegerObj = env->NewObject(intClazz, initInt, intBandwidth);
+                    env->SetObjectField(statusObj, field, newIntegerObj);
+                }
+                break;
+            }
+            case FrontendStatusExt1_1::hidl_discriminator::interval: {
+                jfieldID field = env->GetFieldID(clazz, "mGuardInterval", "Ljava/lang/Integer;");
+                auto interval = s.interval();
+                jint intInterval;
+                bool valid = true;
+                switch(interval.getDiscriminator()) {
+                    case FrontendGuardInterval::hidl_discriminator::dvbt: {
+                        intInterval = static_cast<jint>(interval.dvbt());
+                        break;
+                    }
+                    case FrontendGuardInterval::hidl_discriminator::isdbt: {
+                        intInterval = static_cast<jint>(interval.isdbt());
+                        break;
+                    }
+                    case FrontendGuardInterval::hidl_discriminator::dtmb: {
+                        intInterval = static_cast<jint>(interval.dtmb());
+                        break;
+                    }
+                    default:
+                        valid = false;
+                        break;
+                }
+                if (valid) {
+                    jobject newIntegerObj = env->NewObject(intClazz, initInt, intInterval);
+                    env->SetObjectField(statusObj, field, newIntegerObj);
+                }
+                break;
+            }
+            case FrontendStatusExt1_1::hidl_discriminator::transmissionMode: {
+                jfieldID field = env->GetFieldID(clazz, "mTransmissionMode", "Ljava/lang/Integer;");
+                auto transmissionMode = s.transmissionMode();
+                jint intTransmissionMode;
+                bool valid = true;
+                switch(transmissionMode.getDiscriminator()) {
+                    case FrontendTransmissionMode::hidl_discriminator::dvbt: {
+                        intTransmissionMode = static_cast<jint>(transmissionMode.dvbt());
+                        break;
+                    }
+                    case FrontendTransmissionMode::hidl_discriminator::isdbt: {
+                        intTransmissionMode = static_cast<jint>(transmissionMode.isdbt());
+                        break;
+                    }
+                    case FrontendTransmissionMode::hidl_discriminator::dtmb: {
+                        intTransmissionMode = static_cast<jint>(transmissionMode.dtmb());
+                        break;
+                    }
+                    default:
+                        valid = false;
+                        break;
+                }
+                if (valid) {
+                    jobject newIntegerObj = env->NewObject(intClazz, initInt, intTransmissionMode);
+                    env->SetObjectField(statusObj, field, newIntegerObj);
+                }
+                break;
+            }
+            case FrontendStatusExt1_1::hidl_discriminator::uec: {
+                jfieldID field = env->GetFieldID(clazz, "mUec", "Ljava/lang/Integer;");
+                jobject newIntegerObj = env->NewObject(
+                        intClazz, initInt, static_cast<jint>(s.uec()));
+                env->SetObjectField(statusObj, field, newIntegerObj);
+                break;
+            }
+            case FrontendStatusExt1_1::hidl_discriminator::systemId: {
+                jfieldID field = env->GetFieldID(clazz, "mSystemId", "Ljava/lang/Integer;");
+                jobject newIntegerObj = env->NewObject(
+                        intClazz, initInt, static_cast<jint>(s.systemId()));
+                env->SetObjectField(statusObj, field, newIntegerObj);
+                break;
+            }
+            case FrontendStatusExt1_1::hidl_discriminator::interleaving: {
+                jfieldID field = env->GetFieldID(clazz, "mInterleaving", "[I");
+
+                std::vector<FrontendInterleaveMode> v = s.interleaving();
+                jintArray valObj = env->NewIntArray(v.size());
+                bool valid = false;
+                jint in[1];
+                for (int i = 0; i < v.size(); i++) {
+                    auto interleaving = v[i];
+                    switch(interleaving.getDiscriminator()) {
+                        case FrontendInterleaveMode::hidl_discriminator::atsc3: {
+                            in[0] = static_cast<jint>(interleaving.atsc3());
+                            env->SetIntArrayRegion(valObj, i, 1, in);
+                            valid = true;
+                            break;
+                        }
+                        case FrontendInterleaveMode::hidl_discriminator::dvbc: {
+                            in[0] = static_cast<jint>(interleaving.dvbc());
+                            env->SetIntArrayRegion(valObj, i, 1, in);
+                            valid = true;
+                           break;
+                        }
+                        case FrontendInterleaveMode::hidl_discriminator::dtmb: {
+                            in[0] = static_cast<jint>(interleaving.dtmb());
+                            env->SetIntArrayRegion(valObj, i, 1, in);
+                            valid = true;
+                           break;
+                        }
+                        default:
+                            break;
+                    }
+                }
+                if (valid) {
+                    env->SetObjectField(statusObj, field, valObj);
+                }
+                break;
+            }
+            case FrontendStatusExt1_1::hidl_discriminator::isdbtSegment: {
+                jfieldID field = env->GetFieldID(clazz, "mIsdbtSegment", "[I");
+                std::vector<uint8_t> v = s.isdbtSegment();
+
+                jintArray valObj = env->NewIntArray(v.size());
+                env->SetIntArrayRegion(valObj, 0, v.size(), reinterpret_cast<jint*>(&v[0]));
+
+                env->SetObjectField(statusObj, field, valObj);
+                break;
+            }
+            case FrontendStatusExt1_1::hidl_discriminator::tsDataRate: {
+                jfieldID field = env->GetFieldID(clazz, "mTsDataRate", "[I");
+                std::vector<uint32_t> v = s.tsDataRate();
+
+                jintArray valObj = env->NewIntArray(v.size());
+                env->SetIntArrayRegion(valObj, 0, v.size(), reinterpret_cast<jint*>(&v[0]));
+
+                env->SetObjectField(statusObj, field, valObj);
+                break;
+            }
+            default: {
+                break;
+            }
+        }
+    }
     return statusObj;
 }
 
+bool JTuner::isV1_1ExtendedStatusType(int type) {
+    return (type > static_cast<int>(FrontendStatusType::ATSC3_PLP_INFO)
+                && type <= static_cast<int>(FrontendStatusTypeExt1_1::TS_DATA_RATES));
+}
+
 jint JTuner::closeFrontend() {
     Result r = Result::SUCCESS;
     if (mFe != NULL) {
@@ -3114,6 +3491,31 @@
     return filterAvSettings;
 }
 
+static bool getAvStreamType(JNIEnv *env, jobject filterConfigObj, AvStreamType& type) {
+    jobject settingsObj =
+            env->GetObjectField(
+                    filterConfigObj,
+                    env->GetFieldID(
+                            env->FindClass("android/media/tv/tuner/filter/FilterConfiguration"),
+                            "mSettings",
+                            "Landroid/media/tv/tuner/filter/Settings;"));
+    jclass clazz = env->FindClass("android/media/tv/tuner/filter/AvSettings");
+    AvStreamType streamType;
+    AudioStreamType audioStreamType = static_cast<AudioStreamType>(
+            env->GetIntField(settingsObj, env->GetFieldID(clazz, "mAudioStreamType", "I")));
+    if (audioStreamType != AudioStreamType::UNDEFINED) {
+        type.audio(audioStreamType);
+        return true;
+    }
+    VideoStreamType videoStreamType = static_cast<VideoStreamType>(
+            env->GetIntField(settingsObj, env->GetFieldID(clazz, "mVideoStreamType", "I")));
+    if (videoStreamType != VideoStreamType::UNDEFINED) {
+        type.video(videoStreamType);
+        return true;
+    }
+    return false;
+}
+
 static DemuxFilterPesDataSettings getFilterPesDataSettings(JNIEnv *env, const jobject& settings) {
     jclass clazz = env->FindClass("android/media/tv/tuner/filter/PesSettings");
     uint16_t streamId = static_cast<uint16_t>(
@@ -3436,6 +3838,16 @@
     return size;
 }
 
+static bool isAvFilterSettings(DemuxFilterSettings filterSettings) {
+    return (filterSettings.getDiscriminator() == DemuxFilterSettings::hidl_discriminator::ts
+            && filterSettings.ts().filterSettings.getDiscriminator()
+                    == DemuxTsFilterSettings::FilterSettings::hidl_discriminator::av)
+            ||
+            (filterSettings.getDiscriminator() == DemuxFilterSettings::hidl_discriminator::mmtp
+            && filterSettings.mmtp().filterSettings.getDiscriminator()
+                    == DemuxMmtpFilterSettings::FilterSettings::hidl_discriminator::av);
+}
+
 static jint android_media_tv_Tuner_configure_filter(
         JNIEnv *env, jobject filter, int type, int subtype, jobject settings) {
     ALOGD("configure filter type=%d, subtype=%d", type, subtype);
@@ -3459,6 +3871,20 @@
         }
     }
 
+    AvStreamType streamType;
+    if (isAvFilterSettings(filterSettings) && getAvStreamType(env, settings, streamType)) {
+        sp<::android::hardware::tv::tuner::V1_1::IFilter> iFilterSp_1_1;
+        iFilterSp_1_1 = ::android::hardware::tv::tuner::V1_1::IFilter::castFrom(iFilterSp);
+        if (iFilterSp_1_1 != NULL) {
+            res = iFilterSp_1_1->configureAvStreamType(streamType);
+        } else {
+            ALOGW("configureAvStreamType is not supported with the current HAL implementation.");
+        }
+        if (res != Result::SUCCESS) {
+            return (jint) res;
+        }
+    }
+
     MQDescriptorSync<uint8_t> filterMQDesc;
     Result getQueueDescResult = Result::UNKNOWN_ERROR;
     if (filterSp->mFilterMQ == NULL) {
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index 2b73f31..71d2983 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -20,6 +20,7 @@
 #include <android/hardware/tv/tuner/1.1/IFilter.h>
 #include <android/hardware/tv/tuner/1.1/IFilterCallback.h>
 #include <android/hardware/tv/tuner/1.1/IFrontend.h>
+#include <android/hardware/tv/tuner/1.1/IFrontendCallback.h>
 #include <android/hardware/tv/tuner/1.1/ITuner.h>
 #include <android/hardware/tv/tuner/1.1/types.h>
 
@@ -63,7 +64,6 @@
 using ::android::hardware::tv::tuner::V1_0::IFilter;
 using ::android::hardware::tv::tuner::V1_1::IFilterCallback;
 using ::android::hardware::tv::tuner::V1_0::IFrontend;
-using ::android::hardware::tv::tuner::V1_0::IFrontendCallback;
 using ::android::hardware::tv::tuner::V1_0::ILnb;
 using ::android::hardware::tv::tuner::V1_0::ILnbCallback;
 using ::android::hardware::tv::tuner::V1_0::ITimeFilter;
@@ -73,6 +73,9 @@
 using ::android::hardware::tv::tuner::V1_0::PlaybackStatus;
 using ::android::hardware::tv::tuner::V1_0::RecordStatus;
 using ::android::hardware::tv::tuner::V1_0::Result;
+using ::android::hardware::tv::tuner::V1_1::FrontendScanMessageExt1_1;
+using ::android::hardware::tv::tuner::V1_1::FrontendScanMessageTypeExt1_1;
+using ::android::hardware::tv::tuner::V1_1::IFrontendCallback;
 
 using MQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
 
@@ -191,6 +194,8 @@
     virtual Return<void> onEvent(FrontendEventType frontendEventType);
     virtual Return<void> onScanMessage(
             FrontendScanMessageType type, const FrontendScanMessage& message);
+    virtual Return<void> onScanMessageExt1_1(
+            FrontendScanMessageTypeExt1_1 type, const FrontendScanMessageExt1_1& messageExt);
 
     jweak mObject;
     FrontendId mId;
@@ -268,6 +273,8 @@
     static jobject getIsdbsFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps);
     static jobject getIsdbtFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps);
     static jobject getDtmbFrontendCaps(JNIEnv *env, int id);
+
+    bool isV1_1ExtendedStatusType(jint type);
 };
 
 class C2DataIdInfo : public C2Param {
diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt
index 45d2214..babd54d 100644
--- a/non-updatable-api/current.txt
+++ b/non-updatable-api/current.txt
@@ -10668,12 +10668,15 @@
     field public static final String ACTION_PACKAGE_CHANGED = "android.intent.action.PACKAGE_CHANGED";
     field public static final String ACTION_PACKAGE_DATA_CLEARED = "android.intent.action.PACKAGE_DATA_CLEARED";
     field public static final String ACTION_PACKAGE_FIRST_LAUNCH = "android.intent.action.PACKAGE_FIRST_LAUNCH";
+    field public static final String ACTION_PACKAGE_FULLY_LOADED = "android.intent.action.PACKAGE_FULLY_LOADED";
     field public static final String ACTION_PACKAGE_FULLY_REMOVED = "android.intent.action.PACKAGE_FULLY_REMOVED";
     field @Deprecated public static final String ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL";
     field public static final String ACTION_PACKAGE_NEEDS_VERIFICATION = "android.intent.action.PACKAGE_NEEDS_VERIFICATION";
     field public static final String ACTION_PACKAGE_REMOVED = "android.intent.action.PACKAGE_REMOVED";
     field public static final String ACTION_PACKAGE_REPLACED = "android.intent.action.PACKAGE_REPLACED";
     field public static final String ACTION_PACKAGE_RESTARTED = "android.intent.action.PACKAGE_RESTARTED";
+    field public static final String ACTION_PACKAGE_STARTABLE = "android.intent.action.PACKAGE_STARTABLE";
+    field public static final String ACTION_PACKAGE_UNSTARTABLE = "android.intent.action.PACKAGE_UNSTARTABLE";
     field public static final String ACTION_PACKAGE_VERIFIED = "android.intent.action.PACKAGE_VERIFIED";
     field public static final String ACTION_PASTE = "android.intent.action.PASTE";
     field public static final String ACTION_PICK = "android.intent.action.PICK";
@@ -10838,6 +10841,7 @@
     field public static final String EXTRA_TIMEZONE = "time-zone";
     field public static final String EXTRA_TITLE = "android.intent.extra.TITLE";
     field public static final String EXTRA_UID = "android.intent.extra.UID";
+    field public static final String EXTRA_UNSTARTABLE_REASON = "android.intent.extra.UNSTARTABLE_REASON";
     field public static final String EXTRA_USER = "android.intent.extra.USER";
     field public static final int FILL_IN_ACTION = 1; // 0x1
     field public static final int FILL_IN_CATEGORIES = 4; // 0x4
@@ -12297,6 +12301,9 @@
     field public static final int SYNCHRONOUS = 2; // 0x2
     field @Nullable public static final java.util.List<java.security.cert.Certificate> TRUST_ALL;
     field @NonNull public static final java.util.List<java.security.cert.Certificate> TRUST_NONE;
+    field public static final int UNSTARTABLE_REASON_CONNECTION_ERROR = 1; // 0x1
+    field public static final int UNSTARTABLE_REASON_INSUFFICIENT_STORAGE = 2; // 0x2
+    field public static final int UNSTARTABLE_REASON_UNKNOWN = 0; // 0x0
     field public static final int VERIFICATION_ALLOW = 1; // 0x1
     field public static final int VERIFICATION_REJECT = -1; // 0xffffffff
     field public static final int VERSION_CODE_HIGHEST = -1; // 0xffffffff
diff --git a/non-updatable-api/module-lib-current.txt b/non-updatable-api/module-lib-current.txt
index 3c1d19f..9b83a29 100644
--- a/non-updatable-api/module-lib-current.txt
+++ b/non-updatable-api/module-lib-current.txt
@@ -93,6 +93,10 @@
     field public static final int RESULT_MEDIA_KEY_NOT_HANDLED = 0; // 0x0
   }
 
+  public final class PlaybackState implements android.os.Parcelable {
+    method public boolean isActiveState();
+  }
+
 }
 
 package android.os {
diff --git a/non-updatable-api/system-current.txt b/non-updatable-api/system-current.txt
index f558b48..3b66735 100644
--- a/non-updatable-api/system-current.txt
+++ b/non-updatable-api/system-current.txt
@@ -225,6 +225,7 @@
     field public static final String SET_WALLPAPER_COMPONENT = "android.permission.SET_WALLPAPER_COMPONENT";
     field public static final String SHOW_KEYGUARD_MESSAGE = "android.permission.SHOW_KEYGUARD_MESSAGE";
     field public static final String SHUTDOWN = "android.permission.SHUTDOWN";
+    field public static final String START_ACTIVITIES_FROM_BACKGROUND = "android.permission.START_ACTIVITIES_FROM_BACKGROUND";
     field public static final String STATUS_BAR_SERVICE = "android.permission.STATUS_BAR_SERVICE";
     field public static final String STOP_APP_SWITCHES = "android.permission.STOP_APP_SWITCHES";
     field public static final String SUBSTITUTE_NOTIFICATION_APP_NAME = "android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME";
@@ -594,7 +595,7 @@
 
   public class BroadcastOptions {
     method public static android.app.BroadcastOptions makeBasic();
-    method @RequiresPermission("android.permission.START_ACTIVITIES_FROM_BACKGROUND") public void setBackgroundActivityStartsAllowed(boolean);
+    method @RequiresPermission(android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND) public void setBackgroundActivityStartsAllowed(boolean);
     method public void setDontSendToRestrictedApps(boolean);
     method @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST) public void setTemporaryAppWhitelistDuration(long);
     method public android.os.Bundle toBundle();
@@ -1742,6 +1743,7 @@
     field public static final String APP_PREDICTION_SERVICE = "app_prediction";
     field public static final String BACKUP_SERVICE = "backup";
     field public static final String BATTERY_STATS_SERVICE = "batterystats";
+    field public static final int BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS = 1048576; // 0x100000
     field public static final String BUGREPORT_SERVICE = "bugreport";
     field public static final String CONTENT_SUGGESTIONS_SERVICE = "content_suggestions";
     field public static final String CONTEXTHUB_SERVICE = "contexthub";
@@ -5148,12 +5150,45 @@
 
   public class AvSettings extends android.media.tv.tuner.filter.Settings {
     method @NonNull public static android.media.tv.tuner.filter.AvSettings.Builder builder(int, boolean);
+    method public int getAudioStreamType();
+    method public int getVideoStreamType();
     method public boolean isPassthrough();
+    field public static final int AUDIO_STREAM_TYPE_AAC = 6; // 0x6
+    field public static final int AUDIO_STREAM_TYPE_AC3 = 7; // 0x7
+    field public static final int AUDIO_STREAM_TYPE_AC4 = 9; // 0x9
+    field public static final int AUDIO_STREAM_TYPE_DRA = 15; // 0xf
+    field public static final int AUDIO_STREAM_TYPE_DTS = 10; // 0xa
+    field public static final int AUDIO_STREAM_TYPE_DTS_HD = 11; // 0xb
+    field public static final int AUDIO_STREAM_TYPE_EAC3 = 8; // 0x8
+    field public static final int AUDIO_STREAM_TYPE_MP3 = 2; // 0x2
+    field public static final int AUDIO_STREAM_TYPE_MPEG1 = 3; // 0x3
+    field public static final int AUDIO_STREAM_TYPE_MPEG2 = 4; // 0x4
+    field public static final int AUDIO_STREAM_TYPE_MPEGH = 5; // 0x5
+    field public static final int AUDIO_STREAM_TYPE_OPUS = 13; // 0xd
+    field public static final int AUDIO_STREAM_TYPE_PCM = 1; // 0x1
+    field public static final int AUDIO_STREAM_TYPE_UNDEFINED = 0; // 0x0
+    field public static final int AUDIO_STREAM_TYPE_VORBIS = 14; // 0xe
+    field public static final int AUDIO_STREAM_TYPE_WMA = 12; // 0xc
+    field public static final int VIDEO_STREAM_TYPE_AV1 = 10; // 0xa
+    field public static final int VIDEO_STREAM_TYPE_AVC = 5; // 0x5
+    field public static final int VIDEO_STREAM_TYPE_AVS = 11; // 0xb
+    field public static final int VIDEO_STREAM_TYPE_AVS2 = 12; // 0xc
+    field public static final int VIDEO_STREAM_TYPE_HEVC = 6; // 0x6
+    field public static final int VIDEO_STREAM_TYPE_MPEG1 = 2; // 0x2
+    field public static final int VIDEO_STREAM_TYPE_MPEG2 = 3; // 0x3
+    field public static final int VIDEO_STREAM_TYPE_MPEG4P2 = 4; // 0x4
+    field public static final int VIDEO_STREAM_TYPE_RESERVED = 1; // 0x1
+    field public static final int VIDEO_STREAM_TYPE_UNDEFINED = 0; // 0x0
+    field public static final int VIDEO_STREAM_TYPE_VC1 = 7; // 0x7
+    field public static final int VIDEO_STREAM_TYPE_VP8 = 8; // 0x8
+    field public static final int VIDEO_STREAM_TYPE_VP9 = 9; // 0x9
   }
 
   public static class AvSettings.Builder {
     method @NonNull public android.media.tv.tuner.filter.AvSettings build();
+    method @NonNull public android.media.tv.tuner.filter.AvSettings.Builder setAudioStreamType(int);
     method @NonNull public android.media.tv.tuner.filter.AvSettings.Builder setPassthrough(boolean);
+    method @NonNull public android.media.tv.tuner.filter.AvSettings.Builder setVideoStreamType(int);
   }
 
   public class DownloadEvent extends android.media.tv.tuner.filter.FilterEvent {
@@ -5231,7 +5266,7 @@
     method @NonNull public static android.media.tv.tuner.filter.IpFilterConfiguration.Builder builder();
     method @NonNull @Size(min=4, max=16) public byte[] getDstIpAddress();
     method public int getDstPort();
-    method public int getIpFilterContextId();
+    method @IntRange(from=0, to=61439) public int getIpFilterContextId();
     method @NonNull @Size(min=4, max=16) public byte[] getSrcIpAddress();
     method public int getSrcPort();
     method public int getType();
@@ -5267,6 +5302,7 @@
     method public boolean isPrivateData();
     method public boolean isPtsPresent();
     method public boolean isSecureMemory();
+    method public void release();
   }
 
   public final class MmtpFilterConfiguration extends android.media.tv.tuner.filter.FilterConfiguration {
@@ -5773,6 +5809,7 @@
     method public int getSymbolRate();
     method public int getType();
     method public int getVcmMode();
+    method public boolean isDiseqcRxMessage();
     field public static final int MODULATION_AUTO = 1; // 0x1
     field public static final int MODULATION_MOD_128APSK = 2048; // 0x800
     field public static final int MODULATION_MOD_16APSK = 256; // 0x100
@@ -5816,6 +5853,7 @@
   public static class DvbsFrontendSettings.Builder {
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings build();
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setCodeRate(@Nullable android.media.tv.tuner.frontend.DvbsCodeRate);
+    method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setDiseqcRxMessage(boolean);
     method @IntRange(from=1) @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setFrequency(int);
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setInputStreamId(int);
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setModulation(int);
@@ -6017,14 +6055,21 @@
   public class FrontendStatus {
     method public int getAgc();
     method @NonNull public android.media.tv.tuner.frontend.FrontendStatus.Atsc3PlpTuningInfo[] getAtsc3PlpTuningInfo();
+    method public int getBandwidth();
     method public int getBer();
+    method @NonNull public int[] getBers();
+    method @NonNull public int[] getCodeRates();
     method public int getFreqOffset();
+    method public int getGuardInterval();
     method public int getHierarchy();
     method public long getInnerFec();
+    method @NonNull public int[] getInterleaving();
+    method @NonNull public int[] getIsdbtSegment();
     method @NonNull public boolean[] getLayerErrors();
     method public int getLnbVoltage();
     method public int getMer();
     method public int getModulation();
+    method @NonNull public int[] getModulationsExt();
     method public int getPer();
     method public int getPerBer();
     method public int getPlpId();
@@ -6033,23 +6078,34 @@
     method public int getSnr();
     method public int getSpectralInversion();
     method public int getSymbolRate();
+    method public int getSystemId();
+    method public int getTransmissionMode();
+    method @NonNull public int[] getTsDataRate();
+    method public int getUec();
     method public boolean isDemodLocked();
     method public boolean isEwbs();
     method public boolean isLnaOn();
     method public boolean isRfLocked();
     field public static final int FRONTEND_STATUS_TYPE_AGC = 14; // 0xe
     field public static final int FRONTEND_STATUS_TYPE_ATSC3_PLP_INFO = 21; // 0x15
+    field public static final int FRONTEND_STATUS_TYPE_BANDWIDTH = 25; // 0x19
     field public static final int FRONTEND_STATUS_TYPE_BER = 2; // 0x2
+    field public static final int FRONTEND_STATUS_TYPE_BERS = 23; // 0x17
+    field public static final int FRONTEND_STATUS_TYPE_CODERATES = 24; // 0x18
     field public static final int FRONTEND_STATUS_TYPE_DEMOD_LOCK = 0; // 0x0
     field public static final int FRONTEND_STATUS_TYPE_EWBS = 13; // 0xd
     field public static final int FRONTEND_STATUS_TYPE_FEC = 8; // 0x8
     field public static final int FRONTEND_STATUS_TYPE_FREQ_OFFSET = 18; // 0x12
+    field public static final int FRONTEND_STATUS_TYPE_GUARD_INTERVAL = 26; // 0x1a
     field public static final int FRONTEND_STATUS_TYPE_HIERARCHY = 19; // 0x13
+    field public static final int FRONTEND_STATUS_TYPE_INTERLEAVINGS = 30; // 0x1e
+    field public static final int FRONTEND_STATUS_TYPE_ISDBT_SEGMENTS = 31; // 0x1f
     field public static final int FRONTEND_STATUS_TYPE_LAYER_ERROR = 16; // 0x10
     field public static final int FRONTEND_STATUS_TYPE_LNA = 15; // 0xf
     field public static final int FRONTEND_STATUS_TYPE_LNB_VOLTAGE = 11; // 0xb
     field public static final int FRONTEND_STATUS_TYPE_MER = 17; // 0x11
     field public static final int FRONTEND_STATUS_TYPE_MODULATION = 9; // 0x9
+    field public static final int FRONTEND_STATUS_TYPE_MODULATIONS_EXT = 22; // 0x16
     field public static final int FRONTEND_STATUS_TYPE_PER = 3; // 0x3
     field public static final int FRONTEND_STATUS_TYPE_PLP_ID = 12; // 0xc
     field public static final int FRONTEND_STATUS_TYPE_PRE_BER = 4; // 0x4
@@ -6059,6 +6115,10 @@
     field public static final int FRONTEND_STATUS_TYPE_SNR = 1; // 0x1
     field public static final int FRONTEND_STATUS_TYPE_SPECTRAL = 10; // 0xa
     field public static final int FRONTEND_STATUS_TYPE_SYMBOL_RATE = 7; // 0x7
+    field public static final int FRONTEND_STATUS_TYPE_T2_SYSTEM_ID = 29; // 0x1d
+    field public static final int FRONTEND_STATUS_TYPE_TRANSMISSION_MODE = 27; // 0x1b
+    field public static final int FRONTEND_STATUS_TYPE_TS_DATA_RATES = 32; // 0x20
+    field public static final int FRONTEND_STATUS_TYPE_UEC = 28; // 0x1c
   }
 
   public static class FrontendStatus.Atsc3PlpTuningInfo {
@@ -6222,7 +6282,9 @@
     method public void onHierarchyReported(int);
     method public void onInputStreamIdsReported(@NonNull int[]);
     method public void onLocked();
+    method public default void onModulationReported(int);
     method public void onPlpIdsReported(@NonNull int[]);
+    method public default void onPriorityReported(boolean);
     method public void onProgress(@IntRange(from=0, to=100) int);
     method public void onScanStopped();
     method public void onSignalTypeReported(int);
@@ -10302,6 +10364,10 @@
     field public static final int ROAMING_TYPE_UNKNOWN = 1; // 0x1
   }
 
+  public class SignalStrength implements android.os.Parcelable {
+    ctor public SignalStrength(@NonNull android.telephony.SignalStrength);
+  }
+
   public final class SmsCbCmasInfo implements android.os.Parcelable {
     ctor public SmsCbCmasInfo(int, int, int, int, int, int);
     method public int describeContents();
diff --git a/packages/CarSystemUI/samples/sample3/rro/Android.bp b/packages/CarSystemUI/samples/sample3/rro/Android.bp
new file mode 100644
index 0000000..0eae7c2
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/Android.bp
@@ -0,0 +1,27 @@
+//
+// 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.
+//
+
+android_app {
+    name: "CarSystemUISampleThreeRRO",
+    resource_dirs: ["res"],
+    certificate: "platform",
+    platform_apis: true,
+    manifest: "AndroidManifest.xml",
+    aaptflags: [
+        "--no-resource-deduping",
+        "--no-resource-removal",
+     ]
+}
\ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample3/rro/AndroidManifest.xml b/packages/CarSystemUI/samples/sample3/rro/AndroidManifest.xml
new file mode 100644
index 0000000..5c25056
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ 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.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.systemui.rro">
+    <overlay
+        android:targetPackage="com.android.systemui"
+        android:isStatic="false"
+        android:resourcesMap="@xml/car_sysui_overlays"
+    />
+</manifest>
\ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_apps.xml b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_apps.xml
new file mode 100644
index 0000000..a8d8a2f
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_apps.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:viewportWidth="44"
+        android:viewportHeight="44"
+        android:width="44dp"
+        android:height="44dp">
+<path
+    android:pathData="M7.33333333 14.6666667L14.6666667 14.6666667L14.6666667 7.33333333L7.33333333 7.33333333L7.33333333 14.6666667ZM18.3333333 36.6666667L25.6666667 36.6666667L25.6666667 29.3333333L18.3333333 29.3333333L18.3333333 36.6666667ZM7.33333333 36.6666667L14.6666667 36.6666667L14.6666667 29.3333333L7.33333333 29.3333333L7.33333333 36.6666667ZM7.33333333 25.6666667L14.6666667 25.6666667L14.6666667 18.3333333L7.33333333 18.3333333L7.33333333 25.6666667ZM18.3333333 25.6666667L25.6666667 25.6666667L25.6666667 18.3333333L18.3333333 18.3333333L18.3333333 25.6666667ZM29.3333333 7.33333333L29.3333333 14.6666667L36.6666667 14.6666667L36.6666667 7.33333333L29.3333333 7.33333333ZM18.3333333 14.6666667L25.6666667 14.6666667L25.6666667 7.33333333L18.3333333 7.33333333L18.3333333 14.6666667ZM29.3333333 25.6666667L36.6666667 25.6666667L36.6666667 18.3333333L29.3333333 18.3333333L29.3333333 25.6666667ZM29.3333333 36.6666667L36.6666667 36.6666667L36.6666667 29.3333333L29.3333333 29.3333333L29.3333333 36.6666667Z"
+    android:fillColor="@color/car_nav_icon_fill_color" />
+</vector>
\ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_home.xml b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_home.xml
new file mode 100644
index 0000000..c78f0ed
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_home.xml
@@ -0,0 +1,25 @@
+<?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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="@dimen/system_bar_icon_drawing_size"
+        android:height="@dimen/system_bar_icon_drawing_size"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
+    <path
+        android:pathData="M10,20v-6h4v6h5v-8h3L12,3 2,12h3v8z"
+        android:fillColor="@color/car_nav_icon_fill_color" />
+</vector>
\ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_hvac.xml b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_hvac.xml
new file mode 100644
index 0000000..55c968e
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_hvac.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2018 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="@dimen/system_bar_icon_drawing_size"
+        android:height="@dimen/system_bar_icon_drawing_size"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
+    <path
+        android:pathData="M16.34,8.36l-2.29,0.82c-0.18,-0.13 -0.38,-0.25 -0.58,-0.34c0.17,-0.83 0.63,-1.58 1.36,-2.06C16.85,5.44 16.18,2 13.39,2C9,2 7.16,5.01 8.36,7.66l0.82,2.29c-0.13,0.18 -0.25,0.38 -0.34,0.58c-0.83,-0.17 -1.58,-0.63 -2.06,-1.36C5.44,7.15 2,7.82 2,10.61c0,4.4 3.01,6.24 5.66,5.03l2.29,-0.82c0.18,0.13 0.38,0.25 0.58,0.34c-0.17,0.83 -0.63,1.58 -1.36,2.06C7.15,18.56 7.82,22 10.61,22c4.4,0 6.24,-3.01 5.03,-5.66l-0.82,-2.29c0.13,-0.18 0.25,-0.38 0.34,-0.58c0.83,0.17 1.58,0.63 2.06,1.36c1.34,2.01 4.77,1.34 4.77,-1.45C22,9 18.99,7.16 16.34,8.36zM12,13.5c-0.83,0 -1.5,-0.67 -1.5,-1.5c0,-0.83 0.67,-1.5 1.5,-1.5c0.83,0 1.5,0.67 1.5,1.5C13.5,12.83 12.83,13.5 12,13.5zM10.24,5.22C10.74,4.44 11.89,4 13.39,4c0.79,0 0.71,0.86 0.34,1.11c-1.22,0.81 -2,2.06 -2.25,3.44c-0.21,0.03 -0.42,0.08 -0.62,0.15l-0.68,-1.88C10,6.42 9.86,5.81 10.24,5.22zM6.83,13.82c-0.4,0.18 -1.01,0.32 -1.61,-0.06C4.44,13.26 4,12.11 4,10.61c0,-0.79 0.86,-0.71 1.11,-0.34c0.81,1.22 2.06,2 3.44,2.25c0.03,0.21 0.08,0.42 0.15,0.62L6.83,13.82zM13.76,18.78c-0.5,0.77 -1.65,1.22 -3.15,1.22c-0.79,0 -0.71,-0.86 -0.34,-1.11c1.22,-0.81 2,-2.06 2.25,-3.44c0.21,-0.03 0.42,-0.08 0.62,-0.15l0.68,1.88C14,17.58 14.14,18.18 13.76,18.78zM18.89,13.73c-0.81,-1.22 -2.06,-2 -3.44,-2.25c-0.03,-0.21 -0.08,-0.42 -0.15,-0.62l1.88,-0.68c0.4,-0.18 1.01,-0.32 1.61,0.06c0.77,0.5 1.22,1.65 1.22,3.15C20,14.19 19.14,14.11 18.89,13.73z"
+        android:fillColor="@color/car_nav_icon_fill_color" />
+</vector>
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_music.xml b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_music.xml
new file mode 100644
index 0000000..6339ebb
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_music.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:viewportWidth="44"
+    android:viewportHeight="44"
+    android:width="44dp"
+    android:height="44dp">
+    <path
+        android:pathData="M22 5.5L22 24.8416667C20.9183333 24.2183333 19.6716667 23.8333333 18.3333333 23.8333333C14.2816667 23.8333333 11 27.115 11 31.1666667C11 35.2183333 14.2816667 38.5 18.3333333 38.5C22.385 38.5 25.6666667 35.2183333 25.6666667 31.1666667L25.6666667 12.8333333L33 12.8333333L33 5.5L22 5.5Z"
+        android:fillColor="@color/car_nav_icon_fill_color" />
+</vector>
\ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_navigation.xml b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_navigation.xml
new file mode 100644
index 0000000..e1fabe0
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_navigation.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:viewportWidth="44"
+    android:viewportHeight="44"
+    android:width="44dp"
+    android:height="44dp">
+    <path
+        android:pathData="M39.8016667 20.6983333L23.3016667 4.19833333C22.5866667 3.48333333 21.4316667 3.48333333 20.7166667 4.19833333L4.21666667 20.6983333C3.50166667 21.4133333 3.50166667 22.5683333 4.21666667 23.2833333L20.7166667 39.7833333C21.4316667 40.4983333 22.5866667 40.4983333 23.3016667 39.7833333L39.8016667 23.2833333C40.5166667 22.5866667 40.5166667 21.4316667 39.8016667 20.6983333ZM25.6666667 26.5833333L25.6666667 22L18.3333333 22L18.3333333 27.5L14.6666667 27.5L14.6666667 20.1666667C14.6666667 19.1583333 15.4916667 18.3333333 16.5 18.3333333L25.6666667 18.3333333L25.6666667 13.75L32.0833333 20.1666667L25.6666667 26.5833333Z"
+        android:fillColor="@color/car_nav_icon_fill_color" />
+</vector>
\ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_notification.xml b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_notification.xml
new file mode 100644
index 0000000..aabf916
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_notification.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="@dimen/system_bar_icon_drawing_size"
+        android:height="@dimen/system_bar_icon_drawing_size"
+        android:viewportWidth="44"
+        android:viewportHeight="44">
+    <path
+        android:pathData="M22 39.125C23.925 39.125 25.5 37.55 25.5 35.625L18.5 35.625C18.5 37.55 20.0575 39.125 22 39.125ZM32.5 28.625L32.5 19.875C32.5 14.5025 29.63 10.005 24.625 8.815L24.625 7.625C24.625 6.1725 23.4525 5 22 5C20.5475 5 19.375 6.1725 19.375 7.625L19.375 8.815C14.3525 10.005 11.5 14.485 11.5 19.875L11.5 28.625L8 32.125L8 33.875L36 33.875L36 32.125L32.5 28.625Z"
+        android:fillColor="@color/car_nav_icon_fill_color" />
+</vector>
\ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_overview.xml b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_overview.xml
new file mode 100644
index 0000000..f185eb9
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_overview.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:viewportWidth="44"
+    android:viewportHeight="44"
+    android:width="44dp"
+    android:height="44dp">
+    <path
+        android:pathData="M36.92857 22.39286A14.53571 14.53571 0 0 1 7.857143 22.39286A14.53571 14.53571 0 0 1 36.92857 22.39286Z"
+        android:strokeColor="@color/car_nav_icon_fill_color"
+        android:strokeWidth="4" />
+</vector>
\ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_phone.xml b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_phone.xml
new file mode 100644
index 0000000..50e36b5
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_phone.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:viewportWidth="44"
+    android:viewportHeight="44"
+    android:width="44dp"
+    android:height="44dp">
+    <path
+        android:pathData="M12.1366667 19.7816667C14.7766667 24.97 19.03 29.205 24.2183333 31.8633333L28.2516667 27.83C28.7466667 27.335 29.48 27.17 30.1216667 27.39C32.175 28.0683333 34.3933333 28.435 36.6666667 28.435C37.675 28.435 38.5 29.26 38.5 30.2683333L38.5 36.6666667C38.5 37.675 37.675 38.5 36.6666667 38.5C19.4516667 38.5 5.5 24.5483333 5.5 7.33333333C5.5 6.325 6.325 5.5 7.33333333 5.5L13.75 5.5C14.7583333 5.5 15.5833333 6.325 15.5833333 7.33333333C15.5833333 9.625 15.95 11.825 16.6283333 13.8783333C16.83 14.52 16.6833333 15.235 16.17 15.7483333L12.1366667 19.7816667Z"
+        android:fillColor="@color/car_nav_icon_fill_color" />
+</vector>
\ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/drawable/system_bar_background.xml b/packages/CarSystemUI/samples/sample3/rro/res/drawable/system_bar_background.xml
new file mode 100644
index 0000000..66da21c
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/drawable/system_bar_background.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.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
+    <solid
+        android:color="#404040"
+    />
+</shape>
\ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/layout/car_left_navigation_bar.xml b/packages/CarSystemUI/samples/sample3/rro/res/layout/car_left_navigation_bar.xml
new file mode 100644
index 0000000..3d1cd08
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/layout/car_left_navigation_bar.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<com.android.systemui.car.navigationbar.CarNavigationBarView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent"
+    android:orientation="vertical"
+    android:background="@android:color/transparent">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:gravity="bottom"
+        android:orientation="vertical">
+
+        <com.android.systemui.statusbar.policy.Clock
+            android:id="@+id/clock"
+            android:textAppearance="@style/TextAppearance.StatusBar.Clock"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:singleLine="true"
+            android:gravity="center_horizontal"
+            android:paddingBottom="20dp"
+        />
+
+        <Space
+            android:layout_height="50dp"
+            android:layout_width="match_parent"/>
+
+    </LinearLayout>
+
+</com.android.systemui.car.navigationbar.CarNavigationBarView>
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/layout/car_navigation_bar.xml b/packages/CarSystemUI/samples/sample3/rro/res/layout/car_navigation_bar.xml
new file mode 100644
index 0000000..8314ba5
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/layout/car_navigation_bar.xml
@@ -0,0 +1,122 @@
+<?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.
+  -->
+
+<com.android.systemui.car.navigationbar.CarNavigationBarView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@drawable/system_bar_background"
+    android:gravity="center"
+    android:orientation="horizontal">
+
+    <RelativeLayout
+        android:id="@+id/nav_buttons"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layoutDirection="ltr">
+
+        <com.android.systemui.car.hvac.AdjustableTemperatureView
+            android:id="@+id/driver_hvac"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:gravity="center_vertical"
+            systemui:hvacAreaId="49"
+            systemui:hvacTempFormat="%.0f\u00B0" />
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_centerInParent="true"
+            android:layout_weight="1"
+            android:gravity="center"
+            android:layoutDirection="ltr"
+            android:paddingEnd="@dimen/system_bar_button_group_padding"
+            android:paddingStart="@dimen/system_bar_button_group_padding">
+
+            <Space
+                android:layout_width="0dp"
+                android:layout_height="match_parent"
+                android:layout_weight="1"/>
+
+            <com.android.systemui.car.navigationbar.CarNavigationButton
+                android:id="@+id/home"
+                style="@style/NavigationBarButton"
+                systemui:componentNames="com.android.car.carlauncher/.CarLauncher"
+                systemui:highlightWhenSelected="true"
+                systemui:icon="@drawable/car_ic_home"
+                systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end"/>
+
+            <com.android.systemui.car.navigationbar.CarNavigationButton
+                android:id="@+id/phone_nav"
+                style="@style/NavigationBarButton"
+                systemui:highlightWhenSelected="true"
+                systemui:icon="@drawable/car_ic_phone"
+                systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;package=com.android.car.dialer;launchFlags=0x10000000;end"
+                systemui:packages="com.android.car.dialer"/>
+
+            <com.android.systemui.car.navigationbar.CarNavigationButton
+                android:id="@+id/grid_nav"
+                style="@style/NavigationBarButton"
+                systemui:componentNames="com.android.car.carlauncher/.AppGridActivity"
+                systemui:highlightWhenSelected="true"
+                systemui:icon="@drawable/car_ic_apps"
+                systemui:intent="intent:#Intent;component=com.android.car.carlauncher/.AppGridActivity;launchFlags=0x24000000;end"/>
+
+            <com.android.systemui.car.navigationbar.CarNavigationButton
+                android:id="@+id/hvac"
+                style="@style/NavigationBarButton"
+                systemui:highlightWhenSelected="true"
+                systemui:icon="@drawable/car_ic_hvac"
+                systemui:intent="intent:#Intent;action=android.car.intent.action.TOGGLE_HVAC_CONTROLS;end"
+                systemui:broadcast="true"/>
+
+            <com.android.systemui.car.navigationbar.CarNavigationButton
+                android:id="@+id/notifications"
+                style="@style/NavigationBarButton"
+                systemui:highlightWhenSelected="true"
+                systemui:icon="@drawable/car_ic_notification"
+                systemui:longIntent="intent:#Intent;component=com.android.car.bugreport/.BugReportActivity;end"/>
+
+            <Space
+                android:layout_width="0dp"
+                android:layout_height="match_parent"
+                android:layout_weight="1"/>
+        </LinearLayout>
+
+        <com.android.systemui.car.hvac.AdjustableTemperatureView
+            android:id="@+id/passenger_hvac"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_alignParentEnd="true"
+            android:gravity="center_vertical"
+            systemui:hvacAreaId="68"
+            systemui:hvacTempFormat="%.0f\u00B0" />
+    </RelativeLayout>
+
+    <LinearLayout
+        android:id="@+id/lock_screen_nav_buttons"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:gravity="center"
+        android:layoutDirection="ltr"
+        android:paddingEnd="@dimen/car_keyline_1"
+        android:paddingStart="@dimen/car_keyline_1"
+        android:visibility="gone"
+    />
+</com.android.systemui.car.navigationbar.CarNavigationBarView>
\ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/values/attrs.xml b/packages/CarSystemUI/samples/sample3/rro/res/values/attrs.xml
new file mode 100644
index 0000000..bc7ded2
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/values/attrs.xml
@@ -0,0 +1,43 @@
+<?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>
+    <attr name="broadcast" format="boolean"/>
+    <attr name="icon" format="reference"/>
+    <attr name="intent" format="string"/>
+    <attr name="longIntent" format="string"/>
+    <attr name="componentNames" format="string" />
+    <attr name="highlightWhenSelected" format="boolean" />
+    <attr name="categories" format="string"/>
+    <attr name="packages" format="string" />
+
+    <!-- Custom attributes to configure hvac values -->
+    <declare-styleable name="AnimatedTemperatureView">
+        <attr name="hvacAreaId" format="integer"/>
+        <attr name="hvacPropertyId" format="integer"/>
+        <attr name="hvacTempFormat" format="string"/>
+        <!-- how far away the animations should center around -->
+        <attr name="hvacPivotOffset" format="dimension"/>
+        <attr name="hvacMinValue" format="float"/>
+        <attr name="hvacMaxValue" format="float"/>
+        <attr name="hvacMinText" format="string|reference"/>
+        <attr name="hvacMaxText" format="string|reference"/>
+        <attr name="android:gravity"/>
+        <attr name="android:minEms"/>
+        <attr name="android:textAppearance"/>
+    </declare-styleable>
+</resources>
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/values/colors.xml b/packages/CarSystemUI/samples/sample3/rro/res/values/colors.xml
new file mode 100644
index 0000000..f98cb96
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/values/colors.xml
@@ -0,0 +1,19 @@
+<?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">
+    <color name="car_nav_icon_fill_color">#8F8F8F</color>
+</resources>
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/values/config.xml b/packages/CarSystemUI/samples/sample3/rro/res/values/config.xml
new file mode 100644
index 0000000..2148e7c
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/values/config.xml
@@ -0,0 +1,57 @@
+<?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>
+    <!-- Configure which system bars should be displayed. -->
+    <bool name="config_enableTopNavigationBar">false</bool>
+    <bool name="config_enableLeftNavigationBar">true</bool>
+    <bool name="config_enableRightNavigationBar">false</bool>
+    <bool name="config_enableBottomNavigationBar">true</bool>
+
+    <!-- Configure the type of each system bar. Each system bar must have a unique type. -->
+    <!--    STATUS_BAR = 0-->
+    <!--    NAVIGATION_BAR = 1-->
+    <!--    STATUS_BAR_EXTRA = 2-->
+    <!--    NAVIGATION_BAR_EXTRA = 3-->
+    <integer name="config_topSystemBarType">2</integer>
+    <integer name="config_leftSystemBarType">0</integer>
+    <integer name="config_rightSystemBarType">3</integer>
+    <integer name="config_bottomSystemBarType">1</integer>
+
+    <!-- Configure the relative z-order among the system bars. When two system bars overlap (e.g.
+         if both top bar and left bar are enabled, it creates an overlapping space in the upper left
+         corner), the system bar with the higher z-order takes the overlapping space and padding is
+         applied to the other bar.-->
+    <!-- NOTE: If two overlapping system bars have the same z-order, SystemBarConfigs will throw a
+         RuntimeException, since their placing order cannot be determined. Bars that do not overlap
+         are allowed to have the same z-order. -->
+    <!-- NOTE: If the z-order of a bar is 10 or above, it will also appear on top of HUN's.    -->
+    <integer name="config_topSystemBarZOrder">0</integer>
+    <integer name="config_leftSystemBarZOrder">10</integer>
+    <integer name="config_rightSystemBarZOrder">0</integer>
+    <integer name="config_bottomSystemBarZOrder">15</integer>
+
+    <!-- Whether heads-up notifications should be shown on the bottom. If false, heads-up
+         notifications will be shown pushed to the top of their parent container. If true, they will
+         be shown pushed to the bottom of their parent container. If true, then should override
+         config_headsUpNotificationAnimationHelper to use a different AnimationHelper, such as
+         com.android.car.notification.headsup.animationhelper.
+         CarHeadsUpNotificationBottomAnimationHelper. -->
+    <bool name="config_showHeadsUpNotificationOnBottom">false</bool>
+
+    <string name="config_notificationPanelViewMediator" translatable="false">com.android.systemui.car.notification.BottomNotificationPanelViewMediator</string>
+</resources>
\ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/values/dimens.xml b/packages/CarSystemUI/samples/sample3/rro/res/values/dimens.xml
new file mode 100644
index 0000000..c89f949
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/values/dimens.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<resources>
+    <dimen name="car_left_navigation_bar_width">280dp</dimen>
+    <dimen name="car_keyline_1">24dp</dimen>
+    <dimen name="system_bar_button_group_padding">64dp</dimen>
+    <dimen name="system_bar_icon_drawing_size">44dp</dimen>
+</resources>
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/values/styles.xml b/packages/CarSystemUI/samples/sample3/rro/res/values/styles.xml
new file mode 100644
index 0000000..bad3691
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/values/styles.xml
@@ -0,0 +1,30 @@
+<?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">
+    <style name="TextAppearance.StatusBar.Clock"
+           parent="@*android:style/TextAppearance.StatusBar.Icon">
+        <item name="android:textSize">40sp</item>
+        <item name="android:fontFamily">sans-serif-regular</item>
+        <item name="android:textColor">#FFFFFF</item>
+    </style>
+
+    <style name="NavigationBarButton">
+        <item name="android:layout_height">96dp</item>
+        <item name="android:layout_width">96dp</item>
+        <item name="android:background">?android:attr/selectableItemBackground</item>
+    </style>
+</resources>
\ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/xml/car_sysui_overlays.xml b/packages/CarSystemUI/samples/sample3/rro/res/xml/car_sysui_overlays.xml
new file mode 100644
index 0000000..f08d968
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/xml/car_sysui_overlays.xml
@@ -0,0 +1,75 @@
+
+<!--
+  ~ 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.
+  -->
+
+<overlay>
+    <item target="layout/car_navigation_bar" value="@layout/car_navigation_bar"/>
+    <item target="layout/car_left_navigation_bar" value="@layout/car_left_navigation_bar"/>
+
+    <item target="bool/config_enableTopNavigationBar" value="@bool/config_enableTopNavigationBar"/>
+    <item target="bool/config_enableLeftNavigationBar" value="@bool/config_enableLeftNavigationBar"/>
+    <item target="bool/config_enableRightNavigationBar" value="@bool/config_enableRightNavigationBar"/>
+    <item target="bool/config_enableBottomNavigationBar" value="@bool/config_enableBottomNavigationBar"/>
+    <item target="bool/config_showHeadsUpNotificationOnBottom" value="@bool/config_showHeadsUpNotificationOnBottom"/>
+
+    <item target="attr/icon" value="@attr/icon"/>
+    <item target="attr/intent" value="@attr/intent"/>
+    <item target="attr/longIntent" value="@attr/longIntent"/>
+    <item target="attr/componentNames" value="@attr/componentNames"/>
+    <item target="attr/highlightWhenSelected" value="@attr/highlightWhenSelected"/>
+    <item target="attr/categories" value="@attr/categories"/>
+    <item target="attr/packages" value="@attr/packages"/>
+    <item target="attr/hvacAreaId" value="@attr/hvacAreaId"/>
+    <item target="attr/hvacPropertyId" value="@attr/hvacPropertyId"/>
+    <item target="attr/hvacTempFormat" value="@attr/hvacTempFormat"/>
+    <item target="attr/hvacPivotOffset" value="@attr/hvacPivotOffset"/>
+    <item target="attr/hvacMinValue" value="@attr/hvacMinValue"/>
+    <item target="attr/hvacMaxValue" value="@attr/hvacMaxValue"/>
+    <item target="attr/hvacMinText" value="@attr/hvacMinText"/>
+    <item target="attr/hvacMaxText" value="@attr/hvacMaxText"/>
+    <!-- start the intent as a broad cast instead of an activity if true-->
+    <item target="attr/broadcast" value="@attr/broadcast"/>
+
+    <item target="color/car_nav_icon_fill_color" value="@color/car_nav_icon_fill_color" />
+
+    <item target="drawable/car_ic_overview" value="@drawable/car_ic_overview" />
+    <item target="drawable/car_ic_home" value="@drawable/car_ic_home" />
+    <item target="drawable/car_ic_hvac" value="@drawable/car_ic_hvac" />
+    <item target="drawable/car_ic_apps" value="@drawable/car_ic_apps" />
+    <item target="drawable/car_ic_music" value="@drawable/car_ic_music" />
+    <item target="drawable/car_ic_notification" value="@drawable/car_ic_notification" />
+    <item target="drawable/car_ic_phone" value="@drawable/car_ic_phone" />
+    <item target="drawable/car_ic_navigation" value="@drawable/car_ic_navigation" />
+
+    <item target="dimen/car_left_navigation_bar_width" value="@dimen/car_left_navigation_bar_width" />
+    <item target="dimen/car_keyline_1" value="@dimen/car_keyline_1" />
+    <item target="dimen/system_bar_button_group_padding" value="@dimen/system_bar_button_group_padding" />
+    <item target="dimen/system_bar_icon_drawing_size" value="@dimen/system_bar_icon_drawing_size" />
+
+    <item target="integer/config_topSystemBarType" value="@integer/config_topSystemBarType"/>
+    <item target="integer/config_leftSystemBarType" value="@integer/config_leftSystemBarType"/>
+    <item target="integer/config_rightSystemBarType" value="@integer/config_rightSystemBarType"/>
+    <item target="integer/config_bottomSystemBarType" value="@integer/config_bottomSystemBarType"/>
+
+    <item target="integer/config_topSystemBarZOrder" value="@integer/config_topSystemBarZOrder"/>
+    <item target="integer/config_leftSystemBarZOrder" value="@integer/config_leftSystemBarZOrder"/>
+    <item target="integer/config_rightSystemBarZOrder" value="@integer/config_rightSystemBarZOrder"/>
+    <item target="integer/config_bottomSystemBarZOrder" value="@integer/config_bottomSystemBarZOrder"/>
+
+    <item target="string/config_notificationPanelViewMediator" value="@string/config_notificationPanelViewMediator"/>
+
+    <item target="style/NavigationBarButton" value="@style/NavigationBarButton"/>
+</overlay>
\ No newline at end of file
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarGlobalRootComponent.java b/packages/CarSystemUI/src/com/android/systemui/CarGlobalRootComponent.java
index b17ad0f..b056dcf 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarGlobalRootComponent.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarGlobalRootComponent.java
@@ -19,6 +19,7 @@
 import com.android.systemui.dagger.GlobalModule;
 import com.android.systemui.dagger.GlobalRootComponent;
 import com.android.systemui.dagger.WMModule;
+import com.android.systemui.wmshell.CarWMComponent;
 
 import javax.inject.Singleton;
 
@@ -41,6 +42,12 @@
         CarGlobalRootComponent build();
     }
 
+    /**
+     * Builder for a WMComponent.
+     */
+    @Override
+    CarWMComponent.Builder getWMComponentBuilder();
+
     @Override
     CarSysUIComponent.Builder getSysUIComponent();
 }
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
index 51fda96..1d35bbb 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
@@ -64,7 +64,6 @@
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.volume.VolumeDialogComponent;
-import com.android.systemui.wmshell.CarWMShellModule;
 
 import javax.inject.Named;
 
@@ -74,8 +73,7 @@
 
 @Module(
         includes = {
-                QSModule.class,
-                CarWMShellModule.class
+                QSModule.class
         })
 abstract class CarSystemUIModule {
 
diff --git a/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMComponent.java b/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMComponent.java
new file mode 100644
index 0000000..c6a7fd2
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMComponent.java
@@ -0,0 +1,39 @@
+/*
+ * 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.systemui.wmshell;
+
+import com.android.systemui.dagger.WMComponent;
+import com.android.systemui.dagger.WMSingleton;
+
+import dagger.Subcomponent;
+
+
+/**
+ * Dagger Subcomponent for WindowManager.
+ */
+@WMSingleton
+@Subcomponent(modules = {CarWMShellModule.class})
+public interface CarWMComponent extends WMComponent {
+
+    /**
+     * Builder for a SysUIComponent.
+     */
+    @Subcomponent.Builder
+    interface Builder extends WMComponent.Builder {
+        CarWMComponent build();
+    }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java b/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java
index 3bfe410..27aabff 100644
--- a/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java
@@ -20,7 +20,7 @@
 import android.os.Handler;
 import android.view.IWindowManager;
 
-import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.WMSingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.wm.DisplaySystemBarsController;
 import com.android.wm.shell.common.DisplayController;
@@ -35,7 +35,7 @@
 /** Provides dependencies from {@link com.android.wm.shell} for CarSystemUI. */
 @Module(includes = WMShellBaseModule.class)
 public abstract class CarWMShellModule {
-    @SysUISingleton
+    @WMSingleton
     @Provides
     static DisplayImeController provideDisplayImeController(Context context,
             IWindowManager wmService, DisplayController displayController,
diff --git a/packages/InputDevices/res/values-ar/strings.xml b/packages/InputDevices/res/values-ar/strings.xml
index f27350a..8ed1972 100644
--- a/packages/InputDevices/res/values-ar/strings.xml
+++ b/packages/InputDevices/res/values-ar/strings.xml
@@ -36,7 +36,7 @@
     <string name="keyboard_layout_slovak" msgid="2469379934672837296">"السلوفاكية"</string>
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"السلوفينية"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"التركية"</string>
-    <string name="keyboard_layout_turkish_f" msgid="9130320856010776018">"التركية-ف"</string>
+    <string name="keyboard_layout_turkish_f" msgid="9130320856010776018">"‏لوحة المفاتيح باللغة التركية F"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"الأوكرانية"</string>
     <string name="keyboard_layout_arabic" msgid="5671970465174968712">"العربية"</string>
     <string name="keyboard_layout_greek" msgid="7289253560162386040">"اليونانية"</string>
diff --git a/packages/InputDevices/res/values-gl/strings.xml b/packages/InputDevices/res/values-gl/strings.xml
index 0f979d0..9995f79 100644
--- a/packages/InputDevices/res/values-gl/strings.xml
+++ b/packages/InputDevices/res/values-gl/strings.xml
@@ -36,8 +36,7 @@
     <string name="keyboard_layout_slovak" msgid="2469379934672837296">"Eslovaco"</string>
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Esloveno"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turco"</string>
-    <!-- no translation found for keyboard_layout_turkish_f (9130320856010776018) -->
-    <skip />
+    <string name="keyboard_layout_turkish_f" msgid="9130320856010776018">"Turco F"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ucraíno"</string>
     <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Árabe"</string>
     <string name="keyboard_layout_greek" msgid="7289253560162386040">"Grego"</string>
diff --git a/packages/InputDevices/res/values-gu/strings.xml b/packages/InputDevices/res/values-gu/strings.xml
index 99e5a45..de50fb9 100644
--- a/packages/InputDevices/res/values-gu/strings.xml
+++ b/packages/InputDevices/res/values-gu/strings.xml
@@ -36,8 +36,7 @@
     <string name="keyboard_layout_slovak" msgid="2469379934672837296">"સ્લોવૅક"</string>
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"સ્લોવેનિયન"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"ટર્કીશ"</string>
-    <!-- no translation found for keyboard_layout_turkish_f (9130320856010776018) -->
-    <skip />
+    <string name="keyboard_layout_turkish_f" msgid="9130320856010776018">"ટર્કિશ F"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"યુક્રેનિયન"</string>
     <string name="keyboard_layout_arabic" msgid="5671970465174968712">"અરબી"</string>
     <string name="keyboard_layout_greek" msgid="7289253560162386040">"ગ્રીક"</string>
diff --git a/packages/InputDevices/res/values-kn/strings.xml b/packages/InputDevices/res/values-kn/strings.xml
index c305f09..761b7cc 100644
--- a/packages/InputDevices/res/values-kn/strings.xml
+++ b/packages/InputDevices/res/values-kn/strings.xml
@@ -36,8 +36,7 @@
     <string name="keyboard_layout_slovak" msgid="2469379934672837296">"ಸ್ಲೋವಾಕ್"</string>
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"ಸ್ಲೋವೇನಿಯನ್"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"ಟರ್ಕಿಶ್‌"</string>
-    <!-- no translation found for keyboard_layout_turkish_f (9130320856010776018) -->
-    <skip />
+    <string name="keyboard_layout_turkish_f" msgid="9130320856010776018">"ಟರ್ಕಿಶ್ F"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ಉಕ್ರೇನಿಯನ್"</string>
     <string name="keyboard_layout_arabic" msgid="5671970465174968712">"ಅರೇಬಿಕ್"</string>
     <string name="keyboard_layout_greek" msgid="7289253560162386040">"ಗ್ರೀಕ್"</string>
diff --git a/packages/InputDevices/res/values-mr/strings.xml b/packages/InputDevices/res/values-mr/strings.xml
index 39b2adb..c04006d 100644
--- a/packages/InputDevices/res/values-mr/strings.xml
+++ b/packages/InputDevices/res/values-mr/strings.xml
@@ -36,8 +36,7 @@
     <string name="keyboard_layout_slovak" msgid="2469379934672837296">"स्लोव्हाक"</string>
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"स्लोव्हेनियन"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"तुर्की"</string>
-    <!-- no translation found for keyboard_layout_turkish_f (9130320856010776018) -->
-    <skip />
+    <string name="keyboard_layout_turkish_f" msgid="9130320856010776018">"तुर्कीश एफ"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"यूक्रेनियन"</string>
     <string name="keyboard_layout_arabic" msgid="5671970465174968712">"अरबी"</string>
     <string name="keyboard_layout_greek" msgid="7289253560162386040">"ग्रीक"</string>
diff --git a/packages/InputDevices/res/values-ne/strings.xml b/packages/InputDevices/res/values-ne/strings.xml
index dd6366b..13740e7 100644
--- a/packages/InputDevices/res/values-ne/strings.xml
+++ b/packages/InputDevices/res/values-ne/strings.xml
@@ -36,8 +36,7 @@
     <string name="keyboard_layout_slovak" msgid="2469379934672837296">"स्लोवाक"</string>
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"स्लोवेनियाई"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"टर्किश"</string>
-    <!-- no translation found for keyboard_layout_turkish_f (9130320856010776018) -->
-    <skip />
+    <string name="keyboard_layout_turkish_f" msgid="9130320856010776018">"तुर्किस-F"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"युक्रेनी"</string>
     <string name="keyboard_layout_arabic" msgid="5671970465174968712">"अरबी"</string>
     <string name="keyboard_layout_greek" msgid="7289253560162386040">"ग्रीक"</string>
diff --git a/packages/InputDevices/res/values-pa/strings.xml b/packages/InputDevices/res/values-pa/strings.xml
index 916ee54..f261fb52 100644
--- a/packages/InputDevices/res/values-pa/strings.xml
+++ b/packages/InputDevices/res/values-pa/strings.xml
@@ -36,8 +36,7 @@
     <string name="keyboard_layout_slovak" msgid="2469379934672837296">"ਸਲੋਵਾਕ"</string>
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"ਸਲੋਵੀਅਨ"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"ਤੁਰਕੀ"</string>
-    <!-- no translation found for keyboard_layout_turkish_f (9130320856010776018) -->
-    <skip />
+    <string name="keyboard_layout_turkish_f" msgid="9130320856010776018">"ਤੁਰਕੀ F"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ਯੂਕਰੇਨੀਅਨ"</string>
     <string name="keyboard_layout_arabic" msgid="5671970465174968712">"ਅਰਬੀ"</string>
     <string name="keyboard_layout_greek" msgid="7289253560162386040">"ਯੂਨਾਨੀ"</string>
diff --git a/packages/InputDevices/res/values-pl/strings.xml b/packages/InputDevices/res/values-pl/strings.xml
index 51cd29bf..25a3a90 100644
--- a/packages/InputDevices/res/values-pl/strings.xml
+++ b/packages/InputDevices/res/values-pl/strings.xml
@@ -36,7 +36,7 @@
     <string name="keyboard_layout_slovak" msgid="2469379934672837296">"Słowacki"</string>
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Słoweński"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turecki"</string>
-    <string name="keyboard_layout_turkish_f" msgid="9130320856010776018">"Turecki F"</string>
+    <string name="keyboard_layout_turkish_f" msgid="9130320856010776018">"Turecka F"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukraiński"</string>
     <string name="keyboard_layout_arabic" msgid="5671970465174968712">"arabski"</string>
     <string name="keyboard_layout_greek" msgid="7289253560162386040">"grecki"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index c5a4f2f..0b21a2d 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -28,7 +28,7 @@
     <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"‏پیکربندی IP انجام نشد"</string>
     <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"اتصال ناموفق به دلیل شبکه با کیفیت پایین"</string>
     <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"‏اتصال Wi-Fi برقرار نشد"</string>
-    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"مشکل احراز هویت"</string>
+    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"مشکل اصالت‌سنجی"</string>
     <string name="wifi_cant_connect" msgid="5718417542623056783">"برقراری اتصال ممکن نیست"</string>
     <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"برقراری اتصال به «<xliff:g id="AP_NAME">%1$s</xliff:g>» ممکن نیست"</string>
     <string name="wifi_check_password_try_again" msgid="8817789642851605628">"گذرواژه را بررسی و دوباره امتحان کنید"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index fbfe84c..7c8dc24 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -25,7 +25,7 @@
     <string name="wifi_remembered" msgid="3266709779723179188">"सेव्ह केले"</string>
     <string name="wifi_disconnected" msgid="7054450256284661757">"डिस्कनेक्ट केले"</string>
     <string name="wifi_disabled_generic" msgid="2651916945380294607">"अक्षम"</string>
-    <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP कॉन्फिगरेशन अयशस्वी"</string>
+    <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP कॉंफिगरेशन अयशस्वी"</string>
     <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"कमी दर्जाच्या नेटवर्कमुळे कनेक्ट केलेले नाही"</string>
     <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"WiFi कनेक्शन अयशस्वी"</string>
     <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"प्रमाणीकरण समस्या"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 54adb3a..e34732f 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -89,7 +89,7 @@
     <string name="bluetooth_profile_pbap" msgid="7064307749579335765">"सम्पर्क साझेदारी"</string>
     <string name="bluetooth_profile_pbap_summary" msgid="2955819694801952056">"सम्पर्क साझेदारीका लागि प्रयोग"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"इन्टरनेट जडान साझेदारी गर्दै"</string>
-    <string name="bluetooth_profile_map" msgid="8907204701162107271">"पाठ सन्देशहरू"</string>
+    <string name="bluetooth_profile_map" msgid="8907204701162107271">"टेक्स्ट म्यासेजहरू"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM पहुँच"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD अडियो: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD अडियो"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 1802be6..b971aee 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -197,9 +197,9 @@
     <string name="category_personal" msgid="6236798763159385225">"ذاتی"</string>
     <string name="category_work" msgid="4014193632325996115">"دفتر"</string>
     <string name="development_settings_title" msgid="140296922921597393">"ڈویلپر کے اختیارات"</string>
-    <string name="development_settings_enable" msgid="4285094651288242183">"ڈیولپر کے اختیارات فعال کریں"</string>
+    <string name="development_settings_enable" msgid="4285094651288242183">"ڈویلپر کے اختیارات فعال کریں"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"ایپ ڈویلپمنٹ کیلئے اختیارات سیٹ کریں"</string>
-    <string name="development_settings_not_available" msgid="355070198089140951">"اس صارف کیلئے ڈیولپر کے اختیارات دستیاب نہیں ہیں"</string>
+    <string name="development_settings_not_available" msgid="355070198089140951">"اس صارف کیلئے ڈویلپر کے اختیارات دستیاب نہیں ہیں"</string>
     <string name="vpn_settings_not_available" msgid="2894137119965668920">"‏VPN ترتیبات اس صارف کیلئے دستیاب نہیں ہیں"</string>
     <string name="tethering_settings_not_available" msgid="266821736434699780">"ٹیدرنگ ترتیبات اس صارف کیلئے دستیاب نہیں ہیں"</string>
     <string name="apn_settings_not_available" msgid="1147111671403342300">"رسائی کی جگہ کے نام کی ترتیبات اس صارف کیلئے دستیاب نہیں ہیں"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/location/SettingsInjector.java b/packages/SettingsLib/src/com/android/settingslib/location/SettingsInjector.java
index 450bdb1..a0c8663 100644
--- a/packages/SettingsLib/src/com/android/settingslib/location/SettingsInjector.java
+++ b/packages/SettingsLib/src/com/android/settingslib/location/SettingsInjector.java
@@ -129,10 +129,14 @@
         if (Log.isLoggable(TAG, Log.DEBUG)) {
             Log.d(TAG, "Found services for profile id " + profileId + ": " + resolveInfos);
         }
+
+        final PackageManager userPackageManager = mContext.createContextAsUser(
+                userHandle, /* flags */ 0).getPackageManager();
         List<InjectedSetting> settings = new ArrayList<InjectedSetting>(resolveInfos.size());
         for (ResolveInfo resolveInfo : resolveInfos) {
             try {
-                InjectedSetting setting = parseServiceInfo(resolveInfo, userHandle, pm);
+                InjectedSetting setting = parseServiceInfo(resolveInfo, userHandle,
+                        userPackageManager);
                 if (setting == null) {
                     Log.w(TAG, "Unable to load service info " + resolveInfo);
                 } else {
@@ -248,8 +252,7 @@
                         + SettingInjectorService.ATTRIBUTES_NAME + " tag");
             }
 
-            Resources res = pm.getResourcesForApplicationAsUser(si.packageName,
-                    userHandle.getIdentifier());
+            Resources res = pm.getResourcesForApplication(si.packageName);
             return parseAttributes(si.packageName, si.name, userHandle, res, attrs);
         } catch (PackageManager.NameNotFoundException e) {
             throw new XmlPullParserException(
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index f1fb527..90bed12 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -749,25 +749,25 @@
                 Settings.Global.GPU_DEBUG_LAYERS,
                 GlobalSettingsProto.Gpu.DEBUG_LAYERS);
         dumpSetting(s, p,
-                Settings.Global.GLOBAL_SETTINGS_ANGLE_DEBUG_PACKAGE,
+                Settings.Global.ANGLE_DEBUG_PACKAGE,
                 GlobalSettingsProto.Gpu.ANGLE_DEBUG_PACKAGE);
         dumpSetting(s, p,
-                Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE,
+                Settings.Global.ANGLE_GL_DRIVER_ALL_ANGLE,
                 GlobalSettingsProto.Gpu.ANGLE_GL_DRIVER_ALL_ANGLE);
         dumpSetting(s, p,
-                Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS,
+                Settings.Global.ANGLE_GL_DRIVER_SELECTION_PKGS,
                 GlobalSettingsProto.Gpu.ANGLE_GL_DRIVER_SELECTION_PKGS);
         dumpSetting(s, p,
-                Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES,
+                Settings.Global.ANGLE_GL_DRIVER_SELECTION_VALUES,
                 GlobalSettingsProto.Gpu.ANGLE_GL_DRIVER_SELECTION_VALUES);
         dumpSetting(s, p,
-                Settings.Global.GLOBAL_SETTINGS_ANGLE_ALLOWLIST,
+                Settings.Global.ANGLE_ALLOWLIST,
                 GlobalSettingsProto.Gpu.ANGLE_ALLOWLIST);
         dumpSetting(s, p,
                 Settings.Global.ANGLE_EGL_FEATURES,
                 GlobalSettingsProto.Gpu.ANGLE_EGL_FEATURES);
         dumpSetting(s, p,
-                Settings.Global.GLOBAL_SETTINGS_SHOW_ANGLE_IN_USE_DIALOG_BOX,
+                Settings.Global.SHOW_ANGLE_IN_USE_DIALOG_BOX,
                 GlobalSettingsProto.Gpu.SHOW_ANGLE_IN_USE_DIALOG);
         dumpSetting(s, p,
                 Settings.Global.GPU_DEBUG_LAYER_APP,
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 9b0df96..4713243 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -408,6 +408,7 @@
                     Settings.Global.PDP_WATCHDOG_MAX_PDP_RESET_FAIL_COUNT,
                     Settings.Global.PDP_WATCHDOG_POLL_INTERVAL_MS,
                     Settings.Global.PDP_WATCHDOG_TRIGGER_PACKET_COUNT,
+                    Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE,
                     Settings.Global.POLICY_CONTROL,
                     Settings.Global.POWER_BUTTON_SUPPRESSION_DELAY_AFTER_GESTURE_WAKE,
                     Settings.Global.POWER_MANAGER_CONSTANTS,
@@ -502,11 +503,11 @@
                     Settings.Global.GPU_DEBUG_APP,
                     Settings.Global.GPU_DEBUG_LAYERS,
                     Settings.Global.GPU_DEBUG_LAYERS_GLES,
-                    Settings.Global.GLOBAL_SETTINGS_ANGLE_DEBUG_PACKAGE,
-                    Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE,
-                    Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS,
-                    Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES,
-                    Settings.Global.GLOBAL_SETTINGS_ANGLE_ALLOWLIST,
+                    Settings.Global.ANGLE_DEBUG_PACKAGE,
+                    Settings.Global.ANGLE_GL_DRIVER_ALL_ANGLE,
+                    Settings.Global.ANGLE_GL_DRIVER_SELECTION_PKGS,
+                    Settings.Global.ANGLE_GL_DRIVER_SELECTION_VALUES,
+                    Settings.Global.ANGLE_ALLOWLIST,
                     Settings.Global.ANGLE_EGL_FEATURES,
                     Settings.Global.UPDATABLE_DRIVER_ALL_APPS,
                     Settings.Global.UPDATABLE_DRIVER_PRODUCTION_OPT_IN_APPS,
@@ -516,7 +517,7 @@
                     Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLIST,
                     Settings.Global.UPDATABLE_DRIVER_PRODUCTION_ALLOWLIST,
                     Settings.Global.UPDATABLE_DRIVER_SPHAL_LIBRARIES,
-                    Settings.Global.GLOBAL_SETTINGS_SHOW_ANGLE_IN_USE_DIALOG_BOX,
+                    Settings.Global.SHOW_ANGLE_IN_USE_DIALOG_BOX,
                     Settings.Global.GPU_DEBUG_LAYER_APP,
                     Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING,
                     Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT,
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index bf9b809..ef8064f 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -573,10 +573,17 @@
         </activity>
 
         <!-- People Space UI Screen -->
-        <activity
-            android:name=".people.PeopleSpaceActivity"
+        <activity android:name=".people.PeopleSpaceActivity"
+            android:label="People"
+            android:icon="@drawable/ic_music_note"
             android:exported="true"
-            android:theme="@android:style/Theme.Material.NoActionBar">
+            android:enabled="false"
+            android:theme="@android:style/Theme.Material.NoActionBar"
+            android:launchMode="singleInstance">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
         </activity>
 
         <!-- a gallery of delicious treats -->
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
index bf2963c..7e2e36a 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
@@ -61,6 +61,28 @@
              android:visibility="invisible"
              />
     </FrameLayout>
+    <FrameLayout
+        android:id="@+id/new_lockscreen_clock_view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentEnd="true"
+        android:layout_alignParentTop="true"
+        android:visibility="gone">
+        <com.android.keyguard.GradientTextClock
+            android:id="@+id/gradient_clock_view"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textSize="100dp"
+            android:letterSpacing="0.02"
+            android:lineSpacingMultiplier=".8"
+            android:includeFontPadding="false"
+            android:fontFamily="sans-serif"
+            android:typeface="monospace"
+            android:format12Hour="hh\nmm"
+            android:format24Hour="HH\nmm"
+            android:elegantTextHeight="false"
+        />
+    </FrameLayout>
     <include layout="@layout/keyguard_status_area"
         android:id="@+id/keyguard_status_area"
         android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index f998749..26a313a 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -86,8 +86,7 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Опитайте да направите екранна снимка отново"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Екранната снимка не може да се запази поради ограничено място в хранилището"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Правенето на екранни снимки не е разрешено от приложението или организацията ви"</string>
-    <!-- no translation found for screenshot_edit (3510496440489019191) -->
-    <skip />
+    <string name="screenshot_edit" msgid="3510496440489019191">"Редактиране на екранната снимка"</string>
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Отхвърляне на екранната снимка"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Визуализация на екранната снимка"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Запис на екрана"</string>
@@ -1065,8 +1064,7 @@
     <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Препоръките се зареждат"</string>
     <string name="controls_media_title" msgid="1746947284862928133">"Мултимедия"</string>
     <string name="controls_media_close_session" msgid="3957093425905475065">"Скриване на текущата сесия."</string>
-    <!-- no translation found for controls_media_active_session (1984383994625845642) -->
-    <skip />
+    <string name="controls_media_active_session" msgid="1984383994625845642">"Текущата сесия не може да бъде скрита."</string>
     <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Отхвърляне"</string>
     <string name="controls_media_resume" msgid="1933520684481586053">"Възобновяване"</string>
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Настройки"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 27824ec..a743bbe 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -86,8 +86,7 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Try taking screenshot again"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Can\'t save screenshot due to limited storage space"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Taking screenshots isn\'t allowed by the app or your organisation"</string>
-    <!-- no translation found for screenshot_edit (3510496440489019191) -->
-    <skip />
+    <string name="screenshot_edit" msgid="3510496440489019191">"Edit screenshot"</string>
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Dismiss screenshot"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Screenshot preview"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Screen Recorder"</string>
@@ -1065,8 +1064,7 @@
     <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string>
     <string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
     <string name="controls_media_close_session" msgid="3957093425905475065">"Hide the current session."</string>
-    <!-- no translation found for controls_media_active_session (1984383994625845642) -->
-    <skip />
+    <string name="controls_media_active_session" msgid="1984383994625845642">"Current session cannot be hidden."</string>
     <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dismiss"</string>
     <string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string>
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 012e76a3..3fe7a6a 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -86,8 +86,7 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Try taking screenshot again"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Can\'t save screenshot due to limited storage space"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Taking screenshots isn\'t allowed by the app or your organisation"</string>
-    <!-- no translation found for screenshot_edit (3510496440489019191) -->
-    <skip />
+    <string name="screenshot_edit" msgid="3510496440489019191">"Edit screenshot"</string>
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Dismiss screenshot"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Screenshot preview"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Screen Recorder"</string>
@@ -1065,8 +1064,7 @@
     <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string>
     <string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
     <string name="controls_media_close_session" msgid="3957093425905475065">"Hide the current session."</string>
-    <!-- no translation found for controls_media_active_session (1984383994625845642) -->
-    <skip />
+    <string name="controls_media_active_session" msgid="1984383994625845642">"Current session cannot be hidden."</string>
     <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dismiss"</string>
     <string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string>
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 27824ec..a743bbe 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -86,8 +86,7 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Try taking screenshot again"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Can\'t save screenshot due to limited storage space"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Taking screenshots isn\'t allowed by the app or your organisation"</string>
-    <!-- no translation found for screenshot_edit (3510496440489019191) -->
-    <skip />
+    <string name="screenshot_edit" msgid="3510496440489019191">"Edit screenshot"</string>
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Dismiss screenshot"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Screenshot preview"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Screen Recorder"</string>
@@ -1065,8 +1064,7 @@
     <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string>
     <string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
     <string name="controls_media_close_session" msgid="3957093425905475065">"Hide the current session."</string>
-    <!-- no translation found for controls_media_active_session (1984383994625845642) -->
-    <skip />
+    <string name="controls_media_active_session" msgid="1984383994625845642">"Current session cannot be hidden."</string>
     <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dismiss"</string>
     <string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string>
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 27824ec..a743bbe 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -86,8 +86,7 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Try taking screenshot again"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Can\'t save screenshot due to limited storage space"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Taking screenshots isn\'t allowed by the app or your organisation"</string>
-    <!-- no translation found for screenshot_edit (3510496440489019191) -->
-    <skip />
+    <string name="screenshot_edit" msgid="3510496440489019191">"Edit screenshot"</string>
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Dismiss screenshot"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Screenshot preview"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Screen Recorder"</string>
@@ -1065,8 +1064,7 @@
     <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string>
     <string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
     <string name="controls_media_close_session" msgid="3957093425905475065">"Hide the current session."</string>
-    <!-- no translation found for controls_media_active_session (1984383994625845642) -->
-    <skip />
+    <string name="controls_media_active_session" msgid="1984383994625845642">"Current session cannot be hidden."</string>
     <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dismiss"</string>
     <string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string>
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 4efef9c..1d80192 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -86,8 +86,7 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Փորձեք նորից"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Չհաջողվեց պահել սքրինշոթը անբավարար հիշողության պատճառով"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Հավելվածը կամ ձեր կազմակերպությունը չի թույլատրում սքրինշոթի ստացումը"</string>
-    <!-- no translation found for screenshot_edit (3510496440489019191) -->
-    <skip />
+    <string name="screenshot_edit" msgid="3510496440489019191">"Փոփոխել սքրինշոթը"</string>
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Փակել սքրինշոթը"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Սքրինշոթի նախադիտում"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Էկրանի տեսագրիչ"</string>
@@ -1065,8 +1064,7 @@
     <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Բեռնման խորհուրդներ"</string>
     <string name="controls_media_title" msgid="1746947284862928133">"Մեդիա"</string>
     <string name="controls_media_close_session" msgid="3957093425905475065">"Թաքցրեք ընթացիկ աշխատաշրջանը"</string>
-    <!-- no translation found for controls_media_active_session (1984383994625845642) -->
-    <skip />
+    <string name="controls_media_active_session" msgid="1984383994625845642">"Ընթացիկ աշխատաշրջանը չի կարող թաքցվել։"</string>
     <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Փակել"</string>
     <string name="controls_media_resume" msgid="1933520684481586053">"Շարունակել"</string>
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Կարգավորումներ"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 9bc0356..97aea29 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -86,8 +86,7 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ხელახლა ცადეთ ეკრანის ანაბეჭდის გაკეთება"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"ეკრანის ანაბეჭდის შენახვა ვერ მოხერხდა შეზღუდული მეხსიერების გამო"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ეკრანის ანაბეჭდების შექმნა არ არის ნებადართული აპის ან თქვენი ორგანიზაციის მიერ"</string>
-    <!-- no translation found for screenshot_edit (3510496440489019191) -->
-    <skip />
+    <string name="screenshot_edit" msgid="3510496440489019191">"ეკრანის ანაბეჭდის რედაქტირება"</string>
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"ეკრანის ანაბეჭდის დახურვა"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"ეკრანის ანაბეჭდის გადახედვა"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"ეკრანის ჩამწერი"</string>
@@ -1065,8 +1064,7 @@
     <string name="controls_seeding_in_progress" msgid="3033855341410264148">"მიმდინარეობს რეკომენდაციების ჩატვირთვა"</string>
     <string name="controls_media_title" msgid="1746947284862928133">"მედია"</string>
     <string name="controls_media_close_session" msgid="3957093425905475065">"დაიმალოს მიმდინარე სესია"</string>
-    <!-- no translation found for controls_media_active_session (1984383994625845642) -->
-    <skip />
+    <string name="controls_media_active_session" msgid="1984383994625845642">"მიმდინარე სესიის დამალვა შეუძლებელია."</string>
     <string name="controls_media_dismiss_button" msgid="9081375542265132213">"დახურვა"</string>
     <string name="controls_media_resume" msgid="1933520684481586053">"გაგრძელება"</string>
     <string name="controls_media_settings_button" msgid="5815790345117172504">"პარამეტრები"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 69d3443..9f0f0ae 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -86,8 +86,7 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ກະລຸນາລອງຖ່າຍຮູບໜ້າຈໍອີກຄັ້ງ"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"ບໍ່ສາມາດຖ່າຍຮູບໜ້າຈໍໄດ້ເນື່ອງຈາກພື້ນທີ່ຈັດເກັບຂໍ້ມູນມີຈຳກັດ"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ແອັບ ຫຼື ອົງກອນຂອງທ່ານບໍ່ອະນຸຍາດໃຫ້ຖ່າຍຮູບໜ້າຈໍ"</string>
-    <!-- no translation found for screenshot_edit (3510496440489019191) -->
-    <skip />
+    <string name="screenshot_edit" msgid="3510496440489019191">"ແກ້ໄຂຮູບໜ້າຈໍ"</string>
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"ປິດຮູບໜ້າຈໍ"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"ຕົວຢ່າງຮູບໜ້າຈໍ"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"ໂປຣແກຣມບັນທຶກໜ້າຈໍ"</string>
@@ -1065,8 +1064,7 @@
     <string name="controls_seeding_in_progress" msgid="3033855341410264148">"ກຳລັງໂຫຼດຄຳແນະນຳ"</string>
     <string name="controls_media_title" msgid="1746947284862928133">"ມີເດຍ"</string>
     <string name="controls_media_close_session" msgid="3957093425905475065">"ເຊື່ອງເຊດຊັນປັດຈຸບັນ."</string>
-    <!-- no translation found for controls_media_active_session (1984383994625845642) -->
-    <skip />
+    <string name="controls_media_active_session" msgid="1984383994625845642">"ບໍ່ສາມາດເຊື່ອເຊດຊັນປັດຈຸບັນໄດ້."</string>
     <string name="controls_media_dismiss_button" msgid="9081375542265132213">"ປິດໄວ້"</string>
     <string name="controls_media_resume" msgid="1933520684481586053">"ສືບຕໍ່"</string>
     <string name="controls_media_settings_button" msgid="5815790345117172504">"ການຕັ້ງຄ່າ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index a5d548c..b676e91 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -86,8 +86,7 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Prøv å ta skjermdump på nytt"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Kan ikke lagre skjermdumpen på grunn av begrenset lagringsplass"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Appen eller organisasjonen din tillater ikke at du tar skjermdumper"</string>
-    <!-- no translation found for screenshot_edit (3510496440489019191) -->
-    <skip />
+    <string name="screenshot_edit" msgid="3510496440489019191">"Rediger skjermdumpen"</string>
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Avvis skjermdumpen"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Forhåndsvisning av skjermdump"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Skjermopptaker"</string>
@@ -1065,8 +1064,7 @@
     <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Laster inn anbefalinger"</string>
     <string name="controls_media_title" msgid="1746947284862928133">"Medier"</string>
     <string name="controls_media_close_session" msgid="3957093425905475065">"Skjul den nåværende økten."</string>
-    <!-- no translation found for controls_media_active_session (1984383994625845642) -->
-    <skip />
+    <string name="controls_media_active_session" msgid="1984383994625845642">"Den nåværende økten kan ikke skjules."</string>
     <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Lukk"</string>
     <string name="controls_media_resume" msgid="1933520684481586053">"Gjenoppta"</string>
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Innstillinger"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 0e09185..0db05d8 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -86,8 +86,7 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Tente fazer a captura de tela novamente"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Não é possível salvar a captura de tela, porque não há espaço suficiente"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"O app ou a organização não permitem capturas de tela"</string>
-    <!-- no translation found for screenshot_edit (3510496440489019191) -->
-    <skip />
+    <string name="screenshot_edit" msgid="3510496440489019191">"Editar captura de tela"</string>
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Dispensar captura de tela"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Visualização de captura de tela"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Gravador de tela"</string>
@@ -1065,8 +1064,7 @@
     <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Carregando recomendações"</string>
     <string name="controls_media_title" msgid="1746947284862928133">"Mídia"</string>
     <string name="controls_media_close_session" msgid="3957093425905475065">"Ocultar a sessão atual."</string>
-    <!-- no translation found for controls_media_active_session (1984383994625845642) -->
-    <skip />
+    <string name="controls_media_active_session" msgid="1984383994625845642">"Não é possível ocultar a sessão atual."</string>
     <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dispensar"</string>
     <string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string>
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Configurações"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index ce01888..147ed1d 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -86,8 +86,7 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Experimente voltar a efetuar a captura de ecrã."</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Não é possível guardar a captura de ecrã devido a espaço de armazenamento limitado."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"A app ou a sua entidade não permitem tirar capturas de ecrã"</string>
-    <!-- no translation found for screenshot_edit (3510496440489019191) -->
-    <skip />
+    <string name="screenshot_edit" msgid="3510496440489019191">"Editar captura de ecrã"</string>
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Ignorar captura de ecrã"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Pré-visualização da captura de ecrã"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Gravador de ecrã"</string>
@@ -1065,8 +1064,7 @@
     <string name="controls_seeding_in_progress" msgid="3033855341410264148">"A carregar recomendações…"</string>
     <string name="controls_media_title" msgid="1746947284862928133">"Multimédia"</string>
     <string name="controls_media_close_session" msgid="3957093425905475065">"Oculte a sessão atual."</string>
-    <!-- no translation found for controls_media_active_session (1984383994625845642) -->
-    <skip />
+    <string name="controls_media_active_session" msgid="1984383994625845642">"Não é possível ocultar a sessão atual."</string>
     <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ignorar"</string>
     <string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string>
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Definições"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 0e09185..0db05d8 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -86,8 +86,7 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Tente fazer a captura de tela novamente"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Não é possível salvar a captura de tela, porque não há espaço suficiente"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"O app ou a organização não permitem capturas de tela"</string>
-    <!-- no translation found for screenshot_edit (3510496440489019191) -->
-    <skip />
+    <string name="screenshot_edit" msgid="3510496440489019191">"Editar captura de tela"</string>
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Dispensar captura de tela"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Visualização de captura de tela"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Gravador de tela"</string>
@@ -1065,8 +1064,7 @@
     <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Carregando recomendações"</string>
     <string name="controls_media_title" msgid="1746947284862928133">"Mídia"</string>
     <string name="controls_media_close_session" msgid="3957093425905475065">"Ocultar a sessão atual."</string>
-    <!-- no translation found for controls_media_active_session (1984383994625845642) -->
-    <skip />
+    <string name="controls_media_active_session" msgid="1984383994625845642">"Não é possível ocultar a sessão atual."</string>
     <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dispensar"</string>
     <string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string>
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Configurações"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 29489fd..eab7f69 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -86,8 +86,7 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Jaribu kupiga picha ya skrini tena"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Imeshindwa kuhifadhi picha ya skrini kwa sababu nafasi haitoshi"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Programu au shirika lako halikuruhusu kupiga picha za skrini"</string>
-    <!-- no translation found for screenshot_edit (3510496440489019191) -->
-    <skip />
+    <string name="screenshot_edit" msgid="3510496440489019191">"Badilisha picha ya skrini"</string>
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Ondoa picha ya skrini"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Onyesho la kukagua picha ya skrini"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Kinasa Skrini"</string>
@@ -1065,8 +1064,7 @@
     <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Inapakia mapendekezo"</string>
     <string name="controls_media_title" msgid="1746947284862928133">"Maudhui"</string>
     <string name="controls_media_close_session" msgid="3957093425905475065">"Ficha kipindi cha sasa."</string>
-    <!-- no translation found for controls_media_active_session (1984383994625845642) -->
-    <skip />
+    <string name="controls_media_active_session" msgid="1984383994625845642">"Huwezi kuficha kipindi cha sasa."</string>
     <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ondoa"</string>
     <string name="controls_media_resume" msgid="1933520684481586053">"Endelea"</string>
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Mipangilio"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 71c1dde..332a26d 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -86,8 +86,7 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Qayta skrinshot olib ko‘ring"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Xotirada joy kamligi uchun skrinshot saqlanmadi"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Ilova yoki tashkilotingiz skrinshot olishni taqiqlagan"</string>
-    <!-- no translation found for screenshot_edit (3510496440489019191) -->
-    <skip />
+    <string name="screenshot_edit" msgid="3510496440489019191">"Skrinshotni tahrirlash"</string>
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Skrinshotni yopish"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Skrinshotga razm solish"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Ekrandan yozib olish"</string>
@@ -1065,8 +1064,7 @@
     <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Tavsiyalar yuklanmoqda"</string>
     <string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
     <string name="controls_media_close_session" msgid="3957093425905475065">"Joriy seans berkitilsin."</string>
-    <!-- no translation found for controls_media_active_session (1984383994625845642) -->
-    <skip />
+    <string name="controls_media_active_session" msgid="1984383994625845642">"Joriy seans berkilmaydi."</string>
     <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Yopish"</string>
     <string name="controls_media_resume" msgid="1933520684481586053">"Davom etish"</string>
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Sozlamalar"</string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
index 97196d1..5b41d5f 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
@@ -55,8 +55,6 @@
             WindowManager.TRANSIT_WALLPAPER_INTRA_CLOSE;
     public static final int TRANSIT_TASK_OPEN_BEHIND = WindowManager.TRANSIT_TASK_OPEN_BEHIND;
     public static final int TRANSIT_ACTIVITY_RELAUNCH = WindowManager.TRANSIT_ACTIVITY_RELAUNCH;
-    public static final int TRANSIT_DOCK_TASK_FROM_RECENTS =
-            WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
     public static final int TRANSIT_KEYGUARD_GOING_AWAY = WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
     public static final int TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER =
             WindowManager.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
diff --git a/packages/SystemUI/src/com/android/keyguard/GradientTextClock.java b/packages/SystemUI/src/com/android/keyguard/GradientTextClock.java
new file mode 100644
index 0000000..b596388
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/GradientTextClock.java
@@ -0,0 +1,102 @@
+/*
+ * 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.keyguard;
+
+import android.content.Context;
+import android.graphics.LinearGradient;
+import android.graphics.Shader;
+import android.util.AttributeSet;
+import android.widget.TextClock;
+
+/**
+ * Displays the time with the hour positioned above the minutes. (ie: 09 above 30 is 9:30)
+ * The time's text color is a gradient that changes its colors based on its controller.
+ */
+public class GradientTextClock extends TextClock {
+    private int[] mGradientColors;
+    private float[] mPositions;
+
+    public GradientTextClock(Context context) {
+        this(context, null, 0, 0);
+    }
+
+    public GradientTextClock(Context context, AttributeSet attrs) {
+        this(context, attrs, 0, 0);
+    }
+
+    public GradientTextClock(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public GradientTextClock(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    @Override
+    public void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        addOnLayoutChangeListener(mOnLayoutChangeListener);
+    }
+
+    @Override
+    public void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        removeOnLayoutChangeListener(mOnLayoutChangeListener);
+    }
+
+    @Override
+    public void refreshTime() {
+        updatePaint();
+        super.refreshTime();
+    }
+
+    @Override
+    public void setFormat12Hour(CharSequence format) {
+        super.setFormat12Hour(FORMAT_12);
+    }
+
+    @Override
+    public void setFormat24Hour(CharSequence format) {
+        super.setFormat24Hour(FORMAT_24);
+    }
+
+    public void setGradientColors(int[] colors) {
+        mGradientColors = colors;
+    }
+
+    public void setColorPositions(float[] positions) {
+        mPositions = positions;
+    }
+
+    private void updatePaint() {
+        getPaint().setShader(
+                new LinearGradient(
+                        getX(), getY(), getX(), getMeasuredHeight() + getY(),
+                        mGradientColors, mPositions, Shader.TileMode.REPEAT));
+    }
+
+    private final OnLayoutChangeListener mOnLayoutChangeListener =
+            (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
+                if (bottom != oldBottom || top != oldTop) {
+                    updatePaint();
+                }
+            };
+
+    public static final CharSequence FORMAT_12 = "hh\nmm";
+    public static final CharSequence FORMAT_24 = "HH\nmm";
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 272954d..cf363cc 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -72,6 +72,16 @@
     private TextClock mClockViewBold;
 
     /**
+     * Gradient clock for usage when mode != KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL.
+     */
+    private TimeBasedColorsClockController mNewLockscreenClockViewController;
+
+    /**
+     * Frame for clock when mode != KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL.
+     */
+    private FrameLayout mNewLockscreenClockFrame;
+
+    /**
      * Frame for default and custom clock.
      */
     private FrameLayout mSmallClockFrame;
@@ -137,23 +147,22 @@
         mLockScreenMode = mode;
         RelativeLayout.LayoutParams statusAreaLP = (RelativeLayout.LayoutParams)
                 mKeyguardStatusArea.getLayoutParams();
-        RelativeLayout.LayoutParams clockLP = (RelativeLayout.LayoutParams)
-                mSmallClockFrame.getLayoutParams();
 
         if (mode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1) {
-            statusAreaLP.removeRule(RelativeLayout.BELOW);
-            statusAreaLP.addRule(RelativeLayout.LEFT_OF, R.id.clock_view);
-            statusAreaLP.addRule(RelativeLayout.ALIGN_PARENT_START);
+            mSmallClockFrame.setVisibility(GONE);
+            mNewLockscreenClockFrame.setVisibility(VISIBLE);
+            mNewLockscreenClockViewController.init();
 
-            clockLP.addRule(RelativeLayout.ALIGN_PARENT_END);
-            clockLP.width = ViewGroup.LayoutParams.WRAP_CONTENT;
+            statusAreaLP.removeRule(RelativeLayout.BELOW);
+            statusAreaLP.addRule(RelativeLayout.LEFT_OF, R.id.new_lockscreen_clock_view);
+            statusAreaLP.addRule(RelativeLayout.ALIGN_PARENT_START);
         } else {
+            mSmallClockFrame.setVisibility(VISIBLE);
+            mNewLockscreenClockFrame.setVisibility(GONE);
+
             statusAreaLP.removeRule(RelativeLayout.LEFT_OF);
             statusAreaLP.removeRule(RelativeLayout.ALIGN_PARENT_START);
             statusAreaLP.addRule(RelativeLayout.BELOW, R.id.clock_view);
-
-            clockLP.removeRule(RelativeLayout.ALIGN_PARENT_END);
-            clockLP.width = ViewGroup.LayoutParams.MATCH_PARENT;
         }
 
         requestLayout();
@@ -164,6 +173,9 @@
         super.onFinishInflate();
         mClockView = findViewById(R.id.default_clock_view);
         mClockViewBold = findViewById(R.id.default_clock_view_bold);
+        mNewLockscreenClockFrame = findViewById(R.id.new_lockscreen_clock_view);
+        mNewLockscreenClockViewController =
+                new TimeBasedColorsClockController(findViewById(R.id.gradient_clock_view));
         mSmallClockFrame = findViewById(R.id.clock_view);
         mKeyguardStatusArea = findViewById(R.id.keyguard_status_area);
     }
@@ -336,6 +348,7 @@
      * Refresh the time of the clock, due to either time tick broadcast or doze time tick alarm.
      */
     public void refresh() {
+        mNewLockscreenClockViewController.refreshTime(System.currentTimeMillis());
         mClockView.refreshTime();
         mClockViewBold.refreshTime();
         if (mClockPlugin != null) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardRootViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardRootViewController.java
index 5c125fc..4e375c2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardRootViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardRootViewController.java
@@ -19,7 +19,7 @@
 import android.view.ViewGroup;
 
 import com.android.keyguard.dagger.KeyguardBouncerScope;
-import com.android.keyguard.dagger.RootView;
+import com.android.systemui.dagger.qualifiers.RootView;
 import com.android.systemui.statusbar.phone.KeyguardBouncer;
 import com.android.systemui.util.ViewController;
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index a479bca..a9c06ed 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -33,9 +33,11 @@
 import android.text.TextUtils.TruncateAt;
 import android.util.AttributeSet;
 import android.util.TypedValue;
+import android.view.Gravity;
 import android.view.View;
 import android.view.animation.Animation;
 import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
 import android.widget.TextView;
 
 import androidx.slice.SliceItem;
@@ -55,8 +57,10 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * View visible under the clock on the lock screen and AoD.
@@ -86,6 +90,8 @@
     private float mRowWithHeaderTextSize;
     private View.OnClickListener mOnClickListener;
 
+    private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
+
     public KeyguardSliceView(Context context, AttributeSet attrs) {
         super(context, attrs);
 
@@ -142,6 +148,40 @@
         }
     }
 
+    /**
+     * Updates the lockscreen mode which may change the layout of the keyguard slice view.
+     */
+    public void updateLockScreenMode(int mode) {
+        mLockScreenMode = mode;
+        if (mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1) {
+            // add top padding to better align with top of clock
+            final int topPadding = (int) TypedValue.applyDimension(
+                    TypedValue.COMPLEX_UNIT_DIP,
+                    20,
+                    getResources().getDisplayMetrics());
+            mTitle.setPaddingRelative(0, topPadding, 0, 0);
+            mTitle.setGravity(Gravity.START);
+            setGravity(Gravity.START);
+            RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) getLayoutParams();
+            lp.removeRule(RelativeLayout.CENTER_HORIZONTAL);
+            setLayoutParams(lp);
+        } else {
+            final int horizontalPaddingDpValue = (int) TypedValue.applyDimension(
+                    TypedValue.COMPLEX_UNIT_DIP,
+                    44,
+                    getResources().getDisplayMetrics()
+            );
+            mTitle.setPaddingRelative(horizontalPaddingDpValue, 0, horizontalPaddingDpValue, 0);
+            mTitle.setGravity(Gravity.CENTER_HORIZONTAL);
+            setGravity(Gravity.CENTER_HORIZONTAL);
+            RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) getLayoutParams();
+            lp.addRule(RelativeLayout.CENTER_HORIZONTAL);
+            setLayoutParams(lp);
+        }
+        mRow.setLockscreenMode(mode);
+        requestLayout();
+    }
+
     Map<View, PendingIntent> showSlice(RowContent header, List<SliceContent> subItems) {
         Trace.beginSection("KeyguardSliceView#showSlice");
         mHasHeader = header != null;
@@ -166,6 +206,8 @@
         final int startIndex = mHasHeader ? 1 : 0; // First item is header; skip it
         mRow.setVisibility(subItemsCount > 0 ? VISIBLE : GONE);
         LinearLayout.LayoutParams layoutParams = (LayoutParams) mRow.getLayoutParams();
+        layoutParams.gravity = mLockScreenMode !=  KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL
+                ? Gravity.START :  Gravity.CENTER;
         layoutParams.topMargin = mHasHeader ? mRowWithHeaderPadding : mRowPadding;
         mRow.setLayoutParams(layoutParams);
 
@@ -282,6 +324,7 @@
         pw.println("  mTextColor: " + Integer.toHexString(mTextColor));
         pw.println("  mDarkAmount: " + mDarkAmount);
         pw.println("  mHasHeader: " + mHasHeader);
+        pw.println("  mLockScreenMode: " + mLockScreenMode);
     }
 
     @Override
@@ -291,6 +334,8 @@
     }
 
     public static class Row extends LinearLayout {
+        private Set<KeyguardSliceTextView> mKeyguardSliceTextViewSet = new HashSet();
+        private int mLockScreenModeRow = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
 
         /**
          * This view is visible in AOD, which means that the device will sleep if we
@@ -361,12 +406,18 @@
         protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
             int width = MeasureSpec.getSize(widthMeasureSpec);
             int childCount = getChildCount();
+
             for (int i = 0; i < childCount; i++) {
                 View child = getChildAt(i);
                 if (child instanceof KeyguardSliceTextView) {
-                    ((KeyguardSliceTextView) child).setMaxWidth(width / 3);
+                    if (mLockScreenModeRow == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1) {
+                        ((KeyguardSliceTextView) child).setMaxWidth(Integer.MAX_VALUE);
+                    } else {
+                        ((KeyguardSliceTextView) child).setMaxWidth(width / 3);
+                    }
                 }
             }
+
             super.onMeasure(widthMeasureSpec, heightMeasureSpec);
         }
 
@@ -384,6 +435,42 @@
         public boolean hasOverlappingRendering() {
             return false;
         }
+
+        @Override
+        public void addView(View view, int index) {
+            super.addView(view, index);
+
+            if (view instanceof KeyguardSliceTextView) {
+                ((KeyguardSliceTextView) view).setLockScreenMode(mLockScreenModeRow);
+                mKeyguardSliceTextViewSet.add((KeyguardSliceTextView) view);
+            }
+        }
+
+        @Override
+        public void removeView(View view) {
+            super.removeView(view);
+            if (view instanceof KeyguardSliceTextView) {
+                mKeyguardSliceTextViewSet.remove((KeyguardSliceTextView) view);
+            }
+        }
+
+        /**
+         * Updates the lockscreen mode which may change the layout of this view.
+         */
+        public void setLockscreenMode(int mode) {
+            mLockScreenModeRow = mode;
+            if (mLockScreenModeRow == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1) {
+                setOrientation(LinearLayout.VERTICAL);
+                setGravity(Gravity.START);
+            } else {
+                setOrientation(LinearLayout.HORIZONTAL);
+                setGravity(Gravity.CENTER);
+            }
+
+            for (KeyguardSliceTextView textView : mKeyguardSliceTextViewSet) {
+                textView.setLockScreenMode(mLockScreenModeRow);
+            }
+        }
     }
 
     /**
@@ -392,6 +479,7 @@
     @VisibleForTesting
     static class KeyguardSliceTextView extends TextView implements
             ConfigurationController.ConfigurationListener {
+        private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
 
         @StyleRes
         private static int sStyleId = R.style.TextAppearance_Keyguard_Secondary;
@@ -432,9 +520,16 @@
 
         private void updatePadding() {
             boolean hasText = !TextUtils.isEmpty(getText());
-            int horizontalPadding = (int) getContext().getResources()
+            int padding = (int) getContext().getResources()
                     .getDimension(R.dimen.widget_horizontal_padding) / 2;
-            setPadding(horizontalPadding, 0, horizontalPadding * (hasText ? 1 : -1), 0);
+            if (mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1) {
+                // orientation is vertical, so add padding to top & bottom
+                setPadding(0, padding, 0, padding * (hasText ? 1 : -1));
+            } else {
+                // oreintation is horizontal, so add padding to left & right
+                setPadding(padding, 0, padding * (hasText ? 1 : -1), 0);
+            }
+
             setCompoundDrawablePadding((int) mContext.getResources()
                     .getDimension(R.dimen.widget_icon_padding));
         }
@@ -461,5 +556,18 @@
                 }
             }
         }
+
+        /**
+         * Updates the lockscreen mode which may change the layout of this view.
+         */
+        public void setLockScreenMode(int mode) {
+            mLockScreenMode = mode;
+            if (mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1) {
+                setGravity(Gravity.START);
+            } else {
+                setGravity(Gravity.CENTER);
+            }
+            updatePadding();
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceViewController.java
index 3be7e0a..8b55b06 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceViewController.java
@@ -44,6 +44,7 @@
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.tuner.TunerService;
+import com.android.systemui.util.ViewController;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -55,10 +56,10 @@
 
 /** Controller for a {@link KeyguardSliceView}. */
 @KeyguardStatusViewScope
-public class KeyguardSliceViewController implements Dumpable {
+public class KeyguardSliceViewController extends ViewController<KeyguardSliceView> implements
+        Dumpable {
     private static final String TAG = "KeyguardSliceViewCtrl";
 
-    private final KeyguardSliceView mView;
     private final ActivityStarter mActivityStarter;
     private final ConfigurationController mConfigurationController;
     private final TunerService mTunerService;
@@ -68,41 +69,7 @@
     private Uri mKeyguardSliceUri;
     private Slice mSlice;
     private Map<View, PendingIntent> mClickActions;
-
-    private final View.OnAttachStateChangeListener mOnAttachStateChangeListener =
-            new View.OnAttachStateChangeListener() {
-
-                @Override
-                public void onViewAttachedToWindow(View v) {
-
-                    Display display = mView.getDisplay();
-                    if (display != null) {
-                        mDisplayId = display.getDisplayId();
-                    }
-                    mTunerService.addTunable(mTunable, Settings.Secure.KEYGUARD_SLICE_URI);
-                    // Make sure we always have the most current slice
-                    if (mDisplayId == DEFAULT_DISPLAY && mLiveData != null) {
-                        mLiveData.observeForever(mObserver);
-                    }
-                    mConfigurationController.addCallback(mConfigurationListener);
-                    mDumpManager.registerDumpable(
-                            TAG + "@" + Integer.toHexString(
-                                    KeyguardSliceViewController.this.hashCode()),
-                            KeyguardSliceViewController.this);
-                }
-
-                @Override
-                public void onViewDetachedFromWindow(View v) {
-
-                    // TODO(b/117344873) Remove below work around after this issue be fixed.
-                    if (mDisplayId == DEFAULT_DISPLAY) {
-                        mLiveData.removeObserver(mObserver);
-                    }
-                    mTunerService.removeTunable(mTunable);
-                    mConfigurationController.removeCallback(mConfigurationListener);
-                    mDumpManager.unregisterDumpable(TAG);
-                }
-            };
+    private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
 
     TunerService.Tunable mTunable = (key, newValue) -> setupUri(newValue);
 
@@ -133,24 +100,57 @@
     };
 
     @Inject
-    public KeyguardSliceViewController(KeyguardSliceView keyguardSliceView,
+    public KeyguardSliceViewController(
+            KeyguardSliceView keyguardSliceView,
             ActivityStarter activityStarter,
-            ConfigurationController configurationController, TunerService tunerService,
+            ConfigurationController configurationController,
+            TunerService tunerService,
             DumpManager dumpManager) {
-        mView = keyguardSliceView;
+        super(keyguardSliceView);
         mActivityStarter = activityStarter;
         mConfigurationController = configurationController;
         mTunerService = tunerService;
         mDumpManager = dumpManager;
     }
 
-    /** Initialize the controller. */
-    public void init() {
-        if (mView.isAttachedToWindow()) {
-            mOnAttachStateChangeListener.onViewAttachedToWindow(mView);
+    @Override
+    protected void onViewAttached() {
+        Display display = mView.getDisplay();
+        if (display != null) {
+            mDisplayId = display.getDisplayId();
         }
-        mView.addOnAttachStateChangeListener(mOnAttachStateChangeListener);
-        mView.setOnClickListener(mOnClickListener);
+        mTunerService.addTunable(mTunable, Settings.Secure.KEYGUARD_SLICE_URI);
+        // Make sure we always have the most current slice
+        if (mDisplayId == DEFAULT_DISPLAY && mLiveData != null) {
+            mLiveData.observeForever(mObserver);
+        }
+        mConfigurationController.addCallback(mConfigurationListener);
+        mDumpManager.registerDumpable(
+                TAG + "@" + Integer.toHexString(
+                        KeyguardSliceViewController.this.hashCode()),
+                KeyguardSliceViewController.this);
+        mView.updateLockScreenMode(mLockScreenMode);
+    }
+
+    @Override
+    protected void onViewDetached() {
+        // TODO(b/117344873) Remove below work around after this issue be fixed.
+        if (mDisplayId == DEFAULT_DISPLAY) {
+            mLiveData.removeObserver(mObserver);
+        }
+        mTunerService.removeTunable(mTunable);
+        mConfigurationController.removeCallback(mConfigurationListener);
+        mDumpManager.unregisterDumpable(
+                TAG + "@" + Integer.toHexString(
+                        KeyguardSliceViewController.this.hashCode()));
+    }
+
+    /**
+     * Updates the lockscreen mode which may change the layout of the keyguard slice view.
+     */
+    public void updateLockScreenMode(int mode) {
+        mLockScreenMode = mode;
+        mView.updateLockScreenMode(mLockScreenMode);
     }
 
     /**
@@ -224,10 +224,10 @@
         Trace.endSection();
     }
 
-
     @Override
     public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
         pw.println("  mSlice: " + mSlice);
         pw.println("  mClickActions: " + mClickActions);
+        pw.println("  mLockScreenMode: " + mLockScreenMode);
     }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index 0efb5ee..7705db4 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -267,6 +267,7 @@
         @Override
         public void onLockScreenModeChanged(int mode) {
             mKeyguardClockSwitchController.updateLockScreenMode(mode);
+            mKeyguardSliceViewController.updateLockScreenMode(mode);
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/TimeBasedColorsClockController.java b/packages/SystemUI/src/com/android/keyguard/TimeBasedColorsClockController.java
new file mode 100644
index 0000000..4f1963e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/TimeBasedColorsClockController.java
@@ -0,0 +1,139 @@
+/*
+ * 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.keyguard;
+
+import com.android.systemui.util.ViewController;
+
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+
+/**
+ * Changes the color of the text clock based on the time of day.
+ */
+public class TimeBasedColorsClockController extends ViewController<GradientTextClock> {
+    private final int[] mGradientColors = new int[3];
+    private final float[] mPositions = new float[3];
+
+    public TimeBasedColorsClockController(GradientTextClock view) {
+        super(view);
+    }
+
+    @Override
+    protected void onViewAttached() {
+        refreshTime(System.currentTimeMillis());
+    }
+
+    @Override
+    protected void onViewDetached() {
+
+    }
+
+    /**
+     * Updates the time for this view. Also updates any color changes.
+     */
+    public void refreshTime(long timeInMillis) {
+        Calendar now = new GregorianCalendar();
+        now.setTimeInMillis(timeInMillis);
+        updateColors(now);
+        updatePositions(now);
+        mView.refreshTime();
+    }
+
+    private int getTimeIndex(Calendar now) {
+        int hour = now.get(Calendar.HOUR_OF_DAY); // 0 - 23
+        if (hour < mTimes[0]) {
+            return mTimes.length - 1;
+        }
+
+        for (int i = 1; i < mTimes.length; i++) {
+            if (hour < mTimes[i]) {
+                return i - 1;
+            }
+        }
+
+        return mTimes.length - 1;
+    }
+
+    private void updateColors(Calendar now) {
+        final int index = getTimeIndex(now);
+        for (int i = 0; i < mGradientColors.length; i++) {
+            mGradientColors[i] = COLORS[index][i];
+        }
+        mView.setGradientColors(mGradientColors);
+    }
+
+    private void updatePositions(Calendar now) {
+        final int index = getTimeIndex(now);
+
+        final Calendar startTime = new GregorianCalendar();
+        startTime.setTimeInMillis(now.getTimeInMillis());
+        startTime.set(Calendar.HOUR_OF_DAY, mTimes[index]);
+        if (startTime.getTimeInMillis() > now.getTimeInMillis()) {
+            // start should be earlier than 'now'
+            startTime.add(Calendar.DATE, -1);
+        }
+
+        final Calendar endTime = new GregorianCalendar();
+        endTime.setTimeInMillis(now.getTimeInMillis());
+        if (index == mTimes.length - 1) {
+            endTime.set(Calendar.HOUR_OF_DAY, mTimes[0]);
+            endTime.add(Calendar.DATE, 1); // end time is tomorrow
+        } else {
+            endTime.set(Calendar.HOUR_OF_DAY, mTimes[index + 1]);
+        }
+
+        long totalTimeInThisColorGradient = endTime.getTimeInMillis() - startTime.getTimeInMillis();
+        long timeIntoThisColorGradient = now.getTimeInMillis() - startTime.getTimeInMillis();
+        float percentageWithinGradient =
+                (float) timeIntoThisColorGradient / (float) totalTimeInThisColorGradient;
+
+        for (int i = 0; i < mPositions.length; i++) {
+            // currently hard-coded .3 movement of gradient
+            mPositions[i] = POSITIONS[index][i] - (.3f * percentageWithinGradient);
+        }
+        mView.setColorPositions(mPositions);
+    }
+
+    private static final int[] SUNRISE = new int[] {0xFF6F75AA, 0xFFAFF0FF, 0xFFFFDEBF};
+    private static final int[] DAY = new int[] {0xFF9BD8FB, 0xFFD7F5FF, 0xFFFFF278};
+    private static final int[] NIGHT = new int[] {0xFF333D5E, 0xFFC5A1D6, 0xFF907359};
+
+    private static final float[] SUNRISE_START_POSITIONS = new float[] {.3f, .5f, .8f};
+    private static final float[] DAY_START_POSITIONS = new float[] {.4f, .8f, 1f};
+    private static final float[] NIGHT_START_POSITIONS = new float[] {.25f, .5f, .8f};
+
+    // TODO (b/170228350): use TwilightManager to set sunrise/sunset times
+    private final int mSunriseTime = 6; // 6am
+    private final int mDaytime = 9; // 9 am
+    private final int mNightTime = 19; // 7pm
+
+    private int[] mTimes = new int[] {
+            mSunriseTime,
+            mDaytime,
+            mNightTime
+    };
+    private static final int[][] COLORS = new int[][] {
+            SUNRISE,
+            DAY,
+            NIGHT
+    };
+    private static final float[][] POSITIONS = new float[][] {
+            SUNRISE_START_POSITIONS,
+            DAY_START_POSITIONS,
+            NIGHT_START_POSITIONS
+    };
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java
index 8811088..4fad9a9 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java
@@ -24,6 +24,7 @@
 import com.android.keyguard.KeyguardSecurityContainer;
 import com.android.keyguard.KeyguardSecurityViewFlipper;
 import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.RootView;
 import com.android.systemui.statusbar.phone.KeyguardBouncer;
 
 import dagger.Module;
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 9f28e09..8ac6edb 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -119,13 +119,11 @@
 import com.android.systemui.tracing.ProtoTracer;
 import com.android.systemui.tuner.TunablePadding.TunablePaddingService;
 import com.android.systemui.tuner.TunerService;
+import com.android.systemui.util.DeviceConfigProxy;
 import com.android.systemui.util.leak.GarbageMonitor;
 import com.android.systemui.util.leak.LeakDetector;
 import com.android.systemui.util.leak.LeakReporter;
 import com.android.systemui.util.sensors.AsyncSensorManager;
-import com.android.wm.shell.common.DisplayController;
-import com.android.wm.shell.common.DisplayImeController;
-import com.android.wm.shell.common.SystemWindows;
 
 import java.util.concurrent.Executor;
 import java.util.function.Consumer;
@@ -340,12 +338,10 @@
     @Inject Lazy<CommandQueue> mCommandQueue;
     @Inject Lazy<Recents> mRecents;
     @Inject Lazy<StatusBar> mStatusBar;
-    @Inject Lazy<DisplayController> mDisplayController;
-    @Inject Lazy<SystemWindows> mSystemWindows;
-    @Inject Lazy<DisplayImeController> mDisplayImeController;
     @Inject Lazy<RecordingController> mRecordingController;
     @Inject Lazy<ProtoTracer> mProtoTracer;
     @Inject Lazy<MediaOutputDialogFactory> mMediaOutputDialogFactory;
+    @Inject Lazy<DeviceConfigProxy> mDeviceConfigProxy;
 
     @Inject
     public Dependency() {
@@ -530,10 +526,8 @@
         mProviders.put(CommandQueue.class, mCommandQueue::get);
         mProviders.put(Recents.class, mRecents::get);
         mProviders.put(StatusBar.class, mStatusBar::get);
-        mProviders.put(DisplayController.class, mDisplayController::get);
-        mProviders.put(SystemWindows.class, mSystemWindows::get);
-        mProviders.put(DisplayImeController.class, mDisplayImeController::get);
         mProviders.put(ProtoTracer.class, mProtoTracer::get);
+        mProviders.put(DeviceConfigProxy.class, mDeviceConfigProxy::get);
 
         // TODO(b/118592525): to support multi-display , we start to add something which is
         //                    per-display, while others may be global. I think it's time to add
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 7dcec3d..b388a6e 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -19,15 +19,18 @@
 import android.app.ActivityThread;
 import android.app.Application;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.os.Process;
 import android.os.SystemProperties;
 import android.os.Trace;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.util.Log;
 import android.util.TimingsTraceLog;
 
@@ -35,6 +38,7 @@
 import com.android.systemui.dagger.GlobalRootComponent;
 import com.android.systemui.dagger.SysUIComponent;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.people.PeopleSpaceActivity;
 import com.android.systemui.util.NotificationChannels;
 
 import java.lang.reflect.Constructor;
@@ -104,6 +108,19 @@
                             mServices[i].onBootCompleted();
                         }
                     }
+                    // If flag SHOW_PEOPLE_SPACE is true, enable People Space launcher icon.
+                    try {
+                        int showPeopleSpace = Settings.Global.getInt(context.getContentResolver(),
+                                Settings.Global.SHOW_PEOPLE_SPACE);
+                        context.getPackageManager().setComponentEnabledSetting(
+                                new ComponentName(context, PeopleSpaceActivity.class),
+                                showPeopleSpace == 1
+                                        ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+                                        : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+                                PackageManager.DONT_KILL_APP);
+                    } catch (Exception e) {
+                        Log.w(TAG, "Error enabling People Space launch icon:", e);
+                    }
                 }
             }, bootCompletedFilter);
 
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 80253b4..bdd0b55 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -30,6 +30,7 @@
 import com.android.systemui.navigationbar.gestural.BackGestureTfClassifierProvider;
 import com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider;
 
+import java.util.Optional;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
 
@@ -49,6 +50,11 @@
     }
 
     public static void createFromConfig(Context context) {
+        createFromConfig(context, false);
+    }
+
+    @VisibleForTesting
+    public static void createFromConfig(Context context, boolean fromTest) {
         if (mFactory != null) {
             return;
         }
@@ -62,7 +68,7 @@
             Class<?> cls = null;
             cls = context.getClassLoader().loadClass(clsName);
             mFactory = (SystemUIFactory) cls.newInstance();
-            mFactory.init(context);
+            mFactory.init(context, fromTest);
         } catch (Throwable t) {
             Log.w(TAG, "Error creating SystemUIFactory component: " + clsName, t);
             throw new RuntimeException(t);
@@ -76,16 +82,40 @@
 
     public SystemUIFactory() {}
 
-    private void init(Context context) throws ExecutionException, InterruptedException {
+    @VisibleForTesting
+    public void init(Context context, boolean fromTest)
+            throws ExecutionException, InterruptedException {
+        final boolean initializeComponents = !fromTest
+                && android.os.Process.myUserHandle().isSystem();
         mRootComponent = buildGlobalRootComponent(context);
         // Stand up WMComponent
         mWMComponent = mRootComponent.getWMComponentBuilder().build();
+        if (initializeComponents) {
+            // Only initialize when not starting from tests since this currently initializes some
+            // components that shouldn't be run in the test environment
+            mWMComponent.init();
+        }
 
         // And finally, retrieve whatever SysUI needs from WMShell and build SysUI.
-        // TODO: StubAPIClass is just a placeholder.
-        mSysUIComponent = mRootComponent.getSysUIComponent()
-                .setStubAPIClass(mWMComponent.createStubAPIClass())
+        SysUIComponent.Builder builder = mRootComponent.getSysUIComponent();
+        if (initializeComponents) {
+            // Only initialize when not starting from tests since this currently initializes some
+            // components that shouldn't be run in the test environment
+            builder = builder.setPip(mWMComponent.getPip())
+                    .setSplitScreen(mWMComponent.getSplitScreen())
+                    .setOneHanded(mWMComponent.getOneHanded());
+        } else {
+            builder = builder.setPip(Optional.ofNullable(null))
+                    .setSplitScreen(Optional.ofNullable(null))
+                    .setOneHanded(Optional.ofNullable(null));
+        }
+        mSysUIComponent = builder
+                .setInputConsumerController(mWMComponent.getInputConsumerController())
+                .setShellTaskOrganizer(mWMComponent.getShellTaskOrganizer())
                 .build();
+        if (initializeComponents) {
+            mSysUIComponent.init();
+        }
 
         // Every other part of our codebase currently relies on Dependency, so we
         // really need to ensure the Dependency gets initialized early on.
@@ -93,6 +123,16 @@
         dependency.start();
     }
 
+    /**
+     * Prepares the SysUIComponent builder before it is built.
+     * @param sysUIBuilder the builder provided by the root component's getSysUIComponent() method
+     * @param wm the built WMComponent from the root component's getWMComponent() method
+     */
+    protected SysUIComponent.Builder prepareSysUIComponentBuilder(
+            SysUIComponent.Builder sysUIBuilder, WMComponent wm) {
+        return sysUIBuilder;
+    }
+
     protected GlobalRootComponent buildGlobalRootComponent(Context context) {
         return DaggerGlobalRootComponent.builder()
                 .context(context)
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 3f94b00..0c3dc82 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -177,6 +177,7 @@
     private ScrimView mBubbleScrim;
     @Nullable private BubbleStackView mStackView;
     private BubbleIconFactory mBubbleIconFactory;
+    private BubblePositioner mBubblePositioner;
 
     /**
      * The relative position of the stack when we removed it and nulled it out. If the stack is
@@ -244,7 +245,7 @@
 
     private boolean mInflateSynchronously;
 
-    private MultiWindowTaskListener mTaskListener;
+    private ShellTaskOrganizer mTaskOrganizer;
 
     // TODO (b/145659174): allow for multiple callbacks to support the "shadow" new notif pipeline
     private final List<NotifCallback> mCallbacks = new ArrayList<>();
@@ -387,7 +388,7 @@
                 dumpManager, floatingContentCoordinator,
                 new BubbleDataRepository(context, launcherApps), sysUiState, notificationManager,
                 statusBarService, windowManager, windowManagerShellWrapper, launcherApps, logger,
-                mainHandler, organizer);
+                mainHandler, organizer, new BubblePositioner(context, windowManager));
     }
 
     /**
@@ -419,7 +420,8 @@
             LauncherApps launcherApps,
             BubbleLogger bubbleLogger,
             Handler mainHandler,
-            ShellTaskOrganizer organizer) {
+            ShellTaskOrganizer organizer,
+            BubblePositioner positioner) {
         dumpManager.registerDumpable(TAG, this);
         mContext = context;
         mShadeController = shadeController;
@@ -529,7 +531,8 @@
                 });
 
         mBubbleIconFactory = new BubbleIconFactory(context);
-        mTaskListener = new MultiWindowTaskListener(mMainHandler, organizer);
+        mTaskOrganizer = organizer;
+        mBubblePositioner = positioner;
 
         launcherApps.registerCallback(new LauncherApps.Callback() {
             @Override
@@ -805,8 +808,13 @@
     }
 
     @Override
-    public MultiWindowTaskListener getTaskManager() {
-        return mTaskListener;
+    public ShellTaskOrganizer getTaskOrganizer() {
+        return mTaskOrganizer;
+    }
+
+    @Override
+    public BubblePositioner getPositioner() {
+        return mBubblePositioner;
     }
 
     /**
@@ -818,9 +826,10 @@
             mStackView = new BubbleStackView(
                     mContext, mBubbleData, mSurfaceSynchronizer, mFloatingContentCoordinator,
                     this::onAllBubblesAnimatedOut, this::onImeVisibilityChanged,
-                    this::hideCurrentInputMethod, this::onBubbleExpandChanged);
+                    this::hideCurrentInputMethod, this::onBubbleExpandChanged, mBubblePositioner);
             mStackView.setStackStartPosition(mPositionFromRemovedStack);
             mStackView.addView(mBubbleScrim);
+            mStackView.onOrientationChanged();
             if (mExpandListener != null) {
                 mStackView.setExpandListener(mExpandListener);
             }
@@ -978,10 +987,14 @@
 
     @Override
     public void onConfigChanged(Configuration newConfig) {
+        if (mBubblePositioner != null) {
+            // This doesn't trigger any changes, always update it
+            mBubblePositioner.update(newConfig.orientation);
+        }
         if (mStackView != null && newConfig != null) {
             if (newConfig.orientation != mOrientation) {
                 mOrientation = newConfig.orientation;
-                mStackView.onOrientationChanged(newConfig.orientation);
+                mStackView.onOrientationChanged();
             }
             if (newConfig.densityDpi != mDensityDpi) {
                 mDensityDpi = newConfig.densityDpi;
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 98a2257..bc06020 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -38,7 +38,6 @@
 import android.content.res.TypedArray;
 import android.graphics.Color;
 import android.graphics.Outline;
-import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.drawable.ShapeDrawable;
 import android.os.Bundle;
@@ -48,7 +47,6 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewOutlineProvider;
-import android.view.WindowManager;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
@@ -60,6 +58,7 @@
 import com.android.systemui.R;
 import com.android.systemui.recents.TriangleShape;
 import com.android.systemui.statusbar.AlphaOptimizedButton;
+import com.android.wm.shell.common.HandlerExecutor;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -83,24 +82,26 @@
     private boolean mImeVisible;
     private boolean mNeedsNewHeight;
 
-    private Point mDisplaySize;
     private int mMinHeight;
     private int mOverflowHeight;
     private int mSettingsIconHeight;
     private int mPointerWidth;
     private int mPointerHeight;
-    private ShapeDrawable mPointerDrawable;
+    private ShapeDrawable mCurrentPointer;
+    private ShapeDrawable mTopPointer;
+    private ShapeDrawable mLeftPointer;
+    private ShapeDrawable mRightPointer;
     private int mExpandedViewPadding;
     private float mCornerRadius = 0f;
 
     @Nullable private Bubble mBubble;
     private PendingIntent mPendingIntent;
-
+    // TODO(b/170891664): Don't use a flag, set the BubbleOverflow object instead
     private boolean mIsOverflow;
 
     private Bubbles mBubbles = Dependency.get(Bubbles.class);
-    private WindowManager mWindowManager;
     private BubbleStackView mStackView;
+    private BubblePositioner mPositioner;
 
     /**
      * Container for the ActivityView that has a solid, round-rect background that shows if the
@@ -136,6 +137,7 @@
                 }
                 try {
                     if (!mIsOverflow && mBubble.hasMetadataShortcutId()) {
+                        options.setApplyActivityFlagsForBubbles(true);
                         mTaskView.startShortcutActivity(mBubble.getShortcutInfo(),
                                 options, null /* sourceBounds */);
                     } else {
@@ -224,17 +226,6 @@
         updateDimensions();
     }
 
-    void updateDimensions() {
-        mDisplaySize = new Point();
-        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
-        // Get the real size -- this includes screen decorations (notches, statusbar, navbar).
-        mWindowManager.getDefaultDisplay().getRealSize(mDisplaySize);
-        Resources res = getResources();
-        mMinHeight = res.getDimensionPixelSize(R.dimen.bubble_expanded_default_height);
-        mOverflowHeight = res.getDimensionPixelSize(R.dimen.bubble_overflow_height);
-        mPointerMargin = res.getDimensionPixelSize(R.dimen.bubble_pointer_margin);
-    }
-
     @SuppressLint("ClickableViewAccessibility")
     @Override
     protected void onFinishInflate() {
@@ -245,15 +236,24 @@
         mPointerWidth = res.getDimensionPixelSize(R.dimen.bubble_pointer_width);
         mPointerHeight = res.getDimensionPixelSize(R.dimen.bubble_pointer_height);
 
-        mPointerDrawable = new ShapeDrawable(TriangleShape.create(
+        mTopPointer = new ShapeDrawable(TriangleShape.create(
                 mPointerWidth, mPointerHeight, true /* pointUp */));
+        mLeftPointer = new ShapeDrawable(TriangleShape.createHorizontal(
+                mPointerWidth, mPointerHeight, true /* pointLeft */));
+        mRightPointer = new ShapeDrawable(TriangleShape.createHorizontal(
+                mPointerWidth, mPointerHeight, false /* pointLeft */));
+
+        mCurrentPointer = mTopPointer;
         mPointerView.setVisibility(INVISIBLE);
 
         mSettingsIconHeight = getContext().getResources().getDimensionPixelSize(
                 R.dimen.bubble_manage_button_height);
         mSettingsIcon = findViewById(R.id.settings_button);
 
-        mTaskView = new TaskView(mContext, mBubbles.getTaskManager());
+        mPositioner = mBubbles.getPositioner();
+
+        mTaskView = new TaskView(mContext, mBubbles.getTaskOrganizer(),
+                new HandlerExecutor(getHandler()));
         // Set ActivityView's alpha value as zero, since there is no view content to be shown.
         setContentVisibility(false);
 
@@ -282,8 +282,7 @@
         applyThemeAttrs();
 
         mExpandedViewPadding = res.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding);
-        setPadding(mExpandedViewPadding, mExpandedViewPadding, mExpandedViewPadding,
-                mExpandedViewPadding);
+        setClipToPadding(false);
         setOnTouchListener((view, motionEvent) -> {
             if (mTaskView == null) {
                 return false;
@@ -311,6 +310,52 @@
         setLayoutDirection(LAYOUT_DIRECTION_LOCALE);
     }
 
+    void updateDimensions() {
+        Resources res = getResources();
+        mMinHeight = res.getDimensionPixelSize(R.dimen.bubble_expanded_default_height);
+        mOverflowHeight = res.getDimensionPixelSize(R.dimen.bubble_overflow_height);
+        mPointerMargin = res.getDimensionPixelSize(R.dimen.bubble_pointer_margin);
+    }
+
+    void applyThemeAttrs() {
+        final TypedArray ta = mContext.obtainStyledAttributes(new int[] {
+                android.R.attr.dialogCornerRadius,
+                android.R.attr.colorBackgroundFloating});
+        mCornerRadius = ta.getDimensionPixelSize(0, 0);
+        mExpandedViewContainer.setBackgroundColor(ta.getColor(1, Color.WHITE));
+        ta.recycle();
+
+        if (mTaskView != null && ScreenDecorationsUtils.supportsRoundedCornersOnWindows(
+                mContext.getResources())) {
+            mTaskView.setCornerRadius(mCornerRadius);
+        }
+        updatePointerView();
+    }
+
+    private void updatePointerView() {
+        final int mode =
+                getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
+        switch (mode) {
+            case Configuration.UI_MODE_NIGHT_NO:
+                mCurrentPointer.setTint(getResources().getColor(R.color.bubbles_light));
+                break;
+            case Configuration.UI_MODE_NIGHT_YES:
+                mCurrentPointer.setTint(getResources().getColor(R.color.bubbles_dark));
+                break;
+        }
+        LayoutParams lp = (LayoutParams) mPointerView.getLayoutParams();
+        if (mCurrentPointer == mLeftPointer || mCurrentPointer == mRightPointer) {
+            lp.width = mPointerHeight;
+            lp.height = mPointerWidth;
+        } else {
+            lp.width = mPointerWidth;
+            lp.height = mPointerHeight;
+        }
+        mPointerView.setLayoutParams(lp);
+        mPointerView.setBackground(mCurrentPointer);
+    }
+
+
     private String getBubbleKey() {
         return mBubble != null ? mBubble.getKey() : "null";
     }
@@ -371,32 +416,6 @@
         }
     }
 
-    void applyThemeAttrs() {
-        final TypedArray ta = mContext.obtainStyledAttributes(new int[] {
-                android.R.attr.dialogCornerRadius,
-                android.R.attr.colorBackgroundFloating});
-        mCornerRadius = ta.getDimensionPixelSize(0, 0);
-        mExpandedViewContainer.setBackgroundColor(ta.getColor(1, Color.WHITE));
-        ta.recycle();
-
-        if (mTaskView != null && ScreenDecorationsUtils.supportsRoundedCornersOnWindows(
-                mContext.getResources())) {
-            mTaskView.setCornerRadius(mCornerRadius);
-        }
-
-        final int mode =
-                getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
-        switch (mode) {
-            case Configuration.UI_MODE_NIGHT_NO:
-                mPointerDrawable.setTint(getResources().getColor(R.color.bubbles_light));
-                break;
-            case Configuration.UI_MODE_NIGHT_YES:
-                mPointerDrawable.setTint(getResources().getColor(R.color.bubbles_dark));
-                break;
-        }
-        mPointerView.setBackground(mPointerDrawable);
-    }
-
     @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
@@ -522,12 +541,12 @@
         }
 
         if (mBubble != null || mIsOverflow) {
-            float desiredHeight = mOverflowHeight;
-            if (!mIsOverflow) {
-                desiredHeight = Math.max(mBubble.getDesiredHeight(mContext), mMinHeight);
-            }
+            float desiredHeight = mIsOverflow
+                    ? mOverflowHeight
+                    : mBubble.getDesiredHeight(mContext);
+            desiredHeight = Math.max(desiredHeight, mMinHeight);
             float height = Math.min(desiredHeight, getMaxExpandedHeight());
-            height = Math.max(height, mIsOverflow ? mOverflowHeight : mMinHeight);
+            height = Math.max(height, mMinHeight);
             FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mTaskView.getLayoutParams();
             mNeedsNewHeight = lp.height != height;
             if (!mImeVisible) {
@@ -546,21 +565,17 @@
     }
 
     private int getMaxExpandedHeight() {
-        mWindowManager.getDefaultDisplay().getRealSize(mDisplaySize);
         int expandedContainerY = mExpandedViewContainerLocation != null
-                ? mExpandedViewContainerLocation[1]
+                // Remove top insets back here because availableRect.height would account for that
+                ? mExpandedViewContainerLocation[1] - mPositioner.getInsets().top
                 : 0;
-        int bottomInset = getRootWindowInsets() != null
-                ? getRootWindowInsets().getStableInsetBottom()
-                : 0;
-
-        return mDisplaySize.y
+        return mPositioner.getAvailableRect().height()
                 - expandedContainerY
                 - getPaddingTop()
                 - getPaddingBottom()
                 - mSettingsIconHeight
                 - mPointerHeight
-                - mPointerMargin - bottomInset;
+                - mPointerMargin;
     }
 
     /**
@@ -585,12 +600,25 @@
     }
 
     /**
-     * Set the x position that the tip of the triangle should point to.
+     * Set the position that the tip of the triangle should point to.
      */
-    public void setPointerPosition(float x) {
-        float halfPointerWidth = mPointerWidth / 2f;
-        float pointerLeft = x - halfPointerWidth - mExpandedViewPadding;
-        mPointerView.setTranslationX(pointerLeft);
+    public void setPointerPosition(float x, float y, boolean isLandscape, boolean onLeft) {
+        // Pointer gets drawn in the padding
+        int paddingLeft = (isLandscape && onLeft) ? mPointerHeight : 0;
+        int paddingRight = (isLandscape && !onLeft) ? mPointerHeight : 0;
+        int paddingTop = isLandscape ? 0 : mExpandedViewPadding;
+        setPadding(paddingLeft, paddingTop, paddingRight, 0);
+
+        if (isLandscape) {
+            // TODO: why setY vs setTranslationY ? linearlayout?
+            mPointerView.setY(y - (mPointerWidth / 2f));
+            mPointerView.setTranslationX(onLeft ? -mPointerHeight : x - mExpandedViewPadding);
+        } else {
+            mPointerView.setTranslationY(0f);
+            mPointerView.setTranslationX(x - mExpandedViewPadding - (mPointerWidth / 2f));
+        }
+        mCurrentPointer = isLandscape ? onLeft ? mLeftPointer : mRightPointer : mTopPointer;
+        updatePointerView();
         mPointerView.setVisibility(VISIBLE);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubblePositioner.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubblePositioner.java
new file mode 100644
index 0000000..029caee
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubblePositioner.java
@@ -0,0 +1,89 @@
+/*
+ * 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.systemui.bubbles;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Insets;
+import android.graphics.Rect;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
+
+import androidx.annotation.VisibleForTesting;
+
+/**
+ * Keeps track of display size, configuration, and specific bubble sizes. One place for all
+ * placement and positioning calculations to refer to.
+ */
+public class BubblePositioner {
+
+    private WindowManager mWindowManager;
+    private Rect mPositionRect;
+    private int mOrientation;
+    private Insets mInsets;
+
+    public BubblePositioner(Context context, WindowManager windowManager) {
+        mWindowManager = windowManager;
+        update(Configuration.ORIENTATION_UNDEFINED);
+    }
+
+    public void update(int orientation) {
+        WindowMetrics windowMetrics = mWindowManager.getCurrentWindowMetrics();
+        mPositionRect = new Rect(windowMetrics.getBounds());
+        WindowInsets metricInsets = windowMetrics.getWindowInsets();
+
+        Insets insets = metricInsets.getInsetsIgnoringVisibility(WindowInsets.Type.navigationBars()
+                | WindowInsets.Type.statusBars()
+                | WindowInsets.Type.displayCutout());
+        update(orientation, insets, windowMetrics.getBounds());
+    }
+
+    @VisibleForTesting
+    public void update(int orientation, Insets insets, Rect bounds) {
+        mOrientation = orientation;
+        mInsets = insets;
+
+        mPositionRect = new Rect(bounds);
+        mPositionRect.left += mInsets.left;
+        mPositionRect.top += mInsets.top;
+        mPositionRect.right -= mInsets.right;
+        mPositionRect.bottom -= mInsets.bottom;
+    }
+
+    /**
+     * @return a rect of available screen space for displaying bubbles in the correct orientation,
+     * accounting for system bars and cutouts.
+     */
+    public Rect getAvailableRect() {
+        return mPositionRect;
+    }
+
+    /**
+     * @return the current orientation.
+     */
+    public int getOrientation() {
+        return mOrientation;
+    }
+
+    /**
+     * @return the relevant insets (status bar, nav bar, cutouts).
+     */
+    public Insets getInsets() {
+        return mInsets;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 431719f..0714c5e 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -35,9 +35,9 @@
 import android.content.res.TypedArray;
 import android.graphics.ColorMatrix;
 import android.graphics.ColorMatrixColorFilter;
+import android.graphics.Insets;
 import android.graphics.Outline;
 import android.graphics.Paint;
-import android.graphics.Point;
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.graphics.RectF;
@@ -47,7 +47,6 @@
 import android.provider.Settings;
 import android.util.Log;
 import android.view.Choreographer;
-import android.view.DisplayCutout;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.SurfaceControl;
@@ -57,7 +56,6 @@
 import android.view.ViewOutlineProvider;
 import android.view.ViewTreeObserver;
 import android.view.WindowInsets;
-import android.view.WindowManager;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 import android.view.animation.AccelerateDecelerateInterpolator;
@@ -188,8 +186,6 @@
         }
     };
 
-    private Point mDisplaySize;
-
     private final BubbleData mBubbleData;
 
     private final ValueAnimator mDesaturateAndDarkenAnimator;
@@ -245,8 +241,8 @@
     private int mBubblePaddingTop;
     private int mBubbleTouchPadding;
     private int mExpandedViewPadding;
+    private int mPointerHeight;
     private int mCornerRadius;
-    private int mStatusBarHeight;
     private int mImeOffset;
     @Nullable private BubbleViewProvider mExpandedBubble;
     private boolean mIsExpanded;
@@ -721,13 +717,11 @@
         }
     };
 
-    private DismissView mDismissView;
-    private int mOrientation = Configuration.ORIENTATION_UNDEFINED;
-
     @Nullable
     private BubbleOverflow mBubbleOverflow;
     private StackEducationView mStackEduView;
     private ManageEducationView mManageEduView;
+    private DismissView mDismissView;
 
     private ViewGroup mManageMenu;
     private ImageView mManageSettingsIcon;
@@ -735,6 +729,8 @@
     private boolean mShowingManage = false;
     private PhysicsAnimator.SpringConfig mManageSpringConfig = new PhysicsAnimator.SpringConfig(
             SpringForce.STIFFNESS_MEDIUM, SpringForce.DAMPING_RATIO_LOW_BOUNCY);
+    private BubblePositioner mPositioner;
+
     @SuppressLint("ClickableViewAccessibility")
     public BubbleStackView(Context context, BubbleData data,
             @Nullable SurfaceSynchronizer synchronizer,
@@ -742,7 +738,8 @@
             Runnable allBubblesAnimatedOutAction,
             Consumer<Boolean> onImeVisibilityChanged,
             Runnable hideCurrentInputMethodCallback,
-            Consumer<Boolean> onBubbleExpandChanged) {
+            Consumer<Boolean> onBubbleExpandChanged,
+            BubblePositioner positioner) {
         super(context);
 
         mBubbleData = data;
@@ -753,15 +750,11 @@
         mBubbleElevation = res.getDimensionPixelSize(R.dimen.bubble_elevation);
         mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
         mBubbleTouchPadding = res.getDimensionPixelSize(R.dimen.bubble_touch_padding);
+        mPointerHeight = res.getDimensionPixelSize(R.dimen.bubble_pointer_height);
 
-        mStatusBarHeight =
-                res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
         mImeOffset = res.getDimensionPixelSize(R.dimen.pip_ime_offset);
 
-        mDisplaySize = new Point();
-        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
-        // We use the real size & subtract screen decorations / window insets ourselves when needed
-        wm.getDefaultDisplay().getRealSize(mDisplaySize);
+        mPositioner = positioner;
 
         mExpandedViewPadding = res.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding);
         int elevation = res.getDimensionPixelSize(R.dimen.bubble_elevation);
@@ -778,11 +771,10 @@
         };
 
         mStackAnimationController = new StackAnimationController(
-                floatingContentCoordinator, this::getBubbleCount, onBubbleAnimatedOut);
+                floatingContentCoordinator, this::getBubbleCount, onBubbleAnimatedOut, mPositioner);
 
         mExpandedAnimationController = new ExpandedAnimationController(
-                mDisplaySize, mExpandedViewPadding, res.getConfiguration().orientation,
-                onBubbleAnimatedOut);
+                mPositioner, mExpandedViewPadding, onBubbleAnimatedOut);
         mSurfaceSynchronizer = synchronizer != null ? synchronizer : DEFAULT_SURFACE_SYNCHRONIZER;
 
         // Force LTR by default since most of the Bubbles UI is positioned manually by the user, or
@@ -817,10 +809,10 @@
         mAnimatingOutSurfaceContainer.addView(mAnimatingOutSurfaceView);
 
         mAnimatingOutSurfaceContainer.setPadding(
-                mExpandedViewPadding,
-                mExpandedViewPadding,
-                mExpandedViewPadding,
-                mExpandedViewPadding);
+                mExpandedViewContainer.getPaddingLeft(),
+                mExpandedViewContainer.getPaddingTop(),
+                mExpandedViewContainer.getPaddingRight(),
+                mExpandedViewContainer.getPaddingBottom());
 
         setUpManageMenu();
 
@@ -871,29 +863,16 @@
 
         mOrientationChangedListener =
                 (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
-                    mExpandedAnimationController.updateResources(mOrientation, mDisplaySize);
-                    mStackAnimationController.updateResources(mOrientation);
+                    onDisplaySizeChanged();
+                    mExpandedAnimationController.updateResources();
+                    mStackAnimationController.updateResources();
                     mBubbleOverflow.updateResources();
 
-                    // Need to update the padding around the view
-                    WindowInsets insets = getRootWindowInsets();
-                    int leftPadding = mExpandedViewPadding;
-                    int rightPadding = mExpandedViewPadding;
-                    if (insets != null) {
-                        // Can't have the expanded view overlaying notches
-                        int cutoutLeft = 0;
-                        int cutoutRight = 0;
-                        DisplayCutout cutout = insets.getDisplayCutout();
-                        if (cutout != null) {
-                            cutoutLeft = cutout.getSafeInsetLeft();
-                            cutoutRight = cutout.getSafeInsetRight();
-                        }
-                        // Or overlaying nav or status bar
-                        leftPadding += Math.max(cutoutLeft, insets.getStableInsetLeft());
-                        rightPadding += Math.max(cutoutRight, insets.getStableInsetRight());
+                    if (mRelativeStackPositionBeforeRotation != null) {
+                        mStackAnimationController.setStackPosition(
+                                mRelativeStackPositionBeforeRotation);
+                        mRelativeStackPositionBeforeRotation = null;
                     }
-                    mExpandedViewContainer.setPadding(leftPadding, mExpandedViewPadding,
-                            rightPadding, mExpandedViewPadding);
 
                     if (mIsExpanded) {
                         // Re-draw bubble row and pointer for new orientation.
@@ -903,15 +882,10 @@
                         mExpandedAnimationController.expandFromStack(() -> {
                             afterExpandedViewAnimation();
                         } /* after */);
-                        mExpandedViewContainer.setTranslationX(0);
+                        mExpandedViewContainer.setTranslationX(0f);
                         mExpandedViewContainer.setTranslationY(getExpandedViewY());
                         mExpandedViewContainer.setAlpha(1f);
                     }
-                    if (mRelativeStackPositionBeforeRotation != null) {
-                        mStackAnimationController.setStackPosition(
-                                mRelativeStackPositionBeforeRotation);
-                        mRelativeStackPositionBeforeRotation = null;
-                    }
                     removeOnLayoutChangeListener(mOrientationChangedListener);
                 };
 
@@ -1178,26 +1152,16 @@
     }
 
     /** Respond to the phone being rotated by repositioning the stack and hiding any flyouts. */
-    public void onOrientationChanged(int orientation) {
-        mOrientation = orientation;
-
-        // Display size is based on the rotation device was in when requested, we should update it
-        // We use the real size & subtract screen decorations / window insets ourselves when needed
-        WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
-        wm.getDefaultDisplay().getRealSize(mDisplaySize);
-
-        // Some resources change depending on orientation
+    public void onOrientationChanged() {
         Resources res = getContext().getResources();
-        mStatusBarHeight = res.getDimensionPixelSize(
-                com.android.internal.R.dimen.status_bar_height);
         mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
 
         mRelativeStackPositionBeforeRotation = mStackAnimationController.getRelativeStackPosition();
-        addOnLayoutChangeListener(mOrientationChangedListener);
-        hideFlyoutImmediate();
-
         mManageMenu.setVisibility(View.INVISIBLE);
         mShowingManage = false;
+
+        addOnLayoutChangeListener(mOrientationChangedListener);
+        hideFlyoutImmediate();
     }
 
     /** Tells the views with locale-dependent layout direction to resolve the new direction. */
@@ -1217,11 +1181,7 @@
     public void onDisplaySizeChanged() {
         updateOverflow();
 
-        WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
-        wm.getDefaultDisplay().getRealSize(mDisplaySize);
         Resources res = getContext().getResources();
-        mStatusBarHeight = res.getDimensionPixelSize(
-                com.android.internal.R.dimen.status_bar_height);
         mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
         mBubbleSize = getResources().getDimensionPixelSize(R.dimen.individual_bubble_size);
         for (Bubble b : mBubbleData.getBubbles()) {
@@ -1231,8 +1191,8 @@
             }
             b.getIconView().setLayoutParams(new LayoutParams(mBubbleSize, mBubbleSize));
         }
-        mExpandedAnimationController.updateResources(mOrientation, mDisplaySize);
-        mStackAnimationController.updateResources(mOrientation);
+        mExpandedAnimationController.updateResources();
+        mStackAnimationController.updateResources();
         mDismissView.updateResources();
         mMagneticTarget.setMagneticFieldRadiusPx(mBubbleSize * 2);
     }
@@ -1682,7 +1642,8 @@
 
     private void animateExpansion() {
         cancelDelayedExpandCollapseSwitchAnimations();
-
+        final boolean isLandscape =
+                mPositioner.getOrientation() == Configuration.ORIENTATION_LANDSCAPE;
         mIsExpanded = true;
         if (mStackEduView != null) {
             mStackEduView.hide(true /* fromExpansion */);
@@ -1698,20 +1659,21 @@
             }
         } /* after */);
 
-        mExpandedViewContainer.setTranslationX(0);
+        mExpandedViewContainer.setTranslationX(0f);
         mExpandedViewContainer.setTranslationY(getExpandedViewY());
         mExpandedViewContainer.setAlpha(1f);
 
         // X-value of the bubble we're expanding, once it's settled in its row.
-        final float bubbleWillBeAtX =
-                mExpandedAnimationController.getBubbleLeft(
+        final float bubbleWillBeAt =
+                mExpandedAnimationController.getBubbleXOrYForOrientation(
                         mBubbleData.getBubbles().indexOf(mExpandedBubble));
 
         // How far horizontally the bubble will be animating. We'll wait a bit longer for bubbles
         // that are animating farther, so that the expanded view doesn't move as much.
-        final float horizontalDistanceAnimated =
-                Math.abs(bubbleWillBeAtX
-                        - mStackAnimationController.getStackPosition().x);
+        final float relevantStackPosition = isLandscape
+                ? mStackAnimationController.getStackPosition().y
+                : mStackAnimationController.getStackPosition().x;
+        final float distanceAnimated = Math.abs(bubbleWillBeAt - relevantStackPosition);
 
         // Wait for the path animation target to reach its end, and add a small amount of extra time
         // if the bubble is moving a lot horizontally.
@@ -1721,13 +1683,26 @@
         if (getWidth() > 0) {
             startDelay = (long)
                     (ExpandedAnimationController.EXPAND_COLLAPSE_TARGET_ANIM_DURATION
-                            + (horizontalDistanceAnimated / getWidth()) * 30);
+                            + (distanceAnimated / getWidth()) * 30);
         }
 
         // Set the pivot point for the scale, so the expanded view animates out from the bubble.
-        mExpandedViewContainerMatrix.setScale(
-                0f, 0f,
-                bubbleWillBeAtX + mBubbleSize / 2f, getExpandedViewY());
+        if (isLandscape) {
+            float pivotX;
+            float pivotY = bubbleWillBeAt + mBubbleSize / 2f;
+            if (mStackOnLeftOrWillBe) {
+                pivotX = mPositioner.getAvailableRect().left + mBubbleSize + mExpandedViewPadding;
+            } else {
+                pivotX = mPositioner.getAvailableRect().right - mBubbleSize - mExpandedViewPadding;
+            }
+            mExpandedViewContainerMatrix.setScale(
+                    0f, 0f,
+                    pivotX, pivotY);
+        } else {
+            mExpandedViewContainerMatrix.setScale(
+                    0f, 0f,
+                    bubbleWillBeAt + mBubbleSize / 2f, getExpandedViewY());
+        }
         mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix);
 
         if (mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) {
@@ -1747,9 +1722,11 @@
                         if (mExpandedBubble == null || mExpandedBubble.getIconView() == null) {
                             return;
                         }
+                        float translation = isLandscape
+                                ? mExpandedBubble.getIconView().getTranslationY()
+                                : mExpandedBubble.getIconView().getTranslationX();
                         mExpandedViewContainerMatrix.postTranslate(
-                                mExpandedBubble.getIconView().getTranslationX()
-                                        - bubbleWillBeAtX,
+                                translation - bubbleWillBeAt,
                                 0);
                         mExpandedViewContainer.setAnimationMatrix(
                                 mExpandedViewContainerMatrix);
@@ -1797,16 +1774,29 @@
         // We want to visually collapse into this bubble during the animation.
         final View expandingFromBubble = mExpandedBubble.getIconView();
 
-        // X-value the bubble is animating from (back into the stack).
-        final float expandingFromBubbleAtX =
-                mExpandedAnimationController.getBubbleLeft(
+        // Value the bubble is animating from (back into the stack).
+        final float expandingFromBubbleAt =
+                mExpandedAnimationController.getBubbleXOrYForOrientation(
                         mBubbleData.getBubbles().indexOf(mExpandedBubble));
-
-        // Set the pivot point.
-        mExpandedViewContainerMatrix.setScale(
-                1f, 1f,
-                expandingFromBubbleAtX + mBubbleSize / 2f,
-                getExpandedViewY());
+        final boolean isLandscape =
+                mPositioner.getOrientation() == Configuration.ORIENTATION_LANDSCAPE;
+        if (isLandscape) {
+            float pivotX;
+            float pivotY = expandingFromBubbleAt + mBubbleSize / 2f;
+            if (mStackOnLeftOrWillBe) {
+                pivotX = mPositioner.getAvailableRect().left + mBubbleSize + mExpandedViewPadding;
+            } else {
+                pivotX = mPositioner.getAvailableRect().right - mBubbleSize - mExpandedViewPadding;
+            }
+            mExpandedViewContainerMatrix.setScale(
+                    1f, 1f,
+                    pivotX, pivotY);
+        } else {
+            mExpandedViewContainerMatrix.setScale(
+                    1f, 1f,
+                    expandingFromBubbleAt + mBubbleSize / 2f,
+                    getExpandedViewY());
+        }
 
         PhysicsAnimator.getInstance(mExpandedViewContainerMatrix).cancel();
         PhysicsAnimator.getInstance(mExpandedViewContainerMatrix)
@@ -1815,9 +1805,15 @@
                 .addUpdateListener((target, values) -> {
                     if (expandingFromBubble != null) {
                         // Follow the bubble as it translates!
-                        mExpandedViewContainerMatrix.postTranslate(
-                                expandingFromBubble.getTranslationX()
-                                        - expandingFromBubbleAtX, 0f);
+                        if (isLandscape) {
+                            mExpandedViewContainerMatrix.postTranslate(
+                                    0f, expandingFromBubble.getTranslationY()
+                                            - expandingFromBubbleAt);
+                        } else {
+                            mExpandedViewContainerMatrix.postTranslate(
+                                    expandingFromBubble.getTranslationX()
+                                            - expandingFromBubbleAt, 0f);
+                        }
                     }
 
                     mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix);
@@ -1861,26 +1857,55 @@
         // The surface contains a screenshot of the animating out bubble, so we just need to animate
         // it out (and then release the GraphicBuffer).
         PhysicsAnimator.getInstance(mAnimatingOutSurfaceContainer).cancel();
-        PhysicsAnimator.getInstance(mAnimatingOutSurfaceContainer)
+        PhysicsAnimator animator = PhysicsAnimator.getInstance(mAnimatingOutSurfaceContainer)
                 .spring(DynamicAnimation.SCALE_X, 0f, mScaleOutSpringConfig)
                 .spring(DynamicAnimation.SCALE_Y, 0f, mScaleOutSpringConfig)
-                .spring(DynamicAnimation.TRANSLATION_Y,
-                        mAnimatingOutSurfaceContainer.getTranslationY() - mBubbleSize * 2,
-                        mTranslateSpringConfig)
-                .withEndActions(this::releaseAnimatingOutBubbleBuffer)
-                .start();
+                .withEndActions(this::releaseAnimatingOutBubbleBuffer);
+
+        if (mPositioner.getOrientation() == Configuration.ORIENTATION_LANDSCAPE) {
+            float translationX = mStackAnimationController.isStackOnLeftSide()
+                    ? mAnimatingOutSurfaceContainer.getTranslationX() + mBubbleSize * 2
+                    : mAnimatingOutSurfaceContainer.getTranslationX();
+            animator.spring(DynamicAnimation.TRANSLATION_X,
+                    translationX,
+                    mTranslateSpringConfig)
+                    .start();
+        } else {
+            animator.spring(DynamicAnimation.TRANSLATION_Y,
+                    mAnimatingOutSurfaceContainer.getTranslationY() - mBubbleSize * 2,
+                    mTranslateSpringConfig)
+                    .start();
+        }
 
         boolean isOverflow = mExpandedBubble != null
                 && mExpandedBubble.getKey().equals(BubbleOverflow.KEY);
-        float expandingFromBubbleDestinationX =
-                mExpandedAnimationController.getBubbleLeft(isOverflow ? getBubbleCount()
+        float expandingFromBubbleDestination =
+                mExpandedAnimationController.getBubbleXOrYForOrientation(isOverflow
+                        ? getBubbleCount()
                         : mBubbleData.getBubbles().indexOf(mExpandedBubble));
 
         mExpandedViewContainer.setAlpha(1f);
         mExpandedViewContainer.setVisibility(View.VISIBLE);
 
-        mExpandedViewContainerMatrix.setScale(
-                0f, 0f, expandingFromBubbleDestinationX + mBubbleSize / 2f, getExpandedViewY());
+        if (mPositioner.getOrientation() == Configuration.ORIENTATION_LANDSCAPE) {
+            float pivotX;
+            float pivotY = expandingFromBubbleDestination + mBubbleSize / 2f;
+            if (mStackOnLeftOrWillBe) {
+                pivotX = mPositioner.getAvailableRect().left + mBubbleSize + mExpandedViewPadding;
+            } else {
+                pivotX = mPositioner.getAvailableRect().right - mBubbleSize - mExpandedViewPadding;
+
+            }
+            mExpandedViewContainerMatrix.setScale(
+                    0f, 0f,
+                    pivotX, pivotY);
+        } else {
+            mExpandedViewContainerMatrix.setScale(
+                    0f, 0f,
+                    expandingFromBubbleDestination + mBubbleSize / 2f,
+                    getExpandedViewY());
+        }
+
         mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix);
 
         mDelayedAnimationHandler.postDelayed(() -> {
@@ -2168,7 +2193,12 @@
      * Calculates the y position of the expanded view when it is expanded.
      */
     float getExpandedViewY() {
-        return getStatusBarHeight() + mBubbleSize + mBubblePaddingTop;
+        final int top = mPositioner.getAvailableRect().top;
+        if (mPositioner.getOrientation() == Configuration.ORIENTATION_LANDSCAPE) {
+            return top + mExpandedViewPadding;
+        } else {
+            return top + mBubbleSize + mBubblePaddingTop;
+        }
     }
 
     private boolean shouldShowFlyout(Bubble bubble) {
@@ -2216,9 +2246,10 @@
             }
 
             // Stop suppressing the dot now that the flyout has morphed into the dot.
-            bubble.getIconView().removeDotSuppressionFlag(
-                    BadgedImageView.SuppressionFlag.FLYOUT_VISIBLE);
-
+            if (bubble.getIconView() != null) {
+                bubble.getIconView().removeDotSuppressionFlag(
+                        BadgedImageView.SuppressionFlag.FLYOUT_VISIBLE);
+            }
             // Hide the stack after a delay, if needed.
             updateTemporarilyInvisibleAnimation(false /* hideImmediately */);
         };
@@ -2323,19 +2354,6 @@
         }
     }
 
-    private int getStatusBarHeight() {
-        if (getRootWindowInsets() != null) {
-            WindowInsets insets = getRootWindowInsets();
-            return Math.max(
-                    mStatusBarHeight,
-                    insets.getDisplayCutout() != null
-                            ? insets.getDisplayCutout().getSafeInsetTop()
-                            : 0);
-        }
-
-        return 0;
-    }
-
     private void requestUpdate() {
         if (mViewUpdatedRequested || mIsExpansionAnimating) {
             return;
@@ -2484,7 +2502,7 @@
         PhysicsAnimator.getInstance(mAnimatingOutSurfaceContainer).cancel();
         mAnimatingOutSurfaceContainer.setScaleX(1f);
         mAnimatingOutSurfaceContainer.setScaleY(1f);
-        mAnimatingOutSurfaceContainer.setTranslationX(0);
+        mAnimatingOutSurfaceContainer.setTranslationX(mExpandedViewContainer.getPaddingLeft());
         mAnimatingOutSurfaceContainer.setTranslationY(0);
 
         final int[] activityViewLocation =
@@ -2542,9 +2560,22 @@
             Log.d(TAG, "updateExpandedView: mIsExpanded=" + mIsExpanded);
         }
 
+        // Need to update the padding around the view for any insets
+        Insets insets = mPositioner.getInsets();
+        int leftPadding = insets.left + mExpandedViewPadding;
+        int rightPadding = insets.right + mExpandedViewPadding;
+        if (mPositioner.getOrientation() == Configuration.ORIENTATION_LANDSCAPE) {
+            if (!mStackAnimationController.isStackOnLeftSide()) {
+                rightPadding += mPointerHeight + mBubbleSize;
+            } else {
+                leftPadding += mPointerHeight + mBubbleSize;
+            }
+        }
+        mExpandedViewContainer.setPadding(leftPadding, 0, rightPadding, 0);
         mExpandedViewContainer.setVisibility(mIsExpanded ? VISIBLE : GONE);
         if (mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) {
             mExpandedViewContainer.setTranslationY(getExpandedViewY());
+            mExpandedViewContainer.setTranslationX(0f);
             mExpandedBubble.getExpandedView().updateView(
                     mExpandedViewContainer.getLocationOnScreen());
         }
@@ -2587,12 +2618,27 @@
         if (index == -1) {
             return;
         }
-        float bubbleLeftFromScreenLeft = mExpandedAnimationController.getBubbleLeft(index);
-        float halfBubble = mBubbleSize / 2f;
-        float bubbleCenter = bubbleLeftFromScreenLeft + halfBubble;
-        // Padding might be adjusted for insets, so get it directly from the view
-        bubbleCenter -= mExpandedViewContainer.getPaddingLeft();
-        mExpandedBubble.getExpandedView().setPointerPosition(bubbleCenter);
+        float bubblePosition = mExpandedAnimationController.getBubbleXOrYForOrientation(index);
+        if (mPositioner.getOrientation() == Configuration.ORIENTATION_LANDSCAPE) {
+            float x = mStackOnLeftOrWillBe
+                    ? mPositioner.getAvailableRect().left
+                    : mPositioner.getAvailableRect().right
+                            - mExpandedViewContainer.getPaddingRight()
+                            - mPointerHeight;
+            float bubbleCenter = bubblePosition - getExpandedViewY() + (mBubbleSize / 2f);
+            mExpandedBubble.getExpandedView().setPointerPosition(
+                    x,
+                    bubbleCenter,
+                    true,
+                    mStackOnLeftOrWillBe);
+        } else {
+            float bubbleCenter = bubblePosition + (mBubbleSize / 2f);
+            mExpandedBubble.getExpandedView().setPointerPosition(
+                    bubbleCenter,
+                    getExpandedViewY(),
+                    false,
+                    mStackOnLeftOrWillBe);
+        }
     }
 
     /**
@@ -2621,7 +2667,7 @@
      * @return the normalized x-axis position of the bubble stack rounded to 4 decimal places.
      */
     public float getNormalizedXPosition() {
-        return new BigDecimal(getStackPosition().x / mDisplaySize.x)
+        return new BigDecimal(getStackPosition().x / mPositioner.getAvailableRect().width())
                 .setScale(4, RoundingMode.CEILING.HALF_UP)
                 .floatValue();
     }
@@ -2630,7 +2676,7 @@
      * @return the normalized y-axis position of the bubble stack rounded to 4 decimal places.
      */
     public float getNormalizedYPosition() {
-        return new BigDecimal(getStackPosition().y / mDisplaySize.y)
+        return new BigDecimal(getStackPosition().y / mPositioner.getAvailableRect().height())
                 .setScale(4, RoundingMode.CEILING.HALF_UP)
                 .floatValue();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubbles.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubbles.java
index 39c750d..4882abc 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubbles.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubbles.java
@@ -23,6 +23,7 @@
 import com.android.systemui.statusbar.ScrimView;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.phone.ScrimController;
+import com.android.wm.shell.ShellTaskOrganizer;
 
 import java.util.List;
 
@@ -129,5 +130,8 @@
     void setOverflowListener(BubbleData.Listener listener);
 
     /** The task listener for events in bubble tasks. **/
-    MultiWindowTaskListener getTaskManager();
+    ShellTaskOrganizer getTaskOrganizer();
+
+    /** Contains information to help position things on the screen.  */
+    BubblePositioner getPositioner();
 }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/MultiWindowTaskListener.java b/packages/SystemUI/src/com/android/systemui/bubbles/MultiWindowTaskListener.java
deleted file mode 100644
index 351a268..0000000
--- a/packages/SystemUI/src/com/android/systemui/bubbles/MultiWindowTaskListener.java
+++ /dev/null
@@ -1,179 +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.
- */
-
-package com.android.systemui.bubbles;
-
-import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_MULTI_WINDOW;
-
-import android.app.ActivityManager.RunningTaskInfo;
-import android.app.ActivityTaskManager;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.ArrayMap;
-import android.util.Log;
-import android.view.SurfaceControl;
-import android.window.TaskOrganizer;
-import android.window.WindowContainerToken;
-
-import com.android.wm.shell.ShellTaskOrganizer;
-
-import java.util.ArrayList;
-
-/**
- * Manages tasks that are displayed in multi-window (e.g. bubbles). These are displayed in a
- * {@link TaskView}.
- *
- * This class listens on {@link TaskOrganizer} callbacks for events. Once visible, these tasks will
- * intercept back press events.
- *
- * @see android.app.WindowConfiguration#WINDOWING_MODE_MULTI_WINDOW
- * @see TaskView
- */
-// TODO: Place in com.android.wm.shell vs. com.android.wm.shell.bubbles on shell migration.
-public class MultiWindowTaskListener implements ShellTaskOrganizer.TaskListener {
-    private static final String TAG = MultiWindowTaskListener.class.getSimpleName();
-
-    private static final boolean DEBUG = false;
-
-    //TODO(b/170153209): Have shell listener allow per task registration and remove this.
-    public interface Listener {
-        void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash);
-        void onTaskVanished(RunningTaskInfo taskInfo);
-        void onTaskInfoChanged(RunningTaskInfo taskInfo);
-        void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo);
-    }
-
-    private static class TaskData {
-        final RunningTaskInfo taskInfo;
-        final Listener listener;
-
-        TaskData(RunningTaskInfo info, Listener l) {
-            taskInfo = info;
-            listener = l;
-        }
-    }
-
-    private final Handler mHandler;
-    private final ShellTaskOrganizer mTaskOrganizer;
-    private final ArrayMap<WindowContainerToken, TaskData> mTasks = new ArrayMap<>();
-
-    private ArrayMap<IBinder, Listener> mLaunchCookieToListener = new ArrayMap<>();
-
-    /**
-     * Create a listener for tasks in multi-window mode.
-     */
-    public MultiWindowTaskListener(Handler handler, ShellTaskOrganizer organizer) {
-        mHandler = handler;
-        mTaskOrganizer = organizer;
-        mTaskOrganizer.addListener(this, TASK_LISTENER_TYPE_MULTI_WINDOW);
-    }
-
-    /**
-     * @return the task organizer that is listened to.
-     */
-    public TaskOrganizer getTaskOrganizer() {
-        return mTaskOrganizer;
-    }
-
-    public void setPendingLaunchCookieListener(IBinder cookie, Listener listener) {
-        mLaunchCookieToListener.put(cookie, listener);
-    }
-
-    /**
-     * Removes a task listener previously registered when starting a new activity.
-     */
-    public void removeListener(Listener listener) {
-        if (DEBUG) {
-            Log.d(TAG, "removeListener: listener=" + listener);
-        }
-        for (int i = 0; i < mTasks.size(); i++) {
-            if (mTasks.valueAt(i).listener == listener) {
-                mTasks.removeAt(i);
-            }
-        }
-    }
-
-    @Override
-    public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
-        if (DEBUG) {
-            Log.d(TAG, "onTaskAppeared: taskInfo=" + taskInfo);
-        }
-
-        // We only care about task we launch which should all have a tracking launch cookie.
-        final ArrayList<IBinder> launchCookies = taskInfo.launchCookies;
-        if (launchCookies.isEmpty()) return;
-
-        // See if this task has one of our launch cookies.
-        Listener listener = null;
-        for (int i = launchCookies.size() - 1; i >= 0; --i) {
-            final IBinder cookie = launchCookies.get(i);
-            listener = mLaunchCookieToListener.get(cookie);
-            if (listener != null) {
-                mLaunchCookieToListener.remove(cookie);
-                break;
-            }
-        }
-
-        // This is either not a task we launched or we have handled it previously.
-        if (listener == null) return;
-
-        mTaskOrganizer.setInterceptBackPressedOnTaskRoot(taskInfo.token, true);
-
-        final TaskData data = new TaskData(taskInfo, listener);
-        mTasks.put(taskInfo.token, data);
-        mHandler.post(() -> data.listener.onTaskAppeared(taskInfo, leash));
-    }
-
-    @Override
-    public void onTaskVanished(RunningTaskInfo taskInfo) {
-        final TaskData data = mTasks.remove(taskInfo.token);
-        if (data == null) {
-            return;
-        }
-
-        if (DEBUG) {
-            Log.d(TAG, "onTaskVanished: taskInfo=" + taskInfo + " listener=" + data.listener);
-        }
-        mHandler.post(() -> data.listener.onTaskVanished(taskInfo));
-    }
-
-    @Override
-    public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
-        final TaskData data = mTasks.get(taskInfo.token);
-        if (data == null) {
-            return;
-        }
-
-        if (DEBUG) {
-            Log.d(TAG, "onTaskInfoChanged: taskInfo=" + taskInfo + " listener=" + data.listener);
-        }
-        mHandler.post(() -> data.listener.onTaskInfoChanged(taskInfo));
-    }
-
-    @Override
-    public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
-        final TaskData data = mTasks.get(taskInfo.token);
-        if (data == null) {
-            return;
-        }
-
-        if (DEBUG) {
-            Log.d(TAG, "onTaskInfoChanged: taskInfo=" + taskInfo + " listener=" + data.listener);
-        }
-        mHandler.post(() -> data.listener.onBackPressedOnTaskRoot(taskInfo));
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/TaskView.java b/packages/SystemUI/src/com/android/systemui/bubbles/TaskView.java
index b78e677..85616d1 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/TaskView.java
@@ -30,20 +30,26 @@
 import android.content.pm.ShortcutInfo;
 import android.graphics.Rect;
 import android.os.Binder;
+import android.os.Handler;
 import android.view.SurfaceControl;
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
 import android.window.WindowContainerToken;
 import android.window.WindowContainerTransaction;
 
+import com.android.wm.shell.ShellTaskOrganizer;
+
 import dalvik.system.CloseGuard;
 
+import java.io.PrintWriter;
+import java.util.concurrent.Executor;
+
 /**
  * View that can display a task.
  */
 // TODO: Place in com.android.wm.shell vs. com.android.wm.shell.bubbles on shell migration.
 public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
-        MultiWindowTaskListener.Listener {
+        ShellTaskOrganizer.TaskListener {
 
     public interface Listener {
         /** Called when the container is ready for launching activities. */
@@ -67,7 +73,7 @@
 
     private final CloseGuard mGuard = CloseGuard.get();
 
-    private final MultiWindowTaskListener mMultiWindowTaskListener;
+    private final ShellTaskOrganizer mTaskOrganizer;
 
     private ActivityManager.RunningTaskInfo mTaskInfo;
     private WindowContainerToken mTaskToken;
@@ -76,14 +82,16 @@
     private boolean mSurfaceCreated;
     private boolean mIsInitialized;
     private Listener mListener;
+    private final Executor mExecutor;
 
     private final Rect mTmpRect = new Rect();
     private final Rect mTmpRootRect = new Rect();
 
-    public TaskView(Context context, MultiWindowTaskListener taskListener) {
+    public TaskView(Context context, ShellTaskOrganizer organizer, Executor executor) {
         super(context, null, 0, 0, true /* disableBackgroundLayer */);
 
-        mMultiWindowTaskListener = taskListener;
+        mExecutor = executor;
+        mTaskOrganizer = organizer;
         setUseAlpha();
         getHolder().addCallback(this);
         mGuard.open("release");
@@ -142,7 +150,7 @@
 
     private void prepareActivityOptions(ActivityOptions options) {
         final Binder launchCookie = new Binder();
-        mMultiWindowTaskListener.setPendingLaunchCookieListener(launchCookie, this);
+        mTaskOrganizer.setPendingLaunchCookieListener(launchCookie, this);
         options.setLaunchCookie(launchCookie);
         options.setLaunchWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
         options.setTaskAlwaysOnTop(true);
@@ -165,7 +173,7 @@
         WindowContainerTransaction wct = new WindowContainerTransaction();
         wct.setBounds(mTaskToken, mTmpRect);
         // TODO(b/151449487): Enable synchronization
-        mMultiWindowTaskListener.getTaskOrganizer().applyTransaction(wct);
+        mTaskOrganizer.applyTransaction(wct);
     }
 
     /**
@@ -189,7 +197,7 @@
 
     private void performRelease() {
         getHolder().removeCallback(this);
-        mMultiWindowTaskListener.removeListener(this);
+        mTaskOrganizer.removeListener(this);
         resetTaskInfo();
         mGuard.close();
         if (mListener != null && mIsInitialized) {
@@ -207,7 +215,7 @@
     private void updateTaskVisibility() {
         WindowContainerTransaction wct = new WindowContainerTransaction();
         wct.setHidden(mTaskToken, !mSurfaceCreated /* hidden */);
-        mMultiWindowTaskListener.getTaskOrganizer().applyTransaction(wct);
+        mTaskOrganizer.applyTransaction(wct);
         // TODO(b/151449487): Only call callback once we enable synchronization
         if (mListener != null) {
             mListener.onTaskVisibilityChanged(mTaskInfo.taskId, mSurfaceCreated);
@@ -217,33 +225,37 @@
     @Override
     public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo,
             SurfaceControl leash) {
-        mTaskInfo = taskInfo;
-        mTaskToken = taskInfo.token;
-        mTaskLeash = leash;
+        mExecutor.execute(() -> {
+            mTaskInfo = taskInfo;
+            mTaskToken = taskInfo.token;
+            mTaskLeash = leash;
 
-        if (mSurfaceCreated) {
-            // Surface is ready, so just reparent the task to this surface control
-            mTransaction.reparent(mTaskLeash, getSurfaceControl())
-                    .show(mTaskLeash)
-                    .apply();
-        } else {
-            // The surface has already been destroyed before the task has appeared, so go ahead and
-            // hide the task entirely
-            updateTaskVisibility();
-        }
+            if (mSurfaceCreated) {
+                // Surface is ready, so just reparent the task to this surface control
+                mTransaction.reparent(mTaskLeash, getSurfaceControl())
+                        .show(mTaskLeash)
+                        .apply();
+            } else {
+                // The surface has already been destroyed before the task has appeared,
+                // so go ahead and hide the task entirely
+                updateTaskVisibility();
+            }
 
-        // TODO: Synchronize show with the resize
-        onLocationChanged();
-        setResizeBackgroundColor(taskInfo.taskDescription.getBackgroundColor());
+            // TODO: Synchronize show with the resize
+            onLocationChanged();
+            setResizeBackgroundColor(taskInfo.taskDescription.getBackgroundColor());
 
-        if (mListener != null) {
-            mListener.onTaskCreated(taskInfo.taskId, taskInfo.baseActivity);
-        }
+            if (mListener != null) {
+                mListener.onTaskCreated(taskInfo.taskId, taskInfo.baseActivity);
+            }
+        });
     }
 
     @Override
     public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
-        if (mTaskToken != null && mTaskToken.equals(taskInfo.token)) {
+        mExecutor.execute(() -> {
+            if (mTaskToken == null || !mTaskToken.equals(taskInfo.token)) return;
+
             if (mListener != null) {
                 mListener.onTaskRemovalStarted(taskInfo.taskId);
             }
@@ -251,22 +263,37 @@
             // Unparent the task when this surface is destroyed
             mTransaction.reparent(mTaskLeash, null).apply();
             resetTaskInfo();
-        }
+        });
     }
 
     @Override
     public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
-        mTaskInfo.taskDescription = taskInfo.taskDescription;
-        setResizeBackgroundColor(taskInfo.taskDescription.getBackgroundColor());
+        mExecutor.execute(() -> {
+            mTaskInfo.taskDescription = taskInfo.taskDescription;
+            setResizeBackgroundColor(taskInfo.taskDescription.getBackgroundColor());
+        });
     }
 
     @Override
     public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo taskInfo) {
-        if (mTaskToken != null && mTaskToken.equals(taskInfo.token)) {
+        mExecutor.execute(() -> {
+            if (mTaskToken == null || !mTaskToken.equals(taskInfo.token)) return;
             if (mListener != null) {
                 mListener.onBackPressedOnTaskRoot(taskInfo.taskId);
             }
-        }
+        });
+    }
+
+    @Override
+    public void dump(@androidx.annotation.NonNull PrintWriter pw, String prefix) {
+        final String innerPrefix = prefix + "  ";
+        final String childPrefix = innerPrefix + "  ";
+        pw.println(prefix + this);
+    }
+
+    @Override
+    public String toString() {
+        return "TaskView" + ":" + (mTaskInfo != null ? mTaskInfo.taskId : "null");
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
index 7fdc019..5a70401 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
@@ -19,11 +19,9 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Path;
-import android.graphics.Point;
 import android.graphics.PointF;
-import android.view.DisplayCutout;
+import android.graphics.Rect;
 import android.view.View;
-import android.view.WindowInsets;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -32,6 +30,7 @@
 
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
+import com.android.systemui.bubbles.BubblePositioner;
 import com.android.wm.shell.animation.PhysicsAnimator;
 import com.android.wm.shell.common.magnetictarget.MagnetizedObject;
 
@@ -83,16 +82,8 @@
     private float mBubblePaddingTop;
     /** Size of each bubble. */
     private float mBubbleSizePx;
-    /** Space between bubbles in row above expanded view. */
-    private float mSpaceBetweenBubbles;
-    /** Height of the status bar. */
-    private float mStatusBarHeight;
-    /** Size of display. */
-    private Point mDisplaySize;
     /** Max number of bubbles shown in row above expanded view. */
     private int mBubblesMaxRendered;
-    /** What the current screen orientation is. */
-    private int mScreenOrientation;
 
     private boolean mAnimatingExpand = false;
 
@@ -104,7 +95,8 @@
     private boolean mPreparingToCollapse = false;
 
     private boolean mAnimatingCollapse = false;
-    private @Nullable Runnable mAfterExpand;
+    @Nullable
+    private Runnable mAfterExpand;
     private Runnable mAfterCollapse;
     private PointF mCollapsePoint;
 
@@ -138,9 +130,12 @@
      */
     private Runnable mOnBubbleAnimatedOutAction;
 
-    public ExpandedAnimationController(Point displaySize, int expandedViewPadding,
-            int orientation, Runnable onBubbleAnimatedOutAction) {
-        updateResources(orientation, displaySize);
+    private BubblePositioner mPositioner;
+
+    public ExpandedAnimationController(BubblePositioner positioner, int expandedViewPadding,
+            Runnable onBubbleAnimatedOutAction) {
+        mPositioner = positioner;
+        updateResources();
         mExpandedViewPadding = expandedViewPadding;
         mOnBubbleAnimatedOutAction = onBubbleAnimatedOutAction;
     }
@@ -152,7 +147,8 @@
     private boolean mBubbleDraggedOutEnough = false;
 
     /** End action to run when the lead bubble's expansion animation completes. */
-    @Nullable private Runnable mLeadBubbleEndAction;
+    @Nullable
+    private Runnable mLeadBubbleEndAction;
 
     /**
      * Animates expanding the bubbles into a row along the top of the screen, optionally running an
@@ -200,28 +196,17 @@
 
     /**
      * Update effective screen width based on current orientation.
-     * @param orientation Landscape or portrait.
-     * @param displaySize Updated display size.
      */
-    public void updateResources(int orientation, Point displaySize) {
-        mScreenOrientation = orientation;
-        mDisplaySize = displaySize;
+    public void updateResources() {
         if (mLayout == null) {
             return;
         }
         Resources res = mLayout.getContext().getResources();
         mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
-        mStatusBarHeight = res.getDimensionPixelSize(
-                com.android.internal.R.dimen.status_bar_height);
         mStackOffsetPx = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
         mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
         mBubbleSizePx = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
         mBubblesMaxRendered = res.getInteger(R.integer.bubbles_max_rendered);
-
-        // Includes overflow button.
-        float totalGapWidth = getWidthForDisplayingBubbles() - (mExpandedViewPadding * 2)
-                - (mBubblesMaxRendered + 1) * mBubbleSizePx;
-        mSpaceBetweenBubbles = totalGapWidth / mBubblesMaxRendered;
     }
 
     /**
@@ -270,9 +255,18 @@
                 // If we're expanding, first draw a line from the bubble's current position to the
                 // top of the screen.
                 path.lineTo(bubble.getTranslationX(), expandedY);
-
                 // Then, draw a line across the screen to the bubble's resting position.
-                path.lineTo(getBubbleLeft(index), expandedY);
+                if (mPositioner.getOrientation() == Configuration.ORIENTATION_LANDSCAPE) {
+                    Rect availableRect = mPositioner.getAvailableRect();
+                    boolean onLeft = mCollapsePoint != null
+                            && mCollapsePoint.x < (availableRect.width() / 2f);
+                    float translationX = onLeft
+                            ? availableRect.left + mExpandedViewPadding
+                            : availableRect.right - mBubbleSizePx - mExpandedViewPadding;
+                    path.lineTo(translationX, getBubbleXOrYForOrientation(index));
+                } else {
+                    path.lineTo(getBubbleXOrYForOrientation(index), expandedY);
+                }
             } else {
                 final float stackedX = mCollapsePoint.x;
 
@@ -411,7 +405,8 @@
         updateBubblePositions();
     }
 
-    @Nullable public View getDraggedOutBubble() {
+    @Nullable
+    public View getDraggedOutBubble() {
         return mMagnetizedBubbleDraggingOut == null
                 ? null
                 : mMagnetizedBubbleDraggingOut.getUnderlyingObject();
@@ -430,7 +425,7 @@
         final int index = mLayout.indexOfChild(bubbleView);
 
         animationForChildAtIndex(index)
-                .position(getBubbleLeft(index), getExpandedY())
+                .position(getBubbleXOrYForOrientation(index), getExpandedY())
                 .withPositionStartVelocities(velX, velY)
                 .start(() -> bubbleView.setTranslationZ(0f) /* after */);
 
@@ -457,15 +452,7 @@
 
     /** The Y value of the row of expanded bubbles. */
     public float getExpandedY() {
-        if (mLayout == null || mLayout.getRootWindowInsets() == null) {
-            return 0;
-        }
-        final WindowInsets insets = mLayout.getRootWindowInsets();
-        return mBubblePaddingTop + Math.max(
-                mStatusBarHeight,
-                insets.getDisplayCutout() != null
-                        ? insets.getDisplayCutout().getSafeInsetTop()
-                        : 0);
+        return mPositioner.getAvailableRect().top + mBubblePaddingTop;
     }
 
     /** Description of current animation controller state. */
@@ -479,7 +466,7 @@
 
     @Override
     void onActiveControllerForLayout(PhysicsAnimationLayout layout) {
-        updateResources(mScreenOrientation, mDisplaySize);
+        updateResources();
 
         // Ensure that all child views are at 1x scale, and visible, in case they were animating
         // in.
@@ -524,7 +511,7 @@
         } else if (mAnimatingCollapse) {
             startOrUpdatePathAnimation(false /* expanding */);
         } else {
-            child.setTranslationX(getBubbleLeft(index));
+            child.setTranslationX(getBubbleXOrYForOrientation(index));
 
             // If we're preparing to collapse, don't start animations since the collapse animation
             // will take over and animate the new bubble into the correct (stacked) position.
@@ -593,76 +580,56 @@
                 return;
             }
 
-            animationForChild(bubble)
-                    .translationX(getBubbleLeft(i))
-                    .start();
-        }
-    }
-
-    /**
-     * @param index Bubble index in row.
-     * @return Bubble left x from left edge of screen.
-     */
-    public float getBubbleLeft(int index) {
-        final float bubbleFromRowLeft = index * (mBubbleSizePx + mSpaceBetweenBubbles);
-        return getRowLeft() + bubbleFromRowLeft;
-    }
-
-    /**
-     * When expanded, the bubbles are centered in the screen. In portrait, all available space is
-     * used. In landscape we have too much space so the value is restricted. This method accounts
-     * for window decorations (nav bar, cutouts).
-     *
-     * @return the desired width to display the expanded bubbles in.
-     */
-    public float getWidthForDisplayingBubbles() {
-        final float availableWidth = getAvailableScreenWidth(true /* includeStableInsets */);
-        if (mScreenOrientation == Configuration.ORIENTATION_LANDSCAPE) {
-            // display size y in landscape will be the smaller dimension of the screen
-            return Math.max(mDisplaySize.y, availableWidth * CENTER_BUBBLES_LANDSCAPE_PERCENT);
-        } else {
-            return availableWidth;
-        }
-    }
-
-    /**
-     * Determines the available screen width without the cutout.
-     *
-     * @param subtractStableInsets Whether or not stable insets should also be removed from the
-     *                             returned width.
-     * @return the total screen width available accounting for cutouts and insets,
-     * iff {@param includeStableInsets} is true.
-     */
-    private float getAvailableScreenWidth(boolean subtractStableInsets) {
-        float availableSize = mDisplaySize.x;
-        WindowInsets insets = mLayout != null ? mLayout.getRootWindowInsets() : null;
-        if (insets != null) {
-            int cutoutLeft = 0;
-            int cutoutRight = 0;
-            DisplayCutout cutout = insets.getDisplayCutout();
-            if (cutout != null) {
-                cutoutLeft = cutout.getSafeInsetLeft();
-                cutoutRight = cutout.getSafeInsetRight();
+            if (mPositioner.getOrientation() == Configuration.ORIENTATION_LANDSCAPE) {
+                Rect availableRect = mPositioner.getAvailableRect();
+                boolean onLeft = mCollapsePoint != null
+                        && mCollapsePoint.x < (availableRect.width() / 2f);
+                animationForChild(bubble)
+                        .translationX(onLeft
+                                ? availableRect.left + mExpandedViewPadding
+                                : availableRect.right - mBubbleSizePx - mExpandedViewPadding)
+                        .translationY(getBubbleXOrYForOrientation(i))
+                        .start();
+            } else {
+                animationForChild(bubble)
+                        .translationX(getBubbleXOrYForOrientation(i))
+                        .translationY(getExpandedY())
+                        .start();
             }
-            final int stableLeft = subtractStableInsets ? insets.getStableInsetLeft() : 0;
-            final int stableRight = subtractStableInsets ? insets.getStableInsetRight() : 0;
-            availableSize -= Math.max(stableLeft, cutoutLeft);
-            availableSize -= Math.max(stableRight, cutoutRight);
         }
-        return availableSize;
     }
 
-    private float getRowLeft() {
+    /**
+     * When bubbles are expanded in portrait, they display at the top of the screen in a horizontal
+     * row. When in landscape, they show at the left or right side in a vertical row. This method
+     * accounts for screen orientation and will return an x or y value for the position of the
+     * bubble in the row.
+     *
+     * @param index Bubble index in row.
+     * @return the y position of the bubble if {@link Configuration#ORIENTATION_LANDSCAPE} and the
+     * x position if {@link Configuration#ORIENTATION_PORTRAIT}.
+     */
+    public float getBubbleXOrYForOrientation(int index) {
         if (mLayout == null) {
             return 0;
         }
-        float rowWidth = (mLayout.getChildCount() * mBubbleSizePx)
-                + ((mLayout.getChildCount() - 1) * mSpaceBetweenBubbles);
-
-        // This display size we're using includes the size of the insets, we want the true
-        // center of the display minus the notch here, which means we should include the
-        // stable insets (e.g. status bar, nav bar) in this calculation.
-        final float trueCenter = getAvailableScreenWidth(false /* subtractStableInsets */) / 2f;
-        return trueCenter - (rowWidth / 2f);
+        Rect availableRect = mPositioner.getAvailableRect();
+        final boolean isLandscape =
+                mPositioner.getOrientation() == Configuration.ORIENTATION_LANDSCAPE;
+        final float availableSpace = isLandscape
+                ? availableRect.height()
+                : availableRect.width();
+        final float spaceForMaxBubbles = (mExpandedViewPadding * 2)
+                + (mBubblesMaxRendered + 1) * mBubbleSizePx;
+        final float spaceBetweenBubbles =
+                (availableSpace - spaceForMaxBubbles) / mBubblesMaxRendered;
+        final float expandedStackSize = (mLayout.getChildCount() * mBubbleSizePx)
+                + ((mLayout.getChildCount() - 1) * spaceBetweenBubbles);
+        final float centerPosition = isLandscape
+                ? availableRect.centerY()
+                : availableRect.centerX();
+        final float rowStart = centerPosition - (expandedStackSize / 2f);
+        final float positionInBar = index * (mBubbleSizePx + spaceBetweenBubbles);
+        return rowStart + positionInBar;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
index 1205124..31e1ca8 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
@@ -24,7 +24,6 @@
 import android.provider.Settings;
 import android.util.Log;
 import android.view.View;
-import android.view.WindowInsets;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -35,6 +34,7 @@
 import androidx.dynamicanimation.animation.SpringForce;
 
 import com.android.systemui.R;
+import com.android.systemui.bubbles.BubblePositioner;
 import com.android.systemui.bubbles.BubbleStackView;
 import com.android.wm.shell.animation.PhysicsAnimator;
 import com.android.wm.shell.common.FloatingContentCoordinator;
@@ -59,12 +59,6 @@
 
     private static final String TAG = "Bubbs.StackCtrl";
 
-    /** Scale factor to use initially for new bubbles being animated in. */
-    private static final float ANIMATE_IN_STARTING_SCALE = 1.15f;
-
-    /** Translation factor (multiplied by stack offset) to use for bubbles being animated in/out. */
-    private static final int ANIMATE_TRANSLATION_FACTOR = 4;
-
     /** Values to use for animating bubbles in. */
     private static final float ANIMATE_IN_STIFFNESS = 1000f;
     private static final int ANIMATE_IN_START_DELAY = 25;
@@ -198,10 +192,8 @@
     private int mBubblePaddingTop;
     /** How far offscreen the stack rests. */
     private int mBubbleOffscreen;
-    /** How far down the screen the stack starts, when there is no pre-existing location. */
-    private int mStackStartingVerticalOffset;
-    /** Height of the status bar. */
-    private float mStatusBarHeight;
+    /** Contains display size, orientation, and inset information. */
+    private BubblePositioner mPositioner;
 
     /** FloatingContentCoordinator instance for resolving floating content conflicts. */
     private FloatingContentCoordinator mFloatingContentCoordinator;
@@ -266,10 +258,12 @@
     public StackAnimationController(
             FloatingContentCoordinator floatingContentCoordinator,
             IntSupplier bubbleCountSupplier,
-            Runnable onBubbleAnimatedOutAction) {
+            Runnable onBubbleAnimatedOutAction,
+            BubblePositioner positioner) {
         mFloatingContentCoordinator = floatingContentCoordinator;
         mBubbleCountSupplier = bubbleCountSupplier;
         mOnBubbleAnimatedOutAction = onBubbleAnimatedOutAction;
+        mPositioner = positioner;
     }
 
     /**
@@ -583,45 +577,12 @@
      * be animated or dragged beyond them.
      */
     public RectF getAllowableStackPositionRegion() {
-        final WindowInsets insets = mLayout.getRootWindowInsets();
-        final RectF allowableRegion = new RectF();
-        if (insets != null) {
-            allowableRegion.left =
-                    -mBubbleOffscreen
-                            + Math.max(
-                            insets.getSystemWindowInsetLeft(),
-                            insets.getDisplayCutout() != null
-                                    ? insets.getDisplayCutout().getSafeInsetLeft()
-                                    : 0);
-            allowableRegion.right =
-                    mLayout.getWidth()
-                            - mBubbleSize
-                            + mBubbleOffscreen
-                            - Math.max(
-                            insets.getSystemWindowInsetRight(),
-                            insets.getDisplayCutout() != null
-                                    ? insets.getDisplayCutout().getSafeInsetRight()
-                                    : 0);
-
-            allowableRegion.top =
-                    mBubblePaddingTop
-                            + Math.max(
-                            mStatusBarHeight,
-                            insets.getDisplayCutout() != null
-                                    ? insets.getDisplayCutout().getSafeInsetTop()
-                                    : 0);
-            allowableRegion.bottom =
-                    mLayout.getHeight()
-                            - mBubbleSize
-                            - mBubblePaddingTop
-                            - (mImeHeight != UNSET ? mImeHeight + mBubblePaddingTop : 0f)
-                            - Math.max(
-                            insets.getStableInsetBottom(),
-                            insets.getDisplayCutout() != null
-                                    ? insets.getDisplayCutout().getSafeInsetBottom()
-                                    : 0);
-        }
-
+        final RectF allowableRegion = new RectF(mPositioner.getAvailableRect());
+        allowableRegion.left -= mBubbleOffscreen;
+        allowableRegion.top += mBubblePaddingTop;
+        allowableRegion.right += mBubbleOffscreen - mBubbleSize;
+        allowableRegion.bottom -= mBubblePaddingTop + mBubbleSize
+                + (mImeHeight != UNSET ? mImeHeight + mBubblePaddingTop : 0f);
         return allowableRegion;
     }
 
@@ -824,22 +785,15 @@
         mBubbleBitmapSize = res.getDimensionPixelSize(R.dimen.bubble_bitmap_size);
         mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
         mBubbleOffscreen = res.getDimensionPixelSize(R.dimen.bubble_stack_offscreen);
-        mStackStartingVerticalOffset =
-                res.getDimensionPixelSize(R.dimen.bubble_stack_starting_offset_y);
-        mStatusBarHeight =
-                res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
     }
 
     /**
-     * Update effective screen width based on current orientation.
-     * @param orientation Landscape or portrait.
+     * Update resources.
      */
-    public void updateResources(int orientation) {
+    public void updateResources() {
         if (mLayout != null) {
             Resources res = mLayout.getContext().getResources();
             mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
-            mStatusBarHeight = res.getDimensionPixelSize(
-                    com.android.internal.R.dimen.status_bar_height);
         }
     }
 
@@ -976,19 +930,19 @@
             return;
         }
 
-        final float xOffset =
-                getOffsetForChainedPropertyAnimation(DynamicAnimation.TRANSLATION_X);
+        final float yOffset =
+                getOffsetForChainedPropertyAnimation(DynamicAnimation.TRANSLATION_Y);
 
         // Position the new bubble in the correct position, scaled down completely.
-        child.setTranslationX(mStackPosition.x + xOffset * index);
-        child.setTranslationY(mStackPosition.y);
+        child.setTranslationX(mStackPosition.x);
+        child.setTranslationY(mStackPosition.y + yOffset * index);
         child.setScaleX(0f);
         child.setScaleY(0f);
 
         // Push the subsequent views out of the way, if there are subsequent views.
         if (index + 1 < mLayout.getChildCount()) {
             animationForChildAtIndex(index + 1)
-                    .translationX(mStackPosition.x + xOffset * (index + 1))
+                    .translationY(mStackPosition.y + yOffset * (index + 1))
                     .withStiffness(SpringForce.STIFFNESS_LOW)
                     .start();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
index cb90b61..3aa4626 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
@@ -38,7 +38,6 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.UiEventLogger;
-import com.android.internal.logging.UiEventLoggerImpl;
 import com.android.internal.util.NotificationMessagingUtil;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.ViewMediatorCallback;
@@ -340,13 +339,6 @@
         return Choreographer.getInstance();
     }
 
-    /** Provides an instance of {@link com.android.internal.logging.UiEventLogger} */
-    @Provides
-    @SysUISingleton
-    static UiEventLogger provideUiEventLogger() {
-        return new UiEventLoggerImpl();
-    }
-
     /** */
     @Provides
     @SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/GlobalModule.java b/packages/SystemUI/src/com/android/systemui/dagger/GlobalModule.java
index c5dc8cc..554d9cb 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/GlobalModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/GlobalModule.java
@@ -16,9 +16,20 @@
 
 package com.android.systemui.dagger;
 
+import android.content.Context;
+import android.util.DisplayMetrics;
+
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.UiEventLoggerImpl;
 import com.android.systemui.util.concurrency.GlobalConcurrencyModule;
+import com.android.wm.shell.WindowManagerShellWrapper;
+import com.android.wm.shell.animation.FlingAnimationUtils;
+import com.android.wm.shell.common.FloatingContentCoordinator;
+
+import javax.inject.Singleton;
 
 import dagger.Module;
+import dagger.Provides;
 
 /**
  * Supplies globally scoped instances that should be available in all versions of SystemUI
@@ -39,4 +50,38 @@
         FrameworkServicesModule.class,
         GlobalConcurrencyModule.class})
 public class GlobalModule {
+
+    // TODO(b/161980186): Currently only used by Bubbles, can move back to WMShellBaseModule once
+    //                    Bubbles has migrated over
+    @Singleton
+    @Provides
+    static FloatingContentCoordinator provideFloatingContentCoordinator() {
+        return new FloatingContentCoordinator();
+    }
+
+    // TODO(b/161980186): Currently only used by Bubbles, can move back to WMShellBaseModule once
+    //                    Bubbles has migrated over
+    @Singleton
+    @Provides
+    static WindowManagerShellWrapper provideWindowManagerShellWrapper() {
+        return new WindowManagerShellWrapper();
+    }
+
+    // TODO(b/162923491): This should not be a singleton at all, the display metrics can change and
+    //                    callers should be creating a new builder on demand
+    @Singleton
+    @Provides
+    static FlingAnimationUtils.Builder provideFlingAnimationUtilsBuilder(
+            Context context) {
+        DisplayMetrics displayMetrics = new DisplayMetrics();
+        context.getDisplay().getMetrics(displayMetrics);
+        return new FlingAnimationUtils.Builder(displayMetrics);
+    }
+
+    /** Provides an instance of {@link com.android.internal.logging.UiEventLogger} */
+    @Provides
+    @Singleton
+    static UiEventLogger provideUiEventLogger() {
+        return new UiEventLoggerImpl();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java
index 00fdf55..d648c94 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java
@@ -52,7 +52,7 @@
     WMComponent.Builder getWMComponentBuilder();
 
     /**
-     * Builder for a SysuiComponent.
+     * Builder for a SysUIComponent.
      */
     SysUIComponent.Builder getSysUIComponent();
 
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
index 4bea067..b098579 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
@@ -22,8 +22,15 @@
 import com.android.systemui.SystemUIAppComponentFactory;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.keyguard.KeyguardSliceProvider;
+import com.android.systemui.shared.system.InputConsumerController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.util.InjectionInflationController;
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.onehanded.OneHanded;
+import com.android.wm.shell.pip.Pip;
+import com.android.wm.shell.splitscreen.SplitScreen;
+
+import java.util.Optional;
 
 import dagger.BindsInstance;
 import dagger.Subcomponent;
@@ -43,15 +50,35 @@
     /**
      * Builder for a SysUIComponent.
      */
+    @SysUISingleton
     @Subcomponent.Builder
     interface Builder {
         @BindsInstance
-        Builder setStubAPIClass(WMComponent.StubAPIClass stubAPIClass);
+        Builder setPip(Optional<Pip> p);
+
+        @BindsInstance
+        Builder setSplitScreen(Optional<SplitScreen> s);
+
+        @BindsInstance
+        Builder setOneHanded(Optional<OneHanded> o);
+
+        @BindsInstance
+        Builder setInputConsumerController(InputConsumerController i);
+
+        @BindsInstance
+        Builder setShellTaskOrganizer(ShellTaskOrganizer s);
 
         SysUIComponent build();
     }
 
     /**
+     * Initializes all the SysUI components.
+     */
+    default void init() {
+        // Do nothing
+    }
+
+    /**
      * Provides a BootCompleteCache.
      */
     @SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
index 7d5683f..7ca8e63 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
@@ -62,7 +62,6 @@
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
-import com.android.systemui.wmshell.WMShellModule;
 
 import javax.inject.Named;
 
@@ -76,8 +75,7 @@
  */
 @Module(includes = {
         MediaModule.class,
-        QSModule.class,
-        WMShellModule.class
+        QSModule.class
 })
 public abstract class SystemUIDefaultModule {
 
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 63d9a83..a982ec5 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -21,6 +21,7 @@
 import com.android.systemui.BootCompleteCacheImpl;
 import com.android.systemui.appops.dagger.AppOpsModule;
 import com.android.systemui.assist.AssistModule;
+import com.android.systemui.bubbles.Bubbles;
 import com.android.systemui.controls.dagger.ControlsModule;
 import com.android.systemui.demomode.dagger.DemoModeModule;
 import com.android.systemui.doze.dagger.DozeComponent;
@@ -125,6 +126,9 @@
     @BindsOptionalOf
     abstract StatusBar optionalStatusBar();
 
+    @BindsOptionalOf
+    abstract Bubbles optionalBubbles();
+
     @SysUISingleton
     @Binds
     abstract SystemClock bindSystemClock(SystemClockImpl systemClock);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
index ad90eff..e3bd1b2 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
@@ -16,7 +16,15 @@
 
 package com.android.systemui.dagger;
 
-import javax.inject.Inject;
+import com.android.systemui.shared.system.InputConsumerController;
+import com.android.systemui.wmshell.WMShellModule;
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.DisplayImeController;
+import com.android.wm.shell.onehanded.OneHanded;
+import com.android.wm.shell.pip.Pip;
+import com.android.wm.shell.splitscreen.SplitScreen;
+
+import java.util.Optional;
 
 import dagger.Subcomponent;
 
@@ -24,7 +32,7 @@
  * Dagger Subcomponent for WindowManager.
  */
 @WMSingleton
-@Subcomponent(modules = {})
+@Subcomponent(modules = {WMShellModule.class})
 public interface WMComponent {
 
     /**
@@ -35,18 +43,36 @@
         WMComponent build();
     }
 
-
     /**
-     *  Example class used for passing an API to SysUI from WMShell.
-     *
-     *  TODO: Remove this once real WM classes are ready to go.
-     **/
-    @WMSingleton
-    class StubAPIClass {
-        @Inject
-        StubAPIClass() {}
+     * Initializes all the WMShell components before starting any of the SystemUI components.
+     */
+    default void init() {
+        // This is to prevent circular init problem by separating registration step out of its
+        // constructor. And make sure the initialization of DisplayImeController won't depend on
+        // specific feature anymore.
+        getDisplayImeController().startMonitorDisplays();
+        getShellTaskOrganizer().registerOrganizer();
     }
 
-    /** Create a StubAPIClass. */
-    StubAPIClass createStubAPIClass();
+    // Required components to be initialized at start up
+    @WMSingleton
+    ShellTaskOrganizer getShellTaskOrganizer();
+
+    @WMSingleton
+    DisplayImeController getDisplayImeController();
+
+    @WMSingleton
+    InputConsumerController getInputConsumerController();
+
+    // TODO(b/162923491): We currently pass the instances through to SysUI, but that may change
+    //                    depending on the threading mechanism we go with
+
+    @WMSingleton
+    Optional<OneHanded> getOneHanded();
+
+    @WMSingleton
+    Optional<Pip> getPip();
+
+    @WMSingleton
+    Optional<SplitScreen> getSplitScreen();
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/RootView.java b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/RootView.java
similarity index 88%
rename from packages/SystemUI/src/com/android/keyguard/dagger/RootView.java
rename to packages/SystemUI/src/com/android/systemui/dagger/qualifiers/RootView.java
index 5ebff09..e6c46c0 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/RootView.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/RootView.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.keyguard.dagger;
+package com.android.systemui.dagger.qualifiers;
 
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index 5f726cd..37bcb16 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -316,7 +316,8 @@
             }
             mDatePattern = getContext().getString(R.string.system_ui_aod_date_pattern);
             mPendingIntent = PendingIntent.getActivity(getContext(), 0,
-                    new Intent(getContext(), KeyguardSliceProvider.class), 0);
+                    new Intent(getContext(), KeyguardSliceProvider.class),
+                    PendingIntent.FLAG_IMMUTABLE);
             try {
                 //TODO(b/168778439): Remove this whole try catch. This is for debugging in dogfood.
                 mMediaManager.addCallback(this);
diff --git a/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt
index 9e326aa..c824458 100644
--- a/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt
@@ -91,9 +91,9 @@
         }
     private var playbackState: PlaybackState? = null
     private var callback = object : MediaController.Callback() {
-        override fun onPlaybackStateChanged(state: PlaybackState) {
+        override fun onPlaybackStateChanged(state: PlaybackState?) {
             playbackState = state
-            if (PlaybackState.STATE_NONE.equals(playbackState)) {
+            if (playbackState == null || PlaybackState.STATE_NONE.equals(playbackState)) {
                 clearController()
             } else {
                 checkIfPollingNeeded()
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
index eeb93bb..bdaeb13 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
@@ -18,6 +18,7 @@
 
 import android.app.Activity;
 import android.app.INotificationManager;
+import android.app.people.ConversationChannel;
 import android.app.people.IPeopleManager;
 import android.content.Context;
 import android.content.pm.LauncherApps;
@@ -29,6 +30,7 @@
 import android.os.Bundle;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.service.notification.ConversationChannelWrapper;
 import android.util.Log;
 import android.view.ViewGroup;
@@ -52,7 +54,6 @@
     private INotificationManager mNotificationManager;
     private PackageManager mPackageManager;
     private LauncherApps mLauncherApps;
-    private List<ConversationChannelWrapper> mConversations;
     private Context mContext;
 
     @Override
@@ -77,15 +78,25 @@
      */
     private void setTileViewsWithPriorityConversations() {
         try {
+            boolean showAllConversations = Settings.Global.getInt(mContext.getContentResolver(),
+                    Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE) == 0;
             List<ConversationChannelWrapper> conversations =
                     mNotificationManager.getConversations(
-                            true /* priority only */).getList();
-            mConversations = conversations.stream().filter(
-                    c -> shouldKeepConversation(c)).collect(Collectors.toList());
-            for (ConversationChannelWrapper conversation : mConversations) {
+                            !showAllConversations /* priority only */).getList();
+            List<ShortcutInfo> shortcutInfos = conversations.stream().filter(
+                    c -> shouldKeepConversation(c)).map(c -> c.getShortcutInfo()).collect(
+                    Collectors.toList());
+            if (showAllConversations) {
+                List<ConversationChannel> recentConversations =
+                        mPeopleManager.getRecentConversations().getList();
+                List<ShortcutInfo> recentShortcuts = recentConversations.stream().map(
+                        c -> c.getShortcutInfo()).collect(Collectors.toList());
+                shortcutInfos.addAll(recentShortcuts);
+            }
+            for (ShortcutInfo conversation : shortcutInfos) {
                 PeopleSpaceTileView tileView = new PeopleSpaceTileView(mContext,
                         mPeopleSpaceLayout,
-                        conversation.getShortcutInfo().getId());
+                        conversation.getId());
                 setTileView(tileView, conversation);
             }
         } catch (Exception e) {
@@ -95,11 +106,10 @@
 
     /** Sets {@code tileView} with the data in {@code conversation}. */
     private void setTileView(PeopleSpaceTileView tileView,
-            ConversationChannelWrapper conversation) {
+            ShortcutInfo shortcutInfo) {
         try {
-            ShortcutInfo shortcutInfo = conversation.getShortcutInfo();
             int userId = UserHandle.getUserHandleForUid(
-                    conversation.getUid()).getIdentifier();
+                    shortcutInfo.getUserId()).getIdentifier();
 
             String pkg = shortcutInfo.getPackage();
             long lastInteraction = mPeopleManager.getLastInteraction(
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
index f56e6cd..dc5ba69 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
@@ -69,8 +69,10 @@
         private const val ALL_INDICATORS =
                 SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED
         private const val MIC_CAMERA = SystemUiDeviceConfigFlags.PROPERTY_MIC_CAMERA_ENABLED
+        private const val LOCATION = SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_ENABLED
         private const val DEFAULT_ALL_INDICATORS = false
         private const val DEFAULT_MIC_CAMERA = true
+        private const val DEFAULT_LOCATION = false
     }
 
     @VisibleForTesting
@@ -88,6 +90,11 @@
         return true
     }
 
+    private fun isLocationEnabled(): Boolean {
+        return deviceConfigProxy.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
+                LOCATION, DEFAULT_LOCATION)
+    }
+
     private var currentUserIds = emptyList<Int>()
     private var listening = false
     private val callbacks = mutableListOf<WeakReference<Callback>>()
@@ -107,13 +114,15 @@
         private set
     var micCameraAvailable = isMicCameraEnabled()
         private set
+    var locationAvailable = isLocationEnabled()
 
     private val devicePropertiesChangedListener =
             object : DeviceConfig.OnPropertiesChangedListener {
         override fun onPropertiesChanged(properties: DeviceConfig.Properties) {
             if (DeviceConfig.NAMESPACE_PRIVACY.equals(properties.getNamespace()) &&
                     (properties.keyset.contains(ALL_INDICATORS) ||
-                    properties.keyset.contains(MIC_CAMERA))) {
+                            properties.keyset.contains(MIC_CAMERA) ||
+                            properties.keyset.contains(LOCATION))) {
 
                 // Running on the ui executor so can iterate on callbacks
                 if (properties.keyset.contains(ALL_INDICATORS)) {
@@ -126,6 +135,10 @@
 //                    micCameraAvailable = properties.getBoolean(MIC_CAMERA, DEFAULT_MIC_CAMERA)
 //                    callbacks.forEach { it.get()?.onFlagMicCameraChanged(micCameraAvailable) }
 //                }
+                if (properties.keyset.contains(LOCATION)) {
+                    locationAvailable = properties.getBoolean(LOCATION, DEFAULT_LOCATION)
+                    callbacks.forEach { it.get()?.onFlagLocationChanged(locationAvailable) }
+                }
                 internalUiExecutor.updateListeningState()
             }
         }
@@ -139,7 +152,8 @@
             active: Boolean
         ) {
             // Check if we care about this code right now
-            if (!allIndicatorsAvailable && code in OPS_LOCATION) {
+            if (!allIndicatorsAvailable &&
+                    (code in OPS_LOCATION && !locationAvailable)) {
                 return
             }
             val userId = UserHandle.getUserId(uid)
@@ -195,7 +209,8 @@
      * main thread.
      */
     private fun setListeningState() {
-        val listen = !callbacks.isEmpty() and (allIndicatorsAvailable || micCameraAvailable)
+        val listen = !callbacks.isEmpty() and
+                (allIndicatorsAvailable || micCameraAvailable || locationAvailable)
         if (listening == listen) return
         listening = listen
         if (listening) {
@@ -258,7 +273,9 @@
             AppOpsManager.OP_RECORD_AUDIO -> PrivacyType.TYPE_MICROPHONE
             else -> return null
         }
-        if (type == PrivacyType.TYPE_LOCATION && !allIndicatorsAvailable) return null
+        if (type == PrivacyType.TYPE_LOCATION && (!allIndicatorsAvailable && !locationAvailable)) {
+            return null
+        }
         val app = PrivacyApplication(appOpItem.packageName, appOpItem.uid)
         return PrivacyItem(type, app)
     }
@@ -271,6 +288,9 @@
 
         @JvmDefault
         fun onFlagMicCameraChanged(flag: Boolean) {}
+
+        @JvmDefault
+        fun onFlagLocationChanged(flag: Boolean) {}
     }
 
     private class NotifyChangesToCallback(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt
index dc157a8..8107647 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt
@@ -33,7 +33,7 @@
         private const val NUM_LINES = 2
     }
 
-    protected val mRecords = ArrayList<QSPanel.TileRecord>()
+    protected val mRecords = ArrayList<QSPanelControllerBase.TileRecord>()
     private var _listening = false
     private var smallTileSize = 0
     private val twoLineHeight
@@ -50,17 +50,17 @@
         updateResources()
     }
 
-    override fun addTile(tile: QSPanel.TileRecord) {
+    override fun addTile(tile: QSPanelControllerBase.TileRecord) {
         mRecords.add(tile)
         tile.tile.setListening(this, _listening)
         addTileView(tile)
     }
 
-    protected fun addTileView(tile: QSPanel.TileRecord) {
+    protected fun addTileView(tile: QSPanelControllerBase.TileRecord) {
         addView(tile.tileView)
     }
 
-    override fun removeTile(tile: QSPanel.TileRecord) {
+    override fun removeTile(tile: QSPanelControllerBase.TileRecord) {
         mRecords.remove(tile)
         tile.tile.setListening(this, false)
         removeView(tile.tileView)
@@ -72,7 +72,7 @@
         super.removeAllViews()
     }
 
-    override fun getOffsetTop(tile: QSPanel.TileRecord?) = top
+    override fun getOffsetTop(tile: QSPanelControllerBase.TileRecord?) = top
 
     override fun updateResources(): Boolean {
         with(mContext.resources) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index 04f379e..3062a77 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -26,7 +26,7 @@
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.qs.QSPanel.QSTileLayout;
-import com.android.systemui.qs.QSPanel.TileRecord;
+import com.android.systemui.qs.QSPanelControllerBase.TileRecord;
 
 import java.util.ArrayList;
 import java.util.Set;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index 9dcc924..4d41950 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -28,12 +28,17 @@
 import com.android.systemui.qs.QSPanel.QSTileLayout;
 import com.android.systemui.qs.TouchAnimator.Builder;
 import com.android.systemui.qs.TouchAnimator.Listener;
+import com.android.systemui.qs.dagger.QSScope;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
 
 import java.util.ArrayList;
 import java.util.Collection;
 
+import javax.inject.Inject;
+
+/** */
+@QSScope
 public class QSAnimator implements Callback, PageListener, Listener, OnLayoutChangeListener,
         OnAttachStateChangeListener, Tunable {
 
@@ -53,6 +58,9 @@
     private final ArrayList<View> mQuickQsViews = new ArrayList<>();
     private final QuickQSPanel mQuickQsPanel;
     private final QSPanel mQsPanel;
+    private final QSPanelController mQsPanelController;
+    private final QuickQSPanelController mQuickQSPanelController;
+    private final QSSecurityFooter mSecurityFooter;
     private final QS mQs;
 
     private PagedTileLayout mPagedLayout;
@@ -78,10 +86,19 @@
     private QSTileHost mHost;
     private boolean mShowCollapsedOnKeyguard;
 
-    public QSAnimator(QS qs, QuickQSPanel quickPanel, QSPanel panel) {
+    @Inject
+    public QSAnimator(QS qs, QuickQSPanel quickPanel, QSPanel panel,
+            QSPanelController qsPanelController, QuickQSPanelController quickQSPanelController,
+            QSTileHost qsTileHost,
+            QSSecurityFooter securityFooter) {
         mQs = qs;
         mQuickQsPanel = quickPanel;
         mQsPanel = panel;
+        mQsPanelController = qsPanelController;
+        mQuickQSPanelController = quickQSPanelController;
+        mSecurityFooter = securityFooter;
+        mHost = qsTileHost;
+        mHost.addCallback(this);
         mQsPanel.addOnAttachStateChangeListener(this);
         qs.getView().addOnLayoutChangeListener(this);
         if (mQsPanel.isAttachedToWindow()) {
@@ -134,12 +151,6 @@
                 && !mShowCollapsedOnKeyguard ? View.INVISIBLE : View.VISIBLE);
     }
 
-    public void setHost(QSTileHost qsh) {
-        mHost = qsh;
-        qsh.addCallback(this);
-        updateAnimators();
-    }
-
     @Override
     public void onViewAttachedToWindow(View v) {
         Dependency.get(TunerService.class).addTunable(this, ALLOW_FANCY_ANIMATION,
@@ -148,9 +159,7 @@
 
     @Override
     public void onViewDetachedFromWindow(View v) {
-        if (mHost != null) {
-            mHost.removeCallback(this);
-        }
+        mHost.removeCallback(this);
         Dependency.get(TunerService.class).removeTunable(this);
     }
 
@@ -185,8 +194,7 @@
         TouchAnimator.Builder translationXBuilder = new Builder();
         TouchAnimator.Builder translationYBuilder = new Builder();
 
-        if (mQsPanel.getHost() == null) return;
-        Collection<QSTile> tiles = mQsPanel.getHost().getTiles();
+        Collection<QSTile> tiles = mHost.getTiles();
         int count = 0;
         int[] loc1 = new int[2];
         int[] loc2 = new int[2];
@@ -206,7 +214,7 @@
         firstPageBuilder.addFloat(tileLayout, "translationY", heightDiff, 0);
 
         for (QSTile tile : tiles) {
-            QSTileView tileView = mQsPanel.getTileView(tile);
+            QSTileView tileView = mQsPanelController.getTileView(tile);
             if (tileView == null) {
                 Log.e(TAG, "tileView is null " + tile.getTileSpec());
                 continue;
@@ -217,7 +225,7 @@
             // This case: less tiles to animate in small displays.
             if (count < mQuickQsPanel.getTileLayout().getNumVisibleTiles() && mAllowFancy) {
                 // Quick tiles.
-                QSTileView quickTileView = mQuickQsPanel.getTileView(tile);
+                QSTileView quickTileView = mQuickQSPanelController.getTileView(tile);
                 if (quickTileView == null) continue;
 
                 lastX = loc1[0];
@@ -302,16 +310,12 @@
 
             // Fade in the security footer and the divider as we reach the final position
             builder = new Builder().setStartDelay(EXPANDED_TILE_DELAY);
-            if (mQsPanel.getSecurityFooter() != null) {
-                builder.addFloat(mQsPanel.getSecurityFooter().getView(), "alpha", 0, 1);
-            }
+            builder.addFloat(mSecurityFooter.getView(), "alpha", 0, 1);
             if (mQsPanel.getDivider() != null) {
                 builder.addFloat(mQsPanel.getDivider(), "alpha", 0, 1);
             }
             mAllPagesDelayedAnimator = builder.build();
-            if (mQsPanel.getSecurityFooter() != null) {
-                mAllViews.add(mQsPanel.getSecurityFooter().getView());
-            }
+            mAllViews.add(mSecurityFooter.getView());
             if (mQsPanel.getDivider() != null) {
                 mAllViews.add(mQsPanel.getDivider());
             }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java
index 1e239b1..acead98 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java
@@ -16,19 +16,21 @@
 
 package com.android.systemui.qs;
 
-import com.android.systemui.R;
+import com.android.systemui.qs.dagger.QSScope;
 import com.android.systemui.util.ViewController;
 
 import javax.inject.Inject;
 
-class QSContainerImplController extends ViewController<QSContainerImpl> {
+/** */
+@QSScope
+public class QSContainerImplController extends ViewController<QSContainerImpl> {
     private final QuickStatusBarHeaderController mQuickStatusBarHeaderController;
 
-    private QSContainerImplController(QSContainerImpl view,
-            QuickStatusBarHeaderController.Builder quickStatusBarHeaderControllerBuilder) {
+    @Inject
+    QSContainerImplController(QSContainerImpl view,
+            QuickStatusBarHeaderController quickStatusBarHeaderController) {
         super(view);
-        mQuickStatusBarHeaderController = quickStatusBarHeaderControllerBuilder
-                .setQuickStatusBarHeader(mView.findViewById(R.id.header)).build();
+        mQuickStatusBarHeaderController = quickStatusBarHeaderController;
     }
 
     @Override
@@ -49,23 +51,7 @@
     protected void onViewDetached() {
     }
 
-    static class Builder {
-        private final QuickStatusBarHeaderController.Builder mQuickStatusBarHeaderControllerBuilder;
-        private QSContainerImpl mView;
-
-        @Inject
-        Builder(
-                QuickStatusBarHeaderController.Builder quickStatusBarHeaderControllerBuilder) {
-            mQuickStatusBarHeaderControllerBuilder = quickStatusBarHeaderControllerBuilder;
-        }
-
-        public Builder setQSContainerImpl(QSContainerImpl view) {
-            mView = view;
-            return this;
-        }
-
-        public QSContainerImplController build() {
-            return new QSContainerImplController(mView, mQuickStatusBarHeaderControllerBuilder);
-        }
+    public QSContainerImpl getView() {
+        return mView;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 3a78365..4ea600a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -35,11 +35,11 @@
 
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.R.id;
 import com.android.systemui.media.MediaHost;
 import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.qs.customize.QSCustomizer;
+import com.android.systemui.qs.dagger.QSFragmentComponent;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
@@ -70,7 +70,6 @@
     private HeightListener mPanelView;
     protected QuickStatusBarHeader mHeader;
     private QSCustomizer mQSCustomizer;
-    protected QSPanel mQSPanel;
     protected NonInterceptingScrollView mQSPanelScrollView;
     private QSDetail mQSDetail;
     private boolean mListening;
@@ -82,7 +81,7 @@
 
     private final RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler;
     private final InjectionInflationController mInjectionInflater;
-    private final QSContainerImplController.Builder mQSContainerImplControllerBuilder;
+    private final QSFragmentComponent.Factory mQsComponentFactory;
     private final QSTileHost mHost;
     private boolean mShowCollapsedOnKeyguard;
     private boolean mLastKeyguardAndExpanded;
@@ -96,15 +95,17 @@
     private int[] mTmpLocation = new int[2];
     private int mLastViewHeight;
     private float mLastHeaderTranslation;
+    private QSPanelController mQSPanelController;
+    private QuickQSPanelController mQuickQSPanelController;
 
     @Inject
     public QSFragment(RemoteInputQuickSettingsDisabler remoteInputQsDisabler,
             InjectionInflationController injectionInflater, QSTileHost qsTileHost,
             StatusBarStateController statusBarStateController, CommandQueue commandQueue,
-            QSContainerImplController.Builder qsContainerImplControllerBuilder) {
+            QSFragmentComponent.Factory qsComponentFactory) {
         mRemoteInputQuickSettingsDisabler = remoteInputQsDisabler;
         mInjectionInflater = injectionInflater;
-        mQSContainerImplControllerBuilder = qsContainerImplControllerBuilder;
+        mQsComponentFactory = qsComponentFactory;
         commandQueue.observe(getLifecycle(), this);
         mHost = qsTileHost;
         mStatusBarStateController = statusBarStateController;
@@ -120,8 +121,13 @@
 
     @Override
     public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
-        super.onViewCreated(view, savedInstanceState);
-        mQSPanel = view.findViewById(R.id.quick_settings_panel);
+        QSFragmentComponent qsFragmentComponent = mQsComponentFactory.create(this);
+        mQSPanelController = qsFragmentComponent.getQSPanelController();
+        mQuickQSPanelController = qsFragmentComponent.getQuickQSPanelController();
+
+        mQSPanelController.init();
+        mQuickQSPanelController.init();
+
         mQSPanelScrollView = view.findViewById(R.id.expanded_qs_scroll_view);
         mQSPanelScrollView.addOnLayoutChangeListener(
                 (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
@@ -135,18 +141,15 @@
         });
         mQSDetail = view.findViewById(R.id.qs_detail);
         mHeader = view.findViewById(R.id.header);
-        mQSPanel.setHeaderContainer(view.findViewById(R.id.header_text_container));
+        mQSPanelController.setHeaderContainer(view.findViewById(R.id.header_text_container));
         mFooter = view.findViewById(R.id.qs_footer);
-        mContainer = view.findViewById(id.quick_settings_container);
 
-        mQSContainerImplController = mQSContainerImplControllerBuilder
-                .setQSContainerImpl((QSContainerImpl) view)
-                .build();
+        mQSContainerImplController = qsFragmentComponent.getQSContainerImplController();
         mQSContainerImplController.init();
+        mContainer = mQSContainerImplController.getView();
 
-        mQSDetail.setQsPanel(mQSPanel, mHeader, (View) mFooter);
-        mQSAnimator = new QSAnimator(this, mHeader.findViewById(R.id.quick_qs_panel), mQSPanel);
-
+        mQSDetail.setQsPanel(mQSPanelController.getView(), mHeader, (View) mFooter);
+        mQSAnimator = qsFragmentComponent.getQSAnimator();
 
         mQSCustomizer = view.findViewById(R.id.qs_customize);
         mQSCustomizer.setQs(this);
@@ -156,7 +159,7 @@
             setEditLocation(view);
             mQSCustomizer.restoreInstanceState(savedInstanceState);
             if (mQsExpanded) {
-                mQSPanel.getTileLayout().restoreInstanceState(savedInstanceState);
+                mQSPanelController.getTileLayout().restoreInstanceState(savedInstanceState);
             }
         }
         setHost(mHost);
@@ -188,7 +191,7 @@
         outState.putBoolean(EXTRA_LISTENING, mListening);
         mQSCustomizer.saveInstanceState(outState);
         if (mQsExpanded) {
-            mQSPanel.getTileLayout().saveInstanceState(outState);
+            mQSPanelController.getTileLayout().saveInstanceState(outState);
         }
     }
 
@@ -249,14 +252,10 @@
     }
 
     public void setHost(QSTileHost qsh) {
-        mQSPanel.setHost(qsh, mQSCustomizer);
-        mHeader.setQSPanel(mQSPanel);
-        mFooter.setQSPanel(mQSPanel);
+        mQSPanelController.setCustomizer(mQSCustomizer);
+        mHeader.setQSPanel(mQSPanelController.getView());
+        mFooter.setQSPanel(mQSPanelController.getView());
         mQSDetail.setHost(qsh);
-
-        if (mQSAnimator != null) {
-            mQSAnimator.setHost(qsh);
-        }
     }
 
     @Override
@@ -278,7 +277,7 @@
     private void updateQsState() {
         final boolean expandVisually = mQsExpanded || mStackScrollerOverscrolling
                 || mHeaderAnimating;
-        mQSPanel.setExpanded(mQsExpanded);
+        mQSPanelController.setExpanded(mQsExpanded);
         mQSDetail.setExpanded(mQsExpanded);
         boolean keyguardShowing = isKeyguardShowing();
         mHeader.setVisibility((mQsExpanded || !keyguardShowing || mHeaderAnimating
@@ -294,7 +293,8 @@
                 : View.INVISIBLE);
         mFooter.setExpanded((keyguardShowing && !mHeaderAnimating && !mShowCollapsedOnKeyguard)
                 || (mQsExpanded && !mStackScrollerOverscrolling));
-        mQSPanel.setVisibility(!mQsDisabled && expandVisually ? View.VISIBLE : View.INVISIBLE);
+        mQSPanelController.setVisibility(
+                !mQsDisabled && expandVisually ? View.VISIBLE : View.INVISIBLE);
     }
 
     private boolean isKeyguardShowing() {
@@ -317,8 +317,12 @@
         }
     }
 
+    public QSPanelController getQSPanelController() {
+        return mQSPanelController;
+    }
+
     public QSPanel getQsPanel() {
-        return mQSPanel;
+        return mQSPanelController.getView();
     }
 
     public QSCustomizer getCustomizer() {
@@ -327,7 +331,7 @@
 
     @Override
     public boolean isShowingDetail() {
-        return mQSPanel.isShowingCustomize() || mQSDetail.isShowingDetail();
+        return mQSPanelController.isShowingCustomize() || mQSDetail.isShowingDetail();
     }
 
     @Override
@@ -339,7 +343,7 @@
     public void setExpanded(boolean expanded) {
         if (DEBUG) Log.d(TAG, "setExpanded " + expanded);
         mQsExpanded = expanded;
-        mQSPanel.setListening(mListening, mQsExpanded);
+        mQSPanelController.setListening(mListening, mQsExpanded);
         updateQsState();
     }
 
@@ -368,7 +372,7 @@
         mListening = listening;
         mQSContainerImplController.setListening(listening);
         mFooter.setListening(listening);
-        mQSPanel.setListening(mListening, mQsExpanded);
+        mQSPanelController.setListening(mListening, mQsExpanded);
     }
 
     @Override
@@ -406,11 +410,15 @@
         float panelTranslationY = translationScaleY * heightDiff;
 
         // Let the views animate their contents correctly by giving them the necessary context.
-        mHeader.setExpansion(onKeyguardAndExpanded, expansion,
-                panelTranslationY);
+        mHeader.setExpansion(onKeyguardAndExpanded, expansion, panelTranslationY);
+        if (expansion < 1 && expansion > 0.99) {
+            if (mQuickQSPanelController.switchTileLayout(false)) {
+                mHeader.updateResources();
+            }
+        }
         mFooter.setExpansion(onKeyguardAndExpanded ? 1 : expansion);
-        mQSPanel.getQsTileRevealController().setExpansion(expansion);
-        mQSPanel.getTileLayout().setExpansion(expansion);
+        mQSPanelController.getQsTileRevealController().setExpansion(expansion);
+        mQSPanelController.getTileLayout().setExpansion(expansion);
         mQSPanelScrollView.setTranslationY(translationScaleY * heightDiff);
         if (fullyCollapsed) {
             mQSPanelScrollView.setScrollY(0);
@@ -448,7 +456,8 @@
             float expandedMediaPosition = absoluteBottomPosition - mQSPanelScrollView.getScrollY()
                     + mQSPanelScrollView.getScrollRange();
             // The expanded media host should never move below the laid out position
-            pinToBottom(expandedMediaPosition, mQSPanel.getMediaHost(), true /* expanded */);
+            pinToBottom(
+                    expandedMediaPosition, mQSPanelController.getMediaHost(), true /* expanded */);
             // The expanded media host should never move above the laid out position
             pinToBottom(absoluteBottomPosition, mHeader.getHeaderQsPanel().getMediaHost(),
                     false /* expanded */);
@@ -538,7 +547,7 @@
 
     @Override
     public void closeDetail() {
-        mQSPanel.closeDetail();
+        mQSPanelController.closeDetail();
     }
 
     public void notifyCustomizeChanged() {
@@ -553,8 +562,8 @@
     }
 
     /**
-     * The height this view wants to be. This is different from {@link #getMeasuredHeight} such that
-     * during closing the detail panel, this already returns the smaller height.
+     * The height this view wants to be. This is different from {@link View#getMeasuredHeight} such
+     * that during closing the detail panel, this already returns the smaller height.
      */
     @Override
     public int getDesiredHeight() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index efe4609..1b17a2a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -22,11 +22,9 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
-import android.metrics.LogMaker;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
@@ -43,41 +41,30 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.widget.RemeasuringLinearLayout;
 import com.android.systemui.Dependency;
-import com.android.systemui.Dumpable;
 import com.android.systemui.R;
-import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dump.DumpManager;
 import com.android.systemui.media.MediaHierarchyManager;
 import com.android.systemui.media.MediaHost;
 import com.android.systemui.plugins.qs.DetailAdapter;
 import com.android.systemui.plugins.qs.QSTile;
-import com.android.systemui.plugins.qs.QSTileView;
-import com.android.systemui.qs.QSHost.Callback;
 import com.android.systemui.qs.customize.QSCustomizer;
-import com.android.systemui.qs.external.CustomTile;
 import com.android.systemui.qs.logging.QSLogger;
-import com.android.systemui.settings.BrightnessController;
 import com.android.systemui.settings.ToggleSliderView;
-import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.policy.BrightnessMirrorController;
 import com.android.systemui.statusbar.policy.BrightnessMirrorController.BrightnessMirrorListener;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
 import com.android.systemui.util.animation.DisappearParameters;
 
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.List;
 import java.util.function.Consumer;
-import java.util.stream.Collectors;
 
 import javax.inject.Inject;
 import javax.inject.Named;
 
 /** View that represents the quick settings tile panel (when expanded/pulled down). **/
-public class QSPanel extends LinearLayout implements Tunable, Callback, BrightnessMirrorListener,
-        Dumpable {
+public class QSPanel extends LinearLayout implements Tunable, BrightnessMirrorListener {
 
     public static final String QS_SHOW_BRIGHTNESS = "qs_show_brightness";
     public static final String QS_SHOW_HEADER = "qs_show_header";
@@ -85,20 +72,15 @@
     private static final String TAG = "QSPanel";
 
     protected final Context mContext;
-    protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
-    private final BroadcastDispatcher mBroadcastDispatcher;
     protected final MediaHost mMediaHost;
 
     /**
      * The index where the content starts that needs to be moved between parents
      */
     private final int mMovableContentStartIndex;
-    private String mCachedSpecs = "";
 
     @Nullable
     protected View mBrightnessView;
-    @Nullable
-    private BrightnessController mBrightnessController;
 
     private final H mHandler = new H();
     private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
@@ -112,14 +94,14 @@
     protected boolean mListening;
 
     private QSDetail.Callback mCallback;
-    private final DumpManager mDumpManager;
     private final QSLogger mQSLogger;
     protected final UiEventLogger mUiEventLogger;
     protected QSTileHost mHost;
-    private final UserTracker mUserTracker;
+    private final List<OnConfigurationChangedListener> mOnConfigurationChangedListeners =
+            new ArrayList<>();
 
     @Nullable
-    protected QSSecurityFooter mSecurityFooter;
+    protected View mSecurityFooter;
 
     @Nullable
     protected View mFooter;
@@ -156,12 +138,9 @@
     public QSPanel(
             @Named(VIEW_CONTEXT) Context context,
             AttributeSet attrs,
-            DumpManager dumpManager,
-            BroadcastDispatcher broadcastDispatcher,
             QSLogger qsLogger,
             @Named(QS_PANEL) MediaHost mediaHost,
-            UiEventLogger uiEventLogger,
-            UserTracker userTracker
+            UiEventLogger uiEventLogger
     ) {
         super(context, attrs);
         mUsingMediaPlayer = useQsMediaPlayer(context);
@@ -174,16 +153,14 @@
         });
         mContext = context;
         mQSLogger = qsLogger;
-        mDumpManager = dumpManager;
-        mBroadcastDispatcher = broadcastDispatcher;
         mUiEventLogger = uiEventLogger;
-        mUserTracker = userTracker;
 
         setOrientation(VERTICAL);
 
         addViewsAboveTiles();
         mMovableContentStartIndex = getChildCount();
         mRegularTileLayout = createRegularTileLayout();
+        mTileLayout = mRegularTileLayout;
 
         if (mUsingMediaPlayer) {
             mHorizontalLinearLayout = new RemeasuringLinearLayout(mContext);
@@ -209,35 +186,27 @@
 
             initMediaHostState();
         }
-        addSecurityFooter();
         if (mRegularTileLayout instanceof PagedTileLayout) {
             mQsTileRevealController = new QSTileRevealController(mContext, this,
                     (PagedTileLayout) mRegularTileLayout);
         }
-        mQSLogger.logAllTilesChangeListening(mListening, getDumpableTag(), mCachedSpecs);
-        updateResources();
+        mQSLogger.logAllTilesChangeListening(mListening, getDumpableTag(), "");
     }
 
     protected void onMediaVisibilityChanged(Boolean visible) {
-        switchTileLayout();
         if (mMediaVisibilityChangedListener != null) {
             mMediaVisibilityChangedListener.accept(visible);
         }
     }
 
-    protected void addSecurityFooter() {
-        mSecurityFooter = new QSSecurityFooter(this, mContext, mUserTracker);
-    }
-
     protected void addViewsAboveTiles() {
         mBrightnessView = LayoutInflater.from(mContext).inflate(
             R.layout.quick_settings_brightness_dialog, this, false);
         addView(mBrightnessView);
-        mBrightnessController = new BrightnessController(getContext(),
-                findViewById(R.id.brightness_slider), mBroadcastDispatcher);
     }
 
-    protected QSTileLayout createRegularTileLayout() {
+    /** */
+    public QSTileLayout createRegularTileLayout() {
         if (mRegularTileLayout == null) {
             mRegularTileLayout = (QSTileLayout) LayoutInflater.from(mContext).inflate(
                     R.layout.qs_paged_tile_layout, this, false);
@@ -337,37 +306,10 @@
     }
 
     @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        final TunerService tunerService = Dependency.get(TunerService.class);
-        tunerService.addTunable(this, QS_SHOW_BRIGHTNESS);
-
-        if (mHost != null) {
-            setTiles(mHost.getTiles());
-        }
-        if (mBrightnessMirrorController != null) {
-            mBrightnessMirrorController.addCallback(this);
-        }
-        mDumpManager.registerDumpable(getDumpableTag(), this);
-    }
-
-    @Override
     protected void onDetachedFromWindow() {
-        Dependency.get(TunerService.class).removeTunable(this);
-        if (mHost != null) {
-            mHost.removeCallback(this);
-        }
         if (mTileLayout != null) {
             mTileLayout.setListening(false);
         }
-        for (TileRecord record : mRecords) {
-            record.tile.removeCallbacks();
-        }
-        mRecords.clear();
-        if (mBrightnessMirrorController != null) {
-            mBrightnessMirrorController.removeCallback(this);
-        }
-        mDumpManager.unregisterDumpable(getDumpableTag());
         super.onDetachedFromWindow();
     }
 
@@ -376,11 +318,6 @@
     }
 
     @Override
-    public void onTilesChanged() {
-        setTiles(mHost.getTiles());
-    }
-
-    @Override
     public void onTuningChanged(String key, String newValue) {
         if (QS_SHOW_BRIGHTNESS.equals(key) && mBrightnessView != null) {
             updateViewVisibilityForTuningValue(mBrightnessView, newValue);
@@ -391,8 +328,8 @@
         view.setVisibility(TunerService.parseIntegerSwitch(newValue, true) ? VISIBLE : GONE);
     }
 
-    public void openDetails(String subPanel) {
-        QSTile tile = getTile(subPanel);
+    /** */
+    public void openDetails(QSTile tile) {
         // If there's no tile with that name (as defined in QSFactoryImpl or other QSFactory),
         // QSFactory will not be able to create a tile and getTile will return null
         if (tile != null) {
@@ -400,15 +337,6 @@
         }
     }
 
-    private QSTile getTile(String subPanel) {
-        for (int i = 0; i < mRecords.size(); i++) {
-            if (subPanel.equals(mRecords.get(i).tile.getTileSpec())) {
-                return mRecords.get(i).tile;
-            }
-        }
-        return mHost.createTile(subPanel);
-    }
-
     public void setBrightnessMirror(BrightnessMirrorController c) {
         if (mBrightnessMirrorController != null) {
             mBrightnessMirrorController.removeCallback(this);
@@ -434,17 +362,8 @@
         mCallback = callback;
     }
 
-    public void setHost(QSTileHost host, QSCustomizer customizer) {
-        mHost = host;
-        mHost.addCallback(this);
-        setTiles(mHost.getTiles());
-        if (mSecurityFooter != null) {
-            mSecurityFooter.setHostEnvironment(host);
-        }
+    void setCustomizer(QSCustomizer customizer) {
         mCustomizePanel = customizer;
-        if (mCustomizePanel != null) {
-            mCustomizePanel.setHost(mHost);
-        }
     }
 
     /**
@@ -483,9 +402,6 @@
 
         updatePageIndicator();
 
-        if (mListening) {
-            refreshAllTiles();
-        }
         if (mTileLayout != null) {
             mTileLayout.updateResources();
         }
@@ -506,20 +422,21 @@
                 res.getDimensionPixelSize(R.dimen.qs_panel_padding_bottom));
     }
 
+    void addOnConfigurationChangedListener(OnConfigurationChangedListener listener) {
+        mOnConfigurationChangedListeners.add(listener);
+    }
+
+    void removeOnConfigurationChangedListener(OnConfigurationChangedListener listener) {
+        mOnConfigurationChangedListeners.remove(listener);
+    }
+
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
-        if (mSecurityFooter != null) {
-            mSecurityFooter.onConfigurationChanged();
-        }
-        updateResources();
+        mOnConfigurationChangedListeners.forEach(
+                listener -> listener.onConfigurationChange(newConfig));
 
         updateBrightnessMirror();
-
-        if (newConfig.orientation != mLastOrientation) {
-            mLastOrientation = newConfig.orientation;
-            switchTileLayout();
-        }
     }
 
     @Override
@@ -527,14 +444,9 @@
         super.onFinishInflate();
         mFooter = findViewById(R.id.qs_footer);
         mDivider = findViewById(R.id.divider);
-        switchTileLayout(true /* force */);
     }
 
-    boolean switchTileLayout() {
-        return switchTileLayout(false /* force */);
-    }
-
-    private boolean switchTileLayout(boolean force) {
+    boolean switchTileLayout(boolean force, List<QSPanelControllerBase.TileRecord> records) {
         /** Whether or not the QuickQSPanel currently contains a media player. */
         boolean horizontal = shouldUseHorizontalLayout();
         if (mDivider != null) {
@@ -562,13 +474,12 @@
             reAttachMediaHost();
             if (mTileLayout != null) {
                 mTileLayout.setListening(false);
-                for (TileRecord record : mRecords) {
+                for (QSPanelControllerBase.TileRecord record : records) {
                     mTileLayout.removeTile(record);
                     record.tile.removeCallback(record.callback);
                 }
             }
             mTileLayout = newLayout;
-            if (mHost != null) setTiles(mHost.getTiles());
             newLayout.setListening(mListening);
             if (needsDynamicRowsAndColumns()) {
                 newLayout.setMinRows(horizontal ? 2 : 1);
@@ -617,20 +528,20 @@
         index++;
 
         if (mSecurityFooter != null) {
-            View view = mSecurityFooter.getView();
-            LinearLayout.LayoutParams layoutParams = (LayoutParams) view.getLayoutParams();
+            LinearLayout.LayoutParams layoutParams =
+                    (LayoutParams) mSecurityFooter.getLayoutParams();
             if (mUsingHorizontalLayout && mHeaderContainer != null) {
                 // Adding the security view to the header, that enables us to avoid scrolling
                 layoutParams.width = 0;
                 layoutParams.weight = 1.6f;
-                switchToParent(view, mHeaderContainer, 1 /* always in second place */);
+                switchToParent(mSecurityFooter, mHeaderContainer, 1 /* always in second place */);
             } else {
                 layoutParams.width = LayoutParams.WRAP_CONTENT;
                 layoutParams.weight = 0;
-                switchToParent(view, parent, index);
+                switchToParent(mSecurityFooter, parent, index);
                 index++;
             }
-            view.setLayoutParams(layoutParams);
+            mSecurityFooter.setLayoutParams(layoutParams);
         }
 
         if (mFooter != null) {
@@ -703,14 +614,6 @@
         if (!mExpanded && mTileLayout instanceof PagedTileLayout) {
             ((PagedTileLayout) mTileLayout).setCurrentItem(0, false);
         }
-        mMetricsLogger.visibility(MetricsEvent.QS_PANEL, mExpanded);
-        if (!mExpanded) {
-            mUiEventLogger.log(closePanelEvent());
-            closeDetail();
-        } else {
-            mUiEventLogger.log(openPanelEvent());
-            logTiles();
-        }
     }
 
     public void setPageListener(final PagedTileLayout.PageListener pageListener) {
@@ -723,56 +626,16 @@
         return mExpanded;
     }
 
-    public void setListening(boolean listening) {
+    /** */
+    public void setListening(boolean listening, String cachedSpecs) {
         if (mListening == listening) return;
         mListening = listening;
         if (mTileLayout != null) {
-            mQSLogger.logAllTilesChangeListening(listening, getDumpableTag(), mCachedSpecs);
+            mQSLogger.logAllTilesChangeListening(listening, getDumpableTag(), cachedSpecs);
             mTileLayout.setListening(listening);
         }
-        if (mListening) {
-            refreshAllTiles();
-        }
     }
 
-    private String getTilesSpecs() {
-        return mRecords.stream()
-                .map(tileRecord ->  tileRecord.tile.getTileSpec())
-                .collect(Collectors.joining(","));
-    }
-
-    public void setListening(boolean listening, boolean expanded) {
-        setListening(listening && expanded);
-        if (mSecurityFooter != null) {
-            mSecurityFooter.setListening(listening);
-        }
-        // Set the listening as soon as the QS fragment starts listening regardless of the expansion,
-        // so it will update the current brightness before the slider is visible.
-        setBrightnessListening(listening);
-    }
-
-    public void setBrightnessListening(boolean listening) {
-        if (mBrightnessController == null) {
-            return;
-        }
-        if (listening) {
-            mBrightnessController.registerCallbacks();
-        } else {
-            mBrightnessController.unregisterCallbacks();
-        }
-    }
-
-    public void refreshAllTiles() {
-        if (mBrightnessController != null) {
-            mBrightnessController.checkRestrictionAndSetEnabled();
-        }
-        for (TileRecord r : mRecords) {
-            r.tile.refreshState();
-        }
-        if (mSecurityFooter != null) {
-            mSecurityFooter.refreshState();
-        }
-    }
 
     public void showDetailAdapter(boolean show, DetailAdapter adapter, int[] locationInWindow) {
         int xInWindow = locationInWindow[0];
@@ -794,33 +657,10 @@
         mHandler.obtainMessage(H.SHOW_DETAIL, show ? 1 : 0, 0, r).sendToTarget();
     }
 
-    public void setTiles(Collection<QSTile> tiles) {
-        setTiles(tiles, false);
-    }
-
-    public void setTiles(Collection<QSTile> tiles, boolean collapsedView) {
-        if (!collapsedView) {
-            mQsTileRevealController.updateRevealedTiles(tiles);
-        }
-        for (TileRecord record : mRecords) {
-            mTileLayout.removeTile(record);
-            record.tile.removeCallback(record.callback);
-        }
-        mRecords.clear();
-        mCachedSpecs = "";
-        for (QSTile tile : tiles) {
-            addTile(tile, collapsedView);
-        }
-    }
-
-    protected void drawTile(TileRecord r, QSTile.State state) {
+    protected void drawTile(QSPanelControllerBase.TileRecord r, QSTile.State state) {
         r.tileView.onStateChanged(state);
     }
 
-    protected QSTileView createTileView(QSTile tile, boolean collapsedView) {
-        return mHost.createTileView(tile, collapsedView);
-    }
-
     protected QSEvent openPanelEvent() {
         return QSEvent.QS_PANEL_EXPANDED;
     }
@@ -837,14 +677,15 @@
         return mExpanded;
     }
 
-    protected TileRecord addTile(final QSTile tile, boolean collapsedView) {
-        final TileRecord r = new TileRecord();
-        r.tile = tile;
-        r.tileView = createTileView(tile, collapsedView);
+    void updateRevealedTiles(Collection<QSTile> tiles) {
+        mQsTileRevealController.updateRevealedTiles(tiles);
+    }
+
+    void addTile(QSPanelControllerBase.TileRecord tileRecord) {
         final QSTile.Callback callback = new QSTile.Callback() {
             @Override
             public void onStateChanged(QSTile.State state) {
-                drawTile(r, state);
+                drawTile(tileRecord, state);
             }
 
             @Override
@@ -852,22 +693,22 @@
                 // Both the collapsed and full QS panels get this callback, this check determines
                 // which one should handle showing the detail.
                 if (shouldShowDetail()) {
-                    QSPanel.this.showDetail(show, r);
+                    QSPanel.this.showDetail(show, tileRecord);
                 }
             }
 
             @Override
             public void onToggleStateChanged(boolean state) {
-                if (mDetailRecord == r) {
+                if (mDetailRecord == tileRecord) {
                     fireToggleStateChanged(state);
                 }
             }
 
             @Override
             public void onScanStateChanged(boolean state) {
-                r.scanState = state;
-                if (mDetailRecord == r) {
-                    fireScanStateChanged(r.scanState);
+                tileRecord.scanState = state;
+                if (mDetailRecord == tileRecord) {
+                    fireScanStateChanged(tileRecord.scanState);
                 }
             }
 
@@ -879,20 +720,20 @@
                 }
             }
         };
-        r.tile.addCallback(callback);
-        r.callback = callback;
-        r.tileView.init(r.tile);
-        r.tile.refreshState();
-        mRecords.add(r);
-        mCachedSpecs = getTilesSpecs();
+
+        tileRecord.tile.addCallback(callback);
+        tileRecord.callback = callback;
+        tileRecord.tileView.init(tileRecord.tile);
+        tileRecord.tile.refreshState();
 
         if (mTileLayout != null) {
-            mTileLayout.addTile(r);
+            mTileLayout.addTile(tileRecord);
         }
-
-        return r;
     }
 
+    void removeTile(QSPanelControllerBase.TileRecord tileRecord) {
+        mTileLayout.removeTile(tileRecord);
+    }
 
     public void showEdit(final View v) {
         v.post(new Runnable() {
@@ -925,8 +766,8 @@
     }
 
     protected void handleShowDetail(Record r, boolean show) {
-        if (r instanceof TileRecord) {
-            handleShowDetailTile((TileRecord) r, show);
+        if (r instanceof QSPanelControllerBase.TileRecord) {
+            handleShowDetailTile((QSPanelControllerBase.TileRecord) r, show);
         } else {
             int x = 0;
             int y = 0;
@@ -938,7 +779,7 @@
         }
     }
 
-    private void handleShowDetailTile(TileRecord r, boolean show) {
+    private void handleShowDetailTile(QSPanelControllerBase.TileRecord r, boolean show) {
         if ((mDetailRecord != null) == show && mDetailRecord == r) return;
 
         if (show) {
@@ -959,8 +800,8 @@
     protected void setDetailRecord(Record r) {
         if (r == mDetailRecord) return;
         mDetailRecord = r;
-        final boolean scanState = mDetailRecord instanceof TileRecord
-                && ((TileRecord) mDetailRecord).scanState;
+        final boolean scanState = mDetailRecord instanceof QSPanelControllerBase.TileRecord
+                && ((QSPanelControllerBase.TileRecord) mDetailRecord).scanState;
         fireScanStateChanged(scanState);
     }
 
@@ -972,15 +813,6 @@
         }
         mGridContentVisible = visible;
     }
-
-    private void logTiles() {
-        for (int i = 0; i < mRecords.size(); i++) {
-            QSTile tile = mRecords.get(i).tile;
-            mMetricsLogger.write(tile.populate(new LogMaker(tile.getMetricsCategory())
-                    .setType(MetricsEvent.TYPE_OPEN)));
-        }
-    }
-
     private void fireShowingDetail(DetailAdapter detail, int x, int y) {
         if (mCallback != null) {
             mCallback.onShowingDetail(detail, x, y);
@@ -999,46 +831,15 @@
         }
     }
 
-    public void clickTile(ComponentName tile) {
-        final String spec = CustomTile.toSpec(tile);
-        final int N = mRecords.size();
-        for (int i = 0; i < N; i++) {
-            if (mRecords.get(i).tile.getTileSpec().equals(spec)) {
-                mRecords.get(i).tile.click();
-                break;
-            }
-        }
-    }
-
     QSTileLayout getTileLayout() {
         return mTileLayout;
     }
 
-    QSTileView getTileView(QSTile tile) {
-        for (TileRecord r : mRecords) {
-            if (r.tile == tile) {
-                return r.tileView;
-            }
-        }
-        return null;
-    }
-
-    @Nullable
-    public QSSecurityFooter getSecurityFooter() {
-        return mSecurityFooter;
-    }
-
     @Nullable
     public View getDivider() {
         return mDivider;
     }
 
-    public void showDeviceMonitoringDialog() {
-        if (mSecurityFooter != null) {
-            mSecurityFooter.showDeviceMonitoringDialog();
-        }
-    }
-
     public void setContentMargins(int startMargin, int endMargin) {
         // Only some views actually want this content padding, others want to go all the way
         // to the edge like the brightness slider
@@ -1121,9 +922,11 @@
      */
     protected void updateMargins(View view, int start, int end) {
         LayoutParams lp = (LayoutParams) view.getLayoutParams();
-        lp.setMarginStart(start);
-        lp.setMarginEnd(end);
-        view.setLayoutParams(lp);
+        if (lp != null) {
+            lp.setMarginStart(start);
+            lp.setMarginEnd(end);
+            view.setLayoutParams(lp);
+        }
     }
 
     public MediaHost getMediaHost() {
@@ -1141,6 +944,14 @@
         mMediaVisibilityChangedListener = visibilityChangedListener;
     }
 
+    public boolean isListening() {
+        return mListening;
+    }
+
+    public void setSecurityFooter(View view) {
+        mSecurityFooter = view;
+    }
+
     private class H extends Handler {
         private static final int SHOW_DETAIL = 1;
         private static final int SET_TILE_VISIBILITY = 2;
@@ -1156,46 +967,32 @@
         }
     }
 
-    @Override
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        pw.println(getClass().getSimpleName() + ":");
-        pw.println("  Tile records:");
-        for (TileRecord record : mRecords) {
-            if (record.tile instanceof Dumpable) {
-                pw.print("    "); ((Dumpable) record.tile).dump(fd, pw, args);
-                pw.print("    "); pw.println(record.tileView.toString());
-            }
-        }
-    }
-
-
     protected static class Record {
         DetailAdapter detailAdapter;
         int x;
         int y;
     }
 
-    public static final class TileRecord extends Record {
-        public QSTile tile;
-        public com.android.systemui.plugins.qs.QSTileView tileView;
-        public boolean scanState;
-        public QSTile.Callback callback;
-    }
-
     public interface QSTileLayout {
-
+        /** */
         default void saveInstanceState(Bundle outState) {}
 
+        /** */
         default void restoreInstanceState(Bundle savedInstanceState) {}
 
-        void addTile(TileRecord tile);
+        /** */
+        void addTile(QSPanelControllerBase.TileRecord tile);
 
-        void removeTile(TileRecord tile);
+        /** */
+        void removeTile(QSPanelControllerBase.TileRecord tile);
 
-        int getOffsetTop(TileRecord tile);
+        /** */
+        int getOffsetTop(QSPanelControllerBase.TileRecord tile);
 
+        /** */
         boolean updateResources();
 
+        /** */
         void setListening(boolean listening);
 
         /**
@@ -1222,4 +1019,8 @@
 
         int getNumVisibleTiles();
     }
+
+    interface OnConfigurationChangedListener {
+        void onConfigurationChange(Configuration newConfig);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
new file mode 100644
index 0000000..4e2351f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
@@ -0,0 +1,195 @@
+/*
+ * 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.systemui.qs;
+
+import static com.android.systemui.qs.QSPanel.QS_SHOW_BRIGHTNESS;
+
+import android.annotation.NonNull;
+import android.content.res.Configuration;
+import android.view.ViewGroup;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
+import com.android.systemui.R;
+import com.android.systemui.dump.DumpManager;
+import com.android.systemui.media.MediaHost;
+import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.qs.customize.QSCustomizer;
+import com.android.systemui.qs.dagger.QSScope;
+import com.android.systemui.settings.BrightnessController;
+import com.android.systemui.statusbar.policy.BrightnessMirrorController;
+import com.android.systemui.tuner.TunerService;
+
+import javax.inject.Inject;
+
+/**
+ * Controller for {@link QSPanel}.
+ */
+@QSScope
+public class QSPanelController extends QSPanelControllerBase<QSPanel> {
+    private final QSSecurityFooter mQsSecurityFooter;
+    private final TunerService mTunerService;
+    private final BrightnessController mBrightnessController;
+
+    private final QSPanel.OnConfigurationChangedListener mOnConfigurationChangedListener =
+            new QSPanel.OnConfigurationChangedListener() {
+        @Override
+        public void onConfigurationChange(Configuration newConfig) {
+            mView.updateResources();
+            mQsSecurityFooter.onConfigurationChanged();
+            if (mView.isListening()) {
+                refreshAllTiles();
+            }
+        }
+    };
+    private BrightnessMirrorController mBrightnessMirrorController;
+
+    @Inject
+    QSPanelController(QSPanel view, QSSecurityFooter qsSecurityFooter, TunerService tunerService,
+            QSTileHost qstileHost, DumpManager dumpManager,
+            MetricsLogger metricsLogger, UiEventLogger uiEventLogger,
+            BrightnessController.Factory brightnessControllerFactory) {
+        super(view, qstileHost, metricsLogger, uiEventLogger, dumpManager);
+        mQsSecurityFooter = qsSecurityFooter;
+        mTunerService = tunerService;
+        mQsSecurityFooter.setHostEnvironment(qstileHost);
+        mBrightnessController = brightnessControllerFactory.create(
+                mView.findViewById(R.id.brightness_slider));
+    }
+
+    @Override
+    protected void onViewAttached() {
+        super.onViewAttached();
+        mTunerService.addTunable(mView, QS_SHOW_BRIGHTNESS);
+        mView.updateResources();
+        if (mView.isListening()) {
+            refreshAllTiles();
+        }
+        mView.addOnConfigurationChangedListener(mOnConfigurationChangedListener);
+        mView.setSecurityFooter(mQsSecurityFooter.getView());
+        switchTileLayout(true);
+        if (mBrightnessMirrorController != null) {
+            mBrightnessMirrorController.addCallback(mView);
+        }
+    }
+
+    @Override
+    protected void onViewDetached() {
+        mTunerService.removeTunable(mView);
+        mView.removeOnConfigurationChangedListener(mOnConfigurationChangedListener);
+        if (mBrightnessMirrorController != null) {
+            mBrightnessMirrorController.removeCallback(mView);
+        }
+        super.onViewDetached();
+    }
+
+    /** TODO(b/168904199): Remove this method once view is controllerized. */
+    QSPanel getView() {
+        return mView;
+    }
+
+    /**
+     * Set the header container of quick settings.
+     */
+    public void setHeaderContainer(@NonNull ViewGroup headerContainer) {
+        mView.setHeaderContainer(headerContainer);
+    }
+
+    public QSPanel.QSTileLayout getTileLayout() {
+        return mView.getTileLayout();
+    }
+
+    /** */
+    public void setCustomizer(QSCustomizer customizer) {
+        mView.setCustomizer(customizer);
+    }
+
+    /** */
+    public boolean isShowingCustomize() {
+        return mView.isShowingCustomize();
+    }
+
+    /** */
+    public void setVisibility(int visibility) {
+        mView.setVisibility(visibility);
+    }
+
+    /** */
+    public void setListening(boolean listening, boolean expanded) {
+        setListening(listening && expanded);
+        if (mView.isListening()) {
+            refreshAllTiles();
+        }
+
+        mQsSecurityFooter.setListening(listening);
+
+        // Set the listening as soon as the QS fragment starts listening regardless of the
+        //expansion, so it will update the current brightness before the slider is visible.
+        if (listening) {
+            mBrightnessController.registerCallbacks();
+        } else {
+            mBrightnessController.unregisterCallbacks();
+        }
+    }
+
+    /** */
+    public QSTileRevealController getQsTileRevealController() {
+        return mView.getQsTileRevealController();
+    }
+
+    /** */
+    public MediaHost getMediaHost() {
+        return mView.getMediaHost();
+    }
+
+    /** */
+    public void setBrightnessMirror(BrightnessMirrorController brightnessMirrorController) {
+        mBrightnessMirrorController = brightnessMirrorController;
+        mView.setBrightnessMirror(brightnessMirrorController);
+    }
+
+    /** Get the QSTileHost this panel uses. */
+    public QSTileHost getHost() {
+        return mHost;
+    }
+
+
+    /** Open the details for a specific tile.. */
+    public void openDetails(String subPanel) {
+        QSTile tile = getTile(subPanel);
+        if (tile != null) {
+            mView.openDetails(tile);
+        }
+    }
+
+    /** Show the device monitoring dialog. */
+    public void showDeviceMonitoringDialog() {
+        mQsSecurityFooter.showDeviceMonitoringDialog();
+    }
+
+    /** Update appearance of QSPanel. */
+    public void updateResources() {
+        mView.updateResources();
+    }
+
+    /** Update state of all tiles. */
+    public void refreshAllTiles() {
+        mBrightnessController.checkRestrictionAndSetEnabled();
+        super.refreshAllTiles();
+        mQsSecurityFooter.refreshState();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
new file mode 100644
index 0000000..fe92827
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
@@ -0,0 +1,250 @@
+/*
+ * 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.systemui.qs;
+
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
+import android.content.ComponentName;
+import android.content.res.Configuration;
+import android.metrics.LogMaker;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
+import com.android.systemui.Dumpable;
+import com.android.systemui.dump.DumpManager;
+import com.android.systemui.media.MediaHost;
+import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.plugins.qs.QSTileView;
+import com.android.systemui.qs.external.CustomTile;
+import com.android.systemui.util.ViewController;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.stream.Collectors;
+
+/**
+ * Controller for QSPanel views.
+ *
+ * @param <T> Type of QSPanel.
+ */
+public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewController<T>
+        implements Dumpable{
+    protected final QSTileHost mHost;
+    private final MediaHost mMediaHost;
+    private final MetricsLogger mMetricsLogger;
+    private final UiEventLogger mUiEventLogger;
+    private final DumpManager mDumpManager;
+    protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
+
+    private int mLastOrientation;
+
+    private final QSHost.Callback mQSHostCallback = this::setTiles;
+
+    private final QSPanel.OnConfigurationChangedListener mOnConfigurationChangedListener =
+            new QSPanel.OnConfigurationChangedListener() {
+                @Override
+                public void onConfigurationChange(Configuration newConfig) {
+                    if (newConfig.orientation != mLastOrientation) {
+                        mLastOrientation = newConfig.orientation;
+                        switchTileLayout(false);
+                    }
+                }
+            };
+    private String mCachedSpecs = "";
+
+    protected QSPanelControllerBase(T view, QSTileHost host,
+            MetricsLogger metricsLogger, UiEventLogger uiEventLogger, DumpManager dumpManager) {
+        super(view);
+        mHost = host;
+        mMediaHost = mView.getMediaHost();
+        mMetricsLogger = metricsLogger;
+        mUiEventLogger = uiEventLogger;
+        mDumpManager = dumpManager;
+    }
+
+    @Override
+    protected void onViewAttached() {
+        mView.addOnConfigurationChangedListener(mOnConfigurationChangedListener);
+        mHost.addCallback(mQSHostCallback);
+        mMediaHost.addVisibilityChangeListener(aBoolean -> {
+            switchTileLayout(false);
+            return null;
+        });
+        setTiles();
+        switchTileLayout(true);
+        mDumpManager.registerDumpable(mView.getDumpableTag(), this);
+    }
+
+    @Override
+    protected void onViewDetached() {
+        mView.removeOnConfigurationChangedListener(mOnConfigurationChangedListener);
+        mHost.removeCallback(mQSHostCallback);
+
+        for (TileRecord record : mRecords) {
+            record.tile.removeCallbacks();
+        }
+        mRecords.clear();
+        mDumpManager.unregisterDumpable(mView.getDumpableTag());
+    }
+
+    /** */
+    public void setTiles() {
+        setTiles(mHost.getTiles(), false);
+    }
+
+    /** */
+    public void setTiles(Collection<QSTile> tiles, boolean collapsedView) {
+        if (!collapsedView) {
+            mView.updateRevealedTiles(tiles);
+        }
+        for (QSPanelControllerBase.TileRecord record : mRecords) {
+            mView.removeTile(record);
+            record.tile.removeCallback(record.callback);
+        }
+        mRecords.clear();
+        mCachedSpecs = "";
+        for (QSTile tile : tiles) {
+            addTile(tile, collapsedView);
+        }
+    }
+
+    /** */
+    public void refreshAllTiles() {
+        for (QSPanelControllerBase.TileRecord r : mRecords) {
+            r.tile.refreshState();
+        }
+    }
+
+    private void addTile(final QSTile tile, boolean collapsedView) {
+        final TileRecord r = new TileRecord();
+        r.tile = tile;
+        r.tileView = mHost.createTileView(tile, collapsedView);
+        mView.addTile(r);
+        mRecords.add(r);
+        mCachedSpecs = getTilesSpecs();
+
+    }
+
+    /** */
+    public void clickTile(ComponentName tile) {
+        final String spec = CustomTile.toSpec(tile);
+        for (TileRecord record : mRecords) {
+            if (record.tile.getTileSpec().equals(spec)) {
+                record.tile.click();
+                break;
+            }
+        }
+    }
+    protected QSTile getTile(String subPanel) {
+        for (int i = 0; i < mRecords.size(); i++) {
+            if (subPanel.equals(mRecords.get(i).tile.getTileSpec())) {
+                return mRecords.get(i).tile;
+            }
+        }
+        return mHost.createTile(subPanel);
+    }
+
+
+    QSTileView getTileView(QSTile tile) {
+        for (QSPanelControllerBase.TileRecord r : mRecords) {
+            if (r.tile == tile) {
+                return r.tileView;
+            }
+        }
+        return null;
+    }
+
+    private String getTilesSpecs() {
+        return mRecords.stream()
+                .map(tileRecord ->  tileRecord.tile.getTileSpec())
+                .collect(Collectors.joining(","));
+    }
+
+
+    /** */
+    public void setExpanded(boolean expanded) {
+        mView.setExpanded(expanded);
+        mMetricsLogger.visibility(MetricsEvent.QS_PANEL, expanded);
+        if (!expanded) {
+            mUiEventLogger.log(mView.closePanelEvent());
+            closeDetail();
+        } else {
+            mUiEventLogger.log(mView.openPanelEvent());
+            logTiles();
+        }
+    }
+
+    /** */
+    public void closeDetail() {
+        mView.closeDetail();
+    }
+
+    /** */
+    public void openDetails(String subPanel) {
+        QSTile tile = getTile(subPanel);
+        // If there's no tile with that name (as defined in QSFactoryImpl or other QSFactory),
+        // QSFactory will not be able to create a tile and getTile will return null
+        if (tile != null) {
+            mView.showDetailAdapter(
+                    true, tile.getDetailAdapter(), new int[]{mView.getWidth() / 2, 0});
+        }
+    }
+
+
+    void setListening(boolean listening) {
+        mView.setListening(listening, mCachedSpecs);
+    }
+
+    boolean switchTileLayout(boolean force) {
+        if (mView.switchTileLayout(force, mRecords)) {
+            setTiles();
+            return true;
+        }
+        return false;
+    }
+
+    private void logTiles() {
+        for (int i = 0; i < mRecords.size(); i++) {
+            QSTile tile = mRecords.get(i).tile;
+            mMetricsLogger.write(tile.populate(new LogMaker(tile.getMetricsCategory())
+                    .setType(MetricsEvent.TYPE_OPEN)));
+        }
+    }
+
+
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println(getClass().getSimpleName() + ":");
+        pw.println("  Tile records:");
+        for (QSPanelControllerBase.TileRecord record : mRecords) {
+            if (record.tile instanceof Dumpable) {
+                pw.print("    "); ((Dumpable) record.tile).dump(fd, pw, args);
+                pw.print("    "); pw.println(record.tileView.toString());
+            }
+        }
+    }
+
+    /** */
+    public static final class TileRecord extends QSPanel.Record {
+        public QSTile tile;
+        public com.android.systemui.plugins.qs.QSTileView tileView;
+        public boolean scanState;
+        public QSTile.Callback callback;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
index 0891972..c90182b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
@@ -44,11 +44,15 @@
 import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
 import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.qs.dagger.QSScope;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 import com.android.systemui.statusbar.policy.SecurityController;
 
-public class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListener {
+import javax.inject.Inject;
+
+@QSScope
+class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListener {
     protected static final String TAG = "QSSecurityFooter";
     protected static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     private static final boolean DEBUG_FORCE_VISIBLE = false;
@@ -72,12 +76,13 @@
     private int mFooterTextId;
     private int mFooterIconId;
 
+    @Inject
     public QSSecurityFooter(QSPanel qsPanel, Context context, UserTracker userTracker) {
         mRootView = LayoutInflater.from(context)
                 .inflate(R.layout.quick_settings_footer, qsPanel, false);
         mRootView.setOnClickListener(this);
-        mFooterText = (TextView) mRootView.findViewById(R.id.footer_text);
-        mFooterIcon = (ImageView) mRootView.findViewById(R.id.footer_icon);
+        mFooterText = mRootView.findViewById(R.id.footer_text);
+        mFooterIcon = mRootView.findViewById(R.id.footer_icon);
         mFooterIconId = R.drawable.ic_info_outline;
         mContext = context;
         mMainHandler = new Handler(Looper.myLooper());
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileRevealController.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileRevealController.java
index 2f012e6..3d4a417 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileRevealController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileRevealController.java
@@ -8,11 +8,16 @@
 
 import com.android.systemui.Prefs;
 import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.qs.dagger.QSScope;
 
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Set;
 
+import javax.inject.Inject;
+
+/** */
+@QSScope
 public class QSTileRevealController {
     private static final long QS_REVEAL_TILES_DELAY = 500L;
 
@@ -34,6 +39,7 @@
         }
     };
 
+    @Inject
     QSTileRevealController(Context context, QSPanel qsPanel, PagedTileLayout pagedTileLayout) {
         mContext = context;
         mQSPanel = qsPanel;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index 82cb863..84a5b6f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -28,23 +28,13 @@
 import android.widget.LinearLayout;
 
 import com.android.internal.logging.UiEventLogger;
-import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dump.DumpManager;
 import com.android.systemui.media.MediaHierarchyManager;
 import com.android.systemui.media.MediaHost;
 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.plugins.qs.QSTile.SignalState;
 import com.android.systemui.plugins.qs.QSTile.State;
-import com.android.systemui.qs.customize.QSCustomizer;
 import com.android.systemui.qs.logging.QSLogger;
-import com.android.systemui.settings.UserTracker;
-import com.android.systemui.tuner.TunerService;
-import com.android.systemui.tuner.TunerService.Tunable;
-
-import java.util.ArrayList;
-import java.util.Collection;
 
 import javax.inject.Inject;
 import javax.inject.Named;
@@ -68,15 +58,10 @@
     public QuickQSPanel(
             @Named(VIEW_CONTEXT) Context context,
             AttributeSet attrs,
-            DumpManager dumpManager,
-            BroadcastDispatcher broadcastDispatcher,
             QSLogger qsLogger,
             @Named(QUICK_QS_PANEL) MediaHost mediaHost,
-            UiEventLogger uiEventLogger,
-            UserTracker userTracker
-    ) {
-        super(context, attrs, dumpManager, broadcastDispatcher, qsLogger, mediaHost, uiEventLogger,
-                userTracker);
+            UiEventLogger uiEventLogger) {
+        super(context, attrs, qsLogger, mediaHost, uiEventLogger);
         sDefaultMaxTiles = getResources().getInteger(R.integer.quick_qs_panel_max_columns);
         applyBottomMargin((View) mRegularTileLayout);
     }
@@ -89,17 +74,12 @@
     }
 
     @Override
-    protected void addSecurityFooter() {
-        // No footer needed
-    }
-
-    @Override
     protected void addViewsAboveTiles() {
         // Nothing to add above the tiles
     }
 
     @Override
-    protected TileLayout createRegularTileLayout() {
+    public TileLayout createRegularTileLayout() {
         return new QuickQSPanel.HeaderTileLayout(mContext, mUiEventLogger);
     }
 
@@ -133,18 +113,6 @@
     }
 
     @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        Dependency.get(TunerService.class).addTunable(mNumTiles, NUM_QUICK_TILES);
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-        Dependency.get(TunerService.class).removeTunable(mNumTiles);
-    }
-
-    @Override
     protected String getDumpableTag() {
         return TAG;
     }
@@ -159,7 +127,7 @@
     }
 
     @Override
-    protected void drawTile(TileRecord r, State state) {
+    protected void drawTile(QSPanelControllerBase.TileRecord r, State state) {
         if (state instanceof SignalState) {
             SignalState copy = new SignalState();
             state.copyTo(copy);
@@ -171,17 +139,8 @@
         super.drawTile(r, state);
     }
 
-    @Override
-    public void setHost(QSTileHost host, QSCustomizer customizer) {
-        super.setHost(host, customizer);
-        setTiles(mHost.getTiles());
-    }
-
     public void setMaxTiles(int maxTiles) {
         mMaxTiles = maxTiles;
-        if (mHost != null) {
-            setTiles(mHost.getTiles());
-        }
     }
 
     @Override
@@ -192,25 +151,6 @@
         }
     }
 
-    @Override
-    public void setTiles(Collection<QSTile> tiles) {
-        ArrayList<QSTile> quickTiles = new ArrayList<>();
-        for (QSTile tile : tiles) {
-            quickTiles.add(tile);
-            if (quickTiles.size() == mMaxTiles) {
-                break;
-            }
-        }
-        super.setTiles(quickTiles, true);
-    }
-
-    private final Tunable mNumTiles = new Tunable() {
-        @Override
-        public void onTuningChanged(String key, String newValue) {
-            setMaxTiles(parseNumTiles(newValue));
-        }
-    };
-
     public int getNumQuickTiles() {
         return mMaxTiles;
     }
@@ -308,7 +248,7 @@
         }
 
         @Override
-        protected void addTileView(TileRecord tile) {
+        protected void addTileView(QSPanelControllerBase.TileRecord tile) {
             addView(tile.tileView, getChildCount(), generateTileLayoutParams());
         }
 
@@ -371,7 +311,7 @@
         private void setAccessibilityOrder() {
             if (mRecords != null && mRecords.size() > 0) {
                 View previousView = this;
-                for (TileRecord record : mRecords) {
+                for (QSPanelControllerBase.TileRecord record : mRecords) {
                     if (record.tileView.getVisibility() == GONE) continue;
                     previousView = record.tileView.updateAccessibilityOrder(previousView);
                 }
@@ -383,7 +323,7 @@
         @Override
         protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
             // Measure each QS tile.
-            for (TileRecord record : mRecords) {
+            for (QSPanelControllerBase.TileRecord record : mRecords) {
                 if (record.tileView.getVisibility() == GONE) continue;
                 record.tileView.measure(exactly(mCellWidth), exactly(mCellHeight));
             }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
new file mode 100644
index 0000000..97b6e99
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
@@ -0,0 +1,83 @@
+/*
+ * 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.systemui.qs;
+
+import static com.android.systemui.qs.QuickQSPanel.NUM_QUICK_TILES;
+import static com.android.systemui.qs.QuickQSPanel.parseNumTiles;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
+import com.android.systemui.dump.DumpManager;
+import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.qs.dagger.QSScope;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerService.Tunable;
+
+import java.util.ArrayList;
+
+import javax.inject.Inject;
+
+/** Controller for {@link QuickQSPanel}. */
+@QSScope
+public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel> {
+    private final Tunable mNumTiles =
+            (key, newValue) -> setMaxTiles(parseNumTiles(newValue));
+
+    private final TunerService mTunerService;
+
+    @Inject
+    QuickQSPanelController(QuickQSPanel view, TunerService tunerService, QSTileHost qsTileHost,
+            MetricsLogger metricsLogger, UiEventLogger uiEventLogger,
+            DumpManager dumpManager) {
+        super(view, qsTileHost, metricsLogger, uiEventLogger, dumpManager);
+        mTunerService = tunerService;
+    }
+
+    @Override
+    protected void onViewAttached() {
+        super.onViewAttached();
+        mTunerService.addTunable(mNumTiles, NUM_QUICK_TILES);
+
+    }
+
+    @Override
+    protected void onViewDetached() {
+        super.onViewDetached();
+        mTunerService.removeTunable(mNumTiles);
+    }
+
+    public boolean isListening() {
+        return mView.isListening();
+    }
+
+    private void setMaxTiles(int parseNumTiles) {
+        mView.setMaxTiles(parseNumTiles);
+        setTiles();
+    }
+
+    @Override
+    public void setTiles() {
+        ArrayList<QSTile> quickTiles = new ArrayList<>();
+        for (QSTile tile : mHost.getTiles()) {
+            quickTiles.add(tile);
+            if (quickTiles.size() == mView.getNumQuickTiles()) {
+                break;
+            }
+        }
+        super.setTiles(quickTiles, true);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index a9fbc74..5757602 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -353,11 +353,7 @@
             mPrivacyChip.setExpanded(expansionFraction > 0.5);
             mPrivacyChipAlphaAnimator.setPosition(keyguardExpansionFraction);
         }
-        if (expansionFraction < 1 && expansionFraction > 0.99) {
-            if (mHeaderQsPanel.switchTileLayout()) {
-                updateResources();
-            }
-        }
+
         mKeyguardExpansionFraction = keyguardExpansionFraction;
     }
 
@@ -446,7 +442,6 @@
     public void setQSPanel(final QSPanel qsPanel) {
         //host.setHeaderView(mExpandIndicator);
         mHeaderQsPanel.setQSPanelAndHeader(qsPanel, this);
-        mHeaderQsPanel.setHost(qsPanel.getHost(), null /* No customization in header */);
 
         Rect tintArea = new Rect(0, 0, 0, 0);
         int colorForeground = Utils.getColorAttrDefaultColor(getContext(),
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
index 676a300..febb71c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
@@ -44,6 +44,7 @@
 import com.android.systemui.privacy.PrivacyItem;
 import com.android.systemui.privacy.PrivacyItemController;
 import com.android.systemui.qs.carrier.QSCarrierGroupController;
+import com.android.systemui.qs.dagger.QSScope;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -64,6 +65,7 @@
 /**
  * Controller for {@link QuickStatusBarHeader}.
  */
+@QSScope
 class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader> {
     private static final String TAG = "QuickStatusBarHeader";
 
@@ -74,7 +76,7 @@
     private final ActivityStarter mActivityStarter;
     private final UiEventLogger mUiEventLogger;
     private final QSCarrierGroupController mQSCarrierGroupController;
-    private final QuickQSPanel mHeaderQsPanel;
+    private final QuickQSPanelController mHeaderQsPanelController;
     private final LifecycleRegistry mLifecycle;
     private final OngoingPrivacyChip mPrivacyChip;
     private final Clock mClockView;
@@ -93,6 +95,7 @@
     private AlarmClockInfo mNextAlarm;
     private boolean mAllIndicatorsEnabled;
     private boolean mMicCameraIndicatorsEnabled;
+    private boolean mLocationIndicatorsEnabled;
     private boolean mPrivacyChipLogged;
     private int mRingerMode = AudioManager.RINGER_MODE_NORMAL;
 
@@ -156,6 +159,14 @@
             }
         }
 
+        @Override
+        public void onFlagLocationChanged(boolean flag) {
+            if (mLocationIndicatorsEnabled != flag) {
+                mLocationIndicatorsEnabled = flag;
+                update();
+            }
+        }
+
         private void update() {
             StatusIconContainer iconContainer = mView.requireViewById(R.id.statusIcons);
             iconContainer.setIgnoredSlots(getIgnoredIconSlots());
@@ -194,13 +205,14 @@
         }
     };
 
-    private QuickStatusBarHeaderController(QuickStatusBarHeader view,
+    @Inject
+    QuickStatusBarHeaderController(QuickStatusBarHeader view,
             ZenModeController zenModeController, NextAlarmController nextAlarmController,
             PrivacyItemController privacyItemController, RingerModeTracker ringerModeTracker,
             ActivityStarter activityStarter, UiEventLogger uiEventLogger,
             QSTileHost qsTileHost, StatusBarIconController statusBarIconController,
             CommandQueue commandQueue, DemoModeController demoModeController,
-            UserTracker userTracker,
+            UserTracker userTracker, QuickQSPanelController quickQSPanelController,
             QSCarrierGroupController.Builder qsCarrierGroupControllerBuilder) {
         super(view);
         mZenModeController = zenModeController;
@@ -215,6 +227,7 @@
         mDemoModeController = demoModeController;
         mUserTracker = userTracker;
         mLifecycle = new LifecycleRegistry(mLifecycleOwner);
+        mHeaderQsPanelController = quickQSPanelController;
 
         mQSCarrierGroupController = qsCarrierGroupControllerBuilder
                 .setQSCarrierGroup(mView.findViewById(R.id.carrier_group))
@@ -222,7 +235,6 @@
 
 
         mPrivacyChip = mView.findViewById(R.id.privacy_chip);
-        mHeaderQsPanel = mView.findViewById(R.id.quick_qs_panel);
         mNextAlarmContainer = mView.findViewById(R.id.alarm_container);
         mClockView = mView.findViewById(R.id.clock);
         mRingerContainer = mView.findViewById(R.id.ringer_container);
@@ -252,6 +264,7 @@
 
         mAllIndicatorsEnabled = mPrivacyItemController.getAllIndicatorsAvailable();
         mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable();
+        mLocationIndicatorsEnabled = mPrivacyItemController.getLocationAvailable();
 
         setChipVisibility(mPrivacyChip.getVisibility() == View.VISIBLE);
 
@@ -280,8 +293,12 @@
         }
         mListening = listening;
 
-        mHeaderQsPanel.setListening(listening);
-        if (mHeaderQsPanel.switchTileLayout()) {
+        mHeaderQsPanelController.setListening(listening);
+        if (mHeaderQsPanelController.isListening()) {
+            mHeaderQsPanelController.refreshAllTiles();
+        }
+
+        if (mHeaderQsPanelController.switchTileLayout(false)) {
             mView.updateResources();
         }
 
@@ -292,6 +309,7 @@
             // Get the most up to date info
             mAllIndicatorsEnabled = mPrivacyItemController.getAllIndicatorsAvailable();
             mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable();
+            mLocationIndicatorsEnabled = mPrivacyItemController.getLocationAvailable();
             mPrivacyItemController.addCallback(mPICCallback);
         } else {
             mZenModeController.removeCallback(mZenModeControllerCallback);
@@ -323,7 +341,7 @@
                     com.android.internal.R.string.status_bar_camera));
             ignored.add(mView.getResources().getString(
                     com.android.internal.R.string.status_bar_microphone));
-            if (mAllIndicatorsEnabled) {
+            if (mAllIndicatorsEnabled || mLocationIndicatorsEnabled) {
                 ignored.add(mView.getResources().getString(
                         com.android.internal.R.string.status_bar_location));
             }
@@ -333,7 +351,7 @@
     }
 
     private boolean getChipEnabled() {
-        return mMicCameraIndicatorsEnabled || mAllIndicatorsEnabled;
+        return mMicCameraIndicatorsEnabled || mLocationIndicatorsEnabled || mAllIndicatorsEnabled;
     }
 
     private boolean isZenOverridingRinger() {
@@ -369,55 +387,4 @@
             mClockView.onDemoModeFinished();
         }
     }
-
-    static class Builder {
-        private final ZenModeController mZenModeController;
-        private final NextAlarmController mNextAlarmController;
-        private final PrivacyItemController mPrivacyItemController;
-        private final RingerModeTracker mRingerModeTracker;
-        private final ActivityStarter mActivityStarter;
-        private final UiEventLogger mUiEventLogger;
-        private final QSTileHost mQsTileHost;
-        private final StatusBarIconController mStatusBarIconController;
-        private final CommandQueue mCommandQueue;
-        private final DemoModeController mDemoModeController;
-        private final UserTracker mUserTracker;
-        private final QSCarrierGroupController.Builder mQSCarrierGroupControllerBuilder;
-        private QuickStatusBarHeader mView;
-
-        @Inject
-        Builder(ZenModeController zenModeController, NextAlarmController nextAlarmController,
-                PrivacyItemController privacyItemController, RingerModeTracker ringerModeTracker,
-                ActivityStarter activityStarter, UiEventLogger uiEventLogger, QSTileHost qsTileHost,
-                StatusBarIconController statusBarIconController, CommandQueue commandQueue,
-                DemoModeController demoModeController, UserTracker userTracker,
-                QSCarrierGroupController.Builder qsCarrierGroupControllerBuilder) {
-            mZenModeController = zenModeController;
-            mNextAlarmController = nextAlarmController;
-            mPrivacyItemController = privacyItemController;
-            mRingerModeTracker = ringerModeTracker;
-            mActivityStarter = activityStarter;
-            mUiEventLogger = uiEventLogger;
-            mQsTileHost = qsTileHost;
-            mStatusBarIconController = statusBarIconController;
-            mCommandQueue = commandQueue;
-            mDemoModeController = demoModeController;
-            mUserTracker = userTracker;
-            mQSCarrierGroupControllerBuilder = qsCarrierGroupControllerBuilder;
-        }
-
-        public Builder setQuickStatusBarHeader(QuickStatusBarHeader view) {
-            mView = view;
-            return this;
-        }
-
-
-        QuickStatusBarHeaderController build() {
-            return new QuickStatusBarHeaderController(mView, mZenModeController,
-                    mNextAlarmController, mPrivacyItemController, mRingerModeTracker,
-                    mActivityStarter, mUiEventLogger, mQsTileHost, mStatusBarIconController,
-                    mCommandQueue, mDemoModeController, mUserTracker,
-                    mQSCarrierGroupControllerBuilder);
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index 694492a..4ab7afd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -11,7 +11,7 @@
 
 import com.android.systemui.R;
 import com.android.systemui.qs.QSPanel.QSTileLayout;
-import com.android.systemui.qs.QSPanel.TileRecord;
+import com.android.systemui.qs.QSPanelControllerBase.TileRecord;
 
 import java.util.ArrayList;
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 55b67e0..8097958 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -74,9 +74,9 @@
     private final ScreenLifecycle mScreenLifecycle;
     private final TileQueryHelper mTileQueryHelper;
     private final View mTransparentView;
+    private final QSTileHost mHost;
 
     private boolean isShown;
-    private QSTileHost mHost;
     private RecyclerView mRecyclerView;
     private TileAdapter mTileAdapter;
     private Toolbar mToolbar;
@@ -95,6 +95,7 @@
             KeyguardStateController keyguardStateController,
             ScreenLifecycle screenLifecycle,
             TileQueryHelper tileQueryHelper,
+            QSTileHost qsTileHost,
             UiEventLogger uiEventLogger) {
         super(new ContextThemeWrapper(context, R.style.edit_theme), attrs);
 
@@ -139,6 +140,8 @@
         mLightBarController = lightBarController;
         mKeyguardStateController = keyguardStateController;
         mScreenLifecycle = screenLifecycle;
+        mHost = qsTileHost;
+        mTileAdapter.setHost(mHost);
         updateNavBackDrop(getResources().getConfiguration());
     }
 
@@ -170,11 +173,6 @@
         mLightBarController.setQsCustomizing(mIsShowingNavBackdrop && isShown);
     }
 
-    public void setHost(QSTileHost host) {
-        mHost = host;
-        mTileAdapter.setHost(host);
-    }
-
     public void setContainer(NotificationsQuickSettingsContainer notificationsQsContainer) {
         mNotifQsContainer = notificationsQsContainer;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentComponent.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentComponent.java
new file mode 100644
index 0000000..7ba3563
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentComponent.java
@@ -0,0 +1,51 @@
+/*
+ * 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.systemui.qs.dagger;
+
+import com.android.systemui.qs.QSAnimator;
+import com.android.systemui.qs.QSContainerImplController;
+import com.android.systemui.qs.QSFragment;
+import com.android.systemui.qs.QSPanelController;
+import com.android.systemui.qs.QuickQSPanelController;
+
+import dagger.BindsInstance;
+import dagger.Subcomponent;
+
+/**
+ * Dagger Subcomponent for {@link QSFragment}.
+ */
+@Subcomponent(modules = {QSFragmentModule.class})
+@QSScope
+public interface QSFragmentComponent {
+    /** Factory for building a {@link QSFragmentComponent}. */
+    @Subcomponent.Factory
+    interface Factory {
+        QSFragmentComponent create(@BindsInstance QSFragment qsFragment);
+    }
+
+    /** Construct a {@link QSPanelController}. */
+    QSPanelController getQSPanelController();
+
+    /** Construct a {@link QuickQSPanelController}. */
+    QuickQSPanelController getQuickQSPanelController();
+
+    /** Construct a {@link QSAnimator}. */
+    QSAnimator getQSAnimator();
+
+    /** Construct a {@link QSContainerImplController}. */
+    QSContainerImplController getQSContainerImplController();
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
new file mode 100644
index 0000000..ee3f2f6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
@@ -0,0 +1,73 @@
+/*
+ * 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.systemui.qs.dagger;
+
+import android.view.View;
+
+import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.RootView;
+import com.android.systemui.plugins.qs.QS;
+import com.android.systemui.qs.QSContainerImpl;
+import com.android.systemui.qs.QSFragment;
+import com.android.systemui.qs.QSPanel;
+import com.android.systemui.qs.QuickQSPanel;
+import com.android.systemui.qs.QuickStatusBarHeader;
+
+import dagger.Binds;
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * Dagger Module for {@link QSFragmentComponent}.
+ */
+@Module
+public interface QSFragmentModule {
+    /** */
+    @Provides
+    @RootView
+    static View provideRootView(QSFragment qsFragment) {
+        return qsFragment.getView();
+    }
+
+    /** */
+    @Provides
+    static QSPanel provideQSPanel(@RootView View view) {
+        return view.findViewById(R.id.quick_settings_panel);
+    }
+
+    /** */
+    @Provides
+    static QSContainerImpl providesQSContainerImpl(@RootView View view) {
+        return view.findViewById(R.id.quick_settings_container);
+    }
+
+    /** */
+    @Binds
+    QS bindQS(QSFragment qsFragment);
+
+    /** */
+    @Provides
+    static QuickStatusBarHeader providesQuickStatusBarHeader(@RootView View view) {
+        return view.findViewById(R.id.header);
+    }
+
+    /** */
+    @Provides
+    static QuickQSPanel providesQuickQSPanel(QuickStatusBarHeader quickStatusBarHeader) {
+        return quickStatusBarHeader.findViewById(R.id.quick_qs_panel);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
index 953de60..7c799ae 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
@@ -38,8 +38,8 @@
 /**
  * Module for QS dependencies
  */
-// TODO: Add other QS classes
-@Module(includes = {MediaModule.class})
+@Module(subcomponents = {QSFragmentComponent.class},
+        includes = {MediaModule.class})
 public interface QSModule {
 
     @Provides
@@ -60,7 +60,6 @@
         return manager;
     }
 
-
     /** */
     @Binds
     QSHost provideQsHost(QSTileHost controllerImpl);
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/RootView.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSScope.java
similarity index 74%
copy from packages/SystemUI/src/com/android/keyguard/dagger/RootView.java
copy to packages/SystemUI/src/com/android/systemui/qs/dagger/QSScope.java
index 5ebff09..f615eab 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/RootView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSScope.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,17 +14,19 @@
  * limitations under the License.
  */
 
-package com.android.keyguard.dagger;
+package com.android.systemui.qs.dagger;
 
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
 import java.lang.annotation.Documented;
 import java.lang.annotation.Retention;
 
-import javax.inject.Qualifier;
+import javax.inject.Scope;
 
-@Qualifier
+/**
+ * Scope annotation for singleton items within the {@link QSFragmentComponent}.
+ */
 @Documented
 @Retention(RUNTIME)
-public @interface RootView {
-}
+@Scope
+public @interface QSScope {}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 7d69753..818bb9d 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -18,8 +18,7 @@
 
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
-import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+import static android.view.Display.DEFAULT_DISPLAY;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -30,6 +29,7 @@
 import android.app.ActivityManager;
 import android.app.Notification;
 import android.app.PendingIntent;
+import android.app.WindowContext;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -48,6 +48,7 @@
 import android.graphics.drawable.Icon;
 import android.graphics.drawable.InsetDrawable;
 import android.graphics.drawable.LayerDrawable;
+import android.hardware.display.DisplayManager;
 import android.media.MediaActionSound;
 import android.net.Uri;
 import android.os.Handler;
@@ -84,7 +85,6 @@
 import com.android.internal.logging.UiEventLogger;
 import com.android.systemui.R;
 import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.shared.system.QuickStepContract;
 
 import java.util.ArrayList;
@@ -245,12 +245,20 @@
     };
 
     @Inject
-    public GlobalScreenshot(
-            Context context, @Main Resources resources,
+    public GlobalScreenshot(Context context,
             ScreenshotSmartActions screenshotSmartActions,
             ScreenshotNotificationsController screenshotNotificationsController,
             UiEventLogger uiEventLogger) {
-        mContext = context;
+
+        // Create a visual (Window) context
+        // After this, our windowToken is available from mContext.getActivityToken()
+        final DisplayManager dm = context.getSystemService(DisplayManager.class);
+        mDisplay = dm.getDisplay(DEFAULT_DISPLAY);
+        Context displayContext = context.createDisplayContext(mDisplay);
+        mContext = new WindowContext(
+                displayContext, WindowManager.LayoutParams.TYPE_SCREENSHOT, null);
+        mWindowManager = mContext.getSystemService(WindowManager.class);
+
         mScreenshotSmartActions = screenshotSmartActions;
         mNotificationsController = screenshotNotificationsController;
         mUiEventLogger = uiEventLogger;
@@ -274,13 +282,13 @@
                         | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
                 PixelFormat.TRANSLUCENT);
         mWindowLayoutParams.setTitle("ScreenshotAnimation");
-        mWindowLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+        mWindowLayoutParams.layoutInDisplayCutoutMode =
+                WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
         mWindowLayoutParams.setFitInsetsTypes(0 /* types */);
-        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
-        mDisplay = mWindowManager.getDefaultDisplay();
         mDisplayMetrics = new DisplayMetrics();
         mDisplay.getRealMetrics(mDisplayMetrics);
 
+        final Resources resources = mContext.getResources();
         mCornerSizeX = resources.getDimensionPixelSize(R.dimen.global_screenshot_x_scale);
         mDismissDeltaY = resources.getDimensionPixelSize(R.dimen.screenshot_dismissal_height_delta);
 
@@ -1117,9 +1125,9 @@
      */
     private void setWindowFocusable(boolean focusable) {
         if (focusable) {
-            mWindowLayoutParams.flags &= ~FLAG_NOT_FOCUSABLE;
+            mWindowLayoutParams.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
         } else {
-            mWindowLayoutParams.flags |= FLAG_NOT_FOCUSABLE;
+            mWindowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
         }
         if (mScreenshotLayout.isAttachedToWindow()) {
             mWindowManager.updateViewLayout(mScreenshotLayout, mWindowLayoutParams);
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index 1bea72a..72034f8 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -50,6 +50,8 @@
 
 import java.util.ArrayList;
 
+import javax.inject.Inject;
+
 public class BrightnessController implements ToggleSlider.Listener {
     private static final String TAG = "StatusBar.BrightnessController";
     private static final int SLIDER_ANIMATION_DURATION = 3000;
@@ -475,4 +477,20 @@
         mSliderAnimator.start();
     }
 
+    /** Factory for creating a {@link BrightnessController}. */
+    public static class Factory {
+        private final Context mContext;
+        private final BroadcastDispatcher mBroadcastDispatcher;
+
+        @Inject
+        public Factory(Context context, BroadcastDispatcher broadcastDispatcher) {
+            mContext = context;
+            mBroadcastDispatcher = broadcastDispatcher;
+        }
+
+        /** Create a {@link BrightnessController} */
+        public BrightnessController create(ToggleSlider toggleSlider) {
+            return new BrightnessController(mContext, toggleSlider, mBroadcastDispatcher);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/MediaTransferManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/MediaTransferManager.java
deleted file mode 100644
index 1b1a51b..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/MediaTransferManager.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar;
-
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.GradientDrawable;
-import android.graphics.drawable.RippleDrawable;
-import android.service.notification.StatusBarNotification;
-import android.util.FeatureFlagUtils;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewParent;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import com.android.settingslib.bluetooth.LocalBluetoothManager;
-import com.android.settingslib.media.InfoMediaManager;
-import com.android.settingslib.media.LocalMediaManager;
-import com.android.settingslib.media.MediaDevice;
-import com.android.settingslib.widget.AdaptiveIcon;
-import com.android.systemui.Dependency;
-import com.android.systemui.media.dialog.MediaOutputDialogFactory;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Class for handling MediaTransfer state over a set of notifications.
- */
-public class MediaTransferManager {
-    private final Context mContext;
-    private final MediaOutputDialogFactory mMediaOutputDialogFactory;
-    private MediaDevice mDevice;
-    private List<View> mViews = new ArrayList<>();
-    private LocalMediaManager mLocalMediaManager;
-
-    private static final String TAG = "MediaTransferManager";
-
-    private final View.OnClickListener mOnClickHandler = new View.OnClickListener() {
-        @Override
-        public void onClick(View view) {
-            if (handleMediaTransfer(view)) {
-                return;
-            }
-        }
-
-        private boolean handleMediaTransfer(View view) {
-            if (view.findViewById(com.android.internal.R.id.media_seamless) == null) {
-                return false;
-            }
-
-            ViewParent parent = view.getParent();
-            StatusBarNotification statusBarNotification =
-                    getRowForParent(parent).getEntry().getSbn();
-            mMediaOutputDialogFactory.create(statusBarNotification.getPackageName(), true);
-            return true;
-        }
-    };
-
-    private final LocalMediaManager.DeviceCallback mMediaDeviceCallback =
-            new LocalMediaManager.DeviceCallback() {
-        @Override
-        public void onDeviceListUpdate(List<MediaDevice> devices) {
-            MediaDevice currentDevice = mLocalMediaManager.getCurrentConnectedDevice();
-            // Check because this can be called several times while changing devices
-            if (mDevice == null || !mDevice.equals(currentDevice)) {
-                mDevice = currentDevice;
-                updateAllChips();
-            }
-        }
-
-        @Override
-        public void onSelectedDeviceStateChanged(MediaDevice device, int state) {
-            if (mDevice == null || !mDevice.equals(device)) {
-                mDevice = device;
-                updateAllChips();
-            }
-        }
-    };
-
-    public MediaTransferManager(Context context) {
-        mContext = context;
-        mMediaOutputDialogFactory = Dependency.get(MediaOutputDialogFactory.class);
-        LocalBluetoothManager lbm = Dependency.get(LocalBluetoothManager.class);
-        InfoMediaManager imm = new InfoMediaManager(mContext, null, null, lbm);
-        mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, null);
-    }
-
-    /**
-     * Mark a view as removed. If no views remain the media device listener will be unregistered.
-     * @param root
-     */
-    public void setRemoved(View root) {
-        if (!FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SEAMLESS_TRANSFER)
-                || mLocalMediaManager == null || root == null) {
-            return;
-        }
-        View view = root.findViewById(com.android.internal.R.id.media_seamless);
-        if (mViews.remove(view)) {
-            if (mViews.size() == 0) {
-                mLocalMediaManager.unregisterCallback(mMediaDeviceCallback);
-            }
-        } else {
-            Log.e(TAG, "Tried to remove unknown view " + view);
-        }
-    }
-
-    private ExpandableNotificationRow getRowForParent(ViewParent parent) {
-        while (parent != null) {
-            if (parent instanceof ExpandableNotificationRow) {
-                return ((ExpandableNotificationRow) parent);
-            }
-            parent = parent.getParent();
-        }
-        return null;
-    }
-
-    /**
-     * apply the action button for MediaTransfer
-     *
-     * @param root  The parent container of the view.
-     * @param entry The entry of MediaTransfer action button.
-     */
-    public void applyMediaTransferView(ViewGroup root, NotificationEntry entry) {
-        if (!FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SEAMLESS_TRANSFER)
-                || mLocalMediaManager == null || root == null) {
-            return;
-        }
-
-        View view = root.findViewById(com.android.internal.R.id.media_seamless);
-        if (view == null) {
-            return;
-        }
-
-        view.setVisibility(View.VISIBLE);
-        view.setOnClickListener(mOnClickHandler);
-        if (!mViews.contains(view)) {
-            mViews.add(view);
-            if (mViews.size() == 1) {
-                mLocalMediaManager.registerCallback(mMediaDeviceCallback);
-            }
-        }
-
-        // Initial update
-        mLocalMediaManager.startScan();
-        mDevice = mLocalMediaManager.getCurrentConnectedDevice();
-        updateChip(view);
-    }
-
-    private void updateAllChips() {
-        for (View view : mViews) {
-            updateChip(view);
-        }
-    }
-
-    private void updateChip(View view) {
-        ExpandableNotificationRow enr = getRowForParent(view.getParent());
-        int fgColor = enr.getNotificationHeader().getOriginalIconColor();
-        ColorStateList fgTintList = ColorStateList.valueOf(fgColor);
-        int bgColor = enr.getCurrentBackgroundTint();
-
-        // Update outline color
-        LinearLayout viewLayout = (LinearLayout) view;
-        RippleDrawable bkgDrawable = (RippleDrawable) viewLayout.getBackground();
-        GradientDrawable rect = (GradientDrawable) bkgDrawable.getDrawable(0);
-        rect.setStroke(2, fgColor);
-        rect.setColor(bgColor);
-
-        ImageView iconView = view.findViewById(com.android.internal.R.id.media_seamless_image);
-        TextView deviceName = view.findViewById(com.android.internal.R.id.media_seamless_text);
-        deviceName.setTextColor(fgTintList);
-
-        if (mDevice != null) {
-            Drawable icon = mDevice.getIcon();
-            iconView.setVisibility(View.VISIBLE);
-            iconView.setImageTintList(fgTintList);
-
-            if (icon instanceof AdaptiveIcon) {
-                AdaptiveIcon aIcon = (AdaptiveIcon) icon;
-                aIcon.setBackgroundColor(bgColor);
-                iconView.setImageDrawable(aIcon);
-            } else {
-                iconView.setImageDrawable(icon);
-            }
-            deviceName.setText(mDevice.getName());
-        } else {
-            // Reset to default
-            iconView.setVisibility(View.GONE);
-            deviceName.setText(com.android.internal.R.string.ext_media_seamless_action);
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index ba88f62..fed27bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -304,7 +304,6 @@
             }
         }
     };
-    private boolean mForceUnlocked;
     private boolean mKeepInParent;
     private boolean mRemoved;
     private static final Property<ExpandableNotificationRow, Float> TRANSLATE_CONTENT =
@@ -1294,16 +1293,6 @@
         onAttachedChildrenCountChanged();
     }
 
-    public void setForceUnlocked(boolean forceUnlocked) {
-        mForceUnlocked = forceUnlocked;
-        if (mIsSummaryWithChildren) {
-            List<ExpandableNotificationRow> notificationChildren = getAttachedChildren();
-            for (ExpandableNotificationRow child : notificationChildren) {
-                child.setForceUnlocked(forceUnlocked);
-            }
-        }
-    }
-
     @Override
     public void dismiss(boolean refocusOnDismiss) {
         super.dismiss(refocusOnDismiss);
@@ -2183,7 +2172,7 @@
     }
 
     public boolean isUserLocked() {
-        return mUserLocked && !mForceUnlocked;
+        return mUserLocked;
     }
 
     public void setUserLocked(boolean userLocked) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index 8a644ed..3b55f7c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -44,7 +44,6 @@
 import com.android.internal.util.ContrastColorUtil;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.MediaTransferManager;
 import com.android.systemui.statusbar.RemoteInputController;
 import com.android.systemui.statusbar.SmartReplyController;
 import com.android.systemui.statusbar.TransformableView;
@@ -173,12 +172,10 @@
     private boolean mIsContentExpandable;
     private boolean mRemoteInputVisible;
     private int mUnrestrictedContentHeight;
-    private MediaTransferManager mMediaTransferManager;
 
     public NotificationContentView(Context context, AttributeSet attrs) {
         super(context, attrs);
         mHybridGroupManager = new HybridGroupManager(getContext());
-        mMediaTransferManager = new MediaTransferManager(getContext());
         mSmartReplyConstants = Dependency.get(SmartReplyConstants.class);
         mSmartReplyController = Dependency.get(SmartReplyController.class);
         initView();
@@ -1157,7 +1154,6 @@
             mHeadsUpWrapper.onContentUpdated(row);
         }
         applyRemoteInputAndSmartReply(entry);
-        applyMediaTransfer(entry);
         updateLegacy();
         mForceSelectNextLayout = true;
         mPreviousExpandedRemoteInputIntent = null;
@@ -1185,22 +1181,6 @@
         }
     }
 
-    private void applyMediaTransfer(final NotificationEntry entry) {
-        if (!entry.isMediaNotification()) {
-            return;
-        }
-
-        View bigContentView = mExpandedChild;
-        if (bigContentView != null && (bigContentView instanceof ViewGroup)) {
-            mMediaTransferManager.applyMediaTransferView((ViewGroup) bigContentView, entry);
-        }
-
-        View smallContentView = mContractedChild;
-        if (smallContentView != null && (smallContentView instanceof ViewGroup)) {
-            mMediaTransferManager.applyMediaTransferView((ViewGroup) smallContentView, entry);
-        }
-    }
-
     /**
      * Returns whether the {@link Notification} represented by entry has a free-form remote input.
      * Such an input can be used e.g. to implement smart reply buttons - by passing the replies
@@ -1662,11 +1642,9 @@
         }
         if (mExpandedWrapper != null) {
             mExpandedWrapper.setRemoved();
-            mMediaTransferManager.setRemoved(mExpandedChild);
         }
         if (mContractedWrapper != null) {
             mContractedWrapper.setRemoved();
-            mMediaTransferManager.setRemoved(mContractedChild);
         }
         if (mHeadsUpWrapper != null) {
             mHeadsUpWrapper.setRemoved();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index af6ac22..2767b7e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -38,9 +38,9 @@
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.keyguard.ViewMediatorCallback;
 import com.android.keyguard.dagger.KeyguardBouncerComponent;
-import com.android.keyguard.dagger.RootView;
 import com.android.systemui.DejankUtils;
 import com.android.systemui.biometrics.AuthController;
+import com.android.systemui.dagger.qualifiers.RootView;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.shared.system.SysUiStatsLog;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index e42c3dc..6ed092f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -671,14 +671,18 @@
 
         mIconController.setIconVisibility(mSlotCamera, showCamera);
         mIconController.setIconVisibility(mSlotMicrophone, showMicrophone);
-        if (mPrivacyItemController.getAllIndicatorsAvailable()) {
+        if (mPrivacyItemController.getAllIndicatorsAvailable()
+                || mPrivacyItemController.getLocationAvailable()) {
             mIconController.setIconVisibility(mSlotLocation, showLocation);
         }
     }
 
     @Override
     public void onLocationActiveChanged(boolean active) {
-        if (!mPrivacyItemController.getAllIndicatorsAvailable()) updateLocationFromController();
+        if (!mPrivacyItemController.getAllIndicatorsAvailable()
+                && !mPrivacyItemController.getLocationAvailable()) {
+            updateLocationFromController();
+        }
     }
 
     // Updates the status view based on the current state of location requests.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 88a387d..c7932bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -172,7 +172,7 @@
 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.qs.QSFragment;
-import com.android.systemui.qs.QSPanel;
+import com.android.systemui.qs.QSPanelController;
 import com.android.systemui.recents.ScreenPinningRequest;
 import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.shared.system.WindowManagerWrapper;
@@ -408,7 +408,7 @@
     protected NotificationPanelViewController mNotificationPanelViewController;
 
     // settings
-    private QSPanel mQSPanel;
+    private QSPanelController mQSPanelController;
 
     KeyguardIndicationController mKeyguardIndicationController;
 
@@ -1200,8 +1200,8 @@
             fragmentHostManager.addTagListener(QS.TAG, (tag, f) -> {
                 QS qs = (QS) f;
                 if (qs instanceof QSFragment) {
-                    mQSPanel = ((QSFragment) qs).getQsPanel();
-                    mQSPanel.setBrightnessMirror(mBrightnessMirrorController);
+                    mQSPanelController = ((QSFragment) qs).getQSPanelController();
+                    mQSPanelController.setBrightnessMirror(mBrightnessMirrorController);
                 }
             });
         }
@@ -1593,19 +1593,19 @@
     }
 
     public void addQsTile(ComponentName tile) {
-        if (mQSPanel != null && mQSPanel.getHost() != null) {
-            mQSPanel.getHost().addTile(tile);
+        if (mQSPanelController != null && mQSPanelController.getHost() != null) {
+            mQSPanelController.getHost().addTile(tile);
         }
     }
 
     public void remQsTile(ComponentName tile) {
-        if (mQSPanel != null && mQSPanel.getHost() != null) {
-            mQSPanel.getHost().removeTile(tile);
+        if (mQSPanelController != null && mQSPanelController.getHost() != null) {
+            mQSPanelController.getHost().removeTile(tile);
         }
     }
 
     public void clickTile(ComponentName tile) {
-        mQSPanel.clickTile(tile);
+        mQSPanelController.clickTile(tile);
     }
 
     /**
@@ -2197,7 +2197,7 @@
         if (!mUserSetup) return;
 
         if (subPanel != null) {
-            mQSPanel.openDetails(subPanel);
+            mQSPanelController.openDetails(subPanel);
         }
         mNotificationPanelViewController.expandWithQs();
 
@@ -2845,7 +2845,7 @@
                 resetUserExpandedStates();
             }
             else if (DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG.equals(action)) {
-                mQSPanel.showDeviceMonitoringDialog();
+                mQSPanelController.showDeviceMonitoringDialog();
             }
             Trace.endSection();
         }
@@ -2936,8 +2936,8 @@
      */
     void updateResources() {
         // Update the quick setting tiles
-        if (mQSPanel != null) {
-            mQSPanel.updateResources();
+        if (mQSPanelController != null) {
+            mQSPanelController.updateResources();
         }
 
         if (mStatusBarWindowController != null) {
@@ -3402,8 +3402,8 @@
 
         // Keyguard state has changed, but QS is not listening anymore. Make sure to update the tile
         // visibilities so next time we open the panel we know the correct height already.
-        if (mQSPanel != null) {
-            mQSPanel.refreshAllTiles();
+        if (mQSPanelController != null) {
+            mQSPanelController.refreshAllTiles();
         }
         mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
         releaseGestureWakeLock();
@@ -3987,7 +3987,8 @@
         PackageManager pm = mContext.getPackageManager();
         ResolveInfo resolveInfo = pm.resolveActivity(emergencyIntent, /*flags=*/0);
         if (resolveInfo == null) {
-            Log.wtf(TAG, "Couldn't find an app to process the emergency intent.");
+            // TODO(b/171084088) Upgrade log to wtf when we have default app in main branch.
+            Log.d(TAG, "Couldn't find an app to process the emergency intent.");
             return;
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index 9c3395f..c84589a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -18,11 +18,13 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.app.RemoteInput;
+import android.content.ClipData;
 import android.content.ClipDescription;
 import android.content.Context;
 import android.content.Intent;
@@ -43,6 +45,7 @@
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
+import android.view.OnReceiveContentCallback;
 import android.view.View;
 import android.view.ViewAnimationUtils;
 import android.view.ViewGroup;
@@ -57,9 +60,6 @@
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
-import androidx.core.view.inputmethod.InputConnectionCompat;
-import androidx.core.view.inputmethod.InputContentInfoCompat;
-
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.internal.statusbar.IStatusBarService;
@@ -73,7 +73,9 @@
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 import com.android.systemui.statusbar.phone.LightBarController;
 
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.Set;
 import java.util.function.Consumer;
 
 /**
@@ -313,6 +315,7 @@
         mRemoteInputs = remoteInputs;
         mRemoteInput = remoteInput;
         mEditText.setHint(mRemoteInput.getLabel());
+        mEditText.mSupportedMimeTypes = remoteInput.getAllowedDataTypes();
 
         mEntry.editedSuggestionInfo = editedSuggestionInfo;
         if (editedSuggestionInfo != null) {
@@ -571,6 +574,7 @@
         boolean mShowImeOnInputConnection;
         private LightBarController mLightBarController;
         UserHandle mUser;
+        private Set<String> mSupportedMimeTypes;
 
         public RemoteEditText(Context context, AttributeSet attrs) {
             super(context, attrs);
@@ -578,6 +582,40 @@
             mLightBarController = Dependency.get(LightBarController.class);
         }
 
+        @Override
+        protected void onFinishInflate() {
+            super.onFinishInflate();
+            setOnReceiveContentCallback(new OnReceiveContentCallback<View>() {
+                @Override
+                public boolean onReceiveContent(@NonNull View view, @NonNull Payload payload) {
+                    ClipData clip = payload.getClip();
+                    if (clip.getItemCount() == 0) {
+                        return false;
+                    }
+                    Uri contentUri = clip.getItemAt(0).getUri();
+                    ClipDescription description = clip.getDescription();
+                    String mimeType = null;
+                    if (description.getMimeTypeCount() > 0) {
+                        mimeType = description.getMimeType(0);
+                    }
+                    if (mimeType != null) {
+                        Intent dataIntent = mRemoteInputView
+                                .prepareRemoteInputFromData(mimeType, contentUri);
+                        mRemoteInputView.sendRemoteInput(dataIntent);
+                    }
+                    return true;
+                }
+
+                @NonNull
+                @Override
+                public Set<String> getSupportedMimeTypes(@NonNull View view) {
+                    return mSupportedMimeTypes != null
+                            ? mSupportedMimeTypes
+                            : Collections.emptySet();
+                }
+            });
+        }
+
         private void defocusIfNeeded(boolean animate) {
             if (mRemoteInputView != null && mRemoteInputView.mEntry.getRow().isChangingPosition()
                     || isTemporarilyDetached()) {
@@ -670,36 +708,7 @@
 
         @Override
         public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
-            // TODO: Pass RemoteInput data types to allow image insertion.
-            // String[] allowedDataTypes = mRemoteInputView.mRemoteInput.getAllowedDataTypes()
-            //     .toArray(new String[0]);
-            // EditorInfoCompat.setContentMimeTypes(outAttrs, allowedDataTypes);
-            final InputConnection inputConnection = super.onCreateInputConnection(outAttrs);
-
-            final InputConnectionCompat.OnCommitContentListener callback =
-                    new InputConnectionCompat.OnCommitContentListener() {
-                        @Override
-                        public boolean onCommitContent(
-                                InputContentInfoCompat inputContentInfoCompat, int i,
-                                Bundle bundle) {
-                            Uri contentUri = inputContentInfoCompat.getContentUri();
-                            ClipDescription description = inputContentInfoCompat.getDescription();
-                            String mimeType = null;
-                            if (description != null && description.getMimeTypeCount() > 0) {
-                                mimeType = description.getMimeType(0);
-                            }
-                            if (mimeType != null) {
-                                Intent dataIntent = mRemoteInputView.prepareRemoteInputFromData(
-                                        mimeType, contentUri);
-                                mRemoteInputView.sendRemoteInput(dataIntent);
-                            }
-                            return true;
-                        }
-                    };
-
-            InputConnection ic = inputConnection == null ? null :
-                    InputConnectionCompat.createWrapper(inputConnection, outAttrs, callback);
-
+            final InputConnection ic = super.onCreateInputConnection(outAttrs);
             Context userContext = null;
             try {
                 userContext = mContext.createPackageContextAsUser(
@@ -747,7 +756,6 @@
             } else {
                 setBackground(null);
             }
-
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvGlobalRootComponent.java b/packages/SystemUI/src/com/android/systemui/tv/TvGlobalRootComponent.java
index df741a0..89ab23b 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvGlobalRootComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvGlobalRootComponent.java
@@ -42,6 +42,12 @@
         TvGlobalRootComponent build();
     }
 
+    /**
+     * Builder for a WMComponent.
+     */
+    @Override
+    TvWMComponent.Builder getWMComponentBuilder();
+
     @Override
     TvSysUIComponent.Builder getSysUIComponent();
 }
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponentModule.java b/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponentModule.java
index 334bb01..9621e5f 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponentModule.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponentModule.java
@@ -19,7 +19,7 @@
 import dagger.Module;
 
 /**
- * Dagger module for including the WMComponent.
+ * Dagger module for including the SysUIComponent.
  */
 @Module(subcomponents = {TvSysUIComponent.class})
 public abstract class TvSysUIComponentModule {
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIBinder.java
index bde88b1..2c3ea4f 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIBinder.java
@@ -22,7 +22,7 @@
 import dagger.Binds;
 import dagger.Module;
 
-@Module(includes = TvPipModule.class)
+@Module
 interface TvSystemUIBinder {
     @Binds
     GlobalRootComponent bindGlobalRootComponent(TvGlobalRootComponent globalRootComponent);
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
index c5bb9c1..8ffc7cf 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
@@ -62,7 +62,6 @@
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
-import com.android.systemui.wmshell.TvWMShellModule;
 
 import javax.inject.Named;
 
@@ -75,8 +74,7 @@
  * overridden by the System UI implementation.
  */
 @Module(includes = {
-            QSModule.class,
-            TvWMShellModule.class,
+            QSModule.class
         },
         subcomponents = {
         })
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvWMComponent.java b/packages/SystemUI/src/com/android/systemui/tv/TvWMComponent.java
new file mode 100644
index 0000000..f678513
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvWMComponent.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.tv;
+
+import com.android.systemui.dagger.WMComponent;
+import com.android.systemui.dagger.WMSingleton;
+import com.android.systemui.wmshell.TvWMShellModule;
+
+import dagger.Subcomponent;
+
+
+/**
+ * Dagger Subcomponent for WindowManager.
+ */
+@WMSingleton
+@Subcomponent(modules = {TvWMShellModule.class})
+public interface TvWMComponent extends WMComponent {
+
+    /**
+     * Builder for a SysUIComponent.
+     */
+    @Subcomponent.Builder
+    interface Builder extends WMComponent.Builder {
+        TvWMComponent build();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/util/DeviceConfigProxy.java b/packages/SystemUI/src/com/android/systemui/util/DeviceConfigProxy.java
index 66f8f74..6b5556b 100644
--- a/packages/SystemUI/src/com/android/systemui/util/DeviceConfigProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/util/DeviceConfigProxy.java
@@ -23,13 +23,19 @@
 import android.provider.DeviceConfig;
 import android.provider.Settings;
 
+import com.android.systemui.dagger.SysUISingleton;
+
 import java.util.concurrent.Executor;
 
+import javax.inject.Inject;
+
 /**
  * Wrapper around DeviceConfig useful for testing.
  */
+@SysUISingleton
 public class DeviceConfigProxy {
 
+    @Inject
     public DeviceConfigProxy() {
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java
index 28343ed..5310b3f 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java
@@ -20,7 +20,7 @@
 import android.os.Handler;
 import android.view.LayoutInflater;
 
-import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.WMSingleton;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.WindowManagerShellWrapper;
 import com.android.wm.shell.common.DisplayController;
@@ -46,7 +46,7 @@
  */
 @Module
 public abstract class TvPipModule {
-    @SysUISingleton
+    @WMSingleton
     @Provides
     static Optional<Pip> providePip(
             Context context,
@@ -61,7 +61,7 @@
                         windowManagerShellWrapper));
     }
 
-    @SysUISingleton
+    @WMSingleton
     @Provides
     static PipControlsViewController providePipControlsViewController(
             PipControlsView pipControlsView, PipController pipController,
@@ -70,32 +70,33 @@
                 handler);
     }
 
-    @SysUISingleton
+    @WMSingleton
     @Provides
     static PipControlsView providePipControlsView(Context context) {
         return new PipControlsView(context, null);
     }
 
-    @SysUISingleton
+    @WMSingleton
     @Provides
     static PipNotification providePipNotification(Context context,
             PipController pipController) {
         return new PipNotification(context, pipController);
     }
 
-    @SysUISingleton
+    @WMSingleton
     @Provides
-    static PipBoundsHandler providePipBoundsHandler(Context context) {
-        return new PipBoundsHandler(context);
+    static PipBoundsHandler providePipBoundsHandler(Context context,
+            PipBoundsState pipBoundsState) {
+        return new PipBoundsHandler(context, pipBoundsState);
     }
 
-    @SysUISingleton
+    @WMSingleton
     @Provides
     static PipBoundsState providePipBoundsState() {
         return new PipBoundsState();
     }
 
-    @SysUISingleton
+    @WMSingleton
     @Provides
     static PipTaskOrganizer providePipTaskOrganizer(Context context,
             PipBoundsState pipBoundsState,
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java
index 7e1a2e8..294c749a 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java
@@ -20,7 +20,7 @@
 import android.os.Handler;
 import android.view.IWindowManager;
 
-import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.WMSingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.common.DisplayController;
@@ -40,10 +40,9 @@
  * Provides dependencies from {@link com.android.wm.shell} which could be customized among different
  * branches of SystemUI.
  */
-// TODO(b/162923491): Move most of these dependencies into WMSingleton scope.
 @Module(includes = {WMShellBaseModule.class, TvPipModule.class})
 public class TvWMShellModule {
-    @SysUISingleton
+    @WMSingleton
     @Provides
     static DisplayImeController provideDisplayImeController(IWindowManager wmService,
             DisplayController displayController, @Main Executor mainExecutor,
@@ -52,7 +51,7 @@
                 transactionPool);
     }
 
-    @SysUISingleton
+    @WMSingleton
     @Provides
     static SplitScreen provideSplitScreen(Context context,
             DisplayController displayController, SystemWindows systemWindows,
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
index 3c4c3fc..89ea9e2 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
@@ -65,7 +65,6 @@
 import com.android.systemui.tracing.ProtoTracer;
 import com.android.systemui.tracing.nano.SystemUiTraceProto;
 import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.common.DisplayImeController;
 import com.android.wm.shell.nano.WmShellTraceProto;
 import com.android.wm.shell.onehanded.OneHanded;
 import com.android.wm.shell.onehanded.OneHandedEvents;
@@ -101,19 +100,18 @@
 
     private final CommandQueue mCommandQueue;
     private final ConfigurationController mConfigurationController;
-    private final DisplayImeController mDisplayImeController;
     private final InputConsumerController mInputConsumerController;
     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     private final TaskStackChangeListeners mTaskStackChangeListeners;
     private final NavigationModeController mNavigationModeController;
     private final ScreenLifecycle mScreenLifecycle;
     private final SysUiState mSysUiState;
+    // TODO: This is only here because we need to dump state. Remove and replace with a dumper
+    //  interface.
+    private final ShellTaskOrganizer mShellTaskOrganizer;
     private final Optional<Pip> mPipOptional;
     private final Optional<SplitScreen> mSplitScreenOptional;
     private final Optional<OneHanded> mOneHandedOptional;
-    // Inject the organizer directly in case the optionals aren't loaded to depend on it. There
-    // are non-optional windowing features like FULLSCREEN.
-    private final ShellTaskOrganizer mShellTaskOrganizer;
     private final ProtoTracer mProtoTracer;
     private boolean mIsSysUiStateValid;
     private KeyguardUpdateMonitorCallback mSplitScreenKeyguardCallback;
@@ -126,7 +124,6 @@
             InputConsumerController inputConsumerController,
             KeyguardUpdateMonitor keyguardUpdateMonitor,
             TaskStackChangeListeners taskStackChangeListeners,
-            DisplayImeController displayImeController,
             NavigationModeController navigationModeController,
             ScreenLifecycle screenLifecycle,
             SysUiState sysUiState,
@@ -141,7 +138,6 @@
         mInputConsumerController = inputConsumerController;
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
         mTaskStackChangeListeners = taskStackChangeListeners;
-        mDisplayImeController = displayImeController;
         mNavigationModeController = navigationModeController;
         mScreenLifecycle = screenLifecycle;
         mSysUiState = sysUiState;
@@ -156,10 +152,6 @@
     @Override
     public void start() {
         mCommandQueue.addCallback(this);
-        // This is to prevent circular init problem by separating registration step out of its
-        // constructor. And make sure the initialization of DisplayImeController won't depend on
-        // specific feature anymore.
-        mDisplayImeController.startMonitorDisplays();
         mPipOptional.ifPresent(this::initPip);
         mSplitScreenOptional.ifPresent(this::initSplitScreen);
         mOneHandedOptional.ifPresent(this::initOneHanded);
@@ -201,6 +193,7 @@
             }
         });
 
+        // TODO: Move this into the shell
         // Handle for system task stack changes.
         mTaskStackChangeListeners.registerTaskStackListener(
                 new TaskStackChangeListener() {
@@ -417,6 +410,11 @@
             return;
         }
         // Dump WMShell stuff here if no commands were handled
+        mShellTaskOrganizer.dump(pw, "");
+        pw.println();
+        pw.println();
+        mPipOptional.ifPresent(pip -> pip.dump(pw));
+        mSplitScreenOptional.ifPresent(splitScreen -> splitScreen.dump(pw));
         mOneHandedOptional.ifPresent(oneHanded -> oneHanded.dump(pw));
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
index ac6e5de..b333f8b 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
@@ -20,21 +20,16 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.os.Handler;
-import android.util.DisplayMetrics;
 import android.view.IWindowManager;
 
 import com.android.internal.logging.UiEventLogger;
 import com.android.systemui.bubbles.Bubbles;
-import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.WMSingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.shared.system.InputConsumerController;
-import com.android.systemui.util.DeviceConfigProxy;
 import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.WindowManagerShellWrapper;
-import com.android.wm.shell.animation.FlingAnimationUtils;
 import com.android.wm.shell.common.AnimationThread;
 import com.android.wm.shell.common.DisplayController;
-import com.android.wm.shell.common.FloatingContentCoordinator;
 import com.android.wm.shell.common.HandlerExecutor;
 import com.android.wm.shell.common.SyncTransactionQueue;
 import com.android.wm.shell.common.SystemWindows;
@@ -58,41 +53,28 @@
  * Provides basic dependencies from {@link com.android.wm.shell}, the dependencies declared here
  * should be shared among different branches of SystemUI.
  */
-// TODO(b/162923491): Move most of these dependencies into WMSingleton scope.
 @Module
 public abstract class WMShellBaseModule {
-    @SysUISingleton
+    @WMSingleton
     @Provides
     static TransactionPool provideTransactionPool() {
         return new TransactionPool();
     }
 
-    @SysUISingleton
+    @WMSingleton
     @Provides
     static DisplayController provideDisplayController(Context context, @Main Handler handler,
             IWindowManager wmService) {
         return new DisplayController(context, handler, wmService);
     }
 
-    @SysUISingleton
-    @Provides
-    static DeviceConfigProxy provideDeviceConfigProxy() {
-        return new DeviceConfigProxy();
-    }
-
-    @SysUISingleton
+    @WMSingleton
     @Provides
     static InputConsumerController provideInputConsumerController() {
         return InputConsumerController.getPipInputConsumer();
     }
 
-    @SysUISingleton
-    @Provides
-    static FloatingContentCoordinator provideFloatingContentCoordinator() {
-        return new FloatingContentCoordinator();
-    }
-
-    @SysUISingleton
+    @WMSingleton
     @Provides
     static PipAppOpsListener providePipAppOpsListener(Context context,
             IActivityManager activityManager,
@@ -100,61 +82,46 @@
         return new PipAppOpsListener(context, activityManager, pipTouchHandler.getMotionHelper());
     }
 
-    @SysUISingleton
+    @WMSingleton
     @Provides
     static PipMediaController providePipMediaController(Context context,
             IActivityManager activityManager) {
         return new PipMediaController(context, activityManager);
     }
 
-    @SysUISingleton
+    @WMSingleton
     @Provides
     static PipUiEventLogger providePipUiEventLogger(UiEventLogger uiEventLogger,
             PackageManager packageManager) {
         return new PipUiEventLogger(uiEventLogger, packageManager);
     }
 
-    @SysUISingleton
+    @WMSingleton
     @Provides
     static PipSurfaceTransactionHelper providePipSurfaceTransactionHelper(Context context) {
         return new PipSurfaceTransactionHelper(context);
     }
 
-    @SysUISingleton
+    @WMSingleton
     @Provides
     static SystemWindows provideSystemWindows(DisplayController displayController,
             IWindowManager wmService) {
         return new SystemWindows(displayController, wmService);
     }
 
-    @SysUISingleton
+    @WMSingleton
     @Provides
     static SyncTransactionQueue provideSyncTransactionQueue(@Main Handler handler,
             TransactionPool pool) {
         return new SyncTransactionQueue(pool, handler);
     }
 
-    @SysUISingleton
+    @WMSingleton
     @Provides
     static ShellTaskOrganizer provideShellTaskOrganizer(SyncTransactionQueue syncQueue,
             @Main Handler handler, TransactionPool transactionPool) {
-        ShellTaskOrganizer organizer = new ShellTaskOrganizer(syncQueue, transactionPool,
+        return new ShellTaskOrganizer(syncQueue, transactionPool,
                 new HandlerExecutor(handler), AnimationThread.instance().getExecutor());
-        organizer.registerOrganizer();
-        return organizer;
-    }
-
-    @SysUISingleton
-    @Provides
-    static WindowManagerShellWrapper provideWindowManagerShellWrapper() {
-        return new WindowManagerShellWrapper();
-    }
-
-    @SysUISingleton
-    @Provides
-    static FlingAnimationUtils.Builder provideFlingAnimationUtilsBuilder(
-            DisplayMetrics displayMetrics) {
-        return new FlingAnimationUtils.Builder(displayMetrics);
     }
 
     @BindsOptionalOf
@@ -163,7 +130,7 @@
     @BindsOptionalOf
     abstract Bubbles optionalBubbles();
 
-    @SysUISingleton
+    @WMSingleton
     @Provides
     static Optional<OneHanded> provideOneHandedController(Context context,
             DisplayController displayController) {
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
index 81cb1f4..a6fe728 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
@@ -20,7 +20,7 @@
 import android.os.Handler;
 import android.view.IWindowManager;
 
-import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.WMSingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.WindowManagerShellWrapper;
@@ -54,10 +54,9 @@
  * Provides dependencies from {@link com.android.wm.shell} which could be customized among different
  * branches of SystemUI.
  */
-// TODO(b/162923491): Move most of these dependencies into WMSingleton scope.
 @Module(includes = WMShellBaseModule.class)
 public class WMShellModule {
-    @SysUISingleton
+    @WMSingleton
     @Provides
     static DisplayImeController provideDisplayImeController(IWindowManager wmService,
             DisplayController displayController, @Main Executor mainExecutor,
@@ -66,7 +65,7 @@
                 transactionPool);
     }
 
-    @SysUISingleton
+    @WMSingleton
     @Provides
     static SplitScreen provideSplitScreen(Context context,
             DisplayController displayController, SystemWindows systemWindows,
@@ -77,7 +76,7 @@
                 displayImeController, handler, transactionPool, shellTaskOrganizer, syncQueue);
     }
 
-    @SysUISingleton
+    @WMSingleton
     @Provides
     static Optional<Pip> providePip(Context context, DisplayController displayController,
             PipAppOpsListener pipAppOpsListener, PipBoundsHandler pipBoundsHandler,
@@ -90,26 +89,27 @@
                 windowManagerShellWrapper));
     }
 
-    @SysUISingleton
+    @WMSingleton
     @Provides
     static PipBoundsState providePipBoundsState() {
         return new PipBoundsState();
     }
 
-    @SysUISingleton
+    @WMSingleton
     @Provides
-    static PipBoundsHandler providePipBoundsHandler(Context context) {
-        return new PipBoundsHandler(context);
+    static PipBoundsHandler providesPipBoundsHandler(Context context,
+            PipBoundsState pipBoundsState) {
+        return new PipBoundsHandler(context, pipBoundsState);
     }
 
-    @SysUISingleton
+    @WMSingleton
     @Provides
     static PipMenuActivityController providePipMenuActivityController(Context context,
             PipMediaController pipMediaController, PipTaskOrganizer pipTaskOrganizer) {
         return new PipMenuActivityController(context, pipMediaController, pipTaskOrganizer);
     }
 
-    @SysUISingleton
+    @WMSingleton
     @Provides
     static PipTouchHandler providePipTouchHandler(Context context,
             PipMenuActivityController menuActivityController, PipBoundsHandler pipBoundsHandler,
@@ -121,7 +121,7 @@
                 pipBoundsState, pipTaskOrganizer, floatingContentCoordinator, pipUiEventLogger);
     }
 
-    @SysUISingleton
+    @WMSingleton
     @Provides
     static PipTaskOrganizer providePipTaskOrganizer(Context context,
             PipBoundsState pipBoundsState,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
index 86b1e61..9a77218 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
@@ -72,7 +72,7 @@
 
     @Before
     public void SysuiSetup() throws Exception {
-        SystemUIFactory.createFromConfig(mContext);
+        SystemUIFactory.createFromConfig(mContext, true);
         mDependency = new TestableDependency(
                 SystemUIFactory.getInstance().getSysUIComponent().createDependency());
         Dependency.setInstance(mDependency);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index b082d17..d9e9a8b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -45,6 +45,9 @@
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.content.pm.LauncherApps;
+import android.content.res.Configuration;
+import android.graphics.Insets;
+import android.graphics.Rect;
 import android.hardware.display.AmbientDisplayConfiguration;
 import android.hardware.face.FaceManager;
 import android.os.Handler;
@@ -80,10 +83,8 @@
 import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
-import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.LockscreenLockIconController;
 import com.android.systemui.statusbar.phone.NotificationShadeWindowControllerImpl;
 import com.android.systemui.statusbar.phone.NotificationShadeWindowView;
 import com.android.systemui.statusbar.phone.ShadeController;
@@ -178,8 +179,6 @@
     @Mock
     private ShadeController mShadeController;
     @Mock
-    private NotificationShelfComponent mNotificationShelfComponent;
-    @Mock
     private NotifPipeline mNotifPipeline;
     @Mock
     private FeatureFlags mFeatureFlagsOldPipeline;
@@ -191,11 +190,12 @@
     private IStatusBarService mStatusBarService;
     @Mock
     private LauncherApps mLauncherApps;
-    @Mock private LockscreenLockIconController mLockIconController;
-
-    @Mock private WindowManagerShellWrapper mWindowManagerShellWrapper;
-
-    @Mock private BubbleLogger mBubbleLogger;
+    @Mock
+    private WindowManagerShellWrapper mWindowManagerShellWrapper;
+    @Mock
+    private BubbleLogger mBubbleLogger;
+    @Mock
+    private BubblePositioner mPositioner;
 
     private BubbleData mBubbleData;
 
@@ -210,7 +210,6 @@
         mContext.addMockSystemService(FaceManager.class, mFaceManager);
         when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
 
-        // Bubbles get added to status bar window view
         mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl(mContext,
                 mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController,
                 mConfigurationController, mKeyguardViewMediator, mKeyguardBypassController,
@@ -241,6 +240,13 @@
                 mSysUiStateBubblesExpanded =
                         (sysUiFlags & QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED) != 0);
 
+        mBubbleData = new BubbleData(mContext, mBubbleLogger);
+
+        Rect availableRect = new Rect(0, 0, 1000, 5000);
+        when(mPositioner.getAvailableRect()).thenReturn(availableRect);
+        when(mPositioner.getOrientation()).thenReturn(Configuration.ORIENTATION_PORTRAIT);
+        when(mPositioner.getInsets()).thenReturn(Insets.of(0, 0, 0, 0));
+
         TestableNotificationInterruptStateProviderImpl interruptionStateProvider =
                 new TestableNotificationInterruptStateProviderImpl(mContext.getContentResolver(),
                         mock(PowerManager.class),
@@ -252,7 +258,6 @@
                         mock(HeadsUpManager.class),
                         mock(Handler.class)
                 );
-        mBubbleData = new BubbleData(mContext, mBubbleLogger);
         when(mFeatureFlagsOldPipeline.isNewNotifPipelineRenderingEnabled()).thenReturn(false);
         mBubbleController = new TestableBubbleController(
                 mContext,
@@ -279,7 +284,8 @@
                 mLauncherApps,
                 mBubbleLogger,
                 mock(Handler.class),
-                mock(ShellTaskOrganizer.class));
+                mock(ShellTaskOrganizer.class),
+                mPositioner);
         mBubbleController.setExpandListener(mBubbleExpandListener);
 
         // Get a reference to the BubbleController's entry listener
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/MultiWindowTaskListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/MultiWindowTaskListenerTest.java
deleted file mode 100644
index e7bf86e..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/MultiWindowTaskListenerTest.java
+++ /dev/null
@@ -1,181 +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.
- */
-
-package com.android.systemui.bubbles;
-
-import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_MULTI_WINDOW;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.verify;
-
-import android.app.ActivityManager;
-import android.os.Binder;
-import android.os.Handler;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.view.SurfaceControl;
-import android.window.WindowContainerToken;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.SysuiTestCase;
-import com.android.wm.shell.ShellTaskOrganizer;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper(setAsMainLooper = true)
-// TODO: Place in com.android.wm.shell vs. com.android.wm.shell.bubbles on shell migration.
-public class MultiWindowTaskListenerTest extends SysuiTestCase {
-
-    @Mock
-    ShellTaskOrganizer mOrganizer;
-    @Mock
-    MultiWindowTaskListener.Listener mPendingListener;
-    @Mock
-    SurfaceControl mLeash;
-    @Mock
-    ActivityManager.RunningTaskInfo mTaskInfo;
-    @Mock
-    WindowContainerToken mToken;
-
-    Handler mHandler;
-    MultiWindowTaskListener mTaskListener;
-    TestableLooper mTestableLooper;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
-        mTestableLooper = TestableLooper.get(this);
-        mHandler = new Handler(mTestableLooper.getLooper());
-
-        mTaskInfo = new ActivityManager.RunningTaskInfo();
-        mTaskInfo.token = mToken;
-
-        mTaskListener = new MultiWindowTaskListener(mHandler, mOrganizer);
-    }
-
-    private void addTaskAndVerify() {
-        final Binder cookie = new Binder();
-        mTaskInfo.addLaunchCookie(cookie);
-        mTaskListener.setPendingLaunchCookieListener(cookie, mPendingListener);
-        mTaskListener.onTaskAppeared(mTaskInfo, mLeash);
-        mTestableLooper.processAllMessages();
-        verify(mPendingListener).onTaskAppeared(eq(mTaskInfo), eq(mLeash));
-    }
-
-    @Test
-    public void testListenForMultiWindowMode() {
-        mTaskListener = new MultiWindowTaskListener(mHandler, mOrganizer);
-        verify(mOrganizer).addListener(eq(mTaskListener), eq(TASK_LISTENER_TYPE_MULTI_WINDOW));
-    }
-
-    @Test
-    public void testRemovePendingListener() {
-        addTaskAndVerify();
-        reset(mPendingListener);
-
-        mTaskListener.removeListener(mPendingListener);
-
-        // If it was removed, our pendingListener shouldn't get triggered:
-        mTaskListener.onTaskAppeared(mTaskInfo, mLeash);
-        mTaskListener.onTaskInfoChanged(mTaskInfo);
-        mTaskListener.onBackPressedOnTaskRoot(mTaskInfo);
-        mTaskListener.onTaskVanished(mTaskInfo);
-
-        mTestableLooper.processAllMessages();
-        verify(mPendingListener, never()).onTaskAppeared(any(), any());
-        verify(mPendingListener, never()).onTaskInfoChanged(any());
-        verify(mPendingListener, never()).onBackPressedOnTaskRoot(any());
-        verify(mPendingListener, never()).onTaskVanished(any());
-    }
-
-    @Test
-    public void testOnTaskAppeared() {
-        addTaskAndVerify();
-        verify(mOrganizer).setInterceptBackPressedOnTaskRoot(eq(mToken), eq(true));
-    }
-
-    @Test
-    public void testOnTaskAppeared_nullListener() {
-        mTaskListener.onTaskAppeared(mTaskInfo, mLeash);
-        mTestableLooper.processAllMessages();
-
-        verify(mOrganizer, never()).setInterceptBackPressedOnTaskRoot(any(), anyBoolean());
-        verify(mPendingListener, never()).onTaskAppeared(any(), any());
-    }
-
-    @Test
-    public void testOnTaskVanished() {
-        addTaskAndVerify();
-        mTaskListener.onTaskVanished(mTaskInfo);
-        mTestableLooper.processAllMessages();
-
-        verify(mPendingListener).onTaskVanished(eq(mTaskInfo));
-    }
-
-    @Test
-    public void testOnTaskVanished_neverAdded() {
-        mTaskListener.onTaskVanished(mTaskInfo);
-        mTestableLooper.processAllMessages();
-
-        verify(mPendingListener, never()).onTaskVanished(any());
-    }
-
-    @Test
-    public void testOnTaskInfoChanged() {
-        addTaskAndVerify();
-        mTaskListener.onTaskInfoChanged(mTaskInfo);
-        mTestableLooper.processAllMessages();
-
-        verify(mPendingListener).onTaskInfoChanged(eq(mTaskInfo));
-    }
-
-    @Test
-    public void testOnTaskInfoChanged_neverAdded() {
-        mTaskListener.onTaskInfoChanged(mTaskInfo);
-        mTestableLooper.processAllMessages();
-
-        verify(mPendingListener, never()).onTaskInfoChanged(any());
-    }
-
-    @Test
-    public void testOnBackPressedOnTaskRoot() {
-        addTaskAndVerify();
-        mTaskListener.onBackPressedOnTaskRoot(mTaskInfo);
-        mTestableLooper.processAllMessages();
-
-        verify(mPendingListener).onBackPressedOnTaskRoot(eq(mTaskInfo));
-    }
-
-    @Test
-    public void testOnBackPressedOnTaskRoot_neverAdded() {
-        mTaskListener.onBackPressedOnTaskRoot(mTaskInfo);
-        mTestableLooper.processAllMessages();
-
-        verify(mPendingListener, never()).onBackPressedOnTaskRoot(any());
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
index cbacd53..b9394ff 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
@@ -42,7 +42,9 @@
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.content.pm.LauncherApps;
-import android.content.res.Resources;
+import android.content.res.Configuration;
+import android.graphics.Insets;
+import android.graphics.Rect;
 import android.hardware.display.AmbientDisplayConfiguration;
 import android.hardware.face.FaceManager;
 import android.os.Handler;
@@ -170,8 +172,6 @@
     @Mock
     ColorExtractor.GradientColors mGradientColors;
     @Mock
-    private Resources mResources;
-    @Mock
     private ShadeController mShadeController;
     @Mock
     private NotificationShelfComponent mNotificationShelfComponent;
@@ -191,6 +191,8 @@
     private WindowManagerShellWrapper mWindowManagerShellWrapper;
     @Mock
     private BubbleLogger mBubbleLogger;
+    @Mock
+    private BubblePositioner mPositioner;
 
     private BubbleData mBubbleData;
 
@@ -223,7 +225,6 @@
                 },
                 mLockIconController);
 
-        // Bubbles get added to status bar window view
         mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl(mContext,
                 mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController,
                 mConfigurationController, mKeyguardViewMediator, mKeyguardBypassController,
@@ -243,6 +244,13 @@
         mZenModeConfig.suppressedVisualEffects = 0;
         when(mZenModeController.getConfig()).thenReturn(mZenModeConfig);
 
+        mBubbleData = new BubbleData(mContext, mBubbleLogger);
+
+        Rect availableRect = new Rect(0, 0, 1000, 5000);
+        when(mPositioner.getAvailableRect()).thenReturn(availableRect);
+        when(mPositioner.getOrientation()).thenReturn(Configuration.ORIENTATION_PORTRAIT);
+        when(mPositioner.getInsets()).thenReturn(Insets.of(0, 0, 0, 0));
+
         TestableNotificationInterruptStateProviderImpl interruptionStateProvider =
                 new TestableNotificationInterruptStateProviderImpl(mContext.getContentResolver(),
                         mock(PowerManager.class),
@@ -254,7 +262,6 @@
                         mock(HeadsUpManager.class),
                         mock(Handler.class)
                 );
-        mBubbleData = new BubbleData(mContext, mBubbleLogger);
         when(mFeatureFlagsNewPipeline.isNewNotifPipelineRenderingEnabled()).thenReturn(true);
         mBubbleController = new TestableBubbleController(
                 mContext,
@@ -281,7 +288,8 @@
                 mLauncherApps,
                 mBubbleLogger,
                 mock(Handler.class),
-                mock(ShellTaskOrganizer.class));
+                mock(ShellTaskOrganizer.class),
+                mPositioner);
         mBubbleController.addNotifCallback(mNotifCallback);
         mBubbleController.setExpandListener(mBubbleExpandListener);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TaskViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TaskViewTest.java
index 63d60f9..b13c6fc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TaskViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TaskViewTest.java
@@ -25,6 +25,7 @@
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
@@ -35,6 +36,7 @@
 import android.app.ActivityOptions;
 import android.app.PendingIntent;
 import android.content.Context;
+import android.os.Handler;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.view.SurfaceControl;
@@ -46,6 +48,7 @@
 
 import com.android.systemui.SysuiTestCase;
 import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.HandlerExecutor;
 
 import org.junit.After;
 import org.junit.Before;
@@ -53,6 +56,7 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
@@ -69,7 +73,7 @@
     @Mock
     ShellTaskOrganizer mOrganizer;
     @Mock
-    MultiWindowTaskListener mTaskListener;
+    HandlerExecutor mExecutor;
 
     SurfaceSession mSession;
     SurfaceControl mLeash;
@@ -86,13 +90,18 @@
 
         mContext = getContext();
 
-        when(mTaskListener.getTaskOrganizer()).thenReturn(mOrganizer);
         mTaskInfo = new ActivityManager.RunningTaskInfo();
         mTaskInfo.token = mToken;
         mTaskInfo.taskId = 314;
         mTaskInfo.taskDescription = mock(ActivityManager.TaskDescription.class);
 
-        mTaskView = new TaskView(mContext, mTaskListener);
+        doAnswer((InvocationOnMock invocationOnMock) -> {
+            final Runnable r = invocationOnMock.getArgument(0);
+            r.run();
+            return null;
+        }).when(mExecutor).execute(any());
+
+        mTaskView = new TaskView(mContext, mOrganizer, mExecutor);
         mTaskView.setListener(mViewListener);
     }
 
@@ -105,7 +114,7 @@
 
     @Test
     public void testSetPendingListener_throwsException() {
-        TaskView taskView = new TaskView(mContext, mTaskListener);
+        TaskView taskView = new TaskView(mContext, mOrganizer, mExecutor);
         taskView.setListener(mViewListener);
         try {
             taskView.setListener(mViewListener);
@@ -121,7 +130,7 @@
         ActivityOptions options = ActivityOptions.makeBasic();
         mTaskView.startActivity(mock(PendingIntent.class), null, options);
 
-        verify(mTaskListener).setPendingLaunchCookieListener(any(), eq(mTaskView));
+        verify(mOrganizer).setPendingLaunchCookieListener(any(), eq(mTaskView));
         assertThat(options.getLaunchWindowingMode()).isEqualTo(WINDOWING_MODE_MULTI_WINDOW);
         assertThat(options.getTaskAlwaysOnTop()).isTrue();
     }
@@ -189,7 +198,7 @@
         mTaskView.surfaceCreated(mock(SurfaceHolder.class));
         mTaskView.release();
 
-        verify(mTaskListener).removeListener(eq(mTaskView));
+        verify(mOrganizer).removeListener(eq(mTaskView));
         verify(mViewListener).onReleased();
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java
index 27c6fc1..aaeee16 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java
@@ -70,7 +70,8 @@
             LauncherApps launcherApps,
             BubbleLogger bubbleLogger,
             Handler mainHandler,
-            ShellTaskOrganizer shellTaskOrganizer) {
+            ShellTaskOrganizer shellTaskOrganizer,
+            BubblePositioner positioner) {
         super(context,
                 notificationShadeWindowController, statusBarStateController, shadeController,
                 data, Runnable::run, configurationController, interruptionStateProvider,
@@ -78,7 +79,7 @@
                 notifPipeline, featureFlags, dumpManager, floatingContentCoordinator,
                 dataRepository, sysUiState, notificationManager, statusBarService,
                 windowManager, windowManagerShellWrapper, launcherApps, bubbleLogger,
-                mainHandler, shellTaskOrganizer);
+                mainHandler, shellTaskOrganizer, positioner);
         setInflateSynchronously(true);
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
index 6a14863..a5bb8ea 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
@@ -17,26 +17,30 @@
 package com.android.systemui.bubbles.animation;
 
 import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 
+import android.annotation.SuppressLint;
 import android.content.res.Configuration;
 import android.content.res.Resources;
-import android.graphics.Point;
+import android.graphics.Insets;
 import android.graphics.PointF;
+import android.graphics.Rect;
 import android.testing.AndroidTestingRunner;
 import android.view.View;
+import android.view.WindowManager;
 import android.widget.FrameLayout;
 
 import androidx.dynamicanimation.animation.DynamicAnimation;
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.R;
+import com.android.systemui.bubbles.BubblePositioner;
 
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Mockito;
 import org.mockito.Spy;
 
 @SmallTest
@@ -46,47 +50,45 @@
     private int mDisplayWidth = 500;
     private int mDisplayHeight = 1000;
     private int mExpandedViewPadding = 10;
-    private int mOrientation = Configuration.ORIENTATION_PORTRAIT;
-    private float mLauncherGridDiff = 30f;
 
-    private Runnable mOnBubbleAnimatedOutAction = Mockito.mock(Runnable.class);
-
+    private Runnable mOnBubbleAnimatedOutAction = mock(Runnable.class);
     @Spy
-    private ExpandedAnimationController mExpandedController =
-            new ExpandedAnimationController(
-                    new Point(mDisplayWidth, mDisplayHeight) /* displaySize */,
-                    mExpandedViewPadding, mOrientation, mOnBubbleAnimatedOutAction);
+    ExpandedAnimationController mExpandedController;
 
     private int mStackOffset;
-    private float mBubblePaddingTop;
-    private float mBubbleSize;
-
     private PointF mExpansionPoint;
 
+    @SuppressLint("VisibleForTests")
     @Before
     public void setUp() throws Exception {
         super.setUp();
+
+        BubblePositioner positioner = new BubblePositioner(getContext(), mock(WindowManager.class));
+        positioner.update(Configuration.ORIENTATION_PORTRAIT,
+                Insets.of(0, 0, 0, 0),
+                new Rect(0, 0, mDisplayWidth, mDisplayHeight));
+        mExpandedController = new ExpandedAnimationController(positioner, mExpandedViewPadding,
+                mOnBubbleAnimatedOutAction);
+
         addOneMoreThanBubbleLimitBubbles();
         mLayout.setActiveController(mExpandedController);
 
         Resources res = mLayout.getResources();
         mStackOffset = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
-        mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
-        mBubbleSize = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
         mExpansionPoint = new PointF(100, 100);
     }
 
     @Test
     @Ignore
     public void testExpansionAndCollapse() throws InterruptedException {
-        Runnable afterExpand = Mockito.mock(Runnable.class);
+        Runnable afterExpand = mock(Runnable.class);
         mExpandedController.expandFromStack(afterExpand);
         waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
 
         testBubblesInCorrectExpandedPositions();
         verify(afterExpand).run();
 
-        Runnable afterCollapse = Mockito.mock(Runnable.class);
+        Runnable afterCollapse = mock(Runnable.class);
         mExpandedController.collapseBackToStack(mExpansionPoint, afterCollapse);
         waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
 
@@ -121,7 +123,7 @@
 
     /** Expand the stack and wait for animations to finish. */
     private void expand() throws InterruptedException {
-        mExpandedController.expandFromStack(Mockito.mock(Runnable.class));
+        mExpandedController.expandFromStack(mock(Runnable.class));
         waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
     }
 
@@ -141,51 +143,12 @@
     private void testBubblesInCorrectExpandedPositions() {
         // Check all the visible bubbles to see if they're in the right place.
         for (int i = 0; i < mLayout.getChildCount(); i++) {
-            assertEquals(getBubbleLeft(i),
+            float expectedPosition = mExpandedController.getBubbleXOrYForOrientation(i);
+            assertEquals(expectedPosition,
                     mLayout.getChildAt(i).getTranslationX(),
                     2f);
-            assertEquals(mExpandedController.getExpandedY(),
+            assertEquals(expectedPosition,
                     mLayout.getChildAt(i).getTranslationY(), 2f);
         }
     }
-
-    /**
-     * @param index Bubble index in row.
-     * @return Bubble left x from left edge of screen.
-     */
-    public float getBubbleLeft(int index) {
-        final float bubbleLeft = index * (mBubbleSize + getSpaceBetweenBubbles());
-        return getRowLeft() + bubbleLeft;
-    }
-
-    private float getRowLeft() {
-        if (mLayout == null) {
-            return 0;
-        }
-        int bubbleCount = mLayout.getChildCount();
-        final float totalBubbleWidth = bubbleCount * mBubbleSize;
-        final float totalGapWidth = (bubbleCount - 1) * getSpaceBetweenBubbles();
-        final float rowWidth = totalGapWidth + totalBubbleWidth;
-
-        final float centerScreen = mDisplayWidth / 2f;
-        final float halfRow = rowWidth / 2f;
-        final float rowLeft = centerScreen - halfRow;
-
-        return rowLeft;
-    }
-
-    /**
-     * @return Space between bubbles in row above expanded view.
-     */
-    private float getSpaceBetweenBubbles() {
-        final float rowMargins = (mExpandedViewPadding + mLauncherGridDiff) * 2;
-        final float maxRowWidth = mDisplayWidth - rowMargins;
-
-        final float totalBubbleWidth = mMaxBubbles * mBubbleSize;
-        final float totalGapWidth = maxRowWidth - totalBubbleWidth;
-
-        final int gapCount = mMaxBubbles - 1;
-        final float gapWidth = totalGapWidth / gapCount;
-        return gapWidth;
-    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
index 9242ce9..7d0abec 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
@@ -18,6 +18,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
@@ -33,6 +34,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.R;
+import com.android.systemui.bubbles.BubblePositioner;
 import com.android.wm.shell.common.FloatingContentCoordinator;
 
 import org.junit.Before;
@@ -40,7 +42,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.Mockito;
 
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -67,7 +68,7 @@
                     public int getAsInt() {
                         return mLayout.getChildCount();
                     }
-                }, Mockito.mock(Runnable.class)));
+                }, mock(Runnable.class)));
         mLayout.setActiveController(mStackController);
         addOneMoreThanBubbleLimitBubbles();
         mStackOffset = mLayout.getResources().getDimensionPixelSize(R.dimen.bubble_stack_offset);
@@ -306,7 +307,10 @@
                 FloatingContentCoordinator floatingContentCoordinator,
                 IntSupplier bubbleCountSupplier,
                 Runnable onBubbleAnimatedOutAction) {
-            super(floatingContentCoordinator, bubbleCountSupplier, onBubbleAnimatedOutAction);
+            super(floatingContentCoordinator,
+                    bubbleCountSupplier,
+                    onBubbleAnimatedOutAction,
+                    mock(BubblePositioner.class));
         }
 
         @Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsImeTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsImeTest.java
index 58959c4..bfc7935 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsImeTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsImeTest.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.globalactions;
 
+import static android.provider.Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD;
 import static android.view.WindowInsets.Type.ime;
 
 import static org.junit.Assert.assertEquals;
@@ -24,9 +25,11 @@
 import static org.junit.Assert.fail;
 
 import android.app.Activity;
+import android.content.ContentResolver;
 import android.os.Bundle;
 import android.os.PowerManager;
 import android.os.SystemClock;
+import android.provider.Settings;
 import android.view.View;
 import android.view.WindowInsets;
 import android.view.WindowInsetsController;
@@ -41,6 +44,7 @@
 import com.android.systemui.SysuiTestCase;
 
 import org.junit.After;
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 
@@ -54,8 +58,23 @@
     public ActivityTestRule<TestActivity> mActivityTestRule = new ActivityTestRule<>(
             TestActivity.class, false, false);
 
+    private int mOriginalShowImeWithHardKeyboard;
+
+    @Before
+    public void setUp() {
+        final ContentResolver contentResolver = mContext.getContentResolver();
+        mOriginalShowImeWithHardKeyboard = Settings.Secure.getInt(
+                contentResolver, SHOW_IME_WITH_HARD_KEYBOARD, 0);
+        // Forcibly shows IME even when hardware keyboard is connected.
+        // To change USER_SYSTEM settings, we have to use settings shell command.
+        executeShellCommand("settings put secure " + SHOW_IME_WITH_HARD_KEYBOARD + " 1");
+    }
+
     @After
     public void tearDown() {
+        // To restore USER_SYSTEM settings, we have to use settings shell command.
+        executeShellCommand("settings put secure "
+                + SHOW_IME_WITH_HARD_KEYBOARD + " " + mOriginalShowImeWithHardKeyboard);
         executeShellCommand("input keyevent HOME");
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt
index b81ab74..1f9862c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt
@@ -654,4 +654,21 @@
         fakeExecutor.runAllReady()
         verify(mockController).unregisterCallback(any())
     }
+
+    @Test
+    fun nullPlaybackStateUnregistersCallback() {
+        viewModel.updateController(mockController)
+        val captor = ArgumentCaptor.forClass(MediaController.Callback::class.java)
+        verify(mockController).registerCallback(captor.capture())
+        val callback = captor.value
+        // WHEN the callback receives a null state
+        callback.onPlaybackStateChanged(null)
+        with(fakeExecutor) {
+            advanceClockToNext()
+            runAllReady()
+        }
+        // THEN we unregister callback (as a result of clearing the controller)
+        fakeExecutor.runAllReady()
+        verify(mockController).unregisterCallback(any())
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt
index cb17829..cd94f84 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt
@@ -54,6 +54,7 @@
         private const val ALL_INDICATORS =
                 SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED
         private const val MIC_CAMERA = SystemUiDeviceConfigFlags.PROPERTY_MIC_CAMERA_ENABLED
+        private const val LOCATION = SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_ENABLED
     }
 
     @Mock
@@ -116,6 +117,15 @@
     }
 
     @Test
+    fun testLocationChanged() {
+        changeLocation(true)
+        executor.runAllReady()
+
+        verify(callback).onFlagLocationChanged(true)
+        assertTrue(privacyItemController.locationAvailable)
+    }
+
+    @Test
     fun testAllChanged() {
         changeAll(true)
         executor.runAllReady()
@@ -158,6 +168,14 @@
     }
 
     @Test
+    fun testLocation_listening() {
+        changeLocation(true)
+        executor.runAllReady()
+
+        verify(appOpsController).addCallback(eq(PrivacyItemController.OPS), any())
+    }
+
+    @Test
     @Ignore // TODO(b/168209929)
     fun testAllFalse_notListening() {
         changeAll(true)
@@ -205,6 +223,7 @@
     }
 
     private fun changeMicCamera(value: Boolean?) = changeProperty(MIC_CAMERA, value)
+    private fun changeLocation(value: Boolean?) = changeProperty(LOCATION, value)
     private fun changeAll(value: Boolean?) = changeProperty(ALL_INDICATORS, value)
 
     private fun changeProperty(name: String, value: Boolean?) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index e472cb2..90609cc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -16,7 +16,9 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import android.app.Fragment;
 import android.content.Context;
@@ -42,6 +44,7 @@
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.qs.dagger.QSFragmentComponent;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSFactoryImpl;
 import com.android.systemui.settings.UserTracker;
@@ -61,6 +64,8 @@
 import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
 import java.util.Optional;
 
@@ -71,6 +76,12 @@
 public class QSFragmentTest extends SysuiBaseFragmentTest {
 
     private MetricsLogger mMockMetricsLogger;
+    @Mock
+    private QSFragmentComponent.Factory mQsComponentFactory;
+    @Mock
+    private QSFragmentComponent mQsFragmentComponent;
+    @Mock
+    private QSPanelController mQSPanelController;
 
     public QSFragmentTest() {
         super(QSFragment.class);
@@ -80,6 +91,10 @@
     @Before
     @Ignore("failing")
     public void addLeakCheckDependencies() {
+        MockitoAnnotations.initMocks(this);
+        when(mQsComponentFactory.create(any(QSFragment.class))).thenReturn(mQsFragmentComponent);
+        when(mQsFragmentComponent.getQSPanelController()).thenReturn(mQSPanelController);
+
         mMockMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class);
         mContext.addMockSystemService(Context.LAYOUT_INFLATER_SERVICE,
                 new LayoutInflaterBuilder(mContext)
@@ -152,6 +167,6 @@
                 mock(QSTileHost.class),
                 mock(StatusBarStateController.class),
                 commandQueue,
-                mock(QSContainerImplController.Builder.class));
+                mQsComponentFactory);
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
new file mode 100644
index 0000000..bf0e084
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
@@ -0,0 +1,141 @@
+/*
+ * 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.systemui.qs;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.logging.testing.UiEventLoggerFake;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager;
+import com.android.systemui.media.MediaHost;
+import com.android.systemui.plugins.qs.QSTileView;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Collections;
+
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+@SmallTest
+public class QSPanelControllerBaseTest extends SysuiTestCase {
+
+    @Mock
+    private QSPanel mQSPanel;
+    @Mock
+    private QSTileHost mQSTileHost;
+    @Mock
+    private MediaHost mMediaHost;
+    @Mock
+    private MetricsLogger mMetricsLogger;
+    private UiEventLoggerFake mUiEventLogger = new UiEventLoggerFake();
+    private DumpManager mDumpManager = new DumpManager();
+    @Mock
+    QSTileImpl mQSTile;
+    @Mock
+    QSTileView mQSTileView;
+
+    private QSPanelControllerBase<QSPanel> mController;
+
+    /** Implementation needed to ensure we have a reflectively-available class name. */
+    private static class TestableQSPanelControllerBase extends QSPanelControllerBase<QSPanel> {
+        protected TestableQSPanelControllerBase(QSPanel view, QSTileHost host,
+                MetricsLogger metricsLogger,
+                UiEventLogger uiEventLogger, DumpManager dumpManager) {
+            super(view, host, metricsLogger, uiEventLogger, dumpManager);
+        }
+    }
+
+    @Before
+    public void setup() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        when(mQSPanel.getMediaHost()).thenReturn(mMediaHost);
+        when(mQSPanel.isAttachedToWindow()).thenReturn(true);
+        when(mQSPanel.getDumpableTag()).thenReturn("QSPanel");
+        when(mQSPanel.openPanelEvent()).thenReturn(QSEvent.QS_PANEL_EXPANDED);
+        when(mQSPanel.closePanelEvent()).thenReturn(QSEvent.QS_PANEL_COLLAPSED);
+        when(mQSTileHost.getTiles()).thenReturn(Collections.singleton(mQSTile));
+        when(mQSTileHost.createTileView(eq(mQSTile), anyBoolean())).thenReturn(mQSTileView);
+
+        mController = new TestableQSPanelControllerBase(mQSPanel, mQSTileHost,
+                mMetricsLogger, mUiEventLogger, mDumpManager);
+
+        mController.init();
+    }
+
+    @Test
+    public void testSetExpanded_Metrics() {
+        mController.setExpanded(true);
+        verify(mMetricsLogger).visibility(eq(MetricsEvent.QS_PANEL), eq(true));
+        assertEquals(1, mUiEventLogger.numLogs());
+        assertEquals(QSEvent.QS_PANEL_EXPANDED.getId(), mUiEventLogger.eventId(0));
+        mUiEventLogger.getLogs().clear();
+
+        mController.setExpanded(false);
+        verify(mMetricsLogger).visibility(eq(MetricsEvent.QS_PANEL), eq(false));
+        assertEquals(1, mUiEventLogger.numLogs());
+        assertEquals(QSEvent.QS_PANEL_COLLAPSED.getId(), mUiEventLogger.eventId(0));
+        mUiEventLogger.getLogs().clear();
+
+    }
+
+    @Test
+    public void testDump() {
+        String mockTileViewString = "Mock Tile View";
+        String mockTileString = "Mock Tile";
+        doAnswer(invocation -> {
+            PrintWriter pw = invocation.getArgument(1);
+            pw.println(mockTileString);
+            return null;
+        }).when(mQSTile).dump(any(FileDescriptor.class), any(PrintWriter.class),
+                any(String[].class));
+        when(mQSTileView.toString()).thenReturn(mockTileViewString);
+
+        StringWriter w = new StringWriter();
+        PrintWriter pw = new PrintWriter(w);
+        mController.dump(mock(FileDescriptor.class), pw, new String[]{});
+        String expected = "TestableQSPanelControllerBase:\n"
+                + "  Tile records:\n"
+                + "    " + mockTileString + "\n"
+                + "    " + mockTileViewString + "\n";
+        assertEquals(expected, w.getBuffer().toString());
+    }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
new file mode 100644
index 0000000..0ba0214
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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.systemui.qs;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.testing.UiEventLoggerFake;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager;
+import com.android.systemui.media.MediaHost;
+import com.android.systemui.plugins.qs.QSTileView;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.settings.BrightnessController;
+import com.android.systemui.settings.ToggleSlider;
+import com.android.systemui.tuner.TunerService;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Collections;
+
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+@SmallTest
+public class QSPanelControllerTest extends SysuiTestCase {
+
+    @Mock
+    private QSPanel mQSPanel;
+    @Mock
+    private QSTileHost mQSTileHost;
+    @Mock
+    private MediaHost mMediaHost;
+    @Mock
+    private MetricsLogger mMetricsLogger;
+    private UiEventLogger mUiEventLogger = new UiEventLoggerFake();
+    private DumpManager mDumpManager = new DumpManager();
+    @Mock
+    private TunerService mTunerService;
+    @Mock
+    private QSSecurityFooter mQSSecurityFooter;
+    @Mock
+    private BrightnessController.Factory mBrightnessControllerFactory;
+    @Mock
+    private BrightnessController mBrightnessController;
+    @Mock
+    QSTileImpl mQSTile;
+    @Mock
+    QSTileView mQSTileView;
+
+    private QSPanelController mController;
+
+    @Before
+    public void setup() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        when(mQSPanel.getMediaHost()).thenReturn(mMediaHost);
+        when(mQSPanel.isAttachedToWindow()).thenReturn(true);
+        when(mQSPanel.getDumpableTag()).thenReturn("QSPanel");
+        when(mQSTileHost.getTiles()).thenReturn(Collections.singleton(mQSTile));
+        when(mQSTileHost.createTileView(eq(mQSTile), anyBoolean())).thenReturn(mQSTileView);
+        when(mBrightnessControllerFactory.create(any(ToggleSlider.class)))
+                .thenReturn(mBrightnessController);
+
+        mController = new QSPanelController(mQSPanel, mQSSecurityFooter, mTunerService,
+                mQSTileHost, mDumpManager, mMetricsLogger, mUiEventLogger,
+                mBrightnessControllerFactory);
+
+        mController.init();
+    }
+
+    @Test
+    public void testOpenDetailsWithNonExistingTile_NoException() {
+        mController.openDetails("none");
+
+        verify(mQSPanel, never()).openDetails(any());
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java
index 4b7a268..e38d54b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java
@@ -14,12 +14,9 @@
 
 package com.android.systemui.qs;
 
-import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
@@ -36,19 +33,15 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.logging.testing.UiEventLoggerFake;
 import com.android.systemui.Dependency;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dump.DumpManager;
 import com.android.systemui.media.MediaHost;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.qs.QSTileView;
 import com.android.systemui.qs.customize.QSCustomizer;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
-import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.policy.SecurityController;
 import com.android.systemui.util.animation.DisappearParameters;
 import com.android.systemui.util.animation.UniqueObjectHostView;
@@ -59,9 +52,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.io.StringWriter;
 import java.util.Collections;
 
 @RunWith(AndroidTestingRunner.class)
@@ -79,9 +69,9 @@
     @Mock
     private QSTileImpl dndTile;
     @Mock
-    private BroadcastDispatcher mBroadcastDispatcher;
+    private QSTileImpl mNonTile;
     @Mock
-    private DumpManager mDumpManager;
+    private QSPanelControllerBase.TileRecord mDndTileRecord;
     @Mock
     private QSLogger mQSLogger;
     private ViewGroup mParentView;
@@ -93,9 +83,8 @@
     private MediaHost mMediaHost;
     @Mock
     private ActivityStarter mActivityStarter;
-    @Mock(stubOnly = true)
-    private UserTracker mUserTracker;
     private UiEventLoggerFake mUiEventLogger;
+    private String mCachedSpecs = "";
 
     @Before
     public void setup() throws Exception {
@@ -109,12 +98,13 @@
         mContext.addMockSystemService(Context.USER_SERVICE, mock(UserManager.class));
         when(mMediaHost.getHostView()).thenReturn(new UniqueObjectHostView(getContext()));
         when(mMediaHost.getDisappearParameters()).thenReturn(new DisappearParameters());
+        mDndTileRecord.tile = dndTile;
+        mDndTileRecord.tileView = mQSTileView;
 
         mUiEventLogger = new UiEventLoggerFake();
         mTestableLooper.runWithLooper(() -> {
             mMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class);
-            mQsPanel = new QSPanel(mContext, null, mDumpManager, mBroadcastDispatcher,
-                    mQSLogger, mMediaHost, mUiEventLogger, mUserTracker);
+            mQsPanel = new QSPanel(mContext, null, mQSLogger, mMediaHost, mUiEventLogger);
             mQsPanel.onFinishInflate();
             // Provides a parent with non-zero size for QSPanel
             mParentView = new FrameLayout(mContext);
@@ -124,8 +114,8 @@
             when(mHost.getTiles()).thenReturn(Collections.emptyList());
             when(mHost.createTileView(any(), anyBoolean())).thenReturn(mQSTileView);
 
-            mQsPanel.setHost(mHost, mCustomizer);
-            mQsPanel.addTile(dndTile, true);
+            mQsPanel.setCustomizer(mCustomizer);
+            mQsPanel.addTile(mDndTileRecord);
             mQsPanel.setCallback(mCallback);
         });
     }
@@ -133,25 +123,16 @@
     @Test
     public void testSetExpanded_Metrics() {
         mQsPanel.setExpanded(true);
-        verify(mMetricsLogger).visibility(eq(MetricsEvent.QS_PANEL), eq(true));
         verify(mQSLogger).logPanelExpanded(true, mQsPanel.getDumpableTag());
-        assertEquals(1, mUiEventLogger.numLogs());
-        assertEquals(QSEvent.QS_PANEL_EXPANDED.getId(), mUiEventLogger.eventId(0));
-        mUiEventLogger.getLogs().clear();
 
         mQsPanel.setExpanded(false);
-        verify(mMetricsLogger).visibility(eq(MetricsEvent.QS_PANEL), eq(false));
         verify(mQSLogger).logPanelExpanded(false, mQsPanel.getDumpableTag());
-        assertEquals(1, mUiEventLogger.numLogs());
-        assertEquals(QSEvent.QS_PANEL_COLLAPSED.getId(), mUiEventLogger.eventId(0));
-        mUiEventLogger.getLogs().clear();
-
     }
 
     @Test
     public void testOpenDetailsWithExistingTile_NoException() {
         mTestableLooper.processAllMessages();
-        mQsPanel.openDetails("dnd");
+        mQsPanel.openDetails(dndTile);
         mTestableLooper.processAllMessages();
 
         verify(mCallback).onShowingDetail(any(), anyInt(), anyInt());
@@ -159,53 +140,19 @@
 
     @Test
     public void setListening() {
-        when(dndTile.getTileSpec()).thenReturn("dnd");
-
-        mQsPanel.setListening(true);
+        mQsPanel.setListening(true, "dnd");
         verify(mQSLogger).logAllTilesChangeListening(true, mQsPanel.getDumpableTag(), "dnd");
 
-        mQsPanel.setListening(false);
+        mQsPanel.setListening(false, "dnd");
         verify(mQSLogger).logAllTilesChangeListening(false, mQsPanel.getDumpableTag(), "dnd");
     }
 
-/*    @Test
+    @Test
     public void testOpenDetailsWithNullParameter_NoException() {
         mTestableLooper.processAllMessages();
         mQsPanel.openDetails(null);
         mTestableLooper.processAllMessages();
 
         verify(mCallback, never()).onShowingDetail(any(), anyInt(), anyInt());
-    }*/
-
-    @Test
-    public void testOpenDetailsWithNonExistingTile_NoException() {
-        mTestableLooper.processAllMessages();
-        mQsPanel.openDetails("invalid-name");
-        mTestableLooper.processAllMessages();
-
-        verify(mCallback, never()).onShowingDetail(any(), anyInt(), anyInt());
     }
-
-    @Test
-    public void testDump() {
-        String mockTileViewString = "Mock Tile View";
-        String mockTileString = "Mock Tile";
-        doAnswer(invocation -> {
-            PrintWriter pw = invocation.getArgument(1);
-            pw.println(mockTileString);
-            return null;
-        }).when(dndTile).dump(any(FileDescriptor.class), any(PrintWriter.class),
-                any(String[].class));
-        when(mQSTileView.toString()).thenReturn(mockTileViewString);
-
-        StringWriter w = new StringWriter();
-        PrintWriter pw = new PrintWriter(w);
-        mQsPanel.dump(mock(FileDescriptor.class), pw, new String[]{});
-        String expected = "QSPanel:\n"
-                + "  Tile records:\n"
-                + "    " + mockTileString + "\n"
-                + "    " + mockTileViewString + "\n";
-        assertEquals(expected, w.getBuffer().toString());
-    }
-
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
index fef47bd..6c7c20a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
@@ -57,8 +57,8 @@
                 mContext.getResources().getDimensionPixelSize(R.dimen.qs_tile_margin_horizontal) * 3;
     }
 
-    private QSPanel.TileRecord createTileRecord() {
-        QSPanel.TileRecord tileRecord = new QSPanel.TileRecord();
+    private QSPanelControllerBase.TileRecord createTileRecord() {
+        QSPanelControllerBase.TileRecord tileRecord = new QSPanelControllerBase.TileRecord();
         tileRecord.tile = mock(QSTile.class);
         tileRecord.tileView = spy(new QSTileView(mContext, new QSIconViewImpl(mContext)));
         return tileRecord;
@@ -66,14 +66,14 @@
 
     @Test
     public void testAddTile_CallsSetListeningOnTile() {
-        QSPanel.TileRecord tileRecord = createTileRecord();
+        QSPanelControllerBase.TileRecord tileRecord = createTileRecord();
         mTileLayout.addTile(tileRecord);
         verify(tileRecord.tile, times(1)).setListening(mTileLayout, false);
     }
 
     @Test
     public void testSetListening_CallsSetListeningOnTile() {
-        QSPanel.TileRecord tileRecord = createTileRecord();
+        QSPanelControllerBase.TileRecord tileRecord = createTileRecord();
         mTileLayout.addTile(tileRecord);
         mTileLayout.setListening(true);
         verify(tileRecord.tile, times(1)).setListening(mTileLayout, true);
@@ -81,7 +81,7 @@
 
     @Test
     public void testSetListening_SameValueIsNoOp() {
-        QSPanel.TileRecord tileRecord = createTileRecord();
+        QSPanelControllerBase.TileRecord tileRecord = createTileRecord();
         mTileLayout.addTile(tileRecord);
         mTileLayout.setListening(false);
         verify(tileRecord.tile, times(1)).setListening(any(), anyBoolean());
@@ -89,7 +89,7 @@
 
     @Test
     public void testSetListening_ChangesValueForAddingFutureTiles() {
-        QSPanel.TileRecord tileRecord = createTileRecord();
+        QSPanelControllerBase.TileRecord tileRecord = createTileRecord();
         mTileLayout.setListening(true);
         mTileLayout.addTile(tileRecord);
         verify(tileRecord.tile, times(1)).setListening(mTileLayout, true);
@@ -97,7 +97,7 @@
 
     @Test
     public void testRemoveTile_CallsSetListeningFalseOnTile() {
-        QSPanel.TileRecord tileRecord = createTileRecord();
+        QSPanelControllerBase.TileRecord tileRecord = createTileRecord();
         mTileLayout.setListening(true);
         mTileLayout.addTile(tileRecord);
         mTileLayout.removeTile(tileRecord);
@@ -106,8 +106,8 @@
 
     @Test
     public void testRemoveAllViews_CallsSetListeningFalseOnAllTiles() {
-        QSPanel.TileRecord tileRecord1 = createTileRecord();
-        QSPanel.TileRecord tileRecord2 = createTileRecord();
+        QSPanelControllerBase.TileRecord tileRecord1 = createTileRecord();
+        QSPanelControllerBase.TileRecord tileRecord2 = createTileRecord();
         mTileLayout.setListening(true);
         mTileLayout.addTile(tileRecord1);
         mTileLayout.addTile(tileRecord2);
@@ -118,7 +118,7 @@
 
     @Test
     public void testMeasureLayout_CallsLayoutOnTile() {
-        QSPanel.TileRecord tileRecord = createTileRecord();
+        QSPanelControllerBase.TileRecord tileRecord = createTileRecord();
         mTileLayout.addTile(tileRecord);
         mTileLayout.measure(mLayoutSizeForOneTile, mLayoutSizeForOneTile);
         mTileLayout.layout(0, 0, mLayoutSizeForOneTile, mLayoutSizeForOneTile);
@@ -127,8 +127,8 @@
 
     @Test
     public void testMeasureLayout_CallsLayoutOnTilesWithNeighboredBounds() {
-        QSPanel.TileRecord tileRecord1 = createTileRecord();
-        QSPanel.TileRecord tileRecord2 = createTileRecord();
+        QSPanelControllerBase.TileRecord tileRecord1 = createTileRecord();
+        QSPanelControllerBase.TileRecord tileRecord2 = createTileRecord();
         mTileLayout.addTile(tileRecord1);
         mTileLayout.addTile(tileRecord2);
         mTileLayout.measure(mLayoutSizeForOneTile * 2, mLayoutSizeForOneTile * 2);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureTest.java
index e7ef64e..2b3ca7c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureTest.java
@@ -25,8 +25,8 @@
 import android.testing.AndroidTestingRunner;
 import android.util.Log;
 import android.view.Display;
-import android.view.IScrollCaptureClient;
-import android.view.IScrollCaptureController;
+import android.view.IScrollCaptureCallbacks;
+import android.view.IScrollCaptureConnection;
 import android.view.IWindowManager;
 import android.view.WindowManagerGlobal;
 
@@ -65,19 +65,20 @@
         final CountDownLatch latch = new CountDownLatch(1);
         try {
             wms.requestScrollCapture(Display.DEFAULT_DISPLAY, null, -1,
-                    new IScrollCaptureController.Stub() {
+                    new IScrollCaptureCallbacks.Stub() {
                         @Override
-                        public void onClientConnected(
-                                IScrollCaptureClient client, Rect scrollBounds,
+                        public void onConnected(
+                                IScrollCaptureConnection connection, Rect scrollBounds,
                                 Point positionInWindow) {
                             Log.d(TAG,
-                                    "client connected: " + client + "[scrollBounds= " + scrollBounds
-                                            + ", positionInWindow=" + positionInWindow + "]");
+                                    "client connected: " + connection + "[scrollBounds= "
+                                            + scrollBounds + ", "
+                                            + "positionInWindow=" + positionInWindow + "]");
                             latch.countDown();
                         }
 
                         @Override
-                        public void onClientUnavailable() {
+                        public void onUnavailable() {
                         }
 
                         @Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
index a58f1fd..dd7f263 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
@@ -27,6 +27,7 @@
 
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.systemui.SystemUIFactory;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.keyguard.ScreenLifecycle;
 import com.android.systemui.model.SysUiState;
@@ -53,6 +54,7 @@
 import org.mockito.MockitoAnnotations;
 
 import java.util.Optional;
+import java.util.concurrent.ExecutionException;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -64,7 +66,6 @@
     @Mock ConfigurationController mConfigurationController;
     @Mock KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     @Mock TaskStackChangeListeners mTaskStackChangeListeners;
-    @Mock DisplayImeController mDisplayImeController;
     @Mock InputConsumerController mMockInputConsumerController;
     @Mock NavigationModeController mNavigationModeController;
     @Mock ScreenLifecycle mScreenLifecycle;
@@ -84,21 +85,13 @@
 
         mWMShell = new WMShell(mContext, mCommandQueue, mConfigurationController,
                 mInputConsumerController, mKeyguardUpdateMonitor, mTaskStackChangeListeners,
-                mDisplayImeController, mNavigationModeController, mScreenLifecycle, mSysUiState,
-                Optional.of(mPip), Optional.of(mSplitScreen), Optional.of(mOneHanded),
-                mTaskOrganizer, mProtoTracer);
+                mNavigationModeController, mScreenLifecycle, mSysUiState, Optional.of(mPip),
+                Optional.of(mSplitScreen), Optional.of(mOneHanded), mTaskOrganizer, mProtoTracer);
 
         when(mPip.getPipTouchHandler()).thenReturn(mPipTouchHandler);
     }
 
     @Test
-    public void start_startsMonitorDisplays() {
-        mWMShell.start();
-
-        verify(mDisplayImeController).startMonitorDisplays();
-    }
-
-    @Test
     public void initPip_registersCommandQueueCallback() {
         mWMShell.initPip(mPip);
 
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java b/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
index 9fc1d7e..4f616cd 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
@@ -80,11 +80,6 @@
     private final SparseArray<LinkAddress> mCachedAddresses;
 
     public PrivateAddressCoordinator(Context context, TetheringConfiguration config) {
-        this(context, config, new ArrayList<>(Arrays.asList(new IpPrefix("192.168.0.0/16"))));
-    }
-
-    public PrivateAddressCoordinator(Context context, TetheringConfiguration config,
-            List<IpPrefix> prefixPools) {
         mDownstreams = new ArraySet<>();
         mUpstreamPrefixMap = new ArrayMap<>();
         mConnectivityMgr = (ConnectivityManager) context.getSystemService(
@@ -95,7 +90,11 @@
         mCachedAddresses.put(TETHERING_BLUETOOTH, new LinkAddress(LEGACY_BLUETOOTH_IFACE_ADDRESS));
         mCachedAddresses.put(TETHERING_WIFI_P2P, new LinkAddress(LEGACY_WIFI_P2P_IFACE_ADDRESS));
 
-        mTetheringPrefixes = prefixPools;
+        mTetheringPrefixes = new ArrayList<>(Arrays.asList(new IpPrefix("192.168.0.0/16")));
+        if (config.isSelectAllPrefixRangeEnabled()) {
+            mTetheringPrefixes.add(new IpPrefix("172.16.0.0/12"));
+            mTetheringPrefixes.add(new IpPrefix("10.0.0.0/8"));
+        }
     }
 
     /**
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
index 5783805..799637c 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
@@ -40,7 +40,6 @@
 import java.util.Collection;
 import java.util.StringJoiner;
 
-
 /**
  * A utility class to encapsulate the various tethering configuration elements.
  *
@@ -88,6 +87,13 @@
             "use_legacy_wifi_p2p_dedicated_ip";
 
     /**
+     * Flag use to enable select all prefix ranges feature.
+     * TODO: Remove this flag if there are no problems after M-2020-12 rolls out.
+     */
+    public static final String TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES =
+            "tether_enable_select_all_prefix_ranges";
+
+    /**
      * Default value that used to periodic polls tether offload stats from tethering offload HAL
      * to make the data warnings work.
      */
@@ -118,6 +124,8 @@
     private final boolean mEnableBpfOffload;
     private final boolean mEnableWifiP2pDedicatedIp;
 
+    private final boolean mEnableSelectAllPrefixRange;
+
     public TetheringConfiguration(Context ctx, SharedLog log, int id) {
         final SharedLog configLog = log.forSubComponent("config");
 
@@ -164,6 +172,11 @@
                 R.bool.config_tether_enable_legacy_wifi_p2p_dedicated_ip,
                 false /* defaultValue */);
 
+        // Flags should normally not be booleans, but this is a kill-switch flag that is only used
+        // to turn off the feature, so binary rollback problems do not apply.
+        mEnableSelectAllPrefixRange = getDeviceConfigBoolean(
+                TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES, true /* defaultValue */);
+
         configLog.log(toString());
     }
 
@@ -249,6 +262,9 @@
 
         pw.print("enableWifiP2pDedicatedIp: ");
         pw.println(mEnableWifiP2pDedicatedIp);
+
+        pw.print("mEnableSelectAllPrefixRange: ");
+        pw.println(mEnableSelectAllPrefixRange);
     }
 
     /** Returns the string representation of this object.*/
@@ -310,6 +326,10 @@
         return mEnableBpfOffload;
     }
 
+    public boolean isSelectAllPrefixRangeEnabled() {
+        return mEnableSelectAllPrefixRange;
+    }
+
     private static Collection<Integer> getUpstreamIfaceTypes(Resources res, boolean dunRequired) {
         final int[] ifaceTypes = res.getIntArray(R.array.config_tether_upstream_types);
         final ArrayList<Integer> upstreamIfaceTypes = new ArrayList<>(ifaceTypes.length);
diff --git a/packages/Tethering/tests/mts/Android.bp b/packages/Tethering/tests/mts/Android.bp
new file mode 100644
index 0000000..f925b0a
--- /dev/null
+++ b/packages/Tethering/tests/mts/Android.bp
@@ -0,0 +1,56 @@
+// 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.
+
+android_test {
+    // This tests for functionality that is not required for devices that
+    // don't use Tethering mainline module.
+    name: "MtsTetheringTest",
+
+    libs: [
+        "android.test.base",
+    ],
+
+    srcs: [
+        "src/**/*.java",
+    ],
+
+    static_libs: [
+        "androidx.test.rules",
+        // mockito-target-extended-minus-junit4 used in this lib have dependency with
+        // jni_libs libdexmakerjvmtiagent and libstaticjvmtiagent.
+        "cts-net-utils",
+        // This is needed for androidx.test.runner.AndroidJUnitRunner.
+        "ctstestrunner-axt",
+        "junit",
+        "junit-params",
+    ],
+
+    jni_libs: [
+        // For mockito extended which is pulled in from -net-utils -> net-tests-utils
+        // (mockito-target-extended-minus-junit4).
+        "libdexmakerjvmtiagent",
+        "libstaticjvmtiagent",
+    ],
+
+    platform_apis: true,
+
+    // Tag this module as a mts test artifact
+    test_suites: [
+        "general-tests",
+        "mts",
+    ],
+
+    // Include both the 32 and 64 bit versions
+    compile_multilib: "both",
+}
diff --git a/packages/Tethering/tests/mts/AndroidManifest.xml b/packages/Tethering/tests/mts/AndroidManifest.xml
new file mode 100644
index 0000000..6d2abca
--- /dev/null
+++ b/packages/Tethering/tests/mts/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.tethering.mts">
+
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.INTERNET"/>
+
+    <application android:debuggable="true">
+        <uses-library android:name="android.test.runner" />
+    </application>
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="android.tethering.mts"
+                     android:label="MTS tests of android.tethering">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
+
+</manifest>
diff --git a/packages/Tethering/tests/mts/AndroidTest.xml b/packages/Tethering/tests/mts/AndroidTest.xml
new file mode 100644
index 0000000..80788df
--- /dev/null
+++ b/packages/Tethering/tests/mts/AndroidTest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for MTS Tethering test cases">
+    <option name="test-suite-tag" value="mts" />
+    <option name="config-descriptor:metadata" key="component" value="networking" />
+    <!-- Instant app do not have INTERNET permission. -->
+    <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+    <!-- Feature is not backed by native code. -->
+    <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+    <!-- Allow running this against a secondary user. -->
+    <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="MtsTetheringTest.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.tethering.mts" />
+    </test>
+
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <option name="mainline-module-package-name" value="com.google.android.tethering" />
+    </object>
+</configuration>
diff --git a/packages/Tethering/tests/mts/src/android/tethering/mts/TetheringModuleTest.java b/packages/Tethering/tests/mts/src/android/tethering/mts/TetheringModuleTest.java
new file mode 100644
index 0000000..7ffe37a
--- /dev/null
+++ b/packages/Tethering/tests/mts/src/android/tethering/mts/TetheringModuleTest.java
@@ -0,0 +1,183 @@
+/*
+ * 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.tethering.mts;
+
+import static android.Manifest.permission.MANAGE_TEST_NETWORKS;
+import static android.Manifest.permission.NETWORK_SETTINGS;
+import static android.Manifest.permission.READ_DEVICE_CONFIG;
+import static android.Manifest.permission.TETHER_PRIVILEGED;
+import static android.Manifest.permission.WRITE_SETTINGS;
+import static android.net.cts.util.CtsTetheringUtils.isWifiTetheringSupported;
+import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
+
+import static com.android.testutils.TestNetworkTrackerKt.initTestNetwork;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.UiAutomation;
+import android.content.Context;
+import android.net.IpPrefix;
+import android.net.LinkAddress;
+import android.net.TetheringManager;
+import android.net.cts.util.CtsTetheringUtils;
+import android.net.cts.util.CtsTetheringUtils.TestTetheringEventCallback;
+import android.provider.DeviceConfig;
+
+import androidx.annotation.NonNull;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.testutils.TestNetworkTracker;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.net.InterfaceAddress;
+import java.net.NetworkInterface;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class TetheringModuleTest {
+    private Context mContext;
+    private TetheringManager mTm;
+    private CtsTetheringUtils mCtsTetheringUtils;
+
+    private UiAutomation mUiAutomation =
+            InstrumentationRegistry.getInstrumentation().getUiAutomation();
+
+    @Before
+    public void setUp() throws Exception {
+        mUiAutomation.adoptShellPermissionIdentity(MANAGE_TEST_NETWORKS, NETWORK_SETTINGS,
+                WRITE_SETTINGS, READ_DEVICE_CONFIG, TETHER_PRIVILEGED);
+        mContext = InstrumentationRegistry.getContext();
+        mTm = mContext.getSystemService(TetheringManager.class);
+        mCtsTetheringUtils = new CtsTetheringUtils(mContext);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        mUiAutomation.dropShellPermissionIdentity();
+    }
+
+    private static final String TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES =
+            "tether_enable_select_all_prefix_ranges";
+    @Test
+    public void testSwitchBasePrefixRangeWhenConflict() throws Exception {
+        assumeTrue(isFeatureEnabled(TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES, true));
+
+        addressConflictTest(true);
+    }
+
+    @Test
+    public void testSwitchPrefixRangeWhenConflict() throws Exception {
+        addressConflictTest(false);
+    }
+
+    private void addressConflictTest(final boolean wholeRangeConflict) throws Exception {
+        final TestTetheringEventCallback tetherEventCallback =
+                mCtsTetheringUtils.registerTetheringEventCallback();
+
+        TestNetworkTracker tnt = null;
+        try {
+            tetherEventCallback.assumeTetheringSupported();
+            assumeTrue(isWifiTetheringSupported(tetherEventCallback));
+
+            mCtsTetheringUtils.startWifiTethering(tetherEventCallback);
+
+            final List<String> tetheredIfaces = tetherEventCallback.getTetheredInterfaces();
+            assertEquals(1, tetheredIfaces.size());
+            final String wifiTetheringIface = tetheredIfaces.get(0);
+
+            NetworkInterface nif = NetworkInterface.getByName(wifiTetheringIface);
+            // Tethering downstream only have one ipv4 address.
+            final LinkAddress hotspotAddr = getFirstIpv4Address(nif);
+            assertNotNull(hotspotAddr);
+
+            final IpPrefix testPrefix = getConflictingPrefix(hotspotAddr, wholeRangeConflict);
+            assertNotNull(testPrefix);
+
+            tnt = setUpTestNetwork(
+                    new LinkAddress(testPrefix.getAddress(), testPrefix.getPrefixLength()));
+
+            tetherEventCallback.expectTetheredInterfacesChanged(null);
+            final List<String> wifiRegexs =
+                    tetherEventCallback.getTetheringInterfaceRegexps().getTetherableWifiRegexs();
+
+            tetherEventCallback.expectTetheredInterfacesChanged(wifiRegexs);
+            nif = NetworkInterface.getByName(wifiTetheringIface);
+            final LinkAddress newHotspotAddr = getFirstIpv4Address(nif);
+            assertNotNull(newHotspotAddr);
+
+            assertFalse(testPrefix.containsPrefix(
+                    new IpPrefix(newHotspotAddr.getAddress(), newHotspotAddr.getPrefixLength())));
+
+            mCtsTetheringUtils.stopWifiTethering(tetherEventCallback);
+        } finally {
+            if (tnt != null) {
+                tnt.teardown();
+            }
+            mTm.stopAllTethering();
+            mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback);
+        }
+    }
+
+    private LinkAddress getFirstIpv4Address(final NetworkInterface nif) {
+        for (InterfaceAddress ia : nif.getInterfaceAddresses()) {
+            final LinkAddress addr = new LinkAddress(ia.getAddress(), ia.getNetworkPrefixLength());
+            if (addr.isIpv4()) return addr;
+        }
+        return null;
+    }
+
+    @NonNull
+    private IpPrefix getConflictingPrefix(final LinkAddress address,
+            final boolean wholeRangeConflict) {
+        if (!wholeRangeConflict) {
+            return new IpPrefix(address.getAddress(), address.getPrefixLength());
+        }
+
+        final ArrayList<IpPrefix> prefixPool = new ArrayList<>(Arrays.asList(
+                new IpPrefix("192.168.0.0/16"),
+                new IpPrefix("172.16.0.0/12"),
+                new IpPrefix("10.0.0.0/8")));
+
+        for (IpPrefix prefix : prefixPool) {
+            if (prefix.contains(address.getAddress())) return prefix;
+        }
+
+        fail("Could not find sutiable conflict prefix");
+
+        // Never go here.
+        return null;
+    }
+
+    private TestNetworkTracker setUpTestNetwork(final LinkAddress address) throws Exception {
+        return initTestNetwork(mContext, address, 10_000L /* test timeout ms*/);
+
+    }
+
+    public static boolean isFeatureEnabled(final String name, final boolean defaultValue) {
+        return DeviceConfig.getBoolean(NAMESPACE_CONNECTIVITY, name, defaultValue);
+    }
+}
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java
index 8cb80ba..41d46e5 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java
@@ -99,9 +99,9 @@
         when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(mConnectivityMgr);
         when(mConnectivityMgr.getAllNetworks()).thenReturn(mAllNetworks);
         when(mConfig.shouldEnableWifiP2pDedicatedIp()).thenReturn(false);
+        when(mConfig.isSelectAllPrefixRangeEnabled()).thenReturn(true);
         setUpIpServers();
-        mPrivateAddressCoordinator = spy(new PrivateAddressCoordinator(mContext, mConfig,
-                mTetheringPrefixes));
+        mPrivateAddressCoordinator = spy(new PrivateAddressCoordinator(mContext, mConfig));
     }
 
     private LinkAddress requestDownstreamAddress(final IpServer ipServer, boolean useLastAddress) {
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java
index dc0940c..237e2c2 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java
@@ -131,6 +131,7 @@
         when(mResources.getBoolean(R.bool.config_tether_enable_legacy_wifi_p2p_dedicated_ip))
                 .thenReturn(false);
         initializeBpfOffloadConfiguration(true, null /* unset */);
+        initEnableSelectAllPrefixRangeFlag(null /* unset */);
 
         mHasTelephonyManager = true;
         mMockContext = new MockContext(mContext);
@@ -428,4 +429,30 @@
                 mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
         assertTrue(testCfg.shouldEnableWifiP2pDedicatedIp());
     }
+
+    private void initEnableSelectAllPrefixRangeFlag(final String value) {
+        doReturn(value).when(
+                () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY),
+                eq(TetheringConfiguration.TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES)));
+    }
+
+    @Test
+    public void testSelectAllPrefixRangeFlag() throws Exception {
+        // Test default value.
+        final TetheringConfiguration defaultCfg = new TetheringConfiguration(
+                mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
+        assertTrue(defaultCfg.isSelectAllPrefixRangeEnabled());
+
+        // Test disable flag.
+        initEnableSelectAllPrefixRangeFlag("false");
+        final TetheringConfiguration testDisable = new TetheringConfiguration(
+                mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
+        assertFalse(testDisable.isSelectAllPrefixRangeEnabled());
+
+        // Test enable flag.
+        initEnableSelectAllPrefixRangeFlag("true");
+        final TetheringConfiguration testEnable = new TetheringConfiguration(
+                mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
+        assertTrue(testEnable.isSelectAllPrefixRangeEnabled());
+    }
 }
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
index 20e94b2..114cb7c 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
@@ -456,11 +456,7 @@
         @Override
         public PrivateAddressCoordinator getPrivateAddressCoordinator(Context ctx,
                 TetheringConfiguration cfg) {
-            final ArrayList<IpPrefix> prefixPool = new ArrayList<>(Arrays.asList(
-                    new IpPrefix("192.168.0.0/16"),
-                    new IpPrefix("172.16.0.0/12"),
-                    new IpPrefix("10.0.0.0/8")));
-            mPrivateAddressCoordinator = spy(new PrivateAddressCoordinator(ctx, cfg, prefixPool));
+            mPrivateAddressCoordinator = super.getPrivateAddressCoordinator(ctx, cfg);
             return mPrivateAddressCoordinator;
         }
     }
diff --git a/services/autofill/java/com/android/server/autofill/AutofillInlineSessionController.java b/services/autofill/java/com/android/server/autofill/AutofillInlineSessionController.java
index c25dd37..dd5e58a 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillInlineSessionController.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillInlineSessionController.java
@@ -35,8 +35,8 @@
  * Controls the interaction with the IME for the {@link AutofillInlineSuggestionsRequestSession}s.
  *
  * <p>The class maintains the inline suggestion session with the autofill service. There is at most
- * one active inline suggestion session at any given  corresponding to one focused view.
- * New sessions are created only when {@link #onCreateInlineSuggestionsRequestLocked} is called.</p>
+ * one active inline suggestion session at any given  corresponding to one focused view. New
+ * sessions are created only when {@link #onCreateInlineSuggestionsRequestLocked} is called.</p>
  *
  * <p>The class manages the interaction between the {@link com.android.server.autofill.Session} and
  * the inline suggestion session whenever inline suggestions can be provided. All calls to the
@@ -83,7 +83,6 @@
     @GuardedBy("mLock")
     void onCreateInlineSuggestionsRequestLocked(@NonNull AutofillId autofillId,
             @NonNull Consumer<InlineSuggestionsRequest> requestConsumer, @NonNull Bundle uiExtras) {
-        // TODO(b/151123764): rename the method to better reflect what it does.
         if (mSession != null) {
             // Destroy the existing session.
             mSession.destroySessionLocked();
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index c563b6c..864ead1 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -1055,7 +1055,7 @@
             pw.println(compatPkgs);
         }
         pw.print(prefix); pw.print("Inline Suggestions Enabled: ");
-        pw.println(isInlineSuggestionsEnabled());
+        pw.println(isInlineSuggestionsEnabledLocked());
         pw.print(prefix); pw.print("Last prune: "); pw.println(mLastPrune);
 
         mDisabledInfoCache.dump(mUserId, prefix, pw);
@@ -1168,7 +1168,7 @@
     }
 
     @GuardedBy("mLock")
-    boolean isInlineSuggestionsEnabled() {
+    boolean isInlineSuggestionsEnabledLocked() {
         if (mInfo != null) {
             return mInfo.isInlineSuggestionsEnabled();
         }
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index 80b0375..e35c0ee 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -24,6 +24,9 @@
 import android.content.ComponentName;
 import android.metrics.LogMaker;
 import android.service.autofill.Dataset;
+import android.service.autofill.InternalSanitizer;
+import android.service.autofill.SaveInfo;
+import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Slog;
@@ -38,6 +41,7 @@
 import java.io.PrintWriter;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
+import java.util.Arrays;
 
 public final class Helper {
 
@@ -234,6 +238,46 @@
         }
     }
 
+    @Nullable
+    static ArrayMap<AutofillId, InternalSanitizer> createSanitizers(@Nullable SaveInfo saveInfo) {
+        if (saveInfo == null) return null;
+
+        final InternalSanitizer[] sanitizerKeys = saveInfo.getSanitizerKeys();
+        if (sanitizerKeys == null) return null;
+
+        final int size = sanitizerKeys.length;
+        final ArrayMap<AutofillId, InternalSanitizer> sanitizers = new ArrayMap<>(size);
+        if (sDebug) Slog.d(TAG, "Service provided " + size + " sanitizers");
+        final AutofillId[][] sanitizerValues = saveInfo.getSanitizerValues();
+        for (int i = 0; i < size; i++) {
+            final InternalSanitizer sanitizer = sanitizerKeys[i];
+            final AutofillId[] ids = sanitizerValues[i];
+            if (sDebug) {
+                Slog.d(TAG, "sanitizer #" + i + " (" + sanitizer + ") for ids "
+                        + Arrays.toString(ids));
+            }
+            for (AutofillId id : ids) {
+                sanitizers.put(id, sanitizer);
+            }
+        }
+        return sanitizers;
+    }
+
+    /**
+     * Returns true if {@code s1} contains all characters of {@code s2}, in order.
+     */
+    static boolean containsCharsInOrder(String s1, String s2) {
+        int prevIndex = -1;
+        for (char ch : s2.toCharArray()) {
+            int index = TextUtils.indexOf(s1, ch, prevIndex + 1);
+            if (index == -1) {
+                return false;
+            }
+            prevIndex = index;
+        }
+        return true;
+    }
+
     private interface ViewNodeFilter {
         boolean matches(ViewNode node);
     }
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 6c9d35c..f596b07 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -30,6 +30,8 @@
 import static android.view.autofill.AutofillManager.getSmartSuggestionModeToString;
 
 import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+import static com.android.server.autofill.Helper.containsCharsInOrder;
+import static com.android.server.autofill.Helper.createSanitizers;
 import static com.android.server.autofill.Helper.getNumericValue;
 import static com.android.server.autofill.Helper.sDebug;
 import static com.android.server.autofill.Helper.sVerbose;
@@ -117,7 +119,6 @@
 import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
-import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Consumer;
 import java.util.function.Function;
@@ -372,26 +373,24 @@
      * CountDownLatch.
      */
     private final class AssistDataReceiverImpl extends IAssistDataReceiver.Stub {
-
+        @GuardedBy("mLock")
+        private boolean mWaitForInlineRequest;
         @GuardedBy("mLock")
         private InlineSuggestionsRequest mPendingInlineSuggestionsRequest;
         @GuardedBy("mLock")
         private FillRequest mPendingFillRequest;
-        @GuardedBy("mLock")
-        private CountDownLatch mCountDownLatch = new CountDownLatch(0);
 
         @Nullable Consumer<InlineSuggestionsRequest> newAutofillRequestLocked(ViewState viewState,
                 boolean isInlineRequest) {
-            mCountDownLatch = new CountDownLatch(isInlineRequest ? 2 : 1);
             mPendingFillRequest = null;
+            mWaitForInlineRequest = isInlineRequest;
             mPendingInlineSuggestionsRequest = null;
             return isInlineRequest ? (inlineSuggestionsRequest) -> {
                 synchronized (mLock) {
-                    if (mCountDownLatch.getCount() == 0) {
+                    if (!mWaitForInlineRequest || mPendingInlineSuggestionsRequest != null) {
                         return;
                     }
                     mPendingInlineSuggestionsRequest = inlineSuggestionsRequest;
-                    mCountDownLatch.countDown();
                     maybeRequestFillLocked();
                     viewState.resetState(ViewState.STATE_PENDING_CREATE_INLINE_REQUEST);
                 }
@@ -399,16 +398,23 @@
         }
 
         void maybeRequestFillLocked() {
-            if (mCountDownLatch.getCount() > 0 || mPendingFillRequest == null) {
+            if (mPendingFillRequest == null) {
                 return;
             }
-            if (mPendingInlineSuggestionsRequest != null) {
+
+            if (mWaitForInlineRequest) {
+                if (mPendingInlineSuggestionsRequest == null) {
+                    return;
+                }
+
                 mPendingFillRequest = new FillRequest(mPendingFillRequest.getId(),
                         mPendingFillRequest.getFillContexts(), mPendingFillRequest.getClientState(),
                         mPendingFillRequest.getFlags(), mPendingInlineSuggestionsRequest);
             }
+
             mRemoteFillService.onFillRequest(mPendingFillRequest);
             mPendingInlineSuggestionsRequest = null;
+            mWaitForInlineRequest = false;
             mPendingFillRequest = null;
         }
 
@@ -509,15 +515,8 @@
                 request = new FillRequest(requestId, contexts, mClientState, flags,
                         /*inlineSuggestionsRequest=*/null);
 
-                if (mCountDownLatch.getCount() > 0) {
-                    mPendingFillRequest = request;
-                    mCountDownLatch.countDown();
-                    maybeRequestFillLocked();
-                } else {
-                    // TODO(b/151867668): ideally this case should not happen, but it was
-                    //  observed, we should figure out why and fix.
-                    mRemoteFillService.onFillRequest(request);
-                }
+                mPendingFillRequest = request;
+                maybeRequestFillLocked();
             }
 
             if (mActivityToken != null) {
@@ -545,6 +544,10 @@
         return ids;
     }
 
+    /**
+     * Returns the String value of an {@link AutofillValue} by {@link AutofillId id} if it is of
+     * type {@code AUTOFILL_TYPE_TEXT} or {@code AUTOFILL_TYPE_LIST}.
+     */
     @Override
     @Nullable
     public String findByAutofillId(@NonNull AutofillId id) {
@@ -706,7 +709,7 @@
      * Autofill provider).
      */
     private boolean isInlineSuggestionsEnabledByAutofillProviderLocked() {
-        return mService.isInlineSuggestionsEnabled();
+        return mService.isInlineSuggestionsEnabledLocked();
     }
 
     private boolean isViewFocusedLocked(int flags) {
@@ -767,7 +770,7 @@
         // triggers a new partition and we end up with many duplicate partitions. This is
         // enhanced as the focus change can be much faster than the taking of the assist structure.
         // Hence remove the currently queued request and replace it with the one queued after the
-        // structure is taken. This causes only one fill request per bust of focus changes.
+        // structure is taken. This causes only one fill request per burst of focus changes.
         cancelCurrentRequestLocked();
 
         // Only ask IME to create inline suggestions request if Autofill provider supports it and
@@ -780,7 +783,7 @@
                 && isViewFocusedLocked(flags)) {
             Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestConsumer =
                     mAssistReceiver.newAutofillRequestLocked(viewState,
-                            /*isInlineRequest=*/ true);
+                            /* isInlineRequest= */ true);
             if (inlineSuggestionsRequestConsumer != null) {
                 final AutofillId focusedId = mCurrentViewId;
                 remoteRenderService.getInlineSuggestionsRendererInfo(
@@ -794,8 +797,7 @@
                 viewState.setState(ViewState.STATE_PENDING_CREATE_INLINE_REQUEST);
             }
         } else {
-            mAssistReceiver.newAutofillRequestLocked(viewState,
-                    /*isInlineRequest=*/ false);
+            mAssistReceiver.newAutofillRequestLocked(viewState, /* isInlineRequest= */ false);
         }
 
         // Now request the assist structure data.
@@ -1172,7 +1174,14 @@
         return null;
     }
 
-    // FillServiceCallbacks
+    // VultureCallback
+    @Override
+    public void onServiceDied(@NonNull RemoteFillService service) {
+        Slog.w(TAG, "removing session because service died");
+        forceRemoveSelfLocked();
+    }
+
+    // AutoFillUiCallback
     @Override
     public void authenticate(int requestId, int datasetIndex, IntentSender intent, Bundle extras,
             boolean authenticateInline) {
@@ -1202,13 +1211,6 @@
                 this, authenticationId, intent, fillInIntent, authenticateInline));
     }
 
-    // VultureCallback
-    @Override
-    public void onServiceDied(@NonNull RemoteFillService service) {
-        Slog.w(TAG, "removing session because service died");
-        forceRemoveSelfLocked();
-    }
-
     // AutoFillUiCallback
     @Override
     public void fill(int requestId, int datasetIndex, Dataset dataset) {
@@ -1282,6 +1284,7 @@
         }
     }
 
+    // AutoFillUiCallback
     @Override
     public void dispatchUnhandledKey(AutofillId id, KeyEvent keyEvent) {
         synchronized (mLock) {
@@ -2281,31 +2284,6 @@
     }
 
     @Nullable
-    private ArrayMap<AutofillId, InternalSanitizer> createSanitizers(@Nullable SaveInfo saveInfo) {
-        if (saveInfo == null) return null;
-
-        final InternalSanitizer[] sanitizerKeys = saveInfo.getSanitizerKeys();
-        if (sanitizerKeys == null) return null;
-
-        final int size = sanitizerKeys.length ;
-        final ArrayMap<AutofillId, InternalSanitizer> sanitizers = new ArrayMap<>(size);
-        if (sDebug) Slog.d(TAG, "Service provided " + size + " sanitizers");
-        final AutofillId[][] sanitizerValues = saveInfo.getSanitizerValues();
-        for (int i = 0; i < size; i++) {
-            final InternalSanitizer sanitizer = sanitizerKeys[i];
-            final AutofillId[] ids = sanitizerValues[i];
-            if (sDebug) {
-                Slog.d(TAG, "sanitizer #" + i + " (" + sanitizer + ") for ids "
-                        + Arrays.toString(ids));
-            }
-            for (AutofillId id : ids) {
-                sanitizers.put(id, sanitizer);
-            }
-        }
-        return sanitizers;
-    }
-
-    @Nullable
     private AutofillValue getSanitizedValue(
             @Nullable ArrayMap<AutofillId, InternalSanitizer> sanitizers,
             @NonNull AutofillId id,
@@ -2369,12 +2347,12 @@
      */
     @GuardedBy("mLock")
     @Nullable
-    private CharSequence[] getAutofillOptionsFromContextsLocked(AutofillId id) {
+    private CharSequence[] getAutofillOptionsFromContextsLocked(@NonNull AutofillId autofillId) {
         final int numContexts = mContexts.size();
-
         for (int i = numContexts - 1; i >= 0; i--) {
             final FillContext context = mContexts.get(i);
-            final ViewNode node = Helper.findViewNodeByAutofillId(context.getStructure(), id);
+            final ViewNode node = Helper.findViewNodeByAutofillId(context.getStructure(),
+                    autofillId);
             if (node != null && node.getAutofillOptions() != null) {
                 return node.getAutofillOptions();
             }
@@ -2480,7 +2458,7 @@
     // TODO(b/113281366): rather than merge it here, it might be better to simply reuse the old
     // session instead of creating a new one. But we need to consider what would happen on corner
     // cases such as "Main Activity M -> activity A with username -> activity B with password"
-    // If user follows the normal workflow, than session A would be merged with session B as
+    // If user follows the normal workflow, then session A would be merged with session B as
     // expected. But if when on Activity A the user taps back or somehow launches another activity,
     // session A could be merged with the wrong session.
     /**
@@ -2573,11 +2551,11 @@
             }
             requestNewFillResponseLocked(viewState, ViewState.STATE_STARTED_PARTITION, flags);
             return true;
-        } else {
-            if (sVerbose) {
-                Slog.v(TAG, "Not starting new partition for view " + id + ": "
-                        + viewState.getStateAsString());
-            }
+        }
+
+        if (sVerbose) {
+            Slog.v(TAG, "Not starting new partition for view " + id + ": "
+                    + viewState.getStateAsString());
         }
         return false;
     }
@@ -2938,21 +2916,6 @@
         }
     }
 
-    /**
-     * Returns true if {@code s1} contains all characters of {@code s2}, in order.
-     */
-    private static boolean containsCharsInOrder(String s1, String s2) {
-        int prevIndex = -1;
-        for (char ch : s2.toCharArray()) {
-            int index = TextUtils.indexOf(s1, ch, prevIndex + 1);
-            if (index == -1) {
-                return false;
-            }
-            prevIndex = index;
-        }
-        return true;
-    }
-
     @Override
     public void onFillReady(@NonNull FillResponse response, @NonNull AutofillId filledId,
             @Nullable AutofillValue value) {
@@ -3421,7 +3384,7 @@
                     mInlineSessionController.getInlineSuggestionsRequestLocked().orElse(null));
         }
         if (mAugmentedAutofillDestroyer == null) {
-            mAugmentedAutofillDestroyer = () -> remoteService.onDestroyAutofillWindowsRequest();
+            mAugmentedAutofillDestroyer = remoteService::onDestroyAutofillWindowsRequest;
         }
         return mAugmentedAutofillDestroyer;
     }
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index aa8532b..2ff66b5 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -650,7 +650,7 @@
                         context,
                         /* requestCode */ 0,
                         initIntent,
-                        /* flags */ 0,
+                        /* flags */ PendingIntent.FLAG_IMMUTABLE,
                         UserHandle.of(userId));
 
         // Set up the backup-request journaling
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 35f1194..cdc06ae 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1169,7 +1169,7 @@
 
         mMultipathPolicyTracker = new MultipathPolicyTracker(mContext, mHandler);
 
-        mDnsManager = new DnsManager(mContext, mDnsResolver, mSystemProperties);
+        mDnsManager = new DnsManager(mContext, mDnsResolver);
         registerPrivateDnsSettingsCallbacks();
     }
 
diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java
index b874684..ff2661b 100644
--- a/services/core/java/com/android/server/SystemServiceManager.java
+++ b/services/core/java/com/android/server/SystemServiceManager.java
@@ -26,12 +26,14 @@
 import android.os.Trace;
 import android.os.UserManagerInternal;
 import android.util.ArrayMap;
+import android.util.EventLog;
 import android.util.Slog;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
 import com.android.server.SystemService.TargetUser;
+import com.android.server.am.EventLogTags;
 import com.android.server.utils.TimingsTraceAndSlog;
 
 import dalvik.system.PathClassLoader;
@@ -53,12 +55,14 @@
     private static final int SERVICE_CALL_WARN_TIME_MS = 50;
 
     // Constants used on onUser(...)
-    private static final String START = "Start";
-    private static final String UNLOCKING = "Unlocking";
-    private static final String UNLOCKED = "Unlocked";
-    private static final String SWITCH = "Switch";
-    private static final String STOP = "Stop";
-    private static final String CLEANUP = "Cleanup";
+    // NOTE: do not change their values, as they're used on Trace calls and changes might break
+    // performance tests that rely on them.
+    private static final String USER_STARTING = "Start";
+    private static final String USER_UNLOCKING = "Unlocking";
+    private static final String USER_UNLOCKED = "Unlocked";
+    private static final String USER_SWITCHING = "Switch";
+    private static final String USER_STOPPING = "Stop";
+    private static final String USER_STOPPED = "Cleanup";
 
     private static File sSystemDir;
     private final Context mContext;
@@ -86,7 +90,7 @@
 
     /**
      * Reference to the current user, it's used to set the {@link TargetUser} on
-     * {@link #switchUser(int, int)} as the previous user might have been removed already.
+     * {@link #onUserSwitching(int, int)} as the previous user might have been removed already.
      */
     @GuardedBy("mTargetUsers")
     private @Nullable TargetUser mCurrentUser;
@@ -275,33 +279,38 @@
     /**
      * Starts the given user.
      */
-    public void startUser(@NonNull TimingsTraceAndSlog t, @UserIdInt int userId) {
+    public void onUserStarting(@NonNull TimingsTraceAndSlog t, @UserIdInt int userId) {
+        EventLog.writeEvent(EventLogTags.SSM_USER_STARTING, userId);
+
         final TargetUser targetUser = newTargetUser(userId);
         synchronized (mTargetUsers) {
             mTargetUsers.put(userId, targetUser);
         }
 
-        onUser(t, START, /* prevUser= */ null, targetUser);
+        onUser(t, USER_STARTING, /* prevUser= */ null, targetUser);
     }
 
     /**
      * Unlocks the given user.
      */
-    public void unlockUser(@UserIdInt int userId) {
-        onUser(UNLOCKING, userId);
+    public void onUserUnlocking(@UserIdInt int userId) {
+        EventLog.writeEvent(EventLogTags.SSM_USER_UNLOCKING, userId);
+        onUser(USER_UNLOCKING, userId);
     }
 
     /**
      * Called after the user was unlocked.
      */
     public void onUserUnlocked(@UserIdInt int userId) {
-        onUser(UNLOCKED, userId);
+        EventLog.writeEvent(EventLogTags.SSM_USER_UNLOCKED, userId);
+        onUser(USER_UNLOCKED, userId);
     }
 
     /**
      * Switches to the given user.
      */
-    public void switchUser(@UserIdInt int from, @UserIdInt int to) {
+    public void onUserSwitching(@UserIdInt int from, @UserIdInt int to) {
+        EventLog.writeEvent(EventLogTags.SSM_USER_SWITCHING, from, to);
         final TargetUser curUser, prevUser;
         synchronized (mTargetUsers) {
             if (mCurrentUser == null) {
@@ -321,21 +330,23 @@
                 Slog.d(TAG, "Set mCurrentUser to " + mCurrentUser);
             }
         }
-        onUser(TimingsTraceAndSlog.newAsyncLog(), SWITCH, prevUser, curUser);
+        onUser(TimingsTraceAndSlog.newAsyncLog(), USER_SWITCHING, prevUser, curUser);
     }
 
     /**
      * Stops the given user.
      */
-    public void stopUser(@UserIdInt int userId) {
-        onUser(STOP, userId);
+    public void onUserStopping(@UserIdInt int userId) {
+        EventLog.writeEvent(EventLogTags.SSM_USER_STOPPING, userId);
+        onUser(USER_STOPPING, userId);
     }
 
     /**
      * Cleans up the given user.
      */
-    public void cleanupUser(@UserIdInt int userId) {
-        onUser(CLEANUP, userId);
+    public void onUserStopped(@UserIdInt int userId) {
+        EventLog.writeEvent(EventLogTags.SSM_USER_STOPPED, userId);
+        onUser(USER_STOPPED, userId);
 
         // Remove cached TargetUser
         synchronized (mTargetUsers) {
@@ -351,6 +362,7 @@
     private void onUser(@NonNull TimingsTraceAndSlog t, @NonNull String onWhat,
             @Nullable TargetUser prevUser, @NonNull TargetUser curUser) {
         final int curUserId = curUser.getUserIdentifier();
+        // NOTE: do not change label below, or it might break performance tests that rely on it.
         t.traceBegin("ssm." + onWhat + "User-" + curUserId);
         Slog.i(TAG, "Calling on" + onWhat + "User " + curUserId
                 + (prevUser != null ? " (from " + prevUser + ")" : ""));
@@ -381,22 +393,22 @@
             long time = SystemClock.elapsedRealtime();
             try {
                 switch (onWhat) {
-                    case SWITCH:
+                    case USER_SWITCHING:
                         service.onUserSwitching(prevUser, curUser);
                         break;
-                    case START:
+                    case USER_STARTING:
                         service.onUserStarting(curUser);
                         break;
-                    case UNLOCKING:
+                    case USER_UNLOCKING:
                         service.onUserUnlocking(curUser);
                         break;
-                    case UNLOCKED:
+                    case USER_UNLOCKED:
                         service.onUserUnlocked(curUser);
                         break;
-                    case STOP:
+                    case USER_STOPPING:
                         service.onUserStopping(curUser);
                         break;
-                    case CLEANUP:
+                    case USER_STOPPED:
                         service.onUserStopped(curUser);
                         break;
                     default:
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 49444834..ba1eda9 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -104,6 +104,7 @@
         "media.metrics", // system/bin/mediametrics
         "media.codec", // vendor/bin/hw/android.hardware.media.omx@1.0-service
         "media.swcodec", // /apex/com.android.media.swcodec/bin/mediaswcodec
+        "media.transcoding", // Media transcoding service
         "com.android.bluetooth",  // Bluetooth service
         "/apex/com.android.os.statsd/bin/statsd",  // Stats daemon
     };
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f0c9845..63f7d44 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -7361,7 +7361,7 @@
         final boolean bootingSystemUser = currentUserId == UserHandle.USER_SYSTEM;
 
         if (bootingSystemUser) {
-            mSystemServiceManager.startUser(t, currentUserId);
+            mSystemServiceManager.onUserStarting(t, currentUserId);
         }
 
         synchronized (this) {
@@ -14872,6 +14872,7 @@
             change |= UidRecord.CHANGE_IDLE;
         }
         final int enqueuedChange = mUidObserverController.enqueueUidChange(
+                uidRec == null ? null : uidRec.pendingChange,
                 uid, change, procState, procStateSeq, capability, ephemeral);
         if (uidRec != null) {
             uidRec.lastReportedChange = enqueuedChange;
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index 529c651..f32423f 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -85,19 +85,19 @@
         sGlobalSettingToTypeMap.put(
                 Settings.Global.DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE, String.class);
         sGlobalSettingToTypeMap.put(
-                Settings.Global.GLOBAL_SETTINGS_ANGLE_DEBUG_PACKAGE, String.class);
+                Settings.Global.ANGLE_DEBUG_PACKAGE, String.class);
         sGlobalSettingToTypeMap.put(
-                Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE, int.class);
+                Settings.Global.ANGLE_GL_DRIVER_ALL_ANGLE, int.class);
         sGlobalSettingToTypeMap.put(
-                Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS, String.class);
+                Settings.Global.ANGLE_GL_DRIVER_SELECTION_PKGS, String.class);
         sGlobalSettingToTypeMap.put(
-                Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES, String.class);
+                Settings.Global.ANGLE_GL_DRIVER_SELECTION_VALUES, String.class);
         sGlobalSettingToTypeMap.put(
-                Settings.Global.GLOBAL_SETTINGS_ANGLE_ALLOWLIST, String.class);
+                Settings.Global.ANGLE_ALLOWLIST, String.class);
         sGlobalSettingToTypeMap.put(
                 Settings.Global.ANGLE_EGL_FEATURES, String.class);
         sGlobalSettingToTypeMap.put(
-                Settings.Global.GLOBAL_SETTINGS_SHOW_ANGLE_IN_USE_DIALOG_BOX, String.class);
+                Settings.Global.SHOW_ANGLE_IN_USE_DIALOG_BOX, String.class);
         sGlobalSettingToTypeMap.put(Settings.Global.ENABLE_GPU_DEBUG_LAYERS, int.class);
         sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_APP, String.class);
         sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYERS, String.class);
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index b818ccf..68f2e35 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -104,6 +104,14 @@
 30076 uc_start_user_internal (userId|1|5)
 30077 uc_unlock_user (userId|1|5)
 30078 uc_finish_user_boot (userId|1|5)
-30079 uc_dispatch_user_switch (oldUserId|1|5) (newUserId|1|5)
-30080 uc_continue_user_switch (oldUserId|1|5) (newUserId|1|5)
-30081 uc_send_user_broadcast (userId|1|5),(IntentAction|3)
\ No newline at end of file
+30079 uc_dispatch_user_switch (oldUserId|1|5),(newUserId|1|5)
+30080 uc_continue_user_switch (oldUserId|1|5),(newUserId|1|5)
+30081 uc_send_user_broadcast (userId|1|5),(IntentAction|3)
+# Tags below are used by SystemServiceManager - although it's technically part of am, these are
+# also user switch events and useful to be analyzed together with events above.
+30082 ssm_user_starting (userId|1|5)
+30083 ssm_user_switching (oldUserId|1|5),(newUserId|1|5)
+30084 ssm_user_unlocking (userId|1|5)
+30085 ssm_user_unlocked (userId|1|5)
+30086 ssm_user_stopping (userId|1|5)
+30087 ssm_user_stopped (userId|1|5)
diff --git a/services/core/java/com/android/server/am/PreBootBroadcaster.java b/services/core/java/com/android/server/am/PreBootBroadcaster.java
index 747e8a8..be63dd4 100644
--- a/services/core/java/com/android/server/am/PreBootBroadcaster.java
+++ b/services/core/java/com/android/server/am/PreBootBroadcaster.java
@@ -144,7 +144,8 @@
 
                     final PendingIntent contentIntent;
                     if (context.getPackageManager().resolveActivity(intent, 0) != null) {
-                        contentIntent = PendingIntent.getActivity(context, 0, intent, 0);
+                        contentIntent = PendingIntent.getActivity(context, 0, intent,
+                                PendingIntent.FLAG_IMMUTABLE);
                     } else {
                         contentIntent = null;
                     }
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 2571205..53c6758 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -1460,6 +1460,12 @@
             if (updateServiceConnectionActivities) {
                 mService.mServices.updateServiceConnectionActivitiesLocked(this);
             }
+            if (thread == null) {
+                // Only update lru and oom-adj if the process is alive. Because it may be called
+                // when cleaning up the last activity from handling process died, the dead process
+                // should not be added to lru list again.
+                return;
+            }
             mService.mProcessList.updateLruProcessLocked(this, activityChange, null /* client */);
             if (updateOomAdj) {
                 mService.updateOomAdjLocked(this, OomAdjuster.OOM_ADJ_REASON_ACTIVITY);
diff --git a/services/core/java/com/android/server/am/UidObserverController.java b/services/core/java/com/android/server/am/UidObserverController.java
index b3488c3..b3150d1 100644
--- a/services/core/java/com/android/server/am/UidObserverController.java
+++ b/services/core/java/com/android/server/am/UidObserverController.java
@@ -20,6 +20,8 @@
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_UID_OBSERVERS;
 import static com.android.server.am.ActivityManagerService.TAG_UID_OBSERVERS;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityManagerProto;
 import android.app.IUidObserver;
@@ -29,7 +31,6 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.util.Slog;
-import android.util.SparseArray;
 import android.util.SparseIntArray;
 import android.util.proto.ProtoOutputStream;
 import android.util.proto.ProtoUtils;
@@ -53,7 +54,7 @@
     final RemoteCallbackList<IUidObserver> mUidObservers = new RemoteCallbackList<>();
 
     @GuardedBy("mLock")
-    private final SparseArray<ChangeRecord> mPendingUidChanges = new SparseArray<>();
+    private final ArrayList<ChangeRecord> mPendingUidChanges = new ArrayList<>();
     @GuardedBy("mLock")
     private final ArrayList<ChangeRecord> mAvailUidChanges = new ArrayList<>();
 
@@ -71,27 +72,27 @@
     private static final boolean VALIDATE_UID_STATES = true;
     private final ActiveUids mValidateUids;
 
-    UidObserverController(Handler handler) {
+    UidObserverController(@NonNull Handler handler) {
         mHandler = handler;
         mValidateUids = new ActiveUids(null /* service */, false /* postChangesToAtm */);
     }
 
-    void register(IUidObserver observer, int which, int cutpoint, String callingPackage,
-            int callingUid) {
+    void register(@NonNull IUidObserver observer, int which, int cutpoint,
+            @NonNull String callingPackage, int callingUid) {
         synchronized (mLock) {
             mUidObservers.register(observer, new UidObserverRegistration(callingUid,
                     callingPackage, which, cutpoint));
         }
     }
 
-    void unregister(IUidObserver observer) {
+    void unregister(@NonNull IUidObserver observer) {
         synchronized (mLock) {
             mUidObservers.unregister(observer);
         }
     }
 
-    int enqueueUidChange(int uid, int change, int procState, long procStateSeq,
-            int capability, boolean ephemeral) {
+    int enqueueUidChange(@Nullable ChangeRecord currentRecord, int uid, int change, int procState,
+            long procStateSeq, int capability, boolean ephemeral) {
         synchronized (mLock) {
             if (mPendingUidChanges.size() == 0) {
                 if (DEBUG_UID_OBSERVERS) {
@@ -100,10 +101,11 @@
                 mHandler.post(mDispatchRunnable);
             }
 
-            ChangeRecord changeRecord = mPendingUidChanges.get(uid);
-            if (changeRecord == null) {
-                changeRecord = getOrCreateChangeRecordLocked();
-                mPendingUidChanges.put(uid, changeRecord);
+            final ChangeRecord changeRecord = currentRecord != null
+                    ? currentRecord : getOrCreateChangeRecordLocked();
+            if (!changeRecord.isPending) {
+                changeRecord.isPending = true;
+                mPendingUidChanges.add(changeRecord);
             } else {
                 change = mergeWithPendingChange(change, changeRecord.change);
             }
@@ -119,7 +121,7 @@
         }
     }
 
-    SparseArray<ChangeRecord> getPendingUidChangesForTest() {
+    ArrayList<ChangeRecord> getPendingUidChangesForTest() {
         return mPendingUidChanges;
     }
 
@@ -175,7 +177,10 @@
                 mActiveUidChanges = new ChangeRecord[numUidChanges];
             }
             for (int i = 0; i < numUidChanges; i++) {
-                mActiveUidChanges[i] = mPendingUidChanges.valueAt(i);
+                final ChangeRecord changeRecord = mPendingUidChanges.get(i);
+                mActiveUidChanges[i] = getOrCreateChangeRecordLocked();
+                changeRecord.copyTo(mActiveUidChanges[i]);
+                changeRecord.isPending = false;
             }
             mPendingUidChanges.clear();
             if (DEBUG_UID_OBSERVERS) {
@@ -216,13 +221,15 @@
 
         synchronized (mLock) {
             for (int j = 0; j < numUidChanges; j++) {
-                mAvailUidChanges.add(mActiveUidChanges[j]);
+                final ChangeRecord changeRecord = mActiveUidChanges[j];
+                changeRecord.isPending = false;
+                mAvailUidChanges.add(changeRecord);
             }
         }
     }
 
-    private void dispatchUidsChangedForObserver(IUidObserver observer,
-            UidObserverRegistration reg, int changesSize) {
+    private void dispatchUidsChangedForObserver(@NonNull IUidObserver observer,
+            @NonNull UidObserverRegistration reg, int changesSize) {
         if (observer == null) {
             return;
         }
@@ -318,7 +325,7 @@
         return mValidateUids.get(uid);
     }
 
-    void dump(PrintWriter pw, String dumpPackage) {
+    void dump(@NonNull PrintWriter pw, @Nullable String dumpPackage) {
         synchronized (mLock) {
             final int count = mUidObservers.getRegisteredCallbackCount();
             boolean printed = false;
@@ -353,7 +360,7 @@
         }
     }
 
-    void dumpDebug(ProtoOutputStream proto, String dumpPackage) {
+    void dumpDebug(@NonNull ProtoOutputStream proto, @Nullable String dumpPackage) {
         synchronized (mLock) {
             final int count = mUidObservers.getRegisteredCallbackCount();
             for (int i = 0; i < count; i++) {
@@ -366,23 +373,34 @@
         }
     }
 
-    boolean dumpValidateUids(PrintWriter pw, String dumpPackage, int dumpAppId,
-            String header, boolean needSep) {
+    boolean dumpValidateUids(@NonNull PrintWriter pw, @Nullable String dumpPackage, int dumpAppId,
+            @NonNull String header, boolean needSep) {
         return mValidateUids.dump(pw, dumpPackage, dumpAppId, header, needSep);
     }
 
-    void dumpValidateUidsProto(ProtoOutputStream proto, String dumpPackage,
+    void dumpValidateUidsProto(@NonNull ProtoOutputStream proto, @Nullable String dumpPackage,
             int dumpAppId, long fieldId) {
         mValidateUids.dumpProto(proto, dumpPackage, dumpAppId, fieldId);
     }
 
     static final class ChangeRecord {
+        public boolean isPending;
         public int uid;
         public int change;
         public int procState;
         public int capability;
         public boolean ephemeral;
         public long procStateSeq;
+
+        void copyTo(@NonNull ChangeRecord changeRecord) {
+            changeRecord.isPending = isPending;
+            changeRecord.uid = uid;
+            changeRecord.change = change;
+            changeRecord.procState = procState;
+            changeRecord.capability = capability;
+            changeRecord.ephemeral = ephemeral;
+            changeRecord.procStateSeq = procStateSeq;
+        }
     }
 
     private static final class UidObserverRegistration {
@@ -416,7 +434,7 @@
                 ActivityManagerProto.UID_OBSERVER_FLAG_PROCSTATE,
         };
 
-        UidObserverRegistration(int uid, String pkg, int which, int cutpoint) {
+        UidObserverRegistration(int uid, @NonNull String pkg, int which, int cutpoint) {
             this.mUid = uid;
             this.mPkg = pkg;
             this.mWhich = which;
@@ -425,7 +443,7 @@
                     ? new SparseIntArray() : null;
         }
 
-        void dump(PrintWriter pw, IUidObserver observer) {
+        void dump(@NonNull PrintWriter pw, @NonNull IUidObserver observer) {
             pw.print("    ");
             UserHandle.formatUid(pw, mUid);
             pw.print(" ");
@@ -460,7 +478,7 @@
             }
         }
 
-        void dumpDebug(ProtoOutputStream proto, long fieldId) {
+        void dumpDebug(@NonNull ProtoOutputStream proto, long fieldId) {
             final long token = proto.start(fieldId);
             proto.write(UidObserverRegistrationProto.UID, mUid);
             proto.write(UidObserverRegistrationProto.PACKAGE, mPkg);
diff --git a/services/core/java/com/android/server/am/UidRecord.java b/services/core/java/com/android/server/am/UidRecord.java
index dfd6149..f1945ed 100644
--- a/services/core/java/com/android/server/am/UidRecord.java
+++ b/services/core/java/com/android/server/am/UidRecord.java
@@ -27,6 +27,7 @@
 import android.util.proto.ProtoUtils;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.server.am.UidObserverController.ChangeRecord;
 
 /**
  * Overall information about a uid that has actively running processes.
@@ -107,6 +108,9 @@
             UidRecordProto.CHANGE_UNCACHED,
     };
 
+    // UidObserverController is the only thing that should modify this.
+    final ChangeRecord pendingChange = new ChangeRecord();
+
     int lastReportedChange;
 
     public UidRecord(int _uid) {
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index f1bad98..c29df6c 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -952,7 +952,7 @@
         mInjector.batteryStatsServiceNoteEvent(
                 BatteryStats.HistoryItem.EVENT_USER_RUNNING_FINISH,
                 Integer.toString(userId), userId);
-        mInjector.getSystemServiceManager().stopUser(userId);
+        mInjector.getSystemServiceManager().onUserStopping(userId);
 
         Runnable finishUserStoppedAsync = () ->
                 mHandler.post(() -> finishUserStopped(uss, allowDelayedLocking));
@@ -1028,7 +1028,7 @@
         }
 
         if (stopped) {
-            mInjector.systemServiceManagerCleanupUser(userId);
+            mInjector.systemServiceManagerOnUserStopped(userId);
             mInjector.stackSupervisorRemoveUser(userId);
 
             // Remove the user if it is ephemeral.
@@ -1307,7 +1307,7 @@
                 Slog.w(TAG, "No user info for user #" + userId);
                 return false;
             }
-            if (foreground && userInfo.isManagedProfile()) {
+            if (foreground && userInfo.isProfile()) {
                 Slog.w(TAG, "Cannot switch to User #" + userId + ": not a full user");
                 return false;
             }
@@ -1612,7 +1612,7 @@
             Slog.w(TAG, "Cannot switch to User #" + targetUserId + ": not supported");
             return false;
         }
-        if (targetUserInfo.isManagedProfile()) {
+        if (targetUserInfo.isProfile()) {
             Slog.w(TAG, "Cannot switch to User #" + targetUserId + ": not a full user");
             return false;
         }
@@ -2494,8 +2494,8 @@
                 logUserLifecycleEvent(msg.arg1, USER_LIFECYCLE_EVENT_START_USER,
                         USER_LIFECYCLE_EVENT_STATE_BEGIN);
 
-                mInjector.getSystemServiceManager().startUser(TimingsTraceAndSlog.newAsyncLog(),
-                        msg.arg1);
+                mInjector.getSystemServiceManager().onUserStarting(
+                        TimingsTraceAndSlog.newAsyncLog(), msg.arg1);
 
                 logUserLifecycleEvent(msg.arg1, USER_LIFECYCLE_EVENT_START_USER,
                         USER_LIFECYCLE_EVENT_STATE_FINISH);
@@ -2503,7 +2503,7 @@
                 break;
             case USER_UNLOCK_MSG:
                 final int userId = msg.arg1;
-                mInjector.getSystemServiceManager().unlockUser(userId);
+                mInjector.getSystemServiceManager().onUserUnlocking(userId);
                 // Loads recents on a worker thread that allows disk I/O
                 FgThread.getHandler().post(() -> {
                     mInjector.loadUserRecents(userId);
@@ -2528,7 +2528,7 @@
                         BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_START,
                         Integer.toString(msg.arg1), msg.arg1);
 
-                mInjector.getSystemServiceManager().switchUser(msg.arg2, msg.arg1);
+                mInjector.getSystemServiceManager().onUserSwitching(msg.arg2, msg.arg1);
                 break;
             case FOREGROUND_PROFILE_CHANGED_MSG:
                 dispatchForegroundProfileChanged(msg.arg1);
@@ -2781,8 +2781,8 @@
             LocalServices.getService(ActivityTaskManagerInternal.class).onUserStopped(userId);
         }
 
-        void systemServiceManagerCleanupUser(@UserIdInt int userId) {
-            mService.mSystemServiceManager.cleanupUser(userId);
+        void systemServiceManagerOnUserStopped(@UserIdInt int userId) {
+            mService.mSystemServiceManager.onUserStopped(userId);
         }
 
         protected UserManagerService getUserManager() {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/LockoutFrameworkImpl.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/LockoutFrameworkImpl.java
index 4fc1545..dc5dace9 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/LockoutFrameworkImpl.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/LockoutFrameworkImpl.java
@@ -135,6 +135,6 @@
     private PendingIntent getLockoutResetIntentForUser(int userId) {
         return PendingIntent.getBroadcast(mContext, userId,
                 new Intent(ACTION_LOCKOUT_RESET).putExtra(KEY_LOCKOUT_RESET_USER, userId),
-                PendingIntent.FLAG_UPDATE_CURRENT);
+                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
     }
 }
diff --git a/services/core/java/com/android/server/compat/CompatChange.java b/services/core/java/com/android/server/compat/CompatChange.java
index 2e9818d..bc3bff1 100644
--- a/services/core/java/com/android/server/compat/CompatChange.java
+++ b/services/core/java/com/android/server/compat/CompatChange.java
@@ -63,7 +63,7 @@
     private Map<String, Boolean> mPackageOverrides;
 
     public CompatChange(long changeId) {
-        this(changeId, null, -1, false, false, null);
+        this(changeId, null, -1, -1, false, false, null);
     }
 
     /**
@@ -71,11 +71,14 @@
      * @param name Short descriptive name.
      * @param enableAfterTargetSdk {@code targetSdkVersion} restriction. See {@link EnabledAfter};
      *                             -1 if the change is always enabled.
+     * @param enableSinceTargetSdk {@code targetSdkVersion} restriction. See {@link EnabledSince};
+     *                             -1 if the change is always enabled.
      * @param disabled If {@code true}, overrides any {@code enableAfterTargetSdk} set.
      */
     public CompatChange(long changeId, @Nullable String name, int enableAfterTargetSdk,
-            boolean disabled, boolean loggingOnly, String description) {
-        super(changeId, name, enableAfterTargetSdk, disabled, loggingOnly, description);
+            int enableSinceTargetSdk, boolean disabled, boolean loggingOnly, String description) {
+        super(changeId, name, enableAfterTargetSdk, enableSinceTargetSdk, disabled, loggingOnly,
+              description);
     }
 
     /**
@@ -83,7 +86,8 @@
      */
     public CompatChange(Change change) {
         super(change.getId(), change.getName(), change.getEnableAfterTargetSdk(),
-                change.getDisabled(), change.getLoggingOnly(), change.getDescription());
+                change.getEnableSinceTargetSdk(), change.getDisabled(), change.getLoggingOnly(),
+                change.getDescription());
     }
 
     void registerListener(ChangeListener listener) {
@@ -145,8 +149,8 @@
         if (getDisabled()) {
             return false;
         }
-        if (getEnableAfterTargetSdk() != -1) {
-            return app.targetSdkVersion > getEnableAfterTargetSdk();
+        if (getEnableSinceTargetSdk() != -1) {
+            return app.targetSdkVersion >= getEnableSinceTargetSdk();
         }
         return true;
     }
@@ -167,8 +171,8 @@
         if (getName() != null) {
             sb.append("; name=").append(getName());
         }
-        if (getEnableAfterTargetSdk() != -1) {
-            sb.append("; enableAfterTargetSdk=").append(getEnableAfterTargetSdk());
+        if (getEnableSinceTargetSdk() != -1) {
+            sb.append("; enableSinceTargetSdk=").append(getEnableSinceTargetSdk());
         }
         if (getDisabled()) {
             sb.append("; disabled");
diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java
index aeaa1fe..d80c58b 100644
--- a/services/core/java/com/android/server/compat/CompatConfig.java
+++ b/services/core/java/com/android/server/compat/CompatConfig.java
@@ -192,16 +192,19 @@
     }
 
     /**
-     * Returns the minimum sdk version for which this change should be enabled (or 0 if it is not
+     * Returns the maximum sdk version for which this change can be opted in (or -1 if it is not
      * target sdk gated).
      */
-    int minTargetSdkForChangeId(long changeId) {
+    int maxTargetSdkForChangeIdOptIn(long changeId) {
         synchronized (mChanges) {
             CompatChange c = mChanges.get(changeId);
             if (c == null) {
-                return 0;
+                return -1;
             }
-            return c.getEnableAfterTargetSdk();
+            if (c.getEnableSinceTargetSdk() != -1) {
+                return c.getEnableSinceTargetSdk() - 1;
+            }
+            return -1;
         }
     }
 
@@ -318,7 +321,7 @@
         }
     }
 
-    private long[] getAllowedChangesAfterTargetSdkForPackage(String packageName,
+    private long[] getAllowedChangesSinceTargetSdkForPackage(String packageName,
                                                              int targetSdkVersion)
                     throws RemoteException {
         LongArray allowed = new LongArray();
@@ -326,7 +329,7 @@
             for (int i = 0; i < mChanges.size(); ++i) {
                 try {
                     CompatChange change = mChanges.valueAt(i);
-                    if (change.getEnableAfterTargetSdk() != targetSdkVersion) {
+                    if (change.getEnableSinceTargetSdk() != targetSdkVersion) {
                         continue;
                     }
                     OverrideAllowedState allowedState =
@@ -345,14 +348,14 @@
     }
 
     /**
-     * Enables all changes with enabledAfterTargetSdk == {@param targetSdkVersion} for
+     * Enables all changes with enabledSinceTargetSdk == {@param targetSdkVersion} for
      * {@param packageName}.
      *
      * @return The number of changes that were toggled.
      */
     int enableTargetSdkChangesForPackage(String packageName, int targetSdkVersion)
             throws RemoteException {
-        long[] changes = getAllowedChangesAfterTargetSdkForPackage(packageName, targetSdkVersion);
+        long[] changes = getAllowedChangesSinceTargetSdkForPackage(packageName, targetSdkVersion);
         for (long changeId : changes) {
             addOverride(changeId, packageName, true);
         }
@@ -361,14 +364,14 @@
 
 
     /**
-     * Disables all changes with enabledAfterTargetSdk == {@param targetSdkVersion} for
+     * Disables all changes with enabledSinceTargetSdk == {@param targetSdkVersion} for
      * {@param packageName}.
      *
      * @return The number of changes that were toggled.
      */
     int disableTargetSdkChangesForPackage(String packageName, int targetSdkVersion)
             throws RemoteException {
-        long[] changes = getAllowedChangesAfterTargetSdkForPackage(packageName, targetSdkVersion);
+        long[] changes = getAllowedChangesSinceTargetSdkForPackage(packageName, targetSdkVersion);
         for (long changeId : changes) {
             addOverride(changeId, packageName, false);
         }
@@ -448,12 +451,7 @@
             CompatibilityChangeInfo[] changeInfos = new CompatibilityChangeInfo[mChanges.size()];
             for (int i = 0; i < mChanges.size(); ++i) {
                 CompatChange change = mChanges.valueAt(i);
-                changeInfos[i] = new CompatibilityChangeInfo(change.getId(),
-                        change.getName(),
-                        change.getEnableAfterTargetSdk(),
-                        change.getDisabled(),
-                        change.getLoggingOnly(),
-                        change.getDescription());
+                changeInfos[i] = new CompatibilityChangeInfo(change);
             }
             return changeInfos;
         }
diff --git a/services/core/java/com/android/server/compat/OverrideValidatorImpl.java b/services/core/java/com/android/server/compat/OverrideValidatorImpl.java
index 08d2664..79a13ca 100644
--- a/services/core/java/com/android/server/compat/OverrideValidatorImpl.java
+++ b/services/core/java/com/android/server/compat/OverrideValidatorImpl.java
@@ -58,7 +58,7 @@
 
         boolean debuggableBuild = mAndroidBuildClassifier.isDebuggableBuild();
         boolean finalBuild = mAndroidBuildClassifier.isFinalBuild();
-        int minTargetSdk = mCompatConfig.minTargetSdkForChangeId(changeId);
+        int maxTargetSdk = mCompatConfig.maxTargetSdkForChangeIdOptIn(changeId);
         boolean disabled = mCompatConfig.isDisabled(changeId);
 
         // Allow any override for userdebug or eng builds.
@@ -82,16 +82,16 @@
         }
         // Allow overriding any change for debuggable apps on non-final builds.
         if (!finalBuild) {
-            return new OverrideAllowedState(ALLOWED, appTargetSdk, minTargetSdk);
+            return new OverrideAllowedState(ALLOWED, appTargetSdk, maxTargetSdk);
         }
         // Do not allow overriding default enabled changes on user builds
-        if (minTargetSdk == -1 && !disabled) {
-            return new OverrideAllowedState(DISABLED_NON_TARGET_SDK, appTargetSdk, minTargetSdk);
+        if (maxTargetSdk == -1 && !disabled) {
+            return new OverrideAllowedState(DISABLED_NON_TARGET_SDK, appTargetSdk, maxTargetSdk);
         }
         // Only allow to opt-in for a targetSdk gated change.
-        if (disabled || appTargetSdk <= minTargetSdk) {
-            return new OverrideAllowedState(ALLOWED, appTargetSdk, minTargetSdk);
+        if (disabled || appTargetSdk <= maxTargetSdk) {
+            return new OverrideAllowedState(ALLOWED, appTargetSdk, maxTargetSdk);
         }
-        return new OverrideAllowedState(DISABLED_TARGET_SDK_TOO_HIGH, appTargetSdk, minTargetSdk);
+        return new OverrideAllowedState(DISABLED_TARGET_SDK_TOO_HIGH, appTargetSdk, maxTargetSdk);
     }
 }
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index c7de8d3..e4f52f1 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -59,8 +59,8 @@
     private final ChangeReporter mChangeReporter;
     private final CompatConfig mCompatConfig;
 
-    private static int sMinTargetSdk = Build.VERSION_CODES.P;
-    private static int sMaxTargetSdk = Build.VERSION_CODES.Q;
+    private static int sMinTargetSdk = Build.VERSION_CODES.Q;
+    private static int sMaxTargetSdk = Build.VERSION_CODES.R;
 
     public PlatformCompat(Context context) {
         mContext = context;
@@ -381,9 +381,9 @@
         if (change.getLoggingOnly()) {
             return false;
         }
-        if (change.getEnableAfterTargetSdk() > 0) {
-            if (change.getEnableAfterTargetSdk() < sMinTargetSdk
-                    || change.getEnableAfterTargetSdk() > sMaxTargetSdk) {
+        if (change.getEnableSinceTargetSdk() > 0) {
+            if (change.getEnableSinceTargetSdk() < sMinTargetSdk
+                    || change.getEnableSinceTargetSdk() > sMaxTargetSdk) {
                 return false;
             }
         }
diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java
index 271ec4e..c789186 100644
--- a/services/core/java/com/android/server/connectivity/DnsManager.java
+++ b/services/core/java/com/android/server/connectivity/DnsManager.java
@@ -237,7 +237,6 @@
     private final Context mContext;
     private final ContentResolver mContentResolver;
     private final IDnsResolver mDnsResolver;
-    private final MockableSystemProperties mSystemProperties;
     private final ConcurrentHashMap<Integer, PrivateDnsConfig> mPrivateDnsMap;
     // TODO: Replace the Map with SparseArrays.
     private final Map<Integer, PrivateDnsValidationStatuses> mPrivateDnsValidationMap;
@@ -249,11 +248,10 @@
     private int mMinSamples;
     private int mMaxSamples;
 
-    public DnsManager(Context ctx, IDnsResolver dnsResolver, MockableSystemProperties sp) {
+    public DnsManager(Context ctx, IDnsResolver dnsResolver) {
         mContext = ctx;
         mContentResolver = mContext.getContentResolver();
         mDnsResolver = dnsResolver;
-        mSystemProperties = sp;
         mPrivateDnsMap = new ConcurrentHashMap<>();
         mPrivateDnsValidationMap = new HashMap<>();
         mLinkPropertiesMap = new HashMap<>();
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index a600292..60c83905e 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -91,6 +91,7 @@
 import android.util.Spline;
 import android.view.Display;
 import android.view.DisplayInfo;
+import android.view.IDisplayFoldListener;
 import android.view.Surface;
 import android.view.SurfaceControl;
 
@@ -103,6 +104,7 @@
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.UiThread;
+import com.android.server.policy.WindowManagerPolicy;
 import com.android.server.wm.SurfaceAnimationThread;
 import com.android.server.wm.WindowManagerInternal;
 
@@ -312,6 +314,9 @@
     // Receives notifications about changes to Settings.
     private SettingsObserver mSettingsObserver;
 
+    // Received notifications of the display-fold action
+    private DisplayFoldListener mDisplayFoldListener;
+
     public DisplayManagerService(Context context) {
         this(context, new Injector());
     }
@@ -429,6 +434,11 @@
         synchronized (mSyncRoot) {
             mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
             mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
+            WindowManagerPolicy policy = LocalServices.getService(WindowManagerPolicy.class);
+
+            mDisplayFoldListener = new DisplayFoldListener();
+            policy.registerDisplayFoldListener(mDisplayFoldListener);
+
             scheduleTraversalLocked(false);
         }
     }
@@ -2563,13 +2573,6 @@
         public void ignoreProximitySensorUntilChanged() {
             mDisplayPowerController.ignoreProximitySensorUntilChanged();
         }
-
-        @Override
-        public void setDeviceFolded(boolean isFolded) {
-            synchronized (mSyncRoot) {
-                mLogicalDisplayMapper.setDeviceFoldedLocked(isFolded);
-            }
-        }
     }
 
     class DesiredDisplayModeSpecsObserver
@@ -2606,4 +2609,17 @@
             }
         }
     }
+
+    class DisplayFoldListener extends IDisplayFoldListener.Stub {
+        @Override
+        public void onDisplayFoldChanged(int displayId, boolean folded) {
+            // TODO: multi-display - IDisplayFoldListener callback only really works for the
+            // Display.DEFAULT_DISPLAY.
+            if (displayId == Display.DEFAULT_DISPLAY) {
+                synchronized (mSyncRoot) {
+                    mLogicalDisplayMapper.setDeviceFoldedLocked(folded);
+                }
+            }
+        }
+    };
 }
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 858cce4..6597aa5 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -69,21 +69,27 @@
 
     private final LongSparseArray<LocalDisplayDevice> mDevices = new LongSparseArray<>();
 
-    @SuppressWarnings("unused")  // Becomes active at instantiation time.
-    private PhysicalDisplayEventReceiver mPhysicalDisplayEventReceiver;
+    private final Injector mInjector;
 
 
     // Called with SyncRoot lock held.
     public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
             Context context, Handler handler, Listener listener) {
+        this(syncRoot, context, handler, listener, new Injector());
+    }
+
+    LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
+            Context context, Handler handler, Listener listener, Injector injector) {
         super(syncRoot, context, handler, listener, TAG);
+        mInjector = injector;
     }
 
     @Override
     public void registerLocked() {
         super.registerLocked();
 
-        mPhysicalDisplayEventReceiver = new PhysicalDisplayEventReceiver(getHandler().getLooper());
+        mInjector.setDisplayEventListenerLocked(getHandler().getLooper(),
+                new LocalDisplayEventListener());
 
         for (long physicalDisplayId : SurfaceControl.getPhysicalDisplayIds()) {
             tryConnectDisplayLocked(physicalDisplayId);
@@ -183,13 +189,11 @@
         private int mDefaultModeId;
         private int mDefaultConfigGroup;
         private int mActiveModeId;
-        private boolean mActiveModeInvalid;
         private DisplayModeDirector.DesiredDisplayModeSpecs mDisplayModeSpecs =
                 new DisplayModeDirector.DesiredDisplayModeSpecs();
         private boolean mDisplayModeSpecsInvalid;
         private int mActiveConfigId;
         private int mActiveColorMode;
-        private boolean mActiveColorModeInvalid;
         private Display.HdrCapabilities mHdrCapabilities;
         private boolean mAllmSupported;
         private boolean mGameContentTypeSupported;
@@ -300,7 +304,6 @@
             // Schedule traversals to ensure that the correct state is reapplied if necessary.
             if (mActiveModeId != NO_DISPLAY_MODE_ID
                     && mActiveModeId != activeRecord.mMode.getModeId()) {
-                mActiveModeInvalid = true;
                 sendTraversalRequestLocked();
             }
 
@@ -373,7 +376,6 @@
                             + " mode.");
                 }
                 mActiveModeId = mDefaultModeId;
-                mActiveModeInvalid = true;
             }
 
             // Schedule traversals so that we apply pending changes.
@@ -464,14 +466,12 @@
                     Slog.w(TAG, "Active color mode no longer available, reverting"
                             + " to default mode.");
                     mActiveColorMode = Display.COLOR_MODE_DEFAULT;
-                    mActiveColorModeInvalid = true;
                 } else {
                     if (!mSupportedColorModes.isEmpty()) {
                         // This should never happen.
                         Slog.e(TAG, "Default and active color mode is no longer available!"
                                 + " Reverting to first available mode.");
                         mActiveColorMode = mSupportedColorModes.get(0);
-                        mActiveColorModeInvalid = true;
                     } else {
                         // This should really never happen.
                         Slog.e(TAG, "No color modes available!");
@@ -848,8 +848,7 @@
             }
             mActiveConfigId = activeConfigId;
             mActiveModeId = findMatchingModeIdLocked(activeConfigId);
-            mActiveModeInvalid = mActiveModeId == NO_DISPLAY_MODE_ID;
-            if (mActiveModeInvalid) {
+            if (mActiveModeId == NO_DISPLAY_MODE_ID) {
                 Slog.w(TAG, "In unknown mode after setting allowed configs"
                         + ", activeConfigId=" + mActiveConfigId);
             }
@@ -867,7 +866,6 @@
             }
 
             mActiveColorMode = colorMode;
-            mActiveColorModeInvalid = false;
             getHandler().sendMessage(PooledLambda.obtainMessage(
                     LocalDisplayDevice::requestColorModeAsync, this,
                     getDisplayTokenLocked(), colorMode));
@@ -1052,12 +1050,33 @@
         }
     }
 
-    private final class PhysicalDisplayEventReceiver extends DisplayEventReceiver {
-        PhysicalDisplayEventReceiver(Looper looper) {
-            super(looper, VSYNC_SOURCE_APP, CONFIG_CHANGED_EVENT_DISPATCH);
+    public static class Injector {
+        private ProxyDisplayEventReceiver mReceiver;
+        public void setDisplayEventListenerLocked(Looper looper, DisplayEventListener listener) {
+            mReceiver = new ProxyDisplayEventReceiver(looper, listener);
         }
+    }
 
-        @Override
+    public interface DisplayEventListener {
+        void onHotplug(long timestampNanos, long physicalDisplayId, boolean connected);
+        void onConfigChanged(long timestampNanos, long physicalDisplayId, int configId);
+    }
+
+    public static final class ProxyDisplayEventReceiver extends DisplayEventReceiver {
+        private final DisplayEventListener mListener;
+        ProxyDisplayEventReceiver(Looper looper, DisplayEventListener listener) {
+            super(looper, VSYNC_SOURCE_APP, CONFIG_CHANGED_EVENT_DISPATCH);
+            mListener = listener;
+        }
+        public void onHotplug(long timestampNanos, long physicalDisplayId, boolean connected) {
+            mListener.onHotplug(timestampNanos, physicalDisplayId, connected);
+        }
+        public void onConfigChanged(long timestampNanos, long physicalDisplayId, int configId) {
+            mListener.onConfigChanged(timestampNanos, physicalDisplayId, configId);
+        }
+    }
+
+    private final class LocalDisplayEventListener implements DisplayEventListener {
         public void onHotplug(long timestampNanos, long physicalDisplayId, boolean connected) {
             synchronized (getSyncRoot()) {
                 if (connected) {
@@ -1067,8 +1086,6 @@
                 }
             }
         }
-
-        @Override
         public void onConfigChanged(long timestampNanos, long physicalDisplayId, int configId) {
             if (DEBUG) {
                 Slog.d(TAG, "onConfigChanged("
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index 942a12e..fc3ba35 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -167,7 +167,31 @@
         }
     }
 
-    public void setDeviceFoldedLocked(boolean isFolded) {
+    public void dumpLocked(PrintWriter pw) {
+        pw.println("LogicalDisplayMapper:");
+        IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
+        ipw.increaseIndent();
+
+        ipw.println("mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
+        ipw.println("mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
+
+        final int logicalDisplayCount = mLogicalDisplays.size();
+        ipw.println();
+        ipw.println("Logical Displays: size=" + logicalDisplayCount);
+
+
+        for (int i = 0; i < logicalDisplayCount; i++) {
+            int displayId = mLogicalDisplays.keyAt(i);
+            LogicalDisplay display = mLogicalDisplays.valueAt(i);
+            ipw.println("Display " + displayId + ":");
+            ipw.increaseIndent();
+            display.dumpLocked(ipw);
+            ipw.decreaseIndent();
+            ipw.println();
+        }
+    }
+
+    void setDeviceFoldedLocked(boolean isFolded) {
         mIsFolded = isFolded;
         if (mIsFoldedOverride != null) {
             isFolded = mIsFoldedOverride.booleanValue();
@@ -237,30 +261,6 @@
         }
     }
 
-    public void dumpLocked(PrintWriter pw) {
-        pw.println("LogicalDisplayMapper:");
-        IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
-        ipw.increaseIndent();
-
-        ipw.println("mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
-        ipw.println("mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
-
-        final int logicalDisplayCount = mLogicalDisplays.size();
-        ipw.println();
-        ipw.println("Logical Displays: size=" + logicalDisplayCount);
-
-
-        for (int i = 0; i < logicalDisplayCount; i++) {
-            int displayId = mLogicalDisplays.keyAt(i);
-            LogicalDisplay display = mLogicalDisplays.valueAt(i);
-            ipw.println("Display " + displayId + ":");
-            ipw.increaseIndent();
-            display.dumpLocked(ipw);
-            ipw.decreaseIndent();
-            ipw.println();
-        }
-    }
-
     void setFoldOverrideLocked(Boolean isFolded) {
         if (!Objects.equals(isFolded, mIsFoldedOverride)) {
             mIsFoldedOverride = isFolded;
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 793cfcd..f997352 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -382,7 +382,7 @@
         if (mPlaybackState == null) {
             return false;
         }
-        return MediaSession.isActiveState(mPlaybackState.getState()) == expected;
+        return mPlaybackState.isActiveState() == expected;
     }
 
     /**
diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java
index cb6e960..eeb2655 100644
--- a/services/core/java/com/android/server/om/IdmapManager.java
+++ b/services/core/java/com/android/server/om/IdmapManager.java
@@ -57,7 +57,7 @@
     private final PackageManagerHelper mPackageManager;
 
     /**
-     * Package name of the reference package defined in 'config-signature' tag of
+     * Package name of the reference package defined in 'overlay-config-signature' tag of
      * SystemConfig or empty String if tag not defined. This package is vetted on scan by
      * PackageManagerService that it's a system package and is used to check if overlay matches
      * its signature in order to fulfill the config_signature policy.
@@ -159,7 +159,7 @@
             fulfilledPolicies |= OverlayablePolicy.ACTOR_SIGNATURE;
         }
 
-        // If SystemConfig defines 'config-signature' package, given that
+        // If SystemConfig defines 'overlay-config-signature' package, given that
         // this package is vetted by OverlayManagerService that it's a
         // preinstalled package, check if overlay matches its signature.
         if (!TextUtils.isEmpty(mConfigSignaturePackage)
diff --git a/services/core/java/com/android/server/pm/IncrementalStates.java b/services/core/java/com/android/server/pm/IncrementalStates.java
index dda5faf..43f4a34 100644
--- a/services/core/java/com/android/server/pm/IncrementalStates.java
+++ b/services/core/java/com/android/server/pm/IncrementalStates.java
@@ -16,18 +16,21 @@
 
 package com.android.server.pm;
 
-import android.content.pm.IDataLoaderStatusListener;
+import static android.os.incremental.IStorageHealthListener.HEALTH_STATUS_OK;
+import static android.os.incremental.IStorageHealthListener.HEALTH_STATUS_UNHEALTHY;
+import static android.os.incremental.IStorageHealthListener.HEALTH_STATUS_UNHEALTHY_STORAGE;
+import static android.os.incremental.IStorageHealthListener.HEALTH_STATUS_UNHEALTHY_TRANSPORT;
+
 import android.content.pm.IncrementalStatesInfo;
 import android.content.pm.PackageManager;
 import android.os.Handler;
-import android.os.incremental.IStorageHealthListener;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.function.pooled.PooledLambda;
 
-import java.util.function.BiConsumer;
+import java.util.function.Consumer;
 
 /**
  * Manages state transitions of a package installed on Incremental File System. Currently manages:
@@ -36,8 +39,7 @@
  *
  * The following events might change the states of a package:
  * 1. Installation commit
- * 2. Incremental storage health
- * 3. Data loader stream health
+ * 2. Incremental storage health changes
  * 4. Loading progress changes
  *
  * @hide
@@ -48,16 +50,14 @@
     private final Handler mHandler = BackgroundThread.getHandler();
     private final Object mLock = new Object();
     @GuardedBy("mLock")
-    private int mStreamStatus = IDataLoaderStatusListener.STREAM_HEALTHY;
-    @GuardedBy("mLock")
-    private int mStorageHealthStatus = IStorageHealthListener.HEALTH_STATUS_OK;
+    private int mStorageHealthStatus = HEALTH_STATUS_OK;
     @GuardedBy("mLock")
     private final LoadingState mLoadingState;
     @GuardedBy("mLock")
     private StartableState mStartableState;
     @GuardedBy("mLock")
     private Callback mCallback = null;
-    private final BiConsumer<Integer, Integer> mStatusConsumer;
+    private final Consumer<Integer> mStatusConsumer;
 
     public IncrementalStates() {
         // By default the package is not startable and not fully loaded (i.e., is loading)
@@ -148,12 +148,9 @@
         }
     }
 
-    private class StatusConsumer implements BiConsumer<Integer, Integer> {
+    private class StatusConsumer implements Consumer<Integer> {
         @Override
-        public void accept(Integer streamStatus, Integer storageStatus) {
-            if (streamStatus == null && storageStatus == null) {
-                return;
-            }
+        public void accept(Integer storageStatus) {
             final boolean oldState, newState;
             synchronized (mLock) {
                 if (!mLoadingState.isLoading()) {
@@ -161,12 +158,7 @@
                     return;
                 }
                 oldState = mStartableState.isStartable();
-                if (streamStatus != null) {
-                    mStreamStatus = (Integer) streamStatus;
-                }
-                if (storageStatus != null) {
-                    mStorageHealthStatus = (Integer) storageStatus;
-                }
+                mStorageHealthStatus = storageStatus;
                 updateStartableStateLocked();
                 newState = mStartableState.isStartable();
             }
@@ -188,21 +180,7 @@
             Slog.i(TAG, "received storage health status changed event : storageHealthStatus="
                     + storageHealthStatus);
         }
-        mStatusConsumer.accept(null, storageHealthStatus);
-    }
-
-    /**
-     * By calling this method, the caller indicates that the stream status of the package has
-     * been
-     * changed. This could indicate a streaming error. The state will change according to the
-     * status
-     * code defined in {@code IDataLoaderStatusListener}.
-     */
-    public void onStreamStatusChanged(int streamState) {
-        if (DEBUG) {
-            Slog.i(TAG, "received stream status changed event : streamState=" + streamState);
-        }
-        mStatusConsumer.accept(streamState, null);
+        mStatusConsumer.accept(storageHealthStatus);
     }
 
     /**
@@ -284,35 +262,16 @@
         final boolean currentState = mStartableState.isStartable();
         boolean nextState = currentState;
         if (!currentState) {
-            if (mStorageHealthStatus == IStorageHealthListener.HEALTH_STATUS_OK
-                    && mStreamStatus == IDataLoaderStatusListener.STREAM_HEALTHY) {
-                // change from unstartable -> startable when both stream and storage are healthy
+            if (mStorageHealthStatus == HEALTH_STATUS_OK) {
+                // change from unstartable -> startable
                 nextState = true;
             }
         } else {
-            if (mStorageHealthStatus == IStorageHealthListener.HEALTH_STATUS_UNHEALTHY) {
-                // unrecoverable if storage is unhealthy
+            if (mStorageHealthStatus == HEALTH_STATUS_UNHEALTHY
+                    || mStorageHealthStatus == HEALTH_STATUS_UNHEALTHY_STORAGE
+                    || mStorageHealthStatus == HEALTH_STATUS_UNHEALTHY_TRANSPORT) {
+                // change from startable -> unstartable
                 nextState = false;
-            } else {
-                switch (mStreamStatus) {
-                    case IDataLoaderStatusListener.STREAM_INTEGRITY_ERROR:
-                        // unrecoverable, fall through
-                    case IDataLoaderStatusListener.STREAM_SOURCE_ERROR: {
-                        // unrecoverable
-                        nextState = false;
-                        break;
-                    }
-                    case IDataLoaderStatusListener.STREAM_STORAGE_ERROR: {
-                        if (mStorageHealthStatus != IStorageHealthListener.HEALTH_STATUS_OK) {
-                            // unrecoverable if there is a pending read AND storage is limited
-                            nextState = false;
-                        }
-                        break;
-                    }
-                    default:
-                        // anything else, remain startable
-                        break;
-                }
             }
         }
         if (nextState == currentState) {
@@ -370,17 +329,11 @@
                 return PackageManager.UNSTARTABLE_REASON_UNKNOWN;
             }
             // Translate stream status to reason for unstartable state
-            switch (mStreamStatus) {
-                case IDataLoaderStatusListener.STREAM_TRANSPORT_ERROR:
-                    // fall through
-                case IDataLoaderStatusListener.STREAM_INTEGRITY_ERROR:
-                    // fall through
-                case IDataLoaderStatusListener.STREAM_SOURCE_ERROR: {
-                    return PackageManager.UNSTARTABLE_REASON_DATALOADER_TRANSPORT;
-                }
-                case IDataLoaderStatusListener.STREAM_STORAGE_ERROR: {
-                    return PackageManager.UNSTARTABLE_REASON_DATALOADER_STORAGE;
-                }
+            switch (mStorageHealthStatus) {
+                case HEALTH_STATUS_UNHEALTHY_STORAGE:
+                    return PackageManager.UNSTARTABLE_REASON_INSUFFICIENT_STORAGE;
+                case HEALTH_STATUS_UNHEALTHY_TRANSPORT:
+                    return PackageManager.UNSTARTABLE_REASON_CONNECTION_ERROR;
                 default:
                     return PackageManager.UNSTARTABLE_REASON_UNKNOWN;
             }
@@ -464,7 +417,6 @@
         }
         IncrementalStates l = (IncrementalStates) o;
         return l.mStorageHealthStatus == mStorageHealthStatus
-                && l.mStreamStatus == mStreamStatus
                 && l.mStartableState.equals(mStartableState)
                 && l.mLoadingState.equals(mLoadingState);
     }
@@ -474,7 +426,6 @@
         int hashCode = mStartableState.hashCode();
         hashCode = 31 * hashCode + mLoadingState.hashCode();
         hashCode = 31 * hashCode + mStorageHealthStatus;
-        hashCode = 31 * hashCode + mStreamStatus;
         return hashCode;
     }
 }
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 649cafb..5d2928e 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -143,7 +143,6 @@
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
-import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.LocalServices;
 import com.android.server.pm.Installer.InstallerException;
 import com.android.server.pm.dex.DexManager;
@@ -1702,28 +1701,6 @@
         dispatchSessionFinished(error, detailedMessage, null);
     }
 
-    private void onStorageHealthStatusChanged(int status) {
-        final String packageName = getPackageName();
-        if (TextUtils.isEmpty(packageName)) {
-            // The package has not been installed.
-            return;
-        }
-        mHandler.post(PooledLambda.obtainRunnable(
-                PackageManagerService::onStorageHealthStatusChanged,
-                mPm, packageName, status, userId).recycleOnUse());
-    }
-
-    private void onStreamHealthStatusChanged(int status) {
-        final String packageName = getPackageName();
-        if (TextUtils.isEmpty(packageName)) {
-            // The package has not been installed.
-            return;
-        }
-        mHandler.post(PooledLambda.obtainRunnable(
-                PackageManagerService::onStreamStatusChanged,
-                mPm, packageName, status, userId).recycleOnUse());
-    }
-
     /**
      * If session should be sealed, then it's sealed to prevent further modification.
      * If the session can't be sealed then it's destroyed.
@@ -3315,19 +3292,11 @@
                         return;
                 }
 
-                final boolean isDestroyedOrDataLoaderFinished;
                 synchronized (mLock) {
-                    isDestroyedOrDataLoaderFinished = mDestroyed || mDataLoaderFinished;
-                }
-                if (isDestroyedOrDataLoaderFinished) {
-                    switch (status) {
-                        case IDataLoaderStatusListener.DATA_LOADER_UNRECOVERABLE:
-                            // treat as unhealthy storage
-                            onStorageHealthStatusChanged(
-                                    IStorageHealthListener.HEALTH_STATUS_UNHEALTHY);
-                            return;
+                    if (mDestroyed || mDataLoaderFinished) {
+                        // No need to worry about post installation
+                        return;
                     }
-                    return;
                 }
 
                 try {
@@ -3423,13 +3392,10 @@
             }
             @Override
             public void reportStreamHealth(int dataLoaderId, int streamStatus) {
-                synchronized (mLock) {
-                    if (!mDestroyed && !mDataLoaderFinished) {
-                        // ignore streaming status if package isn't installed
-                        return;
-                    }
-                }
-                onStreamHealthStatusChanged(streamStatus);
+                // Currently the stream status is not used during package installation. It is
+                // technically possible for the data loader to report stream status via this
+                // callback, but if something is wrong with the streaming, it is more likely that
+                // prepareDataLoaderLocked will return false and the installation will be aborted.
             }
         };
 
@@ -3438,20 +3404,16 @@
             healthCheckParams.blockedTimeoutMs = INCREMENTAL_STORAGE_BLOCKED_TIMEOUT_MS;
             healthCheckParams.unhealthyTimeoutMs = INCREMENTAL_STORAGE_UNHEALTHY_TIMEOUT_MS;
             healthCheckParams.unhealthyMonitoringMs = INCREMENTAL_STORAGE_UNHEALTHY_MONITORING_MS;
-
             final boolean systemDataLoader =
                     params.getComponentName().getPackageName() == SYSTEM_DATA_LOADER_PACKAGE;
             final IStorageHealthListener healthListener = new IStorageHealthListener.Stub() {
                 @Override
                 public void onHealthStatus(int storageId, int status) {
-                    final boolean isDestroyedOrDataLoaderFinished;
                     synchronized (mLock) {
-                        isDestroyedOrDataLoaderFinished = mDestroyed || mDataLoaderFinished;
-                    }
-                    if (isDestroyedOrDataLoaderFinished) {
-                        // App's installed.
-                        onStorageHealthStatusChanged(status);
-                        return;
+                        if (mDestroyed || mDataLoaderFinished) {
+                            // No need to worry about post installation
+                            return;
+                        }
                     }
 
                     switch (status) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index d529f0e..3f16abf 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -271,8 +271,10 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.UserManagerInternal;
+import android.os.incremental.IStorageHealthListener;
 import android.os.incremental.IncrementalManager;
 import android.os.incremental.IncrementalStorage;
+import android.os.incremental.StorageHealthCheckParams;
 import android.os.storage.DiskInfo;
 import android.os.storage.IStorageManager;
 import android.os.storage.StorageEventListener;
@@ -506,9 +508,6 @@
 
     private static final boolean HIDE_EPHEMERAL_APIS = false;
 
-    private static final boolean ENABLE_FREE_CACHE_V2 =
-            SystemProperties.getBoolean("fw.free_cache_v2", true);
-
     private static final String PRECOMPILE_LAYOUTS = "pm.precompile_layouts";
 
     private static final int RADIO_UID = Process.PHONE_UID;
@@ -732,14 +731,23 @@
 
     private static final String RANDOM_DIR_PREFIX = "~~";
 
+    /**
+     * Timeout configurations for incremental storage health monitor.
+     * See {@link IStorageHealthListener}
+     */
+    private static final int INCREMENTAL_STORAGE_BLOCKED_TIMEOUT_MS = 2000;
+    private static final int INCREMENTAL_STORAGE_UNHEALTHY_TIMEOUT_MS = 7000;
+    private static final int INCREMENTAL_STORAGE_UNHEALTHY_MONITORING_MS = 60000;
+
     final ServiceThread mHandlerThread;
 
     final Handler mHandler;
 
     private final ProcessLoggingHandler mProcessLoggingHandler;
 
-    final int mSdkVersion = Build.VERSION.SDK_INT;
+    private final boolean mEnableFreeCacheV2;
 
+    final int mSdkVersion;
     final Context mContext;
     final boolean mFactoryTest;
     final boolean mOnlyCore;
@@ -894,24 +902,8 @@
             T produce(Injector injector, PackageManagerService packageManager);
         }
 
-        static class LocalServicesProducer<T> implements Producer<T> {
-            private final Class<T> mProducingClass;
-            LocalServicesProducer(Class<T> clazz) {
-                this.mProducingClass = clazz;
-            }
-            public T produce(Injector injector, PackageManagerService packageManager) {
-                return LocalServices.getService(mProducingClass);
-            }
-        }
-
-        static class SystemServiceProducer<T> implements Producer<T> {
-            private final Class<T> mProducingClass;
-            SystemServiceProducer(Class<T> clazz) {
-                this.mProducingClass = clazz;
-            }
-            public T produce(Injector injector, PackageManagerService packageManager) {
-                return packageManager.mContext.getSystemService(mProducingClass);
-            }
+        interface ServiceProducer {
+            <T> T produce(Class<T> c);
         }
 
         @VisibleForTesting(visibility = Visibility.PRIVATE)
@@ -941,41 +933,43 @@
 
         // ----- producers -----
         private final Singleton<ComponentResolver> mComponentResolverProducer;
-        private final Singleton<PermissionManagerServiceInternal> mPermissionManagerProducer;
+        private final Singleton<PermissionManagerServiceInternal> mPermissionManagerServiceProducer;
         private final Singleton<UserManagerService> mUserManagerProducer;
         private final Singleton<Settings> mSettingsProducer;
-        private final Singleton<ActivityTaskManagerInternal> mActivityTaskManagerProducer;
-        private final Singleton<ActivityManagerInternal> mActivityManagerInternalProducer;
-        private final Singleton<DeviceIdleInternal> mLocalDeviceIdleController;
-        private final Singleton<StorageManagerInternal> mStorageManagerInternalProducer;
-        private final Singleton<NetworkPolicyManagerInternal> mNetworkPolicyManagerProducer;
-        private final Singleton<PermissionPolicyInternal> mPermissionPolicyProducer;
-        private final Singleton<DeviceStorageMonitorInternal> mDeviceStorageMonitorProducer;
-        private final Singleton<DisplayManager> mDisplayManagerProducer;
-        private final Singleton<StorageManager> mStorageManagerProducer;
-        private final Singleton<AppOpsManager> mAppOpsManagerProducer;
         private final Singleton<AppsFilter> mAppsFilterProducer;
         private final Singleton<PlatformCompat> mPlatformCompatProducer;
+        private final Singleton<SystemConfig> mSystemConfigProducer;
+        private final Singleton<PackageDexOptimizer> mPackageDexOptimizerProducer;
+        private final Singleton<DexManager> mDexManagerProducer;
+        private final Singleton<ArtManagerService> mArtManagerServiceProducer;
+        private final Singleton<ApexManager> mApexManagerProducer;
+        private final Singleton<ViewCompiler> mViewCompilerProducer;
+        private final Singleton<IPermissionManager> mPermissionManagerProducer;
+        private final Singleton<IncrementalManager> mIncrementalManagerProducer;
+        private final SystemWrapper mSystemWrapper;
+        private final ServiceProducer mGetLocalServiceProducer;
+        private final ServiceProducer mGetSystemServiceProducer;
 
         Injector(Context context, Object lock, Installer installer,
                 Object installLock, PackageAbiHelper abiHelper,
                 Handler backgroundHandler,
                 Producer<ComponentResolver> componentResolverProducer,
-                Producer<PermissionManagerServiceInternal> permissionManagerProducer,
+                Producer<PermissionManagerServiceInternal> permissionManagerServiceProducer,
                 Producer<UserManagerService> userManagerProducer,
                 Producer<Settings> settingsProducer,
-                Producer<ActivityTaskManagerInternal> activityTaskManagerProducer,
-                Producer<ActivityManagerInternal> activityManagerInternalProducer,
-                Producer<DeviceIdleInternal> deviceIdleControllerProducer,
-                Producer<StorageManagerInternal> storageManagerInternalProducer,
-                Producer<NetworkPolicyManagerInternal> networkPolicyManagerProducer,
-                Producer<PermissionPolicyInternal> permissionPolicyProvider,
-                Producer<DeviceStorageMonitorInternal> deviceStorageMonitorProducer,
-                Producer<DisplayManager> displayManagerProducer,
-                Producer<StorageManager> storageManagerProducer,
-                Producer<AppOpsManager> appOpsManagerProducer,
                 Producer<AppsFilter> appsFilterProducer,
-                Producer<PlatformCompat> platformCompatProducer) {
+                Producer<PlatformCompat> platformCompatProducer,
+                Producer<SystemConfig> systemConfigProducer,
+                Producer<PackageDexOptimizer> packageDexOptimizerProducer,
+                Producer<DexManager> dexManagerProducer,
+                Producer<ArtManagerService> artManagerServiceProducer,
+                Producer<ApexManager> apexManagerProducer,
+                Producer<IPermissionManager> permissionManagerProducer,
+                Producer<ViewCompiler> viewCompilerProducer,
+                Producer<IncrementalManager> incrementalManagerProducer,
+                SystemWrapper systemWrapper,
+                ServiceProducer getLocalServiceProducer,
+                ServiceProducer getSystemServiceProducer) {
             mContext = context;
             mLock = lock;
             mInstaller = installer;
@@ -984,21 +978,22 @@
             mBackgroundHandler = backgroundHandler;
             mBackgroundExecutor = new HandlerExecutor(backgroundHandler);
             mComponentResolverProducer = new Singleton<>(componentResolverProducer);
-            mPermissionManagerProducer = new Singleton<>(permissionManagerProducer);
+            mPermissionManagerServiceProducer = new Singleton<>(permissionManagerServiceProducer);
             mUserManagerProducer = new Singleton<>(userManagerProducer);
             mSettingsProducer = new Singleton<>(settingsProducer);
-            mActivityTaskManagerProducer = new Singleton<>(activityTaskManagerProducer);
-            mActivityManagerInternalProducer = new Singleton<>(activityManagerInternalProducer);
-            mLocalDeviceIdleController = new Singleton<>(deviceIdleControllerProducer);
-            mStorageManagerInternalProducer = new Singleton<>(storageManagerInternalProducer);
-            mNetworkPolicyManagerProducer = new Singleton<>(networkPolicyManagerProducer);
-            mPermissionPolicyProducer = new Singleton<>(permissionPolicyProvider);
-            mDeviceStorageMonitorProducer = new Singleton<>(deviceStorageMonitorProducer);
-            mDisplayManagerProducer = new Singleton<>(displayManagerProducer);
-            mStorageManagerProducer = new Singleton<>(storageManagerProducer);
-            mAppOpsManagerProducer = new Singleton<>(appOpsManagerProducer);
             mAppsFilterProducer = new Singleton<>(appsFilterProducer);
             mPlatformCompatProducer = new Singleton<>(platformCompatProducer);
+            mSystemConfigProducer = new Singleton<>(systemConfigProducer);
+            mPackageDexOptimizerProducer = new Singleton<>(packageDexOptimizerProducer);
+            mDexManagerProducer = new Singleton<>(dexManagerProducer);
+            mArtManagerServiceProducer = new Singleton<>(artManagerServiceProducer);
+            mApexManagerProducer = new Singleton<>(apexManagerProducer);
+            mPermissionManagerProducer = new Singleton<>(permissionManagerProducer);
+            mViewCompilerProducer = new Singleton<>(viewCompilerProducer);
+            mIncrementalManagerProducer = new Singleton<>(incrementalManagerProducer);
+            mSystemWrapper = systemWrapper;
+            mGetLocalServiceProducer = getLocalServiceProducer;
+            mGetSystemServiceProducer = getSystemServiceProducer;
         }
 
         /**
@@ -1038,7 +1033,7 @@
         }
 
         public PermissionManagerServiceInternal getPermissionManagerServiceInternal() {
-            return mPermissionManagerProducer.get(this, mPackageManager);
+            return mPermissionManagerServiceProducer.get(this, mPackageManager);
         }
 
         public Context getContext() {
@@ -1049,46 +1044,6 @@
             return mSettingsProducer.get(this, mPackageManager);
         }
 
-        public ActivityTaskManagerInternal getActivityTaskManagerInternal() {
-            return mActivityTaskManagerProducer.get(this, mPackageManager);
-        }
-
-        public ActivityManagerInternal getActivityManagerInternal() {
-            return mActivityManagerInternalProducer.get(this, mPackageManager);
-        }
-
-        public DeviceIdleInternal getLocalDeviceIdleController() {
-            return mLocalDeviceIdleController.get(this, mPackageManager);
-        }
-
-        public StorageManagerInternal getStorageManagerInternal() {
-            return mStorageManagerInternalProducer.get(this, mPackageManager);
-        }
-
-        public NetworkPolicyManagerInternal getNetworkPolicyManagerInternal() {
-            return mNetworkPolicyManagerProducer.get(this, mPackageManager);
-        }
-
-        public PermissionPolicyInternal getPermissionPolicyInternal() {
-            return mPermissionPolicyProducer.get(this, mPackageManager);
-        }
-
-        public DeviceStorageMonitorInternal getDeviceStorageMonitorInternal() {
-            return mDeviceStorageMonitorProducer.get(this, mPackageManager);
-        }
-
-        public DisplayManager getDisplayManager() {
-            return mDisplayManagerProducer.get(this, mPackageManager);
-        }
-
-        public StorageManager getStorageManager() {
-            return mStorageManagerProducer.get(this, mPackageManager);
-        }
-
-        public AppOpsManager getAppOpsManager() {
-            return mAppOpsManagerProducer.get(this, mPackageManager);
-        }
-
         public AppsFilter getAppsFilter() {
             return mAppsFilterProducer.get(this, mPackageManager);
         }
@@ -1097,6 +1052,34 @@
             return mPlatformCompatProducer.get(this, mPackageManager);
         }
 
+        public SystemConfig getSystemConfig() {
+            return mSystemConfigProducer.get(this, mPackageManager);
+        }
+
+        public PackageDexOptimizer getPackageDexOptimizer() {
+            return mPackageDexOptimizerProducer.get(this, mPackageManager);
+        }
+
+        public DexManager getDexManager() {
+            return mDexManagerProducer.get(this, mPackageManager);
+        }
+
+        public ArtManagerService getArtManagerService() {
+            return mArtManagerServiceProducer.get(this, mPackageManager);
+        }
+
+        public ApexManager getApexManager() {
+            return mApexManagerProducer.get(this, mPackageManager);
+        }
+
+        public ViewCompiler getViewCompiler() {
+            return mViewCompilerProducer.get(this, mPackageManager);
+        }
+
+        public IPermissionManager getPermissionManagerService() {
+            return mPermissionManagerProducer.get(this, mPackageManager);
+        }
+
         public Handler getBackgroundHandler() {
             return mBackgroundHandler;
         }
@@ -1104,6 +1087,70 @@
         public Executor getBackgroundExecutor() {
             return mBackgroundExecutor;
         }
+
+        public <T> T getLocalService(Class<T> c) {
+            return mGetLocalServiceProducer.produce(c);
+        }
+
+        public <T> T getSystemService(Class<T> c) {
+            return mGetSystemServiceProducer.produce(c);
+        }
+
+        public SystemWrapper getSystemWrapper() {
+            return mSystemWrapper;
+        }
+
+        public IncrementalManager getIncrementalManager() {
+            return mIncrementalManagerProducer.get(this, mPackageManager);
+        }
+    }
+
+    /** Provides an abstraction to static access to system state. */
+    public interface SystemWrapper {
+        /** @see SystemProperties#get(String) */
+        String getProperty(String key);
+        /** @see SystemProperties#getInt(String, int) */
+        int getPropertyInt(String key, int defValue);
+        /** @see SystemProperties#getBoolean(String, boolean) */
+        boolean getPropertyBoolean(String key, boolean defValue);
+        /** @see SystemProperties#digestOf(String...) */
+        String digestOfProperties(@NonNull String... keys);
+        /** @see SystemProperties#set(String, String) */
+        void setProperty(String key, String value);
+        /** @see Build.VERSION#SDK_INT */
+        int getSdkInt();
+    }
+
+    private static class DefaultSystemWrapper implements SystemWrapper {
+        @Override
+        public String getProperty(String key) {
+            return SystemProperties.get(key);
+        }
+
+        @Override
+        public int getPropertyInt(String key, int defValue) {
+            return SystemProperties.getInt(key, defValue);
+        }
+
+        @Override
+        public boolean getPropertyBoolean(String key, boolean defValue) {
+            return SystemProperties.getBoolean(key, defValue);
+        }
+
+        @Override
+        public String digestOfProperties(String... keys) {
+            return SystemProperties.digestOf(keys);
+        }
+
+        @Override
+        public void setProperty(String key, String value) {
+            SystemProperties.set(key, value);
+        }
+
+        @Override
+        public int getSdkInt() {
+            return Build.VERSION.SDK_INT;
+        }
     }
 
     @VisibleForTesting(visibility = Visibility.PRIVATE)
@@ -1161,6 +1208,8 @@
         public @Nullable String retailDemoPackage;
         public ComponentName resolveComponentName;
         public ArrayMap<String, AndroidPackage> packages;
+        public boolean enableFreeCacheV2;
+        public int sdkVersion;
     }
 
     private final AppsFilter mAppsFilter;
@@ -1354,7 +1403,7 @@
             options.setTemporaryAppWhitelistDuration(whitelistTimeout);
 
             DeviceIdleInternal idleController =
-                    mInjector.getLocalDeviceIdleController();
+                    mInjector.getLocalService(DeviceIdleInternal.class);
             idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
                     mIntentFilterVerifierComponent.getPackageName(), whitelistTimeout,
                     UserHandle.USER_SYSTEM, true, "intent filter verifier");
@@ -1427,7 +1476,7 @@
                         case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS:
                             if (!verified) {
                                 // Don't demote if sysconfig says 'always'
-                                SystemConfig systemConfig = SystemConfig.getInstance();
+                                SystemConfig systemConfig = mInjector.getSystemConfig();
                                 ArraySet<String> packages = systemConfig.getLinkedApps();
                                 if (!packages.contains(packageName)) {
                                     // updatedStatus is already UNDEFINED
@@ -2324,7 +2373,8 @@
                 // Send broadcast package appeared if external for all users
                 if (res.pkg.isExternalStorage()) {
                     if (!update) {
-                        final StorageManager storage = mInjector.getStorageManager();
+                        final StorageManager storage = mInjector.getSystemService(
+                                StorageManager.class);
                         VolumeInfo volume =
                                 storage.findVolumeByUuid(
                                         res.pkg.getStorageUuid().toString());
@@ -2503,7 +2553,7 @@
             ApkChecksums.Injector injector = new ApkChecksums.Injector(
                     () -> mContext,
                     () -> mInjector.getBackgroundHandler(),
-                    () -> mContext.getSystemService(IncrementalManager.class));
+                    () -> mInjector.getIncrementalManager());
             ApkChecksums.getChecksums(filesToChecksum, optional, required, trustedCerts,
                     statusReceiver, injector);
         });
@@ -2679,31 +2729,32 @@
         Injector injector = new Injector(
                 context, lock, installer, installLock, new PackageAbiHelperImpl(),
                 backgroundHandler,
-                (i, pm) ->
-                        new ComponentResolver(i.getUserManagerService(), pm.mPmInternal, lock),
-                (i, pm) ->
-                PermissionManagerService.create(context, lock),
-                (i, pm) ->
-                new UserManagerService(context, pm,
+                (i, pm) -> new ComponentResolver(i.getUserManagerService(), pm.mPmInternal, lock),
+                (i, pm) -> PermissionManagerService.create(context, lock),
+                (i, pm) -> new UserManagerService(context, pm,
                         new UserDataPreparer(installer, installLock, context, onlyCore),
                         lock),
-                (i, pm) ->
-                        new Settings(Environment.getDataDirectory(),
-                                i.getPermissionManagerServiceInternal().getPermissionSettings(),
-                                RuntimePermissionsPersistence.createInstance(),
-                                i.getPermissionManagerServiceInternal(), lock),
-                new Injector.LocalServicesProducer<>(ActivityTaskManagerInternal.class),
-                new Injector.LocalServicesProducer<>(ActivityManagerInternal.class),
-                new Injector.LocalServicesProducer<>(DeviceIdleInternal.class),
-                new Injector.LocalServicesProducer<>(StorageManagerInternal.class),
-                new Injector.LocalServicesProducer<>(NetworkPolicyManagerInternal.class),
-                new Injector.LocalServicesProducer<>(PermissionPolicyInternal.class),
-                new Injector.LocalServicesProducer<>(DeviceStorageMonitorInternal.class),
-                new Injector.SystemServiceProducer<>(DisplayManager.class),
-                new Injector.SystemServiceProducer<>(StorageManager.class),
-                new Injector.SystemServiceProducer<>(AppOpsManager.class),
+                (i, pm) -> new Settings(Environment.getDataDirectory(),
+                        i.getPermissionManagerServiceInternal().getPermissionSettings(),
+                        RuntimePermissionsPersistence.createInstance(),
+                        i.getPermissionManagerServiceInternal(), lock),
                 (i, pm) -> AppsFilter.create(pm.mPmInternal, i),
-                (i, pm) -> (PlatformCompat) ServiceManager.getService("platform_compat"));
+                (i, pm) -> (PlatformCompat) ServiceManager.getService("platform_compat"),
+                (i, pm) -> SystemConfig.getInstance(),
+                (i, pm) -> new PackageDexOptimizer(i.getInstaller(), i.getInstallLock(),
+                        i.getContext(), "*dexopt*"),
+                (i, pm) -> new DexManager(i.getContext(), pm, i.getPackageDexOptimizer(),
+                        i.getInstaller(), i.getInstallLock()),
+                (i, pm) -> new ArtManagerService(i.getContext(), pm, i.getInstaller(),
+                        i.getInstallLock()),
+                (i, pm) -> ApexManager.getInstance(),
+                (i, pm) -> (IPermissionManager) ServiceManager.getService("permissionmgr"),
+                (i, pm) -> new ViewCompiler(i.getInstallLock(), i.getInstaller()),
+                (i, pm) -> (IncrementalManager)
+                        pm.mContext.getSystemService(Context.INCREMENTAL_SERVICE),
+                new DefaultSystemWrapper(),
+                LocalServices::getService,
+                context::getSystemService);
 
         PackageManagerService m = new PackageManagerService(injector, onlyCore, factoryTest);
         t.traceEnd(); // "create package manager"
@@ -2776,16 +2827,17 @@
      * reasons. This simply requests that the copy takes place and awaits confirmation of its
      * completion. See platform/system/extras/cppreopt/ for the implementation of the actual copy.
      */
-    private static void requestCopyPreoptedFiles() {
+    private static void requestCopyPreoptedFiles(Injector injector) {
         final int WAIT_TIME_MS = 100;
         final String CP_PREOPT_PROPERTY = "sys.cppreopt";
-        if (SystemProperties.getInt("ro.cp_system_other_odex", 0) == 1) {
-            SystemProperties.set(CP_PREOPT_PROPERTY, "requested");
+        if (injector.getSystemWrapper().getPropertyInt("ro.cp_system_other_odex", 0) == 1) {
+            injector.getSystemWrapper().setProperty(CP_PREOPT_PROPERTY, "requested");
             // We will wait for up to 100 seconds.
             final long timeStart = SystemClock.uptimeMillis();
             final long timeEnd = timeStart + 100 * 1000;
             long timeNow = timeStart;
-            while (!SystemProperties.get(CP_PREOPT_PROPERTY).equals("finished")) {
+            while (!injector.getSystemWrapper()
+                    .getProperty(CP_PREOPT_PROPERTY).equals("finished")) {
                 try {
                     Thread.sleep(WAIT_TIME_MS);
                 } catch (InterruptedException e) {
@@ -2793,7 +2845,7 @@
                 }
                 timeNow = SystemClock.uptimeMillis();
                 if (timeNow > timeEnd) {
-                    SystemProperties.set(CP_PREOPT_PROPERTY, "timed-out");
+                    injector.getSystemWrapper().setProperty(CP_PREOPT_PROPERTY, "timed-out");
                     Slog.wtf(TAG, "cppreopt did not finish!");
                     break;
                 }
@@ -2925,6 +2977,8 @@
 
         mResolveComponentName = testParams.resolveComponentName;
         mPackages.putAll(testParams.packages);
+        mEnableFreeCacheV2 = testParams.enableFreeCacheV2;
+        mSdkVersion = testParams.sdkVersion;
     }
 
     public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest) {
@@ -2950,6 +3004,7 @@
         LockGuard.installLock(mLock, LockGuard.INDEX_PACKAGES);
         EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
                 SystemClock.uptimeMillis());
+        mSdkVersion = injector.getSystemWrapper().getSdkInt();
 
         if (mSdkVersion <= 0) {
             Slog.w(TAG, "**** ro.build.version.sdk not set!");
@@ -2960,6 +3015,8 @@
         mOnlyCore = onlyCore;
         mMetrics = new DisplayMetrics();
         mInstaller = injector.getInstaller();
+        mEnableFreeCacheV2 =
+                injector.getSystemWrapper().getPropertyBoolean("fw.free_cache_v2", true);
 
         // Create sub-components that provide services / data. Order here is important.
         t.traceBegin("createSubComponents");
@@ -2971,9 +3028,8 @@
         mComponentResolver = injector.getComponentResolver();
         mPermissionManager = injector.getPermissionManagerServiceInternal();
         mSettings = injector.getSettings();
-        mPermissionManagerService = (IPermissionManager) ServiceManager.getService("permissionmgr");
-        mIncrementalManager =
-                (IncrementalManager) mContext.getSystemService(Context.INCREMENTAL_SERVICE);
+        mPermissionManagerService = injector.getPermissionManagerService();
+        mIncrementalManager = mInjector.getIncrementalManager();
         PlatformCompat platformCompat = mInjector.getCompatibility();
         mPackageParserCallback = new PackageParser2.Callback() {
             @Override
@@ -3009,7 +3065,8 @@
                 ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
         t.traceEnd();
 
-        String separateProcesses = SystemProperties.get("debug.separate_processes");
+        String separateProcesses =
+                injector.getSystemWrapper().getProperty("debug.separate_processes");
         if (separateProcesses != null && separateProcesses.length() > 0) {
             if ("*".equals(separateProcesses)) {
                 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
@@ -3026,25 +3083,22 @@
             mSeparateProcesses = null;
         }
 
-        mPackageDexOptimizer = new PackageDexOptimizer(mInstaller, mInstallLock, mContext,
-                "*dexopt*");
-        mDexManager =
-                new DexManager(mContext, this, mPackageDexOptimizer, mInstaller, mInstallLock);
-        mArtManagerService = new ArtManagerService(mContext, this, mInstaller, mInstallLock);
+        mPackageDexOptimizer = injector.getPackageDexOptimizer();
+        mDexManager = injector.getDexManager();
+        mArtManagerService = injector.getArtManagerService();
         mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());
+        mViewCompiler = injector.getViewCompiler();
 
-        mViewCompiler = new ViewCompiler(mInstallLock, mInstaller);
-
-        getDefaultDisplayMetrics(mInjector.getDisplayManager(), mMetrics);
+        getDefaultDisplayMetrics(mInjector.getSystemService(DisplayManager.class), mMetrics);
 
         t.traceBegin("get system config");
-        SystemConfig systemConfig = SystemConfig.getInstance();
+        SystemConfig systemConfig = injector.getSystemConfig();
         mAvailableFeatures = systemConfig.getAvailableFeatures();
         t.traceEnd();
 
         mProtectedPackages = new ProtectedPackages(mContext);
 
-        mApexManager = ApexManager.getInstance();
+        mApexManager = injector.getApexManager();
         mAppsFilter = mInjector.getAppsFilter();
 
         final List<ScanPartition> scanPartitions = new ArrayList<>();
@@ -3122,7 +3176,7 @@
             }
 
             if (!mOnlyCore && mFirstBoot) {
-                requestCopyPreoptedFiles();
+                requestCopyPreoptedFiles(mInjector);
             }
 
             String customResolverActivityName = Resources.getSystem().getString(
@@ -3177,7 +3231,7 @@
                 }
             }
 
-            mCacheDir = preparePackageParserCache();
+            mCacheDir = preparePackageParserCache(injector);
 
             // Set flag to monitor and not change apk file paths when
             // scanning install directories.
@@ -4000,7 +4054,7 @@
         setUpInstantAppInstallerActivityLP(getInstantAppInstallerLPr());
     }
 
-    private static @Nullable File preparePackageParserCache() {
+    private static @Nullable File preparePackageParserCache(Injector injector) {
         if (!FORCE_PACKAGE_PARSED_CACHE_ENABLED) {
             if (!DEFAULT_PACKAGE_PARSER_CACHE_ENABLED) {
                 return null;
@@ -4011,7 +4065,8 @@
                 return null;
             }
 
-            if (SystemProperties.getBoolean("pm.boot.disable_package_cache", false)) {
+            if (injector.getSystemWrapper()
+                    .getPropertyBoolean("pm.boot.disable_package_cache", false)) {
                 Slog.i(TAG, "Disabling package parser cache due to system property.");
                 return null;
             }
@@ -4027,7 +4082,7 @@
         // identify cached items. In particular, changing the value of certain
         // feature flags should cause us to invalidate any caches.
         final String cacheName = FORCE_PACKAGE_PARSED_CACHE_ENABLED ? "debug"
-                : SystemProperties.digestOf(
+                : injector.getSystemWrapper().digestOfProperties(
                         "ro.build.fingerprint",
                         StorageManager.PROP_ISOLATED_STORAGE,
                         StorageManager.PROP_ISOLATED_STORAGE_SNAPSHOT
@@ -4093,7 +4148,7 @@
     public boolean isDeviceUpgrading() {
         // allow instant applications
         // The system property allows testing ota flow when upgraded to the same image.
-        return mIsUpgrade || SystemProperties.getBoolean(
+        return mIsUpgrade || mInjector.getSystemWrapper().getPropertyBoolean(
                 "persist.pm.mock-upgrade", false /* default */);
     }
 
@@ -4360,7 +4415,7 @@
             Slog.d(TAG, "Priming domain verifications in user " + userId);
         }
 
-        SystemConfig systemConfig = SystemConfig.getInstance();
+        SystemConfig systemConfig = mInjector.getSystemConfig();
         ArraySet<String> packages = systemConfig.getLinkedApps();
 
         for (String packageName : packages) {
@@ -5169,11 +5224,11 @@
      * until the requested bytes are available.
      */
     public void freeStorage(String volumeUuid, long bytes, int storageFlags) throws IOException {
-        final StorageManager storage = mInjector.getStorageManager();
+        final StorageManager storage = mInjector.getSystemService(StorageManager.class);
         final File file = storage.findPathForUuid(volumeUuid);
         if (file.getUsableSpace() >= bytes) return;
 
-        if (ENABLE_FREE_CACHE_V2) {
+        if (mEnableFreeCacheV2) {
             final boolean internalVolume = Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL,
                     volumeUuid);
             final boolean aggressive = (storageFlags
@@ -5252,7 +5307,7 @@
 
     private boolean pruneUnusedStaticSharedLibraries(long neededSpace, long maxCachePeriod)
             throws IOException {
-        final StorageManager storage = mInjector.getStorageManager();
+        final StorageManager storage = mInjector.getSystemService(StorageManager.class);
         final File volume = storage.findPathForUuid(StorageManager.UUID_PRIVATE_INTERNAL);
 
         List<VersionedPackage> packagesToDelete = null;
@@ -5500,7 +5555,8 @@
     }
 
     private boolean isRecentsAccessingChildProfiles(int callingUid, int targetUserId) {
-        if (!mInjector.getActivityTaskManagerInternal().isCallerRecents(callingUid)) {
+        if (!mInjector.getLocalService(ActivityTaskManagerInternal.class)
+                .isCallerRecents(callingUid)) {
             return false;
         }
         final long token = Binder.clearCallingIdentity();
@@ -5983,7 +6039,7 @@
             res.addAll(mAvailableFeatures.values());
         }
         final FeatureInfo fi = new FeatureInfo();
-        fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
+        fi.reqGlEsVersion = mInjector.getSystemWrapper().getPropertyInt("ro.opengles.version",
                 FeatureInfo.GL_ES_VERSION_UNDEFINED);
         res.add(fi);
 
@@ -9065,10 +9121,10 @@
         if (providerInfo != null) {
             // Looking for cross-user grants before enforcing the typical cross-users permissions
             if (userId != UserHandle.getUserId(callingUid)) {
-                final UriGrantsManagerInternal mUgmInternal =
-                        LocalServices.getService(UriGrantsManagerInternal.class);
+                final UriGrantsManagerInternal ugmInternal =
+                        mInjector.getLocalService(UriGrantsManagerInternal.class);
                 checkedGrants =
-                        mUgmInternal.checkAuthorityGrants(callingUid, providerInfo, userId, true);
+                        ugmInternal.checkAuthorityGrants(callingUid, providerInfo, userId, true);
             }
         }
         if (!checkedGrants) {
@@ -9678,7 +9734,7 @@
                                             pkgName, getSettingsVersionForPackage(parsedPackage)),
                                     Collections.singletonMap(pkgName,
                                             getSharedLibLatestVersionSetting(scanResult))),
-                            mSettings.mKeySetManagerService);
+                            mSettings.mKeySetManagerService, mInjector);
                     appIdCreated = optimisticallyRegisterAppId(scanResult);
                     commitReconciledScanResultLocked(
                             reconcileResult.get(pkgName), mUserManager.getUserIds());
@@ -9696,6 +9752,18 @@
                 mSettings.disableSystemPackageLPw(parsedPackage.getPackageName(), true);
             }
         }
+        if (mIncrementalManager != null && isIncrementalPath(parsedPackage.getPath())) {
+            if (pkgSetting != null && pkgSetting.isPackageLoading()) {
+                final StorageHealthCheckParams healthCheckParams = new StorageHealthCheckParams();
+                healthCheckParams.blockedTimeoutMs = INCREMENTAL_STORAGE_BLOCKED_TIMEOUT_MS;
+                healthCheckParams.unhealthyTimeoutMs = INCREMENTAL_STORAGE_UNHEALTHY_TIMEOUT_MS;
+                healthCheckParams.unhealthyMonitoringMs =
+                        INCREMENTAL_STORAGE_UNHEALTHY_MONITORING_MS;
+                mIncrementalManager.registerHealthListener(parsedPackage.getPath(),
+                        healthCheckParams,
+                        new IncrementalHealthListener(parsedPackage.getPackageName()));
+            }
+        }
         return scanResult.pkgSetting.pkg;
     }
 
@@ -9957,7 +10025,7 @@
                 pkgCompilationReason = PackageManagerService.REASON_BACKGROUND_DEXOPT;
             }
 
-            if (SystemProperties.getBoolean(PRECOMPILE_LAYOUTS, false)) {
+            if (mInjector.getSystemWrapper().getPropertyBoolean(PRECOMPILE_LAYOUTS, false)) {
                 mArtManagerService.compileLayouts(pkg);
             }
 
@@ -10933,7 +11001,7 @@
     }
 
     private int getVendorPartitionVersion() {
-        final String version = SystemProperties.get("ro.vndk.version");
+        final String version = mInjector.getSystemWrapper().getProperty("ro.vndk.version");
         if (!version.isEmpty()) {
             try {
                 return Integer.parseInt(version);
@@ -12349,9 +12417,10 @@
                     // A non-preloaded overlay package, without <overlay android:targetName>, will
                     // only be used if it is signed with the same certificate as its target OR if
                     // it is signed with the same certificate as a reference package declared
-                    // in 'config-signature' tag of SystemConfig.
-                    // If the target is already installed or 'config-signature' tag in SystemConfig
-                    // is set, check this here to augment the last line of defence which is OMS.
+                    // in 'overlay-config-signature' tag of SystemConfig.
+                    // If the target is already installed or 'overlay-config-signature' tag in
+                    // SystemConfig is set, check this here to augment the last line of defense
+                    // which is OMS.
                     if (pkg.getOverlayTargetName() == null) {
                         final PackageSetting targetPkgSetting =
                                 mSettings.getPackageLPr(pkg.getOverlayTarget());
@@ -12957,7 +13026,7 @@
                         + intent.toShortString(false, true, false, false)
                         + " " + intent.getExtras(), here);
             }
-            mInjector.getActivityManagerInternal().broadcastIntent(
+            mInjector.getLocalService(ActivityManagerInternal.class).broadcastIntent(
                     intent, finishedReceiver, requiredPermissions,
                     finishedReceiver != null, id,
                     broadcastAllowList == null ? null : broadcastAllowList.get(id));
@@ -14262,7 +14331,7 @@
                     && mInstantAppInstallerActivity.packageName.equals(
                             mRequiredVerifierPackage)) {
                 try {
-                    mInjector.getAppOpsManager()
+                    mInjector.getSystemService(AppOpsManager.class)
                             .checkPackage(installerUid, mRequiredVerifierPackage);
                     if (DEBUG_VERIFY) {
                         Slog.i(TAG, "disable verification for instant app");
@@ -14512,7 +14581,7 @@
         if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
             throw new SecurityException("Instant applications don't have access to this method");
         }
-        mInjector.getAppOpsManager().checkPackage(Binder.getCallingUid(),
+        mInjector.getSystemService(AppOpsManager.class).checkPackage(Binder.getCallingUid(),
                 callerPackageName);
         synchronized (mLock) {
             PackageSetting ps = mSettings.mPackages.get(packageName);
@@ -14672,7 +14741,7 @@
      */
     private boolean performRollbackManagerRestore(int userId, int token, PackageInstalledInfo res,
             PostInstallData data) {
-        RollbackManagerInternal rm = LocalServices.getService(RollbackManagerInternal.class);
+        RollbackManagerInternal rm = mInjector.getLocalService(RollbackManagerInternal.class);
 
         final String packageName = res.pkg.getPackageName();
         final int[] allUsers = mUserManager.getUserIds();
@@ -15435,7 +15504,7 @@
             integrityVerification.setPackage("android");
 
             DeviceIdleInternal idleController =
-                    mInjector.getLocalDeviceIdleController();
+                    mInjector.getLocalService(DeviceIdleInternal.class);
             final long idleDuration = getVerificationTimeout();
 
             idleController.addPowerSaveTempWhitelistAppDirect(Process.myUid(),
@@ -15545,7 +15614,7 @@
                         receivers, verificationState);
 
                 DeviceIdleInternal idleController =
-                        mInjector.getLocalDeviceIdleController();
+                        mInjector.getLocalService(DeviceIdleInternal.class);
                 final long idleDuration = getVerificationTimeout();
                 final BroadcastOptions options = BroadcastOptions.makeBasic();
                 options.setTemporaryAppWhitelistDuration(idleDuration);
@@ -16355,12 +16424,25 @@
 
                 // TODO(b/169721400): generalize Incremental States and create a Callback object
                 // that can be used for all the packages.
-                final IncrementalStatesCallback incrementalStatesCallback =
-                        new IncrementalStatesCallback(ps, userId);
                 final String codePath = ps.getPathString();
                 if (IncrementalManager.isIncrementalPath(codePath) && mIncrementalManager != null) {
-                    mIncrementalManager.registerCallback(codePath, incrementalStatesCallback);
+                    final IncrementalStatesCallback incrementalStatesCallback =
+                            new IncrementalStatesCallback(ps.name,
+                                    UserHandle.getUid(userId, ps.appId),
+                                    getInstalledUsers(ps, userId));
                     ps.setIncrementalStatesCallback(incrementalStatesCallback);
+                    mIncrementalManager.registerLoadingProgressCallback(codePath,
+                            new IncrementalProgressListener(ps.name));
+                    final IncrementalHealthListener incrementalHealthListener =
+                            new IncrementalHealthListener(ps.name);
+                    final StorageHealthCheckParams healthCheckParams =
+                            new StorageHealthCheckParams();
+                    healthCheckParams.blockedTimeoutMs = INCREMENTAL_STORAGE_BLOCKED_TIMEOUT_MS;
+                    healthCheckParams.unhealthyTimeoutMs = INCREMENTAL_STORAGE_UNHEALTHY_TIMEOUT_MS;
+                    healthCheckParams.unhealthyMonitoringMs =
+                            INCREMENTAL_STORAGE_UNHEALTHY_MONITORING_MS;
+                    mIncrementalManager.registerHealthListener(codePath,
+                            new StorageHealthCheckParams(), incrementalHealthListener);
                 }
 
                 // Ensure that the uninstall reason is UNKNOWN for users with the package installed.
@@ -16544,7 +16626,7 @@
 
     @GuardedBy("mLock")
     private static Map<String, ReconciledPackage> reconcilePackagesLocked(
-            final ReconcileRequest request, KeySetManagerService ksms)
+            final ReconcileRequest request, KeySetManagerService ksms, Injector injector)
             throws ReconcileFailure {
         final Map<String, ScanResult> scannedPackages = request.scannedPackages;
 
@@ -16695,7 +16777,8 @@
                                 && compareSignatures(sharedUserSignatures,
                                 parsedPackage.getSigningDetails().signatures)
                                         != PackageManager.SIGNATURE_MATCH) {
-                            if (SystemProperties.getInt("ro.product.first_api_level", 0) <= 29) {
+                            if (injector.getSystemWrapper()
+                                    .getPropertyInt("ro.product.first_api_level", 0) <= 29) {
                                 // Mismatched signatures is an error and silently skipping system
                                 // packages will likely break the device in unforeseen ways.
                                 // However, we allow the device to boot anyway because, prior to Q,
@@ -17069,7 +17152,7 @@
                 try {
                     Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "reconcilePackages");
                     reconciledPackages = reconcilePackagesLocked(
-                            reconcileRequest, mSettings.mKeySetManagerService);
+                            reconcileRequest, mSettings.mKeySetManagerService, mInjector);
                 } catch (ReconcileFailure e) {
                     for (InstallRequest request : requests) {
                         request.installResult.setError("Reconciliation failed...", e);
@@ -17204,7 +17287,7 @@
 
             if (performDexopt) {
                 // Compile the layout resources.
-                if (SystemProperties.getBoolean(PRECOMPILE_LAYOUTS, false)) {
+                if (mInjector.getSystemWrapper().getPropertyBoolean(PRECOMPILE_LAYOUTS, false)) {
                     Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "compileLayouts");
                     mViewCompiler.compileLayouts(pkg);
                     Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
@@ -17263,45 +17346,39 @@
         NativeLibraryHelper.waitForNativeBinariesExtraction(incrementalStorages);
     }
 
-    private class IncrementalStatesCallback extends IPackageLoadingProgressCallback.Stub
-            implements IncrementalStates.Callback {
-        @GuardedBy("mPackageSetting")
-        private final PackageSetting mPackageSetting;
-        private final String mPackageName;
-        private final String mPathString;
-        private final int mUid;
-        private final int[] mInstalledUserIds;
-
-        IncrementalStatesCallback(PackageSetting packageSetting, int userId) {
-            mPackageSetting = packageSetting;
-            mPackageName = packageSetting.name;
-            mUid = UserHandle.getUid(userId, packageSetting.appId);
-            mPathString = packageSetting.getPathString();
-            final int[] allUserIds = resolveUserIds(userId);
-            final ArrayList<Integer> installedUserIds = new ArrayList<>();
-            for (int i = 0; i < allUserIds.length; i++) {
-                if (packageSetting.getInstalled(allUserIds[i])) {
-                    installedUserIds.add(allUserIds[i]);
-                }
-            }
-            final int numInstalledUserId = installedUserIds.size();
-            mInstalledUserIds = new int[numInstalledUserId];
-            for (int i = 0; i < numInstalledUserId; i++) {
-                mInstalledUserIds[i] = installedUserIds.get(i);
+    private int[] getInstalledUsers(PackageSetting ps, int userId) {
+        final int[] allUserIds = resolveUserIds(userId);
+        final ArrayList<Integer> installedUserIdsList = new ArrayList<>();
+        for (int i = 0; i < allUserIds.length; i++) {
+            if (ps.getInstalled(allUserIds[i])) {
+                installedUserIdsList.add(allUserIds[i]);
             }
         }
+        final int numInstalledUserId = installedUserIdsList.size();
+        final int[] installedUserIds = new int[numInstalledUserId];
+        for (int i = 0; i < numInstalledUserId; i++) {
+            installedUserIds[i] = installedUserIdsList.get(i);
+        }
+        return installedUserIds;
+    }
 
-        @Override
-        public void onPackageLoadingProgressChanged(float progress) {
-            synchronized (mPackageSetting) {
-                mPackageSetting.setLoadingProgress(progress);
-            }
+    /**
+     * Package states callback, used to listen for package state changes and send broadcasts
+     */
+    private final class IncrementalStatesCallback implements IncrementalStates.Callback {
+        private final String mPackageName;
+        private final int mUid;
+        private final int[] mInstalledUserIds;
+        IncrementalStatesCallback(String packageName, int uid, int[] installedUserIds) {
+            mPackageName = packageName;
+            mUid = uid;
+            mInstalledUserIds = installedUserIds;
         }
 
         @Override
         public void onPackageFullyLoaded() {
-            mIncrementalManager.unregisterCallback(mPathString, this);
             final SparseArray<int[]> newBroadcastAllowList;
+            final String codePath;
             synchronized (mLock) {
                 final PackageSetting ps = mSettings.mPackages.get(mPackageName);
                 if (ps == null) {
@@ -17309,6 +17386,7 @@
                 }
                 newBroadcastAllowList = mAppsFilter.getVisibilityAllowList(
                         ps, mInstalledUserIds, mSettings.mPackages);
+                codePath = ps.getPathString();
             }
             Bundle extras = new Bundle();
             extras.putInt(Intent.EXTRA_UID, mUid);
@@ -17317,6 +17395,8 @@
                     extras, 0 /*flags*/,
                     null /*targetPackage*/, null /*finishedReceiver*/,
                     mInstalledUserIds, null /* instantUserIds */, newBroadcastAllowList);
+            // Unregister health listener as it will always be healthy from now
+            mIncrementalManager.unregisterHealthListener(codePath);
         }
 
         @Override
@@ -17333,7 +17413,7 @@
             Bundle extras = new Bundle();
             extras.putInt(Intent.EXTRA_UID, mUid);
             extras.putString(Intent.EXTRA_PACKAGE_NAME, mPackageName);
-            extras.putInt(Intent.EXTRA_REASON, reason);
+            extras.putInt(Intent.EXTRA_UNSTARTABLE_REASON, reason);
             // send broadcast to users with this app installed
             sendPackageBroadcast(Intent.ACTION_PACKAGE_UNSTARTABLE, mPackageName,
                     extras, 0 /*flags*/,
@@ -17364,37 +17444,48 @@
     }
 
     /**
-     * This is an internal method that is used to indicate changes on the health status of the
-     * Incremental Storage used by an installed package with an associated user id. This might
-     * result in a change in the loading state of the package.
+     * Loading progress callback, used to listen for progress changes and update package setting
      */
-    public void onStorageHealthStatusChanged(String packageName, int status, int userId) {
-        final int callingUid = Binder.getCallingUid();
-        mPermissionManager.enforceCrossUserPermission(
-                callingUid, userId, true, false,
-                "onStorageHealthStatusChanged");
-        final PackageSetting ps = getPackageSettingForUser(packageName, callingUid, userId);
-        if (ps == null) {
-            return;
+    private class IncrementalProgressListener extends IPackageLoadingProgressCallback.Stub {
+        private final String mPackageName;
+        IncrementalProgressListener(String packageName) {
+            mPackageName = packageName;
         }
-        ps.setStorageHealthStatus(status);
+
+        @Override
+        public void onPackageLoadingProgressChanged(float progress) {
+            final PackageSetting ps;
+            synchronized (mLock) {
+                ps = mSettings.mPackages.get(mPackageName);
+            }
+            if (ps == null) {
+                return;
+            }
+            ps.setLoadingProgress(progress);
+        }
     }
 
     /**
-     * This is an internal method that is used to indicate changes on the stream status of the
-     * data loader used by an installed package with an associated user id. This might
-     * result in a change in the loading state of the package.
+     * Incremental storage health status callback, used to listen for monitoring changes and update
+     * package setting.
      */
-    public void onStreamStatusChanged(String packageName, int status, int userId) {
-        final int callingUid = Binder.getCallingUid();
-        mPermissionManager.enforceCrossUserPermission(
-                callingUid, userId, true, false,
-                "onStreamStatusChanged");
-        final PackageSetting ps = getPackageSettingForUser(packageName, callingUid, userId);
-        if (ps == null) {
-            return;
+    private class IncrementalHealthListener extends IStorageHealthListener.Stub {
+        private final String mPackageName;
+        IncrementalHealthListener(String packageName) {
+            mPackageName = packageName;
         }
-        ps.setStreamStatus(status);
+
+        @Override
+        public void onHealthStatus(int storageId, int status) throws RemoteException {
+            final PackageSetting ps;
+            synchronized (mLock) {
+                ps = mSettings.mPackages.get(mPackageName);
+            }
+            if (ps == null) {
+                return;
+            }
+            ps.setStorageHealthStatus(status);
+        }
     }
 
     @Nullable PackageSetting getPackageSettingForUser(String packageName, int callingUid,
@@ -19839,7 +19930,7 @@
     }
 
     private void resetNetworkPolicies(int userId) {
-        mInjector.getNetworkPolicyManagerInternal().resetUserState(userId);
+        mInjector.getLocalService(NetworkPolicyManagerInternal.class).resetUserState(userId);
     }
 
     /**
@@ -21105,7 +21196,7 @@
     }
 
     public String getOverlayConfigSignaturePackageName() {
-        return ensureSystemPackageName(SystemConfig.getInstance()
+        return ensureSystemPackageName(mInjector.getSystemConfig()
                 .getOverlayConfigSignaturePackage());
     }
 
@@ -21875,7 +21966,7 @@
             mPermissionManager.updateAllPermissions(StorageManager.UUID_PRIVATE_INTERNAL, false);
 
             final PermissionPolicyInternal permissionPolicyInternal =
-                    mInjector.getPermissionPolicyInternal();
+                    mInjector.getLocalService(PermissionPolicyInternal.class);
             permissionPolicyInternal.setOnInitializedCallback(userId -> {
                 // The SDK updated case is already handled when we run during the ctor.
                 synchronized (mLock) {
@@ -21886,13 +21977,13 @@
         }
 
         // Watch for external volumes that come and go over time
-        final StorageManager storage = mInjector.getStorageManager();
+        final StorageManager storage = mInjector.getSystemService(StorageManager.class);
         storage.registerListener(mStorageListener);
 
         mInstallerService.systemReady();
         mPackageDexOptimizer.systemReady();
 
-        mInjector.getStorageManagerInternal().addExternalStoragePolicy(
+        mInjector.getLocalService(StorageManagerInternal.class).addExternalStoragePolicy(
                 new StorageManagerInternal.ExternalStorageMountPolicy() {
                     @Override
                     public int getMountMode(int uid, String packageName) {
@@ -22625,7 +22716,7 @@
         if (ArrayUtils.isEmpty(apkList)) {
            return;
         }
-        String sku = SystemProperties.get("ro.boot.hardware.sku");
+        String sku = mInjector.getSystemWrapper().getProperty("ro.boot.hardware.sku");
         if (!TextUtils.isEmpty(sku) && ArrayUtils.contains(skuArray, sku)) {
             return;
         }
@@ -22921,7 +23012,7 @@
         }
 
         // Reconcile app data for all started/unlocked users
-        final StorageManager sm = mInjector.getStorageManager();
+        final StorageManager sm = mInjector.getSystemService(StorageManager.class);
         UserManagerInternal umInternal = mInjector.getUserManagerInternal();
         for (UserInfo user : mUserManager.getUsers(false /* includeDying */)) {
             final int flags;
@@ -23122,7 +23213,7 @@
      * correct for all installed apps on all mounted volumes.
      */
     void reconcileAppsData(int userId, int flags, boolean migrateAppsData) {
-        final StorageManager storage = mInjector.getStorageManager();
+        final StorageManager storage = mInjector.getSystemService(StorageManager.class);
         for (VolumeInfo vol : storage.getWritablePrivateVolumes()) {
             final String volumeUuid = vol.getFsUuid();
             synchronized (mInstallLock) {
@@ -23257,7 +23348,7 @@
 
         Installer.Batch batch = new Installer.Batch();
         UserManagerInternal umInternal = mInjector.getUserManagerInternal();
-        StorageManagerInternal smInternal = mInjector.getStorageManagerInternal();
+        StorageManagerInternal smInternal = mInjector.getLocalService(StorageManagerInternal.class);
         for (UserInfo user : mUserManager.getUsers(false /*excludeDying*/)) {
             final int flags;
             if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
@@ -23586,7 +23677,7 @@
     private void movePackageInternal(final String packageName, final String volumeUuid,
             final int moveId, final int callingUid, UserHandle user)
                     throws PackageManagerException {
-        final StorageManager storage = mInjector.getStorageManager();
+        final StorageManager storage = mInjector.getSystemService(StorageManager.class);
         final PackageManager pm = mContext.getPackageManager();
 
         final String currentVolumeUuid;
@@ -23824,7 +23915,7 @@
             return;
         }
 
-        final StorageManager storage = mInjector.getStorageManager();;
+        final StorageManager storage = mInjector.getSystemService(StorageManager.class);;
         VolumeInfo volume = storage.findVolumeByUuid(pkg.getStorageUuid().toString());
         int packageExternalStorageType = getPackageExternalStorageType(volume, pkg.isExternalStorage());
 
@@ -23864,7 +23955,7 @@
             }
         };
 
-        final StorageManager storage = mInjector.getStorageManager();
+        final StorageManager storage = mInjector.getSystemService(StorageManager.class);
         storage.setPrimaryStorageUuid(volumeUuid, callback);
         return realMoveId;
     }
@@ -24044,7 +24135,7 @@
         final long token = Binder.clearCallingIdentity();
         try {
             final DeviceStorageMonitorInternal
-                    dsm = mInjector.getDeviceStorageMonitorInternal();
+                    dsm = mInjector.getLocalService(DeviceStorageMonitorInternal.class);
             if (dsm != null) {
                 return dsm.isMemoryLow();
             } else {
@@ -25636,7 +25727,7 @@
                         "Failed registering loading progress callback. Incremental is not enabled");
                 return false;
             }
-            return mIncrementalManager.registerCallback(ps.getPathString(),
+            return mIncrementalManager.registerLoadingProgressCallback(ps.getPathString(),
                     (IPackageLoadingProgressCallback) callback.getBinder());
         }
 
@@ -25655,7 +25746,7 @@
             if (mIncrementalManager == null) {
                 return false;
             }
-            return mIncrementalManager.unregisterCallback(ps.getPathString(),
+            return mIncrementalManager.unregisterLoadingProgressCallback(ps.getPathString(),
                     (IPackageLoadingProgressCallback) callback.getBinder());
         }
     }
@@ -25828,7 +25919,7 @@
 
     @Override
     public boolean isAutoRevokeWhitelisted(String packageName) {
-        int mode = mInjector.getAppOpsManager().checkOpNoThrow(
+        int mode = mInjector.getSystemService(AppOpsManager.class).checkOpNoThrow(
                 AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED,
                 Binder.getCallingUid(), packageName);
         return mode == MODE_IGNORED;
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index c46a7ef..9aa1a62 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -2729,13 +2729,13 @@
         Slog.i(TAG, "Removing " + userId + " or set as ephemeral if in use.");
         int result = um.removeUserOrSetEphemeral(userId);
         switch (result) {
-            case UserManagerService.REMOVE_RESULT_REMOVED:
+            case UserManager.REMOVE_RESULT_REMOVED:
                 getOutPrintWriter().printf("Success: user %d removed\n", userId);
                 return 0;
-            case UserManagerService.REMOVE_RESULT_SET_EPHEMERAL:
+            case UserManager.REMOVE_RESULT_SET_EPHEMERAL:
                 getOutPrintWriter().printf("Success: user %d set as ephemeral\n", userId);
                 return 0;
-            case UserManagerService.REMOVE_RESULT_ALREADY_BEING_REMOVED:
+            case UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED:
                 getOutPrintWriter().printf("Success: user %d is already being removed\n", userId);
                 return 0;
             default:
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index d52ad46..be7c7c6 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -793,13 +793,6 @@
         incrementalStates.onStorageHealthStatusChanged(status);
     }
 
-    /**
-     * @see IncrementalStates#onStreamStatusChanged(int)
-     */
-    public void setStreamStatus(int status) {
-        incrementalStates.onStreamStatusChanged(status);
-    }
-
     protected PackageSettingBase updateFrom(PackageSettingBase other) {
         super.copyFrom(other);
         setPath(other.getPath());
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 66e84b1..a0344e2 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -22,7 +22,6 @@
 import android.Manifest;
 import android.annotation.ColorRes;
 import android.annotation.DrawableRes;
-import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StringRes;
@@ -132,8 +131,6 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -248,43 +245,6 @@
     static final int WRITE_USER_MSG = 1;
     static final int WRITE_USER_DELAY = 2*1000;  // 2 seconds
 
-    /**
-     * A response code from {@link #removeUserOrSetEphemeral(int)} indicating that the specified
-     * user has been successfully removed.
-     */
-    public static final int REMOVE_RESULT_REMOVED = 0;
-
-    /**
-     * A response code from {@link #removeUserOrSetEphemeral(int)} indicating that the specified
-     * user has had its {@link UserInfo#FLAG_EPHEMERAL} flag set to {@code true}, so that it will be
-     * removed when the user is stopped or on boot.
-     */
-    public static final int REMOVE_RESULT_SET_EPHEMERAL = 1;
-
-    /**
-     * A response code from {@link #removeUserOrSetEphemeral(int)} indicating that the specified
-     * user is already in the process of being removed.
-     */
-    public static final int REMOVE_RESULT_ALREADY_BEING_REMOVED = 2;
-
-    /**
-     * A response code from {@link #removeUserOrSetEphemeral(int)} indicating that an error occurred
-     * that prevented the user from being removed or set as ephemeral.
-     */
-    public static final int REMOVE_RESULT_ERROR = 3;
-
-    /**
-     * Possible response codes from {@link #removeUserOrSetEphemeral(int)}.
-     */
-    @IntDef(prefix = { "REMOVE_RESULT_" }, value = {
-            REMOVE_RESULT_REMOVED,
-            REMOVE_RESULT_SET_EPHEMERAL,
-            REMOVE_RESULT_ALREADY_BEING_REMOVED,
-            REMOVE_RESULT_ERROR,
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface RemoveResult {}
-
     // Tron counters
     private static final String TRON_GUEST_CREATED = "users_guest_created";
     private static final String TRON_USER_CREATED = "users_user_created";
@@ -4031,17 +3991,17 @@
     }
 
     @Override
-    public @RemoveResult int removeUserOrSetEphemeral(@UserIdInt int userId) {
+    public @UserManager.RemoveResult int removeUserOrSetEphemeral(@UserIdInt int userId) {
         Slog.i(LOG_TAG, "removeUserOrSetEphemeral u" + userId);
         checkManageUsersPermission("Only the system can remove users");
         final String restriction = getUserRemovalRestriction(userId);
         if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(restriction, false)) {
             Slog.w(LOG_TAG, "Cannot remove user. " + restriction + " is enabled.");
-            return REMOVE_RESULT_ERROR;
+            return UserManager.REMOVE_RESULT_ERROR;
         }
         if (userId == UserHandle.USER_SYSTEM) {
             Slog.e(LOG_TAG, "System user cannot be removed.");
-            return REMOVE_RESULT_ERROR;
+            return UserManager.REMOVE_RESULT_ERROR;
         }
 
         final long ident = Binder.clearCallingIdentity();
@@ -4053,12 +4013,12 @@
                     if (userData == null) {
                         Slog.e(LOG_TAG,
                                 "Cannot remove user " + userId + ", invalid user id provided.");
-                        return REMOVE_RESULT_ERROR;
+                        return UserManager.REMOVE_RESULT_ERROR;
                     }
 
                     if (mRemovingUserIds.get(userId)) {
                         Slog.e(LOG_TAG, "User " + userId + " is already scheduled for removal.");
-                        return REMOVE_RESULT_ALREADY_BEING_REMOVED;
+                        return UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED;
                     }
                 }
 
@@ -4067,7 +4027,7 @@
                 if (currentUser != userId) {
                     // Attempt to remove the user. This will fail if the user is the current user
                     if (removeUser(userId)) {
-                        return REMOVE_RESULT_REMOVED;
+                        return UserManager.REMOVE_RESULT_REMOVED;
                     }
 
                     Slog.w(LOG_TAG, "Unable to immediately remove non-current user: " + userId
@@ -4081,7 +4041,7 @@
                 userData.info.flags |= UserInfo.FLAG_EPHEMERAL;
                 writeUserLP(userData);
 
-                return REMOVE_RESULT_SET_EPHEMERAL;
+                return UserManager.REMOVE_RESULT_SET_EPHEMERAL;
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java
index bebb676..667414e 100644
--- a/services/core/java/com/android/server/pm/permission/BasePermission.java
+++ b/services/core/java/com/android/server/pm/permission/BasePermission.java
@@ -198,6 +198,11 @@
                 == PermissionInfo.PROTECTION_DANGEROUS;
     }
 
+    public boolean isInstalled() {
+        return mPermissionInfo != null
+                && (mPermissionInfo.flags & PermissionInfo.FLAG_INSTALLED) != 0;
+    }
+
     public boolean isRemoved() {
         return mPermissionInfo != null
                 && (mPermissionInfo.flags & PermissionInfo.FLAG_REMOVED) != 0;
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 19a5650..d871325 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -2352,19 +2352,23 @@
 
                 final PermissionInfo permissionInfo = PackageInfoUtils.generatePermissionInfo(p,
                         PackageManager.GET_META_DATA);
+                final BasePermission bp;
                 if (p.isTree()) {
-                    final BasePermission bp = BasePermission.createOrUpdate(
+                    bp = BasePermission.createOrUpdate(
                             mPackageManagerInt,
                             mSettings.getPermissionTreeLocked(p.getName()), permissionInfo, pkg,
                             mSettings.getAllPermissionTreesLocked(), chatty);
                     mSettings.putPermissionTreeLocked(p.getName(), bp);
                 } else {
-                    final BasePermission bp = BasePermission.createOrUpdate(
+                    bp = BasePermission.createOrUpdate(
                             mPackageManagerInt,
                             mSettings.getPermissionLocked(p.getName()),
                             permissionInfo, pkg, mSettings.getAllPermissionTreesLocked(), chatty);
                     mSettings.putPermissionLocked(p.getName(), bp);
                 }
+                if (bp.isInstalled()) {
+                    p.setFlags(p.getFlags() | PermissionInfo.FLAG_INSTALLED);
+                }
             }
         }
     }
diff --git a/services/core/java/com/android/server/policy/DisplayFoldController.java b/services/core/java/com/android/server/policy/DisplayFoldController.java
index 0ca6e59..f8e26fc 100644
--- a/services/core/java/com/android/server/policy/DisplayFoldController.java
+++ b/services/core/java/com/android/server/policy/DisplayFoldController.java
@@ -80,37 +80,42 @@
     }
 
     void setDeviceFolded(boolean folded) {
-        mDisplayManagerInternal.setDeviceFolded(folded);
-
         if (mFolded != null && mFolded == folded) {
             return;
         }
-        if (folded) {
-            Rect foldedArea;
-            if (!mOverrideFoldedArea.isEmpty()) {
-                foldedArea = mOverrideFoldedArea;
-            } else if (!mFoldedArea.isEmpty()) {
-                foldedArea = mFoldedArea;
-            } else {
-                return;
-            }
 
-            mDisplayManagerInternal.getNonOverrideDisplayInfo(mDisplayId, mNonOverrideDisplayInfo);
-            final int dx = (mNonOverrideDisplayInfo.logicalWidth - foldedArea.width()) / 2
-                    - foldedArea.left;
-            final int dy = (mNonOverrideDisplayInfo.logicalHeight - foldedArea.height()) / 2
-                    - foldedArea.top;
-
-            // Bypass scaling otherwise LogicalDisplay will scale contents by default.
-            mDisplayManagerInternal.setDisplayScalingDisabled(mDisplayId, true);
-            mWindowManagerInternal.setForcedDisplaySize(mDisplayId,
-                    foldedArea.width(), foldedArea.height());
-            mDisplayManagerInternal.setDisplayOffsets(mDisplayId, -dx, -dy);
+        final Rect foldedArea;
+        if (!mOverrideFoldedArea.isEmpty()) {
+            foldedArea = mOverrideFoldedArea;
+        } else if (!mFoldedArea.isEmpty()) {
+            foldedArea = mFoldedArea;
         } else {
-            mDisplayManagerInternal.setDisplayScalingDisabled(mDisplayId, false);
-            mWindowManagerInternal.clearForcedDisplaySize(mDisplayId);
-            mDisplayManagerInternal.setDisplayOffsets(mDisplayId, 0, 0);
+            foldedArea = null;
         }
+
+        // Only do display scaling/cropping if it has been configured to do so
+        if (foldedArea != null) {
+            if (folded) {
+
+                mDisplayManagerInternal.getNonOverrideDisplayInfo(
+                        mDisplayId, mNonOverrideDisplayInfo);
+                final int dx = (mNonOverrideDisplayInfo.logicalWidth - foldedArea.width()) / 2
+                        - foldedArea.left;
+                final int dy = (mNonOverrideDisplayInfo.logicalHeight - foldedArea.height()) / 2
+                        - foldedArea.top;
+
+                // Bypass scaling otherwise LogicalDisplay will scale contents by default.
+                mDisplayManagerInternal.setDisplayScalingDisabled(mDisplayId, true);
+                mWindowManagerInternal.setForcedDisplaySize(mDisplayId,
+                        foldedArea.width(), foldedArea.height());
+                mDisplayManagerInternal.setDisplayOffsets(mDisplayId, -dx, -dy);
+            } else {
+                mDisplayManagerInternal.setDisplayScalingDisabled(mDisplayId, false);
+                mWindowManagerInternal.clearForcedDisplaySize(mDisplayId);
+                mDisplayManagerInternal.setDisplayOffsets(mDisplayId, 0, 0);
+            }
+        }
+
         mDurationLogger.setDeviceFolded(folded);
         mDurationLogger.logFocusedAppWithFoldState(folded, mFocusedApp);
         mFolded = folded;
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index b74de13..0983e10 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -471,7 +471,6 @@
     int mLidKeyboardAccessibility;
     int mLidNavigationAccessibility;
     private boolean mLidControlsDisplayFold;
-    private boolean mShouldSwapDisplaysOnLidSwitch;
     int mShortPressOnPowerBehavior;
     int mLongPressOnPowerBehavior;
     int mVeryLongPressOnPowerBehavior;
@@ -1849,8 +1848,6 @@
                 com.android.internal.R.integer.config_lidNavigationAccessibility);
         mLidControlsDisplayFold = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_lidControlsDisplayFold);
-        mShouldSwapDisplaysOnLidSwitch = mContext.getResources().getStringArray(
-                com.android.internal.R.array.config_internalFoldedPhysicalDisplayIds).length == 2;
 
         mAllowTheaterModeWakeFromKey = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_allowTheaterModeWakeFromKey);
@@ -5041,8 +5038,6 @@
         final int lidState = mDefaultDisplayPolicy.getLidState();
         if (mLidControlsDisplayFold && mDisplayFoldController != null) {
             mDisplayFoldController.requestDeviceFolded(lidState == LID_CLOSED);
-        } else if (mShouldSwapDisplaysOnLidSwitch) {
-            mDisplayManagerInternal.setDeviceFolded(lidState == LID_CLOSED);
         } else if (lidState == LID_CLOSED) {
             int lidBehavior = getLidBehavior();
             switch (lidBehavior) {
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 9350edf..1e89e06 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -28,7 +28,6 @@
 import android.content.IntentFilter;
 import android.content.IntentSender;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.ModuleInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageManager;
@@ -1089,8 +1088,8 @@
                 Manifest.permission.TEST_MANAGE_ROLLBACKS,
                 installerPackageName) == PackageManager.PERMISSION_GRANTED;
 
-        // For now only allow rollbacks for modules or for testing.
-        return (isRollbackWhitelisted(packageName) && manageRollbacksGranted)
+        // For now only allow rollbacks for allowlisted packages or for testing.
+        return (isRollbackAllowlisted(packageName) && manageRollbacksGranted)
             || testManageRollbacksGranted;
     }
 
@@ -1098,25 +1097,8 @@
      * Returns true is this package is eligible for enabling rollback.
      */
     @AnyThread
-    private boolean isRollbackWhitelisted(String packageName) {
-        // TODO: Remove #isModule when the allowlist is ready.
-        return SystemConfig.getInstance().getRollbackWhitelistedPackages().contains(packageName)
-                || isModule(packageName);
-    }
-    /**
-     * Returns true if the package name is the name of a module.
-     */
-    @AnyThread
-    private boolean isModule(String packageName) {
-        PackageManager pm = mContext.getPackageManager();
-        final ModuleInfo moduleInfo;
-        try {
-            moduleInfo = pm.getModuleInfo(packageName, 0);
-        } catch (PackageManager.NameNotFoundException e) {
-            return false;
-        }
-
-        return moduleInfo != null;
+    private boolean isRollbackAllowlisted(String packageName) {
+        return SystemConfig.getInstance().getRollbackWhitelistedPackages().contains(packageName);
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 48b0b7d..99b017f 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -5572,7 +5572,10 @@
     }
 
     void updateTopApp(ActivityRecord topResumedActivity) {
-        final ActivityRecord top = topResumedActivity != null ? topResumedActivity
+        // If system is sleeping, use the given record (it should be null) because there won't be
+        // the next resumed activity. Otherwise the process of pausing activity will keep with top
+        // state even the activity has paused and stopped.
+        final ActivityRecord top = mSleeping || topResumedActivity != null ? topResumedActivity
                 // If there is no resumed activity, it will choose the pausing activity.
                 : mRootWindowContainer.getTopResumedActivity();
         mTopApp = top != null ? top.app : null;
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 0e47ea8..6caf916 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -21,7 +21,6 @@
 import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
 import static android.view.WindowManager.TRANSIT_ACTIVITY_RELAUNCH;
 import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
-import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
@@ -92,7 +91,6 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
-import android.graphics.Path;
 import android.graphics.Picture;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
@@ -134,7 +132,6 @@
 import com.android.server.AttributeCache;
 import com.android.server.wm.animation.ClipRectLRAnimation;
 import com.android.server.wm.animation.ClipRectTBAnimation;
-import com.android.server.wm.animation.CurvedTranslateAnimation;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -161,9 +158,6 @@
     static final Interpolator TOUCH_RESPONSE_INTERPOLATOR =
             new PathInterpolator(0.3f, 0f, 0.1f, 1f);
 
-    private static final Interpolator THUMBNAIL_DOCK_INTERPOLATOR =
-            new PathInterpolator(0.85f, 0f, 1f, 1f);
-
     /**
      * Maximum duration for the clip reveal animation. This is used when there is a lot of movement
      * involved, to make it more understandable.
@@ -1127,11 +1121,8 @@
             scale.setInterpolator(interpolator);
             scale.setDuration(duration);
             Animation alpha = new AlphaAnimation(1f, 0f);
-            alpha.setInterpolator(mNextAppTransition == TRANSIT_DOCK_TASK_FROM_RECENTS
-                    ? THUMBNAIL_DOCK_INTERPOLATOR : mThumbnailFadeOutInterpolator);
-            alpha.setDuration(mNextAppTransition == TRANSIT_DOCK_TASK_FROM_RECENTS
-                    ? duration / 2
-                    : duration);
+            alpha.setInterpolator(mThumbnailFadeOutInterpolator);
+            alpha.setDuration(duration);
             Animation translate = createCurvedMotion(fromX, toX, fromY, toY);
             translate.setInterpolator(interpolator);
             translate.setDuration(duration);
@@ -1194,44 +1185,15 @@
     }
 
     private Animation createCurvedMotion(float fromX, float toX, float fromY, float toY) {
-
-        // Almost no x-change - use linear animation
-        if (Math.abs(toX - fromX) < 1f || mNextAppTransition != TRANSIT_DOCK_TASK_FROM_RECENTS) {
-            return new TranslateAnimation(fromX, toX, fromY, toY);
-        } else {
-            final Path path = createCurvedPath(fromX, toX, fromY, toY);
-            return new CurvedTranslateAnimation(path);
-        }
-    }
-
-    private Path createCurvedPath(float fromX, float toX, float fromY, float toY) {
-        final Path path = new Path();
-        path.moveTo(fromX, fromY);
-
-        if (fromY > toY) {
-            // If the object needs to go up, move it in horizontal direction first, then vertical.
-            path.cubicTo(fromX, fromY, toX, 0.9f * fromY + 0.1f * toY, toX, toY);
-        } else {
-            // If the object needs to go down, move it in vertical direction first, then horizontal.
-            path.cubicTo(fromX, fromY, fromX, 0.1f * fromY + 0.9f * toY, toX, toY);
-        }
-        return path;
+        return new TranslateAnimation(fromX, toX, fromY, toY);
     }
 
     private long getAspectScaleDuration() {
-        if (mNextAppTransition == TRANSIT_DOCK_TASK_FROM_RECENTS) {
-            return (long) (THUMBNAIL_APP_TRANSITION_DURATION * 1.35f);
-        } else {
-            return THUMBNAIL_APP_TRANSITION_DURATION;
-        }
+        return THUMBNAIL_APP_TRANSITION_DURATION;
     }
 
     private Interpolator getAspectScaleInterpolator() {
-        if (mNextAppTransition == TRANSIT_DOCK_TASK_FROM_RECENTS) {
-            return mFastOutSlowInInterpolator;
-        } else {
-            return TOUCH_RESPONSE_INTERPOLATOR;
-        }
+        return TOUCH_RESPONSE_INTERPOLATOR;
     }
 
     /**
@@ -1734,7 +1696,6 @@
                             ? WindowAnimation_activityCloseEnterAnimation
                             : WindowAnimation_activityCloseExitAnimation;
                     break;
-                case TRANSIT_DOCK_TASK_FROM_RECENTS:
                 case TRANSIT_TASK_OPEN:
                     animAttr = enter
                             ? WindowAnimation_taskOpenEnterAnimation
@@ -1805,7 +1766,6 @@
 
     int getAppStackClipMode() {
         return mNextAppTransition == TRANSIT_ACTIVITY_RELAUNCH
-                || mNextAppTransition == TRANSIT_DOCK_TASK_FROM_RECENTS
                 || mNextAppTransitionType == NEXT_TRANSIT_TYPE_CLIP_REVEAL
                 || mNextAppTransition == TRANSIT_KEYGUARD_GOING_AWAY
                 || mNextAppTransition == TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER
@@ -2059,9 +2019,6 @@
             case TRANSIT_ACTIVITY_RELAUNCH: {
                 return "TRANSIT_ACTIVITY_RELAUNCH";
             }
-            case TRANSIT_DOCK_TASK_FROM_RECENTS: {
-                return "TRANSIT_DOCK_TASK_FROM_RECENTS";
-            }
             case TRANSIT_KEYGUARD_GOING_AWAY: {
                 return "TRANSIT_KEYGUARD_GOING_AWAY";
             }
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index 57d51c5..6b8a3e22 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -21,7 +21,6 @@
 import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
 import static android.view.WindowManager.TRANSIT_ACTIVITY_RELAUNCH;
 import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
-import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
@@ -701,11 +700,9 @@
             boolean openingAppHasWallpaper, boolean closingAppHasWallpaper) {
         // Given no app transition pass it through instead of a wallpaper transition.
         // Never convert the crashing transition.
-        // Never update the transition for the wallpaper if we are just docking from recents
         // Never convert a change transition since the top activity isn't changing and will likely
         // still be above an opening wallpaper.
         if (transit == TRANSIT_NONE || transit == TRANSIT_CRASHING_ACTIVITY_CLOSE
-                || transit == TRANSIT_DOCK_TASK_FROM_RECENTS
                 || AppTransition.isChangeTransit(transit)) {
             return transit;
         }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index b06d770..4a30ca9 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -192,6 +192,8 @@
 import android.view.InputChannel;
 import android.view.InputDevice;
 import android.view.InputWindowHandle;
+import android.view.InsetsSource;
+import android.view.InsetsState;
 import android.view.InsetsState.InternalInsetsType;
 import android.view.MagnificationSpec;
 import android.view.RemoteAnimationDefinition;
@@ -4830,7 +4832,7 @@
             boolean ignoreRequest) {
         final int type = win.mAttrs.type;
         final boolean stickyHideNav =
-                !win.getRequestedInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR)
+                !win.getRequestedVisibility(ITYPE_NAVIGATION_BAR)
                         && win.mAttrs.insetsFlags.behavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
         return (!stickyHideNav || ignoreRequest) && type != TYPE_INPUT_METHOD
                 && type != TYPE_NOTIFICATION_SHADE && win.getActivityType() != ACTIVITY_TYPE_HOME;
@@ -5557,6 +5559,7 @@
 
     class RemoteInsetsControlTarget implements InsetsControlTarget {
         private final IDisplayWindowInsetsController mRemoteInsetsController;
+        private final InsetsState mRequestedInsetsState = new InsetsState();
 
         RemoteInsetsControlTarget(IDisplayWindowInsetsController controller) {
             mRemoteInsetsController = controller;
@@ -5612,6 +5615,19 @@
                 Slog.w(TAG, "Failed to deliver showInsets", e);
             }
         }
+
+        @Override
+        public boolean getRequestedVisibility(@InternalInsetsType int type) {
+            return mRequestedInsetsState.getSourceOrDefaultVisibility(type);
+        }
+
+        void updateRequestedVisibility(InsetsState state) {
+            for (int i = 0; i < InsetsState.SIZE; i++) {
+                final InsetsSource source = state.peekSource(i);
+                if (source == null) continue;
+                mRequestedInsetsState.addSource(source);
+            }
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 4e7e0ba..0801f68 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -1659,10 +1659,8 @@
                 provider != null ? provider.getControlTarget() : null;
         final WindowState navControllingWin =
                 navControlTarget instanceof WindowState ? (WindowState) navControlTarget : null;
-        final InsetsState requestedState = navControllingWin != null
-                ? navControllingWin.getRequestedInsetsState() : null;
-        final boolean navVisible = requestedState != null
-                ? requestedState.getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR)
+        final boolean navVisible = navControllingWin != null
+                ? navControllingWin.getRequestedVisibility(ITYPE_NAVIGATION_BAR)
                 : InsetsState.getDefaultVisibility(ITYPE_NAVIGATION_BAR);
         final boolean showBarsByTouch = navControllingWin != null
                 && navControllingWin.mAttrs.insetsFlags.behavior == BEHAVIOR_SHOW_BARS_BY_TOUCH;
@@ -2073,11 +2071,9 @@
         // the cutout safe zone.
         if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) {
             final boolean attachedInParent = attached != null && !layoutInScreen;
-            final InsetsState requestedInsetsState = win.getRequestedInsetsState();
-            final boolean requestedFullscreen = (fl & FLAG_FULLSCREEN) != 0
-                    || !requestedInsetsState.getSourceOrDefaultVisibility(ITYPE_STATUS_BAR);
+            final boolean requestedFullscreen = !win.getRequestedVisibility(ITYPE_STATUS_BAR);
             final boolean requestedHideNavigation =
-                    !requestedInsetsState.getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR);
+                    !win.getRequestedVisibility(ITYPE_NAVIGATION_BAR);
 
             // TYPE_BASE_APPLICATION windows are never considered floating here because they don't
             // get cropped / shifted to the displayFrame in WindowState.
@@ -2377,7 +2373,7 @@
                 topIsFullscreen = topAppHidesStatusBar;
                 // The subtle difference between the window for mTopFullscreenOpaqueWindowState
                 // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window
-                // has the FLAG_FULLSCREEN set.  Not sure if there is another way that to be the
+                // requests to hide the status bar.  Not sure if there is another way that to be the
                 // case though.
                 if (!topIsFullscreen || mDisplayContent.getDefaultTaskDisplayArea()
                         .isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)) {
@@ -2421,16 +2417,7 @@
         if (mTopFullscreenOpaqueWindowState == null || mForceShowSystemBars) {
             return false;
         }
-        final LayoutParams attrs = mTopFullscreenOpaqueWindowState.getAttrs();
-        final int fl = attrs.flags;
-        final InsetsSource request = mTopFullscreenOpaqueWindowState.getRequestedInsetsState()
-                .peekSource(ITYPE_STATUS_BAR);
-        if (WindowManagerDebugConfig.DEBUG) {
-            Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrame());
-            Slog.d(TAG, "attr: " + attrs + " request: " + request);
-        }
-        return (fl & LayoutParams.FLAG_FULLSCREEN) != 0
-                || (request != null && !request.isVisible());
+        return !mTopFullscreenOpaqueWindowState.getRequestedVisibility(ITYPE_STATUS_BAR);
     }
 
     /**
@@ -2864,18 +2851,15 @@
             return;
         }
 
-        final InsetsState requestedState = controlTarget.getRequestedInsetsState();
         final @InsetsType int restorePositionTypes =
-                (requestedState.getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR)
+                (controlTarget.getRequestedVisibility(ITYPE_NAVIGATION_BAR)
                         ? Type.navigationBars() : 0)
-                | (requestedState.getSourceOrDefaultVisibility(ITYPE_STATUS_BAR)
+                | (controlTarget.getRequestedVisibility(ITYPE_STATUS_BAR)
                         ? Type.statusBars() : 0)
-                | (mExtraNavBarAlt != null
-                        && requestedState.getSourceOrDefaultVisibility(
+                | (mExtraNavBarAlt != null && controlTarget.getRequestedVisibility(
                                 ITYPE_EXTRA_NAVIGATION_BAR)
                         ? Type.navigationBars() : 0)
-                | (mClimateBarAlt != null
-                        && requestedState.getSourceOrDefaultVisibility(
+                | (mClimateBarAlt != null && controlTarget.getRequestedVisibility(
                                 ITYPE_CLIMATE_BAR)
                         ? Type.statusBars() : 0);
 
@@ -2981,12 +2965,11 @@
                 win.mAttrs.insetsFlags.appearance, mTopFullscreenOpaqueWindowState,
                 mTopFullscreenOpaqueOrDimmingWindowState,
                 mDisplayContent.mInputMethodWindow, navColorWin) | opaqueAppearance;
-        final InsetsState requestedInsets = win.getRequestedInsetsState();
         final int behavior = win.mAttrs.insetsFlags.behavior;
         final boolean isImmersive = behavior == BEHAVIOR_SHOW_BARS_BY_SWIPE
                 || behavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
-        final boolean isFullscreen = !requestedInsets.getSourceOrDefaultVisibility(ITYPE_STATUS_BAR)
-                || !requestedInsets.getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR);
+        final boolean isFullscreen = !win.getRequestedVisibility(ITYPE_STATUS_BAR)
+                || !win.getRequestedVisibility(ITYPE_NAVIGATION_BAR);
         if (mLastDisableFlags == disableFlags
                 && mLastAppearance == appearance
                 && mLastFullscreenAppearance == fullscreenAppearance
@@ -3152,10 +3135,7 @@
                 freeformStackVisible, resizing, fullscreenDrawsNavBarBackground,
                 dockedDrawsNavigationBarBackground);
 
-        final InsetsState requestedInsetsState = win.getRequestedInsetsState();
-        final boolean requestHideNavBar = !requestedInsetsState.getSourceOrDefaultVisibility(
-                        ITYPE_NAVIGATION_BAR);
-
+        final boolean requestHideNavBar = !win.getRequestedVisibility(ITYPE_NAVIGATION_BAR);
         final long now = SystemClock.uptimeMillis();
         final boolean pendingPanic = mPendingPanicGestureUptime != 0
                 && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
diff --git a/services/core/java/com/android/server/wm/InsetsControlTarget.java b/services/core/java/com/android/server/wm/InsetsControlTarget.java
index 5e7ed3f..287dd74 100644
--- a/services/core/java/com/android/server/wm/InsetsControlTarget.java
+++ b/services/core/java/com/android/server/wm/InsetsControlTarget.java
@@ -18,6 +18,7 @@
 
 import android.inputmethodservice.InputMethodService;
 import android.view.InsetsState;
+import android.view.InsetsState.InternalInsetsType;
 import android.view.WindowInsets.Type.InsetsType;
 
 /**
@@ -39,10 +40,10 @@
     }
 
     /**
-     * @return The requested {@link InsetsState} of this target.
+     * @return The requested visibility of this target.
      */
-    default InsetsState getRequestedInsetsState() {
-        return InsetsState.EMPTY;
+    default boolean getRequestedVisibility(@InternalInsetsType int type) {
+        return InsetsState.getDefaultVisibility(type);
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 3617884..bd05da9 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -173,13 +173,7 @@
             // animation frame which will be triggered if a new leash is created.
             mDisplayContent.mWmService.mAnimator.getChoreographer().postFrameCallback(time -> {
                 synchronized (mDisplayContent.mWmService.mGlobalLock) {
-                    final InsetsState state = new InsetsState(mStateController.getRawInsetsState());
-                    startAnimation(true /* show */, () -> {
-                        synchronized (mDisplayContent.mWmService.mGlobalLock) {
-                            mStateController.notifyInsetsChanged();
-                        }
-                    }, state);
-                    mStateController.onInsetsModified(mDummyControlTarget, state);
+                    startAnimation(true /* show */, null /* callback */);
                 }
             });
         }
@@ -189,15 +183,18 @@
         if (mShowingTransientTypes.size() == 0) {
             return;
         }
-        InsetsState state = new InsetsState(mStateController.getRawInsetsState());
         startAnimation(false /* show */, () -> {
             synchronized (mDisplayContent.mWmService.mGlobalLock) {
+                for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
+                    // We are about to clear mShowingTransientTypes, we don't want the transient bar
+                    // can cause insets on the client. Restore the client visibility.
+                    final @InternalInsetsType int type = mShowingTransientTypes.get(i);
+                    mStateController.getSourceProvider(type).setClientVisible(false);
+                }
                 mShowingTransientTypes.clear();
-                mStateController.notifyInsetsChanged();
                 updateBarControlTarget(mFocusedWin);
             }
-        }, state);
-        mStateController.onInsetsModified(mDummyControlTarget, state);
+        });
     }
 
     boolean isTransient(@InternalInsetsType int type) {
@@ -211,7 +208,7 @@
         final InsetsState originalState = mStateController.getInsetsForDispatch(target);
         InsetsState state = originalState;
         for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
-            final int type = mShowingTransientTypes.get(i);
+            final @InternalInsetsType int type = mShowingTransientTypes.get(i);
             final InsetsSource originalSource = state.peekSource(type);
             if (originalSource != null && originalSource.isVisible()) {
                 if (state == originalState) {
@@ -227,26 +224,25 @@
         return state;
     }
 
-    void onInsetsModified(WindowState windowState, InsetsState state) {
-        mStateController.onInsetsModified(windowState, state);
-        checkAbortTransient(windowState, state);
+    void onInsetsModified(InsetsControlTarget caller) {
+        mStateController.onInsetsModified(caller);
+        checkAbortTransient(caller);
         updateBarControlTarget(mFocusedWin);
     }
 
     /**
-     * Called when a window modified the insets state. If the window set a insets source to visible
-     * while it is shown transiently, we need to abort the transient state.
+     * Called when a control target modified the insets state. If the target set a insets source to
+     * visible while it is shown transiently, we need to abort the transient state.
      *
-     * @param windowState who changed the insets state.
-     * @param state the modified insets state.
+     * @param caller who changed the insets state.
      */
-    private void checkAbortTransient(WindowState windowState, InsetsState state) {
+    private void checkAbortTransient(InsetsControlTarget caller) {
         if (mShowingTransientTypes.size() != 0) {
             IntArray abortTypes = new IntArray();
             for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
-                final int type = mShowingTransientTypes.get(i);
-                if (mStateController.isFakeTarget(type, windowState)
-                        && state.getSource(type).isVisible()) {
+                final @InternalInsetsType int type = mShowingTransientTypes.get(i);
+                if (mStateController.isFakeTarget(type, caller)
+                        && caller.getRequestedVisibility(type)) {
                     mShowingTransientTypes.remove(i);
                     abortTypes.add(type);
                 }
@@ -393,12 +389,12 @@
     }
 
     @VisibleForTesting
-    void startAnimation(boolean show, Runnable callback, InsetsState state) {
+    void startAnimation(boolean show, Runnable callback) {
         int typesReady = 0;
         final SparseArray<InsetsSourceControl> controls = new SparseArray<>();
         final IntArray showingTransientTypes = mShowingTransientTypes;
         for (int i = showingTransientTypes.size() - 1; i >= 0; i--) {
-            int type = showingTransientTypes.get(i);
+            final @InternalInsetsType int type = showingTransientTypes.get(i);
             InsetsSourceProvider provider = mStateController.getSourceProvider(type);
             InsetsSourceControl control = provider.getControl(mDummyControlTarget);
             if (control == null || control.getLeash() == null) {
@@ -406,7 +402,6 @@
             }
             typesReady |= InsetsState.toPublicType(type);
             controls.put(control.getType(), new InsetsSourceControl(control));
-            state.setSourceVisible(type, show);
         }
         controlAnimationUnchecked(typesReady, controls, show, callback);
     }
@@ -428,12 +423,9 @@
             mId = id;
         }
 
-        private void updateVisibility(InsetsControlTarget controlTarget,
+        private void updateVisibility(@Nullable InsetsControlTarget controlTarget,
                 @InternalInsetsType int type) {
-            final WindowState controllingWin =
-                    controlTarget instanceof WindowState ? (WindowState) controlTarget : null;
-            setVisible(controllingWin == null
-                    || controllingWin.getRequestedInsetsState().getSourceOrDefaultVisibility(type));
+            setVisible(controlTarget == null || controlTarget.getRequestedVisibility(type));
         }
 
         private void setVisible(boolean visible) {
@@ -463,7 +455,9 @@
         @Override
         protected void onAnimationFinish() {
             super.onAnimationFinish();
-            DisplayThread.getHandler().post(mFinishCallback);
+            if (mFinishCallback != null) {
+                DisplayThread.getHandler().post(mFinishCallback);
+            }
         }
 
         private class InsetsPolicyAnimationControlCallbacks implements
@@ -484,7 +478,7 @@
                 mAnimatingShown = show;
 
                 mAnimationControl = new InsetsAnimationControlImpl(controls,
-                        mFocusedWin.getDisplayContent().getBounds(), getState(),
+                        mFocusedWin.getDisplayContent().getBounds(), mFocusedWin.getInsetsState(),
                         mListener, typesReady, this, mListener.getDurationMs(),
                         InsetsController.SYSTEM_BARS_INTERPOLATOR,
                         show ? ANIMATION_TYPE_SHOW : ANIMATION_TYPE_HIDE);
@@ -495,8 +489,7 @@
             /** Called on SurfaceAnimationThread without global WM lock held. */
             @Override
             public void scheduleApplyChangeInsets(InsetsAnimationControlRunner runner) {
-                InsetsState state = getState();
-                if (mAnimationControl.applyChangeInsets(state)) {
+                if (mAnimationControl.applyChangeInsets(null /* outState */)) {
                     mAnimationControl.finish(mAnimatingShown);
                 }
             }
@@ -507,20 +500,6 @@
                 // onAnimationFinished callback.
             }
 
-            /**
-             * This method will return a state with fullscreen frame override. No need to make copy
-             * after getting state from this method.
-             * @return The client insets state with full display frame override.
-             */
-            private InsetsState getState() {
-                // To animate the transient animation correctly, we need to let the state hold
-                // the full display frame.
-                InsetsState overrideState = new InsetsState(mFocusedWin.getRequestedInsetsState(),
-                        true);
-                overrideState.setDisplayFrame(mFocusedWin.getDisplayContent().getBounds());
-                return overrideState;
-            }
-
             /** Called on SurfaceAnimationThread without global WM lock held. */
             @Override
             public void applySurfaceParams(
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index 7defc5d..e83151d 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -338,11 +338,12 @@
         }
     }
 
-    boolean onInsetsModified(InsetsControlTarget caller, InsetsSource modifiedSource) {
-        if (mControlTarget != caller || modifiedSource.isVisible() == mClientVisible) {
+    boolean updateClientVisibility(InsetsControlTarget caller) {
+        final boolean requestedVisible = caller.getRequestedVisibility(mSource.getType());
+        if (caller != mControlTarget || requestedVisible == mClientVisible) {
             return false;
         }
-        setClientVisible(modifiedSource.isVisible());
+        setClientVisible(requestedVisible);
         return true;
     }
 
@@ -350,7 +351,7 @@
         mIsLeashReadyForDispatching = true;
     }
 
-    private void setClientVisible(boolean clientVisible) {
+    void setClientVisible(boolean clientVisible) {
         if (mClientVisible == clientVisible) {
             return;
         }
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index b59452f..b9c2093 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -289,16 +289,10 @@
         winInsetsChanged.clear();
     }
 
-    void onInsetsModified(InsetsControlTarget windowState, InsetsState state) {
+    void onInsetsModified(InsetsControlTarget caller) {
         boolean changed = false;
-        for (int i = 0; i < InsetsState.SIZE; i++) {
-            final InsetsSource source = state.peekSource(i);
-            if (source == null) continue;
-            final InsetsSourceProvider provider = mProviders.get(source.getType());
-            if (provider == null) {
-                continue;
-            }
-            changed |= provider.onInsetsModified(windowState, source);
+        for (int i = mProviders.size() - 1; i >= 0; i--) {
+            changed |= mProviders.valueAt(i).updateClientVisibility(caller);
         }
         if (changed) {
             notifyInsetsChanged();
@@ -464,11 +458,24 @@
                 final InsetsSourceProvider provider = mProviders.valueAt(i);
                 provider.onSurfaceTransactionApplied();
             }
+            final ArraySet<InsetsControlTarget> newControlTargets = new ArraySet<>();
             for (int i = mPendingControlChanged.size() - 1; i >= 0; i--) {
                 final InsetsControlTarget controlTarget = mPendingControlChanged.valueAt(i);
                 controlTarget.notifyInsetsControlChanged();
+                if (mControlTargetTypeMap.containsKey(controlTarget)) {
+                    // We only collect targets who get controls, not lose controls.
+                    newControlTargets.add(controlTarget);
+                }
             }
             mPendingControlChanged.clear();
+
+            // This updates the insets visibilities AFTER sending current insets state and controls
+            // to the clients, so that the clients can change the current visibilities to the
+            // requested visibilities with animations.
+            for (int i = newControlTargets.size() - 1; i >= 0; i--) {
+                onInsetsModified(newControlTargets.valueAt(i));
+            }
+            newControlTargets.clear();
         });
     }
 
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 02230d6..1b887a7 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -84,6 +84,9 @@
     private final ArraySet<WindowSurfaceController> mAlertWindowSurfaces = new ArraySet<>();
     private final DragDropController mDragDropController;
     final boolean mCanAddInternalSystemWindow;
+    // If non-system overlays from this process can be hidden by the user or app using
+    // HIDE_NON_SYSTEM_OVERLAY_WINDOWS.
+    final boolean mOverlaysCanBeHidden;
     final boolean mCanHideNonSystemOverlayWindows;
     final boolean mCanAcquireSleepToken;
     private AlertWindowNotification mAlertWindowNotification;
@@ -92,6 +95,7 @@
     private float mLastReportedAnimatorScale;
     private String mPackageName;
     private String mRelayoutTag;
+    private final InsetsState mDummyRequestedVisibility = new InsetsState();
     private final InsetsSourceControl[] mDummyControls =  new InsetsSourceControl[0];
 
     public Session(WindowManagerService service, IWindowSessionCallback callback) {
@@ -104,6 +108,8 @@
                 INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED;
         mCanHideNonSystemOverlayWindows = service.mContext.checkCallingOrSelfPermission(
                 HIDE_NON_SYSTEM_OVERLAY_WINDOWS) == PERMISSION_GRANTED;
+        mOverlaysCanBeHidden = !mCanAddInternalSystemWindow
+                && !mService.mAtmInternal.isCallerRecents(mUid);
         mCanAcquireSleepToken = service.mContext.checkCallingOrSelfPermission(DEVICE_POWER)
                 == PERMISSION_GRANTED;
         mShowingAlertWindowNotificationAllowed = mService.mShowAlertWindowNotifications;
@@ -158,25 +164,26 @@
 
     @Override
     public int addToDisplay(IWindow window, WindowManager.LayoutParams attrs,
-            int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
-            Rect outStableInsets,
+            int viewVisibility, int displayId, InsetsState requestedVisibility, Rect outFrame,
+            Rect outContentInsets, Rect outStableInsets,
             DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
             InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
-        return mService.addWindow(this, window, attrs, viewVisibility, displayId, outFrame,
+        return mService.addWindow(this, window, attrs, viewVisibility, displayId,
+                UserHandle.getUserId(mUid), requestedVisibility, outFrame,
                 outContentInsets, outStableInsets, outDisplayCutout, outInputChannel,
-                outInsetsState, outActiveControls, UserHandle.getUserId(mUid));
+                outInsetsState, outActiveControls);
     }
 
 
     @Override
     public int addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs,
-            int viewVisibility, int displayId, int userId, Rect outFrame,
-            Rect outContentInsets, Rect outStableInsets,
+            int viewVisibility, int displayId, int userId, InsetsState requestedVisibility,
+            Rect outFrame, Rect outContentInsets, Rect outStableInsets,
             DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
             InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
-        return mService.addWindow(this, window, attrs, viewVisibility, displayId, outFrame,
-                outContentInsets, outStableInsets, outDisplayCutout, outInputChannel,
-                outInsetsState, outActiveControls, userId);
+        return mService.addWindow(this, window, attrs, viewVisibility, displayId, userId,
+                requestedVisibility, outFrame, outContentInsets, outStableInsets, outDisplayCutout,
+                outInputChannel, outInsetsState, outActiveControls);
     }
 
     @Override
@@ -184,9 +191,10 @@
             int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
             InsetsState outInsetsState) {
         return mService.addWindow(this, window, attrs, viewVisibility, displayId,
+                UserHandle.getUserId(mUid), mDummyRequestedVisibility,
                 new Rect() /* outFrame */, outContentInsets, outStableInsets,
                 new DisplayCutout.ParcelableWrapper() /* cutout */, null /* outInputChannel */,
-                outInsetsState, mDummyControls, UserHandle.getUserId(mUid));
+                outInsetsState, mDummyControls);
     }
 
     @Override
@@ -493,9 +501,8 @@
             final WindowState windowState = mService.windowForClientLocked(this, window,
                     false /* throwOnError */);
             if (windowState != null) {
-                windowState.updateRequestedInsetsState(state);
-                windowState.getDisplayContent().getInsetsPolicy().onInsetsModified(
-                        windowState, state);
+                windowState.updateRequestedVisibility(state);
+                windowState.getDisplayContent().getInsetsPolicy().onInsetsModified(windowState);
             }
         }
     }
@@ -532,7 +539,7 @@
 
         boolean changed;
 
-        if (!mCanAddInternalSystemWindow) {
+        if (mOverlaysCanBeHidden) {
             // We want to track non-system signature apps adding alert windows so we can post an
             // on-going notification for the user to control their visibility.
             if (visible) {
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 48550ed0..6504f00 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -161,17 +161,18 @@
                 return;
             }
             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Task info changed taskId=%d", task.mTaskId);
-            mDeferTaskOrgCallbacksConsumer.accept(() -> {
-                if (!task.isOrganized()) {
-                    // This is safe to ignore if the task is no longer organized
-                    return;
-                }
-                try {
-                    mTaskOrganizer.onTaskInfoChanged(taskInfo);
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Exception sending onTaskInfoChanged callback", e);
-                }
-            });
+            if (!task.isOrganized()) {
+                // This is safe to ignore if the task is no longer organized
+                return;
+            }
+            try {
+                // Purposely notify of task info change immediately instead of deferring (like
+                // appear and vanish) to allow info changes (such as new PIP params) to flow
+                // without waiting.
+                mTaskOrganizer.onTaskInfoChanged(taskInfo);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Exception sending onTaskInfoChanged callback", e);
+            }
         }
 
         void onBackPressedOnTaskRoot(Task task) {
@@ -182,17 +183,15 @@
                 // by the organizer that don't receive that signal
                 return;
             }
-            mDeferTaskOrgCallbacksConsumer.accept(() -> {
-                if (!task.isOrganized()) {
-                    // This is safe to ignore if the task is no longer organized
-                    return;
-                }
-                try {
-                   mTaskOrganizer.onBackPressedOnTaskRoot(task.getTaskInfo());
-                } catch (Exception e) {
-                    Slog.e(TAG, "Exception sending onBackPressedOnTaskRoot callback", e);
-                }
-            });
+            if (!task.isOrganized()) {
+                // This is safe to ignore if the task is no longer organized
+                return;
+            }
+            try {
+                mTaskOrganizer.onBackPressedOnTaskRoot(task.getTaskInfo());
+            } catch (Exception e) {
+                Slog.e(TAG, "Exception sending onBackPressedOnTaskRoot callback", e);
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 87b470a..01adb8b 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -482,8 +482,7 @@
         final int color = ColorUtils.setAlphaComponent(
                 task.getTaskDescription().getBackgroundColor(), 255);
         final LayoutParams attrs = mainWindow.getAttrs();
-        final InsetsState insetsState = new InsetsState(mainWindow.getInsetsState());
-        mergeInsetsSources(insetsState, mainWindow.getRequestedInsetsState());
+        final InsetsState insetsState = getInsetsStateWithVisibilityOverride(mainWindow);
         final Rect systemBarInsets = getSystemBarInsets(mainWindow.getFrame(), insetsState);
         final SystemBarBackgroundPainter decorPainter = new SystemBarBackgroundPainter(attrs.flags,
                 attrs.privateFlags, attrs.insetsFlags.appearance, task.getTaskDescription(),
@@ -603,13 +602,18 @@
         return 0;
     }
 
-    static void mergeInsetsSources(InsetsState base, InsetsState other) {
+    static InsetsState getInsetsStateWithVisibilityOverride(WindowState win) {
+        final InsetsState state = new InsetsState(win.getInsetsState());
         for (@InternalInsetsType int type = 0; type < InsetsState.SIZE; type++) {
-            final InsetsSource source = other.peekSource(type);
-            if (source != null) {
-                base.addSource(source);
+            final boolean requestedVisible = win.getRequestedVisibility(type);
+            InsetsSource source = state.peekSource(type);
+            if (source != null && source.isVisible() != requestedVisible) {
+                source = new InsetsSource(source);
+                source.setVisible(requestedVisible);
+                state.addSource(source);
             }
         }
+        return state;
     }
 
     static Rect getSystemBarInsets(Rect frame, InsetsState state) {
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index efa0525..e8c4491 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -42,8 +42,8 @@
 import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES;
 import static com.android.internal.policy.DecorView.getNavigationBarRect;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
+import static com.android.server.wm.TaskSnapshotController.getInsetsStateWithVisibilityOverride;
 import static com.android.server.wm.TaskSnapshotController.getSystemBarInsets;
-import static com.android.server.wm.TaskSnapshotController.mergeInsetsSources;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
@@ -236,14 +236,15 @@
             task.getBounds(taskBounds);
             currentOrientation = topFullscreenOpaqueWindow.getConfiguration().orientation;
             activityType = activity.getActivityType();
-            insetsState = new InsetsState(topFullscreenOpaqueWindow.getInsetsState());
-            mergeInsetsSources(insetsState, topFullscreenOpaqueWindow.getRequestedInsetsState());
+            insetsState = getInsetsStateWithVisibilityOverride(topFullscreenOpaqueWindow);
+
         }
         try {
             final int res = session.addToDisplay(window, layoutParams,
-                    View.GONE, activity.getDisplayContent().getDisplayId(), tmpFrames.frame,
-                    tmpFrames.contentInsets, tmpFrames.stableInsets, tmpFrames.displayCutout,
-                    null /* outInputChannel */, mTmpInsetsState, mTempControls);
+                    View.GONE, activity.getDisplayContent().getDisplayId(), mTmpInsetsState,
+                    tmpFrames.frame, tmpFrames.contentInsets, tmpFrames.stableInsets,
+                    tmpFrames.displayCutout, null /* outInputChannel */, mTmpInsetsState,
+                    mTempControls);
             if (res < 0) {
                 Slog.w(TAG, "Failed to add snapshot starting window res=" + res);
                 return null;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 26655f4..ad624d5 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -225,7 +225,7 @@
 import android.view.IPinnedStackListener;
 import android.view.IRecentsAnimationRunner;
 import android.view.IRotationWatcher;
-import android.view.IScrollCaptureController;
+import android.view.IScrollCaptureCallbacks;
 import android.view.ISystemGestureExclusionListener;
 import android.view.IWallpaperVisibilityListener;
 import android.view.IWindow;
@@ -1375,10 +1375,10 @@
     }
 
     public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,
-            int displayId, Rect outFrame, Rect outContentInsets, Rect outStableInsets,
+            int displayId, int requestUserId, InsetsState requestedVisibility, Rect outFrame,
+            Rect outContentInsets, Rect outStableInsets,
             DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
-            InsetsState outInsetsState, InsetsSourceControl[] outActiveControls,
-            int requestUserId) {
+            InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
         Arrays.fill(outActiveControls, null);
         int[] appOp = new int[1];
         final boolean isRoundedCornerOverlay = (attrs.privateFlags
@@ -1573,6 +1573,7 @@
 
             final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy();
             displayPolicy.adjustWindowParamsLw(win, win.mAttrs, callingPid, callingUid);
+            win.updateRequestedVisibility(requestedVisibility);
 
             res = displayPolicy.validateAddingWindowLw(attrs, callingPid, callingUid);
             if (res != WindowManagerGlobal.ADD_OKAY) {
@@ -4034,8 +4035,8 @@
                 if (dc == null || dc.mRemoteInsetsControlTarget == null) {
                     return;
                 }
-                dc.getInsetsStateController().onInsetsModified(
-                        dc.mRemoteInsetsControlTarget, state);
+                dc.mRemoteInsetsControlTarget.updateRequestedVisibility(state);
+                dc.getInsetsStateController().onInsetsModified(dc.mRemoteInsetsControlTarget);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -6901,16 +6902,17 @@
      *
      * @param displayId the display for the request
      * @param behindClient token for a window, used to filter the search to windows behind it
-     * @param taskId specifies the id of a task the result must belong to or -1 to ignore task ids
-     * @param controller the controller to receive results; a call to either
-     *      {@link IScrollCaptureController#onClientConnected} or
-     *      {@link IScrollCaptureController#onClientUnavailable}.
+     * @param taskId specifies the id of a task the result must belong to or -1 to match any task
+     * @param callbacks to receive responses
      */
     public void requestScrollCapture(int displayId, @Nullable IBinder behindClient, int taskId,
-            IScrollCaptureController controller) {
+            IScrollCaptureCallbacks callbacks) {
         if (!checkCallingPermission(READ_FRAME_BUFFER, "requestScrollCapture()")) {
             throw new SecurityException("Requires READ_FRAME_BUFFER permission");
         }
+        if (behindClient != null && !isWindowToken(behindClient)) {
+            throw new IllegalArgumentException("behindClient must be a window token");
+        }
         final long token = Binder.clearCallingIdentity();
         try {
             synchronized (mGlobalLock) {
@@ -6918,26 +6920,26 @@
                 if (dc == null) {
                     ProtoLog.e(WM_ERROR,
                             "Invalid displayId for requestScrollCapture: %d", displayId);
-                    controller.onClientUnavailable();
+                    callbacks.onUnavailable();
                     return;
                 }
                 WindowState topWindow = null;
                 if (behindClient != null) {
-                    topWindow = windowForClientLocked(null, behindClient, /* throwOnError*/ true);
+                    topWindow = windowForClientLocked(null, behindClient, /* throwOnError*/ false);
                 }
                 WindowState targetWindow = dc.findScrollCaptureTargetWindow(topWindow, taskId);
                 if (targetWindow == null) {
-                    controller.onClientUnavailable();
+                    callbacks.onUnavailable();
                     return;
                 }
                 // Forward to the window for handling.
                 try {
-                    targetWindow.mClient.requestScrollCapture(controller);
+                    targetWindow.mClient.requestScrollCapture(callbacks);
                 } catch (RemoteException e) {
                     ProtoLog.w(WM_ERROR,
                             "requestScrollCapture: caught exception dispatching to window."
                                     + "token=%s", targetWindow.mClient.asBinder());
-                    controller.onClientUnavailable();
+                    callbacks.onUnavailable();
                 }
             }
         } catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index e8a7a9c1..2e7905c 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -1257,20 +1257,27 @@
         mAtm.mStackSupervisor.removeHistoryRecords(this);
 
         boolean hasVisibleActivities = false;
-        if (mInactiveActivities != null && !mInactiveActivities.isEmpty()) {
+        final boolean hasInactiveActivities =
+                mInactiveActivities != null && !mInactiveActivities.isEmpty();
+        final ArrayList<ActivityRecord> activities =
+                (mHasActivities || hasInactiveActivities) ? new ArrayList<>() : mActivities;
+        if (mHasActivities) {
+            activities.addAll(mActivities);
+        }
+        if (hasInactiveActivities) {
             // Make sure that all activities in this process are handled.
-            mActivities.addAll(mInactiveActivities);
+            activities.addAll(mInactiveActivities);
         }
         if (isRemoved()) {
             // The package of the died process should be force-stopped, so make its activities as
             // finishing to prevent the process from being started again if the next top (or being
             // visible) activity also resides in the same process. This must be done before removal.
-            for (int i = mActivities.size() - 1; i >= 0; i--) {
-                mActivities.get(i).makeFinishingLocked();
+            for (int i = activities.size() - 1; i >= 0; i--) {
+                activities.get(i).makeFinishingLocked();
             }
         }
-        for (int i = mActivities.size() - 1; i >= 0; i--) {
-            final ActivityRecord r = mActivities.get(i);
+        for (int i = activities.size() - 1; i >= 0; i--) {
+            final ActivityRecord r = activities.get(i);
             if (r.mVisibleRequested || r.isVisible()) {
                 // While an activity launches a new activity, it's possible that the old activity
                 // is already requested to be hidden (mVisibleRequested=false), but this visibility
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 25b4828..d4b6d00 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -224,6 +224,7 @@
 import android.view.InputWindowHandle;
 import android.view.InsetsSource;
 import android.view.InsetsState;
+import android.view.InsetsState.InternalInsetsType;
 import android.view.Surface.Rotation;
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
@@ -719,20 +720,20 @@
     private final WindowProcessController mWpcForDisplayConfigChanges;
 
     /**
-     * @return The insets state as requested by the client, i.e. the dispatched insets state
-     *         for which the visibilities are overridden with what the client requested.
+     * Returns the visibility of the given {@link InternalInsetsType type} requested by the client.
+     *
+     * @param type the given {@link InternalInsetsType type}.
+     * @return {@code true} if the type is requested visible.
      */
     @Override
-    public InsetsState getRequestedInsetsState() {
-        return mRequestedInsetsState;
+    public boolean getRequestedVisibility(@InternalInsetsType int type) {
+        return mRequestedInsetsState.getSourceOrDefaultVisibility(type);
     }
 
     /**
-     * @see #getRequestedInsetsState()
+     * @see #getRequestedVisibility(int)
      */
-    void updateRequestedInsetsState(InsetsState state) {
-
-        // Only update the sources the client is actually controlling.
+    void updateRequestedVisibility(InsetsState state) {
         for (int i = 0; i < InsetsState.SIZE; i++) {
             final InsetsSource source = state.peekSource(i);
             if (source == null) continue;
@@ -3056,7 +3057,7 @@
     }
 
     void setForceHideNonSystemOverlayWindowIfNeeded(boolean forceHide) {
-        if (mOwnerCanAddInternalSystemWindow
+        if (!mSession.mOverlaysCanBeHidden
                 || (!isSystemAlertWindowType(mAttrs.type) && mAttrs.type != TYPE_TOAST)) {
             return;
         }
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 30f6fa6..d6a56ba 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -21,6 +21,7 @@
         "BroadcastRadio/TunerCallback.cpp",
         "BroadcastRadio/convert.cpp",
         "BroadcastRadio/regions.cpp",
+        "gnss/GnssConfiguration.cpp",
         "stats/PowerStatsPuller.cpp",
         "stats/SubsystemSleepStatePuller.cpp",
         "com_android_server_adb_AdbDebuggingManager.cpp",
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 31b9ad6..e9d048a 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "GnssLocationProvider"
-
+// Define LOG_TAG and LOG_NDEBUG before <log/log.h> to overwrite the default values.
+#define LOG_TAG "GnssLocationProviderJni"
 #define LOG_NDEBUG 0
 
 #include <android/hardware/gnss/1.0/IGnss.h>
@@ -39,6 +39,7 @@
 #include <nativehelper/JNIHelp.h>
 #include "android_runtime/AndroidRuntime.h"
 #include "android_runtime/Log.h"
+#include "gnss/GnssConfiguration.h"
 #include "hardware_legacy/power.h"
 #include "jni.h"
 #include "utils/Log.h"
@@ -59,7 +60,6 @@
 static jclass class_location;
 static jclass class_gnssNavigationMessage;
 static jclass class_gnssClock;
-static jclass class_gnssConfiguration_halInterfaceVersion;
 static jclass class_gnssAntennaInfoBuilder;
 static jclass class_phaseCenterOffset;
 static jclass class_sphericalCorrections;
@@ -125,7 +125,6 @@
 static jmethodID method_gnssNavigationMessageCtor;
 static jmethodID method_gnssClockCtor;
 static jmethodID method_gnssMeasurementCtor;
-static jmethodID method_halInterfaceVersionCtor;
 static jmethodID method_gnssAntennaInfoBuilderCtor;
 static jmethodID method_phaseCenterOffsetCtor;
 static jmethodID method_sphericalCorrectionsCtor;
@@ -149,6 +148,7 @@
 using android::String16;
 using android::wp;
 using android::binder::Status;
+using android::gnss::GnssConfigurationInterface;
 
 using android::hardware::Return;
 using android::hardware::Void;
@@ -192,10 +192,6 @@
 using IGnssCallback_V1_0 = android::hardware::gnss::V1_0::IGnssCallback;
 using IGnssCallback_V2_0 = android::hardware::gnss::V2_0::IGnssCallback;
 using IGnssCallback_V2_1 = android::hardware::gnss::V2_1::IGnssCallback;
-using IGnssConfiguration_V1_0 = android::hardware::gnss::V1_0::IGnssConfiguration;
-using IGnssConfiguration_V1_1 = android::hardware::gnss::V1_1::IGnssConfiguration;
-using IGnssConfiguration_V2_0 = android::hardware::gnss::V2_0::IGnssConfiguration;
-using IGnssConfiguration_V2_1 = android::hardware::gnss::V2_1::IGnssConfiguration;
 using IGnssDebug_V1_0 = android::hardware::gnss::V1_0::IGnssDebug;
 using IGnssDebug_V2_0 = android::hardware::gnss::V2_0::IGnssDebug;
 using IGnssAntennaInfo = android::hardware::gnss::V2_1::IGnssAntennaInfo;
@@ -269,11 +265,6 @@
 sp<IGnssBatching_V2_0> gnssBatchingIface_V2_0 = nullptr;
 sp<IGnssDebug_V1_0> gnssDebugIface = nullptr;
 sp<IGnssDebug_V2_0> gnssDebugIface_V2_0 = nullptr;
-sp<IGnssConfigurationAidl> gnssConfigurationAidlIface = nullptr;
-sp<IGnssConfiguration_V1_0> gnssConfigurationIface = nullptr;
-sp<IGnssConfiguration_V1_1> gnssConfigurationIface_V1_1 = nullptr;
-sp<IGnssConfiguration_V2_0> gnssConfigurationIface_V2_0 = nullptr;
-sp<IGnssConfiguration_V2_1> gnssConfigurationIface_V2_1 = nullptr;
 sp<IGnssNi> gnssNiIface = nullptr;
 sp<IGnssMeasurement_V1_0> gnssMeasurementIface = nullptr;
 sp<IGnssMeasurement_V1_1> gnssMeasurementIface_V1_1 = nullptr;
@@ -285,6 +276,8 @@
 sp<IGnssVisibilityControl> gnssVisibilityControlIface = nullptr;
 sp<IGnssAntennaInfo> gnssAntennaInfoIface = nullptr;
 
+std::unique_ptr<GnssConfigurationInterface> gnssConfigurationIface = nullptr;
+
 #define WAKE_LOCK_NAME  "GPS"
 
 namespace android {
@@ -467,12 +460,6 @@
     return JNI_TRUE;
 }
 
-static jobject createHalInterfaceVersionJavaObject(JNIEnv* env, jint major, jint minor) {
-    jobject version = env->NewObject(class_gnssConfiguration_halInterfaceVersion,
-            method_halInterfaceVersionCtor, major, minor);
-    return version;
-}
-
 struct ScopedJniString {
     ScopedJniString(JNIEnv* env, jstring javaString) : mEnv(env), mJavaString(javaString) {
         mNativeString = mEnv->GetStringUTFChars(mJavaString, nullptr);
@@ -2159,13 +2146,6 @@
     class_gnssClock = (jclass) env->NewGlobalRef(gnssClockClass);
     method_gnssClockCtor = env->GetMethodID(class_gnssClock, "<init>", "()V");
 
-    jclass gnssConfiguration_halInterfaceVersionClass = env->FindClass(
-            "com/android/server/location/gnss/GnssConfiguration$HalInterfaceVersion");
-    class_gnssConfiguration_halInterfaceVersion =
-            (jclass) env->NewGlobalRef(gnssConfiguration_halInterfaceVersionClass);
-    method_halInterfaceVersionCtor =
-            env->GetMethodID(class_gnssConfiguration_halInterfaceVersion, "<init>", "(II)V");
-
     jclass arrayListClass = env->FindClass("java/util/ArrayList");
     class_arrayList = (jclass)env->NewGlobalRef(arrayListClass);
     method_arrayListCtor = env->GetMethodID(class_arrayList, "<init>", "()V");
@@ -2173,6 +2153,8 @@
 
     jclass doubleArrayClass = env->FindClass("[D");
     class_doubleArray = (jclass)env->NewGlobalRef(doubleArrayClass);
+
+    gnss::GnssConfiguration_class_init_once(env);
 }
 
 /* Initialization needed at system boot and whenever GNSS service dies. */
@@ -2373,44 +2355,38 @@
     if (gnssHalAidl != nullptr) {
         sp<IGnssConfigurationAidl> gnssConfigurationAidl;
         auto status = gnssHalAidl->getExtensionGnssConfiguration(&gnssConfigurationAidl);
-        if (status.isOk()) {
-            gnssConfigurationAidlIface = gnssConfigurationAidl;
-        } else {
-            ALOGD("Unable to get a handle to GnssConfiguration AIDL interface.");
+        if (checkAidlStatus(status,
+                            "Unable to get a handle to GnssConfiguration AIDL interface.")) {
+            gnssConfigurationIface =
+                    std::make_unique<android::gnss::GnssConfiguration>(gnssConfigurationAidl);
         }
     } else if (gnssHal_V2_1 != nullptr) {
         auto gnssConfiguration = gnssHal_V2_1->getExtensionGnssConfiguration_2_1();
-        if (!gnssConfiguration.isOk()) {
-            ALOGD("Unable to get a handle to GnssConfiguration_V2_1");
-        } else {
-            gnssConfigurationIface_V2_1 = gnssConfiguration;
-            gnssConfigurationIface_V2_0 = gnssConfigurationIface_V2_1;
-            gnssConfigurationIface_V1_1 = gnssConfigurationIface_V2_1;
-            gnssConfigurationIface = gnssConfigurationIface_V2_1;
+        if (checkHidlReturn(gnssConfiguration,
+                            "Unable to get a handle to GnssConfiguration_V2_1")) {
+            gnssConfigurationIface =
+                    std::make_unique<android::gnss::GnssConfiguration_V2_1>(gnssConfiguration);
         }
     } else if (gnssHal_V2_0 != nullptr) {
         auto gnssConfiguration = gnssHal_V2_0->getExtensionGnssConfiguration_2_0();
-        if (!gnssConfiguration.isOk()) {
-            ALOGD("Unable to get a handle to GnssConfiguration_V2_0");
-        } else {
-            gnssConfigurationIface_V2_0 = gnssConfiguration;
-            gnssConfigurationIface_V1_1 = gnssConfigurationIface_V2_0;
-            gnssConfigurationIface = gnssConfigurationIface_V2_0;
+        if (checkHidlReturn(gnssConfiguration,
+                            "Unable to get a handle to GnssConfiguration_V2_0")) {
+            gnssConfigurationIface =
+                    std::make_unique<android::gnss::GnssConfiguration_V2_0>(gnssConfiguration);
         }
     } else if (gnssHal_V1_1 != nullptr) {
         auto gnssConfiguration = gnssHal_V1_1->getExtensionGnssConfiguration_1_1();
-        if (!gnssConfiguration.isOk()) {
-            ALOGD("Unable to get a handle to GnssConfiguration_V1_1");
-        } else {
-            gnssConfigurationIface_V1_1 = gnssConfiguration;
-            gnssConfigurationIface = gnssConfigurationIface_V1_1;
+        if (checkHidlReturn(gnssConfiguration,
+                            "Unable to get a handle to GnssConfiguration_V1_1")) {
+            gnssConfigurationIface =
+                    std::make_unique<android::gnss::GnssConfiguration_V1_1>(gnssConfiguration);
         }
     } else {
-        auto gnssConfiguration_V1_0 = gnssHal->getExtensionGnssConfiguration();
-        if (!gnssConfiguration_V1_0.isOk()) {
-            ALOGD("Unable to get a handle to GnssConfiguration");
-        } else {
-            gnssConfigurationIface = gnssConfiguration_V1_0;
+        auto gnssConfiguration = gnssHal->getExtensionGnssConfiguration();
+        if (checkHidlReturn(gnssConfiguration,
+                            "Unable to get a handle to GnssConfiguration_V1_0")) {
+            gnssConfigurationIface =
+                    std::make_unique<android::gnss::GnssConfiguration_V1_0>(gnssConfiguration);
         }
     }
 
@@ -2466,25 +2442,10 @@
 
 static jobject android_location_GnssConfiguration_get_gnss_configuration_version(
         JNIEnv* env, jclass /* jclazz */) {
-    jint major, minor;
-    if (gnssConfigurationIface_V2_1 != nullptr) {
-        major = 2;
-        minor = 1;
-    }
-    else if (gnssConfigurationIface_V2_0 != nullptr) {
-        major = 2;
-        minor = 0;
-    } else if (gnssConfigurationIface_V1_1 != nullptr) {
-        major = 1;
-        minor = 1;
-    } else if (gnssConfigurationIface != nullptr) {
-        major = 1;
-        minor = 0;
-    } else {
+    if (gnssConfigurationIface == nullptr) {
         return nullptr;
     }
-
-    return createHalInterfaceVersionJavaObject(env, major, minor);
+    return gnssConfigurationIface->getVersion(env);
 }
 
 /* Initialization needed each time the GPS service is shutdown. */
@@ -3486,203 +3447,89 @@
 static jboolean android_location_GnssConfiguration_set_emergency_supl_pdn(JNIEnv*,
                                                                           jobject,
                                                                           jint emergencySuplPdn) {
-    if (gnssConfigurationIface == nullptr && gnssConfigurationAidlIface == nullptr) {
+    if (gnssConfigurationIface == nullptr) {
         ALOGE("%s: IGnssConfiguration interface not available.", __func__);
         return JNI_FALSE;
     }
-
-    if (gnssConfigurationAidlIface != nullptr) {
-        auto status = gnssConfigurationAidlIface->setEmergencySuplPdn(emergencySuplPdn);
-        return checkAidlStatus(status, "gnssConfigurationAidlIface setEmergencySuplPdn() failed.");
-    }
-
-    auto result = gnssConfigurationIface->setEmergencySuplPdn(emergencySuplPdn);
-    return checkHidlReturn(result, "IGnssConfiguration setEmergencySuplPdn() failed.");
+    return gnssConfigurationIface->setEmergencySuplPdn(emergencySuplPdn);
 }
 
 static jboolean android_location_GnssConfiguration_set_supl_version(JNIEnv*,
                                                                     jobject,
                                                                     jint version) {
-    if (gnssConfigurationIface == nullptr && gnssConfigurationAidlIface == nullptr) {
+    if (gnssConfigurationIface == nullptr) {
         ALOGE("%s: IGnssConfiguration interface not available.", __func__);
         return JNI_FALSE;
     }
-
-    if (gnssConfigurationAidlIface != nullptr) {
-        auto status = gnssConfigurationAidlIface->setSuplVersion(version);
-        return checkAidlStatus(status, "gnssConfigurationAidlIface setSuplVersion() failed.");
-    }
-
-    auto result = gnssConfigurationIface->setSuplVersion(version);
-    return checkHidlReturn(result, "IGnssConfiguration setSuplVersion() failed.");
+    return gnssConfigurationIface->setSuplVersion(version);
 }
 
 static jboolean android_location_GnssConfiguration_set_supl_es(JNIEnv*,
                                                                jobject,
                                                                jint suplEs) {
-    if (gnssConfigurationIface_V2_0 != nullptr || gnssConfigurationIface_V2_1 != nullptr ||
-        gnssConfigurationAidlIface != nullptr) {
-        ALOGI("Config parameter SUPL_ES is deprecated in IGnssConfiguration.hal version 2.0 and higher.");
-        return JNI_FALSE;
-    }
-
     if (gnssConfigurationIface == nullptr) {
         ALOGE("%s: IGnssConfiguration interface not available.", __func__);
         return JNI_FALSE;
     }
-
-    auto result = gnssConfigurationIface->setSuplEs(suplEs);
-    return checkHidlReturn(result, "IGnssConfiguration setSuplEs() failed.");
+    return gnssConfigurationIface->setSuplEs(suplEs);
 }
 
 static jboolean android_location_GnssConfiguration_set_supl_mode(JNIEnv*,
                                                                  jobject,
                                                                  jint mode) {
-    if (gnssConfigurationIface == nullptr && gnssConfigurationAidlIface == nullptr) {
+    if (gnssConfigurationIface == nullptr) {
         ALOGE("%s: IGnssConfiguration interface not available.", __func__);
         return JNI_FALSE;
     }
-
-    if (gnssConfigurationAidlIface != nullptr) {
-        auto status = gnssConfigurationAidlIface->setSuplMode(mode);
-        return checkAidlStatus(status, "gnssConfigurationAidlIface setSuplMode() failed.");
-    }
-
-    auto result = gnssConfigurationIface->setSuplMode(mode);
-    return checkHidlReturn(result, "IGnssConfiguration setSuplMode() failed.");
+    return gnssConfigurationIface->setSuplMode(mode);
 }
 
 static jboolean android_location_GnssConfiguration_set_gps_lock(JNIEnv*,
                                                                 jobject,
                                                                 jint gpsLock) {
-    if (gnssConfigurationIface_V2_0 != nullptr || gnssConfigurationIface_V2_1 != nullptr ||
-        gnssConfigurationAidlIface != nullptr) {
-        ALOGI("Config parameter GPS_LOCK is deprecated in IGnssConfiguration.hal version 2.0.");
-        return JNI_FALSE;
-    }
-
     if (gnssConfigurationIface == nullptr) {
         ALOGE("%s: IGnssConfiguration interface not available.", __func__);
         return JNI_FALSE;
     }
-
-    auto result = gnssConfigurationIface->setGpsLock(gpsLock);
-    return checkHidlReturn(result, "IGnssConfiguration setGpsLock() failed.");
+    return gnssConfigurationIface->setGpsLock(gpsLock);
 }
 
 static jboolean android_location_GnssConfiguration_set_lpp_profile(JNIEnv*,
                                                                    jobject,
                                                                    jint lppProfile) {
-    if (gnssConfigurationIface == nullptr && gnssConfigurationAidlIface == nullptr) {
+    if (gnssConfigurationIface == nullptr) {
         ALOGE("%s: IGnssConfiguration interface not available.", __func__);
         return JNI_FALSE;
     }
-
-    if (gnssConfigurationAidlIface != nullptr) {
-        auto status = gnssConfigurationAidlIface->setLppProfile(lppProfile);
-        return checkAidlStatus(status, "gnssConfigurationAidlIface setLppProfile() failed.");
-    }
-
-    auto result = gnssConfigurationIface->setLppProfile(lppProfile);
-    return checkHidlReturn(result, "IGnssConfiguration setLppProfile() failed.");
+    return gnssConfigurationIface->setLppProfile(lppProfile);
 }
 
 static jboolean android_location_GnssConfiguration_set_gnss_pos_protocol_select(JNIEnv*,
                                                                             jobject,
                                                                             jint gnssPosProtocol) {
-    if (gnssConfigurationIface == nullptr && gnssConfigurationAidlIface == nullptr) {
+    if (gnssConfigurationIface == nullptr) {
         ALOGE("%s: IGnssConfiguration interface not available.", __func__);
         return JNI_FALSE;
     }
-
-    if (gnssConfigurationAidlIface != nullptr) {
-        auto status = gnssConfigurationAidlIface->setGlonassPositioningProtocol(gnssPosProtocol);
-        return checkAidlStatus(status,
-                               "gnssConfigurationAidlIface setGlonassPositioningProtocol() "
-                               "failed.");
-    }
-
-    auto result = gnssConfigurationIface->setGlonassPositioningProtocol(gnssPosProtocol);
-    return checkHidlReturn(result, "IGnssConfiguration setGlonassPositioningProtocol() failed.");
+    return gnssConfigurationIface->setGlonassPositioningProtocol(gnssPosProtocol);
 }
 
 static jboolean android_location_GnssConfiguration_set_satellite_blacklist(
         JNIEnv* env, jobject, jintArray constellations, jintArray sv_ids) {
-    if (gnssConfigurationIface_V1_1 == nullptr && gnssConfigurationIface_V2_1 == nullptr &&
-        gnssConfigurationAidlIface == nullptr) {
+    if (gnssConfigurationIface == nullptr) {
         ALOGI("IGnssConfiguration interface does not support satellite blacklist.");
         return JNI_FALSE;
     }
-
-    jint *constellation_array = env->GetIntArrayElements(constellations, 0);
-    if (nullptr == constellation_array) {
-        ALOGI("GetIntArrayElements returns nullptr.");
-        return JNI_FALSE;
-    }
-    jsize length = env->GetArrayLength(constellations);
-
-    jint *sv_id_array = env->GetIntArrayElements(sv_ids, 0);
-    if (nullptr == sv_id_array) {
-        ALOGI("GetIntArrayElements returns nullptr.");
-        return JNI_FALSE;
-    }
-
-    if (length != env->GetArrayLength(sv_ids)) {
-        ALOGI("Lengths of constellations and sv_ids are inconsistent.");
-        return JNI_FALSE;
-    }
-
-    if (gnssConfigurationAidlIface != nullptr) {
-        std::vector<BlocklistedSource> sources;
-        sources.resize(length);
-
-        for (int i = 0; i < length; i++) {
-            sources[i].constellation = static_cast<GnssConstellationType>(constellation_array[i]);
-            sources[i].svid = sv_id_array[i];
-        }
-
-        auto status = gnssConfigurationAidlIface->setBlocklist(sources);
-        return checkAidlStatus(status, "gnssConfigurationAidlIface setBlocklist() failed.");
-    } else if (gnssConfigurationIface_V2_1 != nullptr) {
-        hidl_vec<IGnssConfiguration_V2_1::BlacklistedSource> sources;
-        sources.resize(length);
-
-        for (int i = 0; i < length; i++) {
-            sources[i].constellation = static_cast<GnssConstellationType_V2_0>(constellation_array[i]);
-            sources[i].svid = sv_id_array[i];
-        }
-
-        auto result = gnssConfigurationIface_V2_1->setBlacklist_2_1(sources);
-        return checkHidlReturn(result, "IGnssConfiguration_V2_1 setBlacklist_2_1() failed.");
-    }
-
-    hidl_vec<IGnssConfiguration_V1_1::BlacklistedSource> sources;
-    sources.resize(length);
-
-    for (int i = 0; i < length; i++) {
-        sources[i].constellation = static_cast<GnssConstellationType_V1_0>(constellation_array[i]);
-        sources[i].svid = sv_id_array[i];
-    }
-
-    auto result = gnssConfigurationIface_V1_1->setBlacklist(sources);
-    return checkHidlReturn(result, "IGnssConfiguration setBlacklist() failed.");
+    return gnssConfigurationIface->setBlocklist(env, constellations, sv_ids);
 }
 
 static jboolean android_location_GnssConfiguration_set_es_extension_sec(
         JNIEnv*, jobject, jint emergencyExtensionSeconds) {
-    if (gnssConfigurationIface_V2_0 == nullptr && gnssConfigurationAidlIface == nullptr) {
-        ALOGI("Config parameter ES_EXTENSION_SEC is not supported in IGnssConfiguration.hal"
-                " versions earlier than 2.0.");
+    if (gnssConfigurationIface == nullptr) {
+        ALOGE("%s: IGnssConfiguration interface not available.", __func__);
         return JNI_FALSE;
     }
-
-    if (gnssConfigurationAidlIface != nullptr) {
-        auto status = gnssConfigurationAidlIface->setEsExtensionSec(emergencyExtensionSeconds);
-        return checkAidlStatus(status, "gnssConfigurationAidlIface setEsExtensionSec() failed.");
-    }
-
-    auto result = gnssConfigurationIface_V2_0->setEsExtensionSec(emergencyExtensionSeconds);
-    return checkHidlReturn(result, "IGnssConfiguration setEsExtensionSec() failed.");
+    return gnssConfigurationIface->setEsExtensionSec(emergencyExtensionSeconds);
 }
 
 static jint android_location_GnssBatchingProvider_get_batch_size(JNIEnv*, jclass) {
diff --git a/services/core/jni/gnss/GnssConfiguration.cpp b/services/core/jni/gnss/GnssConfiguration.cpp
new file mode 100644
index 0000000..8610c75
--- /dev/null
+++ b/services/core/jni/gnss/GnssConfiguration.cpp
@@ -0,0 +1,264 @@
+/*
+ * 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.
+ */
+
+// Define LOG_TAG before <log/log.h> to overwrite the default value.
+#define LOG_TAG "GnssConfigurationJni"
+
+#include "GnssConfiguration.h"
+
+using android::hardware::gnss::GnssConstellationType;
+using GnssConstellationType_V1_0 = android::hardware::gnss::V1_0::GnssConstellationType;
+using GnssConstellationType_V2_0 = android::hardware::gnss::V2_0::GnssConstellationType;
+
+using android::binder::Status;
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+
+using android::hardware::gnss::IGnssConfiguration;
+using IGnssConfiguration_V1_0 = android::hardware::gnss::V1_0::IGnssConfiguration;
+using IGnssConfiguration_V1_1 = android::hardware::gnss::V1_1::IGnssConfiguration;
+using IGnssConfiguration_V2_0 = android::hardware::gnss::V2_0::IGnssConfiguration;
+using IGnssConfiguration_V2_1 = android::hardware::gnss::V2_1::IGnssConfiguration;
+
+using android::hardware::gnss::BlocklistedSource;
+using BlocklistedSource_V1_1 = IGnssConfiguration_V1_1::BlacklistedSource;
+using BlocklistedSource_V2_1 = IGnssConfiguration_V2_1::BlacklistedSource;
+
+namespace {
+
+jclass class_gnssConfiguration_halInterfaceVersion;
+jmethodID method_halInterfaceVersionCtor;
+
+jboolean checkAidlStatus(const Status& status, const char* errorMessage) {
+    if (!status.isOk()) {
+        ALOGE("%s AIDL transport error: %s", errorMessage, status.toString8().c_str());
+        return JNI_FALSE;
+    }
+    return JNI_TRUE;
+}
+
+template <class T>
+inline void logHidlError(Return<T>& result, const char* errorMessage) {
+    ALOGE("%s HIDL transport error: %s", errorMessage, result.description().c_str());
+}
+
+template <class T>
+jboolean checkHidlReturn(Return<T>& result, const char* errorMessage) {
+    if (!result.isOk()) {
+        logHidlError(result, errorMessage);
+        return JNI_FALSE;
+    } else {
+        return JNI_TRUE;
+    }
+}
+
+jobject createHalInterfaceVersionJavaObject(JNIEnv* env, jint major, jint minor) {
+    return env->NewObject(class_gnssConfiguration_halInterfaceVersion,
+                          method_halInterfaceVersionCtor, major, minor);
+}
+
+} // anonymous namespace
+
+namespace android::gnss {
+
+void GnssConfiguration_class_init_once(JNIEnv* env) {
+    jclass gnssConfiguration_halInterfaceVersionClass = env->FindClass(
+            "com/android/server/location/gnss/GnssConfiguration$HalInterfaceVersion");
+    class_gnssConfiguration_halInterfaceVersion =
+            (jclass)env->NewGlobalRef(gnssConfiguration_halInterfaceVersionClass);
+    method_halInterfaceVersionCtor =
+            env->GetMethodID(class_gnssConfiguration_halInterfaceVersion, "<init>", "(II)V");
+}
+
+// Implementation of GnssConfiguration (AIDL HAL)
+
+GnssConfiguration::GnssConfiguration(const sp<IGnssConfiguration>& iGnssConfiguration)
+      : mIGnssConfiguration(iGnssConfiguration) {}
+
+jobject GnssConfiguration::getVersion(JNIEnv* env) {
+    return createHalInterfaceVersionJavaObject(env, 3, 0);
+}
+
+jboolean GnssConfiguration::setEmergencySuplPdn(jint enable) {
+    auto status = mIGnssConfiguration->setEmergencySuplPdn(enable);
+    return checkAidlStatus(status, "IGnssConfiguration setEmergencySuplPdn() failed.");
+}
+
+jboolean GnssConfiguration::setSuplVersion(jint version) {
+    auto status = mIGnssConfiguration->setSuplVersion(version);
+    return checkAidlStatus(status, "IGnssConfiguration setSuplVersion() failed.");
+}
+
+jboolean GnssConfiguration::setSuplEs(jint enable) {
+    ALOGI("Config parameter SUPL_ES is deprecated in IGnssConfiguration AIDL HAL.");
+    return JNI_FALSE;
+}
+
+jboolean GnssConfiguration::setSuplMode(jint mode) {
+    auto status = mIGnssConfiguration->setSuplMode(mode);
+    return checkAidlStatus(status, "IGnssConfiguration setSuplMode() failed.");
+}
+
+jboolean GnssConfiguration::setGpsLock(jint gpsLock) {
+    ALOGI("Config parameter GPS_LOCK is not supported in IGnssConfiguration AIDL HAL.");
+    return JNI_FALSE;
+}
+
+jboolean GnssConfiguration::setLppProfile(jint lppProfile) {
+    auto status = mIGnssConfiguration->setLppProfile(lppProfile);
+    return checkAidlStatus(status, "IGnssConfiguration setLppProfile() failed.");
+}
+
+jboolean GnssConfiguration::setGlonassPositioningProtocol(jint gnssPosProtocol) {
+    auto status = mIGnssConfiguration->setGlonassPositioningProtocol(gnssPosProtocol);
+    return checkAidlStatus(status, "IGnssConfiguration setGlonassPositioningProtocol() failed.");
+}
+
+jboolean GnssConfiguration::setEsExtensionSec(jint emergencyExtensionSeconds) {
+    auto status = mIGnssConfiguration->setEsExtensionSec(emergencyExtensionSeconds);
+    return checkAidlStatus(status, "IGnssConfiguration setEsExtensionSec() failed.");
+}
+
+jboolean GnssConfiguration::setBlocklist(JNIEnv* env, jintArray& constellations,
+                                         jintArray& sv_ids) {
+    auto sources =
+            getBlocklistedSources<BlocklistedSource, GnssConstellationType>(env, constellations,
+                                                                            sv_ids);
+    auto status = mIGnssConfiguration->setBlocklist(sources);
+    return checkAidlStatus(status, "IGnssConfiguration setBlocklist() failed.");
+}
+
+// Implementation of GnssConfiguration_V1_0
+
+GnssConfiguration_V1_0::GnssConfiguration_V1_0(
+        const sp<IGnssConfiguration_V1_0>& iGnssConfiguration)
+      : mIGnssConfiguration_V1_0(iGnssConfiguration) {}
+
+jobject GnssConfiguration_V1_0::getVersion(JNIEnv* env) {
+    return createHalInterfaceVersionJavaObject(env, 1, 0);
+}
+
+jboolean GnssConfiguration_V1_0::setEmergencySuplPdn(jint enable) {
+    auto result = mIGnssConfiguration_V1_0->setEmergencySuplPdn(enable);
+    return checkHidlReturn(result, "IGnssConfiguration setEmergencySuplPdn() failed.");
+}
+
+jboolean GnssConfiguration_V1_0::setSuplVersion(jint version) {
+    auto result = mIGnssConfiguration_V1_0->setSuplVersion(version);
+    return checkHidlReturn(result, "IGnssConfiguration setSuplVersion() failed.");
+}
+
+jboolean GnssConfiguration_V1_0::setSuplEs(jint enable) {
+    auto result = mIGnssConfiguration_V1_0->setSuplEs(enable);
+    return checkHidlReturn(result, "IGnssConfiguration setSuplEs() failed.");
+}
+
+jboolean GnssConfiguration_V1_0::setSuplMode(jint mode) {
+    auto result = mIGnssConfiguration_V1_0->setSuplMode(mode);
+    return checkHidlReturn(result, "IGnssConfiguration setSuplMode() failed.");
+}
+
+jboolean GnssConfiguration_V1_0::setGpsLock(jint gpsLock) {
+    auto result = mIGnssConfiguration_V1_0->setGpsLock(gpsLock);
+    return checkHidlReturn(result, "IGnssConfiguration setGpsLock() failed.");
+}
+
+jboolean GnssConfiguration_V1_0::setLppProfile(jint lppProfile) {
+    auto result = mIGnssConfiguration_V1_0->setLppProfile(lppProfile);
+    return checkHidlReturn(result, "IGnssConfiguration setLppProfile() failed.");
+}
+
+jboolean GnssConfiguration_V1_0::setGlonassPositioningProtocol(jint gnssPosProtocol) {
+    auto result = mIGnssConfiguration_V1_0->setGlonassPositioningProtocol(gnssPosProtocol);
+    return checkHidlReturn(result, "IGnssConfiguration setGlonassPositioningProtocol() failed.");
+}
+
+jboolean GnssConfiguration_V1_0::setEsExtensionSec(jint emergencyExtensionSeconds) {
+    ALOGI("Config parameter ES_EXTENSION_SEC is not supported in IGnssConfiguration.hal"
+          " versions earlier than 2.0.");
+    return JNI_FALSE;
+}
+
+jboolean GnssConfiguration_V1_0::setBlocklist(JNIEnv* env, jintArray& constellations,
+                                              jintArray& sv_ids) {
+    ALOGI("IGnssConfiguration interface does not support satellite blocklist.");
+    return JNI_FALSE;
+}
+
+// Implementation of GnssConfiguration_V1_1
+
+GnssConfiguration_V1_1::GnssConfiguration_V1_1(
+        const sp<IGnssConfiguration_V1_1>& iGnssConfiguration)
+      : GnssConfiguration_V1_0{iGnssConfiguration}, mIGnssConfiguration_V1_1(iGnssConfiguration) {}
+
+jobject GnssConfiguration_V1_1::getVersion(JNIEnv* env) {
+    return createHalInterfaceVersionJavaObject(env, 1, 1);
+}
+
+jboolean GnssConfiguration_V1_1::setBlocklist(JNIEnv* env, jintArray& constellations,
+                                              jintArray& sv_ids) {
+    auto sources = getBlocklistedSources<BlocklistedSource_V1_1,
+                                         GnssConstellationType_V1_0>(env, constellations, sv_ids);
+    auto result = mIGnssConfiguration_V1_1->setBlacklist(sources);
+    return checkHidlReturn(result, "IGnssConfiguration setBlocklist() failed.");
+}
+
+// Implementation of GnssConfiguration_V2_0
+
+GnssConfiguration_V2_0::GnssConfiguration_V2_0(
+        const sp<IGnssConfiguration_V2_0>& iGnssConfiguration)
+      : GnssConfiguration_V1_1{iGnssConfiguration}, mIGnssConfiguration_V2_0(iGnssConfiguration) {}
+
+jobject GnssConfiguration_V2_0::getVersion(JNIEnv* env) {
+    return createHalInterfaceVersionJavaObject(env, 2, 0);
+}
+
+jboolean GnssConfiguration_V2_0::setSuplEs(jint enable) {
+    ALOGI("Config parameter SUPL_ES is deprecated in IGnssConfiguration.hal version 2.0 and "
+          "higher.");
+    return JNI_FALSE;
+}
+
+jboolean GnssConfiguration_V2_0::setGpsLock(jint enable) {
+    ALOGI("Config parameter GPS_LOCK is deprecated in IGnssConfiguration.hal version 2.0 and "
+          "higher.");
+    return JNI_FALSE;
+}
+
+jboolean GnssConfiguration_V2_0::setEsExtensionSec(jint emergencyExtensionSeconds) {
+    auto result = mIGnssConfiguration_V2_0->setEsExtensionSec(emergencyExtensionSeconds);
+    return checkHidlReturn(result, "IGnssConfiguration setEsExtensionSec() failed.");
+}
+
+// Implementation of GnssConfiguration_V2_1
+
+GnssConfiguration_V2_1::GnssConfiguration_V2_1(
+        const sp<IGnssConfiguration_V2_1>& iGnssConfiguration)
+      : GnssConfiguration_V2_0{iGnssConfiguration}, mIGnssConfiguration_V2_1(iGnssConfiguration) {}
+
+jobject GnssConfiguration_V2_1::getVersion(JNIEnv* env) {
+    return createHalInterfaceVersionJavaObject(env, 2, 1);
+}
+
+jboolean GnssConfiguration_V2_1::setBlocklist(JNIEnv* env, jintArray& constellations,
+                                              jintArray& sv_ids) {
+    auto sources = getBlocklistedSources<BlocklistedSource_V2_1,
+                                         GnssConstellationType_V2_0>(env, constellations, sv_ids);
+    auto result = mIGnssConfiguration_V2_1->setBlacklist_2_1(sources);
+    return checkHidlReturn(result, "IGnssConfiguration setBlocklist() failed.");
+}
+
+} // namespace android::gnss
diff --git a/services/core/jni/gnss/GnssConfiguration.h b/services/core/jni/gnss/GnssConfiguration.h
new file mode 100644
index 0000000..ea0f178
--- /dev/null
+++ b/services/core/jni/gnss/GnssConfiguration.h
@@ -0,0 +1,168 @@
+/*
+ * 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.
+ */
+
+#ifndef _ANDROID_SERVER_GNSS_GNSSCONFIGURATION_H
+#define _ANDROID_SERVER_GNSS_GNSSCONFIGURATION_H
+
+#pragma once
+
+#ifndef LOG_TAG
+#error LOG_TAG must be defined before including this file.
+#endif
+
+#include <android/hardware/gnss/1.0/IGnssConfiguration.h>
+#include <android/hardware/gnss/1.1/IGnssConfiguration.h>
+#include <android/hardware/gnss/2.0/IGnssConfiguration.h>
+#include <android/hardware/gnss/2.1/IGnssConfiguration.h>
+#include <android/hardware/gnss/BnGnssConfiguration.h>
+#include <log/log.h>
+
+#include "jni.h"
+
+namespace android::gnss {
+
+void GnssConfiguration_class_init_once(JNIEnv* env);
+
+class GnssConfigurationInterface {
+public:
+    virtual ~GnssConfigurationInterface() {}
+    virtual jobject getVersion(JNIEnv* env) = 0;
+    virtual jboolean setEmergencySuplPdn(jint enable) = 0;
+    virtual jboolean setSuplVersion(jint version) = 0;
+    virtual jboolean setSuplEs(jint enable) = 0;
+    virtual jboolean setSuplMode(jint mode) = 0;
+    virtual jboolean setGpsLock(jint gpsLock) = 0;
+    virtual jboolean setLppProfile(jint lppProfile) = 0;
+    virtual jboolean setGlonassPositioningProtocol(jint gnssPosProtocol) = 0;
+    virtual jboolean setEsExtensionSec(jint emergencyExtensionSeconds) = 0;
+    virtual jboolean setBlocklist(JNIEnv* env, jintArray& constellations, jintArray& sv_ids) = 0;
+
+protected:
+    template <class T_BlocklistSource, class T_ConstellationType>
+    hardware::hidl_vec<T_BlocklistSource> getBlocklistedSources(JNIEnv* env,
+                                                                jintArray& constellations,
+                                                                jintArray& sv_ids) {
+        jint* constellation_array = env->GetIntArrayElements(constellations, 0);
+        if (nullptr == constellation_array) {
+            ALOGI("GetIntArrayElements returns nullptr.");
+            return JNI_FALSE;
+        }
+
+        jsize length = env->GetArrayLength(constellations);
+
+        jint* sv_id_array = env->GetIntArrayElements(sv_ids, 0);
+        if (nullptr == sv_id_array) {
+            ALOGI("GetIntArrayElements returns nullptr.");
+            return JNI_FALSE;
+        }
+
+        if (length != env->GetArrayLength(sv_ids)) {
+            ALOGI("Lengths of constellations and sv_ids are inconsistent.");
+            return JNI_FALSE;
+        }
+
+        hardware::hidl_vec<T_BlocklistSource> sources;
+        sources.resize(length);
+
+        for (int i = 0; i < length; i++) {
+            sources[i].constellation = static_cast<T_ConstellationType>(constellation_array[i]);
+            sources[i].svid = sv_id_array[i];
+        }
+
+        env->ReleaseIntArrayElements(constellations, constellation_array, 0);
+        env->ReleaseIntArrayElements(sv_ids, sv_id_array, 0);
+
+        return sources;
+    }
+};
+
+class GnssConfiguration : public GnssConfigurationInterface {
+public:
+    GnssConfiguration(const sp<android::hardware::gnss::IGnssConfiguration>& iGnssConfiguration);
+    jobject getVersion(JNIEnv* env) override;
+    jboolean setEmergencySuplPdn(jint enable) override;
+    jboolean setSuplVersion(jint version) override;
+    jboolean setSuplEs(jint enable) override;
+    jboolean setSuplMode(jint mode) override;
+    jboolean setGpsLock(jint gpsLock) override;
+    jboolean setLppProfile(jint lppProfile) override;
+    jboolean setGlonassPositioningProtocol(jint gnssPosProtocol) override;
+    jboolean setEsExtensionSec(jint emergencyExtensionSeconds) override;
+    jboolean setBlocklist(JNIEnv* env, jintArray& constellations, jintArray& sv_ids) override;
+
+private:
+    const sp<android::hardware::gnss::IGnssConfiguration> mIGnssConfiguration;
+};
+
+class GnssConfiguration_V1_0 : public GnssConfigurationInterface {
+public:
+    GnssConfiguration_V1_0(
+            const sp<android::hardware::gnss::V1_0::IGnssConfiguration>& iGnssConfiguration);
+    jobject getVersion(JNIEnv* env) override;
+    jboolean setEmergencySuplPdn(jint enable);
+    jboolean setSuplVersion(jint version) override;
+    jboolean setSuplEs(jint enable) override;
+    jboolean setSuplMode(jint mode) override;
+    jboolean setGpsLock(jint gpsLock) override;
+    jboolean setLppProfile(jint lppProfile);
+    jboolean setGlonassPositioningProtocol(jint gnssPosProtocol) override;
+    jboolean setEsExtensionSec(jint emergencyExtensionSeconds) override;
+    jboolean setBlocklist(JNIEnv* env, jintArray& constellations, jintArray& sv_ids) override;
+
+private:
+    const sp<android::hardware::gnss::V1_0::IGnssConfiguration> mIGnssConfiguration_V1_0;
+};
+
+class GnssConfiguration_V1_1 : public GnssConfiguration_V1_0 {
+public:
+    GnssConfiguration_V1_1(
+            const sp<android::hardware::gnss::V1_1::IGnssConfiguration>& iGnssConfiguration);
+
+    jobject getVersion(JNIEnv* env) override;
+
+    jboolean setBlocklist(JNIEnv* env, jintArray& constellations, jintArray& sv_ids) override;
+
+private:
+    const sp<android::hardware::gnss::V1_1::IGnssConfiguration> mIGnssConfiguration_V1_1;
+};
+
+class GnssConfiguration_V2_0 : public GnssConfiguration_V1_1 {
+public:
+    GnssConfiguration_V2_0(
+            const sp<android::hardware::gnss::V2_0::IGnssConfiguration>& iGnssConfiguration);
+    jobject getVersion(JNIEnv* env) override;
+    jboolean setSuplEs(jint enable) override;
+    jboolean setGpsLock(jint enable) override;
+    jboolean setEsExtensionSec(jint emergencyExtensionSeconds) override;
+
+private:
+    const sp<android::hardware::gnss::V2_0::IGnssConfiguration> mIGnssConfiguration_V2_0;
+};
+
+class GnssConfiguration_V2_1 : public GnssConfiguration_V2_0 {
+public:
+    GnssConfiguration_V2_1(
+            const sp<android::hardware::gnss::V2_1::IGnssConfiguration>& iGnssConfiguration);
+    jobject getVersion(JNIEnv* env) override;
+    jboolean setBlocklist(JNIEnv* env, jintArray& constellations, jintArray& sv_ids) override;
+
+private:
+    const sp<android::hardware::gnss::V2_1::IGnssConfiguration> mIGnssConfiguration_V2_1;
+};
+
+} // namespace android::gnss
+
+#endif // _ANDROID_SERVER_GNSS_GNSSCONFIGURATION_H
diff --git a/services/core/xsd/platform-compat-config.xsd b/services/core/xsd/platform-compat-config.xsd
index 5a4c682..9924708 100644
--- a/services/core/xsd/platform-compat-config.xsd
+++ b/services/core/xsd/platform-compat-config.xsd
@@ -29,6 +29,7 @@
                 <xs:attribute type="xs:boolean" name="disabled"/>
                 <xs:attribute type="xs:boolean" name="loggingOnly"/>
                 <xs:attribute type="xs:int" name="enableAfterTargetSdk"/>
+                <xs:attribute type="xs:int" name="enableSinceTargetSdk"/>
                 <xs:attribute type="xs:string" name="description"/>
             </xs:extension>
         </xs:simpleContent>
diff --git a/services/core/xsd/platform-compat-schema/current.txt b/services/core/xsd/platform-compat-schema/current.txt
index 7def58d..e3640ed 100644
--- a/services/core/xsd/platform-compat-schema/current.txt
+++ b/services/core/xsd/platform-compat-schema/current.txt
@@ -6,6 +6,7 @@
     method public String getDescription();
     method public boolean getDisabled();
     method public int getEnableAfterTargetSdk();
+    method public int getEnableSinceTargetSdk();
     method public long getId();
     method public boolean getLoggingOnly();
     method public String getName();
@@ -13,6 +14,7 @@
     method public void setDescription(String);
     method public void setDisabled(boolean);
     method public void setEnableAfterTargetSdk(int);
+    method public void setEnableSinceTargetSdk(int);
     method public void setId(long);
     method public void setLoggingOnly(boolean);
     method public void setName(String);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 177b7b4..5dbb348 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -4395,12 +4395,13 @@
         return mInjector.binderWithCleanCallingIdentity(() -> mUserManager.getUserInfo(userId));
     }
 
-    private boolean setPasswordPrivileged(@NonNull String password, int flags, int callingUid) {
+    private boolean setPasswordPrivileged(@NonNull String password, int flags,
+            CallerIdentity caller) {
         // Only allow setting password on an unsecured user
-        if (isLockScreenSecureUnchecked(UserHandle.getUserId(callingUid))) {
+        if (isLockScreenSecureUnchecked(caller.getUserId())) {
             throw new SecurityException("Cannot change current password");
         }
-        return resetPasswordInternal(password, 0, null, flags, callingUid);
+        return resetPasswordInternal(password, 0, null, flags, caller);
     }
 
     @Override
@@ -4410,19 +4411,22 @@
             return false;
         }
         if (password == null) password = "";
-        final int callingUid = mInjector.binderGetCallingUid();
-        final int userHandle = mInjector.userHandleGetCallingUserId();
+        final CallerIdentity caller = getCallerIdentity();
+        final int userHandle = caller.getUserId();
 
         // As of R, only privlleged caller holding RESET_PASSWORD can call resetPassword() to
         // set password to an unsecured user.
         if (hasCallingPermission(permission.RESET_PASSWORD)) {
-            return setPasswordPrivileged(password, flags, callingUid);
+            return setPasswordPrivileged(password, flags, caller);
         }
 
+        // If caller has PO (or DO) throw or fail silently depending on its target SDK level.
+        Preconditions.checkCallAuthorization(
+                isDeviceOwner(caller) || isProfileOwner(caller),
+                String.format("UID %d is not a device or profile owner", caller.getUid()));
+
         synchronized (getLockObject()) {
-            // If caller has PO (or DO) throw or fail silently depending on its target SDK level.
-            ActiveAdmin admin = getActiveAdminWithPolicyForUidLocked(
-                    null, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, callingUid);
+            ActiveAdmin admin = getDeviceOrProfileOwnerAdminLocked(caller.getUserId());
             if (admin != null) {
                 if (getTargetSdk(admin.info.getPackageName(), userHandle) < Build.VERSION_CODES.O) {
                     Slog.e(LOG_TAG, "DPC can no longer call resetPassword()");
@@ -4444,7 +4448,8 @@
     }
 
     private boolean resetPasswordInternal(String password, long tokenHandle, byte[] token,
-            int flags, int callingUid) {
+            int flags, CallerIdentity caller) {
+        final int callingUid = caller.getUid();
         final int userHandle = UserHandle.getUserId(callingUid);
         synchronized (getLockObject()) {
             final PasswordMetrics minMetrics = getPasswordMinimumMetrics(userHandle);
@@ -4473,7 +4478,7 @@
             return false;
         }
 
-        boolean callerIsDeviceOwnerAdmin = isCallerDeviceOwner(callingUid);
+        boolean callerIsDeviceOwnerAdmin = isDeviceOwner(caller);
         boolean doNotAskCredentialsOnBoot =
                 (flags & DevicePolicyManager.RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT) != 0;
         if (callerIsDeviceOwnerAdmin && doNotAskCredentialsOnBoot) {
@@ -5388,14 +5393,14 @@
         // Retrieve the user ID of the calling process.
         final int userId = caller.getUserId();
         final boolean hasDoDelegation = !Collections.disjoint(scopes, DEVICE_OWNER_DELEGATIONS);
+        // Ensure calling process is device/profile owner.
+        if (hasDoDelegation) {
+            Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+        } else {
+            Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+        }
+
         synchronized (getLockObject()) {
-            // Ensure calling process is device/profile owner.
-            if (hasDoDelegation) {
-                Preconditions.checkCallAuthorization(isDeviceOwner(caller));
-            } else {
-                // TODO move whole condition out of synchronized block
-                getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
-            }
             // Ensure the delegate is installed (skip this for DELEGATION_CERT_INSTALL in pre-N).
             if (shouldCheckIfDelegatePackageIsInstalled(delegatePackage,
                         getTargetSdk(who.getPackageName(), userId), scopes)) {
@@ -5516,11 +5521,10 @@
         }
 
         // Retrieve the user ID of the calling process.
-        final int userId = mInjector.userHandleGetCallingUserId();
+        final CallerIdentity caller = getCallerIdentity(who);
+        Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
         synchronized (getLockObject()) {
-            // Ensure calling process is device/profile owner.
-            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
-            return getDelegatePackagesInternalLocked(scope, userId);
+            return getDelegatePackagesInternalLocked(scope, caller.getUserId());
         }
     }
 
@@ -5649,11 +5653,12 @@
             String delegatePackage, String scope) {
         Objects.requireNonNull(who, "ComponentName is null");
 
-        final int userId = mInjector.userHandleGetCallingUserId();
+        final CallerIdentity caller = getCallerIdentity(who);
+        // Ensure calling process is device/profile owner.
+        Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+
         synchronized (getLockObject()) {
-            // Ensure calling process is device/profile owner.
-            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
-            final DevicePolicyData policy = getUserData(userId);
+            final DevicePolicyData policy = getUserData(caller.getUserId());
 
             if (delegatePackage != null) {
                 // Set package as a delegate for scope if it is not already one.
@@ -5866,7 +5871,7 @@
                             + "organization-owned device.");
         }
         if ((flags & WIPE_RESET_PROTECTION_DATA) != 0) {
-            Preconditions.checkCallAuthorization(isCallerDeviceOwner(caller.getUid())
+            Preconditions.checkCallAuthorization(isDeviceOwner(caller)
                             || calledByProfileOwnerOnOrgOwnedDevice,
                     "Only device owners or profile owners of organization-owned device can set "
                             + "WIPE_RESET_PROTECTION_DATA");
@@ -6625,8 +6630,8 @@
         }
 
         synchronized (getLockObject()) {
-            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
-                    DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, parent);
+            ActiveAdmin ap = getParentOfAdminIfRequired(getProfileOwnerOrDeviceOwnerLocked(caller),
+                    parent);
             if (ap.disableScreenCapture != disabled) {
                 ap.disableScreenCapture = disabled;
                 saveSettingsLocked(caller.getUserId());
@@ -7309,9 +7314,15 @@
 
     private boolean isDeviceOwner(CallerIdentity caller) {
         synchronized (getLockObject()) {
-            return mOwners.hasDeviceOwner()
-                    && mOwners.getDeviceOwnerUserId() == caller.getUserId()
-                    && mOwners.getDeviceOwnerComponent().equals(caller.getComponentName());
+            if (!mOwners.hasDeviceOwner() || mOwners.getDeviceOwnerUserId() != caller.getUserId()) {
+                return false;
+            }
+
+            if (caller.hasAdminComponent()) {
+                return mOwners.getDeviceOwnerComponent().equals(caller.getComponentName());
+            } else {
+                return isUidDeviceOwnerLocked(caller.getUid());
+            }
         }
     }
 
@@ -7341,8 +7352,43 @@
      * @return true if {@code identity} is a profile owner, false otherwise.
      */
     public boolean isProfileOwner(CallerIdentity caller) {
-        final ComponentName profileOwner = getProfileOwner(caller.getUserId());
-        return profileOwner != null && profileOwner.equals(caller.getComponentName());
+        synchronized (getLockObject()) {
+            final ComponentName profileOwner = getProfileOwner(caller.getUserId());
+            // No profile owner.
+            if (profileOwner == null) {
+                return false;
+            }
+            // The admin ComponentName was specified, check it directly.
+            if (caller.hasAdminComponent()) {
+                return profileOwner.equals(caller.getComponentName());
+            } else {
+                return isUidProfileOwnerLocked(caller.getUid());
+            }
+        }
+    }
+
+    /**
+     * Checks if the app uid provided is the profile owner. This method should only be called
+     * if no componentName is available.
+     *
+     * @param appUid UID of the caller.
+     * @return true if the caller is the profile owner
+     */
+    private boolean isUidProfileOwnerLocked(int appUid) {
+        ensureLocked();
+
+        final int userId = UserHandle.getUserId(appUid);
+        final ComponentName profileOwnerComponent = mOwners.getProfileOwnerComponent(userId);
+        if (profileOwnerComponent == null) {
+            return false;
+        }
+        for (ActiveAdmin admin : getUserData(userId).mAdminList) {
+            final ComponentName currentAdminComponent = admin.info.getComponent();
+            if (admin.getUid() == appUid && profileOwnerComponent.equals(currentAdminComponent)) {
+                return true;
+            }
+        }
+        return false;
     }
 
     private boolean hasProfileOwner(int userId) {
@@ -7652,8 +7698,7 @@
         enforceUserUnlocked(userId);
         synchronized (getLockObject()) {
             // Check if this is the profile owner who is calling
-            final ActiveAdmin admin =
-                    getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller);
 
             mInjector.binderWithCleanCallingIdentity(() -> {
                 clearProfileOwnerLocked(admin, userId);
@@ -8368,8 +8413,10 @@
     }
 
     private void enforceCanCallLockTaskLocked(ComponentName who) {
-        getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
-        final int userId =  mInjector.userHandleGetCallingUserId();
+        final CallerIdentity caller = getAdminCallerIdentity(who);
+        Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+
+        final int userId =  caller.getUserId();
         if (!canUserUseLockTaskLocked(userId)) {
             throw new SecurityException("User " + userId + " is not allowed to use lock task");
         }
@@ -8533,10 +8580,11 @@
     public void addPersistentPreferredActivity(ComponentName who, IntentFilter filter,
             ComponentName activity) {
         Objects.requireNonNull(who, "ComponentName is null");
-        final int userHandle = UserHandle.getCallingUserId();
-        synchronized (getLockObject()) {
-            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+        final CallerIdentity caller = getCallerIdentity(who);
+        Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
 
+        final int userHandle = caller.getUserId();
+        synchronized (getLockObject()) {
             long id = mInjector.binderClearCallingIdentity();
             try {
                 mIPackageManager.addPersistentPreferredActivity(filter, activity, userHandle);
@@ -8559,10 +8607,11 @@
     @Override
     public void clearPackagePersistentPreferredActivities(ComponentName who, String packageName) {
         Objects.requireNonNull(who, "ComponentName is null");
-        final int userHandle = UserHandle.getCallingUserId();
-        synchronized (getLockObject()) {
-            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+        final CallerIdentity caller = getCallerIdentity(who);
+        Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
 
+        final int userHandle = caller.getUserId();
+        synchronized (getLockObject()) {
             long id = mInjector.binderClearCallingIdentity();
             try {
                 mIPackageManager.clearPackagePersistentPreferredActivities(packageName, userHandle);
@@ -8666,7 +8715,7 @@
 
         synchronized (getLockObject()) {
             final String componentName = agent.flattenToString();
-            if (caller.hasAdminComponent()) {
+            if (admin != null) {
                 final ActiveAdmin ap = getActiveAdminUncheckedLocked(admin, userHandle, parent);
                 if (ap == null) return null;
                 TrustAgentInfo trustAgentInfo = ap.trustAgentInfos.get(componentName);
@@ -8714,10 +8763,11 @@
     @Override
     public void setRestrictionsProvider(ComponentName who, ComponentName permissionProvider) {
         Objects.requireNonNull(who, "ComponentName is null");
-        synchronized (getLockObject()) {
-            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+        final CallerIdentity caller = getCallerIdentity(who);
+        Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
 
-            int userHandle = UserHandle.getCallingUserId();
+        synchronized (getLockObject()) {
+            int userHandle = caller.getUserId();
             DevicePolicyData userData = getUserData(userHandle);
             userData.mRestrictionsProvider = permissionProvider;
             saveSettingsLocked(userHandle);
@@ -8736,10 +8786,10 @@
     @Override
     public void addCrossProfileIntentFilter(ComponentName who, IntentFilter filter, int flags) {
         Objects.requireNonNull(who, "ComponentName is null");
-        int callingUserId = UserHandle.getCallingUserId();
+        final CallerIdentity caller = getCallerIdentity(who);
+        Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+        int callingUserId = caller.getUserId();
         synchronized (getLockObject()) {
-            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
-
             long id = mInjector.binderClearCallingIdentity();
             try {
                 UserInfo parent = mUserManager.getProfileParent(callingUserId);
@@ -8785,9 +8835,11 @@
     @Override
     public void clearCrossProfileIntentFilters(ComponentName who) {
         Objects.requireNonNull(who, "ComponentName is null");
-        int callingUserId = UserHandle.getCallingUserId();
+        final CallerIdentity caller = getCallerIdentity(who);
+        Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+
+        int callingUserId = caller.getUserId();
         synchronized (getLockObject()) {
-            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
             long id = mInjector.binderClearCallingIdentity();
             try {
                 UserInfo parent = mUserManager.getProfileParent(callingUserId);
@@ -9462,10 +9514,11 @@
     @Override
     public int logoutUser(ComponentName who) {
         Objects.requireNonNull(who, "ComponentName is null");
+        final CallerIdentity caller = getCallerIdentity(who);
+        Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
 
-        final int callingUserId = mInjector.userHandleGetCallingUserId();
+        final int callingUserId = caller.getUserId();
         synchronized (getLockObject()) {
-            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
             if (!isUserAffiliatedWithDeviceLocked(callingUserId)) {
                 throw new SecurityException("Admin " + who +
                         " is neither the device owner or affiliated user's profile owner.");
@@ -9627,9 +9680,8 @@
 
         int userHandle = caller.getUserId();
         synchronized (getLockObject()) {
-            final ActiveAdmin activeAdmin =
-                    getActiveAdminForCallerLocked(who,
-                            DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, parent);
+            final ActiveAdmin activeAdmin = getParentOfAdminIfRequired(
+                    getProfileOwnerOrDeviceOwnerLocked(caller), parent);
 
             if (isDeviceOwner(caller)) {
                 if (!UserRestrictionsUtils.canDeviceOwnerChange(key)) {
@@ -10546,19 +10598,17 @@
     public void setSystemSetting(ComponentName who, String setting, String value) {
         Objects.requireNonNull(who, "ComponentName is null");
         Preconditions.checkStringNotEmpty(setting, "String setting is null or empty");
+        final CallerIdentity caller = getCallerIdentity(who);
+        Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
 
         synchronized (getLockObject()) {
-            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
-
             if (!SYSTEM_SETTINGS_ALLOWLIST.contains(setting)) {
                 throw new SecurityException(String.format(
                         "Permission denial: device owners cannot update %1$s", setting));
             }
 
-            final int callingUserId = mInjector.userHandleGetCallingUserId();
-
             mInjector.binderWithCleanCallingIdentity(() ->
-                mInjector.settingsSystemPutStringForUser(setting, value, callingUserId));
+                    mInjector.settingsSystemPutStringForUser(setting, value, caller.getUserId()));
         }
     }
 
@@ -10704,11 +10754,11 @@
     @Override
     public void setSecureSetting(ComponentName who, String setting, String value) {
         Objects.requireNonNull(who, "ComponentName is null");
-        int callingUserId = mInjector.userHandleGetCallingUserId();
+        final CallerIdentity caller = getCallerIdentity(who);
+        Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
 
+        int callingUserId = caller.getUserId();
         synchronized (getLockObject()) {
-            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
-
             if (isDeviceOwner(who, callingUserId)) {
                 if (!SECURE_SETTINGS_DEVICEOWNER_ALLOWLIST.contains(setting)
                         && !isCurrentUserDemo()) {
@@ -10800,8 +10850,10 @@
     @Override
     public void setMasterVolumeMuted(ComponentName who, boolean on) {
         Objects.requireNonNull(who, "ComponentName is null");
+        final CallerIdentity caller = getCallerIdentity(who);
+        Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+
         synchronized (getLockObject()) {
-            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
             setUserRestriction(who, UserManager.DISALLOW_UNMUTE_DEVICE, on, /* parent */ false);
             DevicePolicyEventLogger
                     .createEvent(DevicePolicyEnums.SET_MASTER_VOLUME_MUTED)
@@ -10814,9 +10866,10 @@
     @Override
     public boolean isMasterVolumeMuted(ComponentName who) {
         Objects.requireNonNull(who, "ComponentName is null");
-        synchronized (getLockObject()) {
-            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+        final CallerIdentity caller = getCallerIdentity(who);
+        Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
 
+        synchronized (getLockObject()) {
             AudioManager audioManager =
                     (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
             return audioManager.isMasterMute();
@@ -10825,13 +10878,13 @@
 
     @Override
     public void setUserIcon(ComponentName who, Bitmap icon) {
-        synchronized (getLockObject()) {
-            Objects.requireNonNull(who, "ComponentName is null");
-            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+        Objects.requireNonNull(who, "ComponentName is null");
+        final CallerIdentity caller = getCallerIdentity(who);
+        Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
 
-            int userId = UserHandle.getCallingUserId();
+        synchronized (getLockObject()) {
             mInjector.binderWithCleanCallingIdentity(
-                    () -> mUserManagerInternal.setUserIcon(userId, icon));
+                    () -> mUserManagerInternal.setUserIcon(caller.getUserId(), icon));
         }
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_USER_ICON)
@@ -10842,13 +10895,15 @@
     @Override
     public boolean setKeyguardDisabled(ComponentName who, boolean disabled) {
         Objects.requireNonNull(who, "ComponentName is null");
-        final int userId = mInjector.userHandleGetCallingUserId();
+        final CallerIdentity caller = getCallerIdentity(who);
+        Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+
+        final int userId = caller.getUserId();
         synchronized (getLockObject()) {
-            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
-            if (!isUserAffiliatedWithDeviceLocked(userId)) {
-                throw new SecurityException("Admin " + who +
-                        " is neither the device owner or affiliated user's profile owner.");
-            }
+            Preconditions.checkCallAuthorization(isUserAffiliatedWithDeviceLocked(userId),
+                    String.format(
+                            "Admin %s is neither the device owner or affiliated user's profile "
+                                    + "owner.", who));
         }
         if (isManagedProfile(userId)) {
             throw new SecurityException("Managed profile cannot disable keyguard");
@@ -10881,13 +10936,14 @@
 
     @Override
     public boolean setStatusBarDisabled(ComponentName who, boolean disabled) {
-        int userId = UserHandle.getCallingUserId();
+        final CallerIdentity caller = getAdminCallerIdentity(who);
+        Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+
+        int userId = caller.getUserId();
         synchronized (getLockObject()) {
-            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
-            if (!isUserAffiliatedWithDeviceLocked(userId)) {
-                throw new SecurityException("Admin " + who +
-                        " is neither the device owner or affiliated user's profile owner.");
-            }
+            Preconditions.checkCallAuthorization(isUserAffiliatedWithDeviceLocked(userId),
+                    "Admin " + who
+                            + " is neither the device owner or affiliated user's profile owner.");
             if (isManagedProfile(userId)) {
                 throw new SecurityException("Managed profile cannot disable status bar");
             }
@@ -11628,32 +11684,24 @@
     }
 
     /**
-     * Checks if the caller of the method is the device owner app.
-     *
-     * @param callerUid UID of the caller.
-     * @return true if the caller is the device owner app
+     * Checks if any of the packages associated with the UID of the app provided is that
+     * of the device owner.
+     * @param appUid UID of the app to check.
+     * @return {@code true} if any of the packages are the device owner, {@code false} otherwise.
      */
-    @VisibleForTesting
-    boolean isCallerDeviceOwner(int callerUid) {
-        synchronized (getLockObject()) {
-            if (!mOwners.hasDeviceOwner()) {
-                return false;
-            }
-            if (UserHandle.getUserId(callerUid) != mOwners.getDeviceOwnerUserId()) {
-                return false;
-            }
-            final String deviceOwnerPackageName = mOwners.getDeviceOwnerComponent()
-                    .getPackageName();
-                try {
-                    String[] pkgs = mInjector.getIPackageManager().getPackagesForUid(callerUid);
-                    for (String pkg : pkgs) {
-                        if (deviceOwnerPackageName.equals(pkg)) {
-                            return true;
-                        }
-                    }
-                } catch (RemoteException e) {
-                    return false;
+    private boolean isUidDeviceOwnerLocked(int appUid) {
+        ensureLocked();
+        final String deviceOwnerPackageName = mOwners.getDeviceOwnerComponent()
+                .getPackageName();
+        try {
+            String[] pkgs = mInjector.getIPackageManager().getPackagesForUid(appUid);
+            for (String pkg : pkgs) {
+                if (deviceOwnerPackageName.equals(pkg)) {
+                    return true;
                 }
+            }
+        } catch (RemoteException e) {
+            return false;
         }
         return false;
     }
@@ -12633,9 +12681,11 @@
         }
 
         final Set<String> affiliationIds = new ArraySet<>(ids);
-        final int callingUserId = mInjector.userHandleGetCallingUserId();
+        final CallerIdentity caller = getAdminCallerIdentity(admin);
+        Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+        final int callingUserId = caller.getUserId();
+
         synchronized (getLockObject()) {
-            getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
             getUserData(callingUserId).mAffiliationIds = affiliationIds;
             saveSettingsLocked(callingUserId);
             if (callingUserId != UserHandle.USER_SYSTEM && isDeviceOwner(admin, callingUserId)) {
@@ -12661,10 +12711,11 @@
         }
 
         Objects.requireNonNull(admin);
+        final CallerIdentity caller = getCallerIdentity(admin);
+        Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+
         synchronized (getLockObject()) {
-            getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
-            return new ArrayList<String>(
-                    getUserData(mInjector.userHandleGetCallingUserId()).mAffiliationIds);
+            return new ArrayList<String>(getUserData(caller.getUserId()).mAffiliationIds);
         }
     }
 
@@ -13174,11 +13225,11 @@
             return Collections.emptyList();
         }
         Objects.requireNonNull(admin);
+        final CallerIdentity caller = getCallerIdentity(admin);
+        Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
 
         synchronized (getLockObject()) {
-            getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
-
-            final int callingUserId = mInjector.userHandleGetCallingUserId();
+            final int callingUserId = caller.getUserId();
             return mInjector.binderWithCleanCallingIdentity(() -> {
                 ArrayList<UserHandle> targetUsers = new ArrayList<>();
                 if (!isDeviceOwner(admin, callingUserId)) {
@@ -13581,9 +13632,11 @@
         if (token == null || token.length < 32) {
             throw new IllegalArgumentException("token must be at least 32-byte long");
         }
+        final CallerIdentity caller = getAdminCallerIdentity(admin);
+        Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+
         synchronized (getLockObject()) {
-            final int userHandle = mInjector.userHandleGetCallingUserId();
-            getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            final int userHandle = caller.getUserId();
 
             DevicePolicyData policy = getUserData(userHandle);
             return mInjector.binderWithCleanCallingIdentity(() -> {
@@ -13603,9 +13656,11 @@
         if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
             return false;
         }
+        final CallerIdentity caller = getAdminCallerIdentity(admin);
+        Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+
         synchronized (getLockObject()) {
-            final int userHandle = mInjector.userHandleGetCallingUserId();
-            getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            final int userHandle = caller.getUserId();
 
             DevicePolicyData policy = getUserData(userHandle);
             if (policy.mPasswordTokenHandle != 0) {
@@ -13626,11 +13681,11 @@
         if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
             return false;
         }
-        synchronized (getLockObject()) {
-            final int userHandle = mInjector.userHandleGetCallingUserId();
-            getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+        final CallerIdentity caller = getAdminCallerIdentity(admin);
+        Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
 
-            return isResetPasswordTokenActiveForUserLocked(userHandle);
+        synchronized (getLockObject()) {
+            return isResetPasswordTokenActiveForUserLocked(caller.getUserId());
         }
     }
 
@@ -13650,15 +13705,16 @@
             return false;
         }
         Objects.requireNonNull(token);
-        synchronized (getLockObject()) {
-            final int userHandle = mInjector.userHandleGetCallingUserId();
-            getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
 
-            DevicePolicyData policy = getUserData(userHandle);
+        final CallerIdentity caller = getAdminCallerIdentity(admin);
+        Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+
+        synchronized (getLockObject()) {
+            DevicePolicyData policy = getUserData(caller.getUserId());
             if (policy.mPasswordTokenHandle != 0) {
                 final String password = passwordOrNull != null ? passwordOrNull : "";
                 return resetPasswordInternal(password, policy.mPasswordTokenHandle, token,
-                        flags, mInjector.binderGetCallingUid());
+                        flags, caller);
             } else {
                 Slog.w(LOG_TAG, "No saved token handle");
             }
@@ -13973,9 +14029,11 @@
     @Override
     @Nullable
     public PersistableBundle getTransferOwnershipBundle() {
+        final CallerIdentity caller = getCallerIdentity();
+        Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+
         synchronized (getLockObject()) {
-            final int callingUserId = mInjector.userHandleGetCallingUserId();
-            getActiveAdminForCallerLocked(null, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            final int callingUserId = caller.getUserId();
             final File bundleFile = new File(
                     mInjector.environmentGetUserSystemDirectory(callingUserId),
                     TRANSFER_OWNERSHIP_PARAMETERS_XML);
diff --git a/services/incremental/BinderIncrementalService.cpp b/services/incremental/BinderIncrementalService.cpp
index 2f8825b..a31aac9 100644
--- a/services/incremental/BinderIncrementalService.cpp
+++ b/services/incremental/BinderIncrementalService.cpp
@@ -323,6 +323,22 @@
     return ok();
 }
 
+binder::Status BinderIncrementalService::registerStorageHealthListener(
+        int32_t storageId,
+        const ::android::os::incremental::StorageHealthCheckParams& healthCheckParams,
+        const ::android::sp<IStorageHealthListener>& healthListener, bool* _aidl_return) {
+    *_aidl_return = mImpl.registerStorageHealthListener(storageId,
+                                                        const_cast<StorageHealthCheckParams&&>(
+                                                                healthCheckParams),
+                                                        healthListener);
+    return ok();
+}
+
+binder::Status BinderIncrementalService::unregisterStorageHealthListener(int32_t storageId) {
+    mImpl.unregisterStorageHealthListener(storageId);
+    return ok();
+}
+
 } // namespace android::os::incremental
 
 jlong Incremental_IncrementalService_Start(JNIEnv* env) {
diff --git a/services/incremental/BinderIncrementalService.h b/services/incremental/BinderIncrementalService.h
index 0a89166..8afa0f7 100644
--- a/services/incremental/BinderIncrementalService.h
+++ b/services/incremental/BinderIncrementalService.h
@@ -89,6 +89,11 @@
                     progressListener,
             bool* _aidl_return) final;
     binder::Status unregisterLoadingProgressListener(int32_t storageId, bool* _aidl_return) final;
+    binder::Status registerStorageHealthListener(
+            int32_t storageId,
+            const ::android::os::incremental::StorageHealthCheckParams& healthCheckParams,
+            const ::android::sp<IStorageHealthListener>& healthListener, bool* _aidl_return) final;
+    binder::Status unregisterStorageHealthListener(int32_t storageId) final;
 
 private:
     android::incremental::IncrementalService mImpl;
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index 5f145f3..599ac93 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -1801,6 +1801,31 @@
     return removeTimedJobs(*mProgressUpdateJobQueue, storage);
 }
 
+bool IncrementalService::registerStorageHealthListener(
+        StorageId storage, StorageHealthCheckParams&& healthCheckParams,
+        const StorageHealthListener& healthListener) {
+    DataLoaderStubPtr dataLoaderStub;
+    {
+        std::unique_lock l(mLock);
+        const auto& ifs = getIfsLocked(storage);
+        if (!ifs) {
+            return false;
+        }
+        dataLoaderStub = ifs->dataLoaderStub;
+        if (!dataLoaderStub) {
+            return false;
+        }
+    }
+    dataLoaderStub->setHealthListener(std::move(healthCheckParams), &healthListener);
+    return true;
+}
+
+void IncrementalService::unregisterStorageHealthListener(StorageId storage) {
+    StorageHealthCheckParams invalidCheckParams;
+    invalidCheckParams.blockedTimeoutMs = -1;
+    registerStorageHealthListener(storage, std::move(invalidCheckParams), {});
+}
+
 bool IncrementalService::perfLoggingEnabled() {
     static const bool enabled = base::GetBoolProperty("incremental.perflogging", false);
     return enabled;
@@ -2137,6 +2162,19 @@
 
 binder::Status IncrementalService::DataLoaderStub::reportStreamHealth(MountId mountId,
                                                                       int newStatus) {
+    if (!isValid()) {
+        return binder::Status::
+                fromServiceSpecificError(-EINVAL,
+                                         "reportStreamHealth came to invalid DataLoaderStub");
+    }
+    if (id() != mountId) {
+        LOG(ERROR) << "Mount ID mismatch: expected " << id() << ", but got: " << mountId;
+        return binder::Status::fromServiceSpecificError(-EPERM, "Mount ID mismatch.");
+    }
+    {
+        std::lock_guard lock(mMutex);
+        mStreamStatus = newStatus;
+    }
     return binder::Status::ok();
 }
 
@@ -2153,6 +2191,33 @@
     }
 }
 
+static int adjustHealthStatus(int healthStatus, int streamStatus) {
+    if (healthStatus == IStorageHealthListener::HEALTH_STATUS_OK) {
+        // everything is good; no need to change status
+        return healthStatus;
+    }
+    int newHeathStatus = healthStatus;
+    switch (streamStatus) {
+        case IDataLoaderStatusListener::STREAM_STORAGE_ERROR:
+            // storage is limited and storage not healthy
+            newHeathStatus = IStorageHealthListener::HEALTH_STATUS_UNHEALTHY_STORAGE;
+            break;
+        case IDataLoaderStatusListener::STREAM_INTEGRITY_ERROR:
+            // fall through
+        case IDataLoaderStatusListener::STREAM_SOURCE_ERROR:
+            // fall through
+        case IDataLoaderStatusListener::STREAM_TRANSPORT_ERROR:
+            if (healthStatus == IStorageHealthListener::HEALTH_STATUS_UNHEALTHY) {
+                newHeathStatus = IStorageHealthListener::HEALTH_STATUS_UNHEALTHY_TRANSPORT;
+            }
+            // pending/blocked status due to transportation issues is not regarded as unhealthy
+            break;
+        default:
+            break;
+    }
+    return newHeathStatus;
+}
+
 void IncrementalService::DataLoaderStub::updateHealthStatus(bool baseline) {
     LOG(DEBUG) << id() << ": updateHealthStatus" << (baseline ? " (baseline)" : "");
 
@@ -2232,6 +2297,8 @@
             checkBackAfter = unhealthyMonitoring;
             healthStatusToReport = IStorageHealthListener::HEALTH_STATUS_UNHEALTHY;
         }
+        // Adjust health status based on stream status
+        healthStatusToReport = adjustHealthStatus(healthStatusToReport, mStreamStatus);
         LOG(DEBUG) << id() << ": updateHealthStatus in " << double(checkBackAfter.count()) / 1000.0
                    << "secs";
         mService.addTimedJob(*mService.mTimedQueue, id(), checkBackAfter,
@@ -2321,6 +2388,18 @@
     mService.mLooper->wake();
 }
 
+void IncrementalService::DataLoaderStub::setHealthListener(
+        StorageHealthCheckParams&& healthCheckParams, const StorageHealthListener* healthListener) {
+    std::lock_guard lock(mMutex);
+    mHealthCheckParams = std::move(healthCheckParams);
+    if (healthListener == nullptr) {
+        // reset listener and params
+        mHealthListener = {};
+    } else {
+        mHealthListener = *healthListener;
+    }
+}
+
 void IncrementalService::DataLoaderStub::onDump(int fd) {
     dprintf(fd, "    dataLoader: {\n");
     dprintf(fd, "      currentStatus: %d\n", mCurrentStatus);
diff --git a/services/incremental/IncrementalService.h b/services/incremental/IncrementalService.h
index 504c02a..4c4b8bd 100644
--- a/services/incremental/IncrementalService.h
+++ b/services/incremental/IncrementalService.h
@@ -140,7 +140,10 @@
     bool registerLoadingProgressListener(StorageId storage,
                                          const StorageLoadingProgressListener& progressListener);
     bool unregisterLoadingProgressListener(StorageId storage);
-
+    bool registerStorageHealthListener(StorageId storage,
+                                       StorageHealthCheckParams&& healthCheckParams,
+                                       const StorageHealthListener& healthListener);
+    void unregisterStorageHealthListener(StorageId storage);
     RawMetadata getMetadata(StorageId storage, std::string_view path) const;
     RawMetadata getMetadata(StorageId storage, FileId node) const;
 
@@ -197,6 +200,8 @@
 
         MountId id() const { return mId.load(std::memory_order_relaxed); }
         const content::pm::DataLoaderParamsParcel& params() const { return mParams; }
+        void setHealthListener(StorageHealthCheckParams&& healthCheckParams,
+                               const StorageHealthListener* healthListener);
 
     private:
         binder::Status onStatusChanged(MountId mount, int newStatus) final;
@@ -251,6 +256,7 @@
             BootClockTsUs kernelTsUs;
         } mHealthBase = {TimePoint::max(), kMaxBootClockTsUs};
         StorageHealthCheckParams mHealthCheckParams;
+        int mStreamStatus = content::pm::IDataLoaderStatusListener::STREAM_HEALTHY;
     };
     using DataLoaderStubPtr = sp<DataLoaderStub>;
 
diff --git a/services/incremental/test/IncrementalServiceTest.cpp b/services/incremental/test/IncrementalServiceTest.cpp
index aec9fa1..867312e 100644
--- a/services/incremental/test/IncrementalServiceTest.cpp
+++ b/services/incremental/test/IncrementalServiceTest.cpp
@@ -177,6 +177,18 @@
         }
         return binder::Status::ok();
     }
+    binder::Status storageError(int32_t id) {
+        if (mListener) {
+            mListener->reportStreamHealth(id, IDataLoaderStatusListener::STREAM_STORAGE_ERROR);
+        }
+        return binder::Status::ok();
+    }
+    binder::Status transportError(int32_t id) {
+        if (mListener) {
+            mListener->reportStreamHealth(id, IDataLoaderStatusListener::STREAM_INTEGRITY_ERROR);
+        }
+        return binder::Status::ok();
+    }
     int32_t setStorageParams(bool enableReadLogs) {
         int32_t result = -1;
         EXPECT_NE(mServiceConnector.get(), nullptr);
@@ -1221,4 +1233,83 @@
     EXPECT_CALL(*listenerMock, onStorageLoadingProgressChanged(_, _)).Times(0);
     mIncrementalService->registerLoadingProgressListener(storageId, listener);
 }
+
+TEST_F(IncrementalServiceTest, testRegisterStorageHealthListenerSuccess) {
+    mIncFs->openMountSuccess();
+    sp<NiceMock<MockStorageHealthListener>> listener{new NiceMock<MockStorageHealthListener>};
+    sp<NiceMock<MockStorageHealthListener>> newListener{new NiceMock<MockStorageHealthListener>};
+    NiceMock<MockStorageHealthListener>* newListenerMock = newListener.get();
+
+    TemporaryDir tempDir;
+    int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+                                                       IncrementalService::CreateOptions::CreateNew,
+                                                       {}, StorageHealthCheckParams{}, listener);
+    ASSERT_GE(storageId, 0);
+    StorageHealthCheckParams newParams;
+    newParams.blockedTimeoutMs = 10000;
+    newParams.unhealthyTimeoutMs = 20000;
+    newParams.unhealthyMonitoringMs = 30000;
+    ASSERT_TRUE(mIncrementalService->registerStorageHealthListener(storageId, std::move(newParams),
+                                                                   newListener));
+
+    using MS = std::chrono::milliseconds;
+    using MCS = std::chrono::microseconds;
+
+    const auto blockedTimeout = MS(newParams.blockedTimeoutMs);
+    const auto unhealthyTimeout = MS(newParams.unhealthyTimeoutMs);
+
+    const uint64_t kFirstTimestampUs = 1000000000ll;
+    const uint64_t kBlockedTimestampUs =
+            kFirstTimestampUs - std::chrono::duration_cast<MCS>(blockedTimeout).count();
+    const uint64_t kUnhealthyTimestampUs =
+            kFirstTimestampUs - std::chrono::duration_cast<MCS>(unhealthyTimeout).count();
+
+    // test that old listener was not called
+    EXPECT_CALL(*listener.get(),
+                onHealthStatus(_, IStorageHealthListener::HEALTH_STATUS_READS_PENDING))
+            .Times(0);
+    EXPECT_CALL(*newListenerMock,
+                onHealthStatus(_, IStorageHealthListener::HEALTH_STATUS_READS_PENDING))
+            .Times(1);
+    EXPECT_CALL(*newListenerMock, onHealthStatus(_, IStorageHealthListener::HEALTH_STATUS_BLOCKED))
+            .Times(1);
+    EXPECT_CALL(*newListenerMock,
+                onHealthStatus(_, IStorageHealthListener::HEALTH_STATUS_UNHEALTHY_STORAGE))
+            .Times(1);
+    EXPECT_CALL(*newListenerMock,
+                onHealthStatus(_, IStorageHealthListener::HEALTH_STATUS_UNHEALTHY_TRANSPORT))
+            .Times(1);
+    mIncFs->waitForPendingReadsSuccess(kFirstTimestampUs);
+    mLooper->mCallback(-1, -1, mLooper->mCallbackData);
+
+    ASSERT_EQ(IStorageHealthListener::HEALTH_STATUS_READS_PENDING, newListener->mStatus);
+    ASSERT_EQ(storageId, newListener->mStorageId);
+
+    auto timedCallback = mTimedQueue->mWhat;
+    mTimedQueue->clearJob(storageId);
+
+    // test when health status is blocked with transport error
+    mDataLoader->transportError(storageId);
+    mIncFs->waitForPendingReadsSuccess(kBlockedTimestampUs);
+    timedCallback();
+    ASSERT_EQ(IStorageHealthListener::HEALTH_STATUS_BLOCKED, newListener->mStatus);
+    timedCallback = mTimedQueue->mWhat;
+    mTimedQueue->clearJob(storageId);
+
+    // test when health status is blocked with storage error
+    mDataLoader->storageError(storageId);
+    mIncFs->waitForPendingReadsSuccess(kBlockedTimestampUs);
+    timedCallback();
+    ASSERT_EQ(IStorageHealthListener::HEALTH_STATUS_UNHEALTHY_STORAGE, newListener->mStatus);
+    timedCallback = mTimedQueue->mWhat;
+    mTimedQueue->clearJob(storageId);
+
+    // test when health status is unhealthy with transport error
+    mDataLoader->transportError(storageId);
+    mIncFs->waitForPendingReadsSuccess(kUnhealthyTimestampUs);
+    timedCallback();
+    ASSERT_EQ(IStorageHealthListener::HEALTH_STATUS_UNHEALTHY_TRANSPORT, newListener->mStatus);
+    mTimedQueue->clearJob(storageId);
+}
+
 } // namespace android::os::incremental
diff --git a/services/people/java/com/android/server/people/PeopleService.java b/services/people/java/com/android/server/people/PeopleService.java
index 91cb481..7c3b7a6 100644
--- a/services/people/java/com/android/server/people/PeopleService.java
+++ b/services/people/java/com/android/server/people/PeopleService.java
@@ -122,7 +122,7 @@
 
         @Override
         public ParceledListSlice<ConversationChannel> getRecentConversations() {
-            enforceSystemOrRoot("get recent conversations");
+            enforceSystemRootOrSystemUI(getContext(), "get recent conversations");
             return new ParceledListSlice<>(
                     mDataManager.getRecentConversations(
                             Binder.getCallingUserHandle().getIdentifier()));
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index ddd1f75..d14ed5a 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -29,6 +29,8 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
+import android.os.UpdateEngine;
+import android.os.UpdateEngineCallback;
 import android.util.Log;
 
 import com.android.server.IoThread;
@@ -198,6 +200,7 @@
     // Event observers
     private void registerObservers() {
         registerAppLaunchObserver();
+        registerOTAObserver();
     }
 
     private final AppLaunchObserver mAppLaunchObserver = new AppLaunchObserver();
@@ -261,4 +264,33 @@
             // Ignored
         }
     }
+
+    private void registerOTAObserver() {
+        UpdateEngine updateEngine = new UpdateEngine();
+        updateEngine.bind(new UpdateEngineCallback() {
+            @Override
+            public void onStatusUpdate(int status, float percent) {
+                if (status == UpdateEngine.UpdateStatusConstants.UPDATED_NEED_REBOOT) {
+                    packProfileReport();
+                }
+            }
+
+            @Override
+            public void onPayloadApplicationComplete(int errorCode) {
+                // Ignored
+            }
+        });
+    }
+
+    private void packProfileReport() {
+        if (mIProfcollect == null) {
+            return;
+        }
+
+        try {
+            mIProfcollect.CreateProfileReport();
+        } catch (RemoteException e) {
+            Log.e(LOG_TAG, e.getMessage());
+        }
+    }
 }
diff --git a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
index 09552082..27b07c7 100644
--- a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
+++ b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
@@ -45,6 +45,7 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
+import org.mockito.Mockito
 import org.mockito.Mockito.any
 import org.mockito.Mockito.anyBoolean
 import org.mockito.Mockito.anyInt
@@ -341,7 +342,8 @@
             whenever(this.userManagerService) { mockUserManagerService }
             whenever(this.permissionManagerServiceInternal) { mockPermissionManagerService }
             whenever(this.settings) { mockSettings }
-            whenever(this.activityTaskManagerInternal) { mockActivityTaskManager }
+            whenever(this.getLocalService(ActivityTaskManagerInternal::class.java)) {
+                mockActivityTaskManager}
             whenever(this.appsFilter) { mockAppsFilter }
             whenever(this.context) { mockContext }
         }
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
index 9d2393b..0ab1501 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -83,6 +83,8 @@
 
     private LinkedList<DisplayAddress.Physical> mAddresses = new LinkedList<>();
 
+    private Injector mInjector;
+
     @Before
     public void setUp() throws Exception {
         mMockitoSession = mockitoSession()
@@ -94,8 +96,9 @@
         doReturn(mMockedResources).when(mMockedContext).getResources();
         LocalServices.removeServiceForTest(LightsManager.class);
         LocalServices.addService(LightsManager.class, mMockedLightsManager);
+        mInjector = new Injector();
         mAdapter = new LocalDisplayAdapter(mMockedSyncRoot, mMockedContext, mHandler,
-                mListener);
+                mListener, mInjector);
         spyOn(mAdapter);
         doReturn(mMockedContext).when(mAdapter).getOverlayContext();
     }
@@ -222,7 +225,7 @@
         display.configs = configs;
         display.activeConfig = 1;
         setUpDisplay(display);
-        mAdapter.registerLocked();
+        mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
         waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
 
         assertThat(SurfaceControl.getActiveConfig(display.token)).isEqualTo(1);
@@ -272,7 +275,7 @@
                 new int[Display.HdrCapabilities.HDR_TYPE_HDR10_PLUS], 1000, 1000, 0);
         display.hdrCapabilities = changedHdrCapabilities;
         setUpDisplay(display);
-        mAdapter.registerLocked();
+        mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
         waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
 
         assertThat(mListener.addedDisplays.size()).isEqualTo(1);
@@ -308,7 +311,7 @@
         final int[] changedColorModes = new int[]{Display.COLOR_MODE_DEFAULT};
         display.colorModes = changedColorModes;
         setUpDisplay(display);
-        mAdapter.registerLocked();
+        mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
         waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
 
         assertThat(mListener.addedDisplays.size()).isEqualTo(1);
@@ -322,6 +325,35 @@
         assertThat(displayDeviceInfo.supportedColorModes).isEqualTo(changedColorModes);
     }
 
+    @Test
+    public void testDisplayChange_withStaleDesiredDisplayConfigSpecs() throws Exception {
+        SurfaceControl.DisplayConfig[] configs = new SurfaceControl.DisplayConfig[]{
+                createFakeDisplayConfig(1920, 1080, 60f),
+                createFakeDisplayConfig(1920, 1080, 50f)
+        };
+        final int activeConfig = 0;
+        FakeDisplay display = new FakeDisplay(PORT_A, configs, activeConfig);
+        display.desiredDisplayConfigSpecs.defaultConfig = 1;
+
+        setUpDisplay(display);
+        updateAvailableDisplays();
+        mAdapter.registerLocked();
+        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+
+        // Change the display
+        display.configs = new SurfaceControl.DisplayConfig[]{
+                createFakeDisplayConfig(1920, 1080, 60f)
+        };
+        // SurfaceFlinger can return a stale defaultConfig. Make sure this doesn't
+        // trigger ArrayOutOfBoundsException.
+        display.desiredDisplayConfigSpecs.defaultConfig = 1;
+
+        setUpDisplay(display);
+        updateAvailableDisplays();
+        mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
+        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+    }
+
     private void assertDisplayDpi(DisplayDeviceInfo info, int expectedPort,
                                   float expectedXdpi,
                                   float expectedYDpi,
@@ -356,6 +388,8 @@
         public int[] colorModes = new int[]{ Display.COLOR_MODE_DEFAULT };
         public Display.HdrCapabilities hdrCapabilities = new Display.HdrCapabilities(new int[0],
                 1000, 1000, 0);
+        public SurfaceControl.DesiredDisplayConfigSpecs desiredDisplayConfigSpecs =
+                new SurfaceControl.DesiredDisplayConfigSpecs(0, 60.f, 60.f, 60.f, 60.f);
 
         private FakeDisplay(int port) {
             this.address = createDisplayAddress(port);
@@ -387,7 +421,7 @@
                 () -> SurfaceControl.getDisplayColorModes(display.token));
         doReturn(display.hdrCapabilities).when(
                 () -> SurfaceControl.getHdrCapabilities(display.token));
-        doReturn(new SurfaceControl.DesiredDisplayConfigSpecs(0, 60.f, 60.f, 60.f, 60.f))
+        doReturn(display.desiredDisplayConfigSpecs)
                 .when(() -> SurfaceControl.getDesiredDisplayConfigSpecs(display.token));
     }
 
@@ -422,7 +456,7 @@
         return config;
     }
 
-    private void waitForHandlerToComplete(Handler handler, long waitTimeMs)
+    private static void waitForHandlerToComplete(Handler handler, long waitTimeMs)
             throws InterruptedException {
         final Object lock = new Object();
         synchronized (lock) {
@@ -435,6 +469,35 @@
         }
     }
 
+    private class HotplugTransmitter {
+        private final Handler mHandler;
+        private final LocalDisplayAdapter.DisplayEventListener mListener;
+
+        HotplugTransmitter(Looper looper, LocalDisplayAdapter.DisplayEventListener listener) {
+            mHandler = new Handler(looper);
+            mListener = listener;
+        }
+
+        public void sendHotplug(FakeDisplay display, boolean connected)
+                throws InterruptedException {
+            mHandler.post(() -> mListener.onHotplug(/* timestampNanos = */ 0,
+                    display.address.getPhysicalDisplayId(), connected));
+            waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+        }
+    }
+
+    private class Injector extends LocalDisplayAdapter.Injector {
+        private HotplugTransmitter mTransmitter;
+        @Override
+        public void setDisplayEventListenerLocked(Looper looper,
+                LocalDisplayAdapter.DisplayEventListener listener) {
+            mTransmitter = new HotplugTransmitter(looper, listener);
+        }
+        public HotplugTransmitter getTransmitter() {
+            return mTransmitter;
+        }
+    }
+
     private class TestListener implements DisplayAdapter.Listener {
         public ArrayList<DisplayDevice> addedDisplays = new ArrayList<>();
         public ArrayList<DisplayDevice> changedDisplays = new ArrayList<>();
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
index faf7169a..241b5a9 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -68,7 +68,6 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
-import android.util.SparseArray;
 
 import androidx.test.filters.FlakyTest;
 import androidx.test.filters.MediumTest;
@@ -834,12 +833,13 @@
             // Reset the current state
             mHandler.reset();
             clearPendingUidChanges();
+            uidRecord.pendingChange.isPending = false;
 
             mAms.enqueueUidChangeLocked(uidRecord, -1, changeToDispatch);
 
             // Verify that pendingChange is updated correctly.
-            final ChangeRecord pendingChange = getPendingChange(uidRecord.uid);
-            assertNotNull(pendingChange);
+            final ChangeRecord pendingChange = uidRecord.pendingChange;
+            assertTrue(pendingChange.isPending);
             assertEquals(TEST_UID, pendingChange.uid);
             assertEquals(expectedProcState, pendingChange.procState);
             assertEquals(TEST_PROC_STATE_SEQ1, pendingChange.procStateSeq);
@@ -923,22 +923,16 @@
         mAms.mProcessList.mActiveUids.clear();
     }
 
-    private ChangeRecord getPendingChange(int uid) {
-        final SparseArray<ChangeRecord> pendingChanges =
-                mAms.mUidObserverController.getPendingUidChangesForTest();
-        return pendingChanges.get(uid);
-    }
-
     private void addPendingUidChange(ChangeRecord record) {
-        mAms.mUidObserverController.getPendingUidChangesForTest().put(record.uid, record);
+        mAms.mUidObserverController.getPendingUidChangesForTest().add(record);
     }
 
     private void addPendingUidChanges(ArrayList<ChangeRecord> changes) {
-        final SparseArray<ChangeRecord> pendingChanges =
+        final ArrayList<ChangeRecord> pendingChanges =
                 mAms.mUidObserverController.getPendingUidChangesForTest();
         for (int i = 0; i < changes.size(); ++i) {
             final ChangeRecord record = changes.get(i);
-            pendingChanges.put(record.uid, record);
+            pendingChanges.add(record);
         }
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/am/UidObserverControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UidObserverControllerTest.java
index 57c581e..1de5f6f 100644
--- a/services/tests/servicestests/src/com/android/server/am/UidObserverControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UidObserverControllerTest.java
@@ -31,6 +31,7 @@
 import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertNull;
 
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
@@ -51,6 +52,9 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
 
 @SmallTest
 public class UidObserverControllerTest {
@@ -66,36 +70,41 @@
 
     @Before
     public void setUp() {
-        mUidObserverController = new UidObserverController(Mockito.mock(Handler.class));
+        MockitoAnnotations.initMocks(this);
+        mUidObserverController = new UidObserverController(mock(Handler.class));
     }
 
     @Test
     public void testEnqueueUidChange() {
-        int change = mUidObserverController.enqueueUidChange(TEST_UID1, UidRecord.CHANGE_ACTIVE,
-                PROCESS_STATE_FOREGROUND_SERVICE, PROCESS_CAPABILITY_ALL, 0, false);
+        int change = mUidObserverController.enqueueUidChange(null, TEST_UID1,
+                UidRecord.CHANGE_ACTIVE, PROCESS_STATE_FOREGROUND_SERVICE,
+                PROCESS_CAPABILITY_ALL, 0, false);
         assertEquals("expected=ACTIVE,actual=" + changeToStr(change),
                 UidRecord.CHANGE_ACTIVE, change);
         assertPendingChange(TEST_UID1, UidRecord.CHANGE_ACTIVE, PROCESS_STATE_FOREGROUND_SERVICE,
-                PROCESS_CAPABILITY_ALL, 0, false);
-        assertNull(getPendingChange(TEST_UID2));
+                PROCESS_CAPABILITY_ALL, 0, false, null);
+        final ChangeRecord record1 = getLatestPendingChange(TEST_UID1);
+        assertNull(getLatestPendingChange(TEST_UID2));
 
-        change = mUidObserverController.enqueueUidChange(TEST_UID2, UidRecord.CHANGE_CACHED,
-                PROCESS_STATE_CACHED_RECENT, PROCESS_CAPABILITY_NONE, 99, true);
+        final ChangeRecord record2 = new ChangeRecord();
+        change = mUidObserverController.enqueueUidChange(record2, TEST_UID2,
+                UidRecord.CHANGE_CACHED, PROCESS_STATE_CACHED_RECENT, PROCESS_CAPABILITY_NONE,
+                99, true);
         assertEquals("expected=ACTIVE,actual=" + changeToStr(change),
                 UidRecord.CHANGE_CACHED, change);
         assertPendingChange(TEST_UID1, UidRecord.CHANGE_ACTIVE, PROCESS_STATE_FOREGROUND_SERVICE,
-                PROCESS_CAPABILITY_ALL, 0, false);
+                PROCESS_CAPABILITY_ALL, 0, false, null);
         assertPendingChange(TEST_UID2, UidRecord.CHANGE_CACHED, PROCESS_STATE_CACHED_RECENT,
-                PROCESS_CAPABILITY_NONE, 99, true);
+                PROCESS_CAPABILITY_NONE, 99, true, record2);
 
-        change = mUidObserverController.enqueueUidChange(TEST_UID1, UidRecord.CHANGE_UNCACHED,
-                PROCESS_STATE_TOP, PROCESS_CAPABILITY_ALL, 0, false);
+        change = mUidObserverController.enqueueUidChange(record1, TEST_UID1,
+                UidRecord.CHANGE_UNCACHED, PROCESS_STATE_TOP, PROCESS_CAPABILITY_ALL, 0, false);
         assertEquals("expected=ACTIVE|UNCACHED,actual=" + changeToStr(change),
                 UidRecord.CHANGE_ACTIVE | UidRecord.CHANGE_UNCACHED, change);
         assertPendingChange(TEST_UID1, UidRecord.CHANGE_ACTIVE | UidRecord.CHANGE_UNCACHED,
-                PROCESS_STATE_TOP, PROCESS_CAPABILITY_ALL, 0, false);
+                PROCESS_STATE_TOP, PROCESS_CAPABILITY_ALL, 0, false, record1);
         assertPendingChange(TEST_UID2, UidRecord.CHANGE_CACHED, PROCESS_STATE_CACHED_RECENT,
-                PROCESS_CAPABILITY_NONE, 99, true);
+                PROCESS_CAPABILITY_NONE, 99, true, record2);
     }
 
     @Test
@@ -135,11 +144,11 @@
         addPendingChange(TEST_UID1, UidRecord.CHANGE_ACTIVE | UidRecord.CHANGE_PROCSTATE,
                 PROCESS_STATE_TOP, 0, PROCESS_CAPABILITY_ALL, false);
 
-        final IUidObserver observer1 = Mockito.mock(IUidObserver.Stub.class);
+        final IUidObserver observer1 = mock(IUidObserver.Stub.class);
         registerObserver(observer1,
                 ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_ACTIVE,
                 PROCESS_STATE_IMPORTANT_FOREGROUND, TEST_PKG2, TEST_UID2);
-        final IUidObserver observer2 = Mockito.mock(IUidObserver.Stub.class);
+        final IUidObserver observer2 = mock(IUidObserver.Stub.class);
         registerObserver(observer2, ActivityManager.UID_OBSERVER_PROCSTATE,
                 PROCESS_STATE_SERVICE, TEST_PKG3, TEST_UID3);
 
@@ -209,13 +218,16 @@
         record.procStateSeq = procStateSeq;
         record.capability = capability;
         record.ephemeral = ephemeral;
-        mUidObserverController.getPendingUidChangesForTest().put(uid, record);
+        mUidObserverController.getPendingUidChangesForTest().add(record);
     }
 
     private void assertPendingChange(int uid, int change, int procState, long procStateSeq,
-            int capability, boolean ephemeral) {
-        final ChangeRecord record = getPendingChange(uid);
+            int capability, boolean ephemeral, ChangeRecord expectedRecord) {
+        final ChangeRecord record = getLatestPendingChange(uid);
         assertNotNull(record);
+        if (expectedRecord != null) {
+            assertEquals(expectedRecord, record);
+        }
         assertEquals(change, record.change);
         assertEquals(procState, record.procState);
         assertEquals(procStateSeq, record.procStateSeq);
@@ -223,8 +235,16 @@
         assertEquals(ephemeral, record.ephemeral);
     }
 
-    private ChangeRecord getPendingChange(int uid) {
-        return mUidObserverController.getPendingUidChangesForTest().get(uid);
+    private ChangeRecord getLatestPendingChange(int uid) {
+        final ArrayList<ChangeRecord> changeRecords = mUidObserverController
+                .getPendingUidChangesForTest();
+        for (int i = changeRecords.size() - 1; i >= 0; --i) {
+            final ChangeRecord record = changeRecords.get(i);
+            if (record.uid == uid) {
+                return record;
+            }
+        }
+        return null;
     }
 
     private static String changeToStr(int change) {
diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
index 6f4ff35..04de6ca 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -153,7 +153,7 @@
             doNothing().when(mInjector).startHomeActivity(anyInt(), anyString());
             doReturn(false).when(mInjector).stackSupervisorSwitchUser(anyInt(), any());
             doNothing().when(mInjector).stackSupervisorResumeFocusedStackTopActivity();
-            doNothing().when(mInjector).systemServiceManagerCleanupUser(anyInt());
+            doNothing().when(mInjector).systemServiceManagerOnUserStopped(anyInt());
             doNothing().when(mInjector).activityManagerForceStopPackage(anyInt(), anyString());
             doNothing().when(mInjector).activityManagerOnUserStopped(anyInt());
             doNothing().when(mInjector).clearBroadcastQueueForUser(anyInt());
diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java b/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java
index 2cbe7be..870fe4a 100644
--- a/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java
+++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java
@@ -39,58 +39,79 @@
         return new CompatConfigBuilder(buildClassifier, context);
     }
 
-    CompatConfigBuilder addTargetSdkChangeWithId(int sdk, long id) {
-        mChanges.add(new CompatChange(id, "", sdk, false, false, ""));
+    CompatConfigBuilder addEnableAfterSdkChangeWithId(int sdk, long id) {
+        mChanges.add(new CompatChange(id, "", sdk, -1, false, false, ""));
         return this;
     }
 
-    CompatConfigBuilder addTargetSdkDisabledChangeWithId(int sdk, long id) {
-        mChanges.add(new CompatChange(id, "", sdk, true, false, ""));
+    CompatConfigBuilder addEnableAfterSdkChangeWithIdAndName(int sdk, long id, String name) {
+        mChanges.add(new CompatChange(id, name, sdk, -1, false, false, ""));
         return this;
     }
 
-    CompatConfigBuilder addTargetSdkChangeWithIdAndName(int sdk, long id, String name) {
-        mChanges.add(new CompatChange(id, name, sdk, false, false, ""));
+    CompatConfigBuilder addEnableAfterSdkChangeWithIdDefaultDisabled(int sdk, long id) {
+        mChanges.add(new CompatChange(id, "", sdk, -1, true, false, ""));
         return this;
     }
 
-    CompatConfigBuilder addTargetSdkChangeWithIdAndDescription(int sdk, long id,
+    CompatConfigBuilder addEnableAfterSdkChangeWithIdAndDescription(int sdk, long id,
             String description) {
-        mChanges.add(new CompatChange(id, "", sdk, false, false, description));
+        mChanges.add(new CompatChange(id, "", sdk, -1, false, false, description));
+        return this;
+    }
+
+    CompatConfigBuilder addEnableSinceSdkChangeWithId(int sdk, long id) {
+        mChanges.add(new CompatChange(id, "", -1, sdk, false, false, ""));
+        return this;
+    }
+
+    CompatConfigBuilder addEnableSinceSdkChangeWithIdAndName(int sdk, long id, String name) {
+        mChanges.add(new CompatChange(id, name, -1, sdk, false, false, ""));
+        return this;
+    }
+
+    CompatConfigBuilder addEnableSinceSdkChangeWithIdDefaultDisabled(int sdk, long id) {
+        mChanges.add(new CompatChange(id, "", -1, sdk, true, false, ""));
+        return this;
+    }
+
+    CompatConfigBuilder addEnableSinceSdkChangeWithIdAndDescription(int sdk, long id,
+            String description) {
+        mChanges.add(new CompatChange(id, "", -1, sdk, false, false, description));
         return this;
     }
 
     CompatConfigBuilder addEnabledChangeWithId(long id) {
-        mChanges.add(new CompatChange(id, "", -1, false, false, ""));
+        mChanges.add(new CompatChange(id, "", -1, -1, false, false, ""));
         return this;
     }
 
     CompatConfigBuilder addEnabledChangeWithIdAndName(long id, String name) {
-        mChanges.add(new CompatChange(id, name, -1, false, false, ""));
+        mChanges.add(new CompatChange(id, name, -1, -1, false, false, ""));
         return this;
     }
     CompatConfigBuilder addEnabledChangeWithIdAndDescription(long id, String description) {
-        mChanges.add(new CompatChange(id, "", -1, false, false, description));
+        mChanges.add(new CompatChange(id, "", -1, -1, false, false, description));
         return this;
     }
 
     CompatConfigBuilder addDisabledChangeWithId(long id) {
-        mChanges.add(new CompatChange(id, "", -1, true, false, ""));
+        mChanges.add(new CompatChange(id, "", -1, -1, true, false, ""));
         return this;
     }
 
     CompatConfigBuilder addDisabledChangeWithIdAndName(long id, String name) {
-        mChanges.add(new CompatChange(id, name, -1, true, false, ""));
+        mChanges.add(new CompatChange(id, name, -1, -1, true, false, ""));
         return this;
     }
 
     CompatConfigBuilder addDisabledChangeWithIdAndDescription(long id, String description) {
-        mChanges.add(new CompatChange(id, "", -1, true, false, description));
+        mChanges.add(new CompatChange(id, "", -1, -1, true, false, description));
         return this;
     }
 
     CompatConfigBuilder addLoggingOnlyChangeWithId(long id) {
-        mChanges.add(new CompatChange(id, "", -1, false, true, ""));
+        mChanges.add(new CompatChange(id, "", -1, -1, false, true, ""));
         return this;
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
index 8be9213..e588370 100644
--- a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
@@ -98,7 +98,7 @@
     @Test
     public void testTargetSdkChangeDisabled() throws Exception {
         CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
-                .addTargetSdkChangeWithId(2, 1234L)
+                .addEnableAfterSdkChangeWithId(2, 1234L)
                 .build();
 
         assertThat(compatConfig.isChangeEnabled(1234L,
@@ -109,7 +109,7 @@
     @Test
     public void testTargetSdkChangeEnabled() throws Exception {
         CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
-                .addTargetSdkChangeWithId(2, 1234L)
+                .addEnableAfterSdkChangeWithId(2, 1234L)
                 .build();
 
         assertThat(compatConfig.isChangeEnabled(1234L,
@@ -119,7 +119,7 @@
     @Test
     public void testDisabledOverrideTargetSdkChange() throws Exception {
         CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
-                .addTargetSdkDisabledChangeWithId(2, 1234L)
+                .addEnableAfterSdkChangeWithIdDefaultDisabled(2, 1234L)
                 .build();
 
         assertThat(compatConfig.isChangeEnabled(1234L,
@@ -293,8 +293,8 @@
         CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
                 .addEnabledChangeWithId(1L)
                 .addDisabledChangeWithId(2L)
-                .addTargetSdkChangeWithId(3, 3L)
-                .addTargetSdkChangeWithId(4, 4L)
+                .addEnableSinceSdkChangeWithId(3, 3L)
+                .addEnableSinceSdkChangeWithId(4, 4L)
                 .build();
         ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
                 .withPackageName("foo.bar")
@@ -314,8 +314,8 @@
         CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
                 .addEnabledChangeWithId(1L)
                 .addDisabledChangeWithId(2L)
-                .addTargetSdkChangeWithId(3, 3L)
-                .addTargetSdkChangeWithId(4, 4L)
+                .addEnableSinceSdkChangeWithId(3, 3L)
+                .addEnableSinceSdkChangeWithId(4, 4L)
                 .build();
         ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
                 .withPackageName("foo.bar")
diff --git a/services/tests/servicestests/src/com/android/server/compat/OverrideValidatorImplTest.java b/services/tests/servicestests/src/com/android/server/compat/OverrideValidatorImplTest.java
index d45589d..c53b29a 100644
--- a/services/tests/servicestests/src/com/android/server/compat/OverrideValidatorImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/compat/OverrideValidatorImplTest.java
@@ -87,9 +87,9 @@
     public void getOverrideAllowedState_debugBuildAnyChangeDebugApp_allowOverride()
             throws Exception {
         CompatConfig config = CompatConfigBuilder.create(debuggableBuild(), mContext)
-                    .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1)
-                    .addTargetSdkChangeWithId(TARGET_SDK, 2)
-                    .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 3)
+                    .addEnableAfterSdkChangeWithId(TARGET_SDK_BEFORE, 1)
+                    .addEnableAfterSdkChangeWithId(TARGET_SDK, 2)
+                    .addEnableAfterSdkChangeWithId(TARGET_SDK_AFTER, 3)
                     .addEnabledChangeWithId(4)
                     .addDisabledChangeWithId(5)
                     .addLoggingOnlyChangeWithId(6).build();
@@ -131,9 +131,9 @@
     public void getOverrideAllowedState_debugBuildAnyChangeReleaseApp_allowOverride()
             throws Exception {
         CompatConfig config = CompatConfigBuilder.create(debuggableBuild(), mContext)
-                    .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1)
-                    .addTargetSdkChangeWithId(TARGET_SDK, 2)
-                    .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 3)
+                    .addEnableAfterSdkChangeWithId(TARGET_SDK_BEFORE, 1)
+                    .addEnableAfterSdkChangeWithId(TARGET_SDK, 2)
+                    .addEnableAfterSdkChangeWithId(TARGET_SDK_AFTER, 3)
                     .addEnabledChangeWithId(4)
                     .addDisabledChangeWithId(5)
                     .addLoggingOnlyChangeWithId(6).build();
@@ -174,9 +174,9 @@
     public void getOverrideAllowedState_betaBuildTargetSdkChangeDebugApp_allowOverride()
             throws Exception {
         CompatConfig config = CompatConfigBuilder.create(betaBuild(), mContext)
-                        .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1)
-                        .addTargetSdkChangeWithId(TARGET_SDK, 2)
-                        .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 3)
+                        .addEnableAfterSdkChangeWithId(TARGET_SDK_BEFORE, 1)
+                        .addEnableAfterSdkChangeWithId(TARGET_SDK, 2)
+                        .addEnableAfterSdkChangeWithId(TARGET_SDK_AFTER, 3)
                         .addDisabledChangeWithId(4).build();
         IOverrideValidator overrideValidator = config.getOverrideValidator();
         when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
@@ -245,9 +245,9 @@
     public void getOverrideAllowedState_betaBuildAnyChangeReleaseApp_rejectOverride()
             throws Exception {
         CompatConfig config = CompatConfigBuilder.create(betaBuild(), mContext)
-                        .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1)
-                        .addTargetSdkChangeWithId(TARGET_SDK, 2)
-                        .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 3)
+                        .addEnableAfterSdkChangeWithId(TARGET_SDK_BEFORE, 1)
+                        .addEnableAfterSdkChangeWithId(TARGET_SDK, 2)
+                        .addEnableAfterSdkChangeWithId(TARGET_SDK_AFTER, 3)
                         .addEnabledChangeWithId(4)
                         .addDisabledChangeWithId(5)
                         .addLoggingOnlyChangeWithId(6).build();
@@ -288,8 +288,8 @@
     public void getOverrideAllowedState_finalBuildTargetSdkChangeDebugAppOptin_allowOverride()
             throws Exception {
         CompatConfig config = CompatConfigBuilder.create(finalBuild(), mContext)
-                        .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 1)
-                        .addTargetSdkChangeWithId(TARGET_SDK, 2).build();
+                        .addEnableAfterSdkChangeWithId(TARGET_SDK_AFTER, 1)
+                        .addEnableAfterSdkChangeWithId(TARGET_SDK, 2).build();
         IOverrideValidator overrideValidator = config.getOverrideValidator();
         when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
                 .thenReturn(ApplicationInfoBuilder.create()
@@ -313,7 +313,7 @@
     public void getOverrideAllowedState_finalBuildTargetSdkChangeDebugAppOptout_rejectOverride()
             throws Exception {
         CompatConfig config = CompatConfigBuilder.create(finalBuild(), mContext)
-                        .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1).build();
+                        .addEnableAfterSdkChangeWithId(TARGET_SDK_BEFORE, 1).build();
         IOverrideValidator overrideValidator = config.getOverrideValidator();
         when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
                 .thenReturn(ApplicationInfoBuilder.create()
@@ -371,9 +371,9 @@
     public void getOverrideAllowedState_finalBuildAnyChangeReleaseApp_rejectOverride()
             throws Exception {
         CompatConfig config = CompatConfigBuilder.create(finalBuild(), mContext)
-                        .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1)
-                        .addTargetSdkChangeWithId(TARGET_SDK, 2)
-                        .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 3)
+                        .addEnableAfterSdkChangeWithId(TARGET_SDK_BEFORE, 1)
+                        .addEnableAfterSdkChangeWithId(TARGET_SDK, 2)
+                        .addEnableAfterSdkChangeWithId(TARGET_SDK_AFTER, 3)
                         .addEnabledChangeWithId(4)
                         .addDisabledChangeWithId(5)
                         .addLoggingOnlyChangeWithId(6).build();
diff --git a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java
index cef02ff..64014ba 100644
--- a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java
+++ b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java
@@ -84,22 +84,22 @@
         mCompatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
                 .addEnabledChangeWithId(1L)
                 .addDisabledChangeWithIdAndName(2L, "change2")
-                .addTargetSdkChangeWithIdAndDescription(Build.VERSION_CODES.O, 3L, "description")
-                .addTargetSdkChangeWithId(Build.VERSION_CODES.P, 4L)
-                .addTargetSdkChangeWithId(Build.VERSION_CODES.Q, 5L)
-                .addTargetSdkChangeWithId(Build.VERSION_CODES.R, 6L)
+                .addEnableAfterSdkChangeWithIdAndDescription(Build.VERSION_CODES.O, 3L, "desc")
+                .addEnableAfterSdkChangeWithId(Build.VERSION_CODES.P, 4L)
+                .addEnableAfterSdkChangeWithId(Build.VERSION_CODES.Q, 5L)
+                .addEnableAfterSdkChangeWithId(Build.VERSION_CODES.R, 6L)
                 .addLoggingOnlyChangeWithId(7L)
                 .build();
         mPlatformCompat = new PlatformCompat(mContext, mCompatConfig);
         assertThat(mPlatformCompat.listAllChanges()).asList().containsExactly(
-                new CompatibilityChangeInfo(1L, "", -1, false, false, ""),
-                new CompatibilityChangeInfo(2L, "change2", -1, true, false, ""),
-                new CompatibilityChangeInfo(3L, "", Build.VERSION_CODES.O, false, false,
-                        "description"),
-                new CompatibilityChangeInfo(4L, "", Build.VERSION_CODES.P, false, false, ""),
-                new CompatibilityChangeInfo(5L, "", Build.VERSION_CODES.Q, false, false, ""),
-                new CompatibilityChangeInfo(6L, "", Build.VERSION_CODES.R, false, false, ""),
-                new CompatibilityChangeInfo(7L, "", -1, false, true, ""));
+                new CompatibilityChangeInfo(1L, "", -1, -1, false, false, ""),
+                new CompatibilityChangeInfo(2L, "change2", -1, -1, true, false, ""),
+                new CompatibilityChangeInfo(3L, "", Build.VERSION_CODES.O, -1, false, false,
+                        "desc"),
+                new CompatibilityChangeInfo(4L, "", Build.VERSION_CODES.P, -1, false, false, ""),
+                new CompatibilityChangeInfo(5L, "", Build.VERSION_CODES.Q, -1, false, false, ""),
+                new CompatibilityChangeInfo(6L, "", Build.VERSION_CODES.R, -1, false, false, ""),
+                new CompatibilityChangeInfo(7L, "", -1, -1, false, true, ""));
     }
 
     @Test
@@ -107,18 +107,18 @@
         mCompatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
                 .addEnabledChangeWithId(1L)
                 .addDisabledChangeWithIdAndName(2L, "change2")
-                .addTargetSdkChangeWithIdAndDescription(Build.VERSION_CODES.O, 3L, "description")
-                .addTargetSdkChangeWithId(Build.VERSION_CODES.P, 4L)
-                .addTargetSdkChangeWithId(Build.VERSION_CODES.Q, 5L)
-                .addTargetSdkChangeWithId(Build.VERSION_CODES.R, 6L)
+                .addEnableAfterSdkChangeWithIdAndDescription(Build.VERSION_CODES.O, 3L, "desc")
+                .addEnableAfterSdkChangeWithId(Build.VERSION_CODES.P, 4L)
+                .addEnableAfterSdkChangeWithId(Build.VERSION_CODES.Q, 5L)
+                .addEnableAfterSdkChangeWithId(Build.VERSION_CODES.R, 6L)
                 .addLoggingOnlyChangeWithId(7L)
                 .build();
         mPlatformCompat = new PlatformCompat(mContext, mCompatConfig);
         assertThat(mPlatformCompat.listUIChanges()).asList().containsExactly(
-                new CompatibilityChangeInfo(1L, "", -1, false, false, ""),
-                new CompatibilityChangeInfo(2L, "change2", -1, true, false, ""),
-                new CompatibilityChangeInfo(4L, "", Build.VERSION_CODES.P, false, false, ""),
-                new CompatibilityChangeInfo(5L, "", Build.VERSION_CODES.Q, false, false, ""));
+                new CompatibilityChangeInfo(1L, "", -1, -1, false, false, ""),
+                new CompatibilityChangeInfo(2L, "change2", -1, -1, true, false, ""),
+                new CompatibilityChangeInfo(4L, "", Build.VERSION_CODES.P, -1, false, false, ""),
+                new CompatibilityChangeInfo(5L, "", Build.VERSION_CODES.Q, -1, false, false, ""));
     }
 
     @Test
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 631b4d4..30b1b3e 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -5728,6 +5728,7 @@
         // Device owner should be allowed to request Device ID attestation.
         dpms.enforceCallerCanRequestDeviceIdAttestation(dpms.getCallerIdentity(admin1));
 
+        mContext.binder.callingUid = DpmMockContext.ANOTHER_UID;
         // Another package must not be allowed to request Device ID attestation.
         assertExpectException(SecurityException.class, null,
                 () -> dpms.enforceCallerCanRequestDeviceIdAttestation(
@@ -5757,6 +5758,7 @@
         dpms.enforceCallerCanRequestDeviceIdAttestation(dpms.getCallerIdentity(admin1));
 
         // But not another package.
+        mContext.binder.callingUid = DpmMockContext.ANOTHER_UID;
         assertExpectException(SecurityException.class, null,
                 () -> dpms.enforceCallerCanRequestDeviceIdAttestation(
                         dpms.getCallerIdentity(null, admin2.getPackageName())));
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java
new file mode 100644
index 0000000..c7331e1
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.hdmi;
+
+import static com.android.server.hdmi.HdmiCecMessageValidator.ERROR_DESTINATION;
+import static com.android.server.hdmi.HdmiCecMessageValidator.ERROR_PARAMETER_SHORT;
+import static com.android.server.hdmi.HdmiCecMessageValidator.ERROR_SOURCE;
+import static com.android.server.hdmi.HdmiCecMessageValidator.OK;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+
+import com.google.common.truth.IntegerSubject;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for {@link com.android.server.hdmi.HdmiCecMessageValidator} class. */
+@SmallTest
+@Presubmit
+@RunWith(JUnit4.class)
+public class HdmiCecMessageValidatorTest {
+
+    private HdmiCecMessageValidator mHdmiCecMessageValidator;
+
+    @Before
+    public void setUp() throws Exception {
+        HdmiControlService mHdmiControlService = new HdmiControlService(
+                InstrumentationRegistry.getTargetContext());
+
+        mHdmiCecMessageValidator = new HdmiCecMessageValidator(mHdmiControlService);
+    }
+
+    @Test
+    public void isValid_giveDevicePowerStatus() {
+        assertMessageValidity("04:8F").isEqualTo(OK);
+
+        assertMessageValidity("0F:8F").isEqualTo(ERROR_DESTINATION);
+        assertMessageValidity("F4:8F").isEqualTo(ERROR_SOURCE);
+    }
+
+    @Test
+    public void isValid_reportPowerStatus() {
+        assertMessageValidity("04:90:00").isEqualTo(OK);
+
+        assertMessageValidity("0F:90:00").isEqualTo(ERROR_DESTINATION);
+        assertMessageValidity("F0:90").isEqualTo(ERROR_SOURCE);
+        assertMessageValidity("04:90").isEqualTo(ERROR_PARAMETER_SHORT);
+    }
+
+    private IntegerSubject assertMessageValidity(String message) {
+        return assertThat(mHdmiCecMessageValidator.isValid(buildMessage(message)));
+    }
+
+    /**
+     * Build a CEC message from a hex byte string with bytes separated by {@code :}.
+     *
+     * <p>This format is used by both cec-client and www.cec-o-matic.com
+     */
+    private static HdmiCecMessage buildMessage(String message) {
+        String[] parts = message.split(":");
+        int src = Integer.parseInt(parts[0].substring(0, 1), 16);
+        int dest = Integer.parseInt(parts[0].substring(1, 2), 16);
+        int opcode = Integer.parseInt(parts[1], 16);
+        byte[] params = new byte[parts.length - 2];
+        for (int i = 0; i < params.length; i++) {
+            params[i] = (byte) Integer.parseInt(parts[i + 2], 16);
+        }
+        return new HdmiCecMessage(src, dest, opcode, params);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java
index e281f2b..391611b 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java
@@ -35,8 +35,8 @@
 @RunWith(AndroidJUnit4.class)
 public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceImplTestsBase {
 
-    private static final String OVERLAY = "com.dummy.overlay";
-    private static final String TARGET = "com.dummy.target";
+    private static final String OVERLAY = "com.test.overlay";
+    private static final String TARGET = "com.test.target";
     private static final int USER = 0;
 
     private static final String OVERLAY2 = OVERLAY + "2";
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
index c1d862a..4f882ce 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
@@ -39,8 +39,8 @@
 @RunWith(AndroidJUnit4.class)
 public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTestsBase {
 
-    private static final String OVERLAY = "com.dummy.overlay";
-    private static final String TARGET = "com.dummy.target";
+    private static final String OVERLAY = "com.test.overlay";
+    private static final String TARGET = "com.test.target";
     private static final int USER = 0;
 
     private static final String OVERLAY2 = OVERLAY + "2";
@@ -50,7 +50,7 @@
     private static final String OVERLAY3 = OVERLAY + "3";
     private static final int USER3 = USER2 + 1;
 
-    private static final String CONFIG_SIGNATURE_REFERENCE_PKG = "com.dummy.ref";
+    private static final String CONFIG_SIGNATURE_REFERENCE_PKG = "com.test.ref";
     private static final String CERT_CONFIG_OK = "config_certificate_ok";
     private static final String CERT_CONFIG_NOK = "config_certificate_nok";
 
@@ -149,7 +149,7 @@
         installNewPackage(overlay(OVERLAY, TARGET), USER);
         assertState(STATE_MISSING_TARGET, OVERLAY, USER);
 
-        final DummyDeviceState.PackageBuilder target = target(TARGET);
+        final FakeDeviceState.PackageBuilder target = target(TARGET);
         installNewPackage(target, USER);
         assertState(STATE_DISABLED, OVERLAY, USER);
 
@@ -169,9 +169,9 @@
 
     @Test
     public void testOnOverlayPackageUpgraded() {
-        final DummyListener listener = getListener();
-        final DummyDeviceState.PackageBuilder target = target(TARGET);
-        final DummyDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET);
+        final FakeListener listener = getListener();
+        final FakeDeviceState.PackageBuilder target = target(TARGET);
+        final FakeDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET);
         installNewPackage(target, USER);
         installNewPackage(overlay, USER);
         listener.count = 0;
@@ -181,7 +181,7 @@
         // upgrade to a version where the overlay has changed its target
         // expect once for the old target package, once for the new target package
         listener.count = 0;
-        final DummyDeviceState.PackageBuilder overlay2 = overlay(OVERLAY, "some.other.target");
+        final FakeDeviceState.PackageBuilder overlay2 = overlay(OVERLAY, "some.other.target");
         upgradePackage(overlay2, USER);
         assertEquals(3, listener.count);
 
@@ -193,7 +193,7 @@
     @Test
     public void testListener() {
         final OverlayManagerServiceImpl impl = getImpl();
-        final DummyListener listener = getListener();
+        final FakeListener listener = getListener();
         installNewPackage(overlay(OVERLAY, TARGET), USER);
         assertEquals(1, listener.count);
         listener.count = 0;
@@ -219,12 +219,12 @@
         installNewPackage(target(TARGET), USER);
         installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_OK), USER);
 
-        final DummyIdmapDaemon idmapd = getIdmapd();
-        final DummyDeviceState state = getState();
+        final FakeIdmapDaemon idmapd = getIdmapd();
+        final FakeDeviceState state = getState();
         String overlayPath = state.select(OVERLAY, USER).apkPath;
         assertTrue(idmapd.idmapExists(overlayPath, USER));
 
-        DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
+        FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
         assertTrue((CONFIG_SIGNATURE & idmap.policies) == CONFIG_SIGNATURE);
     }
 
@@ -237,12 +237,12 @@
         installNewPackage(target(TARGET), USER);
         installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
 
-        final DummyIdmapDaemon idmapd = getIdmapd();
-        final DummyDeviceState state = getState();
+        final FakeIdmapDaemon idmapd = getIdmapd();
+        final FakeDeviceState state = getState();
         String overlayPath = state.select(OVERLAY, USER).apkPath;
         assertTrue(idmapd.idmapExists(overlayPath, USER));
 
-        DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
+        FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
         assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0);
     }
 
@@ -252,12 +252,12 @@
         installNewPackage(target(TARGET), USER);
         installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
 
-        final DummyIdmapDaemon idmapd = getIdmapd();
-        final DummyDeviceState state = getState();
+        final FakeIdmapDaemon idmapd = getIdmapd();
+        final FakeDeviceState state = getState();
         String overlayPath = state.select(OVERLAY, USER).apkPath;
         assertTrue(idmapd.idmapExists(overlayPath, USER));
 
-        DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
+        FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
         assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0);
     }
 
@@ -266,12 +266,12 @@
         installNewPackage(target(TARGET), USER);
         installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
 
-        final DummyIdmapDaemon idmapd = getIdmapd();
-        final DummyDeviceState state = getState();
+        final FakeIdmapDaemon idmapd = getIdmapd();
+        final FakeDeviceState state = getState();
         String overlayPath = state.select(OVERLAY, USER).apkPath;
         assertTrue(idmapd.idmapExists(overlayPath, USER));
 
-        DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
+        FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
         assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0);
     }
 
@@ -284,12 +284,12 @@
         installNewPackage(target(TARGET), USER);
         installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
 
-        final DummyIdmapDaemon idmapd = getIdmapd();
-        final DummyDeviceState state = getState();
+        final FakeIdmapDaemon idmapd = getIdmapd();
+        final FakeDeviceState state = getState();
         String overlayPath = state.select(OVERLAY, USER).apkPath;
         assertTrue(idmapd.idmapExists(overlayPath, USER));
 
-        DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
+        FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
         assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
index 2faf29f..006dda0 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
@@ -48,19 +48,19 @@
 /** Base class for creating {@link OverlayManagerServiceImplTests} tests. */
 class OverlayManagerServiceImplTestsBase {
     private OverlayManagerServiceImpl mImpl;
-    private DummyDeviceState mState;
-    private DummyListener mListener;
-    private DummyPackageManagerHelper mPackageManager;
-    private DummyIdmapDaemon mIdmapDaemon;
+    private FakeDeviceState mState;
+    private FakeListener mListener;
+    private FakePackageManagerHelper mPackageManager;
+    private FakeIdmapDaemon mIdmapDaemon;
     private OverlayConfig mOverlayConfig;
     private String mConfigSignaturePackageName;
 
     @Before
     public void setUp() {
-        mState = new DummyDeviceState();
-        mListener = new DummyListener();
-        mPackageManager = new DummyPackageManagerHelper(mState);
-        mIdmapDaemon = new DummyIdmapDaemon(mState);
+        mState = new FakeDeviceState();
+        mListener = new FakeListener();
+        mPackageManager = new FakePackageManagerHelper(mState);
+        mIdmapDaemon = new FakeIdmapDaemon(mState);
         mOverlayConfig = mock(OverlayConfig.class);
         when(mOverlayConfig.getPriority(any())).thenReturn(OverlayConfig.DEFAULT_PRIORITY);
         when(mOverlayConfig.isEnabled(any())).thenReturn(false);
@@ -81,15 +81,15 @@
         return mImpl;
     }
 
-    DummyListener getListener() {
+    FakeListener getListener() {
         return mListener;
     }
 
-    DummyIdmapDaemon getIdmapd() {
+    FakeIdmapDaemon getIdmapd() {
         return mIdmapDaemon;
     }
 
-    DummyDeviceState getState() {
+    FakeDeviceState getState() {
         return mState;
     }
 
@@ -116,27 +116,27 @@
         assertEquals(expected, actual);
     }
 
-    DummyDeviceState.PackageBuilder app(String packageName) {
-        return new DummyDeviceState.PackageBuilder(packageName, null /* targetPackageName */,
+    FakeDeviceState.PackageBuilder app(String packageName) {
+        return new FakeDeviceState.PackageBuilder(packageName, null /* targetPackageName */,
                 null /* targetOverlayableName */, "data");
     }
 
-    DummyDeviceState.PackageBuilder target(String packageName) {
-        return new DummyDeviceState.PackageBuilder(packageName, null /* targetPackageName */,
+    FakeDeviceState.PackageBuilder target(String packageName) {
+        return new FakeDeviceState.PackageBuilder(packageName, null /* targetPackageName */,
                 null /* targetOverlayableName */, "");
     }
 
-    DummyDeviceState.PackageBuilder overlay(String packageName, String targetPackageName) {
+    FakeDeviceState.PackageBuilder overlay(String packageName, String targetPackageName) {
         return overlay(packageName, targetPackageName, null /* targetOverlayableName */);
     }
 
-    DummyDeviceState.PackageBuilder overlay(String packageName, String targetPackageName,
+    FakeDeviceState.PackageBuilder overlay(String packageName, String targetPackageName,
             String targetOverlayableName) {
-        return new DummyDeviceState.PackageBuilder(packageName, targetPackageName,
+        return new FakeDeviceState.PackageBuilder(packageName, targetPackageName,
                 targetOverlayableName, "");
     }
 
-    void addPackage(DummyDeviceState.PackageBuilder pkg, int userId) {
+    void addPackage(FakeDeviceState.PackageBuilder pkg, int userId) {
         mState.add(pkg, userId);
     }
 
@@ -155,7 +155,7 @@
      *
      * @throws IllegalStateException if the package is currently installed
      */
-    void installNewPackage(DummyDeviceState.PackageBuilder pkg, int userId) {
+    void installNewPackage(FakeDeviceState.PackageBuilder pkg, int userId) {
         if (mState.select(pkg.packageName, userId) != null) {
             throw new IllegalStateException("package " + pkg.packageName + " already installed");
         }
@@ -178,8 +178,8 @@
      *
      * @throws IllegalStateException if the package is not currently installed
      */
-    void upgradePackage(DummyDeviceState.PackageBuilder pkg, int userId) {
-        final DummyDeviceState.Package replacedPackage = mState.select(pkg.packageName, userId);
+    void upgradePackage(FakeDeviceState.PackageBuilder pkg, int userId) {
+        final FakeDeviceState.Package replacedPackage = mState.select(pkg.packageName, userId);
         if (replacedPackage == null) {
             throw new IllegalStateException("package " + pkg.packageName + " not installed");
         }
@@ -204,7 +204,7 @@
      * @throws IllegalStateException if the package is not currently installed
      */
     void uninstallPackage(String packageName, int userId) {
-        final DummyDeviceState.Package pkg = mState.select(packageName, userId);
+        final FakeDeviceState.Package pkg = mState.select(packageName, userId);
         if (pkg == null) {
             throw new IllegalStateException("package " + packageName+ " not installed");
         }
@@ -217,7 +217,7 @@
     }
 
     /** Represents the state of packages installed on a fake device. */
-    static class DummyDeviceState {
+    static class FakeDeviceState {
         private ArrayMap<String, Package> mPackages = new ArrayMap<>();
 
         void add(PackageBuilder pkgBuilder, int userId) {
@@ -333,16 +333,16 @@
         }
     }
 
-    final class DummyPackageManagerHelper implements PackageManagerHelper {
-        private final DummyDeviceState mState;
+    final class FakePackageManagerHelper implements PackageManagerHelper {
+        private final FakeDeviceState mState;
 
-        private DummyPackageManagerHelper(DummyDeviceState state) {
+        private FakePackageManagerHelper(FakeDeviceState state) {
             mState = state;
         }
 
         @Override
         public PackageInfo getPackageInfo(@NonNull String packageName, int userId) {
-            final DummyDeviceState.Package pkg = mState.select(packageName, userId);
+            final FakeDeviceState.Package pkg = mState.select(packageName, userId);
             if (pkg == null) {
                 return null;
             }
@@ -353,15 +353,15 @@
             pi.packageName = pkg.packageName;
             pi.overlayTarget = pkg.targetPackageName;
             pi.targetOverlayableName = pkg.targetOverlayableName;
-            pi.overlayCategory = "dummy-category-" + pkg.targetPackageName;
+            pi.overlayCategory = "Fake-category-" + pkg.targetPackageName;
             return pi;
         }
 
         @Override
         public boolean signaturesMatching(@NonNull String packageName1,
                 @NonNull String packageName2, int userId) {
-            final DummyDeviceState.Package pkg1 = mState.select(packageName1, userId);
-            final DummyDeviceState.Package pkg2 = mState.select(packageName2, userId);
+            final FakeDeviceState.Package pkg1 = mState.select(packageName1, userId);
+            final FakeDeviceState.Package pkg2 = mState.select(packageName2, userId);
             return pkg1 != null && pkg2 != null && pkg1.certificate.equals(pkg2.certificate);
         }
 
@@ -382,7 +382,7 @@
         @Override
         public OverlayableInfo getOverlayableForTarget(@NonNull String packageName,
                 @NonNull String targetOverlayableName, int userId) {
-            final DummyDeviceState.Package pkg = mState.select(packageName, userId);
+            final FakeDeviceState.Package pkg = mState.select(packageName, userId);
             if (pkg == null || !pkg.overlayableNames.contains(targetOverlayableName)) {
                 return null;
             }
@@ -403,7 +403,7 @@
 
         @Override
         public boolean doesTargetDefineOverlayable(String targetPackageName, int userId) {
-            final DummyDeviceState.Package pkg = mState.select(targetPackageName, userId);
+            final FakeDeviceState.Package pkg = mState.select(targetPackageName, userId);
             return pkg != null && pkg.overlayableNames.contains(targetPackageName);
         }
 
@@ -413,16 +413,16 @@
         }
     }
 
-    static class DummyIdmapDaemon extends IdmapDaemon {
-        private final DummyDeviceState mState;
+    static class FakeIdmapDaemon extends IdmapDaemon {
+        private final FakeDeviceState mState;
         private final ArrayMap<String, IdmapHeader> mIdmapFiles = new ArrayMap<>();
 
-        DummyIdmapDaemon(DummyDeviceState state) {
+        FakeIdmapDaemon(FakeDeviceState state) {
             this.mState = state;
         }
 
         private int getCrc(@NonNull final String path) {
-            final DummyDeviceState.Package pkg = mState.selectFromPath(path);
+            final FakeDeviceState.Package pkg = mState.selectFromPath(path);
             Assert.assertNotNull(pkg);
             return pkg.versionCode;
         }
@@ -486,7 +486,7 @@
         }
     }
 
-    static class DummyListener implements OverlayManagerServiceImpl.OverlayChangeListener {
+    static class FakeListener implements OverlayManagerServiceImpl.OverlayChangeListener {
         public int count;
 
         public void onOverlaysChanged(@NonNull String targetPackage, int userId) {
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java
index 146f60a..9ef7557 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java
@@ -50,55 +50,55 @@
     private OverlayManagerSettings mSettings;
 
     private static final OverlayInfo OVERLAY_A0 = new OverlayInfo(
-            "com.dummy.overlay_a",
-            "com.dummy.target",
+            "com.test.overlay_a",
+            "com.test.target",
             null,
             "some-category",
-            "/data/app/com.dummy.overlay_a-1/base.apk",
+            "/data/app/com.test.overlay_a-1/base.apk",
             STATE_DISABLED,
             0,
             0,
             true);
 
     private static final OverlayInfo OVERLAY_B0 = new OverlayInfo(
-            "com.dummy.overlay_b",
-            "com.dummy.target",
+            "com.test.overlay_b",
+            "com.test.target",
             null,
             "some-category",
-            "/data/app/com.dummy.overlay_b-1/base.apk",
+            "/data/app/com.test.overlay_b-1/base.apk",
             STATE_DISABLED,
             0,
             0,
             true);
 
     private static final OverlayInfo OVERLAY_C0 = new OverlayInfo(
-            "com.dummy.overlay_c",
-            "com.dummy.target",
+            "com.test.overlay_c",
+            "com.test.target",
             null,
             "some-category",
-            "/data/app/com.dummy.overlay_c-1/base.apk",
+            "/data/app/com.test.overlay_c-1/base.apk",
             STATE_DISABLED,
             0,
             0,
             true);
 
     private static final OverlayInfo OVERLAY_A1 = new OverlayInfo(
-            "com.dummy.overlay_a",
-            "com.dummy.target",
+            "com.test.overlay_a",
+            "com.test.target",
             null,
             "some-category",
-            "/data/app/com.dummy.overlay_a-1/base.apk",
+            "/data/app/com.test.overlay_a-1/base.apk",
             STATE_DISABLED,
             1,
             0,
             true);
 
     private static final OverlayInfo OVERLAY_B1 = new OverlayInfo(
-            "com.dummy.overlay_b",
-            "com.dummy.target",
+            "com.test.overlay_b",
+            "com.test.target",
             null,
             "some-category",
-            "/data/app/com.dummy.overlay_b-1/base.apk",
+            "/data/app/com.test.overlay_b-1/base.apk",
             STATE_DISABLED,
             1,
             0,
@@ -230,11 +230,11 @@
         assertListsAreEqual(list, OVERLAY_A0, OVERLAY_C0, OVERLAY_B0);
 
         OverlayInfo otherTarget = new OverlayInfo(
-                "com.dummy.overlay_other",
-                "com.dummy.some.other.target",
+                "com.test.overlay_other",
+                "com.test.some.other.target",
                 null,
                 "some-category",
-                "/data/app/com.dummy.overlay_other-1/base.apk",
+                "/data/app/com.test.overlay_other-1/base.apk",
                 STATE_DISABLED,
                 0,
                 0,
@@ -350,7 +350,7 @@
         ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes("utf-8"));
 
         mSettings.restore(is);
-        assertDoesNotContain(mSettings, "com.dummy.overlay", 0);
+        assertDoesNotContain(mSettings, "com.test.overlay", 0);
     }
 
     @Test
@@ -359,27 +359,27 @@
         final String xml =
                 "<?xml version='1.0' encoding='utf-8' standalone='yes'?>\n"
                 + "<overlays version='" + version + "'>\n"
-                + "<item packageName='com.dummy.overlay'\n"
+                + "<item packageName='com.test.overlay'\n"
                 + "      userId='1234'\n"
-                + "      targetPackageName='com.dummy.target'\n"
-                + "      baseCodePath='/data/app/com.dummy.overlay-1/base.apk'\n"
+                + "      targetPackageName='com.test.target'\n"
+                + "      baseCodePath='/data/app/com.test.overlay-1/base.apk'\n"
                 + "      state='" + STATE_DISABLED + "'\n"
                 + "      isEnabled='false'\n"
-                + "      category='dummy-category'\n"
+                + "      category='test-category'\n"
                 + "      isStatic='false'\n"
                 + "      priority='0' />\n"
                 + "</overlays>\n";
         ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes("utf-8"));
 
         mSettings.restore(is);
-        OverlayInfo oi = mSettings.getOverlayInfo("com.dummy.overlay", 1234);
+        OverlayInfo oi = mSettings.getOverlayInfo("com.test.overlay", 1234);
         assertNotNull(oi);
-        assertEquals("com.dummy.overlay", oi.packageName);
-        assertEquals("com.dummy.target", oi.targetPackageName);
-        assertEquals("/data/app/com.dummy.overlay-1/base.apk", oi.baseCodePath);
+        assertEquals("com.test.overlay", oi.packageName);
+        assertEquals("com.test.target", oi.targetPackageName);
+        assertEquals("/data/app/com.test.overlay-1/base.apk", oi.baseCodePath);
         assertEquals(1234, oi.userId);
         assertEquals(STATE_DISABLED, oi.state);
-        assertFalse(mSettings.getEnabled("com.dummy.overlay", 1234));
+        assertFalse(mSettings.getEnabled("com.test.overlay", 1234));
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/pm/IncrementalStatesTest.java b/services/tests/servicestests/src/com/android/server/pm/IncrementalStatesTest.java
index 62e135b..86758f1 100644
--- a/services/tests/servicestests/src/com/android/server/pm/IncrementalStatesTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/IncrementalStatesTest.java
@@ -20,7 +20,6 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-import android.content.pm.IDataLoaderStatusListener;
 import android.content.pm.PackageManager;
 import android.os.ConditionVariable;
 import android.os.incremental.IStorageHealthListener;
@@ -113,96 +112,30 @@
     }
 
     /**
-     * Test that the package is still startable when Incremental Storage is at blocked status.
+     * Test that the package becomes unstartable when health status indicate storage issues.
      */
     @Test
     public void testStartableTransition_IncrementalStorageBlocked() {
         mIncrementalStates.onStorageHealthStatusChanged(
-                IStorageHealthListener.HEALTH_STATUS_BLOCKED);
-        // Test that package is still startable
-        assertFalse(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
-        assertTrue(mIncrementalStates.isStartable());
+                IStorageHealthListener.HEALTH_STATUS_UNHEALTHY_STORAGE);
+        // Test that package is now unstartable
+        assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
+        assertFalse(mIncrementalStates.isStartable());
+        assertEquals(PackageManager.UNSTARTABLE_REASON_INSUFFICIENT_STORAGE,
+                mUnstartableReason.get());
     }
 
     /**
-     * Test that the package is still startable when Data Loader has unknown transportation issues.
-     */
-    @Test
-    public void testStartableTransition_DataLoaderTransportError() {
-        mIncrementalStates.onStreamStatusChanged(
-                IDataLoaderStatusListener.STREAM_TRANSPORT_ERROR);
-        // Test that package is still startable
-        assertFalse(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
-        assertTrue(mIncrementalStates.isStartable());
-    }
-
-    /**
-     * Test that the package becomes unstartable when Data Loader has data integrity issues.
+     * Test that the package becomes unstartable when health status indicates transport issues.
      */
     @Test
     public void testStartableTransition_DataLoaderIntegrityError() {
-        mIncrementalStates.onStreamStatusChanged(
-                IDataLoaderStatusListener.STREAM_INTEGRITY_ERROR);
-        // Test that package is now unstartable
-        assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
-        assertFalse(mIncrementalStates.isStartable());
-        assertEquals(PackageManager.UNSTARTABLE_REASON_DATALOADER_TRANSPORT,
-                mUnstartableReason.get());
-    }
-
-    /**
-     * Test that the package becomes unstartable when Data Loader has data source issues.
-     */
-    @Test
-    public void testStartableTransition_DataLoaderSourceError() {
-        mIncrementalStates.onStreamStatusChanged(
-                IDataLoaderStatusListener.STREAM_SOURCE_ERROR);
-        // Test that package is now unstartable
-        assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
-        assertFalse(mIncrementalStates.isStartable());
-        assertEquals(PackageManager.UNSTARTABLE_REASON_DATALOADER_TRANSPORT,
-                mUnstartableReason.get());
-    }
-
-    /**
-     * Test that the package becomes unstartable when Data Loader hits limited storage while
-     * Incremental storage has a pending reads.
-     */
-    @Test
-    public void testStartableTransition_DataLoaderStorageErrorWhenIncrementalStoragePending()
-            throws InterruptedException {
-        mIncrementalStates.onStreamStatusChanged(
-                IDataLoaderStatusListener.STREAM_STORAGE_ERROR);
-        // Test that package is still startable
-        assertFalse(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
-        assertTrue(mIncrementalStates.isStartable());
         mIncrementalStates.onStorageHealthStatusChanged(
-                IStorageHealthListener.HEALTH_STATUS_READS_PENDING);
+                IStorageHealthListener.HEALTH_STATUS_UNHEALTHY_TRANSPORT);
         // Test that package is now unstartable
         assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
         assertFalse(mIncrementalStates.isStartable());
-        assertEquals(PackageManager.UNSTARTABLE_REASON_DATALOADER_STORAGE,
-                mUnstartableReason.get());
-    }
-
-    /**
-     * Test that the package becomes unstartable when Data Loader hits limited storage while
-     * Incremental storage is at blocked status.
-     */
-    @Test
-    public void testStartableTransition_DataLoaderStorageErrorWhenIncrementalStorageBlocked()
-            throws InterruptedException {
-        mIncrementalStates.onStreamStatusChanged(
-                IDataLoaderStatusListener.STREAM_STORAGE_ERROR);
-        // Test that package is still startable
-        assertFalse(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
-        assertTrue(mIncrementalStates.isStartable());
-        mIncrementalStates.onStorageHealthStatusChanged(
-                IStorageHealthListener.HEALTH_STATUS_BLOCKED);
-        // Test that package is now unstartable
-        assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
-        assertFalse(mIncrementalStates.isStartable());
-        assertEquals(PackageManager.UNSTARTABLE_REASON_DATALOADER_STORAGE,
+        assertEquals(PackageManager.UNSTARTABLE_REASON_CONNECTION_ERROR,
                 mUnstartableReason.get());
     }
 
@@ -227,42 +160,18 @@
     }
 
     /**
-     * Test that the package becomes unstartable when Data Loader has data integrity issue, and it
-     * becomes startable again when Data Loader is healthy again.
+     * Test that the package becomes unstartable when health status indicates transportation issue,
+     * and it becomes startable again when health status is ok again.
      */
     @Test
     public void testStartableTransition_DataLoaderUnhealthyBackToHealthy()
             throws InterruptedException {
-        mIncrementalStates.onStreamStatusChanged(IDataLoaderStatusListener.STREAM_INTEGRITY_ERROR);
-        // Test that package is unstartable
-        assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
-        assertFalse(mIncrementalStates.isStartable());
-
-        mIncrementalStates.onStreamStatusChanged(IDataLoaderStatusListener.STREAM_HEALTHY);
-        // Test that package is now startable
-        assertTrue(mStartableCalled.block(WAIT_TIMEOUT_MILLIS));
-        assertTrue(mIncrementalStates.isStartable());
-    }
-
-    /**
-     * Test that the package becomes unstartable when both Incremental Storage and Data Loader
-     * are unhealthy, and it becomes startable again when both Incremental Storage and Data Loader
-     * are healthy again.
-     */
-    @Test
-    public void testStartableTransition_DataLoaderAndIncrementalStorageUnhealthyBackToHealthy()
-            throws InterruptedException {
         mIncrementalStates.onStorageHealthStatusChanged(
-                IStorageHealthListener.HEALTH_STATUS_UNHEALTHY);
-        mIncrementalStates.onStreamStatusChanged(IDataLoaderStatusListener.STREAM_INTEGRITY_ERROR);
+                IStorageHealthListener.HEALTH_STATUS_UNHEALTHY_TRANSPORT);
         // Test that package is unstartable
         assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
         assertFalse(mIncrementalStates.isStartable());
 
-        mIncrementalStates.onStreamStatusChanged(IDataLoaderStatusListener.STREAM_HEALTHY);
-        // Test that package is still unstartable
-        assertFalse(mStartableCalled.block(WAIT_TIMEOUT_MILLIS));
-        assertFalse(mIncrementalStates.isStartable());
         mIncrementalStates.onStorageHealthStatusChanged(IStorageHealthListener.HEALTH_STATUS_OK);
         // Test that package is now startable
         assertTrue(mStartableCalled.block(WAIT_TIMEOUT_MILLIS));
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 7579956..b190339 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -220,7 +220,7 @@
                 asHandle(currentUser));
         try {
             assertThat(mUserManager.removeUserOrSetEphemeral(user1.id)).isEqualTo(
-                    UserManagerService.REMOVE_RESULT_ERROR);
+                    UserManager.REMOVE_RESULT_ERROR);
         } finally {
             mUserManager.setUserRestriction(UserManager.DISALLOW_REMOVE_USER, /* value= */ false,
                     asHandle(currentUser));
@@ -234,7 +234,7 @@
     @Test
     public void testRemoveUserOrSetEphemeral_systemUserReturnsError() throws Exception {
         assertThat(mUserManager.removeUserOrSetEphemeral(UserHandle.USER_SYSTEM)).isEqualTo(
-                UserManagerService.REMOVE_RESULT_ERROR);
+                UserManager.REMOVE_RESULT_ERROR);
 
         assertThat(hasUser(UserHandle.USER_SYSTEM)).isTrue();
     }
@@ -244,7 +244,7 @@
     public void testRemoveUserOrSetEphemeral_invalidUserReturnsError() throws Exception {
         assertThat(hasUser(Integer.MAX_VALUE)).isFalse();
         assertThat(mUserManager.removeUserOrSetEphemeral(Integer.MAX_VALUE)).isEqualTo(
-                UserManagerService.REMOVE_RESULT_ERROR);
+                UserManager.REMOVE_RESULT_ERROR);
     }
 
     @MediumTest
@@ -256,7 +256,7 @@
         switchUser(user1.id, null, /* ignoreHandle= */ true);
 
         assertThat(mUserManager.removeUserOrSetEphemeral(user1.id)).isEqualTo(
-                UserManagerService.REMOVE_RESULT_SET_EPHEMERAL);
+                UserManager.REMOVE_RESULT_SET_EPHEMERAL);
 
         assertThat(hasUser(user1.id)).isTrue();
         assertThat(getUser(user1.id).isEphemeral()).isTrue();
@@ -277,7 +277,7 @@
         final UserInfo user1 = createUser("User 1", /* flags= */ 0);
         synchronized (mUserRemoveLock) {
             assertThat(mUserManager.removeUserOrSetEphemeral(user1.id)).isEqualTo(
-                    UserManagerService.REMOVE_RESULT_REMOVED);
+                    UserManager.REMOVE_RESULT_REMOVED);
             waitForUserRemovalLocked(user1.id);
         }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index dd85484..ad9692f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -1523,7 +1523,8 @@
             // Return error to skip unnecessary operation.
             doReturn(WindowManagerGlobal.ADD_STARTING_NOT_NEEDED).when(session).addToDisplay(
                     any() /* window */,  any() /* attrs */,
-                    anyInt() /* viewVisibility */, anyInt() /* displayId */, any() /* outFrame */,
+                    anyInt() /* viewVisibility */, anyInt() /* displayId */,
+                    any() /* requestedVisibility */, any() /* outFrame */,
                     any() /* outContentInsets */, any() /* outStableInsets */,
                     any() /* outDisplayCutout */, any() /* outInputChannel */,
                     any() /* outInsetsState */, any() /* outActiveControls */);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index 3349c6d..8292420 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -23,20 +23,24 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doCallRealMethod;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.when;
 
 import android.app.Activity;
+import android.app.ActivityManager;
 import android.app.PictureInPictureParams;
 import android.app.servertransaction.ClientTransaction;
 import android.app.servertransaction.EnterPipRequestedItem;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.IBinder;
+import android.os.PowerManager;
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
 import android.view.IDisplayWindowListener;
@@ -252,5 +256,36 @@
         assertEquals(Task.ActivityState.RESUMED, homeActivity.getState());
         assertEquals(homeActivity.app, mAtm.mInternal.getTopApp());
     }
+
+    @Test
+    public void testUpdateSleep() {
+        doCallRealMethod().when(mWm.mRoot).hasAwakeDisplay();
+        mSupervisor.mGoingToSleepWakeLock = mock(PowerManager.WakeLock.class);
+        final ActivityRecord topActivity = new ActivityBuilder(mAtm).setCreateTask(true).build();
+        topActivity.setState(Task.ActivityState.RESUMED, "test");
+
+        final Runnable assertTopNonSleeping = () -> {
+            assertFalse(mAtm.mInternal.isSleeping());
+            assertEquals(ActivityManager.PROCESS_STATE_TOP, mAtm.mInternal.getTopProcessState());
+            assertEquals(topActivity.app, mAtm.mInternal.getTopApp());
+        };
+        assertTopNonSleeping.run();
+
+        // Sleep all displays.
+        mWm.mRoot.forAllDisplays(display -> doReturn(true).when(display).shouldSleep());
+        mAtm.updateSleepIfNeededLocked();
+
+        assertEquals(Task.ActivityState.PAUSING, topActivity.getState());
+        assertTrue(mAtm.mInternal.isSleeping());
+        assertEquals(ActivityManager.PROCESS_STATE_TOP_SLEEPING,
+                mAtm.mInternal.getTopProcessState());
+        assertNull(mAtm.mInternal.getTopApp());
+
+        // Wake all displays.
+        mWm.mRoot.forAllDisplays(display -> doReturn(false).when(display).shouldSleep());
+        mAtm.updateSleepIfNeededLocked();
+
+        assertTopNonSleeping.run();
+    }
 }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index 2920c1d..5a14a24 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -522,7 +522,9 @@
         mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
         mDisplayContent.getInsetsPolicy().getInsetsForDispatch(mWindow)
                 .getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
-        mWindow.getRequestedInsetsState().getSource(ITYPE_STATUS_BAR).setVisible(false);
+        final InsetsState requestedState = new InsetsState();
+        requestedState.getSource(ITYPE_STATUS_BAR).setVisible(false);
+        mWindow.updateRequestedVisibility(requestedState);
         addWindow(mWindow);
 
         mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -544,7 +546,9 @@
         mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
         mDisplayContent.getInsetsPolicy().getInsetsForDispatch(mWindow)
                 .getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
-        mWindow.getRequestedInsetsState().getSource(ITYPE_STATUS_BAR).setVisible(false);
+        final InsetsState requestedState = new InsetsState();
+        requestedState.getSource(ITYPE_STATUS_BAR).setVisible(false);
+        mWindow.updateRequestedVisibility(requestedState);
         mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
         addWindow(mWindow);
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
index a55423a..21bdc9e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -313,8 +313,8 @@
         // App requests to hide navigation bar.
         final InsetsState requestedState = new InsetsState();
         requestedState.getSource(ITYPE_NAVIGATION_BAR).setVisible(false);
-        mAppWindow.updateRequestedInsetsState(requestedState);
-        insetsPolicy.onInsetsModified(mAppWindow, requestedState);
+        mAppWindow.updateRequestedVisibility(requestedState);
+        insetsPolicy.onInsetsModified(mAppWindow);
         assertNotNull(displayPolicy.mInputConsumer);
 
         // App still requests to hide navigation bar, but without BEHAVIOR_SHOW_BARS_BY_TOUCH.
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
index 8c02faf..d67120f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -38,7 +38,6 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
@@ -180,7 +179,7 @@
         final WindowState fullscreenApp = addWindow(TYPE_APPLICATION, "fullscreenApp");
         final InsetsState requestedState = new InsetsState();
         requestedState.getSource(ITYPE_STATUS_BAR).setVisible(false);
-        fullscreenApp.updateRequestedInsetsState(requestedState);
+        fullscreenApp.updateRequestedVisibility(requestedState);
 
         // Add a non-fullscreen dialog window.
         final WindowState dialog = addWindow(TYPE_APPLICATION, "dialog");
@@ -215,7 +214,7 @@
         final WindowState newFocusedFullscreenApp = addWindow(TYPE_APPLICATION, "newFullscreenApp");
         final InsetsState newRequestedState = new InsetsState();
         newRequestedState.getSource(ITYPE_STATUS_BAR).setVisible(true);
-        newFocusedFullscreenApp.updateRequestedInsetsState(newRequestedState);
+        newFocusedFullscreenApp.updateRequestedVisibility(newRequestedState);
         // Make sure status bar is hidden by previous insets state.
         mDisplayContent.getInsetsPolicy().updateBarControlTarget(fullscreenApp);
 
@@ -232,20 +231,28 @@
     @UseTestDisplay(addWindows = W_ACTIVITY)
     @Test
     public void testShowTransientBars_bothCanBeTransient_appGetsBothFakeControls() {
-        addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar")
-                .getControllableInsetProvider().getSource().setVisible(false);
-        addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar")
-                .getControllableInsetProvider().getSource().setVisible(false);
+        final WindowState statusBar = addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar");
+        statusBar.setHasSurface(true);
+        statusBar.getControllableInsetProvider().setServerVisible(true);
+        final WindowState navBar = addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar");
+        navBar.setHasSurface(true);
+        navBar.getControllableInsetProvider().setServerVisible(true);
 
         final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
+        doNothing().when(policy).startAnimation(anyBoolean(), any());
 
-        doAnswer(invocation -> {
-            ((InsetsState) invocation.getArgument(2)).setSourceVisible(ITYPE_STATUS_BAR, true);
-            ((InsetsState) invocation.getArgument(2)).setSourceVisible(ITYPE_NAVIGATION_BAR, true);
-            return null;
-        }).when(policy).startAnimation(anyBoolean(), any(), any());
-
+        // Make both system bars invisible.
+        final InsetsState requestedState = new InsetsState();
+        requestedState.getSource(ITYPE_STATUS_BAR).setVisible(false);
+        requestedState.getSource(ITYPE_NAVIGATION_BAR).setVisible(false);
+        mAppWindow.updateRequestedVisibility(requestedState);
         policy.updateBarControlTarget(mAppWindow);
+        waitUntilWindowAnimatorIdle();
+        assertFalse(mDisplayContent.getInsetsStateController().getRawInsetsState()
+                .getSource(ITYPE_STATUS_BAR).isVisible());
+        assertFalse(mDisplayContent.getInsetsStateController().getRawInsetsState()
+                .getSource(ITYPE_NAVIGATION_BAR).isVisible());
+
         policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR});
         waitUntilWindowAnimatorIdle();
         final InsetsSourceControl[] controls =
@@ -272,7 +279,7 @@
                 .getControllableInsetProvider().setServerVisible(true);
 
         final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
-        doNothing().when(policy).startAnimation(anyBoolean(), any(), any());
+        doNothing().when(policy).startAnimation(anyBoolean(), any());
         policy.updateBarControlTarget(mAppWindow);
         policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR});
         waitUntilWindowAnimatorIdle();
@@ -301,7 +308,7 @@
                 .getControllableInsetProvider().getSource().setVisible(false);
 
         final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
-        doNothing().when(policy).startAnimation(anyBoolean(), any(), any());
+        doNothing().when(policy).startAnimation(anyBoolean(), any());
         policy.updateBarControlTarget(mAppWindow);
         policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR});
         waitUntilWindowAnimatorIdle();
@@ -326,7 +333,8 @@
         assertTrue(state.getSource(ITYPE_STATUS_BAR).isVisible());
         assertTrue(state.getSource(ITYPE_NAVIGATION_BAR).isVisible());
 
-        policy.onInsetsModified(mAppWindow, state);
+        mAppWindow.updateRequestedVisibility(state);
+        policy.onInsetsModified(mAppWindow);
         waitUntilWindowAnimatorIdle();
 
         controls = mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow);
@@ -348,7 +356,7 @@
         final WindowState app2 = addWindow(TYPE_APPLICATION, "app");
 
         final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
-        doNothing().when(policy).startAnimation(anyBoolean(), any(), any());
+        doNothing().when(policy).startAnimation(anyBoolean(), any());
         policy.updateBarControlTarget(app);
         policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR});
         final InsetsSourceControl[] controls =
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java
index a0fa936..9830631 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java
@@ -205,7 +205,8 @@
         mProvider.updateControlForTarget(target, false /* force */);
         InsetsState state = new InsetsState();
         state.getSource(ITYPE_STATUS_BAR).setVisible(false);
-        mProvider.onInsetsModified(target, state.getSource(ITYPE_STATUS_BAR));
+        target.updateRequestedVisibility(state);
+        mProvider.updateClientVisibility(target);
         assertFalse(mSource.isVisible());
     }
 
@@ -217,7 +218,8 @@
         mProvider.setWindow(statusBar, null, null);
         InsetsState state = new InsetsState();
         state.getSource(ITYPE_STATUS_BAR).setVisible(false);
-        mProvider.onInsetsModified(target, state.getSource(ITYPE_STATUS_BAR));
+        target.updateRequestedVisibility(state);
+        mProvider.updateClientVisibility(target);
         assertTrue(mSource.isVisible());
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index e2cd8a9..c14df67 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -189,8 +189,8 @@
         getController().onImeControlTargetChanged(mDisplayContent.mInputMethodInputTarget);
         final InsetsState requestedState = new InsetsState();
         requestedState.getSource(ITYPE_IME).setVisible(true);
-        mDisplayContent.mInputMethodInputTarget.updateRequestedInsetsState(requestedState);
-        getController().onInsetsModified(mDisplayContent.mInputMethodInputTarget, requestedState);
+        mDisplayContent.mInputMethodInputTarget.updateRequestedVisibility(requestedState);
+        getController().onInsetsModified(mDisplayContent.mInputMethodInputTarget);
 
         // Send our spy window (app) into the system so that we can detect the invocation.
         final WindowState win = createWindow(null, TYPE_APPLICATION, "app");
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
index ea12233..db1c12f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
@@ -22,7 +22,7 @@
 import android.os.RemoteException;
 import android.util.MergedConfiguration;
 import android.view.DragEvent;
-import android.view.IScrollCaptureController;
+import android.view.IScrollCaptureCallbacks;
 import android.view.IWindow;
 import android.view.InsetsSourceControl;
 import android.view.InsetsState;
@@ -107,7 +107,7 @@
     }
 
     @Override
-    public void requestScrollCapture(IScrollCaptureController controller) throws RemoteException {
+    public void requestScrollCapture(IScrollCaptureCallbacks callbacks) throws RemoteException {
     }
 
     @Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index c18043f..19bed48 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -71,7 +71,7 @@
 import android.platform.test.annotations.Presubmit;
 import android.util.Size;
 import android.view.DisplayCutout;
-import android.view.InsetsSource;
+import android.view.InsetsState;
 import android.view.SurfaceControl;
 import android.view.WindowManager;
 
@@ -426,10 +426,11 @@
                 .setWindow(statusBar, null /* frameProvider */, null /* imeFrameProvider */);
         mDisplayContent.getInsetsStateController().onBarControlTargetChanged(
                 app, null /* fakeTopControlling */, app, null /* fakeNavControlling */);
-        final InsetsSource source = new InsetsSource(ITYPE_STATUS_BAR);
-        source.setVisible(false);
+        final InsetsState state = new InsetsState();
+        state.getSource(ITYPE_STATUS_BAR).setVisible(false);
+        app.updateRequestedVisibility(state);
         mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_STATUS_BAR)
-                .onInsetsModified(app, source);
+                .updateClientVisibility(app);
         waitUntilHandlersIdle();
         assertFalse(statusBar.isVisible());
     }
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 9f16543..a85eb53 100755
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -1683,7 +1683,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public void enterBackgroundAudioProcessing() {
         if (mState != STATE_ACTIVE && mState != STATE_RINGING) {
             throw new IllegalStateException("Call must be active or ringing");
@@ -1704,7 +1703,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public void exitBackgroundAudioProcessing(boolean shouldRing) {
         if (mState != STATE_AUDIO_PROCESSING) {
             throw new IllegalStateException("Call must in the audio processing state");
diff --git a/telecomm/java/android/telecom/CallScreeningService.java b/telecomm/java/android/telecom/CallScreeningService.java
index 49f1831..7988b03 100644
--- a/telecomm/java/android/telecom/CallScreeningService.java
+++ b/telecomm/java/android/telecom/CallScreeningService.java
@@ -21,7 +21,6 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.app.Service;
 import android.content.ComponentName;
 import android.content.Intent;
@@ -323,7 +322,6 @@
              * @hide
              */
             @SystemApi
-            @TestApi
             @RequiresPermission(Manifest.permission.CAPTURE_AUDIO_OUTPUT)
             public @NonNull Builder setShouldScreenCallViaAudioProcessing(
                     boolean shouldScreenCallViaAudioProcessing) {
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index 39c3ff9..dc2fb94 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -24,7 +24,6 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.SystemClock;
@@ -137,7 +136,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public final @NonNull String getTelecomCallId() {
         return mTelecomCallId;
     }
@@ -609,7 +607,6 @@
      * @return The primary connection.
      * @hide
      */
-    @TestApi
     @SystemApi
     public Connection getPrimaryConnection() {
         if (mUnmodifiableChildConnections == null || mUnmodifiableChildConnections.isEmpty()) {
@@ -1012,7 +1009,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(MODIFY_PHONE_STATE)
     public void setConferenceState(boolean isConference) {
         mIsMultiparty = isConference;
@@ -1067,7 +1063,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(MODIFY_PHONE_STATE)
     public final void setAddress(@NonNull Uri address,
             @TelecomManager.Presentation int presentation) {
@@ -1155,7 +1150,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public final void setCallerDisplayName(@NonNull String callerDisplayName,
             @TelecomManager.Presentation int presentation) {
         Log.d(this, "setCallerDisplayName %s", callerDisplayName);
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
old mode 100755
new mode 100644
index 00b7116..bbf34df
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -25,7 +25,6 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.app.Notification;
 import android.bluetooth.BluetoothDevice;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -307,7 +306,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000;
 
     /**
@@ -345,7 +343,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int CAPABILITY_CONFERENCE_HAS_NO_CHILDREN = 0x00200000;
 
     /**
@@ -417,7 +414,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 1<<0;
 
     /**
@@ -428,7 +424,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int PROPERTY_GENERIC_CONFERENCE = 1<<1;
 
     /**
@@ -480,7 +475,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int PROPERTY_IS_DOWNGRADED_CONFERENCE = 1<<6;
 
     /**
@@ -524,7 +518,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int PROPERTY_REMOTELY_HOSTED = 1 << 11;
 
     /**
@@ -702,7 +695,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final String EXTRA_DISABLE_ADD_CALL =
             "android.telecom.extra.DISABLE_ADD_CALL";
 
@@ -2054,7 +2046,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public final @Nullable String getTelecomCallId() {
         return mTelecomCallId;
     }
@@ -2171,7 +2162,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public final @IntRange(from = 0) long getConnectTimeMillis() {
         return mConnectTimeMillis;
     }
@@ -2196,7 +2186,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public final @ElapsedRealtimeLong long getConnectionStartElapsedRealtimeMillis() {
         return mConnectElapsedTimeMillis;
     }
@@ -2279,7 +2268,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public void setTelecomCallId(@NonNull String callId) {
         mTelecomCallId = callId;
     }
@@ -2628,7 +2616,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(MODIFY_PHONE_STATE)
     public final void setConnectTimeMillis(@IntRange(from = 0) long connectTimeMillis) {
         mConnectTimeMillis = connectTimeMillis;
@@ -2651,7 +2638,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(MODIFY_PHONE_STATE)
     public final void setConnectionStartElapsedRealtimeMillis(
             @ElapsedRealtimeLong long connectElapsedTimeMillis) {
@@ -2722,7 +2708,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public final void resetConnectionTime() {
         for (Listener l : mListeners) {
             l.onConnectionTimeReset(this);
@@ -3505,7 +3490,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public void setPhoneAccountHandle(@NonNull PhoneAccountHandle phoneAccountHandle) {
         if (mPhoneAccountHandle != phoneAccountHandle) {
             mPhoneAccountHandle = phoneAccountHandle;
@@ -3524,7 +3508,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public @Nullable PhoneAccountHandle getPhoneAccountHandle() {
         return mPhoneAccountHandle;
     }
@@ -3590,7 +3573,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public void setCallDirection(@Call.Details.CallDirection int callDirection) {
         mCallDirection = callDirection;
     }
diff --git a/telecomm/java/android/telecom/ConnectionRequest.java b/telecomm/java/android/telecom/ConnectionRequest.java
index 6d7ceca..b73ef9b 100644
--- a/telecomm/java/android/telecom/ConnectionRequest.java
+++ b/telecomm/java/android/telecom/ConnectionRequest.java
@@ -327,7 +327,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public @Nullable String getTelecomCallId() {
         return mTelecomCallId;
     }
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index 866e171..5024ae2 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -21,7 +21,6 @@
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.content.Intent;
 import android.graphics.drawable.Icon;
 import android.net.Uri;
@@ -635,7 +634,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         @RequiresPermission(MODIFY_PHONE_STATE)
         public @NonNull Builder setGroupId(@NonNull String groupId) {
             if (groupId != null) {
diff --git a/telecomm/java/android/telecom/PhoneAccountSuggestionService.java b/telecomm/java/android/telecom/PhoneAccountSuggestionService.java
index ba3822c..8a91b9e 100644
--- a/telecomm/java/android/telecom/PhoneAccountSuggestionService.java
+++ b/telecomm/java/android/telecom/PhoneAccountSuggestionService.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.app.Service;
 import android.content.Intent;
 import android.os.IBinder;
@@ -57,7 +56,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public class PhoneAccountSuggestionService extends Service {
     /**
      * The {@link Intent} that must be declared in the {@code intent-filter} element of the
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index f1deec6..82da447 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -25,7 +25,6 @@
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
-import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
@@ -693,7 +692,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final int TTY_MODE_OFF = 0;
 
@@ -703,7 +701,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final int TTY_MODE_FULL = 1;
 
@@ -714,7 +711,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final int TTY_MODE_HCO = 2;
 
@@ -725,7 +721,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final int TTY_MODE_VCO = 3;
 
@@ -736,7 +731,6 @@
      * TTY mode.
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final String ACTION_CURRENT_TTY_MODE_CHANGED =
             "android.telecom.action.CURRENT_TTY_MODE_CHANGED";
@@ -759,7 +753,6 @@
      * plugged into the device.
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final String EXTRA_CURRENT_TTY_MODE =
             "android.telecom.extra.CURRENT_TTY_MODE";
@@ -771,7 +764,6 @@
      * preferred TTY mode.
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final String ACTION_TTY_PREFERRED_MODE_CHANGED =
             "android.telecom.action.TTY_PREFERRED_MODE_CHANGED";
@@ -790,7 +782,6 @@
      * </ul>
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final String EXTRA_TTY_PREFERRED_MODE =
             "android.telecom.extra.TTY_PREFERRED_MODE";
@@ -1045,7 +1036,6 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
-    @TestApi
     @SystemApi
     public void setUserSelectedOutgoingPhoneAccount(@Nullable PhoneAccountHandle accountHandle) {
         try {
@@ -1219,7 +1209,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(READ_PRIVILEGED_PHONE_STATE)
     public @NonNull List<PhoneAccountHandle> getCallCapablePhoneAccounts(
             boolean includeDisabledAccounts) {
@@ -1453,7 +1442,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(READ_PRIVILEGED_PHONE_STATE)
     public @Nullable String getDefaultDialerPackage(@NonNull UserHandle userHandle) {
         try {
@@ -1677,7 +1665,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(anyOf = {
             READ_PRIVILEGED_PHONE_STATE,
             android.Manifest.permission.READ_PHONE_STATE
@@ -1835,7 +1822,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(READ_PRIVILEGED_PHONE_STATE)
     public @TtyMode int getCurrentTtyMode() {
         try {
@@ -2249,7 +2235,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @NonNull
     public Intent createLaunchEmergencyDialerIntent(@Nullable String number) {
         ITelecomService service = getTelecomService();
@@ -2402,7 +2387,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public boolean isInEmergencyCall() {
         try {
diff --git a/telephony/api/system-current.txt b/telephony/api/system-current.txt
index a67273c..228f98e 100644
--- a/telephony/api/system-current.txt
+++ b/telephony/api/system-current.txt
@@ -477,6 +477,10 @@
     field public static final int ROAMING_TYPE_UNKNOWN = 1; // 0x1
   }
 
+  public class SignalStrength implements android.os.Parcelable {
+    ctor public SignalStrength(@NonNull android.telephony.SignalStrength);
+  }
+
   public final class SmsCbCmasInfo implements android.os.Parcelable {
     ctor public SmsCbCmasInfo(int, int, int, int, int, int);
     method public int describeContents();
diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java
index 39a7543..d012971 100644
--- a/telephony/java/android/telephony/AccessNetworkConstants.java
+++ b/telephony/java/android/telephony/AccessNetworkConstants.java
@@ -18,7 +18,6 @@
 
 import android.annotation.IntDef;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.hardware.radio.V1_1.GeranBands;
 import android.hardware.radio.V1_5.AccessNetwork;
 import android.hardware.radio.V1_5.EutranBands;
@@ -49,7 +48,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int TRANSPORT_TYPE_INVALID = -1;
 
     /**
@@ -438,7 +436,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public static final int FREQUENCY_RANGE_GROUP_UNKNOWN = 0;
 
         /**
@@ -447,7 +444,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public static final int FREQUENCY_RANGE_GROUP_1 = 1;
 
         /**
@@ -456,7 +452,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public static final int FREQUENCY_RANGE_GROUP_2 = 2;
 
         /**
@@ -481,7 +476,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public static @FrequencyRangeGroup int getFrequencyRangeGroup(@NgranBand int band) {
             switch (band) {
                 case BAND_1:
diff --git a/telephony/java/android/telephony/BarringInfo.java b/telephony/java/android/telephony/BarringInfo.java
index 92423a2..e9698ad 100644
--- a/telephony/java/android/telephony/BarringInfo.java
+++ b/telephony/java/android/telephony/BarringInfo.java
@@ -252,7 +252,6 @@
     private SparseArray<BarringServiceInfo> mBarringServiceInfos;
 
     /** @hide */
-    @TestApi
     @SystemApi
     public BarringInfo() {
         mBarringServiceInfos = new SparseArray<>();
diff --git a/telephony/java/android/telephony/CallQuality.java b/telephony/java/android/telephony/CallQuality.java
index 1effeb7..fa70c33 100644
--- a/telephony/java/android/telephony/CallQuality.java
+++ b/telephony/java/android/telephony/CallQuality.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -41,7 +40,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class CallQuality implements Parcelable {
 
     // Constants representing the call quality level (see #CallQuality);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
old mode 100755
new mode 100644
index 8261b53..3d33b95
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -23,7 +23,6 @@
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
-import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
@@ -4603,7 +4602,6 @@
      */
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
     @SystemApi
-    @TestApi
     public void overrideConfig(int subscriptionId, @Nullable PersistableBundle overrideValues) {
         overrideConfig(subscriptionId, overrideValues, false);
     }
diff --git a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java
index e91d6fc9..597fe8f 100644
--- a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java
+++ b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -31,7 +30,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class DataSpecificRegistrationInfo implements Parcelable {
     /**
      * @hide
diff --git a/telephony/java/android/telephony/LteVopsSupportInfo.java b/telephony/java/android/telephony/LteVopsSupportInfo.java
index 7994c1b..83e41bf 100644
--- a/telephony/java/android/telephony/LteVopsSupportInfo.java
+++ b/telephony/java/android/telephony/LteVopsSupportInfo.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -33,7 +32,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class LteVopsSupportInfo implements Parcelable {
 
     /**@hide*/
diff --git a/telephony/java/android/telephony/ModemActivityInfo.java b/telephony/java/android/telephony/ModemActivityInfo.java
index 881d85c..e164c4b 100644
--- a/telephony/java/android/telephony/ModemActivityInfo.java
+++ b/telephony/java/android/telephony/ModemActivityInfo.java
@@ -37,7 +37,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class ModemActivityInfo implements Parcelable {
     private static final int TX_POWER_LEVELS = 5;
 
diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java
index aee1e84..9223842 100644
--- a/telephony/java/android/telephony/NetworkRegistrationInfo.java
+++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.AccessNetworkConstants.TransportType;
@@ -71,37 +70,37 @@
      * Not registered. The device is not currently searching a new operator to register.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public static final int REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING = 0;
     /**
      * Registered on home network.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public static final int REGISTRATION_STATE_HOME = 1;
     /**
      * Not registered. The device is currently searching a new operator to register.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public static final int REGISTRATION_STATE_NOT_REGISTERED_SEARCHING = 2;
     /**
      * Registration denied.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public static final int REGISTRATION_STATE_DENIED = 3;
     /**
      * Registration state is unknown.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public static final int REGISTRATION_STATE_UNKNOWN = 4;
     /**
      * Registered on roaming network.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public static final int REGISTRATION_STATE_ROAMING = 5;
 
     /** @hide */
@@ -386,7 +385,7 @@
      *
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public @RegistrationState int getRegistrationState() {
         return mRegistrationState;
     }
@@ -451,7 +450,7 @@
      * @return the current network roaming type.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public @ServiceState.RoamingType int getRoamingType() {
         return mRoamingType;
     }
@@ -460,7 +459,7 @@
      * @return Whether emergency is enabled.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public boolean isEmergencyEnabled() { return mEmergencyOnly; }
 
     /**
@@ -498,7 +497,7 @@
      * 10.5.3.6 for UMTS, 3GPP TS 24.301 9.9.3.9 for LTE, and 3GPP2 A.S0001 6.2.2.44 for CDMA
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public int getRejectCause() {
         return mRejectCause;
     }
@@ -545,7 +544,7 @@
      * @hide
      */
     @Nullable
-    @SystemApi @TestApi
+    @SystemApi
     public DataSpecificRegistrationInfo getDataSpecificInfo() {
         return mDataSpecificInfo;
     }
@@ -680,7 +679,7 @@
      * @hide
      */
     @Override
-    @SystemApi @TestApi
+    @SystemApi
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(mDomain);
         dest.writeInt(mTransportType);
@@ -772,7 +771,7 @@
      * </code></pre>
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public static final class Builder {
         @Domain
         private int mDomain;
@@ -877,7 +876,7 @@
          * @return The same instance of the builder.
          * @hide
          */
-        @SystemApi @TestApi
+        @SystemApi
         public @NonNull Builder setEmergencyOnly(boolean emergencyOnly) {
             mEmergencyOnly = emergencyOnly;
             return this;
@@ -891,7 +890,7 @@
          * @return The same instance of the builder.
          * @hide
          */
-        @SystemApi @TestApi
+        @SystemApi
         public @NonNull Builder setAvailableServices(
                 @NonNull @ServiceType List<Integer> availableServices) {
             mAvailableServices = availableServices;
@@ -906,7 +905,7 @@
          * @return The same instance of the builder.
          * @hide
          */
-        @SystemApi @TestApi
+        @SystemApi
         public @NonNull Builder setCellIdentity(@Nullable CellIdentity cellIdentity) {
             mCellIdentity = cellIdentity;
             return this;
@@ -929,7 +928,7 @@
          * @return the NetworkRegistrationInfo object.
          * @hide
          */
-        @SystemApi @TestApi
+        @SystemApi
         public @NonNull NetworkRegistrationInfo build() {
             return new NetworkRegistrationInfo(mDomain, mTransportType, mRegistrationState,
                     mAccessNetworkTechnology, mRejectCause, mEmergencyOnly, mAvailableServices,
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index ec99408..58e368b 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -2239,7 +2239,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static boolean isVoiceMailNumber(@NonNull Context context, int subId,
             @Nullable String number) {
         String vmNumber, mdn;
@@ -2728,7 +2727,6 @@
      * @return true if number contains @
      */
     @SystemApi
-    @TestApi
     public static boolean isUriNumber(@Nullable String number) {
         // Note we allow either "@" or "%40" to indicate a URI, in case
         // the passed-in string is URI-escaped.  (Neither "@" nor "%40"
@@ -2747,7 +2745,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static @NonNull String getUsernameFromUriNumber(@NonNull String number) {
         // The delimiter between username and domain name can be
         // either "@" or "%40" (the URI-escaped equivalent.)
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index 1376cdd..4a0f007 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -18,6 +18,7 @@
 
 import android.annotation.ElapsedRealtimeLong;
 import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Build;
 import android.os.Bundle;
@@ -287,12 +288,12 @@
     }
 
     /**
-     * Copy constructors
+     * This constructor is used to create a copy of an existing SignalStrength object.
      *
      * @param s Source SignalStrength
-     *
      * @hide
      */
+    @SystemApi
     public SignalStrength(@NonNull SignalStrength s) {
         copyFrom(s);
     }
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index a71a965..2e51ef1 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -32,7 +32,6 @@
 import android.annotation.SuppressAutoDoc;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
-import android.annotation.TestApi;
 import android.app.PendingIntent;
 import android.app.PropertyInvalidatedCache;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -279,7 +278,6 @@
      */
     @NonNull
     @SystemApi
-    @TestApi
     public static final Uri WFC_ENABLED_CONTENT_URI = Uri.withAppendedPath(CONTENT_URI, "wfc");
 
     /**
@@ -299,7 +297,6 @@
      */
     @NonNull
     @SystemApi
-    @TestApi
     public static final Uri ADVANCED_CALLING_ENABLED_CONTENT_URI = Uri.withAppendedPath(
             CONTENT_URI, "advanced_calling");
 
@@ -318,7 +315,6 @@
      */
     @NonNull
     @SystemApi
-    @TestApi
     public static final Uri WFC_MODE_CONTENT_URI = Uri.withAppendedPath(CONTENT_URI, "wfc_mode");
 
     /**
@@ -336,7 +332,6 @@
      */
     @NonNull
     @SystemApi
-    @TestApi
     public static final Uri WFC_ROAMING_MODE_CONTENT_URI = Uri.withAppendedPath(
             CONTENT_URI, "wfc_roaming_mode");
 
@@ -356,7 +351,6 @@
      */
     @NonNull
     @SystemApi
-    @TestApi
     public static final Uri VT_ENABLED_CONTENT_URI = Uri.withAppendedPath(
             CONTENT_URI, "vt_enabled");
 
@@ -375,7 +369,6 @@
      */
     @NonNull
     @SystemApi
-    @TestApi
     public static final Uri WFC_ROAMING_ENABLED_CONTENT_URI = Uri.withAppendedPath(
             CONTENT_URI, "wfc_roaming_enabled");
 
@@ -1966,7 +1959,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
     public void setDefaultVoiceSubscriptionId(int subscriptionId) {
         if (VDBG) logd("setDefaultVoiceSubId sub id = " + subscriptionId);
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index a202644..9b4d31a 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -8357,13 +8357,13 @@
     /**
      * Values used to return status for hasCarrierPrivileges call.
      */
-    /** @hide */ @SystemApi @TestApi
+    /** @hide */ @SystemApi
     public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1;
-    /** @hide */ @SystemApi @TestApi
+    /** @hide */ @SystemApi
     public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0;
-    /** @hide */ @SystemApi @TestApi
+    /** @hide */ @SystemApi
     public static final int CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED = -1;
-    /** @hide */ @SystemApi @TestApi
+    /** @hide */ @SystemApi
     public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2;
 
     /**
@@ -8565,7 +8565,6 @@
 
     /** @hide */
     @SystemApi
-    @TestApi
     @SuppressLint("Doclava125")
     public int checkCarrierPrivilegesForPackage(String pkgName) {
         try {
@@ -8598,7 +8597,6 @@
 
     /** @hide */
     @SystemApi
-    @TestApi
     public List<String> getCarrierPackageNamesForIntent(Intent intent) {
         return getCarrierPackageNamesForIntentAndPhone(intent, getPhoneId());
     }
@@ -10100,7 +10098,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
     public @Nullable ComponentName getAndUpdateDefaultRespondViaMessageApplication() {
         return SmsApplication.getDefaultRespondViaMessageApplication(mContext, true);
@@ -10113,7 +10110,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
     public @Nullable ComponentName getDefaultRespondViaMessageApplication() {
         return SmsApplication.getDefaultRespondViaMessageApplication(mContext, false);
@@ -11861,7 +11857,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     public static final int INVALID_EMERGENCY_NUMBER_DB_VERSION = -1;
 
@@ -11901,7 +11896,6 @@
      */
     @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
     @SystemApi
-    @TestApi
     public void updateOtaEmergencyNumberDbFilePath(
             @NonNull ParcelFileDescriptor otaParcelFileDescriptor) {
         try {
@@ -11927,7 +11921,6 @@
      */
     @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
     @SystemApi
-    @TestApi
     public void resetOtaEmergencyNumberDbFilePath() {
         try {
             ITelephony telephony = getITelephony();
@@ -12149,7 +12142,6 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public int getEmergencyNumberDbVersion() {
@@ -12877,7 +12869,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void setSystemSelectionChannels(@NonNull List<RadioAccessSpecifier> specifiers,
             @NonNull @CallbackExecutor Executor executor,
@@ -12895,7 +12886,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void setSystemSelectionChannels(@NonNull List<RadioAccessSpecifier> specifiers) {
         Objects.requireNonNull(specifiers, "Specifiers must not be null.");
@@ -13307,7 +13297,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL = 1;
 
     /**
@@ -13322,7 +13311,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public static final int MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED = 2;
 
     /**
@@ -13346,7 +13334,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void setMobileDataPolicyEnabledStatus(@MobileDataPolicy int policy, boolean enabled) {
         try {
@@ -13370,7 +13357,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public boolean isMobileDataPolicyEnabled(@MobileDataPolicy int policy) {
         try {
diff --git a/telephony/java/android/telephony/ims/ImsCallForwardInfo.java b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
index d53a2e6..3f9c8d2 100644
--- a/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
+++ b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
@@ -19,7 +19,6 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -33,7 +32,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class ImsCallForwardInfo implements Parcelable {
 
     /**
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index f31fcf4..47a0ab6 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -48,7 +48,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class ImsCallProfile implements Parcelable {
     private static final String TAG = "ImsCallProfile";
 
diff --git a/telephony/java/android/telephony/ims/ImsCallSessionListener.java b/telephony/java/android/telephony/ims/ImsCallSessionListener.java
index d21a051..2fdd195 100644
--- a/telephony/java/android/telephony/ims/ImsCallSessionListener.java
+++ b/telephony/java/android/telephony/ims/ImsCallSessionListener.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.RemoteException;
 import android.telephony.Annotation;
 import android.telephony.CallQuality;
@@ -40,7 +39,6 @@
 // TODO: APIs in here do not conform to API guidelines yet. This can be changed if
 // ImsCallSessionListenerConverter is also changed.
 @SystemApi
-@TestApi
 public class ImsCallSessionListener {
 
     private final IImsCallSessionListener mListener;
diff --git a/telephony/java/android/telephony/ims/ImsConferenceState.java b/telephony/java/android/telephony/ims/ImsConferenceState.java
index 9bf2f44..1fa5f52 100644
--- a/telephony/java/android/telephony/ims/ImsConferenceState.java
+++ b/telephony/java/android/telephony/ims/ImsConferenceState.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -38,7 +37,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class ImsConferenceState implements Parcelable {
     private static final String TAG = "ImsConferenceState";
     /**
diff --git a/telephony/java/android/telephony/ims/ImsException.java b/telephony/java/android/telephony/ims/ImsException.java
index 1c3d58d..50fb828 100644
--- a/telephony/java/android/telephony/ims/ImsException.java
+++ b/telephony/java/android/telephony/ims/ImsException.java
@@ -19,7 +19,6 @@
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.content.pm.PackageManager;
 import android.telephony.SubscriptionManager;
 import android.text.TextUtils;
@@ -83,7 +82,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public ImsException(@Nullable String message) {
         super(getMessage(message, CODE_ERROR_UNSPECIFIED));
     }
@@ -94,7 +92,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public ImsException(@Nullable String message, @ImsErrorCode int code) {
         super(getMessage(message, code));
         mCode = code;
@@ -108,7 +105,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public ImsException(@Nullable String message, @ImsErrorCode  int code,
             @Nullable Throwable cause) {
         super(getMessage(message, code), cause);
diff --git a/telephony/java/android/telephony/ims/ImsExternalCallState.java b/telephony/java/android/telephony/ims/ImsExternalCallState.java
index 7d73165..fdf636c 100644
--- a/telephony/java/android/telephony/ims/ImsExternalCallState.java
+++ b/telephony/java/android/telephony/ims/ImsExternalCallState.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -35,7 +34,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class ImsExternalCallState implements Parcelable {
 
     private static final String TAG = "ImsExternalCallState";
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index 3a0e49e..76c1faf 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -25,7 +25,6 @@
 import android.annotation.SuppressAutoDoc;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Binder;
 import android.os.RemoteException;
 import android.os.ServiceSpecificException;
@@ -97,7 +96,7 @@
      */
     // Do not add to this class, add to RegistrationManager.RegistrationCallback instead.
     @Deprecated
-    @SystemApi @TestApi
+    @SystemApi
     public static class RegistrationCallback extends RegistrationManager.RegistrationCallback {
 
         /**
@@ -231,7 +230,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @Deprecated
     @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
     @RequiresPermission(anyOf = {
@@ -280,7 +278,7 @@
      * @hide
      */
     @Deprecated
-    @SystemApi @TestApi
+    @SystemApi
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void registerImsRegistrationCallback(@NonNull @CallbackExecutor Executor executor,
             @NonNull RegistrationCallback c) throws ImsException {
@@ -366,7 +364,7 @@
      * @hide
      */
     @Deprecated
-    @SystemApi @TestApi
+    @SystemApi
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void unregisterImsRegistrationCallback(@NonNull RegistrationCallback c) {
         if (c == null) {
@@ -422,7 +420,7 @@
      * @hide
      */
     @Override
-    @SystemApi @TestApi
+    @SystemApi
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void getRegistrationState(@NonNull @CallbackExecutor Executor executor,
             @NonNull @ImsRegistrationState Consumer<Integer> stateCallback) {
@@ -681,7 +679,7 @@
      * @hide
      */
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
-    @SystemApi @TestApi
+    @SystemApi
     public void setAdvancedCallingSettingEnabled(boolean isEnabled) {
         ITelephony iTelephony = getITelephony();
         if (iTelephony == null) {
@@ -725,7 +723,7 @@
      * @hide
      */
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
-    @SystemApi @TestApi
+    @SystemApi
     public boolean isCapable(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
             @ImsRegistrationImplBase.ImsRegistrationTech int imsRegTech) {
         ITelephony iTelephony = getITelephony();
@@ -758,7 +756,7 @@
      *         otherwise.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public boolean isAvailable(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
             @ImsRegistrationImplBase.ImsRegistrationTech int imsRegTech) {
@@ -790,7 +788,7 @@
      * available.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void isSupported(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
             @AccessNetworkConstants.TransportType int transportType,
@@ -879,7 +877,7 @@
      * @see #isVtSettingEnabled()
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
     public void setVtSettingEnabled(boolean isEnabled) {
         ITelephony iTelephony = getITelephony();
@@ -954,7 +952,7 @@
      * @see #isVoWiFiSettingEnabled()
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
     public void setVoWiFiSettingEnabled(boolean isEnabled) {
         ITelephony iTelephony = getITelephony();
@@ -1032,7 +1030,7 @@
      * @see #isVoWiFiRoamingSettingEnabled()
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
     public void setVoWiFiRoamingSettingEnabled(boolean isEnabled) {
         ITelephony iTelephony = getITelephony();
@@ -1069,7 +1067,7 @@
      * @see #setVoWiFiSettingEnabled(boolean)
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
     public void setVoWiFiNonPersistent(boolean isCapable, int mode) {
         ITelephony iTelephony = getITelephony();
@@ -1152,7 +1150,7 @@
      * @see #getVoWiFiModeSetting()
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
     public void setVoWiFiModeSetting(@WiFiCallingMode int mode) {
         ITelephony iTelephony = getITelephony();
@@ -1188,7 +1186,7 @@
      * @see #setVoWiFiRoamingSettingEnabled(boolean)
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public @WiFiCallingMode int getVoWiFiRoamingModeSetting() {
         ITelephony iTelephony = getITelephony();
@@ -1224,7 +1222,7 @@
      * @see #getVoWiFiRoamingModeSetting()
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
     public void setVoWiFiRoamingModeSetting(@WiFiCallingMode int mode) {
         ITelephony iTelephony = getITelephony();
@@ -1258,7 +1256,7 @@
      * @param isEnabled if true RTT should be enabled during calls made on this subscription.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
     public void setRttCapabilitySetting(boolean isEnabled) {
         ITelephony iTelephony = getITelephony();
@@ -1338,7 +1336,7 @@
      * the IMS service is not available.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void getFeatureState(@NonNull @CallbackExecutor Executor executor,
             @NonNull @ImsFeature.ImsState Consumer<Integer> callback) throws ImsException {
diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java
index 90a6de7..c806d5c 100644
--- a/telephony/java/android/telephony/ims/ImsService.java
+++ b/telephony/java/android/telephony/ims/ImsService.java
@@ -19,7 +19,6 @@
 import android.annotation.LongDef;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.app.Service;
 import android.content.Intent;
 import android.os.IBinder;
@@ -101,7 +100,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public class ImsService extends Service {
 
     private static final String LOG_TAG = "ImsService";
@@ -558,4 +556,4 @@
         result.append("}");
         return result.toString();
     }
-}
\ No newline at end of file
+}
diff --git a/telephony/java/android/telephony/ims/ImsSsData.java b/telephony/java/android/telephony/ims/ImsSsData.java
index 70bf0c5..fb8e5d3 100644
--- a/telephony/java/android/telephony/ims/ImsSsData.java
+++ b/telephony/java/android/telephony/ims/ImsSsData.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -37,7 +36,6 @@
  * {@hide}
  */
 @SystemApi
-@TestApi
 public final class ImsSsData implements Parcelable {
 
     private static final String TAG = ImsSsData.class.getCanonicalName();
diff --git a/telephony/java/android/telephony/ims/ImsSsInfo.java b/telephony/java/android/telephony/ims/ImsSsInfo.java
index 9cce95f..27b56b8 100644
--- a/telephony/java/android/telephony/ims/ImsSsInfo.java
+++ b/telephony/java/android/telephony/ims/ImsSsInfo.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -38,7 +37,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class ImsSsInfo implements Parcelable {
 
     /**@hide*/
diff --git a/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
index b70fd64..131cb1a 100644
--- a/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
+++ b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -30,7 +29,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class ImsStreamMediaProfile implements Parcelable {
     private static final String TAG = "ImsStreamMediaProfile";
 
diff --git a/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java b/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java
index f67f68e..1630368 100644
--- a/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java
+++ b/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java
@@ -19,7 +19,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -32,7 +31,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class ImsSuppServiceNotification implements Parcelable {
     private static final String TAG = "ImsSuppServiceNotification";
 
diff --git a/telephony/java/android/telephony/ims/ImsUtListener.java b/telephony/java/android/telephony/ims/ImsUtListener.java
index 460a032..baa0576 100644
--- a/telephony/java/android/telephony/ims/ImsUtListener.java
+++ b/telephony/java/android/telephony/ims/ImsUtListener.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.telephony.ims.stub.ImsUtImplBase;
@@ -34,7 +33,6 @@
 // DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
 // will break other implementations of ImsUt maintained by other ImsServices.
 @SystemApi
-@TestApi
 public class ImsUtListener {
 
     /**
diff --git a/telephony/java/android/telephony/ims/ImsVideoCallProvider.java b/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
index 569c6d5..2fca409 100644
--- a/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
+++ b/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
@@ -17,14 +17,12 @@
 package android.telephony.ims;
 
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
-import android.telecom.Connection;
 import android.telecom.VideoProfile;
 import android.telecom.VideoProfile.CameraCapabilities;
 import android.view.Surface;
@@ -37,7 +35,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public abstract class ImsVideoCallProvider {
     private static final int MSG_SET_CALLBACK = 1;
     private static final int MSG_SET_CAMERA = 2;
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index 3affdf6..24ae979 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -23,7 +23,6 @@
 import android.annotation.RequiresPermission;
 import android.annotation.StringDef;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.annotation.WorkerThread;
 import android.os.Binder;
 import android.os.RemoteException;
@@ -59,7 +58,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public class ProvisioningManager {
 
     /**@hide*/
diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java
index 4606f7d..c2ddcea 100644
--- a/telephony/java/android/telephony/ims/RcsUceAdapter.java
+++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java
@@ -22,7 +22,6 @@
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.content.Context;
 import android.net.Uri;
 import android.os.Binder;
@@ -519,7 +518,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
     public void setUceSettingEnabled(boolean isEnabled) throws ImsException {
         IImsRcsController imsRcsController = getIImsRcsController();
diff --git a/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java
index 1918bcb..87a5094 100644
--- a/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java
+++ b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.ims.stub.ImsRegistrationImplBase;
@@ -34,7 +33,6 @@
  * {@hide}
  */
 @SystemApi
-@TestApi
 public final class CapabilityChangeRequest implements Parcelable {
 
     /**
diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java
index e5779b3..b0a7b62 100644
--- a/telephony/java/android/telephony/ims/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java
@@ -44,7 +44,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public abstract class ImsFeature {
 
     private static final String LOG_TAG = "ImsFeature";
@@ -62,19 +61,19 @@
      * CSFB for emergency calling.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public static final int FEATURE_EMERGENCY_MMTEL = 0;
     /**
      * This feature supports the MMTEL feature.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public static final int FEATURE_MMTEL = 1;
     /**
      * This feature supports the RCS feature.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public static final int FEATURE_RCS = 2;
     /**
      * Total number of features defined
@@ -124,7 +123,7 @@
      * during this time will result in an {@link IllegalStateException}.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public static final int STATE_UNAVAILABLE = 0;
     /**
      * This {@link ImsFeature} state is initializing and should not be communicated with. This will
@@ -132,14 +131,14 @@
      * during this time will result in an {@link IllegalStateException}.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public static final int STATE_INITIALIZING = 1;
     /**
      * This {@link ImsFeature} is ready for communication. Do not attempt to call framework methods
      * until {@see #onFeatureReady()} is called.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public static final int STATE_READY = 2;
 
     /**
@@ -169,13 +168,13 @@
      * The capability was unable to be changed.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public static final int CAPABILITY_ERROR_GENERIC = -1;
     /**
      * The capability was able to be changed.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public static final int CAPABILITY_SUCCESS = 0;
 
     /**
@@ -349,7 +348,7 @@
      * subscription IDs associated with this slot.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public final int getSlotIndex() {
         return mSlotId;
     }
@@ -359,7 +358,7 @@
      * or {@link #STATE_UNAVAILABLE} if it has not been updated  yet.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public @ImsState int getFeatureState() {
         synchronized (mLock) {
             return mState;
@@ -373,7 +372,7 @@
      * {@link #STATE_INITIALIZING}, or {@link #STATE_READY}.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public final void setFeatureState(@ImsState int state) {
         synchronized (mLock) {
             if (mState != state) {
diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
index d8a10eb..508d1a7 100644
--- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Bundle;
 import android.os.Message;
 import android.os.RemoteException;
@@ -60,7 +59,7 @@
     /**
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public MmTelFeature() {
     }
 
@@ -228,7 +227,7 @@
          * @see #removeCapabilities(int)
          * @hide
          */
-        @SystemApi @TestApi
+        @SystemApi
         public MmTelCapabilities() {
             super();
         }
@@ -237,7 +236,7 @@
          * @hide
          */
         @Deprecated
-        @SystemApi @TestApi
+        @SystemApi
         public MmTelCapabilities(Capabilities c) {
             mCapabilities = c.mCapabilities;
         }
@@ -248,7 +247,7 @@
          *                     bitfield.
          * @hide
          */
-        @SystemApi @TestApi
+        @SystemApi
         public MmTelCapabilities(@MmTelCapability int capabilities) {
             super(capabilities);
         }
@@ -288,7 +287,7 @@
          * @hide
          */
         @Override
-        @SystemApi @TestApi
+        @SystemApi
         public final void addCapabilities(@MmTelCapability int capabilities) {
             super.addCapabilities(capabilities);
         }
@@ -297,7 +296,7 @@
          * @hide
          */
         @Override
-        @SystemApi @TestApi
+        @SystemApi
         public final void removeCapabilities(@MmTelCapability int capability) {
             super.removeCapabilities(capability);
         }
@@ -375,14 +374,14 @@
      * outgoing call as IMS.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public static final int PROCESS_CALL_IMS = 0;
     /**
      * To be returned by {@link #shouldProcessCall(String[])} when the telephony framework should
      * not process the outgoing call as IMS and should instead use circuit switch.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public static final int PROCESS_CALL_CSFB = 1;
 
     /** @hide */
@@ -400,7 +399,7 @@
      * This is an optional boolean flag.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String EXTRA_IS_USSD = "android.telephony.ims.feature.extra.IS_USSD";
 
     /**
@@ -413,7 +412,7 @@
      * This is an optional boolean flag.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public static final String EXTRA_IS_UNKNOWN_CALL =
             "android.telephony.ims.feature.extra.IS_UNKNOWN_CALL";
 
@@ -453,7 +452,7 @@
      * @hide
      */
     @Override
-    @SystemApi @TestApi
+    @SystemApi
     public @NonNull final MmTelCapabilities queryCapabilityStatus() {
         return new MmTelCapabilities(super.queryCapabilityStatus());
     }
@@ -468,7 +467,7 @@
      * {@link #changeEnabledCapabilities}) should also show the status as disabled.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public final void notifyCapabilitiesStatusChanged(@NonNull MmTelCapabilities c) {
         if (c == null) {
             throw new IllegalArgumentException("MmTelCapabilities must be non-null!");
@@ -483,7 +482,7 @@
      * {@link #EXTRA_IS_UNKNOWN_CALL} and {@link #EXTRA_IS_USSD} above.
       * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public final void notifyIncomingCall(@NonNull ImsCallSessionImplBase c,
             @NonNull Bundle extras) {
         if (c == null || extras == null) {
@@ -509,7 +508,7 @@
      * @param reason The {@link ImsReasonInfo} call rejection reason.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public final void notifyRejectedCall(@NonNull ImsCallProfile callProfile,
             @NonNull ImsReasonInfo reason) {
         if (callProfile == null || reason == null) {
@@ -548,7 +547,7 @@
      * @link count the new Voice Message count.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public final void notifyVoiceMessageCountUpdate(int count) {
         IImsMmTelListener listener = getListener();
         if (listener == null) {
@@ -571,7 +570,7 @@
      * @hide
      */
     @Override
-    @SystemApi @TestApi
+    @SystemApi
     public boolean queryCapabilityConfiguration(@MmTelCapabilities.MmTelCapability int capability,
             @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
         // Base implementation - Override to provide functionality
@@ -592,7 +591,7 @@
      * * @hide
      */
     @Override
-    @SystemApi @TestApi
+    @SystemApi
     public void changeEnabledCapabilities(@NonNull CapabilityChangeRequest request,
             @NonNull CapabilityCallbackProxy c) {
         // Base implementation, no-op
@@ -617,7 +616,7 @@
      * @return a {@link ImsCallProfile} object
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public @Nullable ImsCallProfile createCallProfile(int callSessionType, int callType) {
         // Base Implementation - Should be overridden
         return null;
@@ -640,7 +639,7 @@
      * @param profile a call profile to make the call
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public @Nullable ImsCallSessionImplBase createCallSession(@NonNull ImsCallProfile profile) {
         // Base Implementation - Should be overridden
         return null;
@@ -659,7 +658,7 @@
      *        call will be placed over IMS or via CSFB.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public @ProcessCallResult int shouldProcessCall(@NonNull String[] numbers) {
         return PROCESS_CALL_IMS;
     }
@@ -694,7 +693,7 @@
      * configuration.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public @NonNull ImsUtImplBase getUt() {
         // Base Implementation - Should be overridden
         return new ImsUtImplBase();
@@ -705,7 +704,7 @@
      * calls that support it.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public @NonNull ImsEcbmImplBase getEcbm() {
         // Base Implementation - Should be overridden
         return new ImsEcbmImplBase();
@@ -716,7 +715,7 @@
      * package processing for multi-endpoint.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public @NonNull ImsMultiEndpointImplBase getMultiEndpoint() {
         // Base Implementation - Should be overridden
         return new ImsMultiEndpointImplBase();
@@ -744,7 +743,7 @@
      * }
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public void setUiTtyMode(int mode, @Nullable Message onCompleteMessage) {
         // Base Implementation - Should be overridden
     }
@@ -780,7 +779,7 @@
      * Provider.
      * @hide
      */
-    @SystemApi @TestApi
+    @SystemApi
     public @NonNull ImsSmsImplBase getSmsImplementation() {
         return new ImsSmsImplBase();
     }
@@ -794,7 +793,7 @@
      * @hide
      */
     @Override
-    @SystemApi @TestApi
+    @SystemApi
     public void onFeatureRemoved() {
         // Base Implementation - Should be overridden
     }
@@ -804,7 +803,7 @@
      * @hide
      */
     @Override
-    @SystemApi @TestApi
+    @SystemApi
     public void onFeatureReady() {
         // Base Implementation - Should be overridden
     }
diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java
index 98b0bcf..b8ae146 100644
--- a/telephony/java/android/telephony/ims/feature/RcsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java
@@ -20,7 +20,6 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.net.Uri;
 import android.os.RemoteException;
 import android.telephony.ims.RcsContactUceCapability;
@@ -50,7 +49,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public class RcsFeature extends ImsFeature {
 
     private static final String LOG_TAG = "RcsFeature";
diff --git a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
index 8f738d2..1cebdd5 100644
--- a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Message;
 import android.os.RemoteException;
 import android.telephony.ims.ImsCallProfile;
@@ -39,7 +38,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 // DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
 // will break other implementations of ImsCallSession maintained by other ImsServices.
 public class ImsCallSessionImplBase implements AutoCloseable {
diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
index 4ef44d3..e0290a5 100644
--- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
@@ -19,7 +19,6 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.content.Context;
 import android.os.PersistableBundle;
 import android.os.RemoteException;
@@ -51,7 +50,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public class ImsConfigImplBase {
 
     private static final String TAG = "ImsConfigImplBase";
diff --git a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
index 4a3a2ea..06c35ea 100644
--- a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
@@ -17,7 +17,6 @@
 package android.telephony.ims.stub;
 
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.RemoteException;
 import android.util.Log;
 
@@ -34,7 +33,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public class ImsEcbmImplBase {
     private static final String TAG = "ImsEcbmImplBase";
 
diff --git a/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
index 4e7307e..cd9ebbf 100644
--- a/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
+++ b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.ims.feature.ImsFeature;
@@ -36,7 +35,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class ImsFeatureConfiguration implements Parcelable {
 
     public static final class FeatureSlotPair {
diff --git a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
index 0ae5bba..d002903 100644
--- a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
@@ -17,7 +17,6 @@
 package android.telephony.ims.stub;
 
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.RemoteException;
 import android.telephony.ims.ImsExternalCallState;
 import android.util.Log;
@@ -38,7 +37,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public class ImsMultiEndpointImplBase {
     private static final String TAG = "MultiEndpointImplBase";
 
diff --git a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
index 2cdf70e..12abdd1 100644
--- a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
@@ -18,7 +18,6 @@
 
 import android.annotation.IntDef;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.net.Uri;
 import android.os.RemoteException;
 import android.telephony.ims.ImsReasonInfo;
@@ -40,7 +39,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public class ImsRegistrationImplBase {
 
     private static final String LOG_TAG = "ImsRegistrationImplBase";
diff --git a/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
index a9a33c0..2783e29 100644
--- a/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
@@ -19,7 +19,6 @@
 import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.RemoteException;
 import android.telephony.SmsManager;
 import android.telephony.SmsMessage;
@@ -38,7 +37,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public class ImsSmsImplBase {
     private static final String LOG_TAG = "SmsImplBase";
 
diff --git a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
index 8564f7a..f5219d5 100644
--- a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.telephony.ims.ImsUtListener;
@@ -40,7 +39,6 @@
 // DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
 // will break other implementations of ImsUt maintained by other ImsServices.
 @SystemApi
-@TestApi
 public class ImsUtImplBase {
     /**
      * Bar all incoming calls. (See 3GPP TS 24.611)
diff --git a/telephony/java/android/telephony/mbms/DownloadRequest.java b/telephony/java/android/telephony/mbms/DownloadRequest.java
index ac258cd..eb59f87 100644
--- a/telephony/java/android/telephony/mbms/DownloadRequest.java
+++ b/telephony/java/android/telephony/mbms/DownloadRequest.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Parcel;
@@ -186,7 +185,6 @@
          * @hide
          */
         @SystemApi
-        @TestApi
         public Builder setServiceId(String serviceId) {
             fileServiceId = serviceId;
             return this;
diff --git a/telephony/java/android/telephony/mbms/FileInfo.java b/telephony/java/android/telephony/mbms/FileInfo.java
index ada2872..e52b2ce 100644
--- a/telephony/java/android/telephony/mbms/FileInfo.java
+++ b/telephony/java/android/telephony/mbms/FileInfo.java
@@ -17,7 +17,6 @@
 package android.telephony.mbms;
 
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -50,7 +49,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public FileInfo(Uri uri, String mimeType) {
         this.uri = uri;
         this.mimeType = mimeType;
diff --git a/telephony/java/android/telephony/mbms/FileServiceInfo.java b/telephony/java/android/telephony/mbms/FileServiceInfo.java
index 8c79ab6..8777e7f 100644
--- a/telephony/java/android/telephony/mbms/FileServiceInfo.java
+++ b/telephony/java/android/telephony/mbms/FileServiceInfo.java
@@ -17,7 +17,6 @@
 package android.telephony.mbms;
 
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -36,7 +35,6 @@
 
     /** @hide */
     @SystemApi
-    @TestApi
     public FileServiceInfo(Map<Locale, String> newNames, String newClassName,
             List<Locale> newLocales, String newServiceId, Date start, Date end,
             List<FileInfo> newFiles) {
diff --git a/telephony/java/android/telephony/mbms/StreamingServiceInfo.java b/telephony/java/android/telephony/mbms/StreamingServiceInfo.java
index 8ad1d89..316e8656 100644
--- a/telephony/java/android/telephony/mbms/StreamingServiceInfo.java
+++ b/telephony/java/android/telephony/mbms/StreamingServiceInfo.java
@@ -17,7 +17,6 @@
 package android.telephony.mbms;
 
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -42,7 +41,6 @@
      * @hide
      */
     @SystemApi
-    @TestApi
     public StreamingServiceInfo(Map<Locale, String> names, String className,
             List<Locale> locales, String serviceId, Date start, Date end) {
         super(names, className, locales, serviceId, start, end);
diff --git a/telephony/java/android/telephony/mbms/UriPathPair.java b/telephony/java/android/telephony/mbms/UriPathPair.java
index f53d7e0..9258919 100644
--- a/telephony/java/android/telephony/mbms/UriPathPair.java
+++ b/telephony/java/android/telephony/mbms/UriPathPair.java
@@ -17,7 +17,6 @@
 package android.telephony.mbms;
 
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.content.ContentResolver;
 import android.net.Uri;
 import android.os.Parcel;
@@ -30,7 +29,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public final class UriPathPair implements Parcelable {
     private final Uri mFilePathUri;
     private final Uri mContentUri;
diff --git a/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java b/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java
index 3053ea0..ffc1d2e 100644
--- a/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java
+++ b/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.content.Intent;
 import android.os.Binder;
 import android.os.IBinder;
@@ -45,7 +44,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
     private final Map<IBinder, DownloadStatusListener> mDownloadStatusListenerBinderMap =
             new HashMap<>();
@@ -576,7 +574,6 @@
     // Following two methods exist to workaround b/124210145
     /** @hide */
     @SystemApi
-    @TestApi
     @Override
     public android.os.IBinder asBinder() {
         return super.asBinder();
@@ -584,7 +581,6 @@
 
     /** @hide */
     @SystemApi
-    @TestApi
     @Override
     public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply,
             int flags) throws RemoteException {
diff --git a/telephony/java/android/telephony/mbms/vendor/MbmsGroupCallServiceBase.java b/telephony/java/android/telephony/mbms/vendor/MbmsGroupCallServiceBase.java
index 1335b52..e5b18bb 100644
--- a/telephony/java/android/telephony/mbms/vendor/MbmsGroupCallServiceBase.java
+++ b/telephony/java/android/telephony/mbms/vendor/MbmsGroupCallServiceBase.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.app.Service;
 import android.content.Intent;
 import android.os.Binder;
@@ -41,7 +40,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public class MbmsGroupCallServiceBase extends Service {
     private final IBinder mInterface = new Stub() {
         @Override
diff --git a/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java b/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java
index cced447..e169b16 100644
--- a/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java
+++ b/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java
@@ -18,7 +18,6 @@
 
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Binder;
@@ -39,7 +38,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
     /**
      * Initialize streaming service for this app and subId, registering the listener.
@@ -299,7 +297,6 @@
     // Following two methods exist to workaround b/124210145
     /** @hide */
     @SystemApi
-    @TestApi
     @Override
     public android.os.IBinder asBinder() {
         return super.asBinder();
@@ -307,7 +304,6 @@
 
     /** @hide */
     @SystemApi
-    @TestApi
     @Override
     public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply,
             int flags) throws RemoteException {
diff --git a/telephony/java/android/telephony/mbms/vendor/VendorUtils.java b/telephony/java/android/telephony/mbms/vendor/VendorUtils.java
index f1cac8c..a43f122 100644
--- a/telephony/java/android/telephony/mbms/vendor/VendorUtils.java
+++ b/telephony/java/android/telephony/mbms/vendor/VendorUtils.java
@@ -17,7 +17,6 @@
 package android.telephony.mbms.vendor;
 
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -35,7 +34,6 @@
  * @hide
  */
 @SystemApi
-@TestApi
 public class VendorUtils {
 
     /**
diff --git a/test-mock/api/test-current.txt b/test-mock/api/test-current.txt
index 32ca250..79d746a 100644
--- a/test-mock/api/test-current.txt
+++ b/test-mock/api/test-current.txt
@@ -6,21 +6,12 @@
   }
 
   @Deprecated public class MockPackageManager extends android.content.pm.PackageManager {
-    method public void addOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
-    method public boolean arePermissionsIndividuallyControlled();
-    method public String getDefaultBrowserPackageNameAsUser(int);
     method public int getInstallReason(String, android.os.UserHandle);
     method public java.util.List<android.content.pm.ApplicationInfo> getInstalledApplicationsAsUser(int, int);
-    method public java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(int, int);
     method public String[] getNamesForUids(int[]);
     method public String getPermissionControllerPackageName();
-    method public int getPermissionFlags(String, String, android.os.UserHandle);
     method @NonNull public String getServicesSystemSharedLibraryPackageName();
     method @NonNull public String getSharedSystemSharedLibraryPackageName();
-    method public void grantRuntimePermission(String, String, android.os.UserHandle);
-    method public void removeOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
-    method public void revokeRuntimePermission(String, String, android.os.UserHandle);
-    method public void updatePermissionFlags(String, String, int, int, android.os.UserHandle);
   }
 
 }
diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
index bf7a6ff..725bfa9 100644
--- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
+++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
@@ -280,7 +280,7 @@
         after.removeAll(before);
         // There should be only one /data/misc_ce/0/rollback/<rollbackId> created during test
         assertThat(after).hasSize(1);
-        after.forEach(dir -> assertDirectoryIsEmpty(dir));
+        assertDirectoryIsEmpty(after.get(0));
     }
 
     /**
@@ -336,31 +336,37 @@
         String oldFilePath1 = apexDataDirDeSys(APK_IN_APEX_TESTAPEX_NAME) + "/" + TEST_FILENAME_1;
         String oldFilePath2 =
                 apexDataDirDeSys(APK_IN_APEX_TESTAPEX_NAME) + TEST_SUBDIR + TEST_FILENAME_2;
-        pushString(TEST_STRING_1, oldFilePath1);
-        pushString(TEST_STRING_2, oldFilePath2);
+        runAsRoot(() -> {
+            assertThat(getDevice().pushString(TEST_STRING_1, oldFilePath1)).isTrue();
+            assertThat(getDevice().pushString(TEST_STRING_2, oldFilePath2)).isTrue();
+        });
 
         // Install new version of the APEX with rollback enabled
         runPhase("testRollbackApexDataDirectories_Phase1");
         getDevice().reboot();
 
         // Replace files in data directory
-        getDevice().deleteFile(oldFilePath1);
-        getDevice().deleteFile(oldFilePath2);
         String newFilePath3 = apexDataDirDeSys(APK_IN_APEX_TESTAPEX_NAME) + "/" + TEST_FILENAME_3;
         String newFilePath4 =
                 apexDataDirDeSys(APK_IN_APEX_TESTAPEX_NAME) + TEST_SUBDIR + TEST_FILENAME_4;
-        pushString(TEST_STRING_3, newFilePath3);
-        pushString(TEST_STRING_4, newFilePath4);
+        runAsRoot(() -> {
+            getDevice().deleteFile(oldFilePath1);
+            getDevice().deleteFile(oldFilePath2);
+            assertThat(getDevice().pushString(TEST_STRING_3, newFilePath3)).isTrue();
+            assertThat(getDevice().pushString(TEST_STRING_4, newFilePath4)).isTrue();
+        });
 
         // Roll back the APEX
         runPhase("testRollbackApexDataDirectories_Phase2");
         getDevice().reboot();
 
         // Verify that old files have been restored and new files are gone
-        assertEquals(TEST_STRING_1, getDevice().pullFileContents(oldFilePath1));
-        assertEquals(TEST_STRING_2, getDevice().pullFileContents(oldFilePath2));
-        assertNull(getDevice().pullFile(newFilePath3));
-        assertNull(getDevice().pullFile(newFilePath4));
+        runAsRoot(() -> {
+            assertEquals(TEST_STRING_1, getDevice().pullFileContents(oldFilePath1));
+            assertEquals(TEST_STRING_2, getDevice().pullFileContents(oldFilePath2));
+            assertNull(getDevice().pullFile(newFilePath3));
+            assertNull(getDevice().pullFile(newFilePath4));
+        });
 
         // Verify snapshots are deleted after restoration
         List<String> after = getSnapshotDirectories("/data/misc/apexrollback");
@@ -368,7 +374,7 @@
         after.removeAll(before);
         // There should be only one /data/misc/apexrollback/<rollbackId> created during test
         assertThat(after).hasSize(1);
-        after.forEach(dir -> assertDirectoryIsEmpty(dir));
+        assertDirectoryIsEmpty(after.get(0));
     }
 
     /**
@@ -384,32 +390,38 @@
                 APK_IN_APEX_TESTAPEX_NAME, 0) + "/" + TEST_FILENAME_1;
         String oldFilePath2 =
                 apexDataDirDeUser(APK_IN_APEX_TESTAPEX_NAME, 0) + TEST_SUBDIR + TEST_FILENAME_2;
-        pushString(TEST_STRING_1, oldFilePath1);
-        pushString(TEST_STRING_2, oldFilePath2);
+        runAsRoot(() -> {
+            assertThat(getDevice().pushString(TEST_STRING_1, oldFilePath1)).isTrue();
+            assertThat(getDevice().pushString(TEST_STRING_2, oldFilePath2)).isTrue();
+        });
 
         // Install new version of the APEX with rollback enabled
         runPhase("testRollbackApexDataDirectories_Phase1");
         getDevice().reboot();
 
         // Replace files in data directory
-        getDevice().deleteFile(oldFilePath1);
-        getDevice().deleteFile(oldFilePath2);
         String newFilePath3 =
                 apexDataDirDeUser(APK_IN_APEX_TESTAPEX_NAME, 0) + "/" + TEST_FILENAME_3;
         String newFilePath4 =
                 apexDataDirDeUser(APK_IN_APEX_TESTAPEX_NAME, 0) + TEST_SUBDIR + TEST_FILENAME_4;
-        pushString(TEST_STRING_3, newFilePath3);
-        pushString(TEST_STRING_4, newFilePath4);
+        runAsRoot(() -> {
+            getDevice().deleteFile(oldFilePath1);
+            getDevice().deleteFile(oldFilePath2);
+            assertThat(getDevice().pushString(TEST_STRING_3, newFilePath3)).isTrue();
+            assertThat(getDevice().pushString(TEST_STRING_4, newFilePath4)).isTrue();
+        });
 
         // Roll back the APEX
         runPhase("testRollbackApexDataDirectories_Phase2");
         getDevice().reboot();
 
         // Verify that old files have been restored and new files are gone
-        assertEquals(TEST_STRING_1, getDevice().pullFileContents(oldFilePath1));
-        assertEquals(TEST_STRING_2, getDevice().pullFileContents(oldFilePath2));
-        assertNull(getDevice().pullFile(newFilePath3));
-        assertNull(getDevice().pullFile(newFilePath4));
+        runAsRoot(() -> {
+            assertEquals(TEST_STRING_1, getDevice().pullFileContents(oldFilePath1));
+            assertEquals(TEST_STRING_2, getDevice().pullFileContents(oldFilePath2));
+            assertNull(getDevice().pullFile(newFilePath3));
+            assertNull(getDevice().pullFile(newFilePath4));
+        });
 
         // Verify snapshots are deleted after restoration
         List<String> after = getSnapshotDirectories("/data/misc_de/0/apexrollback");
@@ -417,7 +429,7 @@
         after.removeAll(before);
         // There should be only one /data/misc_de/0/apexrollback/<rollbackId> created during test
         assertThat(after).hasSize(1);
-        after.forEach(dir -> assertDirectoryIsEmpty(dir));
+        assertDirectoryIsEmpty(after.get(0));
     }
 
     /**
@@ -432,31 +444,37 @@
         String oldFilePath1 = apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + "/" + TEST_FILENAME_1;
         String oldFilePath2 =
                 apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + TEST_SUBDIR + TEST_FILENAME_2;
-        pushString(TEST_STRING_1, oldFilePath1);
-        pushString(TEST_STRING_2, oldFilePath2);
+        runAsRoot(() -> {
+            assertThat(getDevice().pushString(TEST_STRING_1, oldFilePath1)).isTrue();
+            assertThat(getDevice().pushString(TEST_STRING_2, oldFilePath2)).isTrue();
+        });
 
         // Install new version of the APEX with rollback enabled
         runPhase("testRollbackApexDataDirectories_Phase1");
         getDevice().reboot();
 
         // Replace files in data directory
-        getDevice().deleteFile(oldFilePath1);
-        getDevice().deleteFile(oldFilePath2);
         String newFilePath3 = apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + "/" + TEST_FILENAME_3;
         String newFilePath4 =
                 apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + TEST_SUBDIR + TEST_FILENAME_4;
-        pushString(TEST_STRING_3, newFilePath3);
-        pushString(TEST_STRING_4, newFilePath4);
+        runAsRoot(() -> {
+            getDevice().deleteFile(oldFilePath1);
+            getDevice().deleteFile(oldFilePath2);
+            assertThat(getDevice().pushString(TEST_STRING_3, newFilePath3)).isTrue();
+            assertThat(getDevice().pushString(TEST_STRING_4, newFilePath4)).isTrue();
+        });
 
         // Roll back the APEX
         runPhase("testRollbackApexDataDirectories_Phase2");
         getDevice().reboot();
 
         // Verify that old files have been restored and new files are gone
-        assertEquals(TEST_STRING_1, getDevice().pullFileContents(oldFilePath1));
-        assertEquals(TEST_STRING_2, getDevice().pullFileContents(oldFilePath2));
-        assertNull(getDevice().pullFile(newFilePath3));
-        assertNull(getDevice().pullFile(newFilePath4));
+        runAsRoot(() -> {
+            assertEquals(TEST_STRING_1, getDevice().pullFileContents(oldFilePath1));
+            assertEquals(TEST_STRING_2, getDevice().pullFileContents(oldFilePath2));
+            assertNull(getDevice().pullFile(newFilePath3));
+            assertNull(getDevice().pullFile(newFilePath4));
+        });
 
         // Verify snapshots are deleted after restoration
         List<String> after = getSnapshotDirectories("/data/misc_ce/0/apexrollback");
@@ -464,7 +482,7 @@
         after.removeAll(before);
         // There should be only one /data/misc_ce/0/apexrollback/<rollbackId> created during test
         assertThat(after).hasSize(1);
-        after.forEach(dir -> assertDirectoryIsEmpty(dir));
+        assertDirectoryIsEmpty(after.get(0));
     }
 
     /**
@@ -478,30 +496,36 @@
         // Push files to apk data directory
         String oldFilePath1 = apkDataDirDe(TESTAPP_A, 0) + "/" + TEST_FILENAME_1;
         String oldFilePath2 = apkDataDirDe(TESTAPP_A, 0) + TEST_SUBDIR + TEST_FILENAME_2;
-        pushString(TEST_STRING_1, oldFilePath1);
-        pushString(TEST_STRING_2, oldFilePath2);
+        runAsRoot(() -> {
+            assertThat(getDevice().pushString(TEST_STRING_1, oldFilePath1)).isTrue();
+            assertThat(getDevice().pushString(TEST_STRING_2, oldFilePath2)).isTrue();
+        });
 
         // Install version 2 of TESTAPP_A with rollback enabled
         runPhase("testRollbackApkDataDirectories_Phase2");
         getDevice().reboot();
 
         // Replace files in data directory
-        getDevice().deleteFile(oldFilePath1);
-        getDevice().deleteFile(oldFilePath2);
         String newFilePath3 = apkDataDirDe(TESTAPP_A, 0) + "/" + TEST_FILENAME_3;
         String newFilePath4 = apkDataDirDe(TESTAPP_A, 0) + TEST_SUBDIR + TEST_FILENAME_4;
-        pushString(TEST_STRING_3, newFilePath3);
-        pushString(TEST_STRING_4, newFilePath4);
+        runAsRoot(() -> {
+            getDevice().deleteFile(oldFilePath1);
+            getDevice().deleteFile(oldFilePath2);
+            assertThat(getDevice().pushString(TEST_STRING_3, newFilePath3)).isTrue();
+            assertThat(getDevice().pushString(TEST_STRING_4, newFilePath4)).isTrue();
+        });
 
         // Roll back the APK
         runPhase("testRollbackApkDataDirectories_Phase3");
         getDevice().reboot();
 
         // Verify that old files have been restored and new files are gone
-        assertEquals(TEST_STRING_1, getDevice().pullFileContents(oldFilePath1));
-        assertEquals(TEST_STRING_2, getDevice().pullFileContents(oldFilePath2));
-        assertNull(getDevice().pullFile(newFilePath3));
-        assertNull(getDevice().pullFile(newFilePath4));
+        runAsRoot(() -> {
+            assertEquals(TEST_STRING_1, getDevice().pullFileContents(oldFilePath1));
+            assertEquals(TEST_STRING_2, getDevice().pullFileContents(oldFilePath2));
+            assertNull(getDevice().pullFile(newFilePath3));
+            assertNull(getDevice().pullFile(newFilePath4));
+        });
     }
 
     @Test
@@ -513,8 +537,10 @@
         String oldFilePath1 = apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + "/" + TEST_FILENAME_1;
         String oldFilePath2 =
                 apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + TEST_SUBDIR + TEST_FILENAME_2;
-        pushString(TEST_STRING_1, oldFilePath1);
-        pushString(TEST_STRING_2, oldFilePath2);
+        runAsRoot(() -> {
+            assertThat(getDevice().pushString(TEST_STRING_1, oldFilePath1)).isTrue();
+            assertThat(getDevice().pushString(TEST_STRING_2, oldFilePath2)).isTrue();
+        });
 
         // Install new version of the APEX with rollback enabled
         runPhase("testRollbackApexDataDirectories_Phase1");
@@ -527,9 +553,11 @@
         assertThat(after).hasSize(1);
         // Expire all rollbacks and check CE snapshot directories are deleted
         runPhase("testCleanUp");
-        for (String dir : after) {
-            assertNull(getDevice().getFileEntry(dir));
-        }
+        runAsRoot(() -> {
+            for (String dir : after) {
+                assertNull(getDevice().getFileEntry(dir));
+            }
+        });
     }
 
     private void pushTestApex() throws Exception {
@@ -563,26 +591,34 @@
     }
 
     private List<String> getSnapshotDirectories(String baseDir) throws Exception {
-        IFileEntry f = getDevice().getFileEntry(baseDir);
-        if (f == null) {
-            Log.d(TAG, "baseDir doesn't exist: " + baseDir);
-            return Collections.EMPTY_LIST;
+        try {
+            getDevice().enableAdbRoot();
+            IFileEntry f = getDevice().getFileEntry(baseDir);
+            if (f == null) {
+                Log.d(TAG, "baseDir doesn't exist: " + baseDir);
+                return Collections.EMPTY_LIST;
+            }
+            List<String> list = f.getChildren(false)
+                    .stream().filter(entry -> entry.getName().matches("\\d+(-prerestore)?"))
+                    .map(entry -> entry.getFullPath())
+                    .collect(Collectors.toList());
+            Log.d(TAG, "getSnapshotDirectories=" + list);
+            return list;
+        } finally {
+            getDevice().disableAdbRoot();
         }
-        List<String> list = f.getChildren(false)
-                .stream().filter(entry -> entry.getName().matches("\\d+(-prerestore)?"))
-                .map(entry -> entry.getFullPath())
-                .collect(Collectors.toList());
-        Log.d(TAG, "getSnapshotDirectories=" + list);
-        return list;
     }
 
-    private void assertDirectoryIsEmpty(String path) {
+    private void assertDirectoryIsEmpty(String path) throws Exception {
         try {
+            getDevice().enableAdbRoot();
             IFileEntry file = getDevice().getFileEntry(path);
             assertTrue("Not a directory: " + path, file.isDirectory());
             assertTrue("Directory not empty: " + path, file.getChildren(false).isEmpty());
         } catch (DeviceNotAvailableException e) {
             fail("Can't access directory: " + path);
+        } finally {
+            getDevice().disableAdbRoot();
         }
     }
 
@@ -621,10 +657,15 @@
         }
     }
 
-    private void pushString(String contents, String deviceFilePath) throws Exception {
+    @FunctionalInterface
+    private interface ExceptionalRunnable {
+        void run() throws Exception;
+    }
+
+    private void runAsRoot(ExceptionalRunnable runnable) throws Exception {
         try {
             getDevice().enableAdbRoot();
-            assertThat(getDevice().pushString(contents, deviceFilePath)).isTrue();
+            runnable.run();
         } finally {
             getDevice().disableAdbRoot();
         }
diff --git a/tests/net/common/Android.bp b/tests/net/common/Android.bp
index 46d680f..373aac6 100644
--- a/tests/net/common/Android.bp
+++ b/tests/net/common/Android.bp
@@ -25,6 +25,7 @@
         "junit",
         "mockito-target-minus-junit4",
         "net-tests-utils",
+        "net-utils-framework-common",
         "platform-test-annotations",
     ],
     libs: [
diff --git a/tests/net/common/java/android/net/LinkPropertiesTest.java b/tests/net/common/java/android/net/LinkPropertiesTest.java
index 3c3076f..f52ab5b 100644
--- a/tests/net/common/java/android/net/LinkPropertiesTest.java
+++ b/tests/net/common/java/android/net/LinkPropertiesTest.java
@@ -32,7 +32,6 @@
 import static org.junit.Assert.fail;
 
 import android.net.LinkProperties.ProvisioningChange;
-import android.net.util.LinkPropertiesUtils.CompareResult;
 import android.os.Build;
 import android.system.OsConstants;
 import android.util.ArraySet;
@@ -41,6 +40,7 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.net.module.util.LinkPropertiesUtils.CompareResult;
 import com.android.testutils.DevSdkIgnoreRule;
 import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
@@ -447,23 +447,21 @@
         assertEquals(3, lp.getRoutes().size());
         assertAllRoutesHaveInterface("wlan0", lp);
 
-        // Check comparisons work.
+        // Check routes are updated correctly when calling setInterfaceName.
         LinkProperties lp2 = new LinkProperties(lp);
         assertAllRoutesHaveInterface("wlan0", lp2);
-        // LinkProperties#compareAllRoutes exists both in R and before R, but the return type
-        // changed in R, so a test compiled with the R version of LinkProperties cannot run on Q.
-        if (isAtLeastR()) {
-            assertEquals(0, lp.compareAllRoutes(lp2).added.size());
-            assertEquals(0, lp.compareAllRoutes(lp2).removed.size());
-        }
+        final CompareResult<RouteInfo> cr1 =
+                new CompareResult<>(lp.getAllRoutes(), lp2.getAllRoutes());
+        assertEquals(0, cr1.added.size());
+        assertEquals(0, cr1.removed.size());
 
         lp2.setInterfaceName("p2p0");
         assertAllRoutesHaveInterface("p2p0", lp2);
         assertAllRoutesNotHaveInterface("wlan0", lp2);
-        if (isAtLeastR()) {
-            assertEquals(3, lp.compareAllRoutes(lp2).added.size());
-            assertEquals(3, lp.compareAllRoutes(lp2).removed.size());
-        }
+        final CompareResult<RouteInfo> cr2 =
+                new CompareResult<>(lp.getAllRoutes(), lp2.getAllRoutes());
+        assertEquals(3, cr2.added.size());
+        assertEquals(3, cr2.removed.size());
 
         // Remove route with incorrect interface, no route removed.
         lp.removeRoute(new RouteInfo(prefix2, null, null));
diff --git a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java
index 32bfa70..f5b85ca 100644
--- a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java
+++ b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java
@@ -98,7 +98,6 @@
 
     @Mock Context mCtx;
     @Mock IDnsResolver mMockDnsResolver;
-    @Mock MockableSystemProperties mSystemProperties;
 
     private void assertResolverOptionsEquals(
             @NonNull ResolverOptionsParcel actual,
@@ -137,7 +136,7 @@
         mContentResolver.addProvider(Settings.AUTHORITY,
                 new FakeSettingsProvider());
         when(mCtx.getContentResolver()).thenReturn(mContentResolver);
-        mDnsManager = new DnsManager(mCtx, mMockDnsResolver, mSystemProperties);
+        mDnsManager = new DnsManager(mCtx, mMockDnsResolver);
 
         // Clear the private DNS settings
         Settings.Global.putString(mContentResolver, PRIVATE_DNS_DEFAULT_MODE, "");
diff --git a/wifi/api/current.txt b/wifi/api/current.txt
index d6e8922..f0cf75c 100644
--- a/wifi/api/current.txt
+++ b/wifi/api/current.txt
@@ -563,6 +563,7 @@
     method public int getMaxServiceNameLength();
     method public int getMaxServiceSpecificInfoLength();
     method public int getSupportedCipherSuites();
+    method public boolean isInstantCommunicationModeSupported();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.aware.Characteristics> CREATOR;
     field public static final int WIFI_AWARE_CIPHER_SUITE_NCS_SK_128 = 1; // 0x1
@@ -661,6 +662,7 @@
     method public android.net.wifi.aware.Characteristics getCharacteristics();
     method public boolean isAvailable();
     method public boolean isDeviceAttached();
+    method public boolean isInstantCommunicationModeEnabled();
     field public static final String ACTION_WIFI_AWARE_STATE_CHANGED = "android.net.wifi.aware.action.WIFI_AWARE_STATE_CHANGED";
     field public static final int WIFI_AWARE_DATA_PATH_ROLE_INITIATOR = 0; // 0x0
     field public static final int WIFI_AWARE_DATA_PATH_ROLE_RESPONDER = 1; // 0x1
diff --git a/wifi/api/system-current.txt b/wifi/api/system-current.txt
index 98cb849..754a8dc 100644
--- a/wifi/api/system-current.txt
+++ b/wifi/api/system-current.txt
@@ -800,6 +800,10 @@
     method @Deprecated public android.net.NetworkSpecifier createNetworkSpecifierPmk(@NonNull android.net.wifi.aware.PeerHandle, @NonNull byte[]);
   }
 
+  public class WifiAwareManager {
+    method public void enableInstantCommunicationMode(boolean);
+  }
+
   public class WifiAwareSession implements java.lang.AutoCloseable {
     method public android.net.NetworkSpecifier createNetworkSpecifierPmk(int, @NonNull byte[], @NonNull byte[]);
   }
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 7c2556d..fd4e1dd 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -1626,6 +1626,14 @@
         private boolean mHasEverConnected;
 
         /**
+         * Boolean indicating if captive portal has never been detected on this network.
+         *
+         * This should be true by default, for newly created WifiConfigurations until a captive
+         * portal is detected.
+         */
+        private boolean mHasNeverDetectedCaptivePortal = true;
+
+        /**
          * set whether this network is visible in latest Qualified Network Selection
          * @param seen value set to candidate
          * @hide
@@ -1714,6 +1722,19 @@
             return mHasEverConnected;
         }
 
+        /**
+         * Set whether a captive portal has never been detected on this network.
+         * @hide
+         */
+        public void setHasNeverDetectedCaptivePortal(boolean value) {
+            mHasNeverDetectedCaptivePortal = value;
+        }
+
+        /** @hide */
+        public boolean hasNeverDetectedCaptivePortal() {
+            return mHasNeverDetectedCaptivePortal;
+        }
+
         /** @hide */
         public NetworkSelectionStatus() {
             // previously stored configs will not have this parameter, so we default to false.
@@ -1989,6 +2010,7 @@
             setCandidateScore(source.getCandidateScore());
             setConnectChoice(source.getConnectChoice());
             setHasEverConnected(source.hasEverConnected());
+            setHasNeverDetectedCaptivePortal(source.hasNeverDetectedCaptivePortal());
         }
 
         /** @hide */
@@ -2008,6 +2030,7 @@
                 dest.writeInt(CONNECT_CHOICE_NOT_EXISTS);
             }
             dest.writeInt(hasEverConnected() ? 1 : 0);
+            dest.writeInt(hasNeverDetectedCaptivePortal() ? 1 : 0);
         }
 
         /** @hide */
@@ -2026,6 +2049,7 @@
                 setConnectChoice(null);
             }
             setHasEverConnected(in.readInt() != 0);
+            setHasNeverDetectedCaptivePortal(in.readInt() != 0);
         }
     }
 
@@ -2287,6 +2311,8 @@
         }
         sbuf.append(" hasEverConnected: ")
                 .append(mNetworkSelectionStatus.hasEverConnected()).append("\n");
+        sbuf.append(" hasNeverDetectedCaptivePortal: ")
+                .append(mNetworkSelectionStatus.hasNeverDetectedCaptivePortal()).append("\n");
 
         if (this.numAssociation > 0) {
             sbuf.append(" numAssociation ").append(this.numAssociation).append("\n");
diff --git a/wifi/java/android/net/wifi/aware/Characteristics.java b/wifi/java/android/net/wifi/aware/Characteristics.java
index d5fd48e..1167865 100644
--- a/wifi/java/android/net/wifi/aware/Characteristics.java
+++ b/wifi/java/android/net/wifi/aware/Characteristics.java
@@ -17,6 +17,7 @@
 package android.net.wifi.aware;
 
 import android.annotation.IntDef;
+import android.net.wifi.util.SdkLevelUtil;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -37,6 +38,9 @@
     public static final String KEY_MAX_MATCH_FILTER_LENGTH = "key_max_match_filter_length";
     /** @hide */
     public static final String KEY_SUPPORTED_CIPHER_SUITES = "key_supported_cipher_suites";
+    /** @hide */
+    public static final String KEY_IS_INSTANT_COMMUNICATION_MODE_SUPPORTED =
+            "key_is_instant_communication_mode_supported";
 
     private Bundle mCharacteristics = new Bundle();
 
@@ -83,6 +87,17 @@
         return mCharacteristics.getInt(KEY_MAX_MATCH_FILTER_LENGTH);
     }
 
+    /**
+     * Check if instant communication mode is supported by device.
+     * @return True if supported, false otherwise.
+     */
+    public boolean isInstantCommunicationModeSupported() {
+        if (!SdkLevelUtil.isAtLeastS()) {
+            throw new UnsupportedOperationException();
+        }
+        return mCharacteristics.getBoolean(KEY_IS_INSTANT_COMMUNICATION_MODE_SUPPORTED);
+    }
+
     /** @hide */
     @IntDef(flag = true, prefix = { "WIFI_AWARE_CIPHER_SUITE_" }, value = {
             WIFI_AWARE_CIPHER_SUITE_NCS_SK_128,
diff --git a/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl b/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl
index f5b1edc..cd2ca69 100644
--- a/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl
+++ b/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl
@@ -37,6 +37,8 @@
     boolean isUsageEnabled();
     Characteristics getCharacteristics();
     boolean isDeviceAttached();
+    void enableInstantCommunicationMode(in String callingPackage, boolean enable);
+    boolean isInstantCommunicationModeEnabled();
 
     // client API
     void connect(in IBinder binder, in String callingPackage, in String callingFeatureId,
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index 03f5f40..bb146e3 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -22,12 +22,14 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.content.Context;
 import android.net.ConnectivityManager;
 import android.net.NetworkRequest;
 import android.net.NetworkSpecifier;
 import android.net.wifi.util.HexEncoding;
+import android.net.wifi.util.SdkLevelUtil;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -208,6 +210,9 @@
      *         or not (false).
      */
     public boolean isDeviceAttached() {
+        if (!SdkLevelUtil.isAtLeastS()) {
+            throw new UnsupportedOperationException();
+        }
         try {
             return mService.isDeviceAttached();
         } catch (RemoteException e) {
@@ -216,6 +221,42 @@
     }
 
     /**
+     * Enable the Wifi Aware Instant communication mode. If the device doesn't support this feature
+     * calling this API will result no action.
+     * @see Characteristics#isInstantCommunicationModeSupported()
+     * @param enable true for enable, false otherwise.
+     * @hide
+     */
+    @SystemApi
+    public void enableInstantCommunicationMode(boolean enable) {
+        if (!SdkLevelUtil.isAtLeastS()) {
+            throw new UnsupportedOperationException();
+        }
+        try {
+            mService.enableInstantCommunicationMode(mContext.getOpPackageName(), enable);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Return the current status of the Wifi Aware instant communication mode.
+     * If the device doesn't support this feature, return will always be false.
+     * @see Characteristics#isInstantCommunicationModeSupported()
+     * @return true if it is enabled, false otherwise.
+     */
+    public boolean isInstantCommunicationModeEnabled() {
+        if (!SdkLevelUtil.isAtLeastS()) {
+            throw new UnsupportedOperationException();
+        }
+        try {
+            return mService.isInstantCommunicationModeEnabled();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Returns the characteristics of the Wi-Fi Aware interface: a set of parameters which specify
      * limitations on configurations, e.g. the maximum service name length.
      *
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
index d163fb0..2cf7f2c 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
@@ -22,6 +22,7 @@
 import static org.hamcrest.core.IsEqual.equalTo;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
@@ -38,6 +39,7 @@
 import android.net.MacAddress;
 import android.net.wifi.RttManager;
 import android.net.wifi.util.HexEncoding;
+import android.net.wifi.util.SdkLevelUtil;
 import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
@@ -156,6 +158,19 @@
         verify(mockAwareService).isDeviceAttached();
     }
 
+    /**
+     * Validate pass-through of isInstantCommunicationModeEnabled() and
+     * enableInstantCommunicationMode() API
+     */
+    @Test
+    public void testEnableInstantCommunicationMode() throws Exception {
+        assumeTrue(SdkLevelUtil.isAtLeastS());
+        mDut.isInstantCommunicationModeEnabled();
+        verify(mockAwareService).isInstantCommunicationModeEnabled();
+        mDut.enableInstantCommunicationMode(true);
+        verify(mockAwareService).enableInstantCommunicationMode(anyString(), eq(true));
+    }
+
     /*
      * WifiAwareEventCallbackProxy Tests
      */