Merge "Update getAuthenticatorId logic" into sc-dev
diff --git a/Android.bp b/Android.bp
index 8b15f02..77044d6 100644
--- a/Android.bp
+++ b/Android.bp
@@ -424,6 +424,7 @@
         ":libbluetooth-binder-aidl",
         ":libcamera_client_aidl",
         ":libcamera_client_framework_aidl",
+        ":packagemanager_aidl",
         ":libupdate_engine_aidl",
         ":resourcemanager_aidl",
         ":storaged_aidl",
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
index 0f6468a..4dd1b79 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
@@ -32,13 +32,11 @@
 import com.android.internal.util.Preconditions;
 
 import java.io.Closeable;
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
-import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
 import java.util.function.Consumer;
 
@@ -158,68 +156,16 @@
                     schemasPackageAccessibleBundles,
                     callbackExecutor,
                     callback);
-            return;
-        }
-
-        try {
-            // Migration process
-            // 1. Generate the current and the final version map.
-            // TODO(b/182855402) Release binder thread and move the heavy work into worker thread.
-            AndroidFuture<AppSearchResult<GetSchemaResponse>> future = new AndroidFuture<>();
-            getSchema(callbackExecutor, future::complete);
-            AppSearchResult<GetSchemaResponse> getSchemaResult = future.get();
-            if (!getSchemaResult.isSuccess()) {
-                callback.accept(AppSearchResult.newFailedResult(getSchemaResult));
-                return;
-            }
-            GetSchemaResponse getSchemaResponse = getSchemaResult.getResultValue();
-            Set<AppSearchSchema> currentSchemas = getSchemaResponse.getSchemas();
-            Map<String, Integer> currentVersionMap =
-                    SchemaMigrationUtil.buildVersionMap(currentSchemas,
-                            getSchemaResponse.getVersion());
-            Map<String, Integer> finalVersionMap =
-                    SchemaMigrationUtil.buildVersionMap(request.getSchemas(), request.getVersion());
-
-            // 2. SetSchema with forceOverride=false, to retrieve the list of incompatible/deleted
-            // types.
-            mService.setSchema(
-                    mPackageName,
-                    mDatabaseName,
+        } else {
+            setSchemaWithMigrations(
+                    request,
                     schemaBundles,
-                    new ArrayList<>(request.getSchemasNotDisplayedBySystem()),
                     schemasPackageAccessibleBundles,
-                    /*forceOverride=*/ false,
-                    mUserId,
-                    request.getVersion(),
-                    new IAppSearchResultCallback.Stub() {
-                        public void onResult(AppSearchResult result) {
-                            callbackExecutor.execute(() -> {
-                                if (result.isSuccess()) {
-                                    // TODO(b/183177268): once migration is implemented, run
-                                    //  it on workExecutor.
-                                    try {
-                                        Bundle bundle = (Bundle) result.getResultValue();
-                                        SetSchemaResponse setSchemaResponse =
-                                                new SetSchemaResponse(bundle);
-                                        setSchemaMigration(
-                                                request, setSchemaResponse, schemaBundles,
-                                                schemasPackageAccessibleBundles, currentVersionMap,
-                                                finalVersionMap, callback);
-                                    } catch (Throwable t) {
-                                        callback.accept(AppSearchResult.throwableToFailedResult(t));
-                                    }
-                                } else {
-                                    callback.accept(result);
-                                }
-                            });
-                        }
-                    });
-            mIsMutated = true;
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }  catch (Throwable t) {
-            callback.accept(AppSearchResult.throwableToFailedResult(t));
+                    workExecutor,
+                    callbackExecutor,
+                    callback);
         }
+        mIsMutated = true;
     }
 
     /**
@@ -641,8 +587,28 @@
         Objects.requireNonNull(executor);
         Objects.requireNonNull(callback);
         Preconditions.checkState(!mIsClosed, "AppSearchSession has already been closed");
-        // TODO(b/182909475): Implement getStorageInfo
-        throw new UnsupportedOperationException();
+        try {
+            mService.getStorageInfo(
+                    mPackageName,
+                    mDatabaseName,
+                    mUserId,
+                    new IAppSearchResultCallback.Stub() {
+                        public void onResult(AppSearchResult result) {
+                            executor.execute(() -> {
+                                if (result.isSuccess()) {
+                                    Bundle responseBundle = (Bundle) result.getResultValue();
+                                    StorageInfo response =
+                                            new StorageInfo(responseBundle);
+                                    callback.accept(AppSearchResult.newSuccessfulResult(response));
+                                } else {
+                                    callback.accept(result);
+                                }
+                            });
+                        }
+                    });
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -667,7 +633,8 @@
      * <p>We only need one time {@link #setSchema} call for no-migration scenario by using the
      * forceoverride in the request.
      */
-    private void setSchemaNoMigrations(@NonNull SetSchemaRequest request,
+    private void setSchemaNoMigrations(
+            @NonNull SetSchemaRequest request,
             @NonNull List<Bundle> schemaBundles,
             @NonNull Map<String, List<Bundle>> schemasPackageAccessibleBundles,
             @NonNull @CallbackExecutor Executor executor,
@@ -709,7 +676,6 @@
                             });
                         }
                     });
-            mIsMutated = true;
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -721,86 +687,144 @@
      * <p>First time {@link #setSchema} call with forceOverride is false gives us all incompatible
      * changes. After trigger migrations, the second time call {@link #setSchema} will actually
      * apply the changes.
-     *
-     * @param setSchemaResponse the result of the first setSchema call with forceOverride=false.
      */
-    private void setSchemaMigration(@NonNull SetSchemaRequest request,
-            @NonNull SetSchemaResponse setSchemaResponse,
+    private void setSchemaWithMigrations(
+            @NonNull SetSchemaRequest request,
             @NonNull List<Bundle> schemaBundles,
             @NonNull Map<String, List<Bundle>> schemasPackageAccessibleBundles,
-            @NonNull Map<String, Integer> currentVersionMap, Map<String, Integer> finalVersionMap,
-            @NonNull Consumer<AppSearchResult<SetSchemaResponse>> callback)
-            throws AppSearchException, IOException, RemoteException, ExecutionException,
-            InterruptedException {
-        // 1. If forceOverride is false, check that all incompatible types will be migrated.
-        // If some aren't we must throw an error, rather than proceeding and deleting those
-        // types.
-        if (!request.isForceOverride()) {
-            Set<String> unmigratedTypes = SchemaMigrationUtil.getUnmigratedIncompatibleTypes(
-                    setSchemaResponse.getIncompatibleTypes(),
-                    request.getMigrators(),
-                    currentVersionMap,
-                    finalVersionMap);
-            // check if there are any unmigrated types or deleted types. If there are, we will throw
-            // an exception.
-            // Since the force override is false, the schema will not have been set if there are any
-            // incompatible or deleted types.
-            checkDeletedAndIncompatible(setSchemaResponse.getDeletedTypes(),
-                    unmigratedTypes);
-        }
-
-        try (AppSearchMigrationHelper migrationHelper =
-                     new AppSearchMigrationHelper(mService, mUserId, currentVersionMap,
-                             finalVersionMap, mPackageName, mDatabaseName)) {
-            Map<String, Migrator> migratorMap = request.getMigrators();
-
-            // 2. Trigger migration for all migrators.
-            // TODO(b/177266929) trigger migration for all types together rather than separately.
-            Set<String> migratedTypes = new ArraySet<>();
-            for (Map.Entry<String, Migrator> entry : migratorMap.entrySet()) {
-                String schemaType = entry.getKey();
-                Migrator migrator = entry.getValue();
-                if (SchemaMigrationUtil.shouldTriggerMigration(
-                        schemaType, migrator, currentVersionMap, finalVersionMap)) {
-                    migrationHelper.queryAndTransform(schemaType, migrator);
-                    migratedTypes.add(schemaType);
+            @NonNull Executor workExecutor,
+            @NonNull @CallbackExecutor Executor callbackExecutor,
+            @NonNull Consumer<AppSearchResult<SetSchemaResponse>> callback) {
+        workExecutor.execute(() -> {
+            try {
+                // Migration process
+                // 1. Generate the current and the final version map.
+                AndroidFuture<AppSearchResult<GetSchemaResponse>> getSchemaFuture =
+                        new AndroidFuture<>();
+                getSchema(callbackExecutor, getSchemaFuture::complete);
+                AppSearchResult<GetSchemaResponse> getSchemaResult = getSchemaFuture.get();
+                if (!getSchemaResult.isSuccess()) {
+                    callbackExecutor.execute(() ->
+                            callback.accept(AppSearchResult.newFailedResult(getSchemaResult)));
+                    return;
                 }
-            }
+                GetSchemaResponse getSchemaResponse = getSchemaResult.getResultValue();
+                Set<AppSearchSchema> currentSchemas = getSchemaResponse.getSchemas();
+                Map<String, Integer> currentVersionMap = SchemaMigrationUtil.buildVersionMap(
+                        currentSchemas, getSchemaResponse.getVersion());
+                Map<String, Integer> finalVersionMap = SchemaMigrationUtil.buildVersionMap(
+                        request.getSchemas(), request.getVersion());
 
-            // 3. SetSchema a second time with forceOverride=true if the first attempted failed.
-            if (!setSchemaResponse.getIncompatibleTypes().isEmpty()
-                    || !setSchemaResponse.getDeletedTypes().isEmpty()) {
-                AndroidFuture<AppSearchResult<SetSchemaResponse>> future = new AndroidFuture<>();
-                // only trigger second setSchema() call if the first one is fail.
+                // 2. SetSchema with forceOverride=false, to retrieve the list of
+                // incompatible/deleted types.
+                AndroidFuture<AppSearchResult<Bundle>> setSchemaFuture = new AndroidFuture<>();
                 mService.setSchema(
                         mPackageName,
                         mDatabaseName,
                         schemaBundles,
                         new ArrayList<>(request.getSchemasNotDisplayedBySystem()),
                         schemasPackageAccessibleBundles,
-                        /*forceOverride=*/ true,
+                        /*forceOverride=*/ false,
                         mUserId,
                         request.getVersion(),
                         new IAppSearchResultCallback.Stub() {
-                            @Override
-                            public void onResult(AppSearchResult result) throws RemoteException {
-                                future.complete(result);
+                            public void onResult(AppSearchResult result) {
+                                setSchemaFuture.complete(result);
                             }
                         });
-                AppSearchResult<SetSchemaResponse> secondSetSchemaResult = future.get();
-                if (!secondSetSchemaResult.isSuccess()) {
-                    // we failed to set the schema in second time with force override = true, which
-                    // is an impossible case. Since we only swallow the incompatible error in the
-                    // first setSchema call, all other errors will be thrown at the first time.
-                    callback.accept(secondSetSchemaResult);
+                AppSearchResult<Bundle> setSchemaResult = setSchemaFuture.get();
+                if (!setSchemaResult.isSuccess()) {
+                    callbackExecutor.execute(() ->
+                            callback.accept(AppSearchResult.newFailedResult(setSchemaResult)));
                     return;
                 }
-            }
+                SetSchemaResponse setSchemaResponse =
+                        new SetSchemaResponse(setSchemaResult.getResultValue());
 
-            SetSchemaResponse.Builder responseBuilder = setSchemaResponse.toBuilder()
-                    .addMigratedTypes(migratedTypes);
-            callback.accept(migrationHelper.putMigratedDocuments(responseBuilder));
-        }
+                // 1. If forceOverride is false, check that all incompatible types will be migrated.
+                // If some aren't we must throw an error, rather than proceeding and deleting those
+                // types.
+                if (!request.isForceOverride()) {
+                    Set<String> unmigratedTypes =
+                            SchemaMigrationUtil.getUnmigratedIncompatibleTypes(
+                                    setSchemaResponse.getIncompatibleTypes(),
+                                    request.getMigrators(),
+                                    currentVersionMap,
+                                    finalVersionMap);
+
+                    // check if there are any unmigrated types or deleted types. If there are, we
+                    // will throw an exception.
+                    // Since the force override is false, the schema will not have been set if there
+                    // are any incompatible or deleted types.
+                    checkDeletedAndIncompatible(
+                            setSchemaResponse.getDeletedTypes(), unmigratedTypes);
+                }
+
+                try (AppSearchMigrationHelper migrationHelper =
+                             new AppSearchMigrationHelper(
+                                     mService, mUserId, currentVersionMap, finalVersionMap,
+                                     mPackageName, mDatabaseName)) {
+                    Map<String, Migrator> migratorMap = request.getMigrators();
+
+                    // 2. Trigger migration for all migrators.
+                    // TODO(b/177266929) trigger migration for all types together rather than
+                    //  separately.
+                    Set<String> migratedTypes = new ArraySet<>();
+                    for (Map.Entry<String, Migrator> entry : migratorMap.entrySet()) {
+                        String schemaType = entry.getKey();
+                        Migrator migrator = entry.getValue();
+                        if (SchemaMigrationUtil.shouldTriggerMigration(
+                                schemaType, migrator, currentVersionMap, finalVersionMap)) {
+                            migrationHelper.queryAndTransform(schemaType, migrator);
+                            migratedTypes.add(schemaType);
+                        }
+                    }
+
+                    // 3. SetSchema a second time with forceOverride=true if the first attempted
+                    // failed.
+                    if (!setSchemaResponse.getIncompatibleTypes().isEmpty()
+                            || !setSchemaResponse.getDeletedTypes().isEmpty()) {
+                        AndroidFuture<AppSearchResult<Bundle>> setSchema2Future =
+                                new AndroidFuture<>();
+                        // only trigger second setSchema() call if the first one is fail.
+                        mService.setSchema(
+                                mPackageName,
+                                mDatabaseName,
+                                schemaBundles,
+                                new ArrayList<>(request.getSchemasNotDisplayedBySystem()),
+                                schemasPackageAccessibleBundles,
+                                /*forceOverride=*/ true,
+                                request.getVersion(),
+                                mUserId,
+                                new IAppSearchResultCallback.Stub() {
+                                    @Override
+                                    public void onResult(AppSearchResult result) {
+                                        setSchema2Future.complete(result);
+                                    }
+                                });
+                        AppSearchResult<Bundle> setSchema2Result = setSchema2Future.get();
+                        if (!setSchema2Result.isSuccess()) {
+                            // we failed to set the schema in second time with forceOverride = true,
+                            // which is an impossible case. Since we only swallow the incompatible
+                            // error in the first setSchema call, all other errors will be thrown at
+                            // the first time.
+                            callbackExecutor.execute(() -> callback.accept(
+                                    AppSearchResult.newFailedResult(setSchemaResult)));
+                            return;
+                        }
+                    }
+
+                    SetSchemaResponse.Builder responseBuilder = setSchemaResponse.toBuilder()
+                            .addMigratedTypes(migratedTypes);
+                    AppSearchResult<SetSchemaResponse> putResult =
+                            migrationHelper.putMigratedDocuments(responseBuilder);
+                    callbackExecutor.execute(() -> callback.accept(putResult));
+                }
+            } catch (Throwable t) {
+                callbackExecutor.execute(() -> callback.accept(
+                        AppSearchResult.throwableToFailedResult(t)));
+            }
+        });
     }
 
     /**  Checks the setSchema() call won't delete any types or has incompatible types. */
diff --git a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
index 48c397f..a8ac27c 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
+++ b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
@@ -307,6 +307,22 @@
         in IAppSearchResultCallback callback);
 
     /**
+     * Gets the storage info.
+     *
+     * @param packageName The name of the package to get the storage info for.
+     * @param databaseName The databaseName to get the storage info for.
+     * @param userId Id of the calling user
+     * @param callback {@link IAppSearchResultCallback#onResult} will be called with an
+     *     {@link AppSearchResult}&lt;{@link Bundle}&gt;, where the value is a
+     *     {@link StorageInfo}.
+     */
+    void getStorageInfo(
+        in String packageName,
+        in String databaseName,
+        in int userId,
+        in IAppSearchResultCallback callback);
+
+    /**
      * Persists all update/delete requests to the disk.
      *
      * @param userId Id of the calling user
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 91ed6cd..991dda7 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -33,6 +33,7 @@
 import android.app.appsearch.SearchResultPage;
 import android.app.appsearch.SearchSpec;
 import android.app.appsearch.SetSchemaResponse;
+import android.app.appsearch.StorageInfo;
 import android.content.Context;
 import android.content.pm.PackageManagerInternal;
 import android.os.Binder;
@@ -610,6 +611,34 @@
         }
 
         @Override
+        public void getStorageInfo(
+                @NonNull String packageName,
+                @NonNull String databaseName,
+                @UserIdInt int userId,
+                @NonNull IAppSearchResultCallback callback) {
+            Preconditions.checkNotNull(packageName);
+            Preconditions.checkNotNull(databaseName);
+            Preconditions.checkNotNull(callback);
+            int callingUid = Binder.getCallingUid();
+            int callingUserId = handleIncomingUser(userId, callingUid);
+            final long callingIdentity = Binder.clearCallingIdentity();
+            try {
+                verifyUserUnlocked(callingUserId);
+                verifyCallingPackage(callingUid, packageName);
+                AppSearchImpl impl =
+                        mImplInstanceManager.getAppSearchImpl(callingUserId);
+                StorageInfo storageInfo = impl.getStorageInfoForDatabase(packageName, databaseName);
+                Bundle storageInfoBundle = storageInfo.getBundle();
+                invokeCallbackOnResult(
+                        callback, AppSearchResult.newSuccessfulResult(storageInfoBundle));
+            } catch (Throwable t) {
+                invokeCallbackOnError(callback, t);
+            } finally {
+                Binder.restoreCallingIdentity(callingIdentity);
+            }
+        }
+
+        @Override
         public void persistToDisk(@UserIdInt int userId) {
             int callingUid = Binder.getCallingUidOrThrow();
             int callingUserId = handleIncomingUser(userId, callingUid);
diff --git a/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java b/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java
index 38500af..22ee501 100644
--- a/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java
+++ b/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java
@@ -258,7 +258,8 @@
     public @NonNull ParcelFileDescriptor openBlob(@NonNull BlobHandle blobHandle)
             throws IOException {
         try {
-            return mService.openBlob(blobHandle, mContext.getOpPackageName());
+            return mService.openBlob(blobHandle, mContext.getOpPackageName(),
+                    mContext.getAttributionTag());
         } catch (ParcelableException e) {
             e.maybeRethrow(IOException.class);
             throw new RuntimeException(e);
@@ -315,7 +316,7 @@
             @CurrentTimeMillisLong long leaseExpiryTimeMillis) throws IOException {
         try {
             mService.acquireLease(blobHandle, descriptionResId, null, leaseExpiryTimeMillis,
-                    mContext.getOpPackageName());
+                    mContext.getOpPackageName(), mContext.getAttributionTag());
         } catch (ParcelableException e) {
             e.maybeRethrow(IOException.class);
             e.maybeRethrow(LimitExceededException.class);
@@ -378,7 +379,7 @@
             @CurrentTimeMillisLong long leaseExpiryTimeMillis) throws IOException {
         try {
             mService.acquireLease(blobHandle, INVALID_RES_ID, description, leaseExpiryTimeMillis,
-                    mContext.getOpPackageName());
+                    mContext.getOpPackageName(), mContext.getAttributionTag());
         } catch (ParcelableException e) {
             e.maybeRethrow(IOException.class);
             e.maybeRethrow(LimitExceededException.class);
@@ -497,7 +498,8 @@
      */
     public void releaseLease(@NonNull BlobHandle blobHandle) throws IOException {
         try {
-            mService.releaseLease(blobHandle, mContext.getOpPackageName());
+            mService.releaseLease(blobHandle, mContext.getOpPackageName(),
+                    mContext.getAttributionTag());
         } catch (ParcelableException e) {
             e.maybeRethrow(IOException.class);
             throw new RuntimeException(e);
@@ -602,7 +604,8 @@
     @Nullable
     public LeaseInfo getLeaseInfo(@NonNull BlobHandle blobHandle) throws IOException {
         try {
-            return mService.getLeaseInfo(blobHandle, mContext.getOpPackageName());
+            return mService.getLeaseInfo(blobHandle, mContext.getOpPackageName(),
+                    mContext.getAttributionTag());
         } catch (ParcelableException e) {
             e.maybeRethrow(IOException.class);
             throw new RuntimeException(e);
@@ -897,6 +900,64 @@
         }
 
         /**
+         * Allow apps with location permission to access this blob data once it is committed using
+         * a {@link BlobHandle} representing the blob.
+         *
+         * <p> This needs to be called before committing the blob using
+         * {@link #commit(Executor, Consumer)}.
+         *
+         * Note that if a caller allows access to the blob using this API in addition to other APIs
+         * like {@link #allowPackageAccess(String, byte[])}, then apps satisfying any one of these
+         * access conditions will be allowed to access the blob.
+         *
+         * @param permissionName the name of the location permission that needs to be granted
+         *                       for the app. This can be either one of
+         *                       {@link android.Manifest.permission#ACCESS_FINE_LOCATION} or
+         *                       {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}.
+         *
+         * @throws IOException when there is an I/O error while changing the access.
+         * @throws SecurityException when the caller is not the owner of the session.
+         * @throws IllegalStateException when the caller tries to change access for a blob which is
+         *                               already committed.
+         */
+        public void allowPackagesWithLocationPermission(@NonNull String permissionName)
+                throws IOException {
+            try {
+                mSession.allowPackagesWithLocationPermission(permissionName);
+            } catch (ParcelableException e) {
+                e.maybeRethrow(IOException.class);
+                throw new RuntimeException(e);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        /**
+         * Returns {@code true} if access has been allowed for apps with location permission by
+         * using {@link #allowPackagesWithLocationPermission(String)}.
+         *
+         * @param permissionName the name of the location permission that needs to be granted
+         *                       for the app. This can be either one of
+         *                       {@link android.Manifest.permission#ACCESS_FINE_LOCATION} or
+         *                       {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}.
+         *
+         * @throws IOException when there is an I/O error while getting the access type.
+         * @throws IllegalStateException when the caller tries to get access type from a session
+         *                               which is closed or abandoned.
+         */
+        public boolean arePackagesWithLocationPermissionAllowed(@NonNull String permissionName)
+                throws IOException {
+            try {
+                return mSession.arePackagesWithLocationPermissionAllowed(permissionName);
+            } catch (ParcelableException e) {
+                e.maybeRethrow(IOException.class);
+                throw new RuntimeException(e);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        /**
          * Commit the file that was written so far to this session to the blob store maintained by
          * the system.
          *
diff --git a/apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl b/apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl
index 39a9fb4..db6cb5c9 100644
--- a/apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl
+++ b/apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl
@@ -25,12 +25,13 @@
 interface IBlobStoreManager {
     long createSession(in BlobHandle handle, in String packageName);
     IBlobStoreSession openSession(long sessionId, in String packageName);
-    ParcelFileDescriptor openBlob(in BlobHandle handle, in String packageName);
+    ParcelFileDescriptor openBlob(in BlobHandle handle, in String packageName,
+           in String attributionTag);
     void abandonSession(long sessionId, in String packageName);
 
     void acquireLease(in BlobHandle handle, int descriptionResId, in CharSequence description,
-            long leaseTimeoutMillis, in String packageName);
-    void releaseLease(in BlobHandle handle, in String packageName);
+            long leaseTimeoutMillis, in String packageName, in String attributionTag);
+    void releaseLease(in BlobHandle handle, in String packageName, in String attributionTag);
     long getRemainingLeaseQuotaBytes(String packageName);
 
     void waitForIdle(in RemoteCallback callback);
@@ -39,5 +40,6 @@
     void deleteBlob(long blobId);
 
     List<BlobHandle> getLeasedBlobs(in String packageName);
-    LeaseInfo getLeaseInfo(in BlobHandle blobHandle, in String packageName);
+    LeaseInfo getLeaseInfo(in BlobHandle blobHandle, in String packageName,
+            in String attributionTag);
 }
\ No newline at end of file
diff --git a/apex/blobstore/framework/java/android/app/blob/IBlobStoreSession.aidl b/apex/blobstore/framework/java/android/app/blob/IBlobStoreSession.aidl
index 4035b96..e3ccfb8 100644
--- a/apex/blobstore/framework/java/android/app/blob/IBlobStoreSession.aidl
+++ b/apex/blobstore/framework/java/android/app/blob/IBlobStoreSession.aidl
@@ -26,10 +26,12 @@
     void allowPackageAccess(in String packageName, in byte[] certificate);
     void allowSameSignatureAccess();
     void allowPublicAccess();
+    void allowPackagesWithLocationPermission(in String permissionName);
 
     boolean isPackageAccessAllowed(in String packageName, in byte[] certificate);
     boolean isSameSignatureAccessAllowed();
     boolean isPublicAccessAllowed();
+    boolean arePackagesWithLocationPermissionAllowed(in String permissionName);
 
     long getSize();
     void close();
diff --git a/apex/blobstore/framework/java/android/app/blob/XmlTags.java b/apex/blobstore/framework/java/android/app/blob/XmlTags.java
index bfc5826..6e4b2f7 100644
--- a/apex/blobstore/framework/java/android/app/blob/XmlTags.java
+++ b/apex/blobstore/framework/java/android/app/blob/XmlTags.java
@@ -38,6 +38,7 @@
     public static final String ATTR_TYPE = "t";
     public static final String TAG_ALLOWED_PACKAGE = "wl";
     public static final String ATTR_CERTIFICATE = "ct";
+    public static final String TAG_ALLOWED_PERMISSION = "ap";
 
     // For BlobHandle
     public static final String TAG_BLOB_HANDLE = "bh";
@@ -55,4 +56,7 @@
     public static final String TAG_LEASEE = "l";
     public static final String ATTR_DESCRIPTION_RES_NAME = "rn";
     public static final String ATTR_DESCRIPTION = "d";
+
+    // Generic
+    public static final String ATTR_VALUE = "val";
 }
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java b/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java
index 4a527ad..ca588c5 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java
@@ -15,18 +15,29 @@
  */
 package com.android.server.blob;
 
+import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
+import static android.Manifest.permission.ACCESS_FINE_LOCATION;
 import static android.app.blob.XmlTags.ATTR_CERTIFICATE;
 import static android.app.blob.XmlTags.ATTR_PACKAGE;
 import static android.app.blob.XmlTags.ATTR_TYPE;
+import static android.app.blob.XmlTags.ATTR_VALUE;
 import static android.app.blob.XmlTags.TAG_ALLOWED_PACKAGE;
+import static android.app.blob.XmlTags.TAG_ALLOWED_PERMISSION;
+
+import static com.android.server.blob.BlobStoreConfig.TAG;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.AppOpsManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.os.UserHandle;
+import android.permission.PermissionManager;
 import android.util.ArraySet;
 import android.util.Base64;
 import android.util.DebugUtils;
+import android.util.Slog;
 
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.XmlUtils;
@@ -53,21 +64,27 @@
             ACCESS_TYPE_PUBLIC,
             ACCESS_TYPE_SAME_SIGNATURE,
             ACCESS_TYPE_ALLOWLIST,
+            ACCESS_TYPE_LOCATION_PERMISSION,
     })
     @interface AccessType {}
     public static final int ACCESS_TYPE_PRIVATE = 1 << 0;
     public static final int ACCESS_TYPE_PUBLIC = 1 << 1;
     public static final int ACCESS_TYPE_SAME_SIGNATURE = 1 << 2;
     public static final int ACCESS_TYPE_ALLOWLIST = 1 << 3;
+    public static final int ACCESS_TYPE_LOCATION_PERMISSION = 1 << 4;
 
     private int mAccessType = ACCESS_TYPE_PRIVATE;
 
     private final ArraySet<PackageIdentifier> mAllowedPackages = new ArraySet<>();
+    private final ArraySet<String> mAllowedPermissions = new ArraySet<>();
 
     void allow(BlobAccessMode other) {
         if ((other.mAccessType & ACCESS_TYPE_ALLOWLIST) != 0) {
             mAllowedPackages.addAll(other.mAllowedPackages);
         }
+        if ((other.mAccessType & ACCESS_TYPE_LOCATION_PERMISSION) != 0) {
+            mAllowedPermissions.addAll(other.mAllowedPermissions);
+        }
         mAccessType |= other.mAccessType;
     }
 
@@ -84,6 +101,11 @@
         mAllowedPackages.add(PackageIdentifier.create(packageName, certificate));
     }
 
+    void allowPackagesWithLocationPermission(@NonNull String permissionName) {
+        mAccessType |= ACCESS_TYPE_LOCATION_PERMISSION;
+        mAllowedPermissions.add(permissionName);
+    }
+
     boolean isPublicAccessAllowed() {
         return (mAccessType & ACCESS_TYPE_PUBLIC) != 0;
     }
@@ -99,8 +121,15 @@
         return mAllowedPackages.contains(PackageIdentifier.create(packageName, certificate));
     }
 
-    boolean isAccessAllowedForCaller(Context context,
-            @NonNull String callingPackage, @NonNull String committerPackage) {
+    boolean arePackagesWithLocationPermissionAllowed(@NonNull String permissionName) {
+        if ((mAccessType & ACCESS_TYPE_LOCATION_PERMISSION) == 0) {
+            return false;
+        }
+        return mAllowedPermissions.contains(permissionName);
+    }
+
+    boolean isAccessAllowedForCaller(Context context, @NonNull String callingPackage,
+            @NonNull String committerPackage, int callingUid, @Nullable String attributionTag) {
         if ((mAccessType & ACCESS_TYPE_PUBLIC) != 0) {
             return true;
         }
@@ -124,9 +153,37 @@
             }
         }
 
+        if ((mAccessType & ACCESS_TYPE_LOCATION_PERMISSION) != 0) {
+            final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
+            for (int i = 0; i < mAllowedPermissions.size(); ++i) {
+                final String permission = mAllowedPermissions.valueAt(i);
+                if (PermissionManager.checkPackageNamePermission(permission, callingPackage,
+                        UserHandle.getUserId(callingUid)) != PackageManager.PERMISSION_GRANTED) {
+                    continue;
+                }
+                // TODO: Add appropriate message
+                if (appOpsManager.noteOpNoThrow(getAppOp(permission), callingUid, callingPackage,
+                        attributionTag, null /* message */) == AppOpsManager.MODE_ALLOWED) {
+                    return true;
+                }
+            }
+        }
+
         return false;
     }
 
+    private static String getAppOp(String permission) {
+        switch (permission) {
+            case ACCESS_FINE_LOCATION:
+                return AppOpsManager.OPSTR_FINE_LOCATION;
+            case ACCESS_COARSE_LOCATION:
+                return AppOpsManager.OPSTR_COARSE_LOCATION;
+            default:
+                Slog.w(TAG, "Unknown permission found: " + permission);
+                return null;
+        }
+    }
+
     int getAccessType() {
         return mAccessType;
     }
@@ -148,6 +205,16 @@
             }
             fout.decreaseIndent();
         }
+        fout.print("Allowed permissions:");
+        if (mAllowedPermissions.isEmpty()) {
+            fout.println(" (Empty)");
+        } else {
+            fout.increaseIndent();
+            for (int i = 0, count = mAllowedPermissions.size(); i < count; ++i) {
+                fout.println(mAllowedPermissions.valueAt(i).toString());
+            }
+            fout.decreaseIndent();
+        }
     }
 
     void writeToXml(@NonNull XmlSerializer out) throws IOException {
@@ -159,6 +226,12 @@
             XmlUtils.writeByteArrayAttribute(out, ATTR_CERTIFICATE, packageIdentifier.certificate);
             out.endTag(null, TAG_ALLOWED_PACKAGE);
         }
+        for (int i = 0, count = mAllowedPermissions.size(); i < count; ++i) {
+            out.startTag(null, TAG_ALLOWED_PERMISSION);
+            final String permission = mAllowedPermissions.valueAt(i);
+            XmlUtils.writeStringAttribute(out, ATTR_VALUE, permission);
+            out.endTag(null, TAG_ALLOWED_PERMISSION);
+        }
     }
 
     @NonNull
@@ -176,6 +249,10 @@
                 final byte[] certificate = XmlUtils.readByteArrayAttribute(in, ATTR_CERTIFICATE);
                 blobAccessMode.allowPackageAccess(packageName, certificate);
             }
+            if (TAG_ALLOWED_PERMISSION.equals(in.getName())) {
+                final String permission = XmlUtils.readStringAttribute(in, ATTR_VALUE);
+                blobAccessMode.allowPackagesWithLocationPermission(permission);
+            }
         }
         return blobAccessMode;
     }
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java b/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
index fb02e96..8b12beb 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
@@ -229,7 +229,8 @@
         return getBlobFile().length();
     }
 
-    boolean isAccessAllowedForCaller(@NonNull String callingPackage, int callingUid) {
+    boolean isAccessAllowedForCaller(@NonNull String callingPackage, int callingUid,
+            @Nullable String attributionTag) {
         // Don't allow the blob to be accessed after it's expiry time has passed.
         if (getBlobHandle().isExpired()) {
             return false;
@@ -254,7 +255,7 @@
                 // Check if the caller is allowed access as per the access mode specified
                 // by the committer.
                 if (committer.blobAccessMode.isAccessAllowedForCaller(mContext,
-                        callingPackage, committer.packageName)) {
+                        callingPackage, committer.packageName, callingUid, attributionTag)) {
                     return true;
                 }
             }
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
index f77f6c6..0e73547 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
@@ -402,12 +402,12 @@
     }
 
     private ParcelFileDescriptor openBlobInternal(BlobHandle blobHandle, int callingUid,
-            String callingPackage) throws IOException {
+            String callingPackage, String attributionTag) throws IOException {
         synchronized (mBlobsLock) {
             final BlobMetadata blobMetadata = getUserBlobsLocked(UserHandle.getUserId(callingUid))
                     .get(blobHandle);
             if (blobMetadata == null || !blobMetadata.isAccessAllowedForCaller(
-                    callingPackage, callingUid)) {
+                    callingPackage, callingUid, attributionTag)) {
                 if (blobMetadata == null) {
                     FrameworkStatsLog.write(FrameworkStatsLog.BLOB_OPENED, callingUid,
                             INVALID_BLOB_ID, INVALID_BLOB_SIZE,
@@ -455,7 +455,7 @@
 
     private void acquireLeaseInternal(BlobHandle blobHandle, int descriptionResId,
             CharSequence description, long leaseExpiryTimeMillis,
-            int callingUid, String callingPackage) {
+            int callingUid, String callingPackage, String attributionTag) {
         synchronized (mBlobsLock) {
             final int leasesCount = getLeasedBlobsCountLocked(callingUid, callingPackage);
             if (leasesCount >= getMaxLeasedBlobs()) {
@@ -468,7 +468,7 @@
             final BlobMetadata blobMetadata = getUserBlobsLocked(UserHandle.getUserId(callingUid))
                     .get(blobHandle);
             if (blobMetadata == null || !blobMetadata.isAccessAllowedForCaller(
-                    callingPackage, callingUid)) {
+                    callingPackage, callingUid, attributionTag)) {
                 if (blobMetadata == null) {
                     FrameworkStatsLog.write(FrameworkStatsLog.BLOB_LEASED, callingUid,
                             INVALID_BLOB_ID, INVALID_BLOB_SIZE,
@@ -527,13 +527,13 @@
     }
 
     private void releaseLeaseInternal(BlobHandle blobHandle, int callingUid,
-            String callingPackage) {
+            String callingPackage, String attributionTag) {
         synchronized (mBlobsLock) {
             final ArrayMap<BlobHandle, BlobMetadata> userBlobs =
                     getUserBlobsLocked(UserHandle.getUserId(callingUid));
             final BlobMetadata blobMetadata = userBlobs.get(blobHandle);
             if (blobMetadata == null || !blobMetadata.isAccessAllowedForCaller(
-                    callingPackage, callingUid)) {
+                    callingPackage, callingUid, attributionTag)) {
                 throw new SecurityException("Caller not allowed to access " + blobHandle
                         + "; callingUid=" + callingUid + ", callingPackage=" + callingPackage);
             }
@@ -634,12 +634,12 @@
     }
 
     private LeaseInfo getLeaseInfoInternal(BlobHandle blobHandle,
-            int callingUid, @NonNull String callingPackage) {
+            int callingUid, @NonNull String callingPackage, String attributionTag) {
         synchronized (mBlobsLock) {
             final BlobMetadata blobMetadata = getUserBlobsLocked(UserHandle.getUserId(callingUid))
                     .get(blobHandle);
             if (blobMetadata == null || !blobMetadata.isAccessAllowedForCaller(
-                    callingPackage, callingUid)) {
+                    callingPackage, callingUid, attributionTag)) {
                 throw new SecurityException("Caller not allowed to access " + blobHandle
                         + "; callingUid=" + callingUid + ", callingPackage=" + callingPackage);
             }
@@ -1465,7 +1465,7 @@
 
         @Override
         public ParcelFileDescriptor openBlob(@NonNull BlobHandle blobHandle,
-                @NonNull String packageName) {
+                @NonNull String packageName, @Nullable String attributionTag) {
             Objects.requireNonNull(blobHandle, "blobHandle must not be null");
             blobHandle.assertIsValid();
             Objects.requireNonNull(packageName, "packageName must not be null");
@@ -1480,7 +1480,7 @@
             }
 
             try {
-                return openBlobInternal(blobHandle, callingUid, packageName);
+                return openBlobInternal(blobHandle, callingUid, packageName, attributionTag);
             } catch (IOException e) {
                 throw ExceptionUtils.wrap(e);
             }
@@ -1489,7 +1489,8 @@
         @Override
         public void acquireLease(@NonNull BlobHandle blobHandle, @IdRes int descriptionResId,
                 @Nullable CharSequence description,
-                @CurrentTimeSecondsLong long leaseExpiryTimeMillis, @NonNull String packageName) {
+                @CurrentTimeSecondsLong long leaseExpiryTimeMillis, @NonNull String packageName,
+                @Nullable String attributionTag) {
             Objects.requireNonNull(blobHandle, "blobHandle must not be null");
             blobHandle.assertIsValid();
             Preconditions.checkArgument(
@@ -1513,7 +1514,7 @@
 
             try {
                 acquireLeaseInternal(blobHandle, descriptionResId, description,
-                        leaseExpiryTimeMillis, callingUid, packageName);
+                        leaseExpiryTimeMillis, callingUid, packageName, attributionTag);
             } catch (Resources.NotFoundException e) {
                 throw new IllegalArgumentException(e);
             } catch (LimitExceededException e) {
@@ -1522,7 +1523,8 @@
         }
 
         @Override
-        public void releaseLease(@NonNull BlobHandle blobHandle, @NonNull String packageName) {
+        public void releaseLease(@NonNull BlobHandle blobHandle, @NonNull String packageName,
+                @Nullable String attributionTag) {
             Objects.requireNonNull(blobHandle, "blobHandle must not be null");
             blobHandle.assertIsValid();
             Objects.requireNonNull(packageName, "packageName must not be null");
@@ -1536,7 +1538,7 @@
                         + "callingUid=" + callingUid + ", callingPackage=" + packageName);
             }
 
-            releaseLeaseInternal(blobHandle, callingUid, packageName);
+            releaseLeaseInternal(blobHandle, callingUid, packageName, attributionTag);
         }
 
         @Override
@@ -1606,7 +1608,8 @@
 
         @Override
         @Nullable
-        public LeaseInfo getLeaseInfo(@NonNull BlobHandle blobHandle, @NonNull String packageName) {
+        public LeaseInfo getLeaseInfo(@NonNull BlobHandle blobHandle, @NonNull String packageName,
+                @Nullable String attributionTag) {
             Objects.requireNonNull(blobHandle, "blobHandle must not be null");
             blobHandle.assertIsValid();
             Objects.requireNonNull(packageName, "packageName must not be null");
@@ -1620,7 +1623,7 @@
                         + "callingUid=" + callingUid + ", callingPackage=" + packageName);
             }
 
-            return getLeaseInfoInternal(blobHandle, callingUid, packageName);
+            return getLeaseInfoInternal(blobHandle, callingUid, packageName, attributionTag);
         }
 
         @Override
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
index fe68882..2c3f682 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
@@ -15,6 +15,8 @@
  */
 package com.android.server.blob;
 
+import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
+import static android.Manifest.permission.ACCESS_FINE_LOCATION;
 import static android.app.blob.BlobStoreManager.COMMIT_RESULT_ERROR;
 import static android.app.blob.XmlTags.ATTR_CREATION_TIME_MS;
 import static android.app.blob.XmlTags.ATTR_ID;
@@ -366,6 +368,21 @@
     }
 
     @Override
+    public void allowPackagesWithLocationPermission(@NonNull String permissionName) {
+        assertCallerIsOwner();
+        Preconditions.checkArgument(ACCESS_FINE_LOCATION.equals(permissionName)
+                        || ACCESS_COARSE_LOCATION.equals(permissionName),
+                "permissionName is unknown: " + permissionName);
+        synchronized (mSessionLock) {
+            if (mState != STATE_OPENED) {
+                throw new IllegalStateException("Not allowed to change access type in state: "
+                        + stateToString(mState));
+            }
+            mBlobAccessMode.allowPackagesWithLocationPermission(permissionName);
+        }
+    }
+
+    @Override
     public boolean isPackageAccessAllowed(@NonNull String packageName,
             @NonNull byte[] certificate) {
         assertCallerIsOwner();
@@ -406,6 +423,21 @@
     }
 
     @Override
+    public boolean arePackagesWithLocationPermissionAllowed(@NonNull String permissionName) {
+        assertCallerIsOwner();
+        Preconditions.checkArgument(ACCESS_FINE_LOCATION.equals(permissionName)
+                        || ACCESS_COARSE_LOCATION.equals(permissionName),
+                "permissionName is unknown: " + permissionName);
+        synchronized (mSessionLock) {
+            if (mState != STATE_OPENED) {
+                throw new IllegalStateException("Not allowed to change access type in state: "
+                        + stateToString(mState));
+            }
+            return mBlobAccessMode.arePackagesWithLocationPermissionAllowed(permissionName);
+        }
+    }
+
+    @Override
     public void close() {
         closeSession(STATE_CLOSED, false /* sendCallback */);
     }
diff --git a/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java b/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java
index fea7a11..cb1fccf 100644
--- a/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java
+++ b/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java
@@ -83,6 +83,12 @@
     }
 
     /**
+     * Does not place the app on any temporary allow list. Nullifies the previous call to
+     * {@link android.app.BroadcastOptions#setTemporaryAppAllowlist(long, int, int, String)}.
+     * Note: this will not remove the receiver app from the temp allow list.
+     */
+    public static final int TEMPORARY_ALLOW_LIST_TYPE_NONE = -1;
+    /**
      * Allow the temp allow list behavior, plus allow foreground service start from background.
      */
     public static final int TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED = 0;
@@ -96,6 +102,7 @@
      * @hide
      */
     @IntDef(flag = true, prefix = { "TEMPORARY_ALLOW_LIST_TYPE_" }, value = {
+            TEMPORARY_ALLOW_LIST_TYPE_NONE,
             TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
             TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED,
     })
diff --git a/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java b/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java
index 9bd57a1..a9ca5cf 100644
--- a/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java
+++ b/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java
@@ -17,9 +17,9 @@
 package com.android.server;
 
 import android.annotation.Nullable;
-import android.os.PowerWhitelistManager;
-import android.os.PowerWhitelistManager.ReasonCode;
-import android.os.PowerWhitelistManager.TempAllowListType;
+import android.os.PowerExemptionManager;
+import android.os.PowerExemptionManager.ReasonCode;
+import android.os.PowerExemptionManager.TempAllowListType;
 
 import com.android.server.deviceidle.IDeviceIdleConstraint;
 
@@ -35,7 +35,7 @@
 
     /**
      * Same as {@link #addPowerSaveTempWhitelistApp(int, String, long, int, boolean, int, String)}
-     * with {@link PowerWhitelistManager#TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED}.
+     * with {@link PowerExemptionManager#TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED}.
      */
     void addPowerSaveTempWhitelistApp(int callingUid, String packageName,
             long durationMs, int userId, boolean sync, @ReasonCode int reasonCode,
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index 667fc60..57c8300 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -16,9 +16,9 @@
 
 package com.android.server;
 
-import static android.os.PowerWhitelistManager.REASON_SHELL;
-import static android.os.PowerWhitelistManager.REASON_UNKNOWN;
-import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
+import static android.os.PowerExemptionManager.REASON_SHELL;
+import static android.os.PowerExemptionManager.REASON_UNKNOWN;
+import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
 import static android.os.Process.INVALID_UID;
 
 import android.Manifest;
@@ -58,11 +58,11 @@
 import android.os.IDeviceIdleController;
 import android.os.Looper;
 import android.os.Message;
+import android.os.PowerExemptionManager.ReasonCode;
+import android.os.PowerExemptionManager.TempAllowListType;
 import android.os.PowerManager;
 import android.os.PowerManager.ServiceType;
 import android.os.PowerManagerInternal;
-import android.os.PowerWhitelistManager.ReasonCode;
-import android.os.PowerWhitelistManager.TempAllowListType;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
@@ -1947,7 +1947,7 @@
                 long durationMs, int userId, boolean sync, @ReasonCode int reasonCode,
                 @Nullable String reason) {
             addPowerSaveTempAllowlistAppInternal(callingUid, packageName, durationMs,
-                    TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+                    TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
                     userId, sync, reasonCode, reason);
         }
 
@@ -2706,7 +2706,7 @@
         final long token = Binder.clearCallingIdentity();
         try {
             addPowerSaveTempAllowlistAppInternal(callingUid,
-                    packageName, duration, TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+                    packageName, duration, TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
                     userId, true, reasonCode, reason);
         } finally {
             Binder.restoreCallingIdentity(token);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 8ac237e..a452fbc 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -1046,7 +1046,7 @@
             FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SCHEDULED_JOB_STATE_CHANGED,
                     uId, null, jobStatus.getBatteryName(),
                     FrameworkStatsLog.SCHEDULED_JOB_STATE_CHANGED__STATE__SCHEDULED,
-                    JobProtoEnums.STOP_REASON_CANCELLED, jobStatus.getStandbyBucket(),
+                    JobProtoEnums.STOP_REASON_UNKNOWN, jobStatus.getStandbyBucket(),
                     jobStatus.getJobId(),
                     jobStatus.hasChargingConstraint(),
                     jobStatus.hasBatteryNotLowConstraint(),
@@ -1055,7 +1055,9 @@
                     jobStatus.hasDeadlineConstraint(),
                     jobStatus.hasIdleConstraint(),
                     jobStatus.hasConnectivityConstraint(),
-                    jobStatus.hasContentTriggerConstraint());
+                    jobStatus.hasContentTriggerConstraint(),
+                    jobStatus.isRequestedExpeditedJob(),
+                    /* isRunningAsExpeditedJob */ false);
 
             // If the job is immediately ready to run, then we can just immediately
             // put it in the pending list and try to schedule it.  This is especially
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
index ce4fd7a..44b3e3e 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -322,7 +322,9 @@
                     job.hasDeadlineConstraint(),
                     job.hasIdleConstraint(),
                     job.hasConnectivityConstraint(),
-                    job.hasContentTriggerConstraint());
+                    job.hasContentTriggerConstraint(),
+                    job.isRequestedExpeditedJob(),
+                    job.shouldTreatAsExpeditedJob());
             try {
                 mBatteryStats.noteJobStart(job.getBatteryName(), job.getSourceUid());
             } catch (RemoteException e) {
@@ -904,7 +906,9 @@
                 completedJob.hasDeadlineConstraint(),
                 completedJob.hasIdleConstraint(),
                 completedJob.hasConnectivityConstraint(),
-                completedJob.hasContentTriggerConstraint());
+                completedJob.hasContentTriggerConstraint(),
+                completedJob.isRequestedExpeditedJob(),
+                completedJob.startedAsExpeditedJob);
         try {
             mBatteryStats.noteJobFinish(mRunningJob.getBatteryName(), mRunningJob.getSourceUid(),
                     legacyStopReason);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
index 370b3c9..1e78ec3 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
@@ -27,10 +27,8 @@
 import android.app.job.JobInfo;
 import android.net.ConnectivityManager;
 import android.net.ConnectivityManager.NetworkCallback;
-import android.net.INetworkPolicyListener;
 import android.net.Network;
 import android.net.NetworkCapabilities;
-import android.net.NetworkPolicyManager;
 import android.net.NetworkRequest;
 import android.os.Handler;
 import android.os.Looper;
@@ -86,7 +84,6 @@
     private static final long MIN_STATS_UPDATE_INTERVAL_MS = 30_000L;
 
     private final ConnectivityManager mConnManager;
-    private final NetworkPolicyManager mNetPolicyManager;
     private final NetworkPolicyManagerInternal mNetPolicyManagerInternal;
 
     /** List of tracked jobs keyed by source UID. */
@@ -170,8 +167,6 @@
      */
     private final List<UidStats> mSortedStats = new ArrayList<>();
 
-    private static final int MSG_DATA_SAVER_TOGGLED = 0;
-    private static final int MSG_UID_RULES_CHANGES = 1;
     private static final int MSG_REEVALUATE_JOBS = 2;
 
     private final Handler mHandler;
@@ -181,15 +176,12 @@
         mHandler = new CcHandler(mContext.getMainLooper());
 
         mConnManager = mContext.getSystemService(ConnectivityManager.class);
-        mNetPolicyManager = mContext.getSystemService(NetworkPolicyManager.class);
         mNetPolicyManagerInternal = LocalServices.getService(NetworkPolicyManagerInternal.class);
 
         // We're interested in all network changes; internally we match these
         // network changes against the active network for each UID with jobs.
         final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
         mConnManager.registerNetworkCallback(request, mNetworkCallback);
-
-        mNetPolicyManager.registerListener(mNetPolicyListener);
     }
 
     @GuardedBy("mLock")
@@ -907,24 +899,6 @@
         }
     };
 
-    private final INetworkPolicyListener mNetPolicyListener = new NetworkPolicyManager.Listener() {
-        @Override
-        public void onRestrictBackgroundChanged(boolean restrictBackground) {
-            if (DEBUG) {
-                Slog.v(TAG, "onRestrictBackgroundChanged: " + restrictBackground);
-            }
-            mHandler.obtainMessage(MSG_DATA_SAVER_TOGGLED).sendToTarget();
-        }
-
-        @Override
-        public void onUidRulesChanged(int uid, int uidRules) {
-            if (DEBUG) {
-                Slog.v(TAG, "onUidRulesChanged: " + uid);
-            }
-            mHandler.obtainMessage(MSG_UID_RULES_CHANGES, uid, 0).sendToTarget();
-        }
-    };
-
     private class CcHandler extends Handler {
         CcHandler(Looper looper) {
             super(looper);
@@ -934,12 +908,6 @@
         public void handleMessage(Message msg) {
             synchronized (mLock) {
                 switch (msg.what) {
-                    case MSG_DATA_SAVER_TOGGLED:
-                        updateTrackedJobs(-1, null);
-                        break;
-                    case MSG_UID_RULES_CHANGES:
-                        updateTrackedJobs(msg.arg1, null);
-                        break;
                     case MSG_REEVALUATE_JOBS:
                         updateTrackedJobs(-1, null);
                         break;
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
index 8d999e1..80e68e9 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
@@ -142,13 +142,14 @@
      * (Atom #21)
      * * CONSTRAINT_BACKGROUND_NOT_RESTRICTED can be inferred with BatterySaverModeStateChanged
      * (Atom #20)
+     * * CONSTRAINT_STORAGE_NOT_LOW can be inferred with LowStorageStateChanged (Atom #130)
      */
     private static final int STATSD_CONSTRAINTS_TO_LOG = CONSTRAINT_CONTENT_TRIGGER
             | CONSTRAINT_DEADLINE
             | CONSTRAINT_IDLE
-            | CONSTRAINT_STORAGE_NOT_LOW
             | CONSTRAINT_TIMING_DELAY
-            | CONSTRAINT_WITHIN_QUOTA;
+            | CONSTRAINT_WITHIN_QUOTA
+            | CONSTRAINT_WITHIN_EXPEDITED_QUOTA;
 
     // TODO(b/129954980)
     private static final boolean STATS_LOG_ENABLED = false;
diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java
index ca1d598..f0ac530 100644
--- a/cmds/content/src/com/android/commands/content/Content.java
+++ b/cmds/content/src/com/android/commands/content/Content.java
@@ -19,6 +19,7 @@
 import android.app.ActivityManager;
 import android.app.ContentProviderHolder;
 import android.app.IActivityManager;
+import android.content.AttributionSource;
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.IContentProvider;
@@ -562,7 +563,8 @@
 
         @Override
         public void onExecute(IContentProvider provider) throws Exception {
-            provider.insert(resolveCallingPackage(), null, mUri, mContentValues, mExtras);
+            provider.insert(new AttributionSource(Binder.getCallingUid(),
+                    resolveCallingPackage(), null), mUri, mContentValues, mExtras);
         }
     }
 
@@ -576,7 +578,8 @@
 
         @Override
         public void onExecute(IContentProvider provider) throws Exception {
-            provider.delete(resolveCallingPackage(), null, mUri, mExtras);
+            provider.delete(new AttributionSource(Binder.getCallingUid(),
+                    resolveCallingPackage(), null), mUri, mExtras);
         }
     }
 
@@ -593,7 +596,8 @@
 
         @Override
         public void onExecute(IContentProvider provider) throws Exception {
-            Bundle result = provider.call(null, null, mUri.getAuthority(), mMethod, mArg, mExtras);
+            Bundle result = provider.call(new AttributionSource(Binder.getCallingUid(),
+                    resolveCallingPackage(), null), mUri.getAuthority(), mMethod, mArg, mExtras);
             if (result != null) {
                 result.size(); // unpack
             }
@@ -620,7 +624,9 @@
 
         @Override
         public void onExecute(IContentProvider provider) throws Exception {
-            try (ParcelFileDescriptor fd = provider.openFile(null, null, mUri, "r", null, null)) {
+            try (ParcelFileDescriptor fd = provider.openFile(
+                    new AttributionSource(Binder.getCallingUid(),
+                    resolveCallingPackage(), null), mUri, "r", null)) {
                 FileUtils.copy(fd.getFileDescriptor(), FileDescriptor.out);
             }
         }
@@ -633,7 +639,8 @@
 
         @Override
         public void onExecute(IContentProvider provider) throws Exception {
-            try (ParcelFileDescriptor fd = provider.openFile(null, null, mUri, "w", null, null)) {
+            try (ParcelFileDescriptor fd = provider.openFile(new AttributionSource(
+                    Binder.getCallingUid(), resolveCallingPackage(), null), mUri, "w", null)) {
                 FileUtils.copy(FileDescriptor.in, fd.getFileDescriptor());
             }
         }
@@ -651,8 +658,8 @@
 
         @Override
         public void onExecute(IContentProvider provider) throws Exception {
-            Cursor cursor = provider.query(resolveCallingPackage(), null, mUri, mProjection,
-                    mExtras, null);
+            Cursor cursor = provider.query(new AttributionSource(Binder.getCallingUid(),
+                    resolveCallingPackage(), null), mUri, mProjection, mExtras, null);
             if (cursor == null) {
                 System.out.println("No result found.");
                 return;
@@ -716,7 +723,8 @@
 
         @Override
         public void onExecute(IContentProvider provider) throws Exception {
-            provider.update(resolveCallingPackage(), null, mUri, mValues, mExtras);
+            provider.update(new AttributionSource(Binder.getCallingUid(),
+                    resolveCallingPackage(), null), mUri, mValues, mExtras);
         }
     }
 
diff --git a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
index b23bf5d..bc95986 100644
--- a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
+++ b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
@@ -20,6 +20,7 @@
 import android.app.ContentProviderHolder;
 import android.app.IActivityManager;
 import android.app.UiAutomation;
+import android.content.AttributionSource;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.IContentProvider;
@@ -28,6 +29,7 @@
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.IPowerManager;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
@@ -67,7 +69,8 @@
                     throw new IllegalStateException("Could not find provider: " + providerName);
                 }
                 provider = holder.provider;
-                cursor = provider.query(null, null, Settings.Secure.CONTENT_URI,
+                cursor = provider.query(new AttributionSource(Binder.getCallingUid(),
+                        resolveCallingPackage(), null), Settings.Secure.CONTENT_URI,
                         new String[] {
                             Settings.Secure.VALUE
                         },
@@ -123,4 +126,18 @@
         }
         return ret;
     }
+
+    private static String resolveCallingPackage() {
+        switch (Binder.getCallingUid()) {
+            case Process.ROOT_UID: {
+                return "root";
+            }
+            case Process.SHELL_UID: {
+                return "com.android.shell";
+            }
+            default: {
+                return null;
+            }
+        }
+    }
 }
diff --git a/core/api/current.txt b/core/api/current.txt
index 3773d3b..fb32055 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -867,6 +867,7 @@
     field public static final int keycode = 16842949; // 0x10100c5
     field public static final int killAfterRestore = 16843420; // 0x101029c
     field public static final int knownCerts = 16844330; // 0x101062a
+    field public static final int lStar = 16844359; // 0x1010647
     field public static final int label = 16842753; // 0x1010001
     field public static final int labelFor = 16843718; // 0x10103c6
     field @Deprecated public static final int labelTextSize = 16843317; // 0x1010235
@@ -7133,6 +7134,8 @@
     method public int getMaximumFailedPasswordsForWipe(@Nullable android.content.ComponentName);
     method public long getMaximumTimeToLock(@Nullable android.content.ComponentName);
     method @NonNull public java.util.List<java.lang.String> getMeteredDataDisabledPackages(@NonNull android.content.ComponentName);
+    method public int getNearbyAppStreamingPolicy();
+    method public int getNearbyNotificationStreamingPolicy();
     method @Deprecated @ColorInt public int getOrganizationColor(@NonNull android.content.ComponentName);
     method @Nullable public CharSequence getOrganizationName(@NonNull android.content.ComponentName);
     method public java.util.List<android.telephony.data.ApnSetting> getOverrideApns(@NonNull android.content.ComponentName);
@@ -7276,6 +7279,8 @@
     method public void setMaximumFailedPasswordsForWipe(@NonNull android.content.ComponentName, int);
     method public void setMaximumTimeToLock(@NonNull android.content.ComponentName, long);
     method @NonNull public java.util.List<java.lang.String> setMeteredDataDisabledPackages(@NonNull android.content.ComponentName, @NonNull java.util.List<java.lang.String>);
+    method public void setNearbyAppStreamingPolicy(int);
+    method public void setNearbyNotificationStreamingPolicy(int);
     method public void setNetworkLoggingEnabled(@Nullable android.content.ComponentName, boolean);
     method @Deprecated public void setOrganizationColor(@NonNull android.content.ComponentName, int);
     method public void setOrganizationId(@NonNull String);
@@ -7444,6 +7449,9 @@
     field public static final int LOCK_TASK_FEATURE_SYSTEM_INFO = 1; // 0x1
     field public static final int MAKE_USER_EPHEMERAL = 2; // 0x2
     field public static final String MIME_TYPE_PROVISIONING_NFC = "application/com.android.managedprovisioning";
+    field public static final int NEARBY_STREAMING_DISABLED = 0; // 0x0
+    field public static final int NEARBY_STREAMING_ENABLED = 1; // 0x1
+    field public static final int NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY = 2; // 0x2
     field public static final int OPERATION_SAFETY_REASON_DRIVING_DISTRACTION = 1; // 0x1
     field public static final int PASSWORD_COMPLEXITY_HIGH = 327680; // 0x50000
     field public static final int PASSWORD_COMPLEXITY_LOW = 65536; // 0x10000
@@ -7873,8 +7881,10 @@
   public static class BlobStoreManager.Session implements java.io.Closeable {
     method public void abandon() throws java.io.IOException;
     method public void allowPackageAccess(@NonNull String, @NonNull byte[]) throws java.io.IOException;
+    method public void allowPackagesWithLocationPermission(@NonNull String) throws java.io.IOException;
     method public void allowPublicAccess() throws java.io.IOException;
     method public void allowSameSignatureAccess() throws java.io.IOException;
+    method public boolean arePackagesWithLocationPermissionAllowed(@NonNull String) throws java.io.IOException;
     method public void close() throws java.io.IOException;
     method public void commit(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws java.io.IOException;
     method public long getSize() throws java.io.IOException;
@@ -9906,6 +9916,27 @@
     method @Deprecated public void setUpdateThrottle(long);
   }
 
+  public final class AttributionSource implements android.os.Parcelable {
+    method public boolean checkCallingUid();
+    method public int describeContents();
+    method public void enforceCallingUid();
+    method @Nullable public String getAttributionTag();
+    method @Nullable public android.content.AttributionSource getNext();
+    method @Nullable public String getPackageName();
+    method public int getUid();
+    method public boolean isTrusted(@NonNull android.content.Context);
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.content.AttributionSource> CREATOR;
+  }
+
+  public static final class AttributionSource.Builder {
+    ctor public AttributionSource.Builder(int);
+    method @NonNull public android.content.AttributionSource build();
+    method @NonNull public android.content.AttributionSource.Builder setAttributionTag(@NonNull String);
+    method @NonNull public android.content.AttributionSource.Builder setNext(@NonNull android.content.AttributionSource);
+    method @NonNull public android.content.AttributionSource.Builder setPackageName(@NonNull String);
+  }
+
   public abstract class BroadcastReceiver {
     ctor public BroadcastReceiver();
     method public final void abortBroadcast();
@@ -10075,6 +10106,7 @@
     method public abstract int delete(@NonNull android.net.Uri, @Nullable String, @Nullable String[]);
     method public int delete(@NonNull android.net.Uri, @Nullable android.os.Bundle);
     method public void dump(java.io.FileDescriptor, java.io.PrintWriter, String[]);
+    method @Nullable public final android.content.AttributionSource getCallingAttributionSource();
     method @Nullable public final String getCallingAttributionTag();
     method @Nullable public final String getCallingPackage();
     method @Nullable public final String getCallingPackageUnchecked();
@@ -10437,6 +10469,7 @@
     method public abstract android.content.Context getApplicationContext();
     method public abstract android.content.pm.ApplicationInfo getApplicationInfo();
     method public abstract android.content.res.AssetManager getAssets();
+    method @NonNull public android.content.AttributionSource getAttributionSource();
     method @Nullable public String getAttributionTag();
     method public abstract java.io.File getCacheDir();
     method public abstract ClassLoader getClassLoader();
@@ -10642,8 +10675,7 @@
 
   public final class ContextParams {
     method @Nullable public String getAttributionTag();
-    method @Nullable public String getReceiverAttributionTag();
-    method @Nullable public String getReceiverPackage();
+    method @Nullable public android.content.AttributionSource getNextAttributionSource();
   }
 
   public static final class ContextParams.Builder {
@@ -10651,7 +10683,7 @@
     ctor public ContextParams.Builder(@NonNull android.content.ContextParams);
     method @NonNull public android.content.ContextParams build();
     method @NonNull public android.content.ContextParams.Builder setAttributionTag(@Nullable String);
-    method @NonNull public android.content.ContextParams.Builder setReceiverPackage(@Nullable String, @Nullable String);
+    method @NonNull public android.content.ContextParams.Builder setNextAttributionSource(@NonNull android.content.AttributionSource);
   }
 
   public class ContextWrapper extends android.content.Context {
@@ -13178,6 +13210,7 @@
     method public boolean isStateful();
     method @NonNull public static android.content.res.ColorStateList valueOf(@ColorInt int);
     method @NonNull public android.content.res.ColorStateList withAlpha(int);
+    method @NonNull public android.content.res.ColorStateList withLStar(float);
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.content.res.ColorStateList> CREATOR;
   }
@@ -39080,6 +39113,7 @@
     method public void bufferReceived(byte[]) throws android.os.RemoteException;
     method public void endOfSpeech() throws android.os.RemoteException;
     method public void error(int) throws android.os.RemoteException;
+    method @NonNull public android.content.AttributionSource getCallingAttributionSource();
     method public int getCallingUid();
     method public void partialResults(android.os.Bundle) throws android.os.RemoteException;
     method public void readyForSpeech(android.os.Bundle) throws android.os.RemoteException;
@@ -40273,6 +40307,7 @@
     field public static final int DURATION_MEDIUM = 2; // 0x2
     field public static final int DURATION_SHORT = 1; // 0x1
     field public static final int DURATION_VERY_SHORT = 0; // 0x0
+    field public static final long ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION = 157233955L; // 0x95f3323L
     field public static final String EXTRA_CALL_BACK_NUMBER = "android.telecom.extra.CALL_BACK_NUMBER";
     field public static final String EXTRA_CALL_DISCONNECT_CAUSE = "android.telecom.extra.CALL_DISCONNECT_CAUSE";
     field public static final String EXTRA_CALL_DISCONNECT_MESSAGE = "android.telecom.extra.CALL_DISCONNECT_MESSAGE";
@@ -41879,7 +41914,7 @@
     method @Deprecated public void onBarringInfoChanged(@NonNull android.telephony.BarringInfo);
     method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onCallDisconnectCauseChanged(int, int);
     method @Deprecated public void onCallForwardingIndicatorChanged(boolean);
-    method @Deprecated public void onCallStateChanged(int, String);
+    method @Deprecated @RequiresPermission(value=android.Manifest.permission.READ_PHONE_STATE, conditional=true) public void onCallStateChanged(int, String);
     method @Deprecated public void onCellInfoChanged(java.util.List<android.telephony.CellInfo>);
     method @Deprecated public void onCellLocationChanged(android.telephony.CellLocation);
     method @Deprecated public void onDataActivity(int);
@@ -42425,7 +42460,7 @@
   }
 
   public static interface TelephonyCallback.CallStateListener {
-    method public void onCallStateChanged(int);
+    method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void onCallStateChanged(int);
   }
 
   public static interface TelephonyCallback.CarrierNetworkListener {
@@ -42515,7 +42550,8 @@
     method public int getActiveModemCount();
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public java.util.List<android.telephony.CellInfo> getAllCellInfo();
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getCallComposerStatus();
-    method public int getCallState();
+    method @Deprecated @RequiresPermission(value=android.Manifest.permission.READ_PHONE_STATE, conditional=true) public int getCallState();
+    method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getCallStateForSubscription();
     method public int getCardIdForDefaultEuicc();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @WorkerThread public android.os.PersistableBundle getCarrierConfig();
     method public int getCarrierIdFromSimMccMnc();
@@ -48771,6 +48807,7 @@
     method protected int[] onCreateDrawableState(int);
     method public android.view.inputmethod.InputConnection onCreateInputConnection(android.view.inputmethod.EditorInfo);
     method @Nullable public android.view.translation.ViewTranslationRequest onCreateTranslationRequest(@NonNull int[]);
+    method public void onCreateTranslationRequests(@NonNull long[], @NonNull int[], @NonNull java.util.function.Consumer<android.view.translation.ViewTranslationRequest>);
     method @CallSuper protected void onDetachedFromWindow();
     method protected void onDisplayHint(int);
     method public boolean onDragEvent(android.view.DragEvent);
@@ -48816,6 +48853,7 @@
     method public boolean onTouchEvent(android.view.MotionEvent);
     method public boolean onTrackballEvent(android.view.MotionEvent);
     method public void onTranslationResponse(@NonNull android.view.translation.ViewTranslationResponse);
+    method public void onTranslationResponse(@NonNull android.util.LongSparseArray<android.view.translation.ViewTranslationResponse>);
     method @CallSuper public void onVisibilityAggregated(boolean);
     method protected void onVisibilityChanged(@NonNull android.view.View, int);
     method public void onWindowFocusChanged(boolean);
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 256337d..4fb9926 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -196,7 +196,6 @@
     method @NonNull public static String blockedReasonsToString(int);
     method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public int getMultipathPreference(@NonNull android.net.Network);
     method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public int getRestrictBackgroundStatus(int);
-    method public static boolean isUidBlocked(int, boolean);
     method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public boolean isUidNetworkingBlocked(int, boolean);
     method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public boolean isUidRestrictedOnMeteredNetworks(int);
     method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public void registerNetworkPolicyCallback(@Nullable java.util.concurrent.Executor, @NonNull android.net.NetworkPolicyManager.NetworkPolicyCallback);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 49b8a90..a0efbb8 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -180,6 +180,7 @@
     field public static final String NETWORK_SIGNAL_STRENGTH_WAKEUP = "android.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP";
     field public static final String NETWORK_STACK = "android.permission.NETWORK_STACK";
     field public static final String NETWORK_STATS_PROVIDER = "android.permission.NETWORK_STATS_PROVIDER";
+    field public static final String NFC_SET_CONTROLLER_ALWAYS_ON = "android.permission.NFC_SET_CONTROLLER_ALWAYS_ON";
     field public static final String NOTIFICATION_DURING_SETUP = "android.permission.NOTIFICATION_DURING_SETUP";
     field public static final String NOTIFY_TV_INPUTS = "android.permission.NOTIFY_TV_INPUTS";
     field public static final String OBSERVE_APP_USAGE = "android.permission.OBSERVE_APP_USAGE";
@@ -596,7 +597,7 @@
 
   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 @Nullable public android.app.AppOpsManager.AttributedHistoricalOps getAttributedOps(@Nullable 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);
@@ -1733,10 +1734,20 @@
     field public static final int CAPABILITY_POSSESSED = 40; // 0x28
   }
 
+  public final class ExternalTimeSuggestion implements android.os.Parcelable {
+    ctor public ExternalTimeSuggestion(long, long);
+    method public void addDebugInfo(@NonNull java.lang.String...);
+    method public int describeContents();
+    method @NonNull public java.util.List<java.lang.String> getDebugInfo();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.app.time.ExternalTimeSuggestion> CREATOR;
+  }
+
   public final class TimeManager {
     method @RequiresPermission(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION) public void addTimeZoneDetectorListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.time.TimeManager.TimeZoneDetectorListener);
     method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION) public android.app.time.TimeZoneCapabilitiesAndConfig getTimeZoneCapabilitiesAndConfig();
     method @RequiresPermission(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION) public void removeTimeZoneDetectorListener(@NonNull android.app.time.TimeManager.TimeZoneDetectorListener);
+    method @RequiresPermission(android.Manifest.permission.SUGGEST_EXTERNAL_TIME) public void suggestExternalTime(@NonNull android.app.time.ExternalTimeSuggestion);
     method @RequiresPermission(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION) public boolean updateTimeZoneConfiguration(@NonNull android.app.time.TimeZoneConfiguration);
   }
 
@@ -2217,6 +2228,14 @@
     method @NonNull public java.io.File getDeviceProtectedDataDirForUser(@NonNull android.os.UserHandle);
   }
 
+  public final class AttributionSource implements android.os.Parcelable {
+    method @NonNull @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS) public java.util.Set<java.lang.String> getRenouncedPermissions();
+  }
+
+  public static final class AttributionSource.Builder {
+    method @NonNull @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS) public android.content.AttributionSource.Builder setRenouncedPermissions(@NonNull java.util.Set<java.lang.String>);
+  }
+
   public abstract class BroadcastReceiver {
     method @NonNull public final android.os.UserHandle getSendingUser();
   }
@@ -2291,11 +2310,11 @@
   }
 
   public final class ContextParams {
-    method @Nullable @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS) public java.util.Set<java.lang.String> getRenouncedPermissions();
+    method @NonNull @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS) public java.util.Set<java.lang.String> getRenouncedPermissions();
   }
 
   public static final class ContextParams.Builder {
-    method @NonNull @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS) public android.content.ContextParams.Builder setRenouncedPermissions(@Nullable java.util.Set<java.lang.String>);
+    method @NonNull @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS) public android.content.ContextParams.Builder setRenouncedPermissions(@NonNull java.util.Set<java.lang.String>);
   }
 
   public class ContextWrapper extends android.content.Context {
@@ -7888,10 +7907,10 @@
     method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enable();
     method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableNdefPush();
     method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableSecureNfc(boolean);
-    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean isAlwaysOnEnabled();
-    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean isAlwaysOnSupported();
+    method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOn();
+    method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOnSupported();
     method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean removeNfcUnlockHandler(android.nfc.NfcAdapter.NfcUnlockHandler);
-    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean setAlwaysOn(boolean);
+    method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean setControllerAlwaysOn(boolean);
     method public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, int);
     field public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 1; // 0x1
   }
@@ -8318,6 +8337,7 @@
     field public static final int REASON_UNKNOWN = 0; // 0x0
     field public static final int TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED = 0; // 0x0
     field public static final int TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED = 1; // 0x1
+    field public static final int TEMPORARY_ALLOW_LIST_TYPE_NONE = -1; // 0xffffffff
   }
 
   public final class PowerManager {
@@ -10372,6 +10392,7 @@
   public abstract static class AlwaysOnHotwordDetector.Callback implements android.service.voice.HotwordDetector.Callback {
     ctor public AlwaysOnHotwordDetector.Callback();
     method public abstract void onAvailabilityChanged(int);
+    method public void onHotwordDetectionServiceInitialized(int);
     method public void onRejected(@Nullable android.service.voice.HotwordRejectedResult);
   }
 
@@ -10419,7 +10440,11 @@
     method public void onDetect(@NonNull android.os.ParcelFileDescriptor, @NonNull android.media.AudioFormat, long, @NonNull android.service.voice.HotwordDetectionService.Callback);
     method public void onDetect(@NonNull android.os.ParcelFileDescriptor, @NonNull android.media.AudioFormat, @NonNull android.service.voice.HotwordDetectionService.Callback);
     method public void onDetect(@NonNull android.os.ParcelFileDescriptor, @NonNull android.media.AudioFormat, @Nullable android.os.PersistableBundle, @NonNull android.service.voice.HotwordDetectionService.Callback);
-    method public void onUpdateState(@Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory);
+    method public void onUpdateState(@Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory, long, @Nullable java.util.function.IntConsumer);
+    field public static final int INITIALIZATION_STATUS_CUSTOM_ERROR_1 = 1; // 0x1
+    field public static final int INITIALIZATION_STATUS_CUSTOM_ERROR_2 = 2; // 0x2
+    field public static final int INITIALIZATION_STATUS_SUCCESS = 0; // 0x0
+    field public static final int INITIALIZATION_STATUS_UNKNOWN = 100; // 0x64
     field public static final String SERVICE_INTERFACE = "android.service.voice.HotwordDetectionService";
   }
 
@@ -10441,6 +10466,7 @@
   public static interface HotwordDetector.Callback {
     method public void onDetected(@NonNull android.service.voice.AlwaysOnHotwordDetector.EventPayload);
     method public void onError();
+    method public void onHotwordDetectionServiceInitialized(int);
     method public void onRecognitionPaused();
     method public void onRecognitionResumed();
     method public void onRejected(@Nullable android.service.voice.HotwordRejectedResult);
@@ -10861,7 +10887,7 @@
     method public java.util.List<android.telecom.PhoneAccount> getAllPhoneAccounts();
     method public int getAllPhoneAccountsCount();
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.telecom.PhoneAccountHandle> getCallCapablePhoneAccounts(boolean);
-    method public int getCallState();
+    method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}, conditional=true) public int getCallState();
     method public android.telecom.PhoneAccountHandle getConnectionManager();
     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);
@@ -13643,13 +13669,13 @@
     ctor @Deprecated public RcsFeature();
     ctor public RcsFeature(@NonNull java.util.concurrent.Executor);
     method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
-    method @NonNull public android.telephony.ims.stub.RcsCapabilityExchangeImplBase createCapabilityExchangeImpl(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.stub.CapabilityExchangeEventListener);
+    method @NonNull public android.telephony.ims.stub.RcsCapabilityExchangeImplBase createCapabilityExchangeImpl(@NonNull android.telephony.ims.stub.CapabilityExchangeEventListener);
+    method public void destroyCapabilityExchangeImpl(@NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase);
     method public final void notifyCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.RcsFeature.RcsImsCapabilities);
     method public void onFeatureReady();
     method public void onFeatureRemoved();
     method public boolean queryCapabilityConfiguration(int, int);
     method @NonNull public final android.telephony.ims.feature.RcsFeature.RcsImsCapabilities queryCapabilityStatus();
-    method public void removeCapabilityExchangeImpl(@NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase);
   }
 
   public static class RcsFeature.RcsImsCapabilities extends android.telephony.ims.feature.ImsFeature.Capabilities {
@@ -13862,7 +13888,7 @@
   }
 
   public class RcsCapabilityExchangeImplBase {
-    ctor public RcsCapabilityExchangeImplBase(@NonNull java.util.concurrent.Executor);
+    ctor public RcsCapabilityExchangeImplBase();
     method public void publishCapabilities(@NonNull String, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.PublishResponseCallback);
     method public void sendOptionsCapabilityRequest(@NonNull android.net.Uri, @NonNull java.util.Set<java.lang.String>, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.OptionsResponseCallback);
     method public void subscribeForCapabilities(@NonNull java.util.Collection<android.net.Uri>, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.SubscribeResponseCallback);
@@ -14719,6 +14745,7 @@
     method public default boolean onCheckIsTextEditor();
     method public void onConfigurationChanged(android.content.res.Configuration);
     method public android.view.inputmethod.InputConnection onCreateInputConnection(android.view.inputmethod.EditorInfo);
+    method @Nullable public default void onCreateTranslationRequests(@NonNull long[], @NonNull int[], @NonNull java.util.function.Consumer<android.view.translation.ViewTranslationRequest>);
     method public void onDetachedFromWindow();
     method public boolean onDragEvent(android.view.DragEvent);
     method public void onDraw(android.graphics.Canvas);
@@ -14743,6 +14770,7 @@
     method public void onStartTemporaryDetach();
     method public boolean onTouchEvent(android.view.MotionEvent);
     method public boolean onTrackballEvent(android.view.MotionEvent);
+    method public default void onTranslationResponse(@NonNull android.util.LongSparseArray<android.view.translation.ViewTranslationResponse>);
     method public void onVisibilityChanged(android.view.View, int);
     method public void onWindowFocusChanged(boolean);
     method public void onWindowVisibilityChanged(int);
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 8a683b2..09bc4a2 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -220,6 +220,7 @@
     method @RequiresPermission("android.permission.MANAGE_APPOPS") public void rebootHistory(long);
     method @RequiresPermission("android.permission.MANAGE_APPOPS") public void reloadNonHistoricalState();
     method @RequiresPermission("android.permission.MANAGE_APPOPS") public void resetHistoryParameters();
+    method @RequiresPermission("android.permission.MANAGE_APPOPS") public void resetPackageOpsNoHistory(@NonNull String);
     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 public static int strOpToOp(@NonNull String);
@@ -252,6 +253,14 @@
     method public void offsetBeginAndEndTime(long);
   }
 
+  public class BroadcastOptions {
+    ctor public BroadcastOptions(@NonNull android.os.Bundle);
+    method public long getTemporaryAppAllowlistDuration();
+    method @Nullable public String getTemporaryAppAllowlistReason();
+    method public int getTemporaryAppAllowlistReasonCode();
+    method public int getTemporaryAppAllowlistType();
+  }
+
   public class DownloadManager {
     field public static final String COLUMN_MEDIASTORE_URI = "mediastore_uri";
   }
@@ -654,6 +663,11 @@
 
 package android.content {
 
+  public final class AttributionSource implements android.os.Parcelable {
+    ctor public AttributionSource(int, @Nullable String, @Nullable String);
+    ctor public AttributionSource(int, @Nullable String, @Nullable String, @Nullable android.content.AttributionSource);
+  }
+
   public final class AutofillOptions implements android.os.Parcelable {
     ctor public AutofillOptions(int, boolean);
     method public int describeContents();
@@ -1140,10 +1154,14 @@
   }
 
   public final class DisplayManager {
+    method public boolean areUserDisabledHdrTypesAllowed();
     method @RequiresPermission(android.Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE) public int getRefreshRateSwitchingType();
+    method @NonNull public int[] getUserDisabledHdrTypes();
     method public boolean isMinimalPostProcessingRequested(int);
+    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setAreUserDisabledHdrTypesAllowed(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE) public void setRefreshRateSwitchingType(int);
     method @RequiresPermission(android.Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS) public void setShouldAlwaysRespectAppRequestedMode(boolean);
+    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setUserDisabledHdrTypes(@NonNull int[]);
     method @RequiresPermission(android.Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS) public boolean shouldAlwaysRespectAppRequestedMode();
     field public static final int SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS = 2; // 0x2
     field public static final int SWITCHING_TYPE_NONE = 0; // 0x0
@@ -1639,6 +1657,7 @@
     field public static final int FIRST_ISOLATED_UID = 99000; // 0x182b8
     field public static final int LAST_APP_ZYGOTE_ISOLATED_UID = 98999; // 0x182b7
     field public static final int LAST_ISOLATED_UID = 99999; // 0x1869f
+    field public static final int NFC_UID = 1027; // 0x403
     field public static final int NUM_UIDS_PER_APP_ZYGOTE = 100; // 0x64
   }
 
@@ -2028,6 +2047,7 @@
 
   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 ARE_USER_DISABLED_HDR_FORMATS_ALLOWED = "are_user_disabled_hdr_formats_allowed";
     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 DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW = "enable_non_resizable_multi_window";
@@ -2042,6 +2062,7 @@
     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 USER_DISABLED_HDR_FORMATS = "user_disabled_hdr_formats";
     field public static final String USE_OPEN_WIFI_PACKAGE = "use_open_wifi_package";
   }
 
@@ -2592,6 +2613,7 @@
   }
 
   public final class Display {
+    method @NonNull public int[] getReportedHdrTypes();
     method @NonNull public android.graphics.ColorSpace[] getSupportedWideColorGamut();
     method public int getType();
     method public boolean hasAccess(int);
@@ -2642,7 +2664,9 @@
   public final class SurfaceControl implements android.os.Parcelable {
     ctor public SurfaceControl(@NonNull android.view.SurfaceControl, @NonNull String);
     method public static long acquireFrameRateFlexibilityToken();
+    method @NonNull public static android.os.IBinder getInternalDisplayToken();
     method public boolean isSameSurface(@NonNull android.view.SurfaceControl);
+    method public static void overrideHdrTypes(@NonNull android.os.IBinder, @NonNull int[]);
     method public static void releaseFrameRateFlexibilityToken(long);
   }
 
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 86e2723..0f38b5f 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -642,7 +642,7 @@
  *     protected void onCreate(Bundle savedInstanceState) {
  *         super.onCreate(savedInstanceState);
  *
- *         SharedPreferences mPrefs = getSharedPreferences();
+ *         mPrefs = getSharedPreferences(getLocalClassName(), MODE_PRIVATE);
  *         mCurViewMode = mPrefs.getInt("view_mode", DAY_VIEW_MODE);
  *     }
  *
@@ -5246,13 +5246,40 @@
         if (requestCode < 0) {
             throw new IllegalArgumentException("requestCode should be >= 0");
         }
+
         if (mHasCurrentPermissionsRequest) {
             Log.w(TAG, "Can request only one set of permissions at a time");
             // Dispatch the callback with empty arrays which means a cancellation.
             onRequestPermissionsResult(requestCode, new String[0], new int[0]);
             return;
         }
-        Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions);
+
+        List<String> filteredPermissions = null;
+
+        if (!getAttributionSource().getRenouncedPermissions().isEmpty()) {
+            final int permissionCount = permissions.length;
+            for (int i = 0; i < permissionCount; i++) {
+                if (getAttributionSource().getRenouncedPermissions().contains(permissions[i])) {
+                    if (filteredPermissions == null) {
+                        filteredPermissions = new ArrayList<>(i);
+                        for (int j = 0; j < i; j++) {
+                            filteredPermissions.add(permissions[i]);
+                        }
+                    }
+                } else if (filteredPermissions != null) {
+                    filteredPermissions.add(permissions[i]);
+                }
+            }
+        }
+
+        final Intent intent;
+        if (filteredPermissions == null) {
+            intent = getPackageManager().buildRequestPermissionsIntent(permissions);
+        } else {
+            intent = getPackageManager().buildRequestPermissionsIntent(
+                    filteredPermissions.toArray(new String[0]));
+        }
+
         startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null);
         mHasCurrentPermissionsRequest = true;
     }
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index f7a3514..a7d5b05 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -30,8 +30,8 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.IBinder;
-import android.os.PowerWhitelistManager.ReasonCode;
-import android.os.PowerWhitelistManager.TempAllowListType;
+import android.os.PowerExemptionManager.ReasonCode;
+import android.os.PowerExemptionManager.TempAllowListType;
 import android.os.TransactionTooLargeException;
 import android.os.WorkSource;
 import android.util.ArraySet;
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 7e4af1a..f76e1c0 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -50,6 +50,7 @@
 import android.os.Looper;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.content.AttributionSource;
 import android.os.Process;
 import android.os.RemoteCallback;
 import android.os.RemoteException;
@@ -5955,7 +5956,7 @@
          *
          * @return The historical ops for the attribution.
          */
-        public @Nullable AttributedHistoricalOps getAttributedOps(@NonNull String attributionTag) {
+        public @Nullable AttributedHistoricalOps getAttributedOps(@Nullable String attributionTag) {
             if (mAttributedHistoricalOps == null) {
                 return null;
             }
@@ -6480,7 +6481,7 @@
          * Gets number of discrete historical app ops.
          *
          * @return The number historical app ops.
-         * @see #getOpAt(int)
+         * @see #getDiscreteAccessAt(int)
          */
         public @IntRange(from = 0) int getDiscreteAccessCount() {
             if (mDiscreteAccesses == null) {
@@ -6494,7 +6495,7 @@
          *
          * @param index The index to lookup.
          * @return The op at the given index.
-         * @see #getOpCount()
+         * @see #getDiscreteAccessCount()
          */
         public @NonNull AttributedOpEntry getDiscreteAccessAt(@IntRange(from = 0) int index) {
             if (mDiscreteAccesses == null) {
@@ -7979,7 +7980,7 @@
         try {
             collectNoteOpCallsForValidation(op);
             int collectionMode = getNotedOpCollectionMode(uid, packageName, op);
-            boolean shouldCollectMessage = Process.myUid() == Process.SYSTEM_UID ? true : false;
+            boolean shouldCollectMessage = Process.myUid() == Process.SYSTEM_UID;
             if (collectionMode == COLLECT_ASYNC) {
                 if (message == null) {
                     // Set stack trace as default message
@@ -8033,14 +8034,9 @@
      */
     public int noteProxyOp(int op, @Nullable String proxiedPackageName, int proxiedUid,
             @Nullable String proxiedAttributionTag, @Nullable String message) {
-        int mode = noteProxyOpNoThrow(op, proxiedPackageName, proxiedUid, proxiedAttributionTag,
-                message);
-        if (mode == MODE_ERRORED) {
-            throw new SecurityException("Proxy package " + mContext.getOpPackageName()
-                    + " from uid " + Process.myUid() + " or calling package " + proxiedPackageName
-                    + " from uid " + proxiedUid + " not allowed to perform " + sOpNames[op]);
-        }
-        return mode;
+        return noteProxyOp(op, new AttributionSource(mContext.getAttributionSource(),
+                new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag)),
+                message, /*skipProxyOperation*/ false);
     }
 
     /**
@@ -8069,6 +8065,36 @@
     }
 
     /**
+     * Make note of an application performing an operation on behalf of another application(s).
+     *
+     * @param op The operation to note. One of the OPSTR_* constants.
+     * @param attributionSource The permission identity for which to note.
+     * @param message A message describing the reason the op was noted
+     * @param skipProxyOperation Whether to skip the proxy note.
+     *
+     * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or {@link #MODE_IGNORED}
+     * if it is not allowed and should be silently ignored (without causing the app to crash).
+     *
+     * @throws SecurityException If the any proxying operations in the permission identityf
+     *     chain fails.
+     *
+     * @hide
+     */
+    public int noteProxyOp(@NonNull int op, @NonNull AttributionSource attributionSource,
+            @Nullable String message, boolean skipProxyOperation) {
+        final int mode = noteProxyOpNoThrow(op, attributionSource, message, skipProxyOperation);
+        if (mode == MODE_ERRORED) {
+            throw new SecurityException("Proxy package "
+                    + attributionSource.getPackageName()  + " from uid "
+                    + attributionSource.getUid() + " or calling package "
+                    + attributionSource.getNextPackageName() + " from uid "
+                    + attributionSource.getNextUid() + " not allowed to perform "
+                    + sOpNames[op]);
+        }
+        return mode;
+    }
+
+    /**
      * @deprecated Use {@link #noteProxyOpNoThrow(String, String, int, String, String)} instead
      */
     @Deprecated
@@ -8093,24 +8119,36 @@
      */
     public int noteProxyOpNoThrow(@NonNull String op, @Nullable String proxiedPackageName,
             int proxiedUid, @Nullable String proxiedAttributionTag, @Nullable String message) {
-        return noteProxyOpNoThrow(strOpToOp(op), proxiedPackageName, proxiedUid,
-                proxiedAttributionTag, message);
+        return noteProxyOpNoThrow(strOpToOp(op), new AttributionSource(
+                mContext.getAttributionSource(), new AttributionSource(proxiedUid,
+                        proxiedPackageName, proxiedAttributionTag)), message,
+                        /*skipProxyOperation*/ false);
     }
 
     /**
-     * @see #noteProxyOpNoThrow(String, String, int, String, String)
+     * Make note of an application performing an operation on behalf of another application(s).
+     *
+     * @param op The operation to note. One of the OPSTR_* constants.
+     * @param attributionSource The permission identity for which to note.
+     * @param message A message describing the reason the op was noted
+     * @param skipProxyOperation Whether to note op for the proxy
+     *
+     * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or {@link #MODE_IGNORED}
+     * if it is not allowed and should be silently ignored (without causing the app to crash).
      *
      * @hide
      */
     @SuppressWarnings("AndroidFrameworkClientSidePermissionCheck")
-    public int noteProxyOpNoThrow(int op, @Nullable String proxiedPackageName, int proxiedUid,
-            @Nullable String proxiedAttributionTag, @Nullable String message) {
+    public int noteProxyOpNoThrow(int op, @NonNull AttributionSource attributionSource,
+            @Nullable String message, boolean skipProxyOperation) {
         int myUid = Process.myUid();
 
         try {
             collectNoteOpCallsForValidation(op);
-            int collectionMode = getNotedOpCollectionMode(proxiedUid, proxiedPackageName, op);
-            boolean shouldCollectMessage = myUid == Process.SYSTEM_UID ? true : false;
+            int collectionMode = getNotedOpCollectionMode(
+                    attributionSource.getNextUid(),
+                    attributionSource.getNextAttributionTag(), op);
+            boolean shouldCollectMessage = (myUid == Process.SYSTEM_UID);
             if (collectionMode == COLLECT_ASYNC) {
                 if (message == null) {
                     // Set stack trace as default message
@@ -8119,20 +8157,19 @@
                 }
             }
 
-            int mode = mService.noteProxyOperation(op, proxiedUid, proxiedPackageName,
-                    proxiedAttributionTag, myUid, mContext.getOpPackageName(),
-                    mContext.getAttributionTag(), collectionMode == COLLECT_ASYNC, message,
-                    shouldCollectMessage);
+            int mode = mService.noteProxyOperation(op, attributionSource,
+                    collectionMode == COLLECT_ASYNC, message,
+                    shouldCollectMessage, skipProxyOperation);
 
             if (mode == MODE_ALLOWED) {
                 if (collectionMode == COLLECT_SELF) {
-                    collectNotedOpForSelf(op, proxiedAttributionTag);
+                    collectNotedOpForSelf(op, attributionSource.getNextAttributionTag());
                 } else if (collectionMode == COLLECT_SYNC
                         // Only collect app-ops when the proxy is trusted
                         && (mContext.checkPermission(Manifest.permission.UPDATE_APP_OPS_STATS, -1,
                         myUid) == PackageManager.PERMISSION_GRANTED ||
-                        Binder.getCallingUid() == proxiedUid)) {
-                    collectNotedOpSync(op, proxiedAttributionTag);
+                            Binder.getCallingUid() == attributionSource.getNextUid())) {
+                    collectNotedOpSync(op, attributionSource.getNextAttributionTag());
                 }
             }
 
@@ -8424,7 +8461,7 @@
         try {
             collectNoteOpCallsForValidation(op);
             int collectionMode = getNotedOpCollectionMode(uid, packageName, op);
-            boolean shouldCollectMessage = Process.myUid() == Process.SYSTEM_UID ? true : false;
+            boolean shouldCollectMessage = Process.myUid() == Process.SYSTEM_UID;
             if (collectionMode == COLLECT_ASYNC) {
                 if (message == null) {
                     // Set stack trace as default message
@@ -8450,6 +8487,7 @@
             throw e.rethrowFromSystemServer();
         }
     }
+
     /**
      * Report that an application has started executing a long-running operation on behalf of
      * another application when handling an IPC. This function will verify that the calling uid and
@@ -8470,19 +8508,45 @@
      */
     public int startProxyOp(@NonNull String op, int proxiedUid, @NonNull String proxiedPackageName,
             @Nullable String proxiedAttributionTag, @Nullable String message) {
-        final int mode = startProxyOpNoThrow(op, proxiedUid, proxiedPackageName,
-                proxiedAttributionTag, message);
+        return startProxyOp(op, new AttributionSource(mContext.getAttributionSource(),
+                new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag)),
+                message, /*skipProxyOperation*/ false);
+    }
+
+    /**
+     * Report that an application has started executing a long-running operation on behalf of
+     * another application for the attribution chain specified by the {@link AttributionSource}}.
+     *
+     * @param op The op to note
+     * @param attributionSource The permission identity for which to check
+     * @param message A message describing the reason the op was noted
+     * @param skipProxyOperation Whether to skip the proxy start.
+     *
+     * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or {@link #MODE_IGNORED}
+     * if it is not allowed and should be silently ignored (without causing the app to crash).
+     *
+     * @throws SecurityException If the any proxying operations in the permission identity
+     *     chain fails.
+     *
+     * @hide
+     */
+    public int startProxyOp(@NonNull String op, @NonNull AttributionSource attributionSource,
+            @Nullable String message, boolean skipProxyOperation) {
+        final int mode = startProxyOpNoThrow(AppOpsManager.strOpToOp(op), attributionSource,
+                message, skipProxyOperation);
         if (mode == MODE_ERRORED) {
-            throw new SecurityException("Proxy package " + mContext.getOpPackageName()
-                    + " from uid " + Process.myUid() + " or calling package " + proxiedPackageName
-                    + " from uid " + proxiedUid + " not allowed to perform "
-                    + sOpNames[strOpToOp(op)]);
+            throw new SecurityException("Proxy package "
+                    + attributionSource.getPackageName()  + " from uid "
+                    + attributionSource.getUid() + " or calling package "
+                    + attributionSource.getNextPackageName() + " from uid "
+                    + attributionSource.getNextUid() + " not allowed to perform "
+                    + op);
         }
         return mode;
     }
 
     /**
-     *Like {@link #startProxyOp(String, int, String, String, String)} but instead
+     * Like {@link #startProxyOp(String, int, String, String, String)} but instead
      * of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}.
      *
      * @see #startProxyOp(String, int, String, String, String)
@@ -8490,11 +8554,28 @@
     public int startProxyOpNoThrow(@NonNull String op, int proxiedUid,
             @NonNull String proxiedPackageName, @Nullable String proxiedAttributionTag,
             @Nullable String message) {
-        try {
-            int opInt = strOpToOp(op);
+        return startProxyOpNoThrow(AppOpsManager.strOpToOp(op), new AttributionSource(
+                mContext.getAttributionSource(), new AttributionSource(proxiedUid,
+                        proxiedPackageName, proxiedAttributionTag)), message,
+                /*skipProxyOperation*/ false);
+    }
 
-            collectNoteOpCallsForValidation(opInt);
-            int collectionMode = getNotedOpCollectionMode(proxiedUid, proxiedPackageName, opInt);
+    /**
+     * Like {@link #startProxyOp(String, AttributionSource, String)} but instead
+     * of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED} and
+     * the checks is for the attribution chain specified by the {@link AttributionSource}.
+     *
+     * @see #startProxyOp(String, AttributionSource, String)
+     *
+     * @hide
+     */
+    public int startProxyOpNoThrow(int op, @NonNull AttributionSource attributionSource,
+            @Nullable String message, boolean skipProxyOperation) {
+        try {
+            collectNoteOpCallsForValidation(op);
+            int collectionMode = getNotedOpCollectionMode(
+                    attributionSource.getNextUid(),
+                    attributionSource.getNextPackageName(), op);
             boolean shouldCollectMessage = Process.myUid() == Process.SYSTEM_UID;
             if (collectionMode == COLLECT_ASYNC) {
                 if (message == null) {
@@ -8504,24 +8585,23 @@
                 }
             }
 
-            int mode = mService.startProxyOperation(getClientId(), opInt, proxiedUid,
-                    proxiedPackageName, proxiedAttributionTag, Process.myUid(),
-                    mContext.getOpPackageName(), mContext.getAttributionTag(), false,
-                    collectionMode == COLLECT_ASYNC, message, shouldCollectMessage);
+            int mode = mService.startProxyOperation(getClientId(), op,
+                    attributionSource, false, collectionMode == COLLECT_ASYNC, message,
+                    shouldCollectMessage, skipProxyOperation);
 
             if (mode == MODE_ALLOWED) {
                 if (collectionMode == COLLECT_SELF) {
-                    collectNotedOpForSelf(opInt, proxiedAttributionTag);
+                    collectNotedOpForSelf(op,
+                            attributionSource.getNextAttributionTag());
                 } else if (collectionMode == COLLECT_SYNC
                         // Only collect app-ops when the proxy is trusted
                         && (mContext.checkPermission(Manifest.permission.UPDATE_APP_OPS_STATS, -1,
                         Process.myUid()) == PackageManager.PERMISSION_GRANTED
-                        || Binder.getCallingUid() == proxiedUid)) {
-                    collectNotedOpSync(opInt, proxiedAttributionTag);
+                        || Binder.getCallingUid() == attributionSource.getNextUid())) {
+                    collectNotedOpSync(op, attributionSource.getNextAttributionTag());
                 }
             }
 
-
             return mode;
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -8580,22 +8660,37 @@
     }
 
     /**
-     *  Report that an application is no longer performing an operation that had previously
+     * Report that an application is no longer performing an operation that had previously
      * been started with {@link #startProxyOp(String, int, String, String, String)}. There is no
      * validation of input or result; the parameters supplied here must be the exact same ones
      * previously passed in when starting the operation.
+     *
      * @param op The operation which was started
-     * @param proxiedUid The uid the op was started on behalf of
-     * @param proxiedPackageName The package the op was started on behalf of
-     * @param proxiedAttributionTag The proxied {@link Context#createAttributionContext
-     * attribution tag} or {@code null} for default attribution
+     * @param proxiedUid The proxied appp's UID
+     * @param proxiedPackageName The proxied appp's package name
+     * @param proxiedAttributionTag The proxied appp's attribution tag or
+     *     {@code null} for default attribution
      */
     public void finishProxyOp(@NonNull String op, int proxiedUid,
             @NonNull String proxiedPackageName, @Nullable String proxiedAttributionTag) {
+        finishProxyOp(op, new AttributionSource(mContext.getAttributionSource(),
+                new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag)));
+    }
+
+    /**
+     * Report that an application is no longer performing an operation that had previously
+     * been started with {@link #startProxyOp(String, AttributionSource, String)}. There is no
+     * validation of input or result; the parameters supplied here must be the exact same ones
+     * previously passed in when starting the operation.
+     *
+     * @param op The operation which was started
+     * @param attributionSource The permission identity for which to finish
+     *
+     * @hide
+     */
+    public void finishProxyOp(@NonNull String op, @NonNull AttributionSource attributionSource) {
         try {
-            mService.finishProxyOperation(getClientId(), strOpToOp(op), proxiedUid,
-                    proxiedPackageName, proxiedAttributionTag, Process.myUid(),
-                    mContext.getOpPackageName(), mContext.getAttributionTag());
+            mService.finishProxyOperation(getClientId(), strOpToOp(op), attributionSource);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -8616,6 +8711,46 @@
     }
 
     /**
+     * Get whether you are currently proxying to another package. That applies only
+     * for long running operations like {@link #OP_RECORD_AUDIO}.
+     *
+     * @param op The op.
+     * @param proxyAttributionTag Your attribution tag to query for.
+     * @param proxiedUid The proxied UID to query for.
+     * @param proxiedPackageName The proxied package to query for.
+     * @return Whether you are currently proxying to this target.
+     *
+     * @hide
+     */
+    public boolean isProxying(int op, @NonNull String proxyAttributionTag, int proxiedUid,
+            @NonNull String proxiedPackageName) {
+        try {
+            return mService.isProxying(op, mContext.getOpPackageName(),
+                    mContext.getAttributionTag(), proxiedUid, proxiedPackageName);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Clears the op state (last accesses + op modes) for a package but not
+     * the historical state.
+     *
+     * @param packageName The package to reset.
+     *
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(Manifest.permission.MANAGE_APPOPS)
+    public void resetPackageOpsNoHistory(@NonNull String packageName) {
+        try {
+            mService.resetPackageOpsNoHistory(packageName);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Start collection of noted appops on this thread.
      *
      * <p>Called at the beginning of a two way binder transaction.
@@ -8771,7 +8906,7 @@
             packageName = "android";
         }
 
-        // check it the appops needs to be collected and cache result
+        // check if the appops needs to be collected and cache result
         if (sAppOpsToNote[op] == SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED) {
             boolean shouldCollectNotes;
             try {
diff --git a/core/java/android/app/AppOpsManagerInternal.java b/core/java/android/app/AppOpsManagerInternal.java
index 5e032f0..a3d0cf2 100644
--- a/core/java/android/app/AppOpsManagerInternal.java
+++ b/core/java/android/app/AppOpsManagerInternal.java
@@ -18,12 +18,17 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.AttributionSource;
+import android.os.IBinder;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 
 import com.android.internal.app.IAppOpsCallback;
 import com.android.internal.util.function.HeptFunction;
+import com.android.internal.util.function.HexFunction;
+import com.android.internal.util.function.OctFunction;
 import com.android.internal.util.function.QuadFunction;
+import com.android.internal.util.function.TriFunction;
 
 /**
  * App ops service local interface.
@@ -76,6 +81,55 @@
                 @Nullable String message, boolean shouldCollectMessage,
                 @NonNull HeptFunction<Integer, Integer, String, String, Boolean, String, Boolean,
                         Integer> superImpl);
+
+        /**
+         * Allows overriding note proxy operation behavior.
+         *
+         * @param code The op code to note.
+         * @param attributionSource The permission identity of the caller.
+         * @param shouldCollectAsyncNotedOp If an {@link AsyncNotedAppOp} should be collected
+         * @param message The message in the async noted op
+         * @param shouldCollectMessage whether to collect messages
+         * @param skipProxyOperation Whether to skip the proxy portion of the operation
+         * @param superImpl The super implementation.
+         * @return The app op note result.
+         */
+        int noteProxyOperation(int code, @NonNull AttributionSource attributionSource,
+                boolean shouldCollectAsyncNotedOp, @Nullable String message,
+                boolean shouldCollectMessage, boolean skipProxyOperation,
+                @NonNull HexFunction<Integer, AttributionSource, Boolean, String, Boolean,
+                        Boolean, Integer> superImpl);
+
+        /**
+         * Allows overriding start proxy operation behavior.
+         *
+         * @param code The op code to start.
+         * @param attributionSource The permission identity of the caller.
+         * @param startIfModeDefault Whether to start the op of the mode is default.
+         * @param shouldCollectAsyncNotedOp If an {@link AsyncNotedAppOp} should be collected
+         * @param message The message in the async noted op
+         * @param shouldCollectMessage whether to collect messages
+         * @param skipProxyOperation Whether to skip the proxy portion of the operation
+         * @param superImpl The super implementation.
+         * @return The app op note result.
+         */
+        int startProxyOperation(IBinder token, int code,
+                @NonNull AttributionSource attributionSource, boolean startIfModeDefault,
+                boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
+                boolean skipProxyOperation, @NonNull OctFunction<IBinder, Integer,
+                        AttributionSource, Boolean, Boolean, String, Boolean, Boolean,
+                        Integer> superImpl);
+
+        /**
+         * Allows overriding finish proxy op.
+         *
+         * @param clientId Client state token.
+         * @param code The op code to finish.
+         * @param attributionSource The permission identity of the caller.
+         */
+        void finishProxyOperation(IBinder clientId, int code,
+                @NonNull AttributionSource attributionSource,
+                @NonNull TriFunction<IBinder, Integer, AttributionSource, Void> superImpl);
     }
 
     /**
diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java
index 477e96b..9da2581 100644
--- a/core/java/android/app/BroadcastOptions.java
+++ b/core/java/android/app/BroadcastOptions.java
@@ -16,14 +16,16 @@
 
 package android.app;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.os.Build;
 import android.os.Bundle;
-import android.os.PowerWhitelistManager;
-import android.os.PowerWhitelistManager.ReasonCode;
-import android.os.PowerWhitelistManager.TempAllowListType;
+import android.os.PowerExemptionManager;
+import android.os.PowerExemptionManager.ReasonCode;
+import android.os.PowerExemptionManager.TempAllowListType;
 
 /**
  * Helper class for building an options Bundle that can be used with
@@ -35,8 +37,7 @@
 public class BroadcastOptions {
     private long mTemporaryAppAllowlistDuration;
     private @TempAllowListType int mTemporaryAppAllowlistType;
-    private @ReasonCode int mTemporaryAppAllowlistReasonCode =
-            PowerWhitelistManager.REASON_UNKNOWN;
+    private @ReasonCode int mTemporaryAppAllowlistReasonCode;
     private @Nullable String mTemporaryAppAllowlistReason;
     private int mMinManifestReceiverApiLevel = 0;
     private int mMaxManifestReceiverApiLevel = Build.VERSION_CODES.CUR_DEVELOPMENT;
@@ -47,59 +48,59 @@
      * How long to temporarily put an app on the power allowlist when executing this broadcast
      * to it.
      */
-    static final String KEY_TEMPORARY_APP_ALLOWLIST_DURATION
+    private static final String KEY_TEMPORARY_APP_ALLOWLIST_DURATION
             = "android:broadcast.temporaryAppAllowlistDuration";
 
-    static final String KEY_TEMPORARY_APP_ALLOWLIST_TYPE
+    private static final String KEY_TEMPORARY_APP_ALLOWLIST_TYPE
             = "android:broadcast.temporaryAppAllowlistType";
 
-    static final String KEY_TEMPORARY_APP_ALLOWLIST_REASON_CODE =
+    private static final String KEY_TEMPORARY_APP_ALLOWLIST_REASON_CODE =
             "android:broadcast.temporaryAppAllowlistReasonCode";
 
-    static final String KEY_TEMPORARY_APP_ALLOWLIST_REASON =
+    private static final String KEY_TEMPORARY_APP_ALLOWLIST_REASON =
             "android:broadcast.temporaryAppAllowlistReason";
 
     /**
      * Corresponds to {@link #setMinManifestReceiverApiLevel}.
      */
-    static final String KEY_MIN_MANIFEST_RECEIVER_API_LEVEL
+    private static final String KEY_MIN_MANIFEST_RECEIVER_API_LEVEL
             = "android:broadcast.minManifestReceiverApiLevel";
 
     /**
      * Corresponds to {@link #setMaxManifestReceiverApiLevel}.
      */
-    static final String KEY_MAX_MANIFEST_RECEIVER_API_LEVEL
+    private static final String KEY_MAX_MANIFEST_RECEIVER_API_LEVEL
             = "android:broadcast.maxManifestReceiverApiLevel";
 
     /**
      * Corresponds to {@link #setDontSendToRestrictedApps}.
      */
-    static final String KEY_DONT_SEND_TO_RESTRICTED_APPS =
+    private static final String KEY_DONT_SEND_TO_RESTRICTED_APPS =
             "android:broadcast.dontSendToRestrictedApps";
 
     /**
      * Corresponds to {@link #setBackgroundActivityStartsAllowed}.
      */
-    static final String KEY_ALLOW_BACKGROUND_ACTIVITY_STARTS =
+    private static final String KEY_ALLOW_BACKGROUND_ACTIVITY_STARTS =
             "android:broadcast.allowBackgroundActivityStarts";
 
     /**
      * @hide
-     * @deprecated Use {@link android.os.PowerWhitelistManager#
-     * TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED} instead.
+     * @deprecated Use {@link android.os.PowerExemptionManager#
+     * TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED} instead.
      */
     @Deprecated
     public static final int TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED =
-            PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
+            PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
 
     /**
      * @hide
-     * @deprecated Use {@link android.os.PowerWhitelistManager#
-     * TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED} instead.
+     * @deprecated Use {@link android.os.PowerExemptionManager#
+     * TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED} instead.
      */
     @Deprecated
     public static final int TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED =
-            PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED;
+            PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED;
 
     public static BroadcastOptions makeBasic() {
         BroadcastOptions opts = new BroadcastOptions();
@@ -107,15 +108,22 @@
     }
 
     private BroadcastOptions() {
+        resetTemporaryAppAllowlist();
     }
 
     /** @hide */
-    public BroadcastOptions(Bundle opts) {
-        mTemporaryAppAllowlistDuration = opts.getLong(KEY_TEMPORARY_APP_ALLOWLIST_DURATION);
-        mTemporaryAppAllowlistType = opts.getInt(KEY_TEMPORARY_APP_ALLOWLIST_TYPE);
-        mTemporaryAppAllowlistReasonCode = opts.getInt(KEY_TEMPORARY_APP_ALLOWLIST_REASON_CODE,
-                PowerWhitelistManager.REASON_UNKNOWN);
-        mTemporaryAppAllowlistReason = opts.getString(KEY_TEMPORARY_APP_ALLOWLIST_REASON);
+    @TestApi
+    public BroadcastOptions(@NonNull Bundle opts) {
+        // Match the logic in toBundle().
+        if (opts.containsKey(KEY_TEMPORARY_APP_ALLOWLIST_DURATION)) {
+            mTemporaryAppAllowlistDuration = opts.getLong(KEY_TEMPORARY_APP_ALLOWLIST_DURATION);
+            mTemporaryAppAllowlistType = opts.getInt(KEY_TEMPORARY_APP_ALLOWLIST_TYPE);
+            mTemporaryAppAllowlistReasonCode = opts.getInt(KEY_TEMPORARY_APP_ALLOWLIST_REASON_CODE,
+                    PowerExemptionManager.REASON_UNKNOWN);
+            mTemporaryAppAllowlistReason = opts.getString(KEY_TEMPORARY_APP_ALLOWLIST_REASON);
+        } else {
+            resetTemporaryAppAllowlist();
+        }
         mMinManifestReceiverApiLevel = opts.getInt(KEY_MIN_MANIFEST_RECEIVER_API_LEVEL, 0);
         mMaxManifestReceiverApiLevel = opts.getInt(KEY_MAX_MANIFEST_RECEIVER_API_LEVEL,
                 Build.VERSION_CODES.CUR_DEVELOPMENT);
@@ -136,18 +144,21 @@
             android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND})
     public void setTemporaryAppWhitelistDuration(long duration) {
         setTemporaryAppAllowlist(duration,
-                PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
-                PowerWhitelistManager.REASON_UNKNOWN, null);
+                PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+                PowerExemptionManager.REASON_UNKNOWN, null);
     }
 
     /**
      * Set a duration for which the system should temporary place an application on the
      * power allowlist when this broadcast is being delivered to it, specify the temp allowlist
      * type.
-     * @param duration the duration in milliseconds; 0 means to not place on allowlist.
-     * @param type one of {@link TempAllowListType}
+     * @param duration the duration in milliseconds.
+     *                 0 means to not place on allowlist, and clears previous call to this method.
+     * @param type one of {@link TempAllowListType}.
+     *             {@link PowerExemptionManager#TEMPORARY_ALLOW_LIST_TYPE_NONE} means
+     *             to not place on allowlist, and clears previous call to this method.
      * @param reasonCode one of {@link ReasonCode}, use
-     *                  {@link PowerWhitelistManager#REASON_UNKNOWN} if not sure.
+     *                  {@link PowerExemptionManager#REASON_UNKNOWN} if not sure.
      * @param reason A human-readable reason explaining why the app is temp allowlisted. Only
      *               used for logging purposes. Could be null or empty string.
      */
@@ -160,12 +171,30 @@
         mTemporaryAppAllowlistType = type;
         mTemporaryAppAllowlistReasonCode = reasonCode;
         mTemporaryAppAllowlistReason = reason;
+
+        if (!isTemporaryAppAllowlistSet()) {
+            resetTemporaryAppAllowlist();
+        }
+    }
+
+    private boolean isTemporaryAppAllowlistSet() {
+        return mTemporaryAppAllowlistDuration > 0
+                && mTemporaryAppAllowlistType
+                    != PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_NONE;
+    }
+
+    private void resetTemporaryAppAllowlist() {
+        mTemporaryAppAllowlistDuration = 0;
+        mTemporaryAppAllowlistType = PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_NONE;
+        mTemporaryAppAllowlistReasonCode = PowerExemptionManager.REASON_UNKNOWN;
+        mTemporaryAppAllowlistReason = null;
     }
 
     /**
      * Return {@link #setTemporaryAppAllowlist}.
      * @hide
      */
+    @TestApi
     public long getTemporaryAppAllowlistDuration() {
         return mTemporaryAppAllowlistDuration;
     }
@@ -174,6 +203,7 @@
      * Return {@link #mTemporaryAppAllowlistType}.
      * @hide
      */
+    @TestApi
     public @TempAllowListType int getTemporaryAppAllowlistType() {
         return mTemporaryAppAllowlistType;
     }
@@ -182,6 +212,7 @@
      * Return {@link #mTemporaryAppAllowlistReasonCode}.
      * @hide
      */
+    @TestApi
     public @ReasonCode int getTemporaryAppAllowlistReasonCode() {
         return mTemporaryAppAllowlistReasonCode;
     }
@@ -190,6 +221,7 @@
      * Return {@link #mTemporaryAppAllowlistReason}.
      * @hide
      */
+    @TestApi
     public @Nullable String getTemporaryAppAllowlistReason() {
         return mTemporaryAppAllowlistReason;
     }
@@ -276,16 +308,10 @@
      */
     public Bundle toBundle() {
         Bundle b = new Bundle();
-        if (mTemporaryAppAllowlistDuration > 0) {
+        if (isTemporaryAppAllowlistSet()) {
             b.putLong(KEY_TEMPORARY_APP_ALLOWLIST_DURATION, mTemporaryAppAllowlistDuration);
-        }
-        if (mTemporaryAppAllowlistType != 0) {
             b.putInt(KEY_TEMPORARY_APP_ALLOWLIST_TYPE, mTemporaryAppAllowlistType);
-        }
-        if (mTemporaryAppAllowlistReasonCode != PowerWhitelistManager.REASON_UNKNOWN) {
             b.putInt(KEY_TEMPORARY_APP_ALLOWLIST_REASON_CODE, mTemporaryAppAllowlistReasonCode);
-        }
-        if (mTemporaryAppAllowlistReason != null) {
             b.putString(KEY_TEMPORARY_APP_ALLOWLIST_REASON, mTemporaryAppAllowlistReason);
         }
         if (mMinManifestReceiverApiLevel != 0) {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 03e95fc..f8165e9 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -60,6 +60,7 @@
 import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
+import android.content.AttributionSource;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -224,8 +225,8 @@
     private final String mBasePackageName;
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final String mOpPackageName;
-
     private final @NonNull ContextParams mParams;
+    private @NonNull AttributionSource mAttributionSource;
 
     private final @NonNull ResourcesManager mResourcesManager;
     @UnsupportedAppUsage
@@ -467,13 +468,13 @@
     /** @hide */
     @Override
     public String getOpPackageName() {
-        return mOpPackageName != null ? mOpPackageName : getBasePackageName();
+        return mAttributionSource.getPackageName();
     }
 
     /** @hide */
     @Override
     public @Nullable String getAttributionTag() {
-        return mParams.getAttributionTag();
+        return mAttributionSource.getAttributionTag();
     }
 
     @Override
@@ -482,6 +483,11 @@
     }
 
     @Override
+    public @NonNull AttributionSource getAttributionSource() {
+        return mAttributionSource;
+    }
+
+    @Override
     public ApplicationInfo getApplicationInfo() {
         if (mPackageInfo != null) {
             return mPackageInfo.getApplicationInfo();
@@ -2074,13 +2080,7 @@
             Log.v(TAG, "Treating renounced permission " + permission + " as denied");
             return PERMISSION_DENIED;
         }
-
-        try {
-            return ActivityManager.getService().checkPermissionWithToken(
-                    permission, pid, uid, callerToken);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return checkPermission(permission, pid, uid);
     }
 
     @Override
@@ -2415,8 +2415,10 @@
         LoadedApk pi = mMainThread.getPackageInfo(application, mResources.getCompatibilityInfo(),
                 flags | CONTEXT_REGISTER_PACKAGE);
         if (pi != null) {
-            ContextImpl c = new ContextImpl(this, mMainThread, pi, ContextParams.EMPTY, null,
-                    mToken, new UserHandle(UserHandle.getUserId(application.uid)),
+            ContextImpl c = new ContextImpl(this, mMainThread, pi, ContextParams.EMPTY,
+                    mAttributionSource.getAttributionTag(),
+                    mAttributionSource.getNext(),
+                    null, mToken, new UserHandle(UserHandle.getUserId(application.uid)),
                     flags, null, null);
 
             final int displayId = getDisplayId();
@@ -2446,15 +2448,19 @@
         if (packageName.equals("system") || packageName.equals("android")) {
             // The system resources are loaded in every application, so we can safely copy
             // the context without reloading Resources.
-            return new ContextImpl(this, mMainThread, mPackageInfo, mParams, null,
-                    mToken, user, flags, null, null);
+            return new ContextImpl(this, mMainThread, mPackageInfo, mParams,
+                    mAttributionSource.getAttributionTag(),
+                    mAttributionSource.getNext(),
+                    null, mToken, user, flags, null, null);
         }
 
         LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(),
                 flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier());
         if (pi != null) {
-            ContextImpl c = new ContextImpl(this, mMainThread, pi, mParams, null,
-                    mToken, user, flags, null, null);
+            ContextImpl c = new ContextImpl(this, mMainThread, pi, mParams,
+                    mAttributionSource.getAttributionTag(),
+                    mAttributionSource.getNext(),
+                    null, mToken, user, flags, null, null);
 
             final int displayId = getDisplayId();
             final Integer overrideDisplayId = mForceDisplayOverrideInResources
@@ -2491,8 +2497,10 @@
         final ClassLoader classLoader = mPackageInfo.getSplitClassLoader(splitName);
         final String[] paths = mPackageInfo.getSplitPaths(splitName);
 
-        final ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo,
-                mParams, splitName, mToken, mUser, mFlags, classLoader, null);
+        final ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mParams,
+                mAttributionSource.getAttributionTag(),
+                mAttributionSource.getNext(),
+                splitName, mToken, mUser, mFlags, classLoader, null);
 
         context.setResources(ResourcesManager.getInstance().getResources(
                 mToken,
@@ -2526,6 +2534,8 @@
         }
 
         ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mParams,
+                mAttributionSource.getAttributionTag(),
+                mAttributionSource.getNext(),
                 mSplitName, mToken, mUser, mFlags, mClassLoader, null);
 
         final int displayId = getDisplayId();
@@ -2544,6 +2554,8 @@
         }
 
         ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mParams,
+                mAttributionSource.getAttributionTag(),
+                mAttributionSource.getNext(),
                 mSplitName, mToken, mUser, mFlags, mClassLoader, null);
 
         final int displayId = display.getDisplayId();
@@ -2650,6 +2662,8 @@
     @UiContext
     ContextImpl createWindowContextBase(@NonNull IBinder token, @NonNull Display display) {
         ContextImpl baseContext = new ContextImpl(this, mMainThread, mPackageInfo, mParams,
+                mAttributionSource.getAttributionTag(),
+                mAttributionSource.getNext(),
                 mSplitName, token, mUser, mFlags, mClassLoader, null);
         // Window contexts receive configurations directly from the server and as such do not
         // need to override their display in ResourcesManager.
@@ -2695,9 +2709,10 @@
 
     @NonNull
     @Override
-    public Context createContext(@NonNull ContextParams params) {
-        return new ContextImpl(this, mMainThread, mPackageInfo, params, mSplitName,
-                mToken, mUser, mFlags, mClassLoader, null);
+    public Context createContext(@NonNull ContextParams contextParams) {
+        return new ContextImpl(this, mMainThread, mPackageInfo, contextParams,
+                contextParams.getAttributionTag(), contextParams.getNextAttributionSource(),
+                mSplitName, mToken, mUser, mFlags, mClassLoader, null);
     }
 
     @Override
@@ -2710,16 +2725,20 @@
     public Context createDeviceProtectedStorageContext() {
         final int flags = (mFlags & ~Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE)
                 | Context.CONTEXT_DEVICE_PROTECTED_STORAGE;
-        return new ContextImpl(this, mMainThread, mPackageInfo, mParams, mSplitName,
-                mToken, mUser, flags, mClassLoader, null);
+        return new ContextImpl(this, mMainThread, mPackageInfo, mParams,
+                mAttributionSource.getAttributionTag(),
+                mAttributionSource.getNext(),
+                mSplitName, mToken, mUser, flags, mClassLoader, null);
     }
 
     @Override
     public Context createCredentialProtectedStorageContext() {
         final int flags = (mFlags & ~Context.CONTEXT_DEVICE_PROTECTED_STORAGE)
                 | Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE;
-        return new ContextImpl(this, mMainThread, mPackageInfo, mParams, mSplitName,
-                mToken, mUser, flags, mClassLoader, null);
+        return new ContextImpl(this, mMainThread, mPackageInfo, mParams,
+                mAttributionSource.getAttributionTag(),
+                mAttributionSource.getNext(),
+                mSplitName, mToken, mUser, flags, mClassLoader, null);
     }
 
     @Override
@@ -2893,7 +2912,7 @@
     static ContextImpl createSystemContext(ActivityThread mainThread) {
         LoadedApk packageInfo = new LoadedApk(mainThread);
         ContextImpl context = new ContextImpl(null, mainThread, packageInfo,
-                ContextParams.EMPTY, null, null, null, 0, null, null);
+                ContextParams.EMPTY, null, null, null, null, null, 0, null, null);
         context.setResources(packageInfo.getResources());
         context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
                 context.mResourcesManager.getDisplayMetrics());
@@ -2911,7 +2930,7 @@
     static ContextImpl createSystemUiContext(ContextImpl systemContext, int displayId) {
         final LoadedApk packageInfo = systemContext.mPackageInfo;
         ContextImpl context = new ContextImpl(null, systemContext.mMainThread, packageInfo,
-                ContextParams.EMPTY, null, null, null, 0, null, null);
+                ContextParams.EMPTY, null, null, null, null, null, 0, null, null);
         context.setResources(createResources(null, packageInfo, null, displayId, null,
                 packageInfo.getCompatibilityInfo(), null));
         context.updateDisplay(displayId);
@@ -2936,7 +2955,7 @@
             String opPackageName) {
         if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
         ContextImpl context = new ContextImpl(null, mainThread, packageInfo,
-                ContextParams.EMPTY, null, null, null, 0, null, opPackageName);
+            ContextParams.EMPTY, null, null, null, null, null, 0, null, opPackageName);
         context.setResources(packageInfo.getResources());
         context.mContextType = isSystemOrSystemUI(context) ? CONTEXT_TYPE_SYSTEM_OR_SYSTEM_UI
                 : CONTEXT_TYPE_NON_UI;
@@ -2966,7 +2985,7 @@
         }
 
         ContextImpl context = new ContextImpl(null, mainThread, packageInfo, ContextParams.EMPTY,
-                activityInfo.splitName, activityToken, null, 0, classLoader, null);
+                null, null, activityInfo.splitName, activityToken, null, 0, classLoader, null);
         context.mContextType = CONTEXT_TYPE_ACTIVITY;
 
         // Clamp display ID to DEFAULT_DISPLAY if it is INVALID_DISPLAY.
@@ -2999,6 +3018,7 @@
 
     private ContextImpl(@Nullable ContextImpl container, @NonNull ActivityThread mainThread,
             @NonNull LoadedApk packageInfo, @NonNull ContextParams params,
+            @Nullable String attributionTag, @Nullable AttributionSource nextAttributionSource,
             @Nullable String splitName, @Nullable IBinder token, @Nullable UserHandle user,
             int flags, @Nullable ClassLoader classLoader, @Nullable String overrideOpPackageName) {
         mOuterContext = this;
@@ -3054,9 +3074,27 @@
 
         mOpPackageName = overrideOpPackageName != null ? overrideOpPackageName : opPackageName;
         mParams = Objects.requireNonNull(params);
+        initializeAttributionSource(attributionTag, nextAttributionSource);
         mContentResolver = new ApplicationContentResolver(this, mainThread);
     }
 
+    private void initializeAttributionSource(@Nullable String attributionTag,
+            @Nullable AttributionSource nextAttributionSource) {
+        mAttributionSource = new AttributionSource(Process.myUid(), mOpPackageName,
+                attributionTag, nextAttributionSource);
+        // If we want to access protected data on behalf of another app we need to
+        // tell the OS that we opt in to participate in the attribution chain.
+        if (nextAttributionSource != null) {
+            // If an app happened to stub the internal OS for testing the registration method
+            // can return null. In this case we keep the current untrusted attribution source.
+            final AttributionSource attributionSource = getSystemService(PermissionManager.class)
+                    .registerAttributionSource(mAttributionSource);
+            if (attributionSource != null) {
+                mAttributionSource = attributionSource;
+            }
+        }
+    }
+
     void setResources(Resources r) {
         if (r instanceof CompatResources) {
             ((CompatResources) r).setContext(this);
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 4c2433c..81e5e1d 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -475,8 +475,6 @@
     @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
     boolean isTopOfTask(in IBinder token);
     void bootAnimationComplete();
-    int checkPermissionWithToken(in String permission, int pid, int uid,
-            in IBinder callerToken);
     @UnsupportedAppUsage
     void registerTaskStackListener(in ITaskStackListener listener);
     void unregisterTaskStackListener(in ITaskStackListener listener);
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index bda2fa9..a5f8f10 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -104,7 +104,6 @@
     void createConversationNotificationChannelForPackage(String pkg, int uid, in NotificationChannel parentChannel, String conversationId);
     NotificationChannel getNotificationChannelForPackage(String pkg, int uid, String channelId, String conversationId, boolean includeDeleted);
     void deleteNotificationChannel(String pkg, String channelId);
-    void deleteConversationNotificationChannels(String pkg, int uid, String conversationId);
     ParceledListSlice getNotificationChannels(String callingPkg, String targetPkg, int userId);
     ParceledListSlice getNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted);
     int getNumNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 26e6741..89d08cc 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1675,6 +1675,29 @@
     })
     public @interface PasswordComplexity {}
 
+    /** Indicates that nearby streaming is disabled. */
+    public static final int NEARBY_STREAMING_DISABLED = 0;
+
+    /** Indicates that nearby streaming is enabled. */
+    public static final int NEARBY_STREAMING_ENABLED = 1;
+
+    /**
+     * Indicates that nearby streaming is enabled only to devices offering a comparable level of
+     * security, with the same authenticated managed account.
+     */
+    public static final int NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY = 2;
+
+    /**
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"NEARBY_STREAMING_"}, value = {
+        NEARBY_STREAMING_DISABLED,
+        NEARBY_STREAMING_ENABLED,
+        NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY,
+    })
+    public @interface NearbyStreamingPolicy {}
+
     /**
      * Activity action: have the user enter a new password for the parent profile.
      * If the intent is launched from within a managed profile, this will trigger
@@ -7163,6 +7186,77 @@
     }
 
     /**
+     * Called by a device/profile owner to set nearby notification streaming policy. Notification
+     * streaming is sending notification data from pre-installed apps to nearby devices.
+     *
+     * @param policy One of the {@code NearbyStreamingPolicy} constants.
+     * @throws SecurityException if caller is not a device or profile owner
+     */
+    public void setNearbyNotificationStreamingPolicy(@NearbyStreamingPolicy int policy) {
+        throwIfParentInstance("setNearbyNotificationStreamingPolicy");
+        if (mService == null) {
+            return;
+        }
+        try {
+            mService.setNearbyNotificationStreamingPolicy(policy);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns the current runtime nearby notification streaming policy set by the device or profile
+     * owner. The default is {@link #NEARBY_STREAMING_DISABLED}.
+     */
+    public @NearbyStreamingPolicy int getNearbyNotificationStreamingPolicy() {
+        throwIfParentInstance("getNearbyNotificationStreamingPolicy");
+        if (mService == null) {
+            return NEARBY_STREAMING_DISABLED;
+        }
+        try {
+            return mService.getNearbyNotificationStreamingPolicy();
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Called by a device/profile owner to set nearby app streaming policy. App streaming is when
+     * the device starts an app on a virtual display and sends a video stream of the app to nearby
+     * devices.
+     *
+     * @param policy One of the {@code NearbyStreamingPolicy} constants.
+     * @throws SecurityException if caller is not a device or profile owner.
+     */
+    public void setNearbyAppStreamingPolicy(@NearbyStreamingPolicy int policy) {
+        throwIfParentInstance("setNearbyAppStreamingPolicy");
+        if (mService == null) {
+            return;
+        }
+        try {
+            mService.setNearbyAppStreamingPolicy(policy);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns the current runtime nearby app streaming policy set by the device or profile owner.
+     * The default is {@link #NEARBY_STREAMING_DISABLED}.
+     */
+    public @NearbyStreamingPolicy int getNearbyAppStreamingPolicy() {
+        throwIfParentInstance("getNearbyAppStreamingPolicy");
+        if (mService == null) {
+            return NEARBY_STREAMING_DISABLED;
+        }
+        try {
+            return mService.getNearbyAppStreamingPolicy();
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Called by a device owner, or alternatively a profile owner from Android 8.0 (API level 26) or
      * higher, to set whether auto time is required. If auto time is required, no user will be able
      * set the date and time and network date and time will be used.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 5e49a98..8a8c69c 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -132,6 +132,12 @@
     void setScreenCaptureDisabled(in ComponentName who, boolean disabled, boolean parent);
     boolean getScreenCaptureDisabled(in ComponentName who, int userHandle, boolean parent);
 
+    void setNearbyNotificationStreamingPolicy(int policy);
+    int getNearbyNotificationStreamingPolicy();
+
+    void setNearbyAppStreamingPolicy(int policy);
+    int getNearbyAppStreamingPolicy();
+
     void setKeyguardDisabledFeatures(in ComponentName who, int which, boolean parent);
     int getKeyguardDisabledFeatures(in ComponentName who, int userHandle, boolean parent);
 
diff --git a/core/java/android/app/time/ExternalTimeSuggestion.java b/core/java/android/app/time/ExternalTimeSuggestion.java
index 61defb5..8e281c0 100644
--- a/core/java/android/app/time/ExternalTimeSuggestion.java
+++ b/core/java/android/app/time/ExternalTimeSuggestion.java
@@ -20,6 +20,7 @@
 import android.annotation.ElapsedRealtimeLong;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.TimestampedValue;
@@ -67,6 +68,7 @@
  *
  * @hide
  */
+@SystemApi
 public final class ExternalTimeSuggestion implements Parcelable {
 
     public static final @NonNull Creator<ExternalTimeSuggestion> CREATOR =
@@ -129,7 +131,6 @@
 
     /**
      * Returns information that can be useful for debugging / logging. See {@link #addDebugInfo}.
-     * {@hide}
      */
     @NonNull
     public List<String> getDebugInfo() {
diff --git a/core/java/android/app/time/TimeManager.java b/core/java/android/app/time/TimeManager.java
index c71badb0..d6acb8c 100644
--- a/core/java/android/app/time/TimeManager.java
+++ b/core/java/android/app/time/TimeManager.java
@@ -262,7 +262,6 @@
      * HAL. This time <em>may</em> be used to set the device system clock, depending on the device
      * configuration and user settings. This method call is processed asynchronously.
      * See {@link ExternalTimeSuggestion} for more details.
-     * {@hide}
      */
     @RequiresPermission(android.Manifest.permission.SUGGEST_EXTERNAL_TIME)
     public void suggestExternalTime(@NonNull ExternalTimeSuggestion timeSuggestion) {
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index a3d19ca..0be7b73 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -745,7 +745,6 @@
      * Use {@link #getDefaultAdapter} to get the BluetoothAdapter instance.
      */
     BluetoothAdapter(IBluetoothManager managerService) {
-
         if (managerService == null) {
             throw new IllegalArgumentException("bluetooth manager service is null");
         }
diff --git a/core/java/android/content/AttributionSource.aidl b/core/java/android/content/AttributionSource.aidl
new file mode 100644
index 0000000..10d5c27
--- /dev/null
+++ b/core/java/android/content/AttributionSource.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2021 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.content;
+
+parcelable AttributionSource;
diff --git a/core/java/android/content/AttributionSource.java b/core/java/android/content/AttributionSource.java
new file mode 100644
index 0000000..053bfc1
--- /dev/null
+++ b/core/java/android/content/AttributionSource.java
@@ -0,0 +1,612 @@
+/*
+ * Copyright (C) 2021 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.content;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.app.AppGlobals;
+import android.os.Binder;
+import android.os.Build;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.permission.PermissionManager;
+import android.util.ArraySet;
+
+import com.android.internal.annotations.Immutable;
+import com.android.internal.util.CollectionUtils;
+import com.android.internal.util.DataClass;
+import com.android.internal.util.Parcelling;
+
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * This class represents a source to which access to permission protected data should be
+ * attributed. Attribution sources can be chained to represent cases where the protected
+ * data would flow through several applications. For example, app A may ask app B for
+ * contacts and in turn app B may ask app C for contacts. In this case, the attribution
+ * chain would be A -> B -> C and the data flow would be C -> B -> A. There are two
+ * main benefits of using the attribution source mechanism: avoid doing explicit permission
+ * checks on behalf of the calling app if you are accessing private data on their behalf
+ * to send back; avoid double data access blaming which happens as you check the calling
+ * app's permissions and when you access the data behind these permissions (for runtime
+ * permissions). Also if not explicitly blaming the caller the data access would be
+ * counted towards your app vs to the previous app where yours was just a proxy.
+ * <p>
+ * Every {@link Context} has an attribution source and you can get it via {@link
+ * Context#getAttributionSource()} representing itself, which is a chain of one. You
+ * can attribute work to another app, or more precisely to a chain of apps, through
+ * which the data you would be accessing would flow, via {@link Context#createContext(
+ * ContextParams)} plus specifying an attribution source for the next app to receive
+ * the protected data you are accessing via {@link AttributionSource.Builder#setNext(
+ * AttributionSource)}. Creating this attribution chain ensures that the datasource would
+ * check whether every app in the attribution chain has permission to access the data
+ * before releasing it. The datasource will also record appropriately that this data was
+ * accessed by the apps in the sequence if the data is behind a sensitive permission
+ * (e.g. dangerous). Again, this is useful if you are accessing the data on behalf of another
+ * app, for example a speech recognizer using the mic so it can provide recognition to
+ * a calling app.
+ * <p>
+ * You can create an attribution chain of you and any other app without any verification
+ * as this is something already available via the {@link android.app.AppOpsManager} APIs.
+ * This is supported to handle cases where you don't have access to the caller's attribution
+ * source and you can directly use the {@link AttributionSource.Builder} APIs. However,
+ * if the data flows through more than two apps (more than you access the data for the
+ * caller - which you cannot know ahead of time) you need to have a handle to the {@link
+ * AttributionSource} for the calling app's context in order to create an attribution context.
+ * This means you either need to have an API for the other app to send you its attribution
+ * source or use a platform API that pipes the callers attribution source.
+ * <p>
+ * You cannot forge an attribution chain without the participation of every app in the
+ * attribution chain (aside of the special case mentioned above). To create an attribution
+ * source that is trusted you need to create an attribution context that points to an
+ * attribution source that was explicitly created by the app that it refers to, recursively.
+ * <p>
+ * Since creating an attribution context leads to all permissions for apps in the attribution
+ * chain being checked, you need to expect getting a security exception when accessing
+ * permission protected APIs since some app in the chain may not have the permission.
+ */
+@Immutable
+// TODO: Codegen doesn't properly verify the class if the parcelling is inner class
+// TODO: Codegen doesn't allow overriding the constructor to change its visibility
+// TODO: Codegen applies method level annotations to argument vs the generated member (@SystemApi)
+// TODO: Codegen doesn't properly read/write IBinder members
+// TODO: Codegen doesn't properly handle Set arguments
+// @DataClass(genEqualsHashCode = true, genConstructor = false, genBuilder = true)
+public final class AttributionSource implements Parcelable {
+    /**
+     * @hide
+     */
+    static class RenouncedPermissionsParcelling implements Parcelling<Set<String>> {
+
+        @Override
+        public void parcel(Set<String> item, Parcel dest, int parcelFlags) {
+            if (item == null) {
+                dest.writeInt(-1);
+            } else {
+                dest.writeInt(item.size());
+                for (String permission : item) {
+                    dest.writeString8(permission);
+                }
+            }
+        }
+
+        @Override
+        public Set<String> unparcel(Parcel source) {
+            final int size = source.readInt();
+            if (size < 0) {
+                return null;
+            }
+            final ArraySet<String> result = new ArraySet<>(size);
+            for (int i = 0; i < size; i++) {
+                result.add(source.readString8());
+            }
+            return result;
+        }
+    }
+
+    /**
+     * The UID that is accessing the permission protected data.
+     */
+    private final int mUid;
+
+    /**
+     * The package that is accessing the permission protected data.
+     */
+    private @Nullable String mPackageName = null;
+
+    /**
+     * The attribution tag of the app accessing the permission protected data.
+     */
+    private @Nullable String mAttributionTag = null;
+
+    /**
+     * Unique token for that source.
+     *
+     * @hide
+     */
+    private @Nullable IBinder mToken = null;
+
+    /**
+     * Permissions that should be considered revoked regardless if granted.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS)
+    @DataClass.ParcelWith(RenouncedPermissionsParcelling.class)
+    private @Nullable Set<String> mRenouncedPermissions = null;
+
+    /**
+     * The next app to receive the permission protected data.
+     */
+    private @Nullable AttributionSource mNext = null;
+
+    /** @hide */
+    @TestApi
+    public AttributionSource(int uid, @Nullable String packageName,
+            @Nullable String attributionTag) {
+        this(uid, packageName, attributionTag, /*next*/ null);
+    }
+
+    /** @hide */
+    @TestApi
+    public AttributionSource(int uid, @Nullable String packageName,
+            @Nullable String attributionTag, @Nullable AttributionSource next) {
+        this(uid, packageName, attributionTag, /*token*/ null,
+                /*renouncedPermissions*/ null, next);
+    }
+
+    /** @hide */
+    public AttributionSource(@NonNull AttributionSource current,
+            @Nullable AttributionSource next) {
+        this(current.getUid(), current.getPackageName(), current.getAttributionTag(),
+                /*token*/ null, /*renouncedPermissions*/ null, next);
+    }
+
+    /** @hide */
+    public AttributionSource withNextAttributionSource(@Nullable AttributionSource next) {
+        return new AttributionSource(mUid, mPackageName, mAttributionTag,  mToken,
+                mRenouncedPermissions, next);
+    }
+
+    /** @hide */
+    public AttributionSource withToken(@Nullable IBinder token) {
+        return new AttributionSource(mUid, mPackageName, mAttributionTag, token,
+                mRenouncedPermissions, mNext);
+    }
+
+    /**
+     * If you are handling an IPC and you don't trust the caller you need to validate
+     * whether the attribution source is one for the calling app to prevent the caller
+     * to pass you a source from another app without including themselves in the
+     * attribution chain.
+     *
+     * @throws SecurityException if the attribution source cannot be trusted to be
+     * from the caller.
+     */
+    public void enforceCallingUid() {
+        final int callingUid = Binder.getCallingUid();
+        if (callingUid != Process.SYSTEM_UID && callingUid != mUid) {
+            throw new SecurityException("Calling uid: " + callingUid
+                    + " doesn't match source uid: " + mUid);
+        }
+        // No need to check package as app ops manager does it already.
+    }
+
+    /**
+     * If you are handling an IPC and you don't trust the caller you need to validate
+     * whether the attribution source is one for the calling app to prevent the caller
+     * to pass you a source from another app without including themselves in the
+     * attribution chain.
+     *f
+     * @return if the attribution source cannot be trusted to be from the caller.
+     */
+    public boolean checkCallingUid() {
+        final int callingUid = Binder.getCallingUid();
+        if (callingUid != Process.SYSTEM_UID && callingUid != mUid) {
+            return false;
+        }
+        // No need to check package as app ops manager does it already.
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        if (Build.IS_DEBUGGABLE) {
+            return "AttributionSource { " +
+                    "uid = " + mUid + ", " +
+                    "packageName = " + mPackageName + ", " +
+                    "attributionTag = " + mAttributionTag + ", " +
+                    "token = " + mToken + ", " +
+                    "next = " + mNext +
+                    " }";
+        }
+        return super.toString();
+    }
+
+    /**
+     * @return The next UID that would receive the permission protected data.
+     *
+     * @hide
+     */
+    public int getNextUid() {
+        if (mNext != null) {
+            return mNext.getUid();
+        }
+        return Process.INVALID_UID;
+    }
+
+    /**
+     * @return The next package that would receive the permission protected data.
+     *
+     * @hide
+     */
+    public @Nullable String getNextPackageName() {
+        if (mNext != null) {
+            return mNext.getPackageName();
+        }
+        return null;
+    }
+
+    /**
+     * @return The nexxt package's attribution tag that would receive
+     * the permission protected data.
+     *
+     * @hide
+     */
+    public @Nullable String getNextAttributionTag() {
+        if (mNext != null) {
+            return mNext.getAttributionTag();
+        }
+        return null;
+    }
+
+    /**
+     * Checks whether this attribution source can be trusted. That is whether
+     * the app it refers to created it and provided to the attribution chain.
+     *
+     * @param context Context handle.
+     * @return Whether this is a trusted source.
+     */
+    public boolean isTrusted(@NonNull Context context) {
+        return mToken != null && context.getSystemService(PermissionManager.class)
+                .isRegisteredAttributionSource(this);
+    }
+
+    /**
+     * Permissions that should be considered revoked regardless if granted.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS)
+    @NonNull
+    public Set<String> getRenouncedPermissions() {
+        return CollectionUtils.emptyIfNull(mRenouncedPermissions);
+    }
+
+    @DataClass.Suppress({"setUid", "setToken"})
+    static class BaseBuilder {}
+
+
+
+
+
+
+    // Code below generated by codegen v1.0.22.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/AttributionSource.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    /* package-private */ AttributionSource(
+            int uid,
+            @Nullable String packageName,
+            @Nullable String attributionTag,
+            @Nullable IBinder token,
+            @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS) @Nullable Set<String> renouncedPermissions,
+            @Nullable AttributionSource next) {
+        this.mUid = uid;
+        this.mPackageName = packageName;
+        this.mAttributionTag = attributionTag;
+        this.mToken = token;
+        this.mRenouncedPermissions = renouncedPermissions;
+        com.android.internal.util.AnnotationValidations.validate(
+                SystemApi.class, null, mRenouncedPermissions);
+        com.android.internal.util.AnnotationValidations.validate(
+                RequiresPermission.class, null, mRenouncedPermissions,
+                "value", android.Manifest.permission.RENOUNCE_PERMISSIONS);
+        this.mNext = next;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    /**
+     * The UID that is accessing the permission protected data.
+     */
+    public int getUid() {
+        return mUid;
+    }
+
+    /**
+     * The package that is accessing the permission protected data.
+     */
+    public @Nullable String getPackageName() {
+        return mPackageName;
+    }
+
+    /**
+     * The attribution tag of the app accessing the permission protected data.
+     */
+    public @Nullable String getAttributionTag() {
+        return mAttributionTag;
+    }
+
+    /**
+     * Unique token for that source.
+     *
+     * @hide
+     */
+    public @Nullable IBinder getToken() {
+        return mToken;
+    }
+
+    /**
+     * The next app to receive the permission protected data.
+     */
+    public @Nullable AttributionSource getNext() {
+        return mNext;
+    }
+
+    @Override
+    public boolean equals(@Nullable Object o) {
+        // You can override field equality logic by defining either of the methods like:
+        // boolean fieldNameEquals(AttributionSource other) { ... }
+        // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        @SuppressWarnings("unchecked")
+        AttributionSource that = (AttributionSource) o;
+        //noinspection PointlessBooleanExpression
+        return true
+                && mUid == that.mUid
+                && Objects.equals(mPackageName, that.mPackageName)
+                && Objects.equals(mAttributionTag, that.mAttributionTag)
+                && Objects.equals(mToken, that.mToken)
+                && Objects.equals(mRenouncedPermissions, that.mRenouncedPermissions)
+                && Objects.equals(mNext, that.mNext);
+    }
+
+    @Override
+    public int hashCode() {
+        // You can override field hashCode logic by defining methods like:
+        // int fieldNameHashCode() { ... }
+
+        int _hash = 1;
+        _hash = 31 * _hash + mUid;
+        _hash = 31 * _hash + Objects.hashCode(mPackageName);
+        _hash = 31 * _hash + Objects.hashCode(mAttributionTag);
+        _hash = 31 * _hash + Objects.hashCode(mToken);
+        _hash = 31 * _hash + Objects.hashCode(mRenouncedPermissions);
+        _hash = 31 * _hash + Objects.hashCode(mNext);
+        return _hash;
+    }
+
+    static Parcelling<Set<String>> sParcellingForRenouncedPermissions =
+            Parcelling.Cache.get(
+                    RenouncedPermissionsParcelling.class);
+    static {
+        if (sParcellingForRenouncedPermissions == null) {
+            sParcellingForRenouncedPermissions = Parcelling.Cache.put(
+                    new RenouncedPermissionsParcelling());
+        }
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        byte flg = 0;
+        if (mPackageName != null) flg |= 0x2;
+        if (mAttributionTag != null) flg |= 0x4;
+        if (mToken != null) flg |= 0x8;
+        if (mRenouncedPermissions != null) flg |= 0x10;
+        if (mNext != null) flg |= 0x20;
+        dest.writeByte(flg);
+        dest.writeInt(mUid);
+        if (mPackageName != null) dest.writeString(mPackageName);
+        if (mAttributionTag != null) dest.writeString(mAttributionTag);
+        if (mToken != null) dest.writeStrongBinder(mToken);
+        sParcellingForRenouncedPermissions.parcel(mRenouncedPermissions, dest, flags);
+        if (mNext != null) dest.writeTypedObject(mNext, flags);
+    }
+
+    @Override
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    /* package-private */ AttributionSource(@NonNull Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        byte flg = in.readByte();
+        int uid = in.readInt();
+        String packageName = (flg & 0x2) == 0 ? null : in.readString();
+        String attributionTag = (flg & 0x4) == 0 ? null : in.readString();
+        IBinder token = (flg & 0x8) == 0 ? null : in.readStrongBinder();
+        Set<String> renouncedPermissions = sParcellingForRenouncedPermissions.unparcel(in);
+        AttributionSource next = (flg & 0x20) == 0 ? null : (AttributionSource) in.readTypedObject(AttributionSource.CREATOR);
+
+        this.mUid = uid;
+        this.mPackageName = packageName;
+        this.mAttributionTag = attributionTag;
+        this.mToken = token;
+        this.mRenouncedPermissions = renouncedPermissions;
+        com.android.internal.util.AnnotationValidations.validate(
+                SystemApi.class, null, mRenouncedPermissions);
+        com.android.internal.util.AnnotationValidations.validate(
+                RequiresPermission.class, null, mRenouncedPermissions,
+                "value", android.Manifest.permission.RENOUNCE_PERMISSIONS);
+        this.mNext = next;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    public static final @NonNull Parcelable.Creator<AttributionSource> CREATOR
+            = new Parcelable.Creator<AttributionSource>() {
+        @Override
+        public AttributionSource[] newArray(int size) {
+            return new AttributionSource[size];
+        }
+
+        @Override
+        public AttributionSource createFromParcel(@NonNull Parcel in) {
+            return new AttributionSource(in);
+        }
+    };
+
+    /**
+     * A builder for {@link AttributionSource}
+     */
+    @SuppressWarnings("WeakerAccess")
+    public static final class Builder extends BaseBuilder {
+
+        private int mUid;
+        private @Nullable String mPackageName;
+        private @Nullable String mAttributionTag;
+        private @Nullable IBinder mToken;
+        private @SystemApi @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS) @Nullable Set<String> mRenouncedPermissions;
+        private @Nullable AttributionSource mNext;
+
+        private long mBuilderFieldsSet = 0L;
+
+        /**
+         * Creates a new Builder.
+         *
+         * @param uid
+         *   The UID that is accessing the permission protected data.
+         */
+        public Builder(
+                int uid) {
+            mUid = uid;
+        }
+
+        /**
+         * The package that is accessing the permission protected data.
+         */
+        public @NonNull Builder setPackageName(@NonNull String value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x2;
+            mPackageName = value;
+            return this;
+        }
+
+        /**
+         * The attribution tag of the app accessing the permission protected data.
+         */
+        public @NonNull Builder setAttributionTag(@NonNull String value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x4;
+            mAttributionTag = value;
+            return this;
+        }
+
+        /**
+         * Permissions that should be considered revoked regardless if granted.
+         *
+         * @hide
+         */
+        @SystemApi
+        @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS)
+        public @NonNull Builder setRenouncedPermissions(@NonNull Set<String> value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x10;
+            mRenouncedPermissions = value;
+            return this;
+        }
+
+        /**
+         * The next app to receive the permission protected data.
+         */
+        public @NonNull Builder setNext(@NonNull AttributionSource value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x20;
+            mNext = value;
+            return this;
+        }
+
+        /** Builds the instance. This builder should not be touched after calling this! */
+        public @NonNull AttributionSource build() {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x40; // Mark builder used
+
+            if ((mBuilderFieldsSet & 0x2) == 0) {
+                mPackageName = null;
+            }
+            if ((mBuilderFieldsSet & 0x4) == 0) {
+                mAttributionTag = null;
+            }
+            if ((mBuilderFieldsSet & 0x8) == 0) {
+                mToken = null;
+            }
+            if ((mBuilderFieldsSet & 0x10) == 0) {
+                mRenouncedPermissions = null;
+            }
+            if ((mBuilderFieldsSet & 0x20) == 0) {
+                mNext = null;
+            }
+            AttributionSource o = new AttributionSource(
+                    mUid,
+                    mPackageName,
+                    mAttributionTag,
+                    mToken,
+                    mRenouncedPermissions,
+                    mNext);
+            return o;
+        }
+
+        private void checkNotUsed() {
+            if ((mBuilderFieldsSet & 0x40) != 0) {
+                throw new IllegalStateException(
+                        "This Builder should not be reused. Use a new Builder instance instead");
+            }
+        }
+    }
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 73b4f62..8284203 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -18,11 +18,6 @@
 
 import static android.Manifest.permission.INTERACT_ACROSS_USERS;
 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
-import static android.app.AppOpsManager.MODE_ALLOWED;
-import static android.app.AppOpsManager.MODE_DEFAULT;
-import static android.app.AppOpsManager.MODE_ERRORED;
-import static android.app.AppOpsManager.MODE_IGNORED;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.os.Trace.TRACE_TAG_DATABASE;
 
 import android.annotation.NonNull;
@@ -45,7 +40,6 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.CancellationSignal;
-import android.os.IBinder;
 import android.os.ICancellationSignal;
 import android.os.ParcelFileDescriptor;
 import android.os.ParcelableException;
@@ -57,7 +51,6 @@
 import android.os.storage.StorageManager;
 import android.text.TextUtils;
 import android.util.Log;
-import android.util.Pair;
 
 import com.android.internal.annotations.VisibleForTesting;
 
@@ -141,7 +134,7 @@
     private boolean mNoPerms;
     private boolean mSingleUser;
 
-    private ThreadLocal<Pair<String, String>> mCallingPackage;
+    private ThreadLocal<AttributionSource> mCallingAttributionSource;
 
     private Transport mTransport = new Transport();
 
@@ -231,13 +224,13 @@
         }
 
         @Override
-        public Cursor query(String callingPkg, @Nullable String attributionTag, Uri uri,
+        public Cursor query(@NonNull AttributionSource attributionSource, Uri uri,
                 @Nullable String[] projection, @Nullable Bundle queryArgs,
                 @Nullable ICancellationSignal cancellationSignal) {
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
-            if (enforceReadPermission(callingPkg, attributionTag, uri, null)
-                    != AppOpsManager.MODE_ALLOWED) {
+            if (enforceReadPermission(attributionSource, uri)
+                    != PermissionChecker.PERMISSION_GRANTED) {
                 // The caller has no access to the data, so return an empty cursor with
                 // the columns in the requested order. The caller may ask for an invalid
                 // column and we would not catch that but this is not a problem in practice.
@@ -253,8 +246,8 @@
                 // we have to execute the query as if allowed to get a cursor with the
                 // columns. We then use the column names to return an empty cursor.
                 Cursor cursor;
-                final Pair<String, String> original = setCallingPackage(
-                        new Pair<>(callingPkg, attributionTag));
+                final AttributionSource original = setCallingAttributionSource(
+                        attributionSource);
                 try {
                     cursor = mInterface.query(
                             uri, projection, queryArgs,
@@ -262,7 +255,7 @@
                 } catch (RemoteException e) {
                     throw e.rethrowAsRuntimeException();
                 } finally {
-                    setCallingPackage(original);
+                    setCallingAttributionSource(original);
                 }
                 if (cursor == null) {
                     return null;
@@ -272,8 +265,8 @@
                 return new MatrixCursor(cursor.getColumnNames(), 0);
             }
             Trace.traceBegin(TRACE_TAG_DATABASE, "query");
-            final Pair<String, String> original = setCallingPackage(
-                    new Pair<>(callingPkg, attributionTag));
+            final AttributionSource original = setCallingAttributionSource(
+                    attributionSource);
             try {
                 return mInterface.query(
                         uri, projection, queryArgs,
@@ -281,7 +274,7 @@
             } catch (RemoteException e) {
                 throw e.rethrowAsRuntimeException();
             } finally {
-                setCallingPackage(original);
+                setCallingAttributionSource(original);
                 Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
@@ -314,60 +307,59 @@
         }
 
         @Override
-        public Uri insert(String callingPkg, @Nullable String attributionTag, Uri uri,
+        public Uri insert(@NonNull AttributionSource attributionSource, Uri uri,
                 ContentValues initialValues, Bundle extras) {
             uri = validateIncomingUri(uri);
             int userId = getUserIdFromUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
-            if (enforceWritePermission(callingPkg, attributionTag, uri, null)
-                    != AppOpsManager.MODE_ALLOWED) {
-                final Pair<String, String> original = setCallingPackage(
-                        new Pair<>(callingPkg, attributionTag));
+            if (enforceWritePermission(attributionSource, uri)
+                    != PermissionChecker.PERMISSION_GRANTED) {
+                final AttributionSource original = setCallingAttributionSource(
+                        attributionSource);
                 try {
                     return rejectInsert(uri, initialValues);
                 } finally {
-                    setCallingPackage(original);
+                    setCallingAttributionSource(original);
                 }
             }
             Trace.traceBegin(TRACE_TAG_DATABASE, "insert");
-            final Pair<String, String> original = setCallingPackage(
-                    new Pair<>(callingPkg, attributionTag));
+            final AttributionSource original = setCallingAttributionSource(
+                    attributionSource);
             try {
                 return maybeAddUserId(mInterface.insert(uri, initialValues, extras), userId);
             } catch (RemoteException e) {
                 throw e.rethrowAsRuntimeException();
             } finally {
-                setCallingPackage(original);
+                setCallingAttributionSource(original);
                 Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
         @Override
-        public int bulkInsert(String callingPkg, @Nullable String attributionTag, Uri uri,
+        public int bulkInsert(@NonNull AttributionSource attributionSource, Uri uri,
                 ContentValues[] initialValues) {
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
-            if (enforceWritePermission(callingPkg, attributionTag, uri, null)
-                    != AppOpsManager.MODE_ALLOWED) {
+            if (enforceWritePermission(attributionSource, uri)
+                    != PermissionChecker.PERMISSION_GRANTED) {
                 return 0;
             }
             Trace.traceBegin(TRACE_TAG_DATABASE, "bulkInsert");
-            final Pair<String, String> original = setCallingPackage(
-                    new Pair<>(callingPkg, attributionTag));
+            final AttributionSource original = setCallingAttributionSource(
+                    attributionSource);
             try {
                 return mInterface.bulkInsert(uri, initialValues);
             } catch (RemoteException e) {
                 throw e.rethrowAsRuntimeException();
             } finally {
-                setCallingPackage(original);
+                setCallingAttributionSource(original);
                 Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
         @Override
-        public ContentProviderResult[] applyBatch(String callingPkg,
-                @Nullable String attributionTag, String authority,
-                ArrayList<ContentProviderOperation> operations)
+        public ContentProviderResult[] applyBatch(@NonNull AttributionSource attributionSource,
+                String authority, ArrayList<ContentProviderOperation> operations)
                 throws OperationApplicationException {
             validateIncomingAuthority(authority);
             int numOperations = operations.size();
@@ -383,22 +375,24 @@
                     operation = new ContentProviderOperation(operation, uri);
                     operations.set(i, operation);
                 }
+                final AttributionSource accessAttributionSource =
+                        attributionSource;
                 if (operation.isReadOperation()) {
-                    if (enforceReadPermission(callingPkg, attributionTag, uri, null)
-                            != AppOpsManager.MODE_ALLOWED) {
+                    if (enforceReadPermission(accessAttributionSource, uri)
+                            != PermissionChecker.PERMISSION_GRANTED) {
                         throw new OperationApplicationException("App op not allowed", 0);
                     }
                 }
                 if (operation.isWriteOperation()) {
-                    if (enforceWritePermission(callingPkg, attributionTag, uri, null)
-                            != AppOpsManager.MODE_ALLOWED) {
+                    if (enforceWritePermission(accessAttributionSource, uri)
+                            != PermissionChecker.PERMISSION_GRANTED) {
                         throw new OperationApplicationException("App op not allowed", 0);
                     }
                 }
             }
             Trace.traceBegin(TRACE_TAG_DATABASE, "applyBatch");
-            final Pair<String, String> original = setCallingPackage(
-                    new Pair<>(callingPkg, attributionTag));
+            final AttributionSource original = setCallingAttributionSource(
+                    attributionSource);
             try {
                 ContentProviderResult[] results = mInterface.applyBatch(authority,
                         operations);
@@ -414,111 +408,111 @@
             } catch (RemoteException e) {
                 throw e.rethrowAsRuntimeException();
             } finally {
-                setCallingPackage(original);
+                setCallingAttributionSource(original);
                 Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
         @Override
-        public int delete(String callingPkg, @Nullable String attributionTag, Uri uri,
+        public int delete(@NonNull AttributionSource attributionSource, Uri uri,
                 Bundle extras) {
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
-            if (enforceWritePermission(callingPkg, attributionTag, uri, null)
-                    != AppOpsManager.MODE_ALLOWED) {
+            if (enforceWritePermission(attributionSource, uri)
+                    != PermissionChecker.PERMISSION_GRANTED) {
                 return 0;
             }
             Trace.traceBegin(TRACE_TAG_DATABASE, "delete");
-            final Pair<String, String> original = setCallingPackage(
-                    new Pair<>(callingPkg, attributionTag));
+            final AttributionSource original = setCallingAttributionSource(
+                    attributionSource);
             try {
                 return mInterface.delete(uri, extras);
             } catch (RemoteException e) {
                 throw e.rethrowAsRuntimeException();
             } finally {
-                setCallingPackage(original);
+                setCallingAttributionSource(original);
                 Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
         @Override
-        public int update(String callingPkg, @Nullable String attributionTag, Uri uri,
+        public int update(@NonNull AttributionSource attributionSource, Uri uri,
                 ContentValues values, Bundle extras) {
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
-            if (enforceWritePermission(callingPkg, attributionTag, uri, null)
-                    != AppOpsManager.MODE_ALLOWED) {
+            if (enforceWritePermission(attributionSource, uri)
+                    != PermissionChecker.PERMISSION_GRANTED) {
                 return 0;
             }
             Trace.traceBegin(TRACE_TAG_DATABASE, "update");
-            final Pair<String, String> original = setCallingPackage(
-                    new Pair<>(callingPkg, attributionTag));
+            final AttributionSource original = setCallingAttributionSource(
+                    attributionSource);
             try {
                 return mInterface.update(uri, values, extras);
             } catch (RemoteException e) {
                 throw e.rethrowAsRuntimeException();
             } finally {
-                setCallingPackage(original);
+                setCallingAttributionSource(original);
                 Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
         @Override
-        public ParcelFileDescriptor openFile(String callingPkg, @Nullable String attributionTag,
-                Uri uri, String mode, ICancellationSignal cancellationSignal, IBinder callerToken)
+        public ParcelFileDescriptor openFile(@NonNull AttributionSource attributionSource,
+                Uri uri, String mode, ICancellationSignal cancellationSignal)
                 throws FileNotFoundException {
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
-            enforceFilePermission(callingPkg, attributionTag, uri, mode, callerToken);
+            enforceFilePermission(attributionSource, uri, mode);
             Trace.traceBegin(TRACE_TAG_DATABASE, "openFile");
-            final Pair<String, String> original = setCallingPackage(
-                    new Pair<>(callingPkg, attributionTag));
+            final AttributionSource original = setCallingAttributionSource(
+                    attributionSource);
             try {
                 return mInterface.openFile(
                         uri, mode, CancellationSignal.fromTransport(cancellationSignal));
             } catch (RemoteException e) {
                 throw e.rethrowAsRuntimeException();
             } finally {
-                setCallingPackage(original);
+                setCallingAttributionSource(original);
                 Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
         @Override
-        public AssetFileDescriptor openAssetFile(String callingPkg, @Nullable String attributionTag,
+        public AssetFileDescriptor openAssetFile(@NonNull AttributionSource attributionSource,
                 Uri uri, String mode, ICancellationSignal cancellationSignal)
                 throws FileNotFoundException {
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
-            enforceFilePermission(callingPkg, attributionTag, uri, mode, null);
+            enforceFilePermission(attributionSource, uri, mode);
             Trace.traceBegin(TRACE_TAG_DATABASE, "openAssetFile");
-            final Pair<String, String> original = setCallingPackage(
-                    new Pair<>(callingPkg, attributionTag));
+            final AttributionSource original = setCallingAttributionSource(
+                    attributionSource);
             try {
                 return mInterface.openAssetFile(
                         uri, mode, CancellationSignal.fromTransport(cancellationSignal));
             } catch (RemoteException e) {
                 throw e.rethrowAsRuntimeException();
             } finally {
-                setCallingPackage(original);
+                setCallingAttributionSource(original);
                 Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
         @Override
-        public Bundle call(String callingPkg, @Nullable String attributionTag, String authority,
+        public Bundle call(@NonNull AttributionSource attributionSource, String authority,
                 String method, @Nullable String arg, @Nullable Bundle extras) {
             validateIncomingAuthority(authority);
             Bundle.setDefusable(extras, true);
             Trace.traceBegin(TRACE_TAG_DATABASE, "call");
-            final Pair<String, String> original = setCallingPackage(
-                    new Pair<>(callingPkg, attributionTag));
+            final AttributionSource original = setCallingAttributionSource(
+                    attributionSource);
             try {
                 return mInterface.call(authority, method, arg, extras);
             } catch (RemoteException e) {
                 throw e.rethrowAsRuntimeException();
             } finally {
-                setCallingPackage(original);
+                setCallingAttributionSource(original);
                 Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
@@ -539,23 +533,23 @@
         }
 
         @Override
-        public AssetFileDescriptor openTypedAssetFile(String callingPkg,
-                @Nullable String attributionTag, Uri uri, String mimeType, Bundle opts,
-                ICancellationSignal cancellationSignal) throws FileNotFoundException {
+        public AssetFileDescriptor openTypedAssetFile(
+                @NonNull AttributionSource attributionSource, Uri uri, String mimeType,
+                Bundle opts, ICancellationSignal cancellationSignal) throws FileNotFoundException {
             Bundle.setDefusable(opts, true);
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
-            enforceFilePermission(callingPkg, attributionTag, uri, "r", null);
+            enforceFilePermission(attributionSource, uri, "r");
             Trace.traceBegin(TRACE_TAG_DATABASE, "openTypedAssetFile");
-            final Pair<String, String> original = setCallingPackage(
-                    new Pair<>(callingPkg, attributionTag));
+            final AttributionSource original = setCallingAttributionSource(
+                    attributionSource);
             try {
                 return mInterface.openTypedAssetFile(
                         uri, mimeType, opts, CancellationSignal.fromTransport(cancellationSignal));
             } catch (RemoteException e) {
                 throw e.rethrowAsRuntimeException();
             } finally {
-                setCallingPackage(original);
+                setCallingAttributionSource(original);
                 Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
@@ -566,34 +560,34 @@
         }
 
         @Override
-        public Uri canonicalize(String callingPkg, @Nullable String attributionTag, Uri uri) {
+        public Uri canonicalize(@NonNull AttributionSource attributionSource, Uri uri) {
             uri = validateIncomingUri(uri);
             int userId = getUserIdFromUri(uri);
             uri = getUriWithoutUserId(uri);
-            if (enforceReadPermission(callingPkg, attributionTag, uri, null)
-                    != AppOpsManager.MODE_ALLOWED) {
+            if (enforceReadPermission(attributionSource, uri)
+                    != PermissionChecker.PERMISSION_GRANTED) {
                 return null;
             }
             Trace.traceBegin(TRACE_TAG_DATABASE, "canonicalize");
-            final Pair<String, String> original = setCallingPackage(
-                    new Pair<>(callingPkg, attributionTag));
+            final AttributionSource original = setCallingAttributionSource(
+                    attributionSource);
             try {
                 return maybeAddUserId(mInterface.canonicalize(uri), userId);
             } catch (RemoteException e) {
                 throw e.rethrowAsRuntimeException();
             } finally {
-                setCallingPackage(original);
+                setCallingAttributionSource(original);
                 Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
         @Override
-        public void canonicalizeAsync(String callingPkg, @Nullable String attributionTag, Uri uri,
+        public void canonicalizeAsync(@NonNull AttributionSource attributionSource, Uri uri,
                 RemoteCallback callback) {
             final Bundle result = new Bundle();
             try {
                 result.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT,
-                        canonicalize(callingPkg, attributionTag, uri));
+                        canonicalize(attributionSource, uri));
             } catch (Exception e) {
                 result.putParcelable(ContentResolver.REMOTE_CALLBACK_ERROR,
                         new ParcelableException(e));
@@ -602,34 +596,34 @@
         }
 
         @Override
-        public Uri uncanonicalize(String callingPkg, String attributionTag,  Uri uri) {
+        public Uri uncanonicalize(@NonNull AttributionSource attributionSource, Uri uri) {
             uri = validateIncomingUri(uri);
             int userId = getUserIdFromUri(uri);
             uri = getUriWithoutUserId(uri);
-            if (enforceReadPermission(callingPkg, attributionTag, uri, null)
-                    != AppOpsManager.MODE_ALLOWED) {
+            if (enforceReadPermission(attributionSource, uri)
+                    != PermissionChecker.PERMISSION_GRANTED) {
                 return null;
             }
             Trace.traceBegin(TRACE_TAG_DATABASE, "uncanonicalize");
-            final Pair<String, String> original = setCallingPackage(
-                    new Pair<>(callingPkg, attributionTag));
+            final AttributionSource original = setCallingAttributionSource(
+                    attributionSource);
             try {
                 return maybeAddUserId(mInterface.uncanonicalize(uri), userId);
             } catch (RemoteException e) {
                 throw e.rethrowAsRuntimeException();
             } finally {
-                setCallingPackage(original);
+                setCallingAttributionSource(original);
                 Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
         @Override
-        public void uncanonicalizeAsync(String callingPkg, @Nullable String attributionTag, Uri uri,
+        public void uncanonicalizeAsync(@NonNull AttributionSource attributionSource, Uri uri,
                 RemoteCallback callback) {
             final Bundle result = new Bundle();
             try {
                 result.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT,
-                        uncanonicalize(callingPkg, attributionTag, uri));
+                        uncanonicalize(attributionSource, uri));
             } catch (Exception e) {
                 result.putParcelable(ContentResolver.REMOTE_CALLBACK_ERROR,
                         new ParcelableException(e));
@@ -638,92 +632,95 @@
         }
 
         @Override
-        public boolean refresh(String callingPkg, String attributionTag, Uri uri, Bundle extras,
-                ICancellationSignal cancellationSignal) throws RemoteException {
+        public boolean refresh(@NonNull AttributionSource attributionSource, Uri uri,
+                Bundle extras, ICancellationSignal cancellationSignal) throws RemoteException {
             uri = validateIncomingUri(uri);
             uri = getUriWithoutUserId(uri);
-            if (enforceReadPermission(callingPkg, attributionTag, uri, null)
-                    != AppOpsManager.MODE_ALLOWED) {
+            if (enforceReadPermission(attributionSource, uri)
+                    != PermissionChecker.PERMISSION_GRANTED) {
                 return false;
             }
             Trace.traceBegin(TRACE_TAG_DATABASE, "refresh");
-            final Pair<String, String> original = setCallingPackage(
-                    new Pair<>(callingPkg, attributionTag));
+            final AttributionSource original = setCallingAttributionSource(
+                    attributionSource);
             try {
                 return mInterface.refresh(uri, extras,
                         CancellationSignal.fromTransport(cancellationSignal));
             } finally {
-                setCallingPackage(original);
+                setCallingAttributionSource(original);
                 Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
         @Override
-        public int checkUriPermission(String callingPkg, @Nullable String attributionTag, Uri uri,
+        public int checkUriPermission(@NonNull AttributionSource attributionSource, Uri uri,
                 int uid, int modeFlags) {
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             Trace.traceBegin(TRACE_TAG_DATABASE, "checkUriPermission");
-            final Pair<String, String> original = setCallingPackage(
-                    new Pair<>(callingPkg, attributionTag));
+            final AttributionSource original = setCallingAttributionSource(
+                    attributionSource);
             try {
                 return mInterface.checkUriPermission(uri, uid, modeFlags);
             } catch (RemoteException e) {
                 throw e.rethrowAsRuntimeException();
             } finally {
-                setCallingPackage(original);
+                setCallingAttributionSource(original);
                 Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
-        private void enforceFilePermission(String callingPkg, @Nullable String attributionTag,
-                Uri uri, String mode, IBinder callerToken)
+        @PermissionChecker.PermissionResult
+        private void enforceFilePermission(@NonNull AttributionSource attributionSource,
+                Uri uri, String mode)
                 throws FileNotFoundException, SecurityException {
             if (mode != null && mode.indexOf('w') != -1) {
-                if (enforceWritePermission(callingPkg, attributionTag, uri, callerToken)
-                        != AppOpsManager.MODE_ALLOWED) {
+                if (enforceWritePermission(attributionSource, uri)
+                        != PermissionChecker.PERMISSION_GRANTED) {
                     throw new FileNotFoundException("App op not allowed");
                 }
             } else {
-                if (enforceReadPermission(callingPkg, attributionTag, uri, callerToken)
-                        != AppOpsManager.MODE_ALLOWED) {
+                if (enforceReadPermission(attributionSource, uri)
+                        != PermissionChecker.PERMISSION_GRANTED) {
                     throw new FileNotFoundException("App op not allowed");
                 }
             }
         }
 
-        private int enforceReadPermission(String callingPkg, @Nullable String attributionTag,
-                Uri uri, IBinder callerToken)
+        @PermissionChecker.PermissionResult
+        private int enforceReadPermission(@NonNull AttributionSource attributionSource, Uri uri)
                 throws SecurityException {
-            final int mode = enforceReadPermissionInner(uri, callingPkg, attributionTag,
-                    callerToken);
-            if (mode != MODE_ALLOWED) {
-                return mode;
+            final int result = enforceReadPermissionInner(uri, attributionSource);
+            if (result != PermissionChecker.PERMISSION_GRANTED) {
+                return result;
             }
-
-            return noteProxyOp(callingPkg, attributionTag, mReadOp);
+            // Only check the read op if it differs from the one for the permission
+            // we already checked above to avoid double attribution for every access.
+            if (mTransport.mReadOp != AppOpsManager.OP_NONE
+                    && mTransport.mReadOp != AppOpsManager.permissionToOpCode(mReadPermission)) {
+                return PermissionChecker.checkOpForDataDelivery(getContext(),
+                        AppOpsManager.opToPublicName(mTransport.mReadOp),
+                        attributionSource, /*message*/ null);
+            }
+            return PermissionChecker.PERMISSION_GRANTED;
         }
 
-        private int enforceWritePermission(String callingPkg, String attributionTag, Uri uri,
-                IBinder callerToken)
+        @PermissionChecker.PermissionResult
+        private int enforceWritePermission(@NonNull AttributionSource attributionSource, Uri uri)
                 throws SecurityException {
-            final int mode = enforceWritePermissionInner(uri, callingPkg, attributionTag,
-                    callerToken);
-            if (mode != MODE_ALLOWED) {
-                return mode;
+            final int result = enforceWritePermissionInner(uri, attributionSource);
+            if (result != PermissionChecker.PERMISSION_GRANTED) {
+                return result;
             }
-
-            return noteProxyOp(callingPkg, attributionTag, mWriteOp);
-        }
-
-        private int noteProxyOp(String callingPkg, String attributionTag, int op) {
-            if (op != AppOpsManager.OP_NONE) {
-                int mode = mAppOpsManager.noteProxyOp(op, callingPkg, Binder.getCallingUid(),
-                        attributionTag, null);
-                return mode == MODE_DEFAULT ? MODE_IGNORED : mode;
+            // Only check the write op if it differs from the one for the permission
+            // we already checked above to avoid double attribution for every access.
+            if (mTransport.mWriteOp != AppOpsManager.OP_NONE
+                    && mTransport.mWriteOp != AppOpsManager.permissionToOpCode(mWritePermission)) {
+                return PermissionChecker.checkOpForDataDelivery(getContext(),
+                        AppOpsManager.opToPublicName(mTransport.mWriteOp),
+                        attributionSource, /*message*/ null);
             }
-
-            return AppOpsManager.MODE_ALLOWED;
+            return PermissionChecker.PERMISSION_GRANTED;
         }
     }
 
@@ -731,49 +728,53 @@
         if (UserHandle.getUserId(uid) == context.getUserId() || mSingleUser) {
             return true;
         }
-        return context.checkPermission(INTERACT_ACROSS_USERS, pid, uid) == PERMISSION_GRANTED
+        return context.checkPermission(INTERACT_ACROSS_USERS, pid, uid)
+                    == PackageManager.PERMISSION_GRANTED
                 || context.checkPermission(INTERACT_ACROSS_USERS_FULL, pid, uid)
-                == PERMISSION_GRANTED;
+                    == PackageManager.PERMISSION_GRANTED;
     }
 
     /**
      * Verify that calling app holds both the given permission and any app-op
      * associated with that permission.
      */
-    private int checkPermissionAndAppOp(String permission, String callingPkg,
-            @Nullable String attributionTag, IBinder callerToken) {
-        if (getContext().checkPermission(permission, Binder.getCallingPid(), Binder.getCallingUid(),
-                callerToken) != PERMISSION_GRANTED) {
-            return MODE_ERRORED;
+    @PermissionChecker.PermissionResult
+    private int checkPermission(String permission,
+            @NonNull AttributionSource attributionSource) {
+        if (Binder.getCallingPid() == Process.myPid()) {
+            return PermissionChecker.PERMISSION_GRANTED;
         }
-
-        return mTransport.noteProxyOp(callingPkg, attributionTag,
-                AppOpsManager.permissionToOpCode(permission));
+        if (!attributionSource.checkCallingUid()) {
+            return PermissionChecker.PERMISSION_HARD_DENIED;
+        }
+        return PermissionChecker.checkPermissionForDataDeliveryFromDataSource(getContext(),
+                permission, -1, new AttributionSource(getContext().getAttributionSource(),
+                        attributionSource), /*message*/ null);
     }
 
     /** {@hide} */
-    protected int enforceReadPermissionInner(Uri uri, String callingPkg,
-            @Nullable String attributionTag, IBinder callerToken) throws SecurityException {
+    @PermissionChecker.PermissionResult
+    protected int enforceReadPermissionInner(Uri uri,
+            @NonNull AttributionSource attributionSource) throws SecurityException {
         final Context context = getContext();
         final int pid = Binder.getCallingPid();
         final int uid = Binder.getCallingUid();
         String missingPerm = null;
-        int strongestMode = MODE_ALLOWED;
+        int strongestResult = PermissionChecker.PERMISSION_GRANTED;
 
         if (UserHandle.isSameApp(uid, mMyUid)) {
-            return MODE_ALLOWED;
+            return PermissionChecker.PERMISSION_GRANTED;
         }
 
         if (mExported && checkUser(pid, uid, context)) {
             final String componentPerm = getReadPermission();
             if (componentPerm != null) {
-                final int mode = checkPermissionAndAppOp(componentPerm, callingPkg, attributionTag,
-                        callerToken);
-                if (mode == MODE_ALLOWED) {
-                    return MODE_ALLOWED;
+                final int result = checkPermission(componentPerm, attributionSource);
+                if (result == PermissionChecker.PERMISSION_GRANTED) {
+                    return PermissionChecker.PERMISSION_GRANTED;
                 } else {
                     missingPerm = componentPerm;
-                    strongestMode = Math.max(strongestMode, mode);
+                    strongestResult = Math.max(strongestResult, result);
                 }
             }
 
@@ -787,16 +788,15 @@
                 for (PathPermission pp : pps) {
                     final String pathPerm = pp.getReadPermission();
                     if (pathPerm != null && pp.match(path)) {
-                        final int mode = checkPermissionAndAppOp(pathPerm, callingPkg,
-                                attributionTag, callerToken);
-                        if (mode == MODE_ALLOWED) {
-                            return MODE_ALLOWED;
+                        final int result = checkPermission(pathPerm, attributionSource);
+                        if (result == PermissionChecker.PERMISSION_GRANTED) {
+                            return PermissionChecker.PERMISSION_GRANTED;
                         } else {
                             // any denied <path-permission> means we lose
                             // default <provider> access.
                             allowDefaultRead = false;
                             missingPerm = pathPerm;
-                            strongestMode = Math.max(strongestMode, mode);
+                            strongestResult = Math.max(strongestResult, result);
                         }
                     }
                 }
@@ -804,22 +804,22 @@
 
             // if we passed <path-permission> checks above, and no default
             // <provider> permission, then allow access.
-            if (allowDefaultRead) return MODE_ALLOWED;
+            if (allowDefaultRead) return PermissionChecker.PERMISSION_GRANTED;
         }
 
         // last chance, check against any uri grants
         final int callingUserId = UserHandle.getUserId(uid);
         final Uri userUri = (mSingleUser && !UserHandle.isSameUser(mMyUid, uid))
                 ? maybeAddUserId(uri, callingUserId) : uri;
-        if (context.checkUriPermission(userUri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION,
-                callerToken) == PERMISSION_GRANTED) {
-            return MODE_ALLOWED;
+        if (context.checkUriPermission(userUri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION)
+                == PackageManager.PERMISSION_GRANTED) {
+            return PermissionChecker.PERMISSION_GRANTED;
         }
 
         // If the worst denial we found above was ignored, then pass that
         // ignored through; otherwise we assume it should be a real error below.
-        if (strongestMode == MODE_IGNORED) {
-            return MODE_IGNORED;
+        if (strongestResult == PermissionChecker.PERMISSION_SOFT_DENIED) {
+            return PermissionChecker.PERMISSION_SOFT_DENIED;
         }
 
         final String suffix;
@@ -836,28 +836,28 @@
     }
 
     /** {@hide} */
-    protected int enforceWritePermissionInner(Uri uri, String callingPkg,
-            @Nullable String attributionTag, IBinder callerToken) throws SecurityException {
+    @PermissionChecker.PermissionResult
+    protected int enforceWritePermissionInner(Uri uri,
+            @NonNull AttributionSource attributionSource) throws SecurityException {
         final Context context = getContext();
         final int pid = Binder.getCallingPid();
         final int uid = Binder.getCallingUid();
         String missingPerm = null;
-        int strongestMode = MODE_ALLOWED;
+        int strongestResult = PermissionChecker.PERMISSION_GRANTED;
 
         if (UserHandle.isSameApp(uid, mMyUid)) {
-            return MODE_ALLOWED;
+            return PermissionChecker.PERMISSION_GRANTED;
         }
 
         if (mExported && checkUser(pid, uid, context)) {
             final String componentPerm = getWritePermission();
             if (componentPerm != null) {
-                final int mode = checkPermissionAndAppOp(componentPerm, callingPkg,
-                        attributionTag, callerToken);
-                if (mode == MODE_ALLOWED) {
-                    return MODE_ALLOWED;
+                final int mode = checkPermission(componentPerm, attributionSource);
+                if (mode == PermissionChecker.PERMISSION_GRANTED) {
+                    return PermissionChecker.PERMISSION_GRANTED;
                 } else {
                     missingPerm = componentPerm;
-                    strongestMode = Math.max(strongestMode, mode);
+                    strongestResult = Math.max(strongestResult, mode);
                 }
             }
 
@@ -871,16 +871,15 @@
                 for (PathPermission pp : pps) {
                     final String pathPerm = pp.getWritePermission();
                     if (pathPerm != null && pp.match(path)) {
-                        final int mode = checkPermissionAndAppOp(pathPerm, callingPkg,
-                                attributionTag, callerToken);
-                        if (mode == MODE_ALLOWED) {
-                            return MODE_ALLOWED;
+                        final int mode = checkPermission(pathPerm, attributionSource);
+                        if (mode == PermissionChecker.PERMISSION_GRANTED) {
+                            return PermissionChecker.PERMISSION_GRANTED;
                         } else {
                             // any denied <path-permission> means we lose
                             // default <provider> access.
                             allowDefaultWrite = false;
                             missingPerm = pathPerm;
-                            strongestMode = Math.max(strongestMode, mode);
+                            strongestResult = Math.max(strongestResult, mode);
                         }
                     }
                 }
@@ -888,19 +887,19 @@
 
             // if we passed <path-permission> checks above, and no default
             // <provider> permission, then allow access.
-            if (allowDefaultWrite) return MODE_ALLOWED;
+            if (allowDefaultWrite) return PermissionChecker.PERMISSION_GRANTED;
         }
 
         // last chance, check against any uri grants
-        if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
-                callerToken) == PERMISSION_GRANTED) {
-            return MODE_ALLOWED;
+        if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
+                == PackageManager.PERMISSION_GRANTED) {
+            return PermissionChecker.PERMISSION_GRANTED;
         }
 
         // If the worst denial we found above was ignored, then pass that
         // ignored through; otherwise we assume it should be a real error below.
-        if (strongestMode == MODE_IGNORED) {
-            return MODE_IGNORED;
+        if (strongestResult == PermissionChecker.PERMISSION_SOFT_DENIED) {
+            return PermissionChecker.PERMISSION_SOFT_DENIED;
         }
 
         final String failReason = mExported
@@ -941,9 +940,10 @@
      * Set the calling package/feature, returning the current value (or {@code null})
      * which can be used later to restore the previous state.
      */
-    private Pair<String, String> setCallingPackage(Pair<String, String> callingPackage) {
-        final Pair<String, String> original = mCallingPackage.get();
-        mCallingPackage.set(callingPackage);
+    private @Nullable AttributionSource setCallingAttributionSource(
+            @Nullable AttributionSource attributionSource) {
+        final AttributionSource original = mCallingAttributionSource.get();
+        mCallingAttributionSource.set(attributionSource);
         onCallingPackageChanged();
         return original;
     }
@@ -963,13 +963,30 @@
      *             calling UID.
      */
     public final @Nullable String getCallingPackage() {
-        final Pair<String, String> pkg = mCallingPackage.get();
-        if (pkg != null) {
-            mTransport.mAppOpsManager.checkPackage(Binder.getCallingUid(), pkg.first);
-            return pkg.first;
-        }
+        final AttributionSource callingAttributionSource = getCallingAttributionSource();
+        return (callingAttributionSource != null)
+                ? callingAttributionSource.getPackageName() : null;
+    }
 
-        return null;
+    /**
+     * Gets the attribution source of the calling app. If you want to attribute
+     * the data access to the calling app you can create an attribution context
+     * via {@link android.content.Context#createContext(ContextParams)} and passing
+     * this identity to {@link ContextParams.Builder#setNextAttributionSource(
+     * AttributionSource)}.
+     *
+     * @return The identity of the caller for permission purposes.
+     *
+     * @see ContextParams.Builder#setNextAttributionSource(AttributionSource)
+     * @see AttributionSource
+     */
+    public final @Nullable AttributionSource getCallingAttributionSource() {
+        final AttributionSource attributionSource = mCallingAttributionSource.get();
+        if (attributionSource != null) {
+            mTransport.mAppOpsManager.checkPackage(Binder.getCallingUid(),
+                    attributionSource.getPackageName());
+        }
+        return attributionSource;
     }
 
     /**
@@ -983,11 +1000,10 @@
      * @see #getCallingPackage
      */
     public final @Nullable String getCallingAttributionTag() {
-        final Pair<String, String> pkg = mCallingPackage.get();
-        if (pkg != null) {
-            return pkg.second;
+        final AttributionSource attributionSource = mCallingAttributionSource.get();
+        if (attributionSource != null) {
+            return attributionSource.getAttributionTag();
         }
-
         return null;
     }
 
@@ -1012,11 +1028,10 @@
      * @see Context#grantUriPermission(String, Uri, int)
      */
     public final @Nullable String getCallingPackageUnchecked() {
-        final Pair<String, String> pkg = mCallingPackage.get();
-        if (pkg != null) {
-            return pkg.first;
+        final AttributionSource attributionSource = mCallingAttributionSource.get();
+        if (attributionSource != null) {
+            return attributionSource.getPackageName();
         }
-
         return null;
     }
 
@@ -1038,12 +1053,12 @@
         /** {@hide} */
         public final long binderToken;
         /** {@hide} */
-        public final Pair<String, String> callingPackage;
+        public final @Nullable AttributionSource callingAttributionSource;
 
         /** {@hide} */
-        public CallingIdentity(long binderToken, Pair<String, String> callingPackage) {
+        public CallingIdentity(long binderToken, @Nullable AttributionSource attributionSource) {
             this.binderToken = binderToken;
-            this.callingPackage = callingPackage;
+            this.callingAttributionSource = attributionSource;
         }
     }
 
@@ -1059,7 +1074,8 @@
      */
     @SuppressWarnings("AndroidFrameworkBinderIdentity")
     public final @NonNull CallingIdentity clearCallingIdentity() {
-        return new CallingIdentity(Binder.clearCallingIdentity(), setCallingPackage(null));
+        return new CallingIdentity(Binder.clearCallingIdentity(),
+                setCallingAttributionSource(null));
     }
 
     /**
@@ -1071,7 +1087,7 @@
      */
     public final void restoreCallingIdentity(@NonNull CallingIdentity identity) {
         Binder.restoreCallingIdentity(identity.binderToken);
-        mCallingPackage.set(identity.callingPackage);
+        mCallingAttributionSource.set(identity.callingAttributionSource);
     }
 
     /**
@@ -2374,7 +2390,7 @@
 
     private void attachInfo(Context context, ProviderInfo info, boolean testing) {
         mNoPerms = testing;
-        mCallingPackage = new ThreadLocal<>();
+        mCallingAttributionSource = new ThreadLocal<>();
 
         /*
          * Only allow it to be set once, so after the content service gives
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index 5af7861..518e753 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -79,7 +79,8 @@
     private final IContentProvider mContentProvider;
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final String mPackageName;
-    private final @Nullable String mAttributionTag;
+    private final @NonNull AttributionSource mAttributionSource;
+
     private final String mAuthority;
     private final boolean mStable;
 
@@ -103,7 +104,7 @@
         mContentResolver = contentResolver;
         mContentProvider = contentProvider;
         mPackageName = contentResolver.mPackageName;
-        mAttributionTag = contentResolver.mAttributionTag;
+        mAttributionSource = contentResolver.getAttributionSource();
 
         mAuthority = authority;
         mStable = stable;
@@ -193,7 +194,7 @@
                 cancellationSignal.setRemote(remoteCancellationSignal);
             }
             final Cursor cursor = mContentProvider.query(
-                    mPackageName, mAttributionTag, uri, projection, queryArgs,
+                    mAttributionSource, uri, projection, queryArgs,
                     remoteCancellationSignal);
             if (cursor == null) {
                 return null;
@@ -254,7 +255,7 @@
 
         beforeRemote();
         try {
-            return mContentProvider.canonicalize(mPackageName, mAttributionTag, url);
+            return mContentProvider.canonicalize(mAttributionSource, url);
         } catch (DeadObjectException e) {
             if (!mStable) {
                 mContentResolver.unstableProviderDied(mContentProvider);
@@ -272,7 +273,7 @@
 
         beforeRemote();
         try {
-            return mContentProvider.uncanonicalize(mPackageName, mAttributionTag, url);
+            return mContentProvider.uncanonicalize(mAttributionSource, url);
         } catch (DeadObjectException e) {
             if (!mStable) {
                 mContentResolver.unstableProviderDied(mContentProvider);
@@ -297,7 +298,7 @@
                 remoteCancellationSignal = mContentProvider.createCancellationSignal();
                 cancellationSignal.setRemote(remoteCancellationSignal);
             }
-            return mContentProvider.refresh(mPackageName, mAttributionTag, url, extras,
+            return mContentProvider.refresh(mAttributionSource, url, extras,
                     remoteCancellationSignal);
         } catch (DeadObjectException e) {
             if (!mStable) {
@@ -317,7 +318,7 @@
 
         beforeRemote();
         try {
-            return mContentProvider.checkUriPermission(mPackageName, mAttributionTag, uri, uid,
+            return mContentProvider.checkUriPermission(mAttributionSource, uri, uid,
                     modeFlags);
         } catch (DeadObjectException e) {
             if (!mStable) {
@@ -343,7 +344,7 @@
 
         beforeRemote();
         try {
-            return mContentProvider.insert(mPackageName, mAttributionTag, url, initialValues,
+            return mContentProvider.insert(mAttributionSource, url, initialValues,
                     extras);
         } catch (DeadObjectException e) {
             if (!mStable) {
@@ -364,7 +365,7 @@
 
         beforeRemote();
         try {
-            return mContentProvider.bulkInsert(mPackageName, mAttributionTag, url, initialValues);
+            return mContentProvider.bulkInsert(mAttributionSource, url, initialValues);
         } catch (DeadObjectException e) {
             if (!mStable) {
                 mContentResolver.unstableProviderDied(mContentProvider);
@@ -388,7 +389,7 @@
 
         beforeRemote();
         try {
-            return mContentProvider.delete(mPackageName, mAttributionTag, url, extras);
+            return mContentProvider.delete(mAttributionSource, url, extras);
         } catch (DeadObjectException e) {
             if (!mStable) {
                 mContentResolver.unstableProviderDied(mContentProvider);
@@ -413,7 +414,7 @@
 
         beforeRemote();
         try {
-            return mContentProvider.update(mPackageName, mAttributionTag, url, values, extras);
+            return mContentProvider.update(mAttributionSource, url, values, extras);
         } catch (DeadObjectException e) {
             if (!mStable) {
                 mContentResolver.unstableProviderDied(mContentProvider);
@@ -457,8 +458,7 @@
                 remoteSignal = mContentProvider.createCancellationSignal();
                 signal.setRemote(remoteSignal);
             }
-            return mContentProvider.openFile(mPackageName, mAttributionTag, url, mode,
-                    remoteSignal, null);
+            return mContentProvider.openFile(mAttributionSource, url, mode, remoteSignal);
         } catch (DeadObjectException e) {
             if (!mStable) {
                 mContentResolver.unstableProviderDied(mContentProvider);
@@ -502,7 +502,7 @@
                 remoteSignal = mContentProvider.createCancellationSignal();
                 signal.setRemote(remoteSignal);
             }
-            return mContentProvider.openAssetFile(mPackageName, mAttributionTag, url, mode,
+            return mContentProvider.openAssetFile(mAttributionSource, url, mode,
                     remoteSignal);
         } catch (DeadObjectException e) {
             if (!mStable) {
@@ -544,7 +544,7 @@
                 signal.setRemote(remoteSignal);
             }
             return mContentProvider.openTypedAssetFile(
-                    mPackageName, mAttributionTag, uri, mimeTypeFilter, opts, remoteSignal);
+                    mAttributionSource, uri, mimeTypeFilter, opts, remoteSignal);
         } catch (DeadObjectException e) {
             if (!mStable) {
                 mContentResolver.unstableProviderDied(mContentProvider);
@@ -571,7 +571,7 @@
 
         beforeRemote();
         try {
-            return mContentProvider.applyBatch(mPackageName, mAttributionTag, authority,
+            return mContentProvider.applyBatch(mAttributionSource, authority,
                     operations);
         } catch (DeadObjectException e) {
             if (!mStable) {
@@ -598,7 +598,7 @@
 
         beforeRemote();
         try {
-            return mContentProvider.call(mPackageName, mAttributionTag, authority, method, arg,
+            return mContentProvider.call(mAttributionSource, authority, method, arg,
                     extras);
         } catch (DeadObjectException e) {
             if (!mStable) {
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
index 7d121d5..47c96699 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.res.AssetFileDescriptor;
@@ -83,8 +84,8 @@
                 {
                     data.enforceInterface(IContentProvider.descriptor);
 
-                    String callingPkg = data.readString();
-                    String callingFeatureId = data.readString();
+                    AttributionSource attributionSource = AttributionSource.CREATOR
+                            .createFromParcel(data);
                     Uri url = Uri.CREATOR.createFromParcel(data);
 
                     // String[] projection
@@ -103,7 +104,7 @@
                     ICancellationSignal cancellationSignal = ICancellationSignal.Stub.asInterface(
                             data.readStrongBinder());
 
-                    Cursor cursor = query(callingPkg, callingFeatureId, url, projection, queryArgs,
+                    Cursor cursor = query(attributionSource, url, projection, queryArgs,
                             cancellationSignal);
                     if (cursor != null) {
                         CursorToBulkCursorAdaptor adaptor = null;
@@ -158,13 +159,13 @@
                 case INSERT_TRANSACTION:
                 {
                     data.enforceInterface(IContentProvider.descriptor);
-                    String callingPkg = data.readString();
-                    String featureId = data.readString();
+                    AttributionSource attributionSource = AttributionSource.CREATOR
+                            .createFromParcel(data);
                     Uri url = Uri.CREATOR.createFromParcel(data);
                     ContentValues values = ContentValues.CREATOR.createFromParcel(data);
                     Bundle extras = data.readBundle();
 
-                    Uri out = insert(callingPkg, featureId, url, values, extras);
+                    Uri out = insert(attributionSource, url, values, extras);
                     reply.writeNoException();
                     Uri.writeToParcel(reply, out);
                     return true;
@@ -173,12 +174,12 @@
                 case BULK_INSERT_TRANSACTION:
                 {
                     data.enforceInterface(IContentProvider.descriptor);
-                    String callingPkg = data.readString();
-                    String featureId = data.readString();
+                    AttributionSource attributionSource = AttributionSource.CREATOR
+                            .createFromParcel(data);
                     Uri url = Uri.CREATOR.createFromParcel(data);
                     ContentValues[] values = data.createTypedArray(ContentValues.CREATOR);
 
-                    int count = bulkInsert(callingPkg, featureId, url, values);
+                    int count = bulkInsert(attributionSource, url, values);
                     reply.writeNoException();
                     reply.writeInt(count);
                     return true;
@@ -187,8 +188,8 @@
                 case APPLY_BATCH_TRANSACTION:
                 {
                     data.enforceInterface(IContentProvider.descriptor);
-                    String callingPkg = data.readString();
-                    String featureId = data.readString();
+                    AttributionSource attributionSource = AttributionSource.CREATOR
+                            .createFromParcel(data);
                     String authority = data.readString();
                     final int numOperations = data.readInt();
                     final ArrayList<ContentProviderOperation> operations =
@@ -196,7 +197,7 @@
                     for (int i = 0; i < numOperations; i++) {
                         operations.add(i, ContentProviderOperation.CREATOR.createFromParcel(data));
                     }
-                    final ContentProviderResult[] results = applyBatch(callingPkg, featureId,
+                    final ContentProviderResult[] results = applyBatch(attributionSource,
                             authority, operations);
                     reply.writeNoException();
                     reply.writeTypedArray(results, 0);
@@ -206,12 +207,12 @@
                 case DELETE_TRANSACTION:
                 {
                     data.enforceInterface(IContentProvider.descriptor);
-                    String callingPkg = data.readString();
-                    String featureId = data.readString();
+                    AttributionSource attributionSource = AttributionSource.CREATOR
+                            .createFromParcel(data);
                     Uri url = Uri.CREATOR.createFromParcel(data);
                     Bundle extras = data.readBundle();
 
-                    int count = delete(callingPkg, featureId, url, extras);
+                    int count = delete(attributionSource, url, extras);
 
                     reply.writeNoException();
                     reply.writeInt(count);
@@ -221,13 +222,13 @@
                 case UPDATE_TRANSACTION:
                 {
                     data.enforceInterface(IContentProvider.descriptor);
-                    String callingPkg = data.readString();
-                    String featureId = data.readString();
+                    AttributionSource attributionSource = AttributionSource.CREATOR
+                            .createFromParcel(data);
                     Uri url = Uri.CREATOR.createFromParcel(data);
                     ContentValues values = ContentValues.CREATOR.createFromParcel(data);
                     Bundle extras = data.readBundle();
 
-                    int count = update(callingPkg, featureId, url, values, extras);
+                    int count = update(attributionSource, url, values, extras);
 
                     reply.writeNoException();
                     reply.writeInt(count);
@@ -237,16 +238,15 @@
                 case OPEN_FILE_TRANSACTION:
                 {
                     data.enforceInterface(IContentProvider.descriptor);
-                    String callingPkg = data.readString();
-                    String featureId = data.readString();
+                    AttributionSource attributionSource = AttributionSource.CREATOR
+                            .createFromParcel(data);
                     Uri url = Uri.CREATOR.createFromParcel(data);
                     String mode = data.readString();
                     ICancellationSignal signal = ICancellationSignal.Stub.asInterface(
                             data.readStrongBinder());
-                    IBinder callerToken = data.readStrongBinder();
 
                     ParcelFileDescriptor fd;
-                    fd = openFile(callingPkg, featureId, url, mode, signal, callerToken);
+                    fd = openFile(attributionSource, url, mode, signal);
                     reply.writeNoException();
                     if (fd != null) {
                         reply.writeInt(1);
@@ -261,15 +261,15 @@
                 case OPEN_ASSET_FILE_TRANSACTION:
                 {
                     data.enforceInterface(IContentProvider.descriptor);
-                    String callingPkg = data.readString();
-                    String featureId = data.readString();
+                    AttributionSource attributionSource = AttributionSource.CREATOR
+                            .createFromParcel(data);
                     Uri url = Uri.CREATOR.createFromParcel(data);
                     String mode = data.readString();
                     ICancellationSignal signal = ICancellationSignal.Stub.asInterface(
                             data.readStrongBinder());
 
                     AssetFileDescriptor fd;
-                    fd = openAssetFile(callingPkg, featureId, url, mode, signal);
+                    fd = openAssetFile(attributionSource, url, mode, signal);
                     reply.writeNoException();
                     if (fd != null) {
                         reply.writeInt(1);
@@ -285,14 +285,14 @@
                 {
                     data.enforceInterface(IContentProvider.descriptor);
 
-                    String callingPkg = data.readString();
-                    String featureId = data.readString();
+                    AttributionSource attributionSource = AttributionSource.CREATOR
+                            .createFromParcel(data);
                     String authority = data.readString();
                     String method = data.readString();
                     String stringArg = data.readString();
                     Bundle extras = data.readBundle();
 
-                    Bundle responseBundle = call(callingPkg, featureId, authority, method,
+                    Bundle responseBundle = call(attributionSource, authority, method,
                             stringArg, extras);
 
                     reply.writeNoException();
@@ -315,8 +315,8 @@
                 case OPEN_TYPED_ASSET_FILE_TRANSACTION:
                 {
                     data.enforceInterface(IContentProvider.descriptor);
-                    String callingPkg = data.readString();
-                    String featureId = data.readString();
+                    AttributionSource attributionSource = AttributionSource.CREATOR
+                            .createFromParcel(data);
                     Uri url = Uri.CREATOR.createFromParcel(data);
                     String mimeType = data.readString();
                     Bundle opts = data.readBundle();
@@ -324,7 +324,7 @@
                             data.readStrongBinder());
 
                     AssetFileDescriptor fd;
-                    fd = openTypedAssetFile(callingPkg, featureId, url, mimeType, opts, signal);
+                    fd = openTypedAssetFile(attributionSource, url, mimeType, opts, signal);
                     reply.writeNoException();
                     if (fd != null) {
                         reply.writeInt(1);
@@ -349,11 +349,11 @@
                 case CANONICALIZE_TRANSACTION:
                 {
                     data.enforceInterface(IContentProvider.descriptor);
-                    String callingPkg = data.readString();
-                    String featureId = data.readString();
+                    AttributionSource attributionSource = AttributionSource.CREATOR
+                            .createFromParcel(data);
                     Uri url = Uri.CREATOR.createFromParcel(data);
 
-                    Uri out = canonicalize(callingPkg, featureId, url);
+                    Uri out = canonicalize(attributionSource, url);
                     reply.writeNoException();
                     Uri.writeToParcel(reply, out);
                     return true;
@@ -361,22 +361,22 @@
 
                 case CANONICALIZE_ASYNC_TRANSACTION: {
                     data.enforceInterface(IContentProvider.descriptor);
-                    String callingPkg = data.readString();
-                    String featureId = data.readString();
+                    AttributionSource attributionSource = AttributionSource.CREATOR
+                            .createFromParcel(data);
                     Uri uri = Uri.CREATOR.createFromParcel(data);
                     RemoteCallback callback = RemoteCallback.CREATOR.createFromParcel(data);
-                    canonicalizeAsync(callingPkg, featureId, uri, callback);
+                    canonicalizeAsync(attributionSource, uri, callback);
                     return true;
                 }
 
                 case UNCANONICALIZE_TRANSACTION:
                 {
                     data.enforceInterface(IContentProvider.descriptor);
-                    String callingPkg = data.readString();
-                    String featureId = data.readString();
+                    AttributionSource attributionSource = AttributionSource.CREATOR
+                            .createFromParcel(data);
                     Uri url = Uri.CREATOR.createFromParcel(data);
 
-                    Uri out = uncanonicalize(callingPkg, featureId, url);
+                    Uri out = uncanonicalize(attributionSource, url);
                     reply.writeNoException();
                     Uri.writeToParcel(reply, out);
                     return true;
@@ -384,24 +384,24 @@
 
                 case UNCANONICALIZE_ASYNC_TRANSACTION: {
                     data.enforceInterface(IContentProvider.descriptor);
-                    String callingPkg = data.readString();
-                    String featureId = data.readString();
+                    AttributionSource attributionSource = AttributionSource.CREATOR
+                            .createFromParcel(data);
                     Uri uri = Uri.CREATOR.createFromParcel(data);
                     RemoteCallback callback = RemoteCallback.CREATOR.createFromParcel(data);
-                    uncanonicalizeAsync(callingPkg, featureId, uri, callback);
+                    uncanonicalizeAsync(attributionSource, uri, callback);
                     return true;
                 }
 
                 case REFRESH_TRANSACTION: {
                     data.enforceInterface(IContentProvider.descriptor);
-                    String callingPkg = data.readString();
-                    String featureId = data.readString();
+                    AttributionSource attributionSource = AttributionSource.CREATOR
+                            .createFromParcel(data);
                     Uri url = Uri.CREATOR.createFromParcel(data);
                     Bundle extras = data.readBundle();
                     ICancellationSignal signal = ICancellationSignal.Stub.asInterface(
                             data.readStrongBinder());
 
-                    boolean out = refresh(callingPkg, featureId, url, extras, signal);
+                    boolean out = refresh(attributionSource, url, extras, signal);
                     reply.writeNoException();
                     reply.writeInt(out ? 0 : -1);
                     return true;
@@ -409,13 +409,13 @@
 
                 case CHECK_URI_PERMISSION_TRANSACTION: {
                     data.enforceInterface(IContentProvider.descriptor);
-                    String callingPkg = data.readString();
-                    String featureId = data.readString();
+                    AttributionSource attributionSource = AttributionSource.CREATOR
+                            .createFromParcel(data);
                     Uri uri = Uri.CREATOR.createFromParcel(data);
                     int uid = data.readInt();
                     int modeFlags = data.readInt();
 
-                    int out = checkUriPermission(callingPkg, featureId, uri, uid, modeFlags);
+                    int out = checkUriPermission(attributionSource, uri, uid, modeFlags);
                     reply.writeNoException();
                     reply.writeInt(out);
                     return true;
@@ -451,7 +451,7 @@
     }
 
     @Override
-    public Cursor query(String callingPkg, @Nullable String featureId, Uri url,
+    public Cursor query(@NonNull AttributionSource attributionSource, Uri url,
             @Nullable String[] projection, @Nullable Bundle queryArgs,
             @Nullable ICancellationSignal cancellationSignal)
             throws RemoteException {
@@ -461,8 +461,7 @@
         try {
             data.writeInterfaceToken(IContentProvider.descriptor);
 
-            data.writeString(callingPkg);
-            data.writeString(featureId);
+            attributionSource.writeToParcel(data, 0);
             url.writeToParcel(data, 0);
             int length = 0;
             if (projection != null) {
@@ -540,7 +539,7 @@
     }
 
     @Override
-    public Uri insert(String callingPkg, @Nullable String featureId, Uri url,
+    public Uri insert(@NonNull AttributionSource attributionSource, Uri url,
             ContentValues values, Bundle extras) throws RemoteException
     {
         Parcel data = Parcel.obtain();
@@ -548,8 +547,7 @@
         try {
             data.writeInterfaceToken(IContentProvider.descriptor);
 
-            data.writeString(callingPkg);
-            data.writeString(featureId);
+            attributionSource.writeToParcel(data, 0);
             url.writeToParcel(data, 0);
             values.writeToParcel(data, 0);
             data.writeBundle(extras);
@@ -566,15 +564,14 @@
     }
 
     @Override
-    public int bulkInsert(String callingPkg, @Nullable String featureId, Uri url,
+    public int bulkInsert(@NonNull AttributionSource attributionSource, Uri url,
             ContentValues[] values) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         try {
             data.writeInterfaceToken(IContentProvider.descriptor);
 
-            data.writeString(callingPkg);
-            data.writeString(featureId);
+            attributionSource.writeToParcel(data, 0);
             url.writeToParcel(data, 0);
             data.writeTypedArray(values, 0);
 
@@ -590,15 +587,14 @@
     }
 
     @Override
-    public ContentProviderResult[] applyBatch(String callingPkg, @Nullable String featureId,
+    public ContentProviderResult[] applyBatch(@NonNull AttributionSource attributionSource,
             String authority, ArrayList<ContentProviderOperation> operations)
             throws RemoteException, OperationApplicationException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         try {
             data.writeInterfaceToken(IContentProvider.descriptor);
-            data.writeString(callingPkg);
-            data.writeString(featureId);
+            attributionSource.writeToParcel(data, 0);
             data.writeString(authority);
             data.writeInt(operations.size());
             for (ContentProviderOperation operation : operations) {
@@ -617,15 +613,14 @@
     }
 
     @Override
-    public int delete(String callingPkg, @Nullable String featureId, Uri url, Bundle extras)
+    public int delete(@NonNull AttributionSource attributionSource, Uri url, Bundle extras)
             throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         try {
             data.writeInterfaceToken(IContentProvider.descriptor);
 
-            data.writeString(callingPkg);
-            data.writeString(featureId);
+            attributionSource.writeToParcel(data, 0);
             url.writeToParcel(data, 0);
             data.writeBundle(extras);
 
@@ -641,15 +636,14 @@
     }
 
     @Override
-    public int update(String callingPkg, @Nullable String featureId, Uri url,
+    public int update(@NonNull AttributionSource attributionSource, Uri url,
             ContentValues values, Bundle extras) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         try {
             data.writeInterfaceToken(IContentProvider.descriptor);
 
-            data.writeString(callingPkg);
-            data.writeString(featureId);
+            attributionSource.writeToParcel(data, 0);
             url.writeToParcel(data, 0);
             values.writeToParcel(data, 0);
             data.writeBundle(extras);
@@ -666,20 +660,18 @@
     }
 
     @Override
-    public ParcelFileDescriptor openFile(String callingPkg, @Nullable String featureId, Uri url,
-            String mode, ICancellationSignal signal, IBinder token)
+    public ParcelFileDescriptor openFile(@NonNull AttributionSource attributionSource, Uri url,
+            String mode, ICancellationSignal signal)
             throws RemoteException, FileNotFoundException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         try {
             data.writeInterfaceToken(IContentProvider.descriptor);
 
-            data.writeString(callingPkg);
-            data.writeString(featureId);
+            attributionSource.writeToParcel(data, 0);
             url.writeToParcel(data, 0);
             data.writeString(mode);
             data.writeStrongBinder(signal != null ? signal.asBinder() : null);
-            data.writeStrongBinder(token);
 
             mRemote.transact(IContentProvider.OPEN_FILE_TRANSACTION, data, reply, 0);
 
@@ -695,7 +687,7 @@
     }
 
     @Override
-    public AssetFileDescriptor openAssetFile(String callingPkg, @Nullable String featureId,
+    public AssetFileDescriptor openAssetFile(@NonNull AttributionSource attributionSource,
             Uri url, String mode, ICancellationSignal signal)
             throws RemoteException, FileNotFoundException {
         Parcel data = Parcel.obtain();
@@ -703,8 +695,7 @@
         try {
             data.writeInterfaceToken(IContentProvider.descriptor);
 
-            data.writeString(callingPkg);
-            data.writeString(featureId);
+            attributionSource.writeToParcel(data, 0);
             url.writeToParcel(data, 0);
             data.writeString(mode);
             data.writeStrongBinder(signal != null ? signal.asBinder() : null);
@@ -723,15 +714,14 @@
     }
 
     @Override
-    public Bundle call(String callingPkg, @Nullable String featureId, String authority,
+    public Bundle call(@NonNull AttributionSource attributionSource, String authority,
             String method, String request, Bundle extras) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         try {
             data.writeInterfaceToken(IContentProvider.descriptor);
 
-            data.writeString(callingPkg);
-            data.writeString(featureId);
+            attributionSource.writeToParcel(data, 0);
             data.writeString(authority);
             data.writeString(method);
             data.writeString(request);
@@ -771,7 +761,7 @@
     }
 
     @Override
-    public AssetFileDescriptor openTypedAssetFile(String callingPkg, @Nullable String featureId,
+    public AssetFileDescriptor openTypedAssetFile(@NonNull AttributionSource attributionSource,
             Uri url, String mimeType, Bundle opts, ICancellationSignal signal)
             throws RemoteException, FileNotFoundException {
         Parcel data = Parcel.obtain();
@@ -779,8 +769,7 @@
         try {
             data.writeInterfaceToken(IContentProvider.descriptor);
 
-            data.writeString(callingPkg);
-            data.writeString(featureId);
+            attributionSource.writeToParcel(data, 0);
             url.writeToParcel(data, 0);
             data.writeString(mimeType);
             data.writeBundle(opts);
@@ -820,15 +809,14 @@
     }
 
     @Override
-    public Uri canonicalize(String callingPkg, @Nullable String featureId, Uri url)
+    public Uri canonicalize(@NonNull AttributionSource attributionSource, Uri url)
             throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         try {
             data.writeInterfaceToken(IContentProvider.descriptor);
 
-            data.writeString(callingPkg);
-            data.writeString(featureId);
+            attributionSource.writeToParcel(data, 0);
             url.writeToParcel(data, 0);
 
             mRemote.transact(IContentProvider.CANONICALIZE_TRANSACTION, data, reply, 0);
@@ -843,14 +831,13 @@
     }
 
     @Override
-    /* oneway */ public void canonicalizeAsync(String callingPkg, @Nullable String featureId,
+    /* oneway */ public void canonicalizeAsync(@NonNull AttributionSource attributionSource,
             Uri uri, RemoteCallback callback) throws RemoteException {
         Parcel data = Parcel.obtain();
         try {
             data.writeInterfaceToken(IContentProvider.descriptor);
 
-            data.writeString(callingPkg);
-            data.writeString(featureId);
+            attributionSource.writeToParcel(data, 0);
             uri.writeToParcel(data, 0);
             callback.writeToParcel(data, 0);
 
@@ -862,15 +849,14 @@
     }
 
     @Override
-    public Uri uncanonicalize(String callingPkg, @Nullable String featureId, Uri url)
+    public Uri uncanonicalize(@NonNull AttributionSource attributionSource, Uri url)
             throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         try {
             data.writeInterfaceToken(IContentProvider.descriptor);
 
-            data.writeString(callingPkg);
-            data.writeString(featureId);
+            attributionSource.writeToParcel(data, 0);
             url.writeToParcel(data, 0);
 
             mRemote.transact(IContentProvider.UNCANONICALIZE_TRANSACTION, data, reply, 0);
@@ -885,14 +871,13 @@
     }
 
     @Override
-    /* oneway */ public void uncanonicalizeAsync(String callingPkg, @Nullable String featureId,
+    /* oneway */ public void uncanonicalizeAsync(@NonNull AttributionSource attributionSource,
             Uri uri, RemoteCallback callback) throws RemoteException {
         Parcel data = Parcel.obtain();
         try {
             data.writeInterfaceToken(IContentProvider.descriptor);
 
-            data.writeString(callingPkg);
-            data.writeString(featureId);
+            attributionSource.writeToParcel(data, 0);
             uri.writeToParcel(data, 0);
             callback.writeToParcel(data, 0);
 
@@ -904,15 +889,14 @@
     }
 
     @Override
-    public boolean refresh(String callingPkg, @Nullable String featureId, Uri url, Bundle extras,
+    public boolean refresh(@NonNull AttributionSource attributionSource, Uri url, Bundle extras,
             ICancellationSignal signal) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         try {
             data.writeInterfaceToken(IContentProvider.descriptor);
 
-            data.writeString(callingPkg);
-            data.writeString(featureId);
+            attributionSource.writeToParcel(data, 0);
             url.writeToParcel(data, 0);
             data.writeBundle(extras);
             data.writeStrongBinder(signal != null ? signal.asBinder() : null);
@@ -929,15 +913,14 @@
     }
 
     @Override
-    public int checkUriPermission(String callingPkg, @Nullable String featureId, Uri url, int uid,
+    public int checkUriPermission(@NonNull AttributionSource attributionSource, Uri url, int uid,
             int modeFlags) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         try {
             data.writeInterfaceToken(IContentProvider.descriptor);
 
-            data.writeString(callingPkg);
-            data.writeString(featureId);
+            attributionSource.writeToParcel(data, 0);
             url.writeToParcel(data, 0);
             data.writeInt(uid);
             data.writeInt(modeFlags);
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 8ea417f..14b2a65 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -816,7 +816,6 @@
     public ContentResolver(@Nullable Context context, @Nullable ContentInterface wrapped) {
         mContext = context != null ? context : ActivityThread.currentApplication();
         mPackageName = mContext.getOpPackageName();
-        mAttributionTag = mContext.getAttributionTag();
         mTargetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
         mWrapped = wrapped;
     }
@@ -1217,7 +1216,7 @@
                 cancellationSignal.setRemote(remoteCancellationSignal);
             }
             try {
-                qCursor = unstableProvider.query(mPackageName, mAttributionTag, uri, projection,
+                qCursor = unstableProvider.query(mContext.getAttributionSource(), uri, projection,
                         queryArgs, remoteCancellationSignal);
             } catch (DeadObjectException e) {
                 // The remote process has died...  but we only hold an unstable
@@ -1228,7 +1227,7 @@
                 if (stableProvider == null) {
                     return null;
                 }
-                qCursor = stableProvider.query(mPackageName, mAttributionTag, uri, projection,
+                qCursor = stableProvider.query(mContext.getAttributionSource(), uri, projection,
                         queryArgs, remoteCancellationSignal);
             }
             if (qCursor == null) {
@@ -1320,7 +1319,7 @@
 
         try {
             final UriResultListener resultListener = new UriResultListener();
-            provider.canonicalizeAsync(mPackageName, mAttributionTag, url,
+            provider.canonicalizeAsync(mContext.getAttributionSource(), url,
                     new RemoteCallback(resultListener));
             resultListener.waitForResult(CONTENT_PROVIDER_TIMEOUT_MILLIS);
             if (resultListener.exception != null) {
@@ -1371,7 +1370,7 @@
 
         try {
             final UriResultListener resultListener = new UriResultListener();
-            provider.uncanonicalizeAsync(mPackageName, mAttributionTag, url,
+            provider.uncanonicalizeAsync(mContext.getAttributionSource(), url,
                     new RemoteCallback(resultListener));
             resultListener.waitForResult(CONTENT_PROVIDER_TIMEOUT_MILLIS);
             if (resultListener.exception != null) {
@@ -1429,7 +1428,7 @@
                 remoteCancellationSignal = provider.createCancellationSignal();
                 cancellationSignal.setRemote(remoteCancellationSignal);
             }
-            return provider.refresh(mPackageName, mAttributionTag, url, extras,
+            return provider.refresh(mContext.getAttributionSource(), url, extras,
                     remoteCancellationSignal);
         } catch (RemoteException e) {
             // Arbitrary and not worth documenting, as Activity
@@ -1858,7 +1857,7 @@
 
                     try {
                         fd = unstableProvider.openAssetFile(
-                                mPackageName, mAttributionTag, uri, mode,
+                                mContext.getAttributionSource(), uri, mode,
                                 remoteCancellationSignal);
                         if (fd == null) {
                             // The provider will be released by the finally{} clause
@@ -1873,8 +1872,8 @@
                         if (stableProvider == null) {
                             throw new FileNotFoundException("No content provider: " + uri);
                         }
-                        fd = stableProvider.openAssetFile(
-                                mPackageName, mAttributionTag, uri, mode, remoteCancellationSignal);
+                        fd = stableProvider.openAssetFile(mContext.getAttributionSource(),
+                                uri, mode, remoteCancellationSignal);
                         if (fd == null) {
                             // The provider will be released by the finally{} clause
                             return null;
@@ -2025,7 +2024,7 @@
 
             try {
                 fd = unstableProvider.openTypedAssetFile(
-                        mPackageName, mAttributionTag, uri, mimeType, opts,
+                        mContext.getAttributionSource(), uri, mimeType, opts,
                         remoteCancellationSignal);
                 if (fd == null) {
                     // The provider will be released by the finally{} clause
@@ -2041,7 +2040,7 @@
                     throw new FileNotFoundException("No content provider: " + uri);
                 }
                 fd = stableProvider.openTypedAssetFile(
-                        mPackageName, mAttributionTag, uri, mimeType, opts,
+                        mContext.getAttributionSource(), uri, mimeType, opts,
                         remoteCancellationSignal);
                 if (fd == null) {
                     // The provider will be released by the finally{} clause
@@ -2190,7 +2189,7 @@
         }
         try {
             long startTime = SystemClock.uptimeMillis();
-            Uri createdRow = provider.insert(mPackageName, mAttributionTag, url, values, extras);
+            Uri createdRow = provider.insert(mContext.getAttributionSource(), url, values, extras);
             long durationMillis = SystemClock.uptimeMillis() - startTime;
             maybeLogUpdateToEventLog(durationMillis, url, "insert", null /* where */);
             return createdRow;
@@ -2271,7 +2270,7 @@
         }
         try {
             long startTime = SystemClock.uptimeMillis();
-            int rowsCreated = provider.bulkInsert(mPackageName, mAttributionTag, url, values);
+            int rowsCreated = provider.bulkInsert(mContext.getAttributionSource(), url, values);
             long durationMillis = SystemClock.uptimeMillis() - startTime;
             maybeLogUpdateToEventLog(durationMillis, url, "bulkinsert", null /* where */);
             return rowsCreated;
@@ -2330,7 +2329,7 @@
         }
         try {
             long startTime = SystemClock.uptimeMillis();
-            int rowsDeleted = provider.delete(mPackageName, mAttributionTag, url, extras);
+            int rowsDeleted = provider.delete(mContext.getAttributionSource(), url, extras);
             long durationMillis = SystemClock.uptimeMillis() - startTime;
             maybeLogUpdateToEventLog(durationMillis, url, "delete", null);
             return rowsDeleted;
@@ -2397,7 +2396,8 @@
         }
         try {
             long startTime = SystemClock.uptimeMillis();
-            int rowsUpdated = provider.update(mPackageName, mAttributionTag, uri, values, extras);
+            int rowsUpdated = provider.update(mContext.getAttributionSource(),
+                    uri, values, extras);
             long durationMillis = SystemClock.uptimeMillis() - startTime;
             maybeLogUpdateToEventLog(durationMillis, uri, "update", null);
             return rowsUpdated;
@@ -2446,8 +2446,8 @@
             throw new IllegalArgumentException("Unknown authority " + authority);
         }
         try {
-            final Bundle res = provider.call(mPackageName, mAttributionTag, authority, method, arg,
-                    extras);
+            final Bundle res = provider.call(mContext.getAttributionSource(),
+                    authority, method, arg, extras);
             Bundle.setDefusable(res, true);
             return res;
         } catch (RemoteException e) {
@@ -3866,12 +3866,17 @@
     /** @hide */
     @UnsupportedAppUsage
     public String getPackageName() {
-        return mPackageName;
+        return mContext.getOpPackageName();
     }
 
     /** @hide */
     public @Nullable String getAttributionTag() {
-        return mAttributionTag;
+        return mContext.getAttributionTag();
+    }
+
+    /** @hide */
+    public @NonNull AttributionSource getAttributionSource() {
+        return mContext.getAttributionSource();
     }
 
     @UnsupportedAppUsage
@@ -3881,7 +3886,6 @@
 
     @UnsupportedAppUsage
     final String mPackageName;
-    final @Nullable String mAttributionTag;
     final int mTargetSdkVersion;
     final ContentInterface mWrapped;
 
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 6ff296c..8531d34 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -889,6 +889,15 @@
         return null;
     }
 
+    /**
+     * @return The identity of this context for permission purposes.
+     *
+     * @see AttributionSource
+     */
+    public @NonNull AttributionSource getAttributionSource() {
+        return null;
+    }
+
     // TODO moltmann: Remove
     /**
      * @removed
@@ -6465,8 +6474,10 @@
      * @removed
      */
     @Deprecated
-    public @NonNull Context createFeatureContext(@Nullable String featureId) {
-        return createAttributionContext(featureId);
+    public @NonNull Context createFeatureContext(@Nullable String attributionTag) {
+        return createContext(new ContextParams.Builder()
+                .setAttributionTag(attributionTag)
+                .build());
     }
 
     /**
diff --git a/core/java/android/content/ContextParams.java b/core/java/android/content/ContextParams.java
index fad905b..2b2db8f 100644
--- a/core/java/android/content/ContextParams.java
+++ b/core/java/android/content/ContextParams.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
-import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 
 import java.util.Collections;
@@ -38,36 +37,26 @@
  * is an arbitrary string your app specifies for the purposes of tracking permission
  * accesses from a given portion of your app; against another package and optionally
  * its attribution tag if you are accessing the data on behalf of another app and
- * you will be passing that data to this app. Both attributions are not mutually
- * exclusive.
- *
- * <p>For example if you have a feature "foo" in your app which accesses
- * permissions on behalf of app "foo.bar.baz" with feature "bar" you need to
- * create a context like this:
- *
- * <pre class="prettyprint">
- * context.createContext(new ContextParams.Builder()
- *     .setAttributionTag("foo")
- *     .setReceiverPackage("foo.bar.baz", "bar")
- *     .build())
- * </pre>
+ * you will be passing that data to this app, recursively. Both attributions are
+ * not mutually exclusive.
  *
  * @see Context#createContext(ContextParams)
+ * @see AttributionSource
  */
 public final class ContextParams {
-    private final String mAttributionTag;
-    private final String mReceiverPackage;
-    private final String mReceiverAttributionTag;
-    private final Set<String> mRenouncedPermissions;
+    private final @Nullable String mAttributionTag;
+    private final @Nullable AttributionSource mNext;
+    private final @NonNull Set<String> mRenouncedPermissions;
 
     /** {@hide} */
     public static final ContextParams EMPTY = new ContextParams.Builder().build();
 
-    private ContextParams(@NonNull ContextParams.Builder builder) {
-        mAttributionTag = builder.mAttributionTag;
-        mReceiverPackage = builder.mReceiverPackage;
-        mReceiverAttributionTag = builder.mReceiverAttributionTag;
-        mRenouncedPermissions = builder.mRenouncedPermissions;
+    private ContextParams(@Nullable String attributionTag,
+            @Nullable AttributionSource next,
+            @NonNull Set<String> renouncedPermissions) {
+        mAttributionTag = attributionTag;
+        mNext = next;
+        mRenouncedPermissions = renouncedPermissions;
     }
 
     /**
@@ -79,45 +68,35 @@
     }
 
     /**
-     * @return The receiving package.
-     */
-    @Nullable
-    public String getReceiverPackage() {
-        return mReceiverPackage;
-    }
-
-    /**
-     * @return The receiving package's attribution tag.
-     */
-    @Nullable
-    public String getReceiverAttributionTag() {
-        return mReceiverAttributionTag;
-    }
-
-    /**
      * @return The set of permissions to treat as renounced.
      * @hide
      */
     @SystemApi
-    @SuppressLint("NullableCollection")
     @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS)
-    public @Nullable Set<String> getRenouncedPermissions() {
+    public @NonNull Set<String> getRenouncedPermissions() {
         return mRenouncedPermissions;
     }
 
     /** @hide */
     public boolean isRenouncedPermission(@NonNull String permission) {
-        return mRenouncedPermissions != null && mRenouncedPermissions.contains(permission);
+        return mRenouncedPermissions.contains(permission);
+    }
+
+    /**
+     * @return The receiving attribution source.
+     */
+    @Nullable
+    public AttributionSource getNextAttributionSource() {
+        return mNext;
     }
 
     /**
      * Builder for creating a {@link ContextParams}.
      */
     public static final class Builder {
-        private String mAttributionTag;
-        private String mReceiverPackage;
-        private String mReceiverAttributionTag;
-        private Set<String> mRenouncedPermissions;
+        private @Nullable String mAttributionTag;
+        private @NonNull Set<String> mRenouncedPermissions = Collections.emptySet();
+        private @Nullable AttributionSource mNext;
 
         /**
          * Create a new builder.
@@ -145,9 +124,8 @@
         public Builder(@NonNull ContextParams params) {
             Objects.requireNonNull(params);
             mAttributionTag = params.mAttributionTag;
-            mReceiverPackage = params.mReceiverPackage;
-            mReceiverAttributionTag = params.mReceiverAttributionTag;
             mRenouncedPermissions = params.mRenouncedPermissions;
+            mNext = params.mNext;
         }
 
         /**
@@ -163,18 +141,16 @@
         }
 
         /**
-         * Sets the package and its optional attribution tag that would be receiving
-         * the permission protected data.
+         * Sets the attribution source for the app on whose behalf you are doing the work.
          *
-         * @param packageName The package name receiving the permission protected data.
-         * @param attributionTag An attribution tag of the receiving package.
+         * @param next The permission identity of the receiving app.
          * @return This builder.
+         *
+         * @see AttributionSource
          */
         @NonNull
-        public Builder setReceiverPackage(@Nullable String packageName,
-                @Nullable String attributionTag) {
-            mReceiverPackage = packageName;
-            mReceiverAttributionTag = attributionTag;
+        public Builder setNextAttributionSource(@NonNull AttributionSource next) {
+            mNext = Objects.requireNonNull(next);
             return this;
         }
 
@@ -194,19 +170,16 @@
          * permissions are supported by this mechanism.
          *
          * @param renouncedPermissions The set of permissions to treat as
-         *            renounced.
+         *            renounced, which is as if not granted.
          * @return This builder.
          * @hide
          */
         @SystemApi
         @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS)
         public @NonNull Builder setRenouncedPermissions(
-                @Nullable Set<String> renouncedPermissions) {
-            if (renouncedPermissions != null) {
-                mRenouncedPermissions = Collections.unmodifiableSet(renouncedPermissions);
-            } else {
-                mRenouncedPermissions = null;
-            }
+                @NonNull Set<String> renouncedPermissions) {
+            mRenouncedPermissions = Collections.unmodifiableSet(
+                    Objects.requireNonNull(renouncedPermissions));
             return this;
         }
 
@@ -217,7 +190,8 @@
          */
         @NonNull
         public ContextParams build() {
-            return new ContextParams(this);
+            return new ContextParams(mAttributionTag, mNext,
+                    mRenouncedPermissions);
         }
     }
 }
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 609f417..de0d65f 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -1060,6 +1060,12 @@
         return mBase.createAttributionContext(attributionTag);
     }
 
+    @NonNull
+    @Override
+    public AttributionSource getAttributionSource() {
+        return mBase.getAttributionSource();
+    }
+
     @Override
     public boolean isRestricted() {
         return mBase.isRestricted();
diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java
index 9210b13..e0315a3 100644
--- a/core/java/android/content/IContentProvider.java
+++ b/core/java/android/content/IContentProvider.java
@@ -16,11 +16,13 @@
 
 package android.content;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.res.AssetFileDescriptor;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -38,11 +40,11 @@
  * @hide
  */
 public interface IContentProvider extends IInterface {
-    public Cursor query(String callingPkg, @Nullable String attributionTag, Uri url,
+    Cursor query(@NonNull AttributionSource attributionSource, Uri url,
             @Nullable String[] projection,
             @Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal)
             throws RemoteException;
-    public String getType(Uri url) throws RemoteException;
+    String getType(Uri url) throws RemoteException;
 
     /**
      * A oneway version of getType. The functionality is exactly the same, except that the
@@ -55,54 +57,56 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
             + "ContentProviderClient#insert(android.net.Uri, android.content.ContentValues)} "
             + "instead")
-    public default Uri insert(String callingPkg, Uri url, ContentValues initialValues)
+    default Uri insert(String callingPkg, Uri url, ContentValues initialValues)
             throws RemoteException {
-        return insert(callingPkg, null, url, initialValues, null);
+        return insert(new AttributionSource(Binder.getCallingUid(), callingPkg, null),
+                url, initialValues, null);
     }
-    public Uri insert(String callingPkg, String attributionTag, Uri url,
+    Uri insert(@NonNull AttributionSource attributionSource, Uri url,
             ContentValues initialValues, Bundle extras) throws RemoteException;
     @Deprecated
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
             + "ContentProviderClient#bulkInsert(android.net.Uri, android.content.ContentValues[])"
             + "} instead")
-    public default int bulkInsert(String callingPkg, Uri url, ContentValues[] initialValues)
+    default int bulkInsert(String callingPkg, Uri url, ContentValues[] initialValues)
             throws RemoteException {
-        return bulkInsert(callingPkg, null, url, initialValues);
+        return bulkInsert(new AttributionSource(Binder.getCallingUid(), callingPkg, null),
+                url, initialValues);
     }
-    public int bulkInsert(String callingPkg, String attributionTag, Uri url,
+    int bulkInsert(@NonNull AttributionSource attributionSource, Uri url,
             ContentValues[] initialValues) throws RemoteException;
     @Deprecated
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
             + "ContentProviderClient#delete(android.net.Uri, java.lang.String, java.lang"
             + ".String[])} instead")
-    public default int delete(String callingPkg, Uri url, String selection, String[] selectionArgs)
+    default int delete(String callingPkg, Uri url, String selection, String[] selectionArgs)
             throws RemoteException {
-        return delete(callingPkg, null, url,
-                ContentResolver.createSqlQueryBundle(selection, selectionArgs));
+        return delete(new AttributionSource(Binder.getCallingUid(), callingPkg, null),
+                url, ContentResolver.createSqlQueryBundle(selection, selectionArgs));
     }
-    public int delete(String callingPkg, String attributionTag, Uri url, Bundle extras)
+    int delete(@NonNull AttributionSource attributionSource, Uri url, Bundle extras)
             throws RemoteException;
     @Deprecated
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
             + "ContentProviderClient#update(android.net.Uri, android.content.ContentValues, java"
             + ".lang.String, java.lang.String[])} instead")
-    public default int update(String callingPkg, Uri url, ContentValues values, String selection,
+    default int update(String callingPkg, Uri url, ContentValues values, String selection,
             String[] selectionArgs) throws RemoteException {
-        return update(callingPkg, null, url, values,
-                ContentResolver.createSqlQueryBundle(selection, selectionArgs));
+        return update(new AttributionSource(Binder.getCallingUid(), callingPkg, null),
+                url, values, ContentResolver.createSqlQueryBundle(selection, selectionArgs));
     }
-    public int update(String callingPkg, String attributionTag, Uri url, ContentValues values,
+    int update(@NonNull AttributionSource attributionSource, Uri url, ContentValues values,
             Bundle extras) throws RemoteException;
 
-    public ParcelFileDescriptor openFile(String callingPkg, @Nullable String attributionTag,
-            Uri url, String mode, ICancellationSignal signal, IBinder callerToken)
-            throws RemoteException, FileNotFoundException;
-
-    public AssetFileDescriptor openAssetFile(String callingPkg, @Nullable String attributionTag,
+    ParcelFileDescriptor openFile(@NonNull AttributionSource attributionSource,
             Uri url, String mode, ICancellationSignal signal)
             throws RemoteException, FileNotFoundException;
 
-    public ContentProviderResult[] applyBatch(String callingPkg, @Nullable String attributionTag,
+    AssetFileDescriptor openAssetFile(@NonNull AttributionSource attributionSource,
+            Uri url, String mode, ICancellationSignal signal)
+            throws RemoteException, FileNotFoundException;
+
+    ContentProviderResult[] applyBatch(@NonNull AttributionSource attributionSource,
             String authority, ArrayList<ContentProviderOperation> operations)
             throws RemoteException, OperationApplicationException;
 
@@ -112,18 +116,19 @@
             + "instead")
     public default Bundle call(String callingPkg, String method,
             @Nullable String arg, @Nullable Bundle extras) throws RemoteException {
-        return call(callingPkg, null, "unknown", method, arg, extras);
+        return call(new AttributionSource(Binder.getCallingUid(), callingPkg, null),
+                "unknown", method, arg, extras);
     }
 
-    public Bundle call(String callingPkg, @Nullable String attributionTag, String authority,
+    Bundle call(@NonNull AttributionSource attributionSource, String authority,
             String method, @Nullable String arg, @Nullable Bundle extras) throws RemoteException;
 
-    public int checkUriPermission(String callingPkg, @Nullable String attributionTag, Uri uri,
+    int checkUriPermission(@NonNull AttributionSource attributionSource, Uri uri,
             int uid, int modeFlags) throws RemoteException;
 
-    public ICancellationSignal createCancellationSignal() throws RemoteException;
+    ICancellationSignal createCancellationSignal() throws RemoteException;
 
-    public Uri canonicalize(String callingPkg, @Nullable String attributionTag, Uri uri)
+    Uri canonicalize(@NonNull AttributionSource attributionSource, Uri uri)
             throws RemoteException;
 
     /**
@@ -131,10 +136,10 @@
      * call returns immediately, and the resulting type is returned when available via
      * a binder callback.
      */
-    void canonicalizeAsync(String callingPkg, @Nullable String attributionTag, Uri uri,
+    void canonicalizeAsync(@NonNull AttributionSource attributionSource, Uri uri,
             RemoteCallback callback) throws RemoteException;
 
-    public Uri uncanonicalize(String callingPkg, @Nullable String attributionTag, Uri uri)
+    Uri uncanonicalize(@NonNull AttributionSource attributionSource, Uri uri)
             throws RemoteException;
 
     /**
@@ -142,18 +147,17 @@
      * call returns immediately, and the resulting type is returned when available via
      * a binder callback.
      */
-    void uncanonicalizeAsync(String callingPkg, @Nullable String attributionTag, Uri uri,
+    void uncanonicalizeAsync(@NonNull AttributionSource attributionSource, Uri uri,
             RemoteCallback callback) throws RemoteException;
 
-    public boolean refresh(String callingPkg, @Nullable String attributionTag, Uri url,
+    public boolean refresh(@NonNull AttributionSource attributionSource, Uri url,
             @Nullable Bundle extras, ICancellationSignal cancellationSignal) throws RemoteException;
 
     // Data interchange.
     public String[] getStreamTypes(Uri url, String mimeTypeFilter) throws RemoteException;
 
-    public AssetFileDescriptor openTypedAssetFile(String callingPkg,
-            @Nullable String attributionTag, Uri url, String mimeType, Bundle opts,
-            ICancellationSignal signal)
+    public AssetFileDescriptor openTypedAssetFile(@NonNull AttributionSource attributionSource,
+            Uri url, String mimeType, Bundle opts, ICancellationSignal signal)
             throws RemoteException, FileNotFoundException;
 
     /* IPC constants */
diff --git a/core/java/android/content/PermissionChecker.java b/core/java/android/content/PermissionChecker.java
index 159db92..08eac5a 100644
--- a/core/java/android/content/PermissionChecker.java
+++ b/core/java/android/content/PermissionChecker.java
@@ -27,6 +27,8 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * This class provides permission check APIs that verify both the
@@ -68,8 +70,14 @@
  * @hide
  */
 public final class PermissionChecker {
+    private static final String PLATFORM_PACKAGE_NAME = "android";
+
     /** The permission is granted. */
-    public static final int PERMISSION_GRANTED =  PackageManager.PERMISSION_GRANTED;
+    public static final int PERMISSION_GRANTED = AppOpsManager.MODE_ALLOWED;
+
+    /** Only for runtime permissions, its returned when the runtime permission
+     * is granted, but the corresponding app op is denied. */
+    public static final int PERMISSION_SOFT_DENIED = AppOpsManager.MODE_IGNORED;
 
     /** Returned when:
      * <ul>
@@ -79,15 +87,14 @@
      * </ul>
      *
      */
-    public static final int PERMISSION_HARD_DENIED =  PackageManager.PERMISSION_DENIED;
-
-    /** Only for runtime permissions, its returned when the runtime permission
-     * is granted, but the corresponding app op is denied. */
-    public static final int PERMISSION_SOFT_DENIED =  PackageManager.PERMISSION_DENIED - 1;
+    public static final int PERMISSION_HARD_DENIED = AppOpsManager.MODE_ERRORED;
 
     /** Constant when the PID for which we check permissions is unknown. */
     public static final int PID_UNKNOWN = -1;
 
+    private static final ConcurrentHashMap<String, PermissionInfo> sPlatformPermissions
+            = new ConcurrentHashMap<>();
+
     /** @hide */
     @IntDef({PERMISSION_GRANTED,
             PERMISSION_SOFT_DENIED,
@@ -131,6 +138,50 @@
      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
      * @param message A message describing the reason the permission was checked
+     * @param startDataDelivery Whether this is the start of data delivery.
+     *
+     * @see #checkPermissionForPreflight(Context, String, int, int, String)
+     */
+    @PermissionResult
+    public static int checkPermissionForDataDelivery(@NonNull Context context,
+            @NonNull String permission, int pid, int uid, @Nullable String packageName,
+            @Nullable String attributionTag, @Nullable String message, boolean startDataDelivery) {
+        return checkPermissionForDataDelivery(context, permission, pid, new AttributionSource(uid,
+                packageName, attributionTag), message, startDataDelivery);
+    }
+
+    /**
+     * Checks whether a given package in a UID and PID has a given permission
+     * and whether the app op that corresponds to this permission is allowed.
+     *
+     * <strong>NOTE:</strong> Use this method only for permission checks at the
+     * point where you will deliver the permission protected data to clients.
+     *
+     * <p>For example, if an app registers a location listener it should have the location
+     * permission but no data is actually sent to the app at the moment of registration
+     * and you should use {@link #checkPermissionForPreflight(Context, String, int, int, String)}
+     * to determine if the app has or may have location permission (if app has only foreground
+     * location the grant state depends on the app's fg/gb state) and this check will not
+     * leave a trace that permission protected data was delivered. When you are about to
+     * deliver the location data to a registered listener you should use this method which
+     * will evaluate the permission access based on the current fg/bg state of the app and
+     * leave a record that the data was accessed.
+     *
+     * <p>For more details how to determine the {@code packageName}, {@code attributionTag}, and
+     * {@code message}, please check the description in
+     * {@link AppOpsManager#noteOp(String, int, String, String, String)}
+     *
+     * @param context Context for accessing resources.
+     * @param permission The permission to check.
+     * @param pid The process id for which to check. Use {@link #PID_UNKNOWN} if the PID
+     *    is not known.
+     * @param uid The uid for which to check.
+     * @param packageName The package name for which to check. If null the
+     *     the first package for the calling UID will be used.
+     * @param attributionTag attribution tag
+     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+     *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
+     * @param message A message describing the reason the permission was checked
      *
      * @see #checkPermissionForPreflight(Context, String, int, int, String)
      */
@@ -138,8 +189,303 @@
     public static int checkPermissionForDataDelivery(@NonNull Context context,
             @NonNull String permission, int pid, int uid, @Nullable String packageName,
             @Nullable String attributionTag, @Nullable String message) {
-        return checkPermissionCommon(context, permission, pid, uid, packageName, attributionTag,
-                message, true /*forDataDelivery*/);
+        return checkPermissionForDataDelivery(context, permission, pid, uid,
+                packageName, attributionTag, message, false /*startDataDelivery*/);
+    }
+
+    /**
+     * Checks whether a given data access chain described by the given {@link AttributionSource}
+     * has a given permission and whether the app op that corresponds to this permission
+     * is allowed. Call this method if you are the datasource which would not blame you for
+     * access to the data since you are the data.
+     *
+     * <strong>NOTE:</strong> Use this method only for permission checks at the
+     * point where you will deliver the permission protected data to clients.
+     *
+     * <p>For example, if an app registers a location listener it should have the location
+     * permission but no data is actually sent to the app at the moment of registration
+     * and you should use {@link #checkPermissionForPreflight(Context, String, int, int, String)}
+     * to determine if the app has or may have location permission (if app has only foreground
+     * location the grant state depends on the app's fg/gb state) and this check will not
+     * leave a trace that permission protected data was delivered. When you are about to
+     * deliver the location data to a registered listener you should use this method which
+     * will evaluate the permission access based on the current fg/bg state of the app and
+     * leave a record that the data was accessed.
+     *
+     * @param context Context for accessing resources.
+     * @param permission The permission to check.
+     * @param pid The process id for which to check. Use {@link #PID_UNKNOWN} if the PID
+     *    is not known.
+     * @param attributionSource the permission identity
+     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+     *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
+     * @param message A message describing the reason the permission was checked
+     *
+     * @see #checkPermissionForPreflight(Context, String, AttributionSource)
+     */
+    @PermissionResult
+    public static int checkPermissionForDataDeliveryFromDataSource(@NonNull Context context,
+            @NonNull String permission, int pid, @NonNull AttributionSource attributionSource,
+            @Nullable String message) {
+        return checkPermissionForDataDeliveryCommon(context, permission, pid, attributionSource,
+                message, false /*startDataDelivery*/, /*fromDatasource*/ true);
+    }
+
+    /**
+     * Checks whether a given data access chain described by the given {@link AttributionSource}
+     * has a given permission and whether the app op that corresponds to this permission
+     * is allowed.
+     *
+     * <strong>NOTE:</strong> Use this method only for permission checks at the
+     * point where you will deliver the permission protected data to clients.
+     *
+     * <p>For example, if an app registers a location listener it should have the location
+     * permission but no data is actually sent to the app at the moment of registration
+     * and you should use {@link #checkPermissionForPreflight(Context, String, AttributionSource)}
+     * to determine if the app has or may have location permission (if app has only foreground
+     * location the grant state depends on the app's fg/gb state) and this check will not
+     * leave a trace that permission protected data was delivered. When you are about to
+     * deliver the location data to a registered listener you should use this method which
+     * will evaluate the permission access based on the current fg/bg state of the app and
+     * leave a record that the data was accessed.
+     *
+     * @param context Context for accessing resources.
+     * @param permission The permission to check.
+     * @param pid The process id for which to check. Use {@link #PID_UNKNOWN} if the PID
+     *    is not known.
+     * @param attributionSource the permission identity
+     * @param message A message describing the reason the permission was checked
+     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+     *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
+     *
+     * @see #checkPermissionForPreflight(Context, String, AttributionSource)
+     */
+    @PermissionResult
+    public static int checkPermissionForDataDelivery(@NonNull Context context,
+            @NonNull String permission, int pid, @NonNull AttributionSource attributionSource,
+            @Nullable String message) {
+        return checkPermissionForDataDelivery(context, permission, pid, attributionSource,
+                message, false /*startDataDelivery*/);
+    }
+
+    /**
+     * Checks whether a given data access chain described by the given {@link AttributionSource}
+     * has a given permission and whether the app op that corresponds to this permission
+     * is allowed.
+     *
+     * <strong>NOTE:</strong> Use this method only for permission checks at the
+     * point where you will deliver the permission protected data to clients.
+     *
+     * <p>For example, if an app registers a data listener it should have the required
+     * permission but no data is actually sent to the app at the moment of registration
+     * and you should use {@link #checkPermissionForPreflight(Context, String,
+     * AttributionSource)}
+     * to determine if the app has or may have permission and this check will not
+     * leave a trace that permission protected data was delivered. When you are about to
+     * deliver the data to a registered listener you should use this method which
+     * will evaluate the permission access based on the current fg/bg state of the app and
+     * leave a record that the data was accessed.
+     *
+     * @param context Context for accessing resources.
+     * @param permission The permission to check.
+     * @param pid The process id for which to check. Use {@link #PID_UNKNOWN} if the PID
+     *    is not known.
+     * @param attributionSource The identity for which to check the permission.
+     * @param message A message describing the reason the permission was checked
+     * @param startDataDelivery Whether this is the start of data delivery.
+     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+     *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
+     *
+     * @see #checkPermissionForPreflight(Context, String, AttributionSource)
+     */
+    @PermissionResult
+    public static int checkPermissionForDataDelivery(@NonNull Context context,
+            @NonNull String permission, int pid, @NonNull AttributionSource attributionSource,
+            @Nullable String message, boolean startDataDelivery) {
+        return checkPermissionForDataDeliveryCommon(context, permission, pid, attributionSource,
+                message, startDataDelivery, /*fromDatasource*/ false);
+    }
+
+    private static int checkPermissionForDataDeliveryCommon(@NonNull Context context,
+            @NonNull String permission, int pid, @NonNull AttributionSource attributionSource,
+            @Nullable String message, boolean startDataDelivery, boolean fromDatasource) {
+        // If the check failed in the middle of the chain, finish any started op.
+        final int result = checkPermissionCommon(context, permission, attributionSource,
+                message, true /*forDataDelivery*/, startDataDelivery, fromDatasource);
+        if (startDataDelivery && result != PERMISSION_GRANTED) {
+            finishDataDelivery(context, AppOpsManager.permissionToOp(permission),
+                    attributionSource);
+        }
+        return result;
+    }
+
+    /**
+     * Checks whether a given data access chain described by the given {@link AttributionSource}
+     * has a given permission and whether the app op that corresponds to this permission
+     * is allowed. The app ops area also marked as started. This is useful for long running
+     * permissions like camera.
+     *
+     * <strong>NOTE:</strong> Use this method only for permission checks at the
+     * point where you will deliver the permission protected data to clients.
+     *
+     * <p>For example, if an app registers a data listener it should have the required
+     * permission but no data is actually sent to the app at the moment of registration
+     * and you should use {@link #checkPermissionForPreflight(Context, String,
+     * AttributionSource)}
+     * to determine if the app has or may have permission and this check will not
+     * leave a trace that permission protected data was delivered. When you are about to
+     * deliver the data to a registered listener you should use this method which
+     * will evaluate the permission access based on the current fg/bg state of the app and
+     * leave a record that the data was accessed.
+     *
+     * @param context Context for accessing resources.
+     * @param permission The permission to check.
+     * @param attributionSource The identity for which to check the permission.
+     * @param message A message describing the reason the permission was checked
+     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+     *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
+     *
+     * @see #checkPermissionForPreflight(Context, String, AttributionSource)
+     */
+    @PermissionResult
+    public static int checkPermissionAndStartDataDelivery(@NonNull Context context,
+            @NonNull String permission, @NonNull AttributionSource attributionSource,
+            @Nullable String message) {
+        return checkPermissionCommon(context, permission, attributionSource,
+                message, true /*forDataDelivery*/, /*startDataDelivery*/ true,
+                /*fromDatasource*/ false);
+    }
+
+    /**
+     * Checks whether a given data access chain described by the given {@link
+     * AttributionSource} has a given app op allowed and marks the op as started.
+     *
+     * <strong>NOTE:</strong> Use this method only for app op checks at the
+     * point where you will deliver the protected data to clients.
+     *
+     * <p>For example, if an app registers a data listener it should have the data
+     * op but no data is actually sent to the app at the moment of registration
+     * and you should use {@link #checkOpForPreflight(Context, String, AttributionSource, String)}
+     * to determine if the app has or may have op access and this check will not
+     * leave a trace that op protected data was delivered. When you are about to
+     * deliver the data to a registered listener you should use this method which
+     * will evaluate the op access based on the current fg/bg state of the app and
+     * leave a record that the data was accessed.
+     *
+     * @param context Context for accessing resources.
+     * @param opName THe op to start.
+     * @param attributionSource The identity for which to check the permission.
+     * @param message A message describing the reason the permission was checked
+     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+     *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
+     *
+     * @see #finishDataDelivery(Context, String, AttributionSource)
+     */
+    @PermissionResult
+    public static int startOpForDataDelivery(@NonNull Context context,
+            @NonNull String opName, @NonNull AttributionSource attributionSource,
+            @Nullable String message) {
+        final int result = checkOp(context, AppOpsManager.strOpToOp(opName), attributionSource,
+                message, true /*forDataDelivery*/, true /*startDataDelivery*/);
+        // It is important to finish any started op if some step in the attribution chain failed.
+        if (result != PERMISSION_GRANTED) {
+            finishDataDelivery(context, opName, attributionSource);
+        }
+        return result;
+    }
+
+    /**
+     * Finishes an ongoing op for data access chain described by the given {@link
+     * AttributionSource}.
+     *
+     * @param context Context for accessing resources.
+     * @param op The op to finish.
+     * @param attributionSource The identity for which finish op.
+     *
+     * @see #startOpForDataDelivery(Context, String, AttributionSource, String)
+     * @see #checkPermissionAndStartDataDelivery(Context, String, AttributionSource, String)
+     */
+    public static void finishDataDelivery(@NonNull Context context, @NonNull String op,
+            @NonNull AttributionSource attributionSource) {
+        if (op == null || attributionSource.getPackageName() == null) {
+            return;
+        }
+
+        final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
+        appOpsManager.finishProxyOp(op, attributionSource);
+
+        if (attributionSource.getNext() != null) {
+            finishDataDelivery(context, op, attributionSource.getNext());
+        }
+    }
+
+    /**
+     * Checks whether a given data access chain described by the given {@link
+     * AttributionSource} has a given app op allowed.
+     *
+     * <strong>NOTE:</strong> Use this method only for op checks at the
+     * preflight point where you will not deliver the protected data
+     * to clients but schedule a data delivery, apps register listeners,
+     * etc.
+     *
+     * <p>For example, if an app registers a data listener it should have the op
+     * but no data is actually sent to the app at the moment of registration
+     * and you should use this method to determine if the app has or may have data
+     * access and this check will not leave a trace that protected data
+     * was delivered. When you are about to deliver the data to a registered
+     * listener you should use {@link #checkOpForDataDelivery(Context, String,
+     * AttributionSource, String)} which will evaluate the op access based
+     * on the current fg/bg state of the app and leave a record that the data was
+     * accessed.
+     *
+     * @param context Context for accessing resources.
+     * @param opName The op to check.
+     * @param attributionSource The identity for which to check the permission.
+     * @param message A message describing the reason the permission was checked
+     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+     *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
+     *
+     * @see #checkOpForDataDelivery(Context, String, AttributionSource, String)
+     */
+    @PermissionResult
+    public static int checkOpForPreflight(@NonNull Context context,
+            @NonNull String opName, @NonNull AttributionSource attributionSource,
+            @Nullable String message) {
+        return checkOp(context, AppOpsManager.strOpToOp(opName), attributionSource,
+                message,  false /*forDataDelivery*/, false /*startDataDelivery*/);
+    }
+
+    /**
+     * Checks whether a given data access chain described by the given {@link AttributionSource}
+     * has an allowed app op.
+     *
+     * <strong>NOTE:</strong> Use this method only for op checks at the
+     * point where you will deliver the permission protected data to clients.
+     *
+     * <p>For example, if an app registers a data listener it should have the data
+     * permission but no data is actually sent to the app at the moment of registration
+     * and you should use {@link #checkOpForPreflight(Context, String, AttributionSource, String)}
+     * to determine if the app has or may have data access and this check will not
+     * leave a trace that op protected data was delivered. When you are about to
+     * deliver the  data to a registered listener you should use this method which
+     * will evaluate the op access based on the current fg/bg state of the app and
+     * leave a record that the data was accessed.
+     *
+     * @param context Context for accessing resources.
+     * @param opName The op to check.
+     * @param attributionSource The identity for which to check the op.
+     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+     *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
+     * @param message A message describing the reason the permission was checked
+     *
+     * @see #checkOpForPreflight(Context, String, AttributionSource, String)
+     */
+    @PermissionResult
+    public static int checkOpForDataDelivery(@NonNull Context context,
+            @NonNull String opName, @NonNull AttributionSource attributionSource,
+            @Nullable String message) {
+        return checkOp(context, AppOpsManager.strOpToOp(opName), attributionSource,
+                message,  true /*forDataDelivery*/, false /*startDataDelivery*/);
     }
 
     /**
@@ -158,8 +504,8 @@
      * fg/gb state) and this check will not leave a trace that permission protected data
      * was delivered. When you are about to deliver the location data to a registered
      * listener you should use {@link #checkPermissionForDataDelivery(Context, String,
-     * int, int, String, String)} which will evaluate the permission access based on the current
-     * fg/bg state of the app and leave a record that the data was accessed.
+     * int, int, String, String, String)} which will evaluate the permission access based
+     * on the currentfg/bg state of the app and leave a record that the data was accessed.
      *
      * @param context Context for accessing resources.
      * @param permission The permission to check.
@@ -170,13 +516,49 @@
      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
      *
-     * @see #checkPermissionForDataDelivery(Context, String, int, int, String, String)
+     * @see #checkPermissionForDataDelivery(Context, String, int, int, String, String, String)
      */
     @PermissionResult
     public static int checkPermissionForPreflight(@NonNull Context context,
             @NonNull String permission, int pid, int uid, @Nullable String packageName) {
-        return checkPermissionCommon(context, permission, pid, uid, packageName,
-                null /*attributionTag*/, null /*message*/, false /*forDataDelivery*/);
+        return checkPermissionForPreflight(context, permission, new AttributionSource(
+                uid, packageName, null /*attributionTag*/));
+    }
+
+    /**
+     * Checks whether a given data access chain described by the given {@link AttributionSource}
+     * has a given permission and whether the app op that corresponds to this permission
+     * is allowed.
+     *
+     * <strong>NOTE:</strong> Use this method only for permission checks at the
+     * preflight point where you will not deliver the permission protected data
+     * to clients but schedule permission data delivery, apps register listeners,
+     * etc.
+     *
+     * <p>For example, if an app registers a data listener it should have the required
+     * permission but no data is actually sent to the app at the moment of registration
+     * and you should use this method to determine if the app has or may have the
+     * permission and this check will not leave a trace that permission protected data
+     * was delivered. When you are about to deliver the protected data to a registered
+     * listener you should use {@link #checkPermissionForDataDelivery(Context, String,
+     * int, AttributionSource, String, boolean)} which will evaluate the permission access based
+     * on the current fg/bg state of the app and leave a record that the data was accessed.
+     *
+     * @param context Context for accessing resources.
+     * @param permission The permission to check.
+     * @param attributionSource The identity for which to check the permission.
+     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+     *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
+     *
+     * @see #checkPermissionForDataDelivery(Context, String, int, AttributionSource,
+     *     String, boolean)
+     */
+    @PermissionResult
+    public static int checkPermissionForPreflight(@NonNull Context context,
+            @NonNull String permission, @NonNull AttributionSource attributionSource) {
+        return checkPermissionCommon(context, permission, attributionSource,
+                null /*message*/, false /*forDataDelivery*/, /*startDataDelivery*/ false,
+                /*fromDatasource*/ false);
     }
 
     /**
@@ -211,7 +593,8 @@
     public static int checkSelfPermissionForDataDelivery(@NonNull Context context,
             @NonNull String permission, @Nullable String message) {
         return checkPermissionForDataDelivery(context, permission, Process.myPid(),
-                Process.myUid(), context.getPackageName(), context.getAttributionTag(), message);
+                Process.myUid(), context.getPackageName(), context.getAttributionTag(), message,
+                /*startDataDelivery*/ false);
     }
 
     /**
@@ -289,7 +672,8 @@
             return PERMISSION_HARD_DENIED;
         }
         return checkPermissionForDataDelivery(context, permission, Binder.getCallingPid(),
-                Binder.getCallingUid(), callingPackageName, callingAttributionTag, message);
+                Binder.getCallingUid(), callingPackageName, callingAttributionTag, message,
+                /*startDataDelivery*/ false);
     }
 
     /**
@@ -308,8 +692,8 @@
      * fg/gb state) and this check will not leave a trace that permission protected data
      * was delivered. When you are about to deliver the location data to a registered
      * listener you should use {@link #checkCallingOrSelfPermissionForDataDelivery(Context,
-     * String, String)} which will evaluate the permission access based on the current fg/bg state
-     * of the app and leave a record that the data was accessed.
+     * String, String, String, String)} which will evaluate the permission access based on the
+     * current fg/bg stateof the app and leave a record that the data was accessed.
      *
      * @param context Context for accessing resources.
      * @param permission The permission to check.
@@ -318,7 +702,7 @@
      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
      *
-     * @see #checkCallingPermissionForDataDelivery(Context, String, String, String)
+     * @see #checkCallingPermissionForDataDelivery(Context, String, String, String, String)
      */
     @PermissionResult
     public static int checkCallingPermissionForPreflight(@NonNull Context context,
@@ -370,7 +754,8 @@
         callingAttributionTag = (Binder.getCallingPid() == Process.myPid())
                 ? context.getAttributionTag() : callingAttributionTag;
         return checkPermissionForDataDelivery(context, permission, Binder.getCallingPid(),
-                Binder.getCallingUid(), callingPackageName, callingAttributionTag, message);
+                Binder.getCallingUid(), callingPackageName, callingAttributionTag, message,
+                /*startDataDelivery*/ false);
     }
 
     /**
@@ -408,88 +793,325 @@
                 Binder.getCallingUid(), packageName);
     }
 
-    static int checkPermissionCommon(@NonNull Context context, @NonNull String permission,
-            int pid, int uid, @Nullable String packageName, @Nullable String attributionTag,
-            @Nullable String message, boolean forDataDelivery) {
-        final PermissionInfo permissionInfo;
-        try {
-            // TODO(b/147869157): Cache platform defined app op and runtime permissions to avoid
-            // calling into the package manager every time.
-            permissionInfo = context.getPackageManager().getPermissionInfo(permission, 0);
-        } catch (PackageManager.NameNotFoundException ignored) {
-            return PERMISSION_HARD_DENIED;
-        }
+    @PermissionResult
+    private static int checkPermissionCommon(@NonNull Context context, @NonNull String permission,
+            @NonNull AttributionSource attributionSource,
+            @Nullable String message, boolean forDataDelivery, boolean startDataDelivery,
+            boolean fromDatasource) {
+        PermissionInfo permissionInfo = sPlatformPermissions.get(permission);
 
-        if (packageName == null) {
-            String[] packageNames = context.getPackageManager().getPackagesForUid(uid);
-            if (packageNames != null && packageNames.length > 0) {
-                packageName = packageNames[0];
+        if (permissionInfo == null) {
+            try {
+                permissionInfo = context.getPackageManager().getPermissionInfo(permission, 0);
+                if (PLATFORM_PACKAGE_NAME.equals(permissionInfo.packageName)) {
+                    // Double addition due to concurrency is fine - the backing store is concurrent.
+                    sPlatformPermissions.put(permission, permissionInfo);
+                }
+            } catch (PackageManager.NameNotFoundException ignored) {
+                return PERMISSION_HARD_DENIED;
             }
         }
 
         if (permissionInfo.isAppOp()) {
-            return checkAppOpPermission(context, permission, pid, uid, packageName, attributionTag,
-                    message, forDataDelivery);
+            return checkAppOpPermission(context, permission, attributionSource, message,
+                    forDataDelivery, fromDatasource);
         }
         if (permissionInfo.isRuntime()) {
-            return checkRuntimePermission(context, permission, pid, uid, packageName,
-                    attributionTag, message, forDataDelivery);
+            return checkRuntimePermission(context, permission, attributionSource, message,
+                    forDataDelivery, startDataDelivery, fromDatasource);
         }
-        return context.checkPermission(permission, pid, uid);
+
+        if (!fromDatasource && !checkPermission(context, permission, attributionSource.getUid(),
+                attributionSource.getRenouncedPermissions())) {
+            return PERMISSION_HARD_DENIED;
+        }
+
+        if (attributionSource.getNext() != null) {
+            return checkPermissionCommon(context, permission,
+                    attributionSource.getNext(), message, forDataDelivery,
+                    startDataDelivery, /*fromDatasource*/ false);
+        }
+
+        return PERMISSION_GRANTED;
     }
 
+    @PermissionResult
     private static int checkAppOpPermission(@NonNull Context context, @NonNull String permission,
-            int pid, int uid, @Nullable String packageName, @Nullable String attributionTag,
-            @Nullable String message, boolean forDataDelivery) {
-        final String op = AppOpsManager.permissionToOp(permission);
-        if (op == null || packageName == null) {
+            @NonNull AttributionSource attributionSource, @Nullable String message,
+            boolean forDataDelivery, boolean fromDatasource) {
+        final int op = AppOpsManager.permissionToOpCode(permission);
+        if (op < 0 || attributionSource.getPackageName() == null) {
             return PERMISSION_HARD_DENIED;
         }
 
         final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
-        final int opMode = (forDataDelivery)
-                ? appOpsManager.noteProxyOpNoThrow(op, packageName, uid, attributionTag, message)
-                : appOpsManager.unsafeCheckOpRawNoThrow(op, uid, packageName);
 
-        switch (opMode) {
-            case AppOpsManager.MODE_ALLOWED:
-            case AppOpsManager.MODE_FOREGROUND: {
-                return PERMISSION_GRANTED;
-            }
-            case AppOpsManager.MODE_DEFAULT: {
-                return context.checkPermission(permission, pid, uid)
-                            == PackageManager.PERMISSION_GRANTED
-                        ? PERMISSION_GRANTED : PERMISSION_HARD_DENIED;
-            }
-            default: {
+        AttributionSource current = attributionSource;
+        AttributionSource next = null;
+
+        while (true) {
+            final boolean skipCurrentChecks = (fromDatasource || next != null);
+
+            next = current.getNext();
+
+            // If the call is from a datasource we need to vet only the chain before it. This
+            // way we can avoid the datasource creating an attribution context for every call.
+            if ((!fromDatasource || current != attributionSource)
+                    && next != null && !current.isTrusted(context)) {
                 return PERMISSION_HARD_DENIED;
             }
+
+            int opMode;
+            if (forDataDelivery) {
+                if (next == null) {
+                    opMode = appOpsManager.noteOpNoThrow(op, current.getUid(),
+                            current.getPackageName(), current.getAttributionTag(), message);
+                } else {
+                    opMode = appOpsManager.noteProxyOpNoThrow(op, current, message,
+                            skipCurrentChecks);
+                }
+            } else {
+                opMode = appOpsManager.unsafeCheckOpRawNoThrow(op, current.getUid(),
+                        current.getPackageName());
+                if (next != null && opMode == AppOpsManager.MODE_ALLOWED) {
+                    opMode = appOpsManager.unsafeCheckOpRawNoThrow(op, next.getUid(),
+                            next.getPackageName());
+                }
+            }
+
+            switch (opMode) {
+                case AppOpsManager.MODE_IGNORED:
+                case AppOpsManager.MODE_ERRORED: {
+                    return PERMISSION_HARD_DENIED;
+                }
+                case AppOpsManager.MODE_DEFAULT: {
+                    if (!skipCurrentChecks && !checkPermission(context, permission,
+                            attributionSource.getUid(), attributionSource
+                                    .getRenouncedPermissions())) {
+                        return PERMISSION_HARD_DENIED;
+                    }
+                    if (next != null && !checkPermission(context, permission,
+                            next.getUid(), next.getRenouncedPermissions())) {
+                        return PERMISSION_HARD_DENIED;
+                    }
+                }
+            }
+
+            if (next == null || next.getNext() == null) {
+                return PERMISSION_GRANTED;
+            }
+
+            current = next;
         }
     }
 
     private static int checkRuntimePermission(@NonNull Context context, @NonNull String permission,
-            int pid, int uid, @Nullable String packageName, @Nullable String attributionTag,
-            @Nullable String message, boolean forDataDelivery) {
-        if (context.checkPermission(permission, pid, uid) == PackageManager.PERMISSION_DENIED) {
+            @NonNull AttributionSource attributionSource, @Nullable String message,
+            boolean forDataDelivery, boolean startDataDelivery, boolean fromDatasource) {
+        // Now let's check the identity chain...
+        final int op = AppOpsManager.permissionToOpCode(permission);
+
+        AttributionSource current = attributionSource;
+        AttributionSource next = null;
+
+        while (true) {
+            final boolean skipCurrentChecks = (fromDatasource || next != null);
+            next = current.getNext();
+
+            // If the call is from a datasource we need to vet only the chain before it. This
+            // way we can avoid the datasource creating an attribution context for every call.
+            if ((!fromDatasource || current != attributionSource)
+                    && next != null && !current.isTrusted(context)) {
+                return PERMISSION_HARD_DENIED;
+            }
+
+            // If we already checked the permission for this one, skip the work
+            if (!skipCurrentChecks && !checkPermission(context, permission,
+                    current.getUid(), current.getRenouncedPermissions())) {
+                return PERMISSION_HARD_DENIED;
+            }
+
+            if (next != null && !checkPermission(context, permission,
+                    next.getUid(), next.getRenouncedPermissions())) {
+                return PERMISSION_HARD_DENIED;
+            }
+
+            if (op < 0) {
+                continue;
+            }
+
+            // The access is for oneself if this is the single receiver of data
+            // after the data source or if this is the single attribution source
+            // in the chain if not from a datasource.
+            final boolean singleReceiverFromDatasource = (fromDatasource
+                    && current == attributionSource && next != null && next.getNext() == null);
+            final boolean selfAccess = singleReceiverFromDatasource || next == null;
+
+            final int opMode = performOpTransaction(context, op, current, message,
+                    forDataDelivery, startDataDelivery, skipCurrentChecks, selfAccess,
+                    singleReceiverFromDatasource);
+
+            switch (opMode) {
+                case AppOpsManager.MODE_ERRORED: {
+                    return PERMISSION_HARD_DENIED;
+                }
+                case AppOpsManager.MODE_IGNORED: {
+                    return PERMISSION_SOFT_DENIED;
+                }
+            }
+
+            if (next == null || next.getNext() == null) {
+                return PERMISSION_GRANTED;
+            }
+
+            current = next;
+        }
+    }
+
+    private static boolean checkPermission(@NonNull Context context, @NonNull String permission,
+            int uid, @NonNull Set<String> renouncedPermissions) {
+        final boolean permissionGranted = context.checkPermission(permission, /*pid*/ -1,
+                uid) == PackageManager.PERMISSION_GRANTED;
+        if (permissionGranted && renouncedPermissions.contains(permission)) {
+            return false;
+        }
+        return permissionGranted;
+    }
+
+    private static int checkOp(@NonNull Context context, @NonNull int op,
+            @NonNull AttributionSource attributionSource, @Nullable String message,
+            boolean forDataDelivery, boolean startDataDelivery) {
+        if (op < 0 || attributionSource.getPackageName() == null) {
             return PERMISSION_HARD_DENIED;
         }
 
-        final String op = AppOpsManager.permissionToOp(permission);
-        if (op == null || packageName == null) {
-            return PERMISSION_GRANTED;
-        }
+        AttributionSource current = attributionSource;
+        AttributionSource next = null;
 
-        final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
-        final int opMode = (forDataDelivery)
-                ? appOpsManager.noteProxyOpNoThrow(op, packageName, uid, attributionTag, message)
-                : appOpsManager.unsafeCheckOpRawNoThrow(op, uid, packageName);
+        while (true) {
+            final boolean skipCurrentChecks = (next != null);
+            next = current.getNext();
 
-        switch (opMode) {
-            case AppOpsManager.MODE_ALLOWED:
-            case AppOpsManager.MODE_FOREGROUND:
+            // If the call is from a datasource we need to vet only the chain before it. This
+            // way we can avoid the datasource creating an attribution context for every call.
+            if (next != null && !current.isTrusted(context)) {
+                return PERMISSION_HARD_DENIED;
+            }
+
+            // The access is for oneself if this is the single attribution source in the chain.
+            final boolean selfAccess = (next == null);
+
+            final int opMode = performOpTransaction(context, op, current, message,
+                    forDataDelivery, startDataDelivery, skipCurrentChecks, selfAccess,
+                    /*fromDatasource*/ false);
+
+            switch (opMode) {
+                case AppOpsManager.MODE_ERRORED: {
+                    return PERMISSION_HARD_DENIED;
+                }
+                case AppOpsManager.MODE_IGNORED: {
+                    return PERMISSION_SOFT_DENIED;
+                }
+            }
+
+            if (next == null || next.getNext() == null) {
                 return PERMISSION_GRANTED;
-            default:
-                return PERMISSION_SOFT_DENIED;
+            }
+
+            current = next;
         }
     }
+    // If from data source and there is next app after that we need to note SELF of (noteOp) for the app vs proxy
+    private static int performOpTransaction(@NonNull Context context, int op,
+            @NonNull AttributionSource attributionSource, @Nullable String message,
+            boolean forDataDelivery, boolean startDataDelivery, boolean skipProxyOperation,
+            boolean selfAccess, boolean singleReceiverFromDatasource) {
+        // We cannot perform app ops transactions without a package name. In all relevant
+        // places we pass the package name but just in case there is a bug somewhere we
+        // do a best effort to resolve the package from the UID (pick first without a loss
+        // of generality - they are in the same security sandbox).
+        final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
+        if (!forDataDelivery) {
+            final String resolvedPackageName = resolvePackageName(context, attributionSource);
+            if (resolvedPackageName == null) {
+                return AppOpsManager.MODE_ERRORED;
+            }
+            final int opMode = appOpsManager.unsafeCheckOpRawNoThrow(op,
+                    attributionSource.getUid(), resolvedPackageName);
+            final AttributionSource previous = attributionSource.getNext();
+            if (opMode == AppOpsManager.MODE_ALLOWED && previous != null) {
+                final String resolvedPreviousPackageName = resolvePackageName(context,
+                        previous);
+                if (resolvedPreviousPackageName == null) {
+                    return AppOpsManager.MODE_ERRORED;
+                }
+                return appOpsManager.unsafeCheckOpRawNoThrow(op, previous.getUid(),
+                        resolvedPreviousPackageName);
+            }
+            return opMode;
+        } else if (startDataDelivery) {
+            final AttributionSource accessorSource = (!singleReceiverFromDatasource)
+                    ? attributionSource : attributionSource.getNext();
+            final AttributionSource resolvedAttributionSource = resolveAttributionSource(
+                    context, accessorSource);
+            if (resolvedAttributionSource.getPackageName() == null) {
+                return AppOpsManager.MODE_ERRORED;
+            }
+            if (selfAccess) {
+                return appOpsManager.startOpNoThrow(op, resolvedAttributionSource.getUid(),
+                        resolvedAttributionSource.getPackageName(),
+                        /*startIfModeDefault*/ false,
+                        resolvedAttributionSource.getAttributionTag(),
+                        message);
+            } else {
+                return appOpsManager.startProxyOpNoThrow(op, resolvedAttributionSource, message,
+                        skipProxyOperation);
+            }
+        } else {
+            final AttributionSource accessorSource = (!singleReceiverFromDatasource)
+                    ? attributionSource : attributionSource.getNext();
+            final AttributionSource resolvedAttributionSource = resolveAttributionSource(
+                    context, accessorSource);
+            if (resolvedAttributionSource.getPackageName() == null) {
+                return AppOpsManager.MODE_ERRORED;
+            }
+            if (selfAccess) {
+                return appOpsManager.noteOpNoThrow(op, resolvedAttributionSource.getUid(),
+                        resolvedAttributionSource.getPackageName(),
+                        resolvedAttributionSource.getAttributionTag(),
+                        message);
+            } else {
+                return appOpsManager.noteProxyOpNoThrow(op, resolvedAttributionSource, message,
+                        skipProxyOperation);
+            }
+        }
+    }
+
+    private static @Nullable String resolvePackageName(@NonNull Context context,
+            @NonNull AttributionSource attributionSource) {
+        if (attributionSource.getPackageName() != null) {
+            return attributionSource.getPackageName();
+        }
+        final String[] packageNames = context.getPackageManager().getPackagesForUid(
+                attributionSource.getUid());
+        if (packageNames != null) {
+            // This is best effort if the caller doesn't pass a package. The security
+            // sandbox is UID, therefore we pick an arbitrary package.
+            return packageNames[0];
+        }
+        return null;
+    }
+
+    private static @NonNull AttributionSource resolveAttributionSource(
+            @NonNull Context context, @NonNull AttributionSource attributionSource) {
+        if (attributionSource.getPackageName() != null) {
+            return attributionSource;
+        }
+        return new AttributionSource(attributionSource.getUid(),
+                resolvePackageName(context, attributionSource),
+                attributionSource.getAttributionTag(),
+                attributionSource.getToken(),
+                attributionSource.getRenouncedPermissions(),
+                attributionSource.getNext());
+    }
 }
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index 921c630..cdd8265 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -34,6 +34,7 @@
 import android.util.Xml;
 
 import com.android.internal.R;
+import com.android.internal.graphics.ColorUtils;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.GrowingArrayUtils;
 
@@ -112,6 +113,18 @@
  *         android:color="?android:attr/colorAccent"
  *         android:alpha="0.5" /&gt;
  * </pre>
+ * <p>
+ * Starting with API 31, items may optionally define an {@link android.R.attr#lStar android:lStar}
+ * attribute to modify the base color's perceptual luminance. This attribute takes a either
+ * floating-point value between 0 and 100 or a theme attribute that resolves as such. The item's
+ * overall color is calculated by converting the base color to an accessibility friendly color space
+ * and setting its L* to the value specified on the {@code lStar} attribute. For
+ * example, the following item represents the theme's accent color at 50% perpectual luminosity:
+ * <pre>
+ * &lt;item android:state_enabled="false"
+ *         android:color="?android:attr/colorAccent"
+ *         android:lStar="50" /&gt;
+ * </pre>
  *
  * <a name="DeveloperGuide"></a>
  * <h3>Developer guide</h3>
@@ -122,6 +135,7 @@
  *
  * @attr ref android.R.styleable#ColorStateListItem_alpha
  * @attr ref android.R.styleable#ColorStateListItem_color
+ * @attr ref android.R.styleable#ColorStateListItem_lStar
  */
 public class ColorStateList extends ComplexColor implements Parcelable {
     private static final String TAG = "ColorStateList";
@@ -301,6 +315,24 @@
     }
 
     /**
+     * Creates a new ColorStateList that has the same states and colors as this
+     * one but where each color has the specified perceived luminosity value (0-100).
+     *
+     * @param lStar Target perceptual luminance (0-100).
+     * @return A new color state list.
+     */
+    @NonNull
+    public ColorStateList withLStar(float lStar) {
+        final int[] colors = new int[mColors.length];
+        final int len = colors.length;
+        for (int i = 0; i < len; i++) {
+            colors[i] = modulateColor(mColors[i], 1.0f /* alphaMod */, lStar);
+        }
+
+        return new ColorStateList(mStateSpecs, colors);
+    }
+
+    /**
      * Fill in this object based on the contents of an XML "selector" element.
      */
     private void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
@@ -332,6 +364,7 @@
             final int[] themeAttrs = a.extractThemeAttrs();
             final int baseColor = a.getColor(R.styleable.ColorStateListItem_color, Color.MAGENTA);
             final float alphaMod = a.getFloat(R.styleable.ColorStateListItem_alpha, 1.0f);
+            final float lStar = a.getFloat(R.styleable.ColorStateListItem_lStar, -1.0f);
 
             changingConfigurations |= a.getChangingConfigurations();
 
@@ -346,6 +379,7 @@
                 switch (stateResId) {
                     case R.attr.color:
                     case R.attr.alpha:
+                    case R.attr.lStar:
                         // Recognized attribute, ignore.
                         break;
                     default:
@@ -355,10 +389,11 @@
             }
             stateSpec = StateSet.trimStateSet(stateSpec, j);
 
-            // Apply alpha modulation. If we couldn't resolve the color or
+            // Apply alpha and luma modulation. If we couldn't resolve the color or
             // alpha yet, the default values leave us enough information to
             // modulate again during applyTheme().
-            final int color = modulateColorAlpha(baseColor, alphaMod);
+            final int color = modulateColor(baseColor, alphaMod, lStar);
+
             if (listSize == 0 || stateSpec.length == 0) {
                 defaultColor = color;
             }
@@ -455,7 +490,9 @@
                         R.styleable.ColorStateListItem_color, mColors[i]);
                 final float alphaMod = a.getFloat(
                         R.styleable.ColorStateListItem_alpha, defaultAlphaMod);
-                mColors[i] = modulateColorAlpha(baseColor, alphaMod);
+                final float lStar = a.getFloat(
+                        R.styleable.ColorStateListItem_lStar, -1.0f);
+                mColors[i] = modulateColor(baseColor, alphaMod, lStar);
 
                 // Account for any configuration changes.
                 mChangingConfigurations |= a.getChangingConfigurations();
@@ -505,13 +542,21 @@
         return super.getChangingConfigurations() | mChangingConfigurations;
     }
 
-    private int modulateColorAlpha(int baseColor, float alphaMod) {
-        if (alphaMod == 1.0f) {
+    private int modulateColor(int baseColor, float alphaMod, float lStar) {
+        final boolean validLStar = lStar >= 0.0f && lStar <= 100.0f;
+        if (alphaMod == 1.0f && !validLStar) {
             return baseColor;
         }
 
         final int baseAlpha = Color.alpha(baseColor);
         final int alpha = MathUtils.constrain((int) (baseAlpha * alphaMod + 0.5f), 0, 255);
+
+        if (validLStar) {
+            final double[] labColor = new double[3];
+            ColorUtils.colorToLAB(baseColor, labColor);
+            baseColor = ColorUtils.LABToColor(lStar, labColor[1], labColor[2]);
+        }
+
         return (baseColor & 0xFFFFFF) | (alpha << 24);
     }
 
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 2430c09..216e7b0 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -17,6 +17,7 @@
 package android.hardware.display;
 
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.HdrCapabilities.HdrType;
 
 import android.Manifest;
 import android.annotation.FloatRange;
@@ -710,6 +711,55 @@
     }
 
     /**
+     * Sets the HDR types that have been disabled by user.
+     * @param userDisabledTypes the HDR types to disable.
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
+    public void setUserDisabledHdrTypes(@NonNull @HdrType int[] userDisabledTypes) {
+        mGlobal.setUserDisabledHdrTypes(userDisabledTypes);
+    }
+
+    /**
+     * Sets whether or not the user disabled HDR types are returned from
+     * {@link Display#getHdrCapabilities}.
+     *
+     * @param areUserDisabledHdrTypesAllowed If true, the user-disabled types
+     * are ignored and returned, if the display supports them. If false, the
+     * user-disabled types are taken into consideration and are never returned,
+     * even if the display supports them.
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
+    public void setAreUserDisabledHdrTypesAllowed(boolean areUserDisabledHdrTypesAllowed) {
+        mGlobal.setAreUserDisabledHdrTypesAllowed(areUserDisabledHdrTypesAllowed);
+    }
+
+    /**
+     * Returns whether or not the user-disabled HDR types are returned from
+     * {@link Display#getHdrCapabilities}.
+     *
+     * @hide
+     */
+    @TestApi
+    public boolean areUserDisabledHdrTypesAllowed() {
+        return mGlobal.areUserDisabledHdrTypesAllowed();
+    }
+
+    /**
+     * Returns the HDR formats disabled by the user.
+     *
+     * @hide
+     */
+    @TestApi
+    public @NonNull int[] getUserDisabledHdrTypes() {
+        return mGlobal.getUserDisabledHdrTypes();
+    }
+
+
+    /**
      * Creates a virtual display.
      *
      * @see #createVirtualDisplay(String, int, int, int, Surface, int,
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 06efc4f..cdc219a 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -16,7 +16,9 @@
 
 package android.hardware.display;
 
+
 import static android.hardware.display.DisplayManager.EventsMask;
+import static android.view.Display.HdrCapabilities.HdrType;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -508,6 +510,59 @@
         }
     }
 
+    /**
+     * Sets the HDR types that have been disabled by user.
+     * @param userDisabledHdrTypes the HDR types to disable. The HDR types are any of
+     */
+    public void setUserDisabledHdrTypes(@HdrType int[] userDisabledHdrTypes) {
+        try {
+            mDm.setUserDisabledHdrTypes(userDisabledHdrTypes);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Sets whether or not the user disabled HDR types are returned from
+     * {@link Display#getHdrCapabilities}.
+     *
+     * @param areUserDisabledHdrTypesAllowed If true, the user-disabled
+     * types are ignored and returned, if the display supports them. If
+     * false, the user-disabled types are taken into consideration and
+     * are never returned, even if the display supports them.
+     */
+    public void setAreUserDisabledHdrTypesAllowed(boolean areUserDisabledHdrTypesAllowed) {
+        try {
+            mDm.setAreUserDisabledHdrTypesAllowed(areUserDisabledHdrTypesAllowed);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns whether or not the user-disabled HDR types are returned from
+     * {@link Display#getHdrCapabilities}.
+     */
+    public boolean areUserDisabledHdrTypesAllowed() {
+        try {
+            return mDm.areUserDisabledHdrTypesAllowed();
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns the HDR formats disabled by the user.
+     *
+     */
+    public int[] getUserDisabledHdrTypes() {
+        try {
+            return mDm.getUserDisabledHdrTypes();
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
     public void requestColorMode(int displayId, int colorMode) {
         try {
             mDm.requestColorMode(displayId, colorMode);
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index 3538ff1..5ca4e0c 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -68,6 +68,18 @@
     // No permissions required.
     WifiDisplayStatus getWifiDisplayStatus();
 
+    // Requires WRITE_SECURE_SETTINGS permission.
+    void setUserDisabledHdrTypes(in int[] userDisabledTypes);
+
+    // Requires WRITE_SECURE_SETTINGS permission.
+    void setAreUserDisabledHdrTypesAllowed(boolean areUserDisabledHdrTypesAllowed);
+
+    // No permissions required.
+    boolean areUserDisabledHdrTypesAllowed();
+
+    // No permissions required.
+    int[] getUserDisabledHdrTypes();
+
     // Requires CONFIGURE_DISPLAY_COLOR_MODE
     void requestColorMode(int displayId, int colorMode);
 
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index b202420..9a8cd79 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -18,8 +18,6 @@
 
 import static android.app.ActivityManager.procStateToString;
 import static android.content.pm.PackageManager.GET_SIGNATURES;
-import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_MASK;
-import static android.net.ConnectivityManager.BLOCKED_REASON_NONE;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -787,36 +785,6 @@
     }
 
     /**
-     * Returns whether network access of an UID is blocked or not based on {@code blockedReasons}
-     * corresponding to it.
-     *
-     * {@code blockedReasons} would be a bitwise {@code OR} combination of the
-     * {@code BLOCKED_REASON_*} and/or {@code BLOCKED_METERED_REASON_*} constants.
-     *
-     * @param blockedReasons Value indicating the reasons for why the network access of an UID is
-     *                       blocked. If the value is equal to
-     *                       {@link ConnectivityManager#BLOCKED_REASON_NONE}, then
-     *                       it indicates that an app's network access is not blocked.
-     * @param meteredNetwork Value indicating whether the network is metered or not.
-     * @return Whether network access is blocked or not.
-     * @hide
-     */
-    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
-    public static boolean isUidBlocked(int blockedReasons, boolean meteredNetwork) {
-        if (blockedReasons == BLOCKED_REASON_NONE) {
-            return false;
-        }
-        final int blockedOnAllNetworksReason = (blockedReasons & ~BLOCKED_METERED_REASON_MASK);
-        if (blockedOnAllNetworksReason != BLOCKED_REASON_NONE) {
-            return true;
-        }
-        if (meteredNetwork) {
-            return blockedReasons != BLOCKED_REASON_NONE;
-        }
-        return false;
-    }
-
-    /**
      * Returns the {@code string} representation of {@code blockedReasons} argument.
      *
      * @param blockedReasons Value indicating the reasons for why the network access of an UID is
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
index bc3d5c4..11445e9 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -72,7 +72,7 @@
     boolean deviceSupportsNfcSecure();
     boolean setNfcSecure(boolean enable);
 
-    boolean setAlwaysOn(boolean value);
-    boolean isAlwaysOnEnabled();
-    boolean isAlwaysOnSupported();
+    boolean setControllerAlwaysOn(boolean value);
+    boolean isControllerAlwaysOn();
+    boolean isControllerAlwaysOnSupported();
 }
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index e85eb93..eed2c77 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -2254,13 +2254,13 @@
      * @hide
      */
     @SystemApi
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public boolean setAlwaysOn(boolean value) {
+    @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON)
+    public boolean setControllerAlwaysOn(boolean value) {
         if (!sHasNfcFeature) {
             throw new UnsupportedOperationException();
         }
         try {
-            return sService.setAlwaysOn(value);
+            return sService.setControllerAlwaysOn(value);
         } catch (RemoteException e) {
             attemptDeadServiceRecovery(e);
             // Try one more time
@@ -2269,7 +2269,7 @@
                 return false;
             }
             try {
-                return sService.setAlwaysOn(value);
+                return sService.setControllerAlwaysOn(value);
             } catch (RemoteException ee) {
                 Log.e(TAG, "Failed to recover NFC Service.");
             }
@@ -2286,10 +2286,10 @@
      */
 
     @SystemApi
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public boolean isAlwaysOnEnabled() {
+    @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON)
+    public boolean isControllerAlwaysOn() {
         try {
-            return sService.isAlwaysOnEnabled();
+            return sService.isControllerAlwaysOn();
         } catch (RemoteException e) {
             attemptDeadServiceRecovery(e);
             // Try one more time
@@ -2298,7 +2298,7 @@
                 return false;
             }
             try {
-                return sService.isAlwaysOnEnabled();
+                return sService.isControllerAlwaysOn();
             } catch (RemoteException ee) {
                 Log.e(TAG, "Failed to recover NFC Service.");
             }
@@ -2315,13 +2315,13 @@
      */
 
     @SystemApi
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public boolean isAlwaysOnSupported() {
+    @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON)
+    public boolean isControllerAlwaysOnSupported() {
         if (!sHasNfcFeature) {
             throw new UnsupportedOperationException();
         }
         try {
-            return sService.isAlwaysOnSupported();
+            return sService.isControllerAlwaysOnSupported();
         } catch (RemoteException e) {
             attemptDeadServiceRecovery(e);
             // Try one more time
@@ -2330,7 +2330,7 @@
                 return false;
             }
             try {
-                return sService.isAlwaysOnSupported();
+                return sService.isControllerAlwaysOnSupported();
             } catch (RemoteException ee) {
                 Log.e(TAG, "Failed to recover NFC Service.");
             }
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index ae7d94c..425e797 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -27,9 +27,9 @@
 interface IPowerManager
 {
     void acquireWakeLock(IBinder lock, int flags, String tag, String packageName, in WorkSource ws,
-            String historyTag);
+            String historyTag, int displayId);
     void acquireWakeLockWithUid(IBinder lock, int flags, String tag, String packageName,
-            int uidtoblame);
+            int uidtoblame, int displayId);
     @UnsupportedAppUsage
     void releaseWakeLock(IBinder lock, int flags);
     void updateWakeLockUids(IBinder lock, in int[] uids);
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 2c4d130..9d1fd50 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -36,6 +36,7 @@
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.proto.ProtoOutputStream;
+import android.view.Display;
 
 import com.android.internal.util.Preconditions;
 
@@ -1143,8 +1144,7 @@
      * wake lock, and {@link WakeLock#release release()} when you are done.
      * </p><p>
      * {@samplecode
-     * PowerManager pm = (PowerManager)mContext.getSystemService(
-     *                                          Context.POWER_SERVICE);
+     * PowerManager pm = mContext.getSystemService(PowerManager.class);
      * PowerManager.WakeLock wl = pm.newWakeLock(
      *                                      PowerManager.SCREEN_DIM_WAKE_LOCK
      *                                      | PowerManager.ON_AFTER_RELEASE,
@@ -1162,6 +1162,8 @@
      * {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead.
      * This window flag will be correctly managed by the platform
      * as the user moves between applications and doesn't require a special permission.
+     * Additionally using the flag will keep only the appropriate screen on in a
+     * multi-display scenario while using a wake lock will keep every screen powered on.
      * </p>
      *
      * <p>
@@ -1179,7 +1181,7 @@
      * can be transformed by java optimizer and obfuscator tools.
      * <li>avoid wrapping the tag or a prefix to avoid collision with wake lock
      * tags from the platform (e.g. *alarm*).
-     * <li>never include personnally identifiable information for privacy
+     * <li>never include personally identifiable information for privacy
      * reasons.
      * </ul>
      * </p>
@@ -1200,7 +1202,27 @@
      */
     public WakeLock newWakeLock(int levelAndFlags, String tag) {
         validateWakeLockParameters(levelAndFlags, tag);
-        return new WakeLock(levelAndFlags, tag, mContext.getOpPackageName());
+        return new WakeLock(levelAndFlags, tag, mContext.getOpPackageName(),
+                Display.INVALID_DISPLAY);
+    }
+
+    /**
+     * Creates a new wake lock with the specified level and flags.
+     * <p>
+     * The wakelock will only apply to the {@link com.android.server.display.DisplayGroup} of the
+     * provided {@code displayId}. If {@code displayId} is {@link Display#INVALID_DISPLAY} then it
+     * will apply to all {@link com.android.server.display.DisplayGroup DisplayGroups}.
+     *
+     * @param levelAndFlags Combination of wake lock level and flag values defining
+     * the requested behavior of the WakeLock.
+     * @param tag Your class name (or other tag) for debugging purposes.
+     * @param displayId The display id to which this wake lock is tied.
+     *
+     * @hide
+     */
+    public WakeLock newWakeLock(int levelAndFlags, String tag, int displayId) {
+        validateWakeLockParameters(levelAndFlags, tag);
+        return new WakeLock(levelAndFlags, tag, mContext.getOpPackageName(), displayId);
     }
 
     /** @hide */
@@ -2603,19 +2625,17 @@
         private WorkSource mWorkSource;
         private String mHistoryTag;
         private final String mTraceName;
+        private final int mDisplayId;
 
-        private final Runnable mReleaser = new Runnable() {
-            public void run() {
-                release(RELEASE_FLAG_TIMEOUT);
-            }
-        };
+        private final Runnable mReleaser = () -> release(RELEASE_FLAG_TIMEOUT);
 
-        WakeLock(int flags, String tag, String packageName) {
+        WakeLock(int flags, String tag, String packageName, int displayId) {
             mFlags = flags;
             mTag = tag;
             mPackageName = packageName;
             mToken = new Binder();
             mTraceName = "WakeLock (" + mTag + ")";
+            mDisplayId = displayId;
         }
 
         @Override
@@ -2696,7 +2716,7 @@
                 Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, mTraceName, 0);
                 try {
                     mService.acquireWakeLock(mToken, mFlags, mTag, mPackageName, mWorkSource,
-                            mHistoryTag);
+                            mHistoryTag, mDisplayId);
                 } catch (RemoteException e) {
                     throw e.rethrowFromSystemServer();
                 }
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index bf859d4..f9e4f73 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -131,6 +131,7 @@
      * @hide
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+    @TestApi
     public static final int NFC_UID = 1027;
 
     /**
diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl
index 8c105be..ef075e1 100644
--- a/core/java/android/permission/IPermissionManager.aidl
+++ b/core/java/android/permission/IPermissionManager.aidl
@@ -16,6 +16,7 @@
 
 package android.permission;
 
+import android.content.AttributionSource;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
@@ -85,4 +86,8 @@
     boolean setAutoRevokeExempted(String packageName, boolean exempted, int userId);
 
     boolean isAutoRevokeExempted(String packageName, int userId);
+
+    AttributionSource registerAttributionSource(in AttributionSource source);
+
+    boolean isRegisteredAttributionSource(in AttributionSource source);
 }
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index baa25f0..936cbfc 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -44,6 +44,7 @@
 import android.content.pm.permission.SplitPermissionInfoParcelable;
 import android.location.LocationManager;
 import android.media.AudioManager;
+import android.content.AttributionSource;
 import android.os.Build;
 import android.os.Handler;
 import android.os.Looper;
@@ -1099,6 +1100,48 @@
                 callingFeatureId, pid, uid);
     }
 
+    /**
+     * Registers an attribution source with the OS. An app can only register an attribution
+     * source for itself. Once an attribution source has been registered another app can
+     * check whether this registration exists and thus trust the payload in the source
+     * object. This is important for permission checking and specifically for app op blaming
+     * since a malicious app should not be able to force the OS to blame another app
+     * that doesn't participate in an attribution chain.
+     *
+     * @param source The attribution source to register.
+     *
+     * @see #isRegisteredAttributionSource(AttributionSource)
+     *
+     * @hide
+     */
+    public @NonNull AttributionSource registerAttributionSource(@NonNull AttributionSource source) {
+        try {
+            return mPermissionManager.registerAttributionSource(source);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+        return null;
+    }
+
+    /**
+     * Checks whether an attribution source is registered.
+     *
+     * @param source The attribution source to check.
+     * @return Whether this is a registered source.
+     *
+     * @see #registerAttributionSource(AttributionSource)
+     *
+     * @hide
+     */
+    public boolean isRegisteredAttributionSource(@NonNull AttributionSource source) {
+        try {
+            return mPermissionManager.isRegisteredAttributionSource(source);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+        return false;
+    }
+
     /* @hide */
     private static int checkPermissionUncached(@Nullable String permission, int pid, int uid) {
         final IActivityManager am = ActivityManager.getService();
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index b704d66..a5a24c0 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -1102,8 +1102,7 @@
             // signed with platform signature can hold MANAGE_DOCUMENTS, we are going to check for
             // MANAGE_DOCUMENTS or associated URI permission here instead
             final Uri rootUri = extraUri;
-            enforceWritePermissionInner(rootUri, getCallingPackage(), getCallingAttributionTag(),
-                    null);
+            enforceWritePermissionInner(rootUri, getCallingAttributionSource());
 
             final String rootId = DocumentsContract.getRootId(rootUri);
             ejectRoot(rootId);
@@ -1121,8 +1120,7 @@
         }
 
         if (METHOD_IS_CHILD_DOCUMENT.equals(method)) {
-            enforceReadPermissionInner(documentUri, getCallingPackage(),
-                    getCallingAttributionTag(), null);
+            enforceReadPermissionInner(documentUri, getCallingAttributionSource());
 
             final Uri childUri = extraTargetUri;
             final String childAuthority = childUri.getAuthority();
@@ -1134,8 +1132,7 @@
                             && isChildDocument(documentId, childId));
 
         } else if (METHOD_CREATE_DOCUMENT.equals(method)) {
-            enforceWritePermissionInner(documentUri, getCallingPackage(),
-                    getCallingAttributionTag(), null);
+            enforceWritePermissionInner(documentUri, getCallingAttributionSource());
 
             final String mimeType = extras.getString(Document.COLUMN_MIME_TYPE);
             final String displayName = extras.getString(Document.COLUMN_DISPLAY_NAME);
@@ -1149,8 +1146,7 @@
             out.putParcelable(DocumentsContract.EXTRA_URI, newDocumentUri);
 
         } else if (METHOD_CREATE_WEB_LINK_INTENT.equals(method)) {
-            enforceWritePermissionInner(documentUri, getCallingPackage(),
-                    getCallingAttributionTag(), null);
+            enforceWritePermissionInner(documentUri, getCallingAttributionSource());
 
             final Bundle options = extras.getBundle(DocumentsContract.EXTRA_OPTIONS);
             final IntentSender intentSender = createWebLinkIntent(documentId, options);
@@ -1158,8 +1154,7 @@
             out.putParcelable(DocumentsContract.EXTRA_RESULT, intentSender);
 
         } else if (METHOD_RENAME_DOCUMENT.equals(method)) {
-            enforceWritePermissionInner(documentUri, getCallingPackage(),
-                    getCallingAttributionTag(), null);
+            enforceWritePermissionInner(documentUri, getCallingAttributionSource());
 
             final String displayName = extras.getString(Document.COLUMN_DISPLAY_NAME);
             final String newDocumentId = renameDocument(documentId, displayName);
@@ -1183,8 +1178,7 @@
             }
 
         } else if (METHOD_DELETE_DOCUMENT.equals(method)) {
-            enforceWritePermissionInner(documentUri, getCallingPackage(),
-                    getCallingAttributionTag(), null);
+            enforceWritePermissionInner(documentUri, getCallingAttributionSource());
             deleteDocument(documentId);
 
             // Document no longer exists, clean up any grants.
@@ -1194,10 +1188,8 @@
             final Uri targetUri = extraTargetUri;
             final String targetId = DocumentsContract.getDocumentId(targetUri);
 
-            enforceReadPermissionInner(documentUri, getCallingPackage(),
-                    getCallingAttributionTag(), null);
-            enforceWritePermissionInner(targetUri, getCallingPackage(), getCallingAttributionTag(),
-                    null);
+            enforceReadPermissionInner(documentUri, getCallingAttributionSource());
+            enforceWritePermissionInner(targetUri, getCallingAttributionSource());
 
             final String newDocumentId = copyDocument(documentId, targetId);
 
@@ -1220,12 +1212,9 @@
             final Uri targetUri = extraTargetUri;
             final String targetId = DocumentsContract.getDocumentId(targetUri);
 
-            enforceWritePermissionInner(documentUri, getCallingPackage(),
-                    getCallingAttributionTag(), null);
-            enforceReadPermissionInner(parentSourceUri, getCallingPackage(),
-                    getCallingAttributionTag(), null);
-            enforceWritePermissionInner(targetUri, getCallingPackage(), getCallingAttributionTag(),
-                    null);
+            enforceWritePermissionInner(documentUri, getCallingAttributionSource());
+            enforceReadPermissionInner(parentSourceUri, getCallingAttributionSource());
+            enforceWritePermissionInner(targetUri, getCallingAttributionSource());
 
             final String newDocumentId = moveDocument(documentId, parentSourceId, targetId);
 
@@ -1246,10 +1235,8 @@
             final Uri parentSourceUri = extraParentUri;
             final String parentSourceId = DocumentsContract.getDocumentId(parentSourceUri);
 
-            enforceReadPermissionInner(parentSourceUri, getCallingPackage(),
-                    getCallingAttributionTag(), null);
-            enforceWritePermissionInner(documentUri, getCallingPackage(),
-                    getCallingAttributionTag(), null);
+            enforceReadPermissionInner(parentSourceUri, getCallingAttributionSource());
+            enforceWritePermissionInner(documentUri, getCallingAttributionSource());
             removeDocument(documentId, parentSourceId);
 
             // It's responsibility of the provider to revoke any grants, as the document may be
@@ -1258,8 +1245,7 @@
             final boolean isTreeUri = isTreeUri(documentUri);
 
             if (isTreeUri) {
-                enforceReadPermissionInner(documentUri, getCallingPackage(),
-                        getCallingAttributionTag(), null);
+                enforceReadPermissionInner(documentUri, getCallingAttributionSource());
             } else {
                 getContext().enforceCallingPermission(Manifest.permission.MANAGE_DOCUMENTS, null);
             }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 30d0423..16a8fa8 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2754,7 +2754,7 @@
                     arg.putBoolean(CALL_METHOD_OVERRIDEABLE_BY_RESTORE_KEY, true);
                 }
                 IContentProvider cp = mProviderHolder.getProvider(cr);
-                cp.call(cr.getPackageName(), cr.getAttributionTag(),
+                cp.call(cr.getAttributionSource(),
                         mProviderHolder.mUri.getAuthority(), mCallSetCommand, name, arg);
             } catch (RemoteException e) {
                 Log.w(TAG, "Can't set key " + name + " in " + mUri, e);
@@ -2774,7 +2774,7 @@
                 args.putString(CALL_METHOD_PREFIX_KEY, prefix);
                 args.putSerializable(CALL_METHOD_FLAGS_KEY, keyValues);
                 IContentProvider cp = mProviderHolder.getProvider(cr);
-                Bundle bundle = cp.call(cr.getPackageName(), cr.getAttributionTag(),
+                Bundle bundle = cp.call(cr.getAttributionSource(),
                         mProviderHolder.mUri.getAuthority(),
                         mCallSetAllCommand, null, args);
                 return bundle.getBoolean(KEY_CONFIG_SET_RETURN);
@@ -2862,14 +2862,14 @@
                     if (Settings.isInSystemServer() && Binder.getCallingUid() != Process.myUid()) {
                         final long token = Binder.clearCallingIdentity();
                         try {
-                            b = cp.call(cr.getPackageName(), cr.getAttributionTag(),
+                            b = cp.call(cr.getAttributionSource(),
                                     mProviderHolder.mUri.getAuthority(), mCallGetCommand, name,
                                     args);
                         } finally {
                             Binder.restoreCallingIdentity(token);
                         }
                     } else {
-                        b = cp.call(cr.getPackageName(), cr.getAttributionTag(),
+                        b = cp.call(cr.getAttributionSource(),
                                 mProviderHolder.mUri.getAuthority(), mCallGetCommand, name, args);
                     }
                     if (b != null) {
@@ -2939,13 +2939,13 @@
                 if (Settings.isInSystemServer() && Binder.getCallingUid() != Process.myUid()) {
                     final long token = Binder.clearCallingIdentity();
                     try {
-                        c = cp.query(cr.getPackageName(), cr.getAttributionTag(), mUri,
+                        c = cp.query(cr.getAttributionSource(), mUri,
                                 SELECT_VALUE_PROJECTION, queryArgs, null);
                     } finally {
                         Binder.restoreCallingIdentity(token);
                     }
                 } else {
-                    c = cp.query(cr.getPackageName(), cr.getAttributionTag(), mUri,
+                    c = cp.query(cr.getAttributionSource(), mUri,
                             SELECT_VALUE_PROJECTION, queryArgs, null);
                 }
                 if (c == null) {
@@ -3051,7 +3051,7 @@
                 }
 
                 // Fetch all flags for the namespace at once for caching purposes
-                Bundle b = cp.call(cr.getPackageName(), cr.getAttributionTag(),
+                Bundle b = cp.call(cr.getAttributionSource(),
                         mProviderHolder.mUri.getAuthority(), mCallListCommand, null, args);
                 if (b == null) {
                     // Invalid response, return an empty map
@@ -5877,7 +5877,7 @@
                 }
                 arg.putInt(CALL_METHOD_RESET_MODE_KEY, mode);
                 IContentProvider cp = sProviderHolder.getProvider(resolver);
-                cp.call(resolver.getPackageName(), resolver.getAttributionTag(),
+                cp.call(resolver.getAttributionSource(),
                         sProviderHolder.mUri.getAuthority(), CALL_METHOD_RESET_SECURE, null, arg);
             } catch (RemoteException e) {
                 Log.w(TAG, "Can't reset do defaults for " + CONTENT_URI, e);
@@ -9740,6 +9740,12 @@
                 "accessibility_magnification_mode";
 
         /**
+         * Magnification mode value that is a default value for the magnification logging feature.
+         * @hide
+         */
+        public static final int ACCESSIBILITY_MAGNIFICATION_MODE_NONE = 0x0;
+
+        /**
          * Magnification mode value that magnifies whole display.
          * @hide
          */
@@ -14056,6 +14062,40 @@
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
         public static final int ZEN_MODE_ALARMS = 3;
 
+        /**
+         * A comma-separated list of HDR formats that have been disabled by the user.
+         * <p>
+         * If present, these formats will not be reported to apps, even if the display supports
+         * them. This list is treated as empty if the ARE_USER_DISABLED_HDR_FORMATS_ALLOWED setting
+         * is '1'.
+         * </p>
+         * @hide
+         */
+        @TestApi
+        @Readable
+        @SuppressLint("NoSettingsProvider")
+        public static final String USER_DISABLED_HDR_FORMATS = "user_disabled_hdr_formats";
+
+        /**
+         * Whether or not user-disabled HDR formats are allowed.
+         * <p>
+         * The value is boolean (1 or 0). The value '1' means the user preference for disabling a
+         * format is ignored, and the disabled formats are still reported to apps (if supported
+         * by the display). The value '0' means the user-disabled formats are not reported to
+         * apps, even if the display supports them.
+         * </p><p>
+         * The list of formats disabled by the user are contained in the
+         * USER_DISABLED_HDR_FORMATS setting. This list is treated as empty when the value of
+         * this setting is '1'.
+         * </p>
+         * @hide
+         */
+        @TestApi
+        @Readable
+        @SuppressLint("NoSettingsProvider")
+        public static final String ARE_USER_DISABLED_HDR_FORMATS_ALLOWED =
+                "are_user_disabled_hdr_formats_allowed";
+
         /** @hide */ public static String zenModeToString(int mode) {
             if (mode == ZEN_MODE_IMPORTANT_INTERRUPTIONS) return "ZEN_MODE_IMPORTANT_INTERRUPTIONS";
             if (mode == ZEN_MODE_ALARMS) return "ZEN_MODE_ALARMS";
@@ -14880,7 +14920,7 @@
                 }
                 arg.putInt(CALL_METHOD_RESET_MODE_KEY, mode);
                 IContentProvider cp = sProviderHolder.getProvider(resolver);
-                cp.call(resolver.getPackageName(), resolver.getAttributionTag(),
+                cp.call(resolver.getAttributionSource(),
                         sProviderHolder.mUri.getAuthority(), CALL_METHOD_RESET_GLOBAL, null, arg);
             } catch (RemoteException e) {
                 Log.w(TAG, "Can't reset do defaults for " + CONTENT_URI, e);
@@ -16019,7 +16059,7 @@
                     arg.putString(Settings.CALL_METHOD_PREFIX_KEY, createPrefix(namespace));
                 }
                 IContentProvider cp = sProviderHolder.getProvider(resolver);
-                cp.call(resolver.getPackageName(), resolver.getAttributionTag(),
+                cp.call(resolver.getAttributionSource(),
                         sProviderHolder.mUri.getAuthority(), CALL_METHOD_RESET_CONFIG, null, arg);
             } catch (RemoteException e) {
                 Log.w(TAG, "Can't reset to defaults for " + DeviceConfig.CONTENT_URI, e);
@@ -16048,7 +16088,7 @@
                 arg.putInt(CALL_METHOD_USER_KEY, userHandle);
                 arg.putParcelable(CALL_METHOD_MONITOR_CALLBACK_KEY, callback);
                 IContentProvider cp = sProviderHolder.getProvider(resolver);
-                cp.call(resolver.getPackageName(), resolver.getAttributionTag(),
+                cp.call(resolver.getAttributionSource(),
                         sProviderHolder.mUri.getAuthority(),
                         CALL_METHOD_REGISTER_MONITOR_CALLBACK_CONFIG, null, arg);
             } catch (RemoteException e) {
diff --git a/core/java/android/provider/TEST_MAPPING b/core/java/android/provider/TEST_MAPPING
index ae2836f..c55572e 100644
--- a/core/java/android/provider/TEST_MAPPING
+++ b/core/java/android/provider/TEST_MAPPING
@@ -19,6 +19,14 @@
         },
         {
             "name": "SettingsProviderTest"
+        },
+        {
+            "name": "CtsAppSecurityHostTestCases",
+            "options": [
+                {
+                    "include-filter": "android.appsecurity.cts.ReadableSettingsFieldsTest"
+                }
+            ]
         }
     ]
 }
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index 73e0da1..8ca0e7c 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -48,6 +48,7 @@
 import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.os.SharedMemory;
+import android.service.voice.HotwordDetectionService.InitializationStatus;
 import android.util.Slog;
 
 import com.android.internal.app.IHotwordRecognitionStatusCallback;
@@ -260,6 +261,7 @@
     private static final int MSG_DETECTION_PAUSE = 4;
     private static final int MSG_DETECTION_RESUME = 5;
     private static final int MSG_HOTWORD_REJECTED = 6;
+    private static final int MSG_HOTWORD_STATUS_REPORTED = 7;
 
     private final String mText;
     private final Locale mLocale;
@@ -523,6 +525,15 @@
          */
         public void onRejected(@Nullable HotwordRejectedResult result) {
         }
+
+        /**
+         * Called when the {@link HotwordDetectionService} is created by the system and given a
+         * short amount of time to report it's initialization state.
+         *
+         * @param status Info about initialization state of {@link HotwordDetectionService}.
+         */
+        public void onHotwordDetectionServiceInitialized(@InitializationStatus int status) {
+        }
     }
 
     /**
@@ -559,7 +570,7 @@
         mTargetSdkVersion = targetSdkVersion;
         mSupportHotwordDetectionService = supportHotwordDetectionService;
         if (mSupportHotwordDetectionService) {
-            updateState(options, sharedMemory);
+            updateStateLocked(options, sharedMemory, mInternalCallback);
         }
         try {
             Identity identity = new Identity();
@@ -583,20 +594,34 @@
      * such data to the trusted process.
      *
      * @throws IllegalStateException if this AlwaysOnHotwordDetector wasn't specified to use a
-     * {@link HotwordDetectionService} when it was created.
+     * {@link HotwordDetectionService} when it was created. In addition, if this
+     * AlwaysOnHotwordDetector is in an invalid or error state.
      */
     public final void updateState(@Nullable PersistableBundle options,
             @Nullable SharedMemory sharedMemory) {
         if (DBG) {
             Slog.d(TAG, "updateState()");
         }
-        if (!mSupportHotwordDetectionService) {
-            throw new IllegalStateException(
-                    "updateState called, but it doesn't support hotword detection service");
+        synchronized (mLock) {
+            if (!mSupportHotwordDetectionService) {
+                throw new IllegalStateException(
+                        "updateState called, but it doesn't support hotword detection service");
+            }
+            if (mAvailability == STATE_INVALID || mAvailability == STATE_ERROR) {
+                throw new IllegalStateException(
+                        "updateState called on an invalid detector or error state");
+            }
+            updateStateLocked(options, sharedMemory, null /* callback */);
         }
+    }
 
+    private void updateStateLocked(@Nullable PersistableBundle options,
+            @Nullable SharedMemory sharedMemory, IHotwordRecognitionStatusCallback callback) {
+        if (DBG) {
+            Slog.d(TAG, "updateStateLocked()");
+        }
         try {
-            mModelManagementService.updateState(options, sharedMemory);
+            mModelManagementService.updateState(options, sharedMemory, callback);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1147,6 +1172,18 @@
             Slog.i(TAG, "onRecognitionResumed");
             mHandler.sendEmptyMessage(MSG_DETECTION_RESUME);
         }
+
+        @Override
+        public void onStatusReported(int status) {
+            if (DBG) {
+                Slog.d(TAG, "onStatusReported(" + status + ")");
+            } else {
+                Slog.i(TAG, "onStatusReported");
+            }
+            Message message = Message.obtain(mHandler, MSG_HOTWORD_STATUS_REPORTED);
+            message.arg1 = status;
+            message.sendToTarget();
+        }
     }
 
     class MyHandler extends Handler {
@@ -1178,6 +1215,9 @@
                 case MSG_HOTWORD_REJECTED:
                     mExternalCallback.onRejected((HotwordRejectedResult) msg.obj);
                     break;
+                case MSG_HOTWORD_STATUS_REPORTED:
+                    mExternalCallback.onHotwordDetectionServiceInitialized(msg.arg1);
+                    break;
                 default:
                     super.handleMessage(msg);
             }
diff --git a/core/java/android/service/voice/HotwordDetectionService.java b/core/java/android/service/voice/HotwordDetectionService.java
index fb731a0..7c14c2e 100644
--- a/core/java/android/service/voice/HotwordDetectionService.java
+++ b/core/java/android/service/voice/HotwordDetectionService.java
@@ -37,10 +37,13 @@
 import android.os.SharedMemory;
 import android.util.Log;
 
+import com.android.internal.app.IHotwordRecognitionStatusCallback;
+
 import java.lang.annotation.Documented;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Locale;
+import java.util.function.IntConsumer;
 
 /**
  * Implemented by an application that wants to offer detection for hotword. The system will
@@ -54,6 +57,39 @@
     // TODO (b/177502877): Set the Debug flag to false before shipping.
     private static final boolean DBG = true;
 
+    private static final long UPDATE_TIMEOUT_MILLIS = 5000;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(flag = true, prefix = { "INITIALIZATION_STATUS_" }, value = {
+            INITIALIZATION_STATUS_SUCCESS,
+            INITIALIZATION_STATUS_CUSTOM_ERROR_1,
+            INITIALIZATION_STATUS_CUSTOM_ERROR_2,
+            INITIALIZATION_STATUS_UNKNOWN,
+    })
+    public @interface InitializationStatus {}
+
+    /**
+     * Indicates that the updated status is successful.
+     */
+    public static final int INITIALIZATION_STATUS_SUCCESS = 0;
+
+    /**
+     * Indicates that the updated status is failure for some application specific reasons.
+     */
+    public static final int INITIALIZATION_STATUS_CUSTOM_ERROR_1 = 1;
+
+    /**
+     * Indicates that the updated status is failure for some application specific reasons.
+     */
+    public static final int INITIALIZATION_STATUS_CUSTOM_ERROR_2 = 2;
+
+    /**
+     * Indicates that the callback wasn’t invoked within the timeout.
+     * This is used by system.
+     */
+    public static final int INITIALIZATION_STATUS_UNKNOWN = 100;
+
     /**
      * Source for the given audio stream.
      *
@@ -104,15 +140,16 @@
         }
 
         @Override
-        public void updateState(PersistableBundle options, SharedMemory sharedMemory)
-                throws RemoteException {
+        public void updateState(PersistableBundle options, SharedMemory sharedMemory,
+                IHotwordRecognitionStatusCallback callback) throws RemoteException {
             if (DBG) {
                 Log.d(TAG, "#updateState");
             }
-            mHandler.sendMessage(obtainMessage(HotwordDetectionService::onUpdateState,
+            mHandler.sendMessage(obtainMessage(HotwordDetectionService::onUpdateStateInternal,
                     HotwordDetectionService.this,
                     options,
-                    sharedMemory));
+                    sharedMemory,
+                    callback));
         }
 
         @Override
@@ -207,12 +244,20 @@
      * @param sharedMemory The unrestricted data blob to provide to the
      * {@link HotwordDetectionService}. Use this to provide the hotword models data or other
      * such data to the trusted process.
+     * @param callbackTimeoutMillis Timeout in milliseconds for the operation to invoke the
+     * statusCallback.
+     * @param statusCallback Use this to return the updated result. This is non-null only when the
+     * {@link HotwordDetectionService} is being initialized; and it is null if the state is updated
+     * after that.
      *
      * @hide
      */
     @SystemApi
-    public void onUpdateState(@Nullable PersistableBundle options,
-            @Nullable SharedMemory sharedMemory) {
+    public void onUpdateState(
+            @Nullable PersistableBundle options,
+            @Nullable SharedMemory sharedMemory,
+            @DurationMillisLong long callbackTimeoutMillis,
+            @Nullable @InitializationStatus IntConsumer statusCallback) {
         // TODO: Handle the unimplemented case by throwing?
     }
 
@@ -268,6 +313,23 @@
         throw new UnsupportedOperationException();
     }
 
+    private void onUpdateStateInternal(@Nullable PersistableBundle options,
+            @Nullable SharedMemory sharedMemory, IHotwordRecognitionStatusCallback callback) {
+        // TODO (b/183684347): Implement timeout case.
+        IntConsumer intConsumer = null;
+        if (callback != null) {
+            intConsumer =
+                    value -> {
+                        try {
+                            callback.onStatusReported(value);
+                        } catch (RemoteException e) {
+                            throw e.rethrowFromSystemServer();
+                        }
+                    };
+        }
+        onUpdateState(options, sharedMemory, UPDATE_TIMEOUT_MILLIS, intConsumer);
+    }
+
     /**
      * Callback for returning the detection result.
      *
diff --git a/core/java/android/service/voice/HotwordDetector.java b/core/java/android/service/voice/HotwordDetector.java
index 2649124..f4e5dda 100644
--- a/core/java/android/service/voice/HotwordDetector.java
+++ b/core/java/android/service/voice/HotwordDetector.java
@@ -27,6 +27,7 @@
 import android.media.AudioFormat;
 import android.os.ParcelFileDescriptor;
 import android.os.PersistableBundle;
+import android.service.voice.HotwordDetectionService.InitializationStatus;
 
 /**
  * Basic functionality for hotword detectors.
@@ -144,5 +145,13 @@
          *         {@link HotwordDetectionService}.
          */
         void onRejected(@Nullable HotwordRejectedResult result);
+
+        /**
+         * Called when the {@link HotwordDetectionService} is created by the system and given a
+         * short amount of time to report it's initialization state.
+         *
+         * @param status Info about initialization state of {@link HotwordDetectionService}.
+         */
+        void onHotwordDetectionServiceInitialized(@InitializationStatus int status);
     }
 }
diff --git a/core/java/android/service/voice/IHotwordDetectionService.aidl b/core/java/android/service/voice/IHotwordDetectionService.aidl
index cb140f9..cac8333 100644
--- a/core/java/android/service/voice/IHotwordDetectionService.aidl
+++ b/core/java/android/service/voice/IHotwordDetectionService.aidl
@@ -22,6 +22,8 @@
 import android.os.SharedMemory;
 import android.service.voice.IDspHotwordDetectionCallback;
 
+import com.android.internal.app.IHotwordRecognitionStatusCallback;
+
 /**
  * Provide the interface to communicate with hotword detection service.
  *
@@ -41,5 +43,6 @@
         in PersistableBundle options,
         in IDspHotwordDetectionCallback callback);
 
-    void updateState(in PersistableBundle options, in SharedMemory sharedMemory);
+    void updateState(in PersistableBundle options, in SharedMemory sharedMemory,
+            in IHotwordRecognitionStatusCallback callback);
 }
diff --git a/core/java/android/service/voice/SoftwareHotwordDetector.java b/core/java/android/service/voice/SoftwareHotwordDetector.java
index f49a9d4..376596b 100644
--- a/core/java/android/service/voice/SoftwareHotwordDetector.java
+++ b/core/java/android/service/voice/SoftwareHotwordDetector.java
@@ -67,7 +67,7 @@
         mHandler = new Handler(Looper.getMainLooper());
 
         try {
-            mManagerService.updateState(options, sharedMemory);
+            mManagerService.updateState(options, sharedMemory, null /* callback */);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/speech/IRecognitionService.aidl b/core/java/android/speech/IRecognitionService.aidl
index cc1cded..9a5e534 100644
--- a/core/java/android/speech/IRecognitionService.aidl
+++ b/core/java/android/speech/IRecognitionService.aidl
@@ -17,6 +17,7 @@
 package android.speech;
 
 import android.os.Bundle;
+import android.content.AttributionSource;
 import android.content.Intent;
 import android.speech.IRecognitionListener;
 
@@ -39,11 +40,10 @@
      *        this intent can contain extra parameters to manipulate the behavior of the recognition
      *        client. For more information see {@link RecognizerIntent}.
      * @param listener to receive callbacks, note that this must be non-null
-     * @param packageName the package name calling this API
-     * @param featureId The feature in the package
+     * @param attributionSource The attribution source of the caller.
      */
     void startListening(in Intent recognizerIntent, in IRecognitionListener listener,
-            String packageName, String featureId, int callingUid);
+            in AttributionSource attributionSource);
 
     /**
      * Stops listening for speech. Speech captured so far will be recognized as
@@ -51,18 +51,14 @@
      * is called during the speech capturing.
      *
      * @param listener to receive callbacks, note that this must be non-null
-     * @param packageName the package name calling this API
-     * @param featureId The feature in the package
      */
-    void stopListening(in IRecognitionListener listener, String packageName, String featureId);
+    void stopListening(in IRecognitionListener listener);
 
     /**
      * Cancels the speech recognition.
      *
      * @param listener to receive callbacks, note that this must be non-null
      * @param packageName the package name calling this API
-     * @param featureId The feature in the package
-     * @param isShutdown Whether the cancellation is caused by a client calling #shutdown
      */
-    void cancel(in IRecognitionListener listener, String packageName, String featureId, boolean isShutdown);
+    void cancel(in IRecognitionListener listener, boolean isShutdown);
 }
diff --git a/core/java/android/speech/RecognitionService.java b/core/java/android/speech/RecognitionService.java
index fd584f1..4afa9473 100644
--- a/core/java/android/speech/RecognitionService.java
+++ b/core/java/android/speech/RecognitionService.java
@@ -16,11 +16,16 @@
 
 package android.speech;
 
+import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SuppressLint;
+import android.app.AppOpsManager;
 import android.app.Service;
+import android.content.Context;
+import android.content.ContextParams;
 import android.content.Intent;
 import android.content.PermissionChecker;
 import android.os.Binder;
@@ -28,13 +33,13 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
+import android.content.AttributionSource;
 import android.os.Process;
 import android.os.RemoteException;
 import android.util.Log;
 
-import com.android.internal.util.Preconditions;
-
 import java.lang.ref.WeakReference;
+import java.util.Objects;
 
 /**
  * This class provides a base class for recognition service implementations. This class should be
@@ -86,13 +91,13 @@
             switch (msg.what) {
                 case MSG_START_LISTENING:
                     StartListeningArgs args = (StartListeningArgs) msg.obj;
-                    dispatchStartListening(args.mIntent, args.mListener, args.mCallingUid);
+                    dispatchStartListening(args.mIntent, args.mListener, args.mAttributionSource);
                     break;
                 case MSG_STOP_LISTENING:
                     dispatchStopListening((IRecognitionListener) msg.obj);
                     break;
                 case MSG_CANCEL:
-                    dispatchCancel((IRecognitionListener) msg.obj);
+                    dispatchCancel((IRecognitionListener) msg.obj, msg.arg1 == 1);
                     break;
                 case MSG_RESET:
                     dispatchClearCallback();
@@ -102,10 +107,11 @@
     };
 
     private void dispatchStartListening(Intent intent, final IRecognitionListener listener,
-            int callingUid) {
+            @NonNull AttributionSource attributionSource) {
         if (mCurrentCallback == null) {
             if (DBG) Log.d(TAG, "created new mCurrentCallback, listener = " + listener.asBinder());
-            mCurrentCallback = new Callback(listener, callingUid);
+            mCurrentCallback = new Callback(listener, attributionSource);
+
             RecognitionService.this.onStartListening(intent, mCurrentCallback);
         } else {
             try {
@@ -133,13 +139,16 @@
         }
     }
 
-    private void dispatchCancel(IRecognitionListener listener) {
+    private void dispatchCancel(IRecognitionListener listener, boolean shutDown) {
         if (mCurrentCallback == null) {
             if (DBG) Log.d(TAG, "cancel called with no preceding startListening - ignoring");
         } else if (mCurrentCallback.mListener.asBinder() != listener.asBinder()) {
             Log.w(TAG, "cancel called by client who did not call startListening - ignoring");
         } else { // the correct state
             RecognitionService.this.onCancel(mCurrentCallback);
+            if (shutDown) {
+                mCurrentCallback.finishRecordAudioOpAttributionToCallerIfNeeded();
+            }
             mCurrentCallback = null;
             if (DBG) Log.d(TAG, "canceling - setting mCurrentCallback to null");
         }
@@ -153,12 +162,13 @@
         public final Intent mIntent;
 
         public final IRecognitionListener mListener;
-        public final int mCallingUid;
+        public final @NonNull AttributionSource mAttributionSource;
 
-        public StartListeningArgs(Intent intent, IRecognitionListener listener, int callingUid) {
+        public StartListeningArgs(Intent intent, IRecognitionListener listener,
+                @NonNull AttributionSource attributionSource) {
             this.mIntent = intent;
             this.mListener = listener;
-            this.mCallingUid = callingUid;
+            this.mAttributionSource = attributionSource;
         }
     }
 
@@ -247,18 +257,19 @@
      */
     public class Callback {
         private final IRecognitionListener mListener;
-        private final int mCallingUid;
+        private final @NonNull AttributionSource mCallingAttributionSource;
+        private @Nullable Context mAttributionContext;
 
-        private Callback(IRecognitionListener listener, int callingUid) {
+        private Callback(IRecognitionListener listener,
+                @NonNull AttributionSource attributionSource) {
             mListener = listener;
-            mCallingUid = callingUid;
+            mCallingAttributionSource = attributionSource;
         }
 
         /**
          * The service should call this method when the user has started to speak.
          */
         public void beginningOfSpeech() throws RemoteException {
-            if (DBG) Log.d(TAG, "beginningOfSpeech");
             mListener.onBeginningOfSpeech();
         }
 
@@ -270,6 +281,7 @@
          *        single channel audio stream. The sample rate is implementation dependent.
          */
         public void bufferReceived(byte[] buffer) throws RemoteException {
+            startRecordAudioOpAttributionToCallerIfNeeded();
             mListener.onBufferReceived(buffer);
         }
 
@@ -302,6 +314,7 @@
          *        {@link SpeechRecognizer#RESULTS_RECOGNITION} as a parameter
          */
         public void partialResults(Bundle partialResults) throws RemoteException {
+            startRecordAudioOpAttributionToCallerIfNeeded();
             mListener.onPartialResults(partialResults);
         }
 
@@ -323,6 +336,7 @@
          *        {@link SpeechRecognizer#RESULTS_RECOGNITION} as a parameter
          */
         public void results(Bundle results) throws RemoteException {
+            startRecordAudioOpAttributionToCallerIfNeeded();
             Message.obtain(mHandler, MSG_RESET).sendToTarget();
             mListener.onResults(results);
         }
@@ -342,7 +356,65 @@
          * is being processed. This is obtained from {@link Binder#getCallingUid()}.
          */
         public int getCallingUid() {
-            return mCallingUid;
+            return mCallingAttributionSource.getUid();
+        }
+
+        /**
+         * Gets the permission identity of the calling app. If you want to attribute
+         * the mic access to the calling app you can create an attribution context
+         * via {@link android.content.Context#createContext(android.content.ContextParams)}
+         * and passing this identity to {@link
+         * android.content.ContextParams.Builder#setNextAttributionSource(AttributionSource)}.
+         *
+         *
+         *
+         *
+         * @return The permission identity of the calling app.
+         *
+         * @see android.content.ContextParams.Builder#setNextAttributionSource(
+         * AttributionSource)
+         */
+        @SuppressLint("CallbackMethodName")
+        public @NonNull AttributionSource getCallingAttributionSource() {
+            return mCallingAttributionSource;
+        }
+
+        private void startRecordAudioOpAttributionToCallerIfNeeded() throws RemoteException {
+            if (!isProxyingRecordAudioToCaller()) {
+                final int result = PermissionChecker.checkPermissionAndStartDataDelivery(
+                        RecognitionService.this, Manifest.permission.RECORD_AUDIO,
+                        getAttributionContextForCaller().getAttributionSource(),
+                        /*message*/ null);
+                if (result == PermissionChecker.PERMISSION_GRANTED) {
+                    return;
+                }
+                error(SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS);
+            }
+        }
+
+        private @NonNull Context getAttributionContextForCaller() {
+            if (mAttributionContext == null) {
+                mAttributionContext = createContext(new ContextParams.Builder()
+                        .setNextAttributionSource(mCallingAttributionSource)
+                        .build());
+            }
+            return mAttributionContext;
+        }
+
+        void finishRecordAudioOpAttributionToCallerIfNeeded() {
+            if (isProxyingRecordAudioToCaller()) {
+                final String op = AppOpsManager.permissionToOp(Manifest.permission.RECORD_AUDIO);
+                PermissionChecker.finishDataDelivery(RecognitionService.this,
+                        op, getAttributionContextForCaller().getAttributionSource());
+            }
+        }
+
+        private boolean isProxyingRecordAudioToCaller() {
+            final int op = AppOpsManager.permissionToOpCode(Manifest.permission.RECORD_AUDIO);
+            final AppOpsManager appOpsManager = getSystemService(AppOpsManager.class);
+            return appOpsManager.isProxying(op, getAttributionTag(),
+                    mCallingAttributionSource.getUid(),
+                    mCallingAttributionSource.getPackageName());
         }
     }
 
@@ -356,44 +428,35 @@
 
         @Override
         public void startListening(Intent recognizerIntent, IRecognitionListener listener,
-                String packageName, String featureId, int callingUid) {
-            Preconditions.checkNotNull(packageName);
-
+                @NonNull AttributionSource attributionSource) {
+            Objects.requireNonNull(attributionSource);
+            attributionSource.enforceCallingUid();
             if (DBG) Log.d(TAG, "startListening called by:" + listener.asBinder());
             final RecognitionService service = mServiceRef.get();
-            if (service != null && service.checkPermissions(listener, true /*forDataDelivery*/,
-                    packageName, featureId)) {
+            if (service != null) {
                 service.mHandler.sendMessage(Message.obtain(service.mHandler,
                         MSG_START_LISTENING, service.new StartListeningArgs(
-                                recognizerIntent, listener, callingUid)));
+                                recognizerIntent, listener, attributionSource)));
             }
         }
 
         @Override
-        public void stopListening(IRecognitionListener listener, String packageName,
-                String featureId) {
-            Preconditions.checkNotNull(packageName);
-
+        public void stopListening(IRecognitionListener listener) {
             if (DBG) Log.d(TAG, "stopListening called by:" + listener.asBinder());
             final RecognitionService service = mServiceRef.get();
-            if (service != null && service.checkPermissions(listener, false /*forDataDelivery*/,
-                    packageName, featureId)) {
+            if (service != null) {
                 service.mHandler.sendMessage(Message.obtain(service.mHandler,
                         MSG_STOP_LISTENING, listener));
             }
         }
 
         @Override
-        public void cancel(IRecognitionListener listener, String packageName,
-                String featureId, boolean isShutdown) {
-            Preconditions.checkNotNull(packageName);
-
+        public void cancel(IRecognitionListener listener, boolean isShutdown) {
             if (DBG) Log.d(TAG, "cancel called by:" + listener.asBinder());
             final RecognitionService service = mServiceRef.get();
-            if (service != null && service.checkPermissions(listener, false /*forDataDelivery*/,
-                    packageName, featureId)) {
+            if (service != null) {
                 service.mHandler.sendMessage(Message.obtain(service.mHandler,
-                        MSG_CANCEL, listener));
+                        MSG_CANCEL, isShutdown ? 1 : 0, 0, listener));
             }
         }
 
diff --git a/core/java/android/speech/SpeechRecognizer.java b/core/java/android/speech/SpeechRecognizer.java
index 9b93a64..7aa5ee5 100644
--- a/core/java/android/speech/SpeechRecognizer.java
+++ b/core/java/android/speech/SpeechRecognizer.java
@@ -386,8 +386,7 @@
             return;
         }
         try {
-            mService.startListening(recognizerIntent, mListener, mContext.getOpPackageName(),
-                    mContext.getAttributionTag(), android.os.Process.myUid());
+            mService.startListening(recognizerIntent, mListener, mContext.getAttributionSource());
             if (DBG) Log.d(TAG, "service start listening command succeded");
         } catch (final RemoteException e) {
             Log.e(TAG, "startListening() failed", e);
@@ -401,8 +400,7 @@
             return;
         }
         try {
-            mService.stopListening(mListener, mContext.getOpPackageName(),
-                    mContext.getAttributionTag());
+            mService.stopListening(mListener);
             if (DBG) Log.d(TAG, "service stop listening command succeded");
         } catch (final RemoteException e) {
             Log.e(TAG, "stopListening() failed", e);
@@ -416,11 +414,7 @@
             return;
         }
         try {
-            mService.cancel(
-                    mListener,
-                    mContext.getOpPackageName(),
-                    mContext.getAttributionTag(),
-                    false /* isShutdown */);
+            mService.cancel(mListener, /*isShutdown*/ false);
             if (DBG) Log.d(TAG, "service cancel command succeded");
         } catch (final RemoteException e) {
             Log.e(TAG, "cancel() failed", e);
@@ -463,8 +457,7 @@
     public void destroy() {
         if (mService != null) {
             try {
-                mService.cancel(mListener, mContext.getOpPackageName(),
-                        mContext.getAttributionTag(), true /* isShutdown */);
+                mService.cancel(mListener, /*isShutdown*/ true);
             } catch (final RemoteException e) {
                 // Not important
             }
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index 1da7dc4..49065aa 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -703,6 +703,10 @@
      * calling {@link TelephonyManager#getCallState()} from within this callback may return a
      * different state than the callback reports.
      *
+     * Requires Permission:
+     * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} for applications
+     * targeting API level 31+.
+     *
      * @param state call state
      * @param phoneNumber call phone number. If application does not have
      * {@link android.Manifest.permission#READ_CALL_LOG READ_CALL_LOG} permission or carrier
@@ -712,6 +716,7 @@
      * @deprecated Use {@link TelephonyCallback.CallStateListener} instead.
      */
     @Deprecated
+    @RequiresPermission(value = android.Manifest.permission.READ_PHONE_STATE, conditional = true)
     public void onCallStateChanged(@CallState int state, String phoneNumber) {
         // default implementation empty
     }
diff --git a/core/java/android/telephony/TelephonyCallback.java b/core/java/android/telephony/TelephonyCallback.java
index 18949cd..1ab6e0f 100644
--- a/core/java/android/telephony/TelephonyCallback.java
+++ b/core/java/android/telephony/TelephonyCallback.java
@@ -752,6 +752,7 @@
          *
          * @param state the current call state
          */
+        @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
         public void onCallStateChanged(@Annotation.CallState int state);
     }
 
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 913ceae..572e50a 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -70,7 +70,7 @@
         DEFAULT_FLAGS.put("settings_tether_all_in_one", "false");
         DEFAULT_FLAGS.put("settings_silky_home", "true");
         DEFAULT_FLAGS.put("settings_contextual_home", "false");
-        DEFAULT_FLAGS.put(SETTINGS_PROVIDER_MODEL, "false");
+        DEFAULT_FLAGS.put(SETTINGS_PROVIDER_MODEL, "true");
         DEFAULT_FLAGS.put(SETTINGS_USE_NEW_BACKUP_ELIGIBILITY_RULES, "true");
         DEFAULT_FLAGS.put(SETTINGS_ENABLE_SECURITY_HUB, "false");
     }
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index d484f4d4..bf152cb 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -44,6 +44,7 @@
 import android.os.Parcelable;
 import android.os.Process;
 import android.os.SystemClock;
+import android.util.ArraySet;
 import android.util.DisplayMetrics;
 import android.util.Log;
 
@@ -1066,7 +1067,47 @@
     public HdrCapabilities getHdrCapabilities() {
         synchronized (mLock) {
             updateDisplayInfoLocked();
-            return mDisplayInfo.hdrCapabilities;
+            if (mDisplayInfo.userDisabledHdrTypes.length == 0) {
+                return mDisplayInfo.hdrCapabilities;
+            }
+            ArraySet<Integer> enabledTypesSet = new ArraySet<>();
+            for (int supportedType : mDisplayInfo.hdrCapabilities.getSupportedHdrTypes()) {
+                boolean typeDisabled = false;
+                for (int userDisabledType : mDisplayInfo.userDisabledHdrTypes) {
+                    if (supportedType == userDisabledType) {
+                        typeDisabled = true;
+                        break;
+                    }
+                }
+                if (!typeDisabled) {
+                    enabledTypesSet.add(supportedType);
+                }
+            }
+            int[] enabledTypes = new int[enabledTypesSet.size()];
+            int index = 0;
+            for (int enabledType : enabledTypesSet) {
+                enabledTypes[index++] = enabledType;
+            }
+            return new HdrCapabilities(enabledTypes,
+                    mDisplayInfo.hdrCapabilities.mMaxLuminance,
+                    mDisplayInfo.hdrCapabilities.mMaxAverageLuminance,
+                    mDisplayInfo.hdrCapabilities.mMinLuminance);
+        }
+    }
+
+    /**
+     * @hide
+     * Returns the display's HDR supported types.
+     *
+     * @see #isHdr()
+     * @see HdrCapabilities#getSupportedHdrTypes()
+     */
+    @TestApi
+    @NonNull
+    public int[] getReportedHdrTypes() {
+        synchronized (mLock) {
+            updateDisplayInfoLocked();
+            return mDisplayInfo.hdrCapabilities.getSupportedHdrTypes();
         }
     }
 
@@ -1079,7 +1120,7 @@
     public boolean isHdr() {
         synchronized (mLock) {
             updateDisplayInfoLocked();
-            return mDisplayInfo.isHdr();
+            return !(getHdrCapabilities().getSupportedHdrTypes().length == 0);
         }
     }
 
@@ -1855,6 +1896,14 @@
         public static final int HDR_TYPE_HDR10_PLUS = 4;
 
         /** @hide */
+        public static final int[] HDR_TYPES = {
+                HDR_TYPE_DOLBY_VISION,
+                HDR_TYPE_HDR10,
+                HDR_TYPE_HLG,
+                HDR_TYPE_HDR10_PLUS
+        };
+
+        /** @hide */
         @IntDef(prefix = { "HDR_TYPE_" }, value = {
                 HDR_TYPE_DOLBY_VISION,
                 HDR_TYPE_HDR10,
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 9aaf5c0..36be9f8 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -198,6 +198,9 @@
     /** The display's HDR capabilities */
     public Display.HdrCapabilities hdrCapabilities;
 
+    /** The formats disabled by user **/
+    public int[] userDisabledHdrTypes = {};
+
     /**
      * Indicates whether the display can be switched into a mode with minimal post
      * processing.
@@ -363,6 +366,7 @@
                 && colorMode == other.colorMode
                 && Arrays.equals(supportedColorModes, other.supportedColorModes)
                 && Objects.equals(hdrCapabilities, other.hdrCapabilities)
+                && Arrays.equals(userDisabledHdrTypes, other.userDisabledHdrTypes)
                 && minimalPostProcessingSupported == other.minimalPostProcessingSupported
                 && logicalDensityDpi == other.logicalDensityDpi
                 && physicalXDpi == other.physicalXDpi
@@ -412,6 +416,7 @@
         supportedColorModes = Arrays.copyOf(
                 other.supportedColorModes, other.supportedColorModes.length);
         hdrCapabilities = other.hdrCapabilities;
+        userDisabledHdrTypes = other.userDisabledHdrTypes;
         minimalPostProcessingSupported = other.minimalPostProcessingSupported;
         logicalDensityDpi = other.logicalDensityDpi;
         physicalXDpi = other.physicalXDpi;
@@ -478,6 +483,11 @@
         brightnessMaximum = source.readFloat();
         brightnessDefault = source.readFloat();
         roundedCorners = source.readTypedObject(RoundedCorners.CREATOR);
+        int numUserDisabledFormats = source.readInt();
+        userDisabledHdrTypes = new int[numUserDisabledFormats];
+        for (int i = 0; i < numUserDisabledFormats; i++) {
+            userDisabledHdrTypes[i] = source.readInt();
+        }
     }
 
     @Override
@@ -528,6 +538,10 @@
         dest.writeFloat(brightnessMaximum);
         dest.writeFloat(brightnessDefault);
         dest.writeTypedObject(roundedCorners, flags);
+        dest.writeInt(userDisabledHdrTypes.length);
+        for (int i = 0; i < userDisabledHdrTypes.length; i++) {
+            dest.writeInt(userDisabledHdrTypes[i]);
+        }
     }
 
     @Override
@@ -729,6 +743,8 @@
         sb.append(Arrays.toString(supportedModes));
         sb.append(", hdrCapabilities ");
         sb.append(hdrCapabilities);
+        sb.append(", userDisabledHdrTypes ");
+        sb.append(Arrays.toString(userDisabledHdrTypes));
         sb.append(", minimalPostProcessingSupported ");
         sb.append(minimalPostProcessingSupported);
         sb.append(", rotation ");
diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java
index 8db6456..0686104 100644
--- a/core/java/android/view/ImeInsetsSourceConsumer.java
+++ b/core/java/android/view/ImeInsetsSourceConsumer.java
@@ -51,8 +51,8 @@
     }
 
     @Override
-    public void onWindowFocusGained() {
-        super.onWindowFocusGained();
+    public void onWindowFocusGained(boolean hasViewFocus) {
+        super.onWindowFocusGained(hasViewFocus);
         getImm().registerImeConsumer(this);
     }
 
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index a68f528..c001ec9 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -1302,8 +1302,8 @@
     /**
      * Called when current window gains focus.
      */
-    public void onWindowFocusGained() {
-        getSourceConsumer(ITYPE_IME).onWindowFocusGained();
+    public void onWindowFocusGained(boolean hasViewFocused) {
+        getSourceConsumer(ITYPE_IME).onWindowFocusGained(hasViewFocused);
     }
 
     /**
@@ -1366,8 +1366,9 @@
             final InsetsSourceControl imeControl = consumer != null ? consumer.getControl() : null;
             // Skip showing animation once that made by system for some reason.
             // (e.g. starting window with IME snapshot)
-            if (imeControl != null && show) {
-                skipAnim = imeControl.getAndClearSkipAnimationOnce();
+            if (imeControl != null) {
+                skipAnim = imeControl.getAndClearSkipAnimationOnce() && show
+                        && consumer.hasViewFocusWhenWindowFocusGain();
             }
         }
         applyAnimation(types, show, fromIme, skipAnim);
diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java
index fd1c3b8..bc50dbe 100644
--- a/core/java/android/view/InsetsSourceConsumer.java
+++ b/core/java/android/view/InsetsSourceConsumer.java
@@ -81,6 +81,11 @@
     private final Supplier<Transaction> mTransactionSupplier;
     private @Nullable InsetsSourceControl mSourceControl;
     private boolean mHasWindowFocus;
+
+    /**
+     * Whether the view has focus returned by {@link #onWindowFocusGained(boolean)}.
+     */
+    private boolean mHasViewFocusWhenWindowFocusGain;
     private Rect mPendingFrame;
     private Rect mPendingVisibleFrame;
 
@@ -223,8 +228,9 @@
     /**
      * Called when current window gains focus
      */
-    public void onWindowFocusGained() {
+    public void onWindowFocusGained(boolean hasViewFocus) {
         mHasWindowFocus = true;
+        mHasViewFocusWhenWindowFocusGain = hasViewFocus;
     }
 
     /**
@@ -238,6 +244,10 @@
         return mHasWindowFocus;
     }
 
+    boolean hasViewFocusWhenWindowFocusGain() {
+        return mHasViewFocusWhenWindowFocusGain;
+    }
+
     boolean applyLocalVisibilityOverride() {
         final InsetsSource source = mState.peekSource(mType);
         final boolean isVisible = source != null ? source.isVisible() : getDefaultVisibility(mType);
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 85d4878..b2a84a2 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -190,6 +190,8 @@
     private static native void nativeReparent(long transactionObj, long nativeObject,
             long newParentNativeObject);
 
+    private static native void nativeOverrideHdrTypes(IBinder displayToken, int[] modes);
+
     private static native void nativeSetInputWindowInfo(long transactionObj, long nativeObject,
             InputWindowHandle handle);
 
@@ -2204,6 +2206,18 @@
     }
 
     /**
+     * Overrides HDR modes for a display device.
+     *
+     * If the caller does not have ACCESS_SURFACE_FLINGER permission, this will throw a Security
+     * Exception.
+     * @hide
+     */
+    @TestApi
+    public static void overrideHdrTypes(@NonNull IBinder displayToken, @NonNull int[] modes) {
+        nativeOverrideHdrTypes(displayToken, modes);
+    }
+
+    /**
      * @hide
      */
     @UnsupportedAppUsage
@@ -2244,6 +2258,8 @@
      *
      * @hide
      */
+    @TestApi
+    @NonNull
     public static IBinder getInternalDisplayToken() {
         final long[] physicalDisplayIds = getPhysicalDisplayIds();
         if (physicalDisplayIds.length == 0) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index fb52899..615dd82 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -107,6 +107,7 @@
 import android.util.FloatProperty;
 import android.util.LayoutDirection;
 import android.util.Log;
+import android.util.LongSparseArray;
 import android.util.LongSparseLongArray;
 import android.util.Pair;
 import android.util.Pools.SynchronizedPool;
@@ -30741,6 +30742,30 @@
     }
 
     /**
+     * Returns a {@link ViewTranslationRequest} list which represents the content to be translated
+     * in the virtual view. This is called if this view returned a virtual view structure
+     * from {@link #onProvideContentCaptureStructure} and the system determined that those virtual
+     * views were relevant for translation.
+     *
+     * <p>The default implementation does nothing.</p>
+     *
+     * @param virtualChildIds the virtual child ids which represents the child views in the virtual
+     * view.
+     * @param supportedFormats the supported translation formats. For now, the only possible value
+     * is the {@link android.view.translation.TranslationSpec#DATA_FORMAT_TEXT}.
+     * @param requestsCollector a {@link ViewTranslationRequest} collector that will be called
+     * multiple times to collect the information to be translated in the virtual view. One
+     * {@link ViewTranslationRequest} per virtual child. The {@link ViewTranslationRequest} must
+     * contains the {@link AutofillId} corresponding to the virtualChildIds.
+     */
+    @SuppressLint("NullableCollection")
+    public void onCreateTranslationRequests(@NonNull long[] virtualChildIds,
+            @NonNull @DataFormat int[] supportedFormats,
+            @NonNull Consumer<ViewTranslationRequest> requestsCollector) {
+        // no-op
+    }
+
+    /**
      * Returns a {@link ViewTranslationCallback} that is used to display/hide the translated
      * information. If the View supports displaying translated content, it should implement
      * {@link ViewTranslationCallback}.
@@ -30782,13 +30807,29 @@
     }
 
     /**
+     * Called when the content from {@link View#onCreateTranslationRequest} had been translated by
+     * the TranslationService.
+     *
+     * <p> The default implementation does nothing.</p>
+     *
+     * @param response a {@link ViewTranslationResponse} SparseArray for the request that send by
+     * {@link View#onCreateTranslationRequests} that contains the translated information which can
+     * be shown in the view. The key of SparseArray is
+     * the virtual child ids.
+     */
+    public void onTranslationResponse(@NonNull LongSparseArray<ViewTranslationResponse> response) {
+        // no-op
+    }
+
+    /**
      * Dispatch to collect the {@link ViewTranslationRequest}s for translation purpose by traversing
      * the hierarchy when the app requests ui translation. Typically, this method should only be
      * overridden by subclasses that provide a view hierarchy (such as {@link ViewGroup}). Other
      * classes should override {@link View#onCreateTranslationRequest}. When requested to start the
      * ui translation, the system will call this method to traverse the view hierarchy to call
      * {@link View#onCreateTranslationRequest} to build {@link ViewTranslationRequest}s and create a
-     * {@link android.view.translation.Translator} to translate the requests.
+     * {@link android.view.translation.Translator} to translate the requests. All the
+     * {@link ViewTranslationRequest}s will be added when the traversal is done.
      *
      * <p> The default implementation will call {@link View#onCreateTranslationRequest} to build
      * {@link ViewTranslationRequest} if the view should be translated. </p>
@@ -30808,14 +30849,15 @@
             @NonNull List<ViewTranslationRequest> requests) {
         AutofillId autofillId = getAutofillId();
         if (viewIds.containsKey(autofillId)) {
-            ViewTranslationRequest request = null;
             if (viewIds.get(autofillId) == null) {
-                request = onCreateTranslationRequest(supportedFormats);
+                ViewTranslationRequest request = onCreateTranslationRequest(supportedFormats);
                 if (request != null && request.getKeys().size() > 0) {
                     requests.add(request);
                 }
             } else {
-                // TODO: handle virtual view
+                onCreateTranslationRequests(viewIds.get(autofillId), supportedFormats, request -> {
+                    requests.add(request);
+                });
             }
         }
     }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 0a246a6..426c950 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -3344,8 +3344,9 @@
         }
         // TODO (b/131181940): Make sure this doesn't leak Activity with mActivityConfigCallback
         // config changes.
+        final View focusedView = mView != null ? mView.findFocus() : null;
         if (hasWindowFocus) {
-            mInsetsController.onWindowFocusGained();
+            mInsetsController.onWindowFocusGained(focusedView != null /* hasViewFocused */);
         } else {
             mInsetsController.onWindowFocusLost();
         }
@@ -3394,8 +3395,7 @@
 
             // Note: must be done after the focus change callbacks,
             // so all of the view state is set up correctly.
-            mImeFocusController.onPostWindowFocus(mView != null ? mView.findFocus() : null,
-                    hasWindowFocus, mWindowAttributes);
+            mImeFocusController.onPostWindowFocus(focusedView, hasWindowFocus, mWindowAttributes);
 
             if (hasWindowFocus) {
                 // Clear the forward bit.  We can just do this directly, since
diff --git a/core/java/android/view/translation/UiTranslationController.java b/core/java/android/view/translation/UiTranslationController.java
index cfe892f..0fa6e16 100644
--- a/core/java/android/view/translation/UiTranslationController.java
+++ b/core/java/android/view/translation/UiTranslationController.java
@@ -31,6 +31,7 @@
 import android.os.Process;
 import android.util.ArrayMap;
 import android.util.Log;
+import android.util.LongSparseArray;
 import android.util.Pair;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
@@ -238,29 +239,90 @@
         final SparseArray<ViewTranslationResponse> translatedResult =
                 response.getViewTranslationResponses();
         final SparseArray<ViewTranslationResponse> viewsResult = new SparseArray<>();
-        final SparseArray<ViewTranslationResponse> virtualViewsResult = new SparseArray<>();
-        final List<AutofillId> viewIds = new ArrayList<>();
+        final SparseArray<LongSparseArray<ViewTranslationResponse>> virtualViewsResult =
+                new SparseArray<>();
+        // TODO: use another structure to prevent autoboxing?
+        final List<Integer> viewIds = new ArrayList<>();
+
         for (int i = 0; i < translatedResult.size(); i++) {
             final ViewTranslationResponse result = translatedResult.valueAt(i);
             final AutofillId autofillId = result.getAutofillId();
+            if (!viewIds.contains(autofillId.getViewId())) {
+                viewIds.add(autofillId.getViewId());
+            }
             if (autofillId.isNonVirtual()) {
                 viewsResult.put(translatedResult.keyAt(i), result);
-                viewIds.add(autofillId);
             } else {
-                virtualViewsResult.put(translatedResult.keyAt(i), result);
+                final boolean isVirtualViewAdded =
+                        virtualViewsResult.indexOfKey(autofillId.getViewId()) >= 0;
+                final LongSparseArray<ViewTranslationResponse> childIds =
+                        isVirtualViewAdded ? virtualViewsResult.get(autofillId.getViewId())
+                                : new LongSparseArray<>();
+                childIds.put(autofillId.getVirtualChildLongId(), result);
+                if (!isVirtualViewAdded) {
+                    virtualViewsResult.put(autofillId.getViewId(), childIds);
+                }
             }
         }
+        // Traverse tree and get views by the responsed AutofillId
+        findViewsTraversalByAutofillIds(viewIds);
+
         if (viewsResult.size() > 0) {
-            onTranslationCompleted(viewsResult, viewIds);
+            onTranslationCompleted(viewsResult);
         }
-        //TODO(b/177960696): call virtual views onTranslationCompleted()
+        if (virtualViewsResult.size() > 0) {
+            onVirtualViewTranslationCompleted(virtualViewsResult);
+        }
+    }
+
+    /**
+     * The method is used to handle the translation result for the vertual views.
+     */
+    private void onVirtualViewTranslationCompleted(
+            SparseArray<LongSparseArray<ViewTranslationResponse>> translatedResult) {
+        if (!mActivity.isResumed()) {
+            if (DEBUG) {
+                Log.v(TAG, "onTranslationCompleted: Activity is not resumed.");
+            }
+            return;
+        }
+        synchronized (mLock) {
+            if (mCurrentState == STATE_UI_TRANSLATION_FINISHED) {
+                Log.w(TAG, "onTranslationCompleted: the translation state is finished now. "
+                        + "Skip to show the translated text.");
+                return;
+            }
+            for (int i = 0; i < translatedResult.size(); i++) {
+                final AutofillId autofillId = new AutofillId(translatedResult.keyAt(i));
+                final View view = mViews.get(autofillId).get();
+                if (view == null) {
+                    Log.w(TAG, "onTranslationCompleted: the view for autofill id " + autofillId
+                            + " may be gone.");
+                    continue;
+                }
+                final LongSparseArray<ViewTranslationResponse> virtualChildResponse =
+                        translatedResult.valueAt(i);
+                mActivity.runOnUiThread(() -> {
+                    if (view.getViewTranslationCallback() == null) {
+                        if (DEBUG) {
+                            Log.d(TAG, view + " doesn't support showing translation because of "
+                                    + "null ViewTranslationCallback.");
+                        }
+                        return;
+                    }
+                    view.onTranslationResponse(virtualChildResponse);
+                    if (view.getViewTranslationCallback() != null) {
+                        view.getViewTranslationCallback().onShowTranslation(view);
+                    }
+                });
+            }
+        }
     }
 
     /**
      * The method is used to handle the translation result for non-vertual views.
      */
-    private void onTranslationCompleted(SparseArray<ViewTranslationResponse> translatedResult,
-            List<AutofillId> viewIds) {
+    private void onTranslationCompleted(SparseArray<ViewTranslationResponse> translatedResult) {
         if (!mActivity.isResumed()) {
             if (DEBUG) {
                 Log.v(TAG, "onTranslationCompleted: Activity is not resumed.");
@@ -277,8 +339,6 @@
                         + "Skip to show the translated text.");
                 return;
             }
-            // Traverse tree and get views by the responsed AutofillId
-            findViewsTraversalByAutofillIds(viewIds);
             for (int i = 0; i < resultCount; i++) {
                 final ViewTranslationResponse response = translatedResult.valueAt(i);
                 final AutofillId autofillId = response.getAutofillId();
@@ -300,7 +360,9 @@
                         return;
                     }
                     view.onTranslationResponse(response);
-                    view.getViewTranslationCallback().onShowTranslation(view);
+                    if (view.getViewTranslationCallback() != null) {
+                        view.getViewTranslationCallback().onShowTranslation(view);
+                    }
                 });
             }
         }
@@ -359,7 +421,7 @@
                         childs = new long[childCount];
                         viewIds.put(virtualViewAutofillId, childs);
                     }
-                    int end = childs.length;
+                    int end = childs.length - 1;
                     childs[end] = autofillId.getVirtualChildLongId();
                 }
             }
@@ -403,7 +465,7 @@
         return new int[] {TranslationSpec.DATA_FORMAT_TEXT};
     }
 
-    private void findViewsTraversalByAutofillIds(List<AutofillId> sourceViewIds) {
+    private void findViewsTraversalByAutofillIds(List<Integer> sourceViewIds) {
         final ArrayList<ViewRootImpl> roots =
                 WindowManagerGlobal.getInstance().getRootViews(mActivity.getActivityToken());
         for (int rootNum = 0; rootNum < roots.size(); rootNum++) {
@@ -417,7 +479,7 @@
     }
 
     private void findViewsTraversalByAutofillIds(ViewGroup viewGroup,
-            List<AutofillId> sourceViewIds) {
+            List<Integer> sourceViewIds) {
         final int childCount = viewGroup.getChildCount();
         for (int i = 0; i < childCount; ++i) {
             final View child = viewGroup.getChildAt(i);
@@ -429,9 +491,9 @@
         }
     }
 
-    private void addViewIfNeeded(List<AutofillId> sourceViewIds, View view) {
+    private void addViewIfNeeded(List<Integer> sourceViewIds, View view) {
         final AutofillId autofillId = view.getAutofillId();
-        if (sourceViewIds.contains(autofillId)) {
+        if (sourceViewIds.contains(autofillId.getViewId()) && !mViews.containsKey(autofillId)) {
             mViews.put(autofillId, new WeakReference<>(view));
         }
     }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 487d13e..6d4fa65 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -45,6 +45,7 @@
 import android.print.PrintDocumentAdapter;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.LongSparseArray;
 import android.util.SparseArray;
 import android.view.DragEvent;
 import android.view.KeyEvent;
@@ -64,6 +65,9 @@
 import android.view.inputmethod.InputConnection;
 import android.view.inspector.InspectableProperty;
 import android.view.textclassifier.TextClassifier;
+import android.view.translation.TranslationSpec.DataFormat;
+import android.view.translation.ViewTranslationRequest;
+import android.view.translation.ViewTranslationResponse;
 import android.widget.AbsoluteLayout;
 
 import java.io.BufferedWriter;
@@ -73,6 +77,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Executor;
+import java.util.function.Consumer;
 
 /**
  * A View that displays web pages.
@@ -2854,6 +2859,20 @@
         return mProvider.getViewDelegate().isVisibleToUserForAutofill(virtualId);
     }
 
+    @Override
+    @Nullable
+    public void onCreateTranslationRequests(@NonNull long[] virtualChildIds,
+            @NonNull @DataFormat int[] supportedFormats,
+            @NonNull Consumer<ViewTranslationRequest> requestsCollector) {
+        mProvider.getViewDelegate().onCreateTranslationRequests(virtualChildIds, supportedFormats,
+                requestsCollector);
+    }
+
+    @Override
+    public void onTranslationResponse(@NonNull LongSparseArray<ViewTranslationResponse> response) {
+        mProvider.getViewDelegate().onTranslationResponse(response);
+    }
+
     /** @hide */
     @Override
     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 18a110b..2647360 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.content.Intent;
 import android.content.res.Configuration;
@@ -33,6 +34,7 @@
 import android.os.Handler;
 import android.os.Message;
 import android.print.PrintDocumentAdapter;
+import android.util.LongSparseArray;
 import android.util.SparseArray;
 import android.view.DragEvent;
 import android.view.KeyEvent;
@@ -47,6 +49,9 @@
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 import android.view.textclassifier.TextClassifier;
+import android.view.translation.TranslationSpec.DataFormat;
+import android.view.translation.ViewTranslationRequest;
+import android.view.translation.ViewTranslationResponse;
 import android.webkit.WebView.HitTestResult;
 import android.webkit.WebView.PictureListener;
 import android.webkit.WebView.VisualStateCallback;
@@ -56,6 +61,7 @@
 import java.io.File;
 import java.util.Map;
 import java.util.concurrent.Executor;
+import java.util.function.Consumer;
 
 /**
  * WebView backend provider interface: this interface is the abstract backend to a WebView
@@ -358,6 +364,20 @@
                 @SuppressWarnings("unused") int flags) {
         }
 
+        @SuppressLint("NullableCollection")
+        @Nullable
+        default void onCreateTranslationRequests(
+                @NonNull @SuppressWarnings("unused") long[] virtualChildIds,
+                @NonNull @SuppressWarnings("unused") @DataFormat int[] supportedFormats,
+                @NonNull @SuppressWarnings("unused")
+                        Consumer<ViewTranslationRequest> requestsCollector) {
+        }
+
+        default void onTranslationResponse(
+                @NonNull @SuppressWarnings("unused")
+                        LongSparseArray<ViewTranslationResponse> response) {
+        }
+
         public AccessibilityNodeProvider getAccessibilityNodeProvider();
 
         public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info);
diff --git a/core/java/com/android/internal/accessibility/util/AccessibilityStatsLogUtils.java b/core/java/com/android/internal/accessibility/util/AccessibilityStatsLogUtils.java
index 7baa53b..a600a94 100644
--- a/core/java/com/android/internal/accessibility/util/AccessibilityStatsLogUtils.java
+++ b/core/java/com/android/internal/accessibility/util/AccessibilityStatsLogUtils.java
@@ -133,6 +133,17 @@
                 duration);
     }
 
+    /**
+     * Logs the activated mode of the magnification when the IME window is shown on the screen.
+     * Calls this when the magnification is enabled and the IME window is shown on the screen.
+     *
+     * @param mode The activated magnification mode.
+     */
+    public static void logMagnificationModeWithImeOn(int mode) {
+        FrameworkStatsLog.write(FrameworkStatsLog.MAGNIFICATION_MODE_WITH_IME_ON_REPORTED,
+                convertToLoggingMagnificationMode(mode));
+    }
+
     private static int convertToLoggingShortcutType(@ShortcutType int shortcutType) {
         switch (shortcutType) {
             case ACCESSIBILITY_BUTTON:
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index eecd0cf..01bb199 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -20,6 +20,7 @@
 import android.app.AsyncNotedAppOp;
 import android.app.SyncNotedAppOp;
 import android.app.RuntimeAppOpAccessMessage;
+import android.content.AttributionSource;
 import android.content.pm.ParceledListSlice;
 import android.os.Bundle;
 import android.os.RemoteCallback;
@@ -52,17 +53,13 @@
     // End of methods also called by native code.
     // Any new method exposed to native must be added after the last one, do not reorder
 
-    int noteProxyOperation(int code, int proxiedUid, String proxiedPackageName,
-            String proxiedAttributionTag, int proxyUid, String proxyPackageName,
-            String proxyAttributionTag, boolean shouldCollectAsyncNotedOp, String message,
-            boolean shouldCollectMessage);
-    int startProxyOperation(IBinder clientId, int code, int proxiedUid, String proxiedPackageName,
-            @nullable String proxiedAttributionTag, int proxyUid, String proxyPackageName,
-            @nullable String proxyAttributionTag, boolean startIfModeDefault,
-            boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage);
-    void finishProxyOperation(IBinder clientId, int code, int proxiedUid, String proxiedPackageName,
-            @nullable String proxiedAttributionTag, int proxyUid, String proxyPackageName,
-            @nullable String proxyAttributionTag);
+    int noteProxyOperation(int code, in AttributionSource attributionSource,
+            boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
+            boolean skipProxyOperation);
+    int startProxyOperation(IBinder clientId, int code, in AttributionSource attributionSource,
+            boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message,
+            boolean shouldCollectMessage, boolean skipProxyOperation);
+    void finishProxyOperation(IBinder clientId, int code, in AttributionSource attributionSource);
 
     // Remaining methods are only used in Java.
     int checkPackage(int uid, String packageName);
@@ -83,6 +80,7 @@
     void setHistoryParameters(int mode, long baseSnapshotInterval, int compressionStep);
     void addHistoricalOps(in AppOpsManager.HistoricalOps ops);
     void resetHistoryParameters();
+    void resetPackageOpsNoHistory(String packageName);
     void clearHistory();
     void rebootHistory(long offlineDurationMillis);
     List<AppOpsManager.PackageOps> getUidOps(int uid, in int[] ops);
@@ -100,6 +98,8 @@
     void startWatchingActive(in int[] ops, IAppOpsActiveCallback callback);
     void stopWatchingActive(IAppOpsActiveCallback callback);
     boolean isOperationActive(int code, int uid, String packageName);
+    boolean isProxying(int op, String proxyPackageName, String proxyAttributionTag, int proxiedUid,
+            String proxiedPackageName);
 
     void startWatchingStarted(in int[] ops, IAppOpsStartedCallback callback);
     void stopWatchingStarted(IAppOpsStartedCallback callback);
diff --git a/core/java/com/android/internal/app/IHotwordRecognitionStatusCallback.aidl b/core/java/com/android/internal/app/IHotwordRecognitionStatusCallback.aidl
index 23314e7..9bec505 100644
--- a/core/java/com/android/internal/app/IHotwordRecognitionStatusCallback.aidl
+++ b/core/java/com/android/internal/app/IHotwordRecognitionStatusCallback.aidl
@@ -66,4 +66,12 @@
      * Called when the recognition is resumed after it was temporarily paused.
      */
     void onRecognitionResumed();
+
+    /**
+     * Called when the {@link HotwordDetectionService} reported the result for requesting update
+     * state action.
+     *
+     * @param status The status about the result of requesting update state action.
+     */
+    void onStatusReported(int status);
 }
diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
index bb6233b..fffeb02 100644
--- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
@@ -26,6 +26,7 @@
 import android.os.RemoteCallback;
 import android.os.SharedMemory;
 
+import com.android.internal.app.IHotwordRecognitionStatusCallback;
 import com.android.internal.app.IVoiceActionCheckCallback;
 import com.android.internal.app.IVoiceInteractionSessionShowCallback;
 import com.android.internal.app.IVoiceInteractor;
@@ -238,8 +239,12 @@
      * @param sharedMemory The unrestricted data blob to provide to the
      * {@link HotwordDetectionService}. Use this to provide the hotword models data or other
      * such data to the trusted process.
+     * @param callback Use this to report {@link HotwordDetectionService} status.
      */
-    void updateState(in PersistableBundle options, in SharedMemory sharedMemory);
+    void updateState(
+            in PersistableBundle options,
+            in SharedMemory sharedMemory,
+            in IHotwordRecognitionStatusCallback callback);
 
     /**
      * Requests to shutdown hotword detection service.
diff --git a/core/java/com/android/internal/widget/NotificationExpandButton.java b/core/java/com/android/internal/widget/NotificationExpandButton.java
index fc4cc57..7a8ead6 100644
--- a/core/java/com/android/internal/widget/NotificationExpandButton.java
+++ b/core/java/com/android/internal/widget/NotificationExpandButton.java
@@ -20,6 +20,7 @@
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.ColorStateList;
+import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.view.RemotableViewMethod;
@@ -165,11 +166,13 @@
     private void updateColors() {
         if (shouldShowNumber() && !mDisallowColor) {
             mPillView.setBackgroundTintList(ColorStateList.valueOf(mHighlightPillColor));
-            mIconView.setColorFilter(mHighlightTextColor);
+            mPillView.setBackgroundTintMode(PorterDuff.Mode.SRC_IN);
+            mIconView.setColorFilter(mHighlightTextColor, PorterDuff.Mode.SRC_IN);
             mNumberView.setTextColor(mHighlightTextColor);
         } else {
             mPillView.setBackgroundTintList(ColorStateList.valueOf(mDefaultPillColor));
-            mIconView.setColorFilter(mDefaultTextColor);
+            mPillView.setBackgroundTintMode(PorterDuff.Mode.SRC_IN);
+            mIconView.setColorFilter(mDefaultTextColor, PorterDuff.Mode.SRC_IN);
             mNumberView.setTextColor(mDefaultTextColor);
         }
     }
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 419dc6e..5f41105 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -1460,6 +1460,27 @@
     transaction->reparent(ctrl, newParent);
 }
 
+static void nativeOverrideHdrTypes(JNIEnv* env, jclass clazz, jobject tokenObject,
+                                   jintArray jHdrTypes) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObject));
+    if (token == nullptr || jHdrTypes == nullptr) return;
+
+    int* hdrTypes = env->GetIntArrayElements(jHdrTypes, 0);
+    int numHdrTypes = env->GetArrayLength(jHdrTypes);
+
+    std::vector<ui::Hdr> hdrTypesVector;
+    for (int i = 0; i < numHdrTypes; i++) {
+        hdrTypesVector.push_back(static_cast<ui::Hdr>(hdrTypes[i]));
+    }
+    env->ReleaseIntArrayElements(jHdrTypes, hdrTypes, 0);
+
+    status_t error = SurfaceComposerClient::overrideHdrTypes(token, hdrTypesVector);
+    if (error != NO_ERROR) {
+        jniThrowExceptionFmt(env, "java/lang/SecurityException",
+                             "ACCESS_SURFACE_FLINGER is missing");
+    }
+}
+
 static void nativeSetAutoLowLatencyMode(JNIEnv* env, jclass clazz, jobject tokenObject, jboolean on) {
     sp<IBinder> token(ibinderForJavaObject(env, tokenObject));
     if (token == NULL) return;
@@ -1821,6 +1842,8 @@
             (void*)nativeSetGameContentType },
     {"nativeGetCompositionDataspaces", "()[I",
             (void*)nativeGetCompositionDataspaces},
+    {"nativeOverrideHdrTypes", "(Landroid/os/IBinder;[I)V",
+                (void*)nativeOverrideHdrTypes },
     {"nativeClearContentFrameStats", "(J)Z",
             (void*)nativeClearContentFrameStats },
     {"nativeGetContentFrameStats", "(JLandroid/view/WindowContentFrameStats;)Z",
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index be306e0..00b165e 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1313,7 +1313,7 @@
         android:permissionGroup="android.permission-group.UNDEFINED"
         android:label="@string/permlab_recordBackgroundAudio"
         android:description="@string/permdesc_recordBackgroundAudio"
-        android:protectionLevel="internal" />
+        android:protectionLevel="internal|role" />
 
     <!-- ====================================================================== -->
     <!-- Permissions for activity recognition                        -->
@@ -1405,7 +1405,7 @@
             android:permissionGroup="android.permission-group.UNDEFINED"
             android:label="@string/permlab_backgroundCamera"
             android:description="@string/permdesc_backgroundCamera"
-            android:protectionLevel="internal" />
+            android:protectionLevel="internal|role" />
 
     <!-- @SystemApi Required in addition to android.permission.CAMERA to be able to access
            system only camera devices.
@@ -2016,6 +2016,12 @@
         android:label="@string/permlab_preferredPaymentInfo"
         android:protectionLevel="normal" />
 
+    <!-- @SystemApi Allows access to set NFC controller always on states.
+         <p>Protection level: signature|privileged
+         @hide -->
+    <permission android:name="android.permission.NFC_SET_CONTROLLER_ALWAYS_ON"
+        android:protectionLevel="signature|privileged" />
+
     <!-- @SystemApi Allows an internal user to use privileged SecureElement APIs.
          Applications holding this permission can access OMAPI reset system API
          and bypass OMAPI AccessControlEnforcer.
@@ -5682,6 +5688,12 @@
     <permission android:name="android.permission.RENOUNCE_PERMISSIONS"
                 android:protectionLevel="signature|privileged" />
 
+    <!-- Allows an application to read nearby streaming policy. The policy allows the device
+         to stream its notifications and apps to nearby devices.
+         @hide -->
+    <permission android:name="android.permission.READ_NEARBY_STREAMING_POLICY"
+        android:protectionLevel="signature|privileged" />
+
     <!-- @SystemApi Allows the holder to set the source of the data when setting a clip on the
          clipboard.
          @hide -->
diff --git a/core/res/res/values-television/themes.xml b/core/res/res/values-television/themes.xml
index 176e89e..b023c75 100644
--- a/core/res/res/values-television/themes.xml
+++ b/core/res/res/values-television/themes.xml
@@ -14,14 +14,14 @@
      limitations under the License.
 -->
 <resources>
-    <style name="Theme.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
+    <style name="Theme.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
     <style name="Theme.Dialog.Confirmation" parent="Theme.Leanback.Dialog.Confirmation" />
     <style name="Theme.Holo.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
-    <style name="Theme.Holo.Light.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
+    <style name="Theme.Holo.Light.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
     <style name="Theme.Material.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
-    <style name="Theme.Material.Light.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
+    <style name="Theme.Material.Light.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
     <style name="Theme.Material.Settings.Dialog.Alert" parent="Theme.Leanback.Settings.Dialog.Alert" />
     <style name="Theme.Material.Dialog" parent="Theme.Leanback.Dialog" />
-    <style name="Theme.Material.Light.Dialog" parent="Theme.Leanback.Light.Dialog" />
+    <style name="Theme.Material.Light.Dialog" parent="Theme.Leanback.Dialog" />
     <style name="Theme.Material.Settings.Dialog" parent="Theme.Leanback.Settings.Dialog" />
 </resources>
diff --git a/core/res/res/values-television/themes_device_defaults.xml b/core/res/res/values-television/themes_device_defaults.xml
index d6bdeee..9d0e522 100644
--- a/core/res/res/values-television/themes_device_defaults.xml
+++ b/core/res/res/values-television/themes_device_defaults.xml
@@ -16,7 +16,7 @@
 <resources>
     <style name="Theme.DeviceDefault.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
     <style name="Theme.DeviceDefault.Dialog.AppError" parent="Theme.Leanback.Dialog.AppError" />
-    <style name="Theme.DeviceDefault.Light.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
+    <style name="Theme.DeviceDefault.Light.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
 
     <!-- TODO(b/116457731): remove colorBackground from colors_material.xml if not used anymore -->
     <style name="Theme.DeviceDefault.Autofill" parent="Theme.Material">
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 4b15e01..74f8ff6 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -6070,6 +6070,8 @@
         <attr name="color" />
         <!-- Alpha multiplier applied to the base color. -->
         <attr name="alpha" />
+        <!-- Perceptual luminance applied to the base color. From 0 to 100. -->
+        <attr name="lStar" format="float" />
     </declare-styleable>
 
     <!-- Drawable used to render according to the animation scale. Esp. when it is 0 due to battery
@@ -9535,4 +9537,6 @@
 
     <attr name="iconfactoryIconSize" format="dimension"/>
     <attr name="iconfactoryBadgeSize" format="dimension"/>
+    <!-- Perceptual luminance of a color, in accessibility friendly color space. From 0 to 100. -->
+    <attr name="lStar" format="float"/>
 </resources>
diff --git a/core/res/res/values/colors_leanback.xml b/core/res/res/values/colors_leanback.xml
index df0be03..1b0fad8 100644
--- a/core/res/res/values/colors_leanback.xml
+++ b/core/res/res/values/colors_leanback.xml
@@ -16,15 +16,11 @@
 
 <!-- Colors specific to Leanback themes. -->
 <resources>
-    <color name="background_leanback_dark">#ff324248</color>
-    <color name="background_leanback_light">#ffeeeeee</color>
+    <color name="background_leanback_dark">#FF1F232B</color>
 
     <color name="primary_text_leanback_dark">#cceeeeee</color>
     <color name="secondary_text_leanback_dark">#99eeeeee</color>
 
-    <color name="primary_text_leanback_light">#cc222222</color>
-    <color name="secondary_text_leanback_light">#99222222</color>
-
     <color name="primary_text_leanback_formwizard_default_dark">#ffeeeeee</color>
 
     <color name="btn_leanback_focused">#E8EAED</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b6c22bb..842f12d 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3561,10 +3561,6 @@
     <!-- True if assistant app should be pinned via Pinner Service -->
     <bool name="config_pinnerAssistantApp">false</bool>
 
-    <!-- List of files pinned by the Pinner Service with the JIT Zygote boot image b/119800099 -->
-    <string-array translatable="false" name="config_jitzygoteBootImagePinnerServiceFiles">
-    </string-array>
-
     <!-- Number of days preloaded file cache should be preserved on a device before it can be
          deleted -->
     <integer name="config_keepPreloadsMinDays">7</integer>
diff --git a/core/res/res/values/dimens_leanback.xml b/core/res/res/values/dimens_leanback.xml
index 3ab2196..ecda735 100644
--- a/core/res/res/values/dimens_leanback.xml
+++ b/core/res/res/values/dimens_leanback.xml
@@ -89,4 +89,6 @@
     <dimen name="leanback_button_radius">55dp</dimen>
     <dimen name="leanback_button_padding_horizontal">22dp</dimen>
     <dimen name="leanback_button_padding_vertical">11dp</dimen>
+
+    <dimen name="leanback_dialog_corner_radius">8dp</dimen>
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index bc49818..49039f9 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3095,6 +3095,7 @@
     <public name="requestOptimizedExternalStorageAccess" />
     <!-- @hide @SystemApi -->
     <public name="playHomeTransitionSound" />
+    <public name="lStar" />
   </public-group>
 
   <public-group type="drawable" first-id="0x010800b5">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index dd64750..ce60633 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -745,7 +745,7 @@
 
     <!-- Text shown when viewing channel settings for notifications related to accessibility
          security policy. [CHAR_LIMIT=NONE]-->
-    <string name="notification_channel_accessibility_security_policy">Accessibility security policy</string>
+    <string name="notification_channel_accessibility_security_policy">Accessibility usage</string>
 
     <!-- Label for foreground service notification when one app is running.
     [CHAR LIMIT=NONE BACKUP_MESSAGE_ID=6826789589341671842] -->
@@ -5924,7 +5924,7 @@
     <!-- Notification title to prompt the user that new magnification feature is available. [CHAR LIMIT=50] -->
     <string name="window_magnification_prompt_title">New magnification settings</string>
     <!-- Notification content to prompt the user that new magnification feature is available. [CHAR LIMIT=NONE] -->
-    <string name="window_magnification_prompt_content">You can now magnify part of your screen.</string>
+    <string name="window_magnification_prompt_content">You can now magnify part of your screen</string>
     <!-- Notification action to bring the user to magnification settings page. [CHAR LIMIT=50] -->
     <string name="turn_on_magnification_settings_action">Turn on in Settings</string>
     <!-- Notification action to dismiss. [CHAR LIMIT=50] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index b924ecd..8621147 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3148,7 +3148,6 @@
   <java-symbol type="bool" name="config_pinnerCameraApp" />
   <java-symbol type="bool" name="config_pinnerHomeApp" />
   <java-symbol type="bool" name="config_pinnerAssistantApp" />
-  <java-symbol type="array" name="config_jitzygoteBootImagePinnerServiceFiles" />
 
   <java-symbol type="string" name="config_doubleTouchGestureEnableFile" />
 
diff --git a/core/res/res/values/themes_leanback.xml b/core/res/res/values/themes_leanback.xml
index efe5826..0be9e9800 100644
--- a/core/res/res/values/themes_leanback.xml
+++ b/core/res/res/values/themes_leanback.xml
@@ -15,31 +15,21 @@
 -->
 <resources>
     <style name="Theme.Leanback.Dialog" parent="Theme.Material.BaseDialog">
-      <item name="colorBackground">@color/background_leanback_dark</item>
-      <item name="textColorPrimary">@color/primary_text_leanback_dark</item>
-      <item name="textColorSecondary">@color/secondary_text_leanback_dark</item>
-      <item name="alertDialogStyle">@style/AlertDialog.Leanback</item>
-      <item name="timePickerStyle">@style/Widget.Leanback.TimePicker</item>
-      <item name="datePickerStyle">@style/Widget.Leanback.DatePicker</item>
-      <item name="numberPickerStyle">@style/Widget.Leanback.NumberPicker</item>
-      <item name="buttonBarButtonStyle">@style/Widget.Leanback.Button.ButtonBarGravityStart</item>
-      <item name="buttonBarStyle">@style/Widget.Leanback.ButtonBar</item>
-    </style>
-
-    <style name="Theme.Leanback.Light.Dialog" parent="Theme.Material.Light.BaseDialog">
-      <item name="colorBackground">@color/background_leanback_dark</item>
-      <item name="textColorPrimary">@color/primary_text_leanback_dark</item>
-      <item name="textColorSecondary">@color/secondary_text_leanback_dark</item>
-      <item name="alertDialogStyle">@style/AlertDialog.Leanback</item>
-      <item name="timePickerStyle">@style/Widget.Leanback.TimePicker</item>
-      <item name="datePickerStyle">@style/Widget.Leanback.DatePicker</item>
-      <item name="numberPickerStyle">@style/Widget.Leanback.NumberPicker</item>
+        <item name="colorBackground">@color/background_leanback_dark</item>
+        <item name="dialogCornerRadius">@dimen/leanback_dialog_corner_radius</item>
+        <item name="textColorPrimary">@color/primary_text_leanback_dark</item>
+        <item name="textColorSecondary">@color/secondary_text_leanback_dark</item>
+        <item name="alertDialogStyle">@style/AlertDialog.Leanback</item>
+        <item name="timePickerStyle">@style/Widget.Leanback.TimePicker</item>
+        <item name="datePickerStyle">@style/Widget.Leanback.DatePicker</item>
+        <item name="numberPickerStyle">@style/Widget.Leanback.NumberPicker</item>
         <item name="buttonBarButtonStyle">@style/Widget.Leanback.Button.ButtonBarGravityStart</item>
-      <item name="buttonBarStyle">@style/Widget.Leanback.ButtonBar</item>
+        <item name="buttonBarStyle">@style/Widget.Leanback.ButtonBar</item>
     </style>
 
     <style name="Theme.Leanback.Settings.Dialog" parent="Theme.Material.Settings.BaseDialog">
         <item name="colorBackground">@color/background_leanback_dark</item>
+        <item name="dialogCornerRadius">@dimen/leanback_dialog_corner_radius</item>
         <item name="textColorPrimary">@color/primary_text_leanback_dark</item>
         <item name="textColorSecondary">@color/secondary_text_leanback_dark</item>
         <item name="alertDialogStyle">@style/AlertDialog.Leanback</item>
@@ -51,34 +41,25 @@
     </style>
 
     <style name="Theme.Leanback.Dialog.Alert" parent="Theme.Material.Dialog.BaseAlert">
-      <item name="colorBackground">@color/background_leanback_dark</item>
-      <item name="textColorPrimary">@color/primary_text_leanback_dark</item>
-      <item name="textColorSecondary">@color/secondary_text_leanback_dark</item>
-      <item name="alertDialogStyle">@style/AlertDialog.Leanback</item>
-      <item name="timePickerStyle">@style/Widget.Leanback.TimePicker</item>
-      <item name="datePickerStyle">@style/Widget.Leanback.DatePicker</item>
-      <item name="numberPickerStyle">@style/Widget.Leanback.NumberPicker</item>
-      <item name="buttonBarButtonStyle">@style/Widget.Leanback.Button.ButtonBarGravityStart</item>
-      <item name="buttonBarStyle">@style/Widget.Leanback.ButtonBar</item>
-    </style>
-
-    <style name="Theme.Leanback.Light.Dialog.Alert" parent="Theme.Material.Light.Dialog.BaseAlert">
-      <item name="colorBackground">@color/background_leanback_light</item>
-      <item name="textColorPrimary">@color/primary_text_leanback_light</item>
-      <item name="textColorSecondary">@color/secondary_text_leanback_light</item>
-      <item name="alertDialogStyle">@style/AlertDialog.Leanback.Light</item>
-      <item name="timePickerStyle">@style/Widget.Leanback.TimePicker</item>
-      <item name="datePickerStyle">@style/Widget.Leanback.DatePicker</item>
-      <item name="numberPickerStyle">@style/Widget.Leanback.NumberPicker</item>
+        <item name="colorBackground">@color/background_leanback_dark</item>
+        <item name="dialogCornerRadius">@dimen/leanback_dialog_corner_radius</item>
+        <item name="textColorPrimary">@color/primary_text_leanback_dark</item>
+        <item name="textColorSecondary">@color/secondary_text_leanback_dark</item>
+        <item name="alertDialogStyle">@style/AlertDialog.Leanback</item>
+        <item name="timePickerStyle">@style/Widget.Leanback.TimePicker</item>
+        <item name="datePickerStyle">@style/Widget.Leanback.DatePicker</item>
+        <item name="numberPickerStyle">@style/Widget.Leanback.NumberPicker</item>
         <item name="buttonBarButtonStyle">@style/Widget.Leanback.Button.ButtonBarGravityStart</item>
-      <item name="buttonBarStyle">@style/Widget.Leanback.ButtonBar</item>
+        <item name="buttonBarStyle">@style/Widget.Leanback.ButtonBar</item>
     </style>
 
-    <style name="Theme.Leanback.Settings.Dialog.Alert" parent="Theme.Material.Settings.Dialog.BaseAlert">
-        <item name="colorBackground">@color/background_leanback_light</item>
-        <item name="textColorPrimary">@color/primary_text_leanback_light</item>
-        <item name="textColorSecondary">@color/secondary_text_leanback_light</item>
-        <item name="alertDialogStyle">@style/AlertDialog.Leanback.Light</item>
+    <style name="Theme.Leanback.Settings.Dialog.Alert"
+           parent="Theme.Material.Settings.Dialog.BaseAlert">
+        <item name="colorBackground">@color/background_leanback_dark</item>
+        <item name="dialogCornerRadius">@dimen/leanback_dialog_corner_radius</item>
+        <item name="textColorPrimary">@color/primary_text_leanback_dark</item>
+        <item name="textColorSecondary">@color/secondary_text_leanback_dark</item>
+        <item name="alertDialogStyle">@style/AlertDialog.Leanback</item>
         <item name="timePickerStyle">@style/Widget.Leanback.TimePicker</item>
         <item name="datePickerStyle">@style/Widget.Leanback.DatePicker</item>
         <item name="numberPickerStyle">@style/Widget.Leanback.NumberPicker</item>
@@ -144,9 +125,9 @@
         <!-- Icon sizes -->
         <item name="iconfactoryIconSize">@dimen/resolver_icon_size</item>
         <item name="iconfactoryBadgeSize">@dimen/resolver_badge_size</item>
-      </style>
+    </style>
 
     <!-- @hide Special theme for the default system Activity-based Alert dialogs. -->
-    <style name="Theme.Leanback.Dialog.Confirmation" parent="Theme.DeviceDefault.Dialog.Alert" />
+    <style name="Theme.Leanback.Dialog.Confirmation" parent="Theme.DeviceDefault.Dialog.Alert"/>
 
 </resources>
diff --git a/core/tests/coretests/src/android/content/ContentResolverTest.java b/core/tests/coretests/src/android/content/ContentResolverTest.java
index b517428..01e240a 100644
--- a/core/tests/coretests/src/android/content/ContentResolverTest.java
+++ b/core/tests/coretests/src/android/content/ContentResolverTest.java
@@ -86,7 +86,7 @@
 
         final AssetFileDescriptor afd = new AssetFileDescriptor(
                 new ParcelFileDescriptor(mImage.getFileDescriptor()), 0, mSize, null);
-        when(mProvider.openTypedAssetFile(any(), any(), any(), any(), any(), any())).thenReturn(
+        when(mProvider.openTypedAssetFile(any(), any(), any(), any(), any())).thenReturn(
                 afd);
     }
 
diff --git a/core/tests/coretests/src/android/provider/NameValueCacheTest.java b/core/tests/coretests/src/android/provider/NameValueCacheTest.java
index 4212ef2..97e66c4 100644
--- a/core/tests/coretests/src/android/provider/NameValueCacheTest.java
+++ b/core/tests/coretests/src/android/provider/NameValueCacheTest.java
@@ -33,6 +33,7 @@
 import android.util.MemoryIntArray;
 
 import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
@@ -73,7 +74,8 @@
         Settings.Config.clearProviderForTest();
         MockitoAnnotations.initMocks(this);
         when(mMockContentProvider.getIContentProvider()).thenReturn(mMockIContentProvider);
-        mMockContentResolver = new MockContentResolver();
+        mMockContentResolver = new MockContentResolver(InstrumentationRegistry
+                .getInstrumentation().getContext());
         mMockContentResolver.addProvider(DeviceConfig.CONTENT_URI.getAuthority(),
                 mMockContentProvider);
         mCacheGenerationStore = new MemoryIntArray(1);
@@ -82,10 +84,10 @@
         // Stores keyValues for a given prefix and increments the generation. (Note that this
         // increments the generation no matter what, it doesn't pay attention to if anything
         // actually changed).
-        when(mMockIContentProvider.call(any(), any(), eq(DeviceConfig.CONTENT_URI.getAuthority()),
+        when(mMockIContentProvider.call(any(), eq(DeviceConfig.CONTENT_URI.getAuthority()),
                 eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
                 any(), any(Bundle.class))).thenAnswer(invocationOnMock -> {
-                    Bundle incomingBundle = invocationOnMock.getArgument(5);
+                    Bundle incomingBundle = invocationOnMock.getArgument(4);
                     HashMap<String, String> keyValues =
                             (HashMap<String, String>) incomingBundle.getSerializable(
                                     Settings.CALL_METHOD_FLAGS_KEY);
@@ -101,10 +103,10 @@
         // Returns the keyValues corresponding to a namespace, or an empty map if the namespace
         // doesn't have anything stored for it. Returns the generation key if the caller asked
         // for one.
-        when(mMockIContentProvider.call(any(), any(), eq(DeviceConfig.CONTENT_URI.getAuthority()),
+        when(mMockIContentProvider.call(any(), eq(DeviceConfig.CONTENT_URI.getAuthority()),
                 eq(Settings.CALL_METHOD_LIST_CONFIG),
                 any(), any(Bundle.class))).thenAnswer(invocationOnMock -> {
-                    Bundle incomingBundle = invocationOnMock.getArgument(5);
+                    Bundle incomingBundle = invocationOnMock.getArgument(4);
 
                     String prefix = incomingBundle.getString(Settings.CALL_METHOD_PREFIX_KEY);
 
@@ -132,14 +134,14 @@
         HashMap<String, String> keyValues = new HashMap<>();
         keyValues.put("a", "b");
         Settings.Config.setStrings(mMockContentResolver, NAMESPACE, keyValues);
-        verify(mMockIContentProvider).call(any(), any(), any(),
+        verify(mMockIContentProvider).call(any(), any(),
                 eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
                 any(), any(Bundle.class));
 
         Map<String, String> returnedValues = Settings.Config.getStrings(mMockContentResolver,
                 NAMESPACE,
                 Collections.emptyList());
-        verify(mMockIContentProvider).call(any(), any(), any(),
+        verify(mMockIContentProvider).call(any(), any(),
                 eq(Settings.CALL_METHOD_LIST_CONFIG),
                 any(), any(Bundle.class));
         assertThat(returnedValues).containsExactlyEntriesIn(keyValues);
@@ -152,13 +154,13 @@
         // Modify the value to invalidate the cache.
         keyValues.put("a", "c");
         Settings.Config.setStrings(mMockContentResolver, NAMESPACE, keyValues);
-        verify(mMockIContentProvider, times(2)).call(any(), any(), any(),
+        verify(mMockIContentProvider, times(2)).call(any(), any(),
                 eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
                 any(), any(Bundle.class));
 
         Map<String, String> returnedValues2 = Settings.Config.getStrings(mMockContentResolver,
                 NAMESPACE, Collections.emptyList());
-        verify(mMockIContentProvider, times(2)).call(any(), any(), any(),
+        verify(mMockIContentProvider, times(2)).call(any(), any(),
                 eq(Settings.CALL_METHOD_LIST_CONFIG),
                 any(), any(Bundle.class));
         assertThat(returnedValues2).containsExactlyEntriesIn(keyValues);
@@ -174,7 +176,7 @@
         HashMap<String, String> keyValues = new HashMap<>();
         keyValues.put("a", "b");
         Settings.Config.setStrings(mMockContentResolver, NAMESPACE, keyValues);
-        verify(mMockIContentProvider).call(any(), any(), any(),
+        verify(mMockIContentProvider).call(any(), any(),
                 eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
                 any(), any(Bundle.class));
 
@@ -182,14 +184,14 @@
         keyValues2.put("c", "d");
         keyValues2.put("e", "f");
         Settings.Config.setStrings(mMockContentResolver, NAMESPACE2, keyValues2);
-        verify(mMockIContentProvider, times(2)).call(any(), any(), any(),
+        verify(mMockIContentProvider, times(2)).call(any(), any(),
                 eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
                 any(), any(Bundle.class));
 
         Map<String, String> returnedValues = Settings.Config.getStrings(mMockContentResolver,
                 NAMESPACE,
                 Collections.emptyList());
-        verify(mMockIContentProvider).call(any(), any(), any(),
+        verify(mMockIContentProvider).call(any(), any(),
                 eq(Settings.CALL_METHOD_LIST_CONFIG),
                 any(), any(Bundle.class));
         assertThat(returnedValues).containsExactlyEntriesIn(keyValues);
@@ -197,7 +199,7 @@
         Map<String, String> returnedValues2 = Settings.Config.getStrings(mMockContentResolver,
                 NAMESPACE2,
                 Collections.emptyList());
-        verify(mMockIContentProvider, times(2)).call(any(), any(), any(),
+        verify(mMockIContentProvider, times(2)).call(any(), any(),
                 eq(Settings.CALL_METHOD_LIST_CONFIG),
                 any(), any(Bundle.class));
         assertThat(returnedValues2).containsExactlyEntriesIn(keyValues2);
@@ -218,7 +220,7 @@
         Map<String, String> returnedValues = Settings.Config.getStrings(mMockContentResolver,
                 NAMESPACE,
                 Collections.emptyList());
-        verify(mMockIContentProvider).call(any(), any(), any(),
+        verify(mMockIContentProvider).call(any(), any(),
                 eq(Settings.CALL_METHOD_LIST_CONFIG),
                 any(), any(Bundle.class));
         assertThat(returnedValues).isEmpty();
diff --git a/core/tests/coretests/src/android/provider/TestDocumentsProvider.java b/core/tests/coretests/src/android/provider/TestDocumentsProvider.java
index 5f640be..4496983 100644
--- a/core/tests/coretests/src/android/provider/TestDocumentsProvider.java
+++ b/core/tests/coretests/src/android/provider/TestDocumentsProvider.java
@@ -18,13 +18,13 @@
 
 import android.annotation.Nullable;
 import android.app.AppOpsManager;
+import android.content.AttributionSource;
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.pm.ProviderInfo;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.CancellationSignal;
-import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
 import android.provider.DocumentsContract.Path;
 
@@ -93,14 +93,12 @@
     }
 
     @Override
-    protected int enforceReadPermissionInner(Uri uri, String callingPkg,
-            @Nullable String callingFeatureId, IBinder callerToken) {
+    protected int enforceReadPermissionInner(Uri uri, AttributionSource attributionSource) {
         return AppOpsManager.MODE_ALLOWED;
     }
 
     @Override
-    protected int enforceWritePermissionInner(Uri uri, String callingPkg,
-            @Nullable String callingFeatureId, IBinder callerToken) {
+    protected int enforceWritePermissionInner(Uri uri, AttributionSource attributionSource) {
         return AppOpsManager.MODE_ALLOWED;
     }
 
diff --git a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
index 47556c3..34a1fd8 100644
--- a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
@@ -97,7 +97,7 @@
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
             // test if setVisibility can show IME
-            mImeConsumer.onWindowFocusGained();
+            mImeConsumer.onWindowFocusGained(true);
             mController.show(WindowInsets.Type.ime(), true /* fromIme */);
             mController.cancelExistingAnimations();
             assertTrue(mController.getSourceConsumer(ime.getType()).isRequestedVisible());
@@ -116,7 +116,7 @@
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
             // Request IME visible before control is available.
-            mImeConsumer.onWindowFocusGained();
+            mImeConsumer.onWindowFocusGained(true);
             mController.show(WindowInsets.Type.ime(), true /* fromIme */);
 
             // set control and verify visibility is applied.
@@ -132,24 +132,58 @@
     }
 
     @Test
-    public void testImeGetAndClearSkipAnimationOnce() {
+    public void testImeGetAndClearSkipAnimationOnce_expectSkip() {
+        // Expect IME animation will skipped when the IME is visible at first place.
+        verifyImeGetAndClearSkipAnimationOnce(true /* hasWindowFocus */, true /* hasViewFocus */,
+                true /* expectSkipAnim */);
+    }
+
+    @Test
+    public void testImeGetAndClearSkipAnimationOnce_expectNoSkip() {
+        // Expect IME animation will not skipped if previously no view focused when gained the
+        // window focus and requesting the IME visible next time.
+        verifyImeGetAndClearSkipAnimationOnce(true /* hasWindowFocus */, false /* hasViewFocus */,
+                false /* expectSkipAnim */);
+    }
+
+    private void verifyImeGetAndClearSkipAnimationOnce(boolean hasWindowFocus, boolean hasViewFocus,
+            boolean expectSkipAnim) {
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
             // Request IME visible before control is available.
-            mImeConsumer.onWindowFocusGained();
-            mController.show(WindowInsets.Type.ime(), true /* fromIme */);
+            mImeConsumer.onWindowFocusGained(hasWindowFocus);
+            final boolean imeVisible = hasWindowFocus && hasViewFocus;
+            if (imeVisible) {
+                mController.show(WindowInsets.Type.ime(), true /* fromIme */);
+            }
 
             // set control and verify visibility is applied.
             InsetsSourceControl control = Mockito.spy(
                     new InsetsSourceControl(ITYPE_IME, mLeash, new Point(), Insets.NONE));
             // Simulate IME source control set this flag when the target has starting window.
             control.setSkipAnimationOnce(true);
-            mController.onControlsChanged(new InsetsSourceControl[] { control });
-            // Verify IME show animation should be triggered when control becomes available and
-            // the animation will be skipped by getAndClearSkipAnimationOnce invoked.
-            verify(control).getAndClearSkipAnimationOnce();
-            verify(mController).applyAnimation(
-                    eq(WindowInsets.Type.ime()), eq(true) /* show */, eq(false) /* fromIme */,
-                    eq(true) /* skipAnim */);
+
+            if (imeVisible) {
+                // Verify IME applyAnimation should be triggered when control becomes available,
+                // and expect skip animation state after getAndClearSkipAnimationOnce invoked.
+                mController.onControlsChanged(new InsetsSourceControl[]{ control });
+                verify(control).getAndClearSkipAnimationOnce();
+                verify(mController).applyAnimation(eq(WindowInsets.Type.ime()),
+                        eq(true) /* show */, eq(false) /* fromIme */,
+                        eq(expectSkipAnim) /* skipAnim */);
+            }
+
+            // If previously hasViewFocus is false, verify when requesting the IME visible next
+            // time will not skip animation.
+            if (!hasViewFocus) {
+                mController.show(WindowInsets.Type.ime(), true);
+                mController.onControlsChanged(new InsetsSourceControl[]{ control });
+                // Verify IME show animation should be triggered when control becomes available and
+                // the animation will be skipped by getAndClearSkipAnimationOnce invoked.
+                verify(control).getAndClearSkipAnimationOnce();
+                verify(mController).applyAnimation(eq(WindowInsets.Type.ime()),
+                        eq(true) /* show */, eq(true) /* fromIme */,
+                        eq(false) /* skipAnim */);
+            }
         });
     }
 }
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index 4390546..6301f32 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -234,7 +234,7 @@
         InsetsSourceControl ime = controls[2];
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
-            mController.getSourceConsumer(ITYPE_IME).onWindowFocusGained();
+            mController.getSourceConsumer(ITYPE_IME).onWindowFocusGained(true);
             // since there is no focused view, forcefully make IME visible.
             mController.show(Type.ime(), true /* fromIme */);
             mController.show(Type.all());
@@ -260,7 +260,7 @@
         InsetsSourceControl ime = createControl(ITYPE_IME);
         mController.onControlsChanged(new InsetsSourceControl[] { ime });
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
-            mController.getSourceConsumer(ITYPE_IME).onWindowFocusGained();
+            mController.getSourceConsumer(ITYPE_IME).onWindowFocusGained(true);
             mController.show(Type.ime(), true /* fromIme */);
             mController.cancelExistingAnimations();
             assertTrue(mController.getSourceConsumer(ime.getType()).isRequestedVisible());
diff --git a/data/etc/OWNERS b/data/etc/OWNERS
index 549e074..5aacfdd 100644
--- a/data/etc/OWNERS
+++ b/data/etc/OWNERS
@@ -13,3 +13,4 @@
 yamasani@google.com
 
 per-file preinstalled-packages* = file:/MULTIUSER_OWNERS
+per-file services.core.protolog.json =  file:/services/core/java/com/android/server/wm/OWNERS
diff --git a/keystore/java/android/security/KeyStore2.java b/keystore/java/android/security/KeyStore2.java
index 75e248e..df579bb 100644
--- a/keystore/java/android/security/KeyStore2.java
+++ b/keystore/java/android/security/KeyStore2.java
@@ -125,6 +125,8 @@
         }
     }
 
+    private static final String KEYSTORE2_SERVICE_NAME =
+            "android.system.keystore2.IKeystoreService/default";
 
     private KeyStore2() {
         mBinder = null;
@@ -137,7 +139,7 @@
     private synchronized IKeystoreService getService(boolean retryLookup) {
         if (mBinder == null || retryLookup) {
             mBinder = IKeystoreService.Stub.asInterface(ServiceManager
-                    .getService("android.system.keystore2"));
+                    .getService(KEYSTORE2_SERVICE_NAME));
         }
         return mBinder;
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java
index d90cc47..c7dbe88 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java
@@ -23,7 +23,6 @@
 import android.util.Log;
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
-import android.view.WindowManager;
 import android.window.DisplayAreaAppearedInfo;
 import android.window.DisplayAreaInfo;
 import android.window.DisplayAreaOrganizer;
@@ -34,8 +33,9 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.wm.shell.R;
-import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.DisplayLayout;
 
+import java.io.PrintWriter;
 import java.util.List;
 import java.util.concurrent.Executor;
 
@@ -52,12 +52,15 @@
     private final SurfaceSession mSurfaceSession = new SurfaceSession();
     private final float[] mColor;
     private final float mAlpha;
-    private final Rect mRect;
     private final Executor mMainExecutor;
-    private final Rect mDisplaySize;
     private final OneHandedSurfaceTransactionHelper.SurfaceControlTransactionFactory
             mSurfaceControlTransactionFactory;
 
+    /**
+     * The background to distinguish the boundary of translated windows and empty region when
+     * one handed mode triggered.
+     */
+    private Rect mBkgBounds;
     @VisibleForTesting
     @GuardedBy("mLock")
     boolean mIsShowing;
@@ -82,15 +85,19 @@
         mMainExecutor.execute(() -> removeBackgroundPanelLayer());
     }
 
-    public OneHandedBackgroundPanelOrganizer(Context context, WindowManager windowManager,
-            DisplayController displayController, Executor executor) {
+    public OneHandedBackgroundPanelOrganizer(Context context, DisplayLayout displayLayout,
+            Executor executor) {
         super(executor);
-        mDisplaySize = windowManager.getCurrentWindowMetrics().getBounds();
         final Resources res = context.getResources();
         final float defaultRGB = res.getFloat(R.dimen.config_one_handed_background_rgb);
         mColor = new float[]{defaultRGB, defaultRGB, defaultRGB};
         mAlpha = res.getFloat(R.dimen.config_one_handed_background_alpha);
-        mRect = new Rect(0, 0, mDisplaySize.width(), mDisplaySize.height());
+        // Ensure the mBkgBounds is portrait, due to OHM only support on portrait
+        if (displayLayout.height() > displayLayout.width()) {
+            mBkgBounds = new Rect(0, 0, displayLayout.width(), displayLayout.height());
+        } else {
+            mBkgBounds = new Rect(0, 0, displayLayout.height(), displayLayout.width());
+        }
         mMainExecutor = executor;
         mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new;
     }
@@ -144,6 +151,7 @@
             if (mBackgroundSurface == null) {
                 mBackgroundSurface = new SurfaceControl.Builder(mSurfaceSession)
                         .setParent(mParentLeash)
+                        .setBufferSize(mBkgBounds.width(), mBkgBounds.height())
                         .setColorLayer()
                         .setFormat(PixelFormat.RGBA_8888)
                         .setOpaque(false)
@@ -188,11 +196,19 @@
 
             SurfaceControl.Transaction transaction =
                     mSurfaceControlTransactionFactory.getTransaction();
-            transaction.remove(mBackgroundSurface);
-            transaction.apply();
+            transaction.remove(mBackgroundSurface).apply();
             transaction.close();
             mBackgroundSurface = null;
             mIsShowing = false;
         }
     }
+
+    void dump(@NonNull PrintWriter pw) {
+        final String innerPrefix = "  ";
+        pw.println(TAG + "states: ");
+        pw.print(innerPrefix + "mIsShowing=");
+        pw.println(mIsShowing);
+        pw.print(innerPrefix + "mBkgBounds=");
+        pw.println(mBkgBounds);
+    }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
index 25968eb..7965a80 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
@@ -17,10 +17,10 @@
 package com.android.wm.shell.onehanded;
 
 import static android.os.UserHandle.USER_CURRENT;
+import static android.view.Display.DEFAULT_DISPLAY;
 
 import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
 
-import android.Manifest;
 import android.annotation.BinderThread;
 import android.content.ComponentName;
 import android.content.Context;
@@ -28,13 +28,13 @@
 import android.content.om.OverlayInfo;
 import android.content.res.Configuration;
 import android.database.ContentObserver;
-import android.graphics.Rect;
 import android.os.Handler;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.provider.Settings;
 import android.util.Slog;
+import android.view.Surface;
 import android.view.ViewConfiguration;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityManager;
@@ -47,7 +47,7 @@
 import com.android.wm.shell.R;
 import com.android.wm.shell.common.DisplayChangeController;
 import com.android.wm.shell.common.DisplayController;
-import com.android.wm.shell.common.ExecutorUtils;
+import com.android.wm.shell.common.DisplayLayout;
 import com.android.wm.shell.common.RemoteCallable;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.TaskStackListenerCallback;
@@ -76,9 +76,10 @@
     private boolean mLockedDisabled;
     private float mOffSetFraction;
 
-    private final Context mContext;
+    private Context mContext;
+
+    private final AccessibilityManager mAccessibilityManager;
     private final DisplayController mDisplayController;
-    private final OneHandedGestureHandler mGestureHandler;
     private final OneHandedSettingsUtil mOneHandedSettingsUtil;
     private final OneHandedTimeoutHandler mTimeoutHandler;
     private final OneHandedTouchHandler mTouchHandler;
@@ -89,10 +90,9 @@
     private final ShellExecutor mMainExecutor;
     private final Handler mMainHandler;
     private final OneHandedImpl mImpl = new OneHandedImpl();
-    private final WindowManager mWindowManager;
 
     private OneHandedDisplayAreaOrganizer mDisplayAreaOrganizer;
-    private final AccessibilityManager mAccessibilityManager;
+    private OneHandedGestureHandler mGestureHandler;
     private OneHandedBackgroundPanelOrganizer mBackgroundPanelOrganizer;
 
     /**
@@ -100,8 +100,29 @@
      */
     private final DisplayChangeController.OnDisplayChangingListener mRotationController =
             (display, fromRotation, toRotation, wct) -> {
-                if (mDisplayAreaOrganizer != null) {
-                    mDisplayAreaOrganizer.onRotateDisplay(fromRotation, toRotation, wct);
+                if (!isInitialized()) {
+                    return;
+                }
+                mDisplayAreaOrganizer.onRotateDisplay(mContext, toRotation, wct);
+                mGestureHandler.onRotateDisplay(mDisplayAreaOrganizer.getDisplayLayout());
+            };
+
+    private final DisplayController.OnDisplaysChangedListener mDisplaysChangedListener =
+            new DisplayController.OnDisplaysChangedListener() {
+                @Override
+                public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
+                    if (displayId != DEFAULT_DISPLAY || !isInitialized()) {
+                        return;
+                    }
+                    updateDisplayLayout(displayId);
+                }
+
+                @Override
+                public void onDisplayAdded(int displayId) {
+                    if (displayId != DEFAULT_DISPLAY || !isInitialized()) {
+                        return;
+                    }
+                    updateDisplayLayout(displayId);
                 }
             };
 
@@ -115,8 +136,7 @@
             new AccessibilityManager.AccessibilityStateChangeListener() {
                 @Override
                 public void onAccessibilityStateChanged(boolean enabled) {
-                    if (mOneHandedSettingsUtil == null) {
-                        Slog.w(TAG, "mOneHandedSettingsUtil may not instantiate yet");
+                    if (!isInitialized()) {
                         return;
                     }
                     if (enabled) {
@@ -147,6 +167,14 @@
                 }
             };
 
+    private boolean isInitialized() {
+        if (mDisplayAreaOrganizer == null || mDisplayController == null
+                || mGestureHandler == null || mOneHandedSettingsUtil == null) {
+            Slog.w(TAG, "Components may not initialized yet!");
+            return false;
+        }
+        return true;
+    }
 
     /**
      * Creates {@link OneHandedController}, returns {@code null} if the feature is not supported.
@@ -154,8 +182,8 @@
     @Nullable
     public static OneHandedController create(
             Context context, WindowManager windowManager, DisplayController displayController,
-            TaskStackListenerImpl taskStackListener, UiEventLogger uiEventLogger,
-            ShellExecutor mainExecutor, Handler mainHandler) {
+            DisplayLayout displayLayout, TaskStackListenerImpl taskStackListener,
+            UiEventLogger uiEventLogger, ShellExecutor mainExecutor, Handler mainHandler) {
         if (!SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false)) {
             Slog.w(TAG, "Device doesn't support OneHanded feature");
             return null;
@@ -169,19 +197,17 @@
         OneHandedTouchHandler touchHandler = new OneHandedTouchHandler(timeoutHandler,
                 mainExecutor);
         OneHandedGestureHandler gestureHandler = new OneHandedGestureHandler(
-                context, windowManager, displayController, ViewConfiguration.get(context),
-                mainExecutor);
+                context, displayLayout, ViewConfiguration.get(context), mainExecutor);
         OneHandedBackgroundPanelOrganizer oneHandedBackgroundPanelOrganizer =
-                new OneHandedBackgroundPanelOrganizer(context, windowManager, displayController,
-                        mainExecutor);
+                new OneHandedBackgroundPanelOrganizer(context, displayLayout, mainExecutor);
         OneHandedDisplayAreaOrganizer organizer = new OneHandedDisplayAreaOrganizer(
-                context, windowManager, animationController, tutorialHandler,
+                context, displayLayout, animationController, tutorialHandler,
                 oneHandedBackgroundPanelOrganizer, mainExecutor);
         OneHandedSettingsUtil settingsUtil = new OneHandedSettingsUtil();
         OneHandedUiEventLogger oneHandedUiEventsLogger = new OneHandedUiEventLogger(uiEventLogger);
         IOverlayManager overlayManager = IOverlayManager.Stub.asInterface(
                 ServiceManager.getService(Context.OVERLAY_SERVICE));
-        return new OneHandedController(context, windowManager, displayController,
+        return new OneHandedController(context, displayController,
                 oneHandedBackgroundPanelOrganizer, organizer, touchHandler, tutorialHandler,
                 gestureHandler, settingsUtil, timeoutHandler, oneHandedUiEventsLogger,
                 overlayManager, taskStackListener, mainExecutor, mainHandler);
@@ -189,7 +215,6 @@
 
     @VisibleForTesting
     OneHandedController(Context context,
-            WindowManager windowManager,
             DisplayController displayController,
             OneHandedBackgroundPanelOrganizer backgroundPanelOrganizer,
             OneHandedDisplayAreaOrganizer displayAreaOrganizer,
@@ -205,7 +230,6 @@
             Handler mainHandler) {
         mContext = context;
         mOneHandedSettingsUtil = settingsUtil;
-        mWindowManager = windowManager;
         mBackgroundPanelOrganizer = backgroundPanelOrganizer;
         mDisplayAreaOrganizer = displayAreaOrganizer;
         mDisplayController = displayController;
@@ -218,6 +242,7 @@
         mOneHandedUiEventLogger = uiEventsLogger;
         mTaskStackListener = taskStackListener;
 
+        mDisplayController.addDisplayWindowListener(mDisplaysChangedListener);
         final float offsetPercentageConfig = context.getResources().getFraction(
                 R.fraction.config_one_handed_offset, 1, 1);
         final int sysPropPercentageConfig = SystemProperties.getInt(
@@ -297,8 +322,14 @@
             Slog.d(TAG, "Temporary lock disabled");
             return;
         }
+        final int currentRotation = mDisplayAreaOrganizer.getDisplayLayout().rotation();
+        if (currentRotation != Surface.ROTATION_0 && currentRotation != Surface.ROTATION_180) {
+            Slog.w(TAG, "One handed mode only support portrait mode");
+            return;
+        }
         if (!mDisplayAreaOrganizer.isInOneHanded()) {
-            final int yOffSet = Math.round(getDisplaySize().height() * mOffSetFraction);
+            final int yOffSet = Math.round(
+                    mDisplayAreaOrganizer.getDisplayLayout().height() * mOffSetFraction);
             mDisplayAreaOrganizer.scheduleOffset(0, yOffSet);
             mTimeoutHandler.resetTimer();
 
@@ -371,6 +402,12 @@
                 .getSettingsSwipeToNotificationEnabled(mContext.getContentResolver()));
     }
 
+    private void updateDisplayLayout(int displayId) {
+        mDisplayAreaOrganizer.setDisplayLayout(
+                mDisplayController.getDisplayLayout(displayId));
+        mGestureHandler.onDisplayChanged(mDisplayAreaOrganizer.getDisplayLayout());
+    }
+
     private ContentObserver getObserver(Runnable onChangeRunnable) {
         return new ContentObserver(mMainHandler) {
             @Override
@@ -454,24 +491,6 @@
                 OneHandedUiEventLogger.EVENT_ONE_HANDED_TRIGGER_TIMEOUT_OUT));
     }
 
-    /**
-     * Query the current display real size from {@link WindowManager}
-     *
-     * @return {@link WindowManager#getCurrentWindowMetrics()#getBounds()}
-     */
-    private Rect getDisplaySize() {
-        if (mWindowManager == null) {
-            Slog.e(TAG, "WindowManager instance is null! Can not get display size!");
-            return new Rect();
-        }
-        final Rect displaySize = mWindowManager.getCurrentWindowMetrics().getBounds();
-        if (displaySize.width() == 0 || displaySize.height() == 0) {
-            Slog.e(TAG, "Display size error! width = " + displaySize.width()
-                    + ", height = " + displaySize.height());
-        }
-        return displaySize;
-    }
-
     @VisibleForTesting
     boolean isLockedDisabled() {
         return mLockedDisabled;
@@ -483,7 +502,7 @@
         }
 
         mTouchHandler.onOneHandedEnabled(mIsOneHandedEnabled);
-        mGestureHandler.onOneHandedEnabled(mIsOneHandedEnabled || mIsSwipeToNotificationEnabled);
+        mGestureHandler.onGestureEnabled(mIsOneHandedEnabled || mIsSwipeToNotificationEnabled);
 
         if (!mIsOneHandedEnabled) {
             mDisplayAreaOrganizer.unregisterOrganizer();
@@ -532,10 +551,15 @@
 
     @VisibleForTesting
     void setLockedDisabled(boolean locked, boolean enabled) {
-        if (enabled == mIsOneHandedEnabled) {
+        final boolean isFeatureEnabled = mIsOneHandedEnabled || mIsSwipeToNotificationEnabled;
+
+        if (enabled == isFeatureEnabled) {
             return;
         }
         mLockedDisabled = locked && !enabled;
+
+        // Disabled gesture when keyguard ON
+        mGestureHandler.onGestureEnabled(!mLockedDisabled && isFeatureEnabled);
     }
 
     private void onConfigChanged(Configuration newConfig) {
@@ -556,6 +580,10 @@
         pw.print(innerPrefix + "mLockedDisabled=");
         pw.println(mLockedDisabled);
 
+        if (mBackgroundPanelOrganizer != null) {
+            mBackgroundPanelOrganizer.dump(pw);
+        }
+
         if (mDisplayAreaOrganizer != null) {
             mDisplayAreaOrganizer.dump(pw);
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
index 5eec231..682c9a3f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
@@ -23,9 +23,7 @@
 import android.graphics.Rect;
 import android.os.SystemProperties;
 import android.util.ArrayMap;
-import android.util.Slog;
 import android.view.SurfaceControl;
-import android.view.WindowManager;
 import android.window.DisplayAreaAppearedInfo;
 import android.window.DisplayAreaInfo;
 import android.window.DisplayAreaOrganizer;
@@ -37,6 +35,7 @@
 import androidx.annotation.VisibleForTesting;
 
 import com.android.wm.shell.R;
+import com.android.wm.shell.common.DisplayLayout;
 import com.android.wm.shell.common.ShellExecutor;
 
 import java.io.PrintWriter;
@@ -58,7 +57,8 @@
     private static final String ONE_HANDED_MODE_TRANSLATE_ANIMATION_DURATION =
             "persist.debug.one_handed_translate_animation_duration";
 
-    private final WindowManager mWindowManager;
+    private DisplayLayout mDisplayLayout = new DisplayLayout();
+
     private final Rect mLastVisualDisplayBounds = new Rect();
     private final Rect mDefaultDisplayBounds = new Rect();
 
@@ -108,15 +108,15 @@
      * Constructor of OneHandedDisplayAreaOrganizer
      */
     public OneHandedDisplayAreaOrganizer(Context context,
-            WindowManager windowManager,
+            DisplayLayout displayLayout,
             OneHandedAnimationController animationController,
             OneHandedTutorialHandler tutorialHandler,
             OneHandedBackgroundPanelOrganizer oneHandedBackgroundGradientOrganizer,
             ShellExecutor mainExecutor) {
         super(mainExecutor);
-        mWindowManager = windowManager;
+        mDisplayLayout.set(displayLayout);
+        updateDisplayBounds();
         mAnimationController = animationController;
-        mLastVisualDisplayBounds.set(getDisplayBounds());
         final int animationDurationConfig = context.getResources().getInteger(
                 R.integer.config_one_handed_translate_animation_duration);
         mEnterExitAnimationDurationMs =
@@ -146,7 +146,7 @@
             final DisplayAreaAppearedInfo info = displayAreaInfos.get(i);
             onDisplayAreaAppeared(info.getDisplayAreaInfo(), info.getLeash());
         }
-        mDefaultDisplayBounds.set(getDisplayBounds());
+        updateDisplayBounds();
         return displayAreaInfos;
     }
 
@@ -157,29 +157,21 @@
     }
 
     /**
-     * Handler for display rotation changes by below policy which
-     * handles 90 degree display rotation changes {@link Surface.Rotation}.
+     * Handler for display rotation changes by {@link DisplayLayout}
      *
-     * @param fromRotation starting rotation of the display.
-     * @param toRotation   target rotation of the display (after rotating).
-     * @param wct          A task transaction {@link WindowContainerTransaction} from
-     *                     {@link DisplayChangeController} to populate.
+     * @param context       Any context
+     * @param toRotation    target rotation of the display (after rotating).
+     * @param wct           A task transaction {@link WindowContainerTransaction} from
+     *                      {@link DisplayChangeController} to populate.
      */
-    public void onRotateDisplay(int fromRotation, int toRotation, WindowContainerTransaction wct) {
-        // Stop one handed without animation and reset cropped size immediately
-        final Rect newBounds = new Rect(getDisplayBounds());
-        // This diff rule will only filter the cases portrait <-> landscape
-        final boolean isOrientationDiff = Math.abs(fromRotation - toRotation) % 2 == 1;
-
-        if (isOrientationDiff) {
-            // getDisplayBounds() will return window metrics bounds which dose not update to
-            // corresponding display orientation yet, we have to manual rotate bounds
-            newBounds.set(0, 0, newBounds.bottom, newBounds.right);
-            resetWindowsOffset(wct);
-            mDefaultDisplayBounds.set(newBounds);
-            mLastVisualDisplayBounds.set(newBounds);
-            finishOffset(0, TRANSITION_DIRECTION_EXIT);
+    public void onRotateDisplay(Context context, int toRotation, WindowContainerTransaction wct) {
+        if (mDisplayLayout.rotation() == toRotation) {
+            return;
         }
+        mDisplayLayout.rotateTo(context.getResources(), toRotation);
+        resetWindowsOffset(wct);
+        updateDisplayBounds();
+        finishOffset(0, TRANSITION_DIRECTION_EXIT);
     }
 
     /**
@@ -191,9 +183,7 @@
                 mDefaultDisplayBounds.top + yOffset,
                 mDefaultDisplayBounds.right,
                 mDefaultDisplayBounds.bottom + yOffset);
-        final Rect fromBounds = getLastVisualDisplayBounds() != null
-                ? getLastVisualDisplayBounds()
-                : mDefaultDisplayBounds;
+        final Rect fromBounds = getLastVisualDisplayBounds();
         final int direction = yOffset > 0
                 ? TRANSITION_DIRECTION_TRIGGER
                 : TRANSITION_DIRECTION_EXIT;
@@ -219,7 +209,8 @@
         applyTransaction(wct);
     }
 
-    private void resetWindowsOffset(WindowContainerTransaction wct) {
+    @VisibleForTesting
+    void resetWindowsOffset(WindowContainerTransaction wct) {
         final SurfaceControl.Transaction tx =
                 mSurfaceControlTransactionFactory.getTransaction();
         mDisplayAreaTokenMap.forEach(
@@ -292,19 +283,19 @@
         return mLastVisualDisplayBounds;
     }
 
-    @Nullable
     @VisibleForTesting
-    Rect getDisplayBounds() {
-        if (mWindowManager == null) {
-            Slog.e(TAG, "WindowManager instance is null! Can not get display size!");
-            return new Rect();
-        }
-        final Rect displayBounds = mWindowManager.getCurrentWindowMetrics().getBounds();
-        if (displayBounds.width() == 0 || displayBounds.height() == 0) {
-            Slog.e(TAG, "Display size error! width = " + displayBounds.width()
-                    + ", height = " + displayBounds.height());
-        }
-        return displayBounds;
+    @Nullable
+    Rect getLastDisplayBounds() {
+        return mLastVisualDisplayBounds;
+    }
+
+    public DisplayLayout getDisplayLayout() {
+        return mDisplayLayout;
+    }
+
+    @VisibleForTesting
+    void setDisplayLayout(@NonNull DisplayLayout displayLayout) {
+        mDisplayLayout.set(displayLayout);
     }
 
     @VisibleForTesting
@@ -312,6 +303,11 @@
         return mDisplayAreaTokenMap;
     }
 
+    void updateDisplayBounds() {
+        mDefaultDisplayBounds.set(0, 0, mDisplayLayout.width(), mDisplayLayout.height());
+        mLastVisualDisplayBounds.set(mDefaultDisplayBounds);
+    }
+
     /**
      * Register transition callback
      */
@@ -324,13 +320,13 @@
         pw.println(TAG + "states: ");
         pw.print(innerPrefix + "mIsInOneHanded=");
         pw.println(mIsInOneHanded);
+        pw.print(innerPrefix + "mDisplayLayout.rotation()=");
+        pw.println(mDisplayLayout.rotation());
         pw.print(innerPrefix + "mDisplayAreaTokenMap=");
         pw.println(mDisplayAreaTokenMap);
         pw.print(innerPrefix + "mDefaultDisplayBounds=");
         pw.println(mDefaultDisplayBounds);
         pw.print(innerPrefix + "mLastVisualDisplayBounds=");
         pw.println(mLastVisualDisplayBounds);
-        pw.print(innerPrefix + "getDisplayBounds()=");
-        pw.println(getDisplayBounds());
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java
index 778876c..495362a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java
@@ -24,7 +24,6 @@
 import android.graphics.Rect;
 import android.hardware.input.InputManager;
 import android.os.Looper;
-import android.util.Log;
 import android.view.Display;
 import android.view.InputChannel;
 import android.view.InputEvent;
@@ -33,29 +32,23 @@
 import android.view.MotionEvent;
 import android.view.Surface;
 import android.view.ViewConfiguration;
-import android.view.WindowManager;
-import android.window.WindowContainerTransaction;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
 
 import com.android.wm.shell.R;
-import com.android.wm.shell.common.DisplayChangeController;
-import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.DisplayLayout;
 import com.android.wm.shell.common.ShellExecutor;
 
 import java.io.PrintWriter;
 
 /**
- * The class manage swipe up and down gesture for 3-Button mode navigation,
- * others(e.g, 2-button, full gesture mode) are handled by Launcher quick steps.
- * TODO(b/160934654) Migrate to Launcher quick steps
+ * The class manage swipe up and down gesture for 3-Button mode navigation, others(e.g, 2-button,
+ * full gesture mode) are handled by Launcher quick steps. TODO(b/160934654) Migrate to Launcher
+ * quick steps
  */
-public class OneHandedGestureHandler implements OneHandedTransitionCallback,
-        DisplayChangeController.OnDisplayChangingListener {
+public class OneHandedGestureHandler implements OneHandedTransitionCallback {
     private static final String TAG = "OneHandedGestureHandler";
-    private static final boolean DEBUG_GESTURE = false;
 
     private static final int ANGLE_MAX = 150;
     private static final int ANGLE_MIN = 30;
@@ -64,14 +57,13 @@
     private final PointF mDownPos = new PointF();
     private final PointF mLastPos = new PointF();
     private final PointF mStartDragPos = new PointF();
-    private final WindowManager mWindowManager;
 
     private boolean mPassedSlop;
     private boolean mAllowGesture;
     private boolean mIsEnabled;
     private int mNavGestureHeight;
     private boolean mIsThreeButtonModeEnabled;
-    private int mRotation = Surface.ROTATION_0;
+    private int mRotation;
 
     @VisibleForTesting
     InputMonitor mInputMonitor;
@@ -85,37 +77,35 @@
     private boolean mIsStopGesture;
 
     /**
-     * Constructor of OneHandedGestureHandler, we only handle the gesture of
-     * {@link Display#DEFAULT_DISPLAY}
+     * Constructor of OneHandedGestureHandler, we only handle the gesture of {@link
+     * Display#DEFAULT_DISPLAY}
      *
-     * @param context                  {@link Context}
-     * @param displayController        {@link DisplayController}
+     * @param context       Any context
+     * @param displayLayout Current {@link DisplayLayout} from controller
+     * @param viewConfig    {@link ViewConfiguration} to obtain touch slop
+     * @param mainExecutor  The wm-shell main executor
      */
-    public OneHandedGestureHandler(Context context, WindowManager windowManager,
-            DisplayController displayController, ViewConfiguration viewConfig,
+    public OneHandedGestureHandler(Context context,
+            DisplayLayout displayLayout,
+            ViewConfiguration viewConfig,
             ShellExecutor mainExecutor) {
-        mWindowManager = windowManager;
         mMainExecutor = mainExecutor;
-        displayController.addDisplayChangingController(this);
-        mNavGestureHeight = getNavBarSize(context,
-                displayController.getDisplayLayout(DEFAULT_DISPLAY));
         mDragDistThreshold = context.getResources().getDimensionPixelSize(
                 R.dimen.gestures_onehanded_drag_threshold);
+
         final float slop = viewConfig.getScaledTouchSlop();
         mSquaredSlop = slop * slop;
-
+        onDisplayChanged(displayLayout);
         updateIsEnabled();
     }
 
     /**
-     * Notified by {@link OneHandedController}, when user update settings of Enabled or Disabled
+     * Notifies by {@link OneHandedController}, when swipe down gesture is enabled on 3 button
+     * navigation bar mode.
      *
-     * @param isEnabled is one handed settings enabled or not
+     * @param isEnabled Either one handed mode or swipe for notification function enabled or not
      */
-    public void onOneHandedEnabled(boolean isEnabled) {
-        if (DEBUG_GESTURE) {
-            Log.d(TAG, "onOneHandedEnabled, isEnabled = " + isEnabled);
-        }
+    public void onGestureEnabled(boolean isEnabled) {
         mIsEnabled = isEnabled;
         updateIsEnabled();
     }
@@ -126,25 +116,31 @@
     }
 
     /**
-     * Register {@link OneHandedGestureEventCallback} to receive onStart(), onStop() callback
+     * Registers {@link OneHandedGestureEventCallback} to receive onStart(), onStop() callback
      */
     public void setGestureEventListener(OneHandedGestureEventCallback callback) {
         mGestureEventCallback = callback;
     }
 
+    /**
+     * Called when onDisplayAdded() or onDisplayRemoved() callback
+     * @param displayLayout The latest {@link DisplayLayout} representing current displayId
+     */
+    public void onDisplayChanged(DisplayLayout displayLayout) {
+        mNavGestureHeight = getNavBarSize(displayLayout);
+        mGestureRegion.set(0, displayLayout.height() - mNavGestureHeight, displayLayout.width(),
+                displayLayout.height());
+        mRotation = displayLayout.rotation();
+    }
+
     private void onMotionEvent(MotionEvent ev) {
         int action = ev.getActionMasked();
         if (action == MotionEvent.ACTION_DOWN) {
-            mAllowGesture = isWithinTouchRegion(ev.getX(), ev.getY())
-                    && mRotation == Surface.ROTATION_0;
+            mAllowGesture = isWithinTouchRegion(ev.getX(), ev.getY()) && isGestureAvailable();
             if (mAllowGesture) {
                 mDownPos.set(ev.getX(), ev.getY());
                 mLastPos.set(mDownPos);
             }
-            if (DEBUG_GESTURE) {
-                Log.d(TAG, "ACTION_DOWN, mDownPos=" + mDownPos + ", mAllowGesture="
-                        + mAllowGesture);
-            }
         } else if (mAllowGesture) {
             switch (action) {
                 case MotionEvent.ACTION_MOVE:
@@ -204,34 +200,17 @@
     }
 
     private boolean isWithinTouchRegion(float x, float y) {
-        if (DEBUG_GESTURE) {
-            Log.d(TAG, "isWithinTouchRegion(), mGestureRegion=" + mGestureRegion + ", downX=" + x
-                    + ", downY=" + y);
-        }
         return mGestureRegion.contains(Math.round(x), Math.round(y));
     }
 
-    private int getNavBarSize(Context context, @Nullable DisplayLayout displayLayout) {
-        if (displayLayout != null) {
-            return displayLayout.navBarFrameHeight();
-        } else {
-            return isRotated()
-                    ? context.getResources().getDimensionPixelSize(
-                    com.android.internal.R.dimen.navigation_bar_height_landscape)
-                    : context.getResources().getDimensionPixelSize(
-                            com.android.internal.R.dimen.navigation_bar_height);
-        }
+    private int getNavBarSize(@NonNull DisplayLayout displayLayout) {
+        return isGestureAvailable() ? displayLayout.navBarFrameHeight() : 0 /* In landscape */;
     }
 
     private void updateIsEnabled() {
         disposeInputChannel();
 
-        // Either OHM or swipe notification shade can activate in portrait mode only
-        if (mIsEnabled && mIsThreeButtonModeEnabled && !isRotated()) {
-            final Rect displaySize = mWindowManager.getCurrentWindowMetrics().getBounds();
-            // Register input event receiver to monitor the touch region of NavBar gesture height
-            mGestureRegion.set(0, displaySize.height() - mNavGestureHeight, displaySize.width(),
-                    displaySize.height());
+        if (mIsEnabled && mIsThreeButtonModeEnabled && isGestureAvailable()) {
             mInputMonitor = InputManager.getInstance().monitorGestureInput(
                     "onehanded-gesture-offset", DEFAULT_DISPLAY);
             try {
@@ -251,10 +230,16 @@
         }
     }
 
-    @Override
-    public void onRotateDisplay(int displayId, int fromRotation, int toRotation,
-            WindowContainerTransaction t) {
-        mRotation = toRotation;
+    /**
+     * Handler for display rotation changes by {@link DisplayLayout}
+     *
+     * @param displayLayout The rotated displayLayout
+     */
+    public void onRotateDisplay(DisplayLayout displayLayout) {
+        mRotation = displayLayout.rotation();
+        mNavGestureHeight = getNavBarSize(displayLayout);
+        mGestureRegion.set(0, displayLayout.height() - mNavGestureHeight, displayLayout.width(),
+                displayLayout.height());
         updateIsEnabled();
     }
 
@@ -270,8 +255,9 @@
         }
     }
 
-    private boolean isRotated() {
-        return mRotation == Surface.ROTATION_90 || mRotation == Surface.ROTATION_270;
+    private boolean isGestureAvailable() {
+        // Either OHM or swipe notification shade can activate in portrait mode only
+        return mRotation == Surface.ROTATION_0 || mRotation == Surface.ROTATION_180;
     }
 
     private boolean isValidStartAngle(float deltaX, float deltaY) {
@@ -291,14 +277,18 @@
     void dump(@NonNull PrintWriter pw) {
         final String innerPrefix = "  ";
         pw.println(TAG + "States: ");
+        pw.print(innerPrefix + "mAllowGesture=");
+        pw.println(mAllowGesture);
         pw.print(innerPrefix + "mIsEnabled=");
         pw.println(mIsEnabled);
+        pw.print(innerPrefix + "mGestureRegion=");
+        pw.println(mGestureRegion);
         pw.print(innerPrefix + "mNavGestureHeight=");
         pw.println(mNavGestureHeight);
         pw.print(innerPrefix + "mIsThreeButtonModeEnabled=");
         pw.println(mIsThreeButtonModeEnabled);
-        pw.print(innerPrefix + "isLandscape=");
-        pw.println(isRotated());
+        pw.print(innerPrefix + "mRotation=");
+        pw.println(mRotation);
     }
 
     /**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
index e7cd38f..01a81d2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
@@ -40,15 +40,17 @@
     void addTask(ActivityManager.RunningTaskInfo task, Rect rootBounds,
             WindowContainerTransaction wct) {
         final WindowContainerToken rootToken = mRootTaskInfo.token;
-        wct.setHidden(rootToken, false)
-                .setBounds(rootToken, rootBounds)
+        wct.setBounds(rootToken, rootBounds)
                 .reparent(task.token, rootToken, true /* onTop*/)
                 // Moving the root task to top after the child tasks were repareted , or the root
                 // task cannot be visible and focused.
-                .reorder(rootToken, true);
+                .reorder(rootToken, true /* onTop */);
     }
 
     boolean removeAllTasks(WindowContainerTransaction wct, boolean toTop) {
+        // No matter if the root task is empty or not, moving the root to bottom because it no
+        // longer preserves visible child task.
+        wct.reorder(mRootTaskInfo.token, false /* onTop */);
         if (mChildrenTaskInfo.size() == 0) return false;
         wct.reparentTasks(
                 mRootTaskInfo.token,
@@ -62,10 +64,7 @@
     boolean removeTask(int taskId, WindowContainerToken newParent, WindowContainerTransaction wct) {
         final ActivityManager.RunningTaskInfo task = mChildrenTaskInfo.get(taskId);
         if (task == null) return false;
-
-        wct.setHidden(mRootTaskInfo.token, true)
-                .reorder(mRootTaskInfo.token, false)
-                .reparent(task.token, newParent, false /* onTop */);
+        wct.reparent(task.token, newParent, false /* onTop */);
         return true;
     }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizerTest.java
index d6bcf03..3f47c04 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizerTest.java
@@ -22,6 +22,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
 import android.testing.AndroidTestingRunner;
@@ -35,6 +36,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.DisplayLayout;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -48,7 +50,8 @@
 public class OneHandedBackgroundPanelOrganizerTest extends OneHandedTestCase {
     private DisplayAreaInfo mDisplayAreaInfo;
     private Display mDisplay;
-    private OneHandedBackgroundPanelOrganizer mBackgroundPanelOrganizer;
+    private DisplayLayout mDisplayLayout;
+    private OneHandedBackgroundPanelOrganizer mSpiedBackgroundPanelOrganizer;
     private WindowContainerToken mToken;
     private SurfaceControl mLeash;
     private TestableLooper mTestableLooper;
@@ -65,37 +68,38 @@
         mToken = new WindowContainerToken(mMockRealToken);
         mLeash = new SurfaceControl();
         mDisplay = mContext.getDisplay();
+        mDisplayLayout = new DisplayLayout(mContext, mDisplay);
         when(mMockDisplayController.getDisplay(anyInt())).thenReturn(mDisplay);
         mDisplayAreaInfo = new DisplayAreaInfo(mToken, DEFAULT_DISPLAY,
                 FEATURE_ONE_HANDED_BACKGROUND_PANEL);
 
-        mBackgroundPanelOrganizer = new OneHandedBackgroundPanelOrganizer(mContext, mWindowManager,
-                mMockDisplayController, Runnable::run);
+        mSpiedBackgroundPanelOrganizer = spy(
+                new OneHandedBackgroundPanelOrganizer(mContext, mDisplayLayout, Runnable::run));
     }
 
     @Test
     public void testOnDisplayAreaAppeared() {
-        mBackgroundPanelOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash);
+        mSpiedBackgroundPanelOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash);
         mTestableLooper.processAllMessages();
 
-        assertThat(mBackgroundPanelOrganizer.getBackgroundSurface()).isNotNull();
+        assertThat(mSpiedBackgroundPanelOrganizer.getBackgroundSurface()).isNotNull();
     }
 
     @Test
     public void testShowBackgroundLayer() {
-        mBackgroundPanelOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash);
-        mBackgroundPanelOrganizer.showBackgroundPanelLayer();
+        mSpiedBackgroundPanelOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash);
+        mSpiedBackgroundPanelOrganizer.showBackgroundPanelLayer();
         mTestableLooper.processAllMessages();
 
-        assertThat(mBackgroundPanelOrganizer.mIsShowing).isTrue();
+        assertThat(mSpiedBackgroundPanelOrganizer.mIsShowing).isTrue();
     }
 
     @Test
     public void testRemoveBackgroundLayer() {
-        mBackgroundPanelOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash);
-        mBackgroundPanelOrganizer.removeBackgroundPanelLayer();
+        mSpiedBackgroundPanelOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash);
+        mSpiedBackgroundPanelOrganizer.removeBackgroundPanelLayer();
         mTestableLooper.processAllMessages();
 
-        assertThat(mBackgroundPanelOrganizer.mIsShowing).isFalse();
+        assertThat(mSpiedBackgroundPanelOrganizer.mIsShowing).isFalse();
     }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java
index bd5fe2b..b0fc4c1 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java
@@ -23,20 +23,24 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.content.om.IOverlayManager;
+import android.graphics.Rect;
 import android.os.Handler;
 import android.testing.AndroidTestingRunner;
 import android.util.ArrayMap;
 import android.view.Display;
+import android.view.Surface;
 import android.view.SurfaceControl;
 
 import androidx.test.filters.SmallTest;
 
 import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.DisplayLayout;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.TaskStackListenerImpl;
 
@@ -50,6 +54,7 @@
 @RunWith(AndroidTestingRunner.class)
 public class OneHandedControllerTest extends OneHandedTestCase {
     Display mDisplay;
+    DisplayLayout mDisplayLayout;
     OneHandedController mSpiedOneHandedController;
     OneHandedTimeoutHandler mSpiedTimeoutHandler;
 
@@ -88,6 +93,7 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mDisplay = mContext.getDisplay();
+        mDisplayLayout = new DisplayLayout(mContext, mDisplay);
         mSpiedTimeoutHandler = spy(new OneHandedTimeoutHandler(mMockShellMainExecutor));
 
         when(mMockDisplayController.getDisplay(anyInt())).thenReturn(mDisplay);
@@ -103,9 +109,12 @@
         when(mMockSettingsUitl.getSettingsSwipeToNotificationEnabled(any())).thenReturn(
                 mDefaultSwipeToNotificationEnabled);
 
+        when(mMockDisplayAreaOrganizer.getLastDisplayBounds()).thenReturn(
+                new Rect(0, 0, mDisplayLayout.width(), mDisplayLayout.height()));
+        when(mMockDisplayAreaOrganizer.getDisplayLayout()).thenReturn(mDisplayLayout);
+
         mSpiedOneHandedController = spy(new OneHandedController(
                 mContext,
-                mWindowManager,
                 mMockDisplayController,
                 mMockBackgroundOrganizer,
                 mMockDisplayAreaOrganizer,
@@ -127,7 +136,7 @@
         final OneHandedAnimationController animationController = new OneHandedAnimationController(
                 mContext);
         OneHandedDisplayAreaOrganizer displayAreaOrganizer = new OneHandedDisplayAreaOrganizer(
-                mContext, mWindowManager, animationController, mMockTutorialHandler,
+                mContext, mDisplayLayout, animationController, mMockTutorialHandler,
                 mMockBackgroundOrganizer, mMockShellMainExecutor);
 
         assertThat(displayAreaOrganizer.isInOneHanded()).isFalse();
@@ -188,7 +197,7 @@
         mSpiedOneHandedController.setOneHandedEnabled(true);
 
         verify(mMockTouchHandler, atLeastOnce()).onOneHandedEnabled(anyBoolean());
-        verify(mMockGestureHandler, atLeastOnce()).onOneHandedEnabled(anyBoolean());
+        verify(mMockGestureHandler, atLeastOnce()).onGestureEnabled(anyBoolean());
     }
 
     @Test
@@ -196,7 +205,7 @@
         mSpiedOneHandedController.setSwipeToNotificationEnabled(mDefaultSwipeToNotificationEnabled);
 
         verify(mMockTouchHandler, atLeastOnce()).onOneHandedEnabled(anyBoolean());
-        verify(mMockGestureHandler, atLeastOnce()).onOneHandedEnabled(anyBoolean());
+        verify(mMockGestureHandler, atLeastOnce()).onGestureEnabled(anyBoolean());
     }
 
     @Test
@@ -282,4 +291,67 @@
 
         verify(mMockDisplayAreaOrganizer).scheduleOffset(anyInt(), anyInt());
     }
+
+    @Test
+    public void testRotation90CanNotStartOneHanded() {
+        final DisplayLayout landscapeDisplayLayout = new DisplayLayout(mDisplayLayout);
+        landscapeDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_90);
+        when(mMockDisplayAreaOrganizer.isInOneHanded()).thenReturn(false);
+        when(mMockDisplayAreaOrganizer.getDisplayLayout()).thenReturn(landscapeDisplayLayout);
+        mSpiedOneHandedController.setOneHandedEnabled(true);
+        mSpiedOneHandedController.setLockedDisabled(false /* locked */, false /* enabled */);
+        mSpiedOneHandedController.startOneHanded();
+
+        verify(mMockDisplayAreaOrganizer, never()).scheduleOffset(anyInt(), anyInt());
+    }
+
+    @Test
+    public void testRotation180CanStartOneHanded() {
+        final DisplayLayout testDisplayLayout = new DisplayLayout(mDisplayLayout);
+        testDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_180);
+        when(mMockDisplayAreaOrganizer.isInOneHanded()).thenReturn(false);
+        when(mMockDisplayAreaOrganizer.getDisplayLayout()).thenReturn(testDisplayLayout);
+        mSpiedOneHandedController.setOneHandedEnabled(true);
+        mSpiedOneHandedController.setLockedDisabled(false /* locked */, false /* enabled */);
+        mSpiedOneHandedController.startOneHanded();
+
+        verify(mMockDisplayAreaOrganizer).scheduleOffset(anyInt(), anyInt());
+    }
+
+    @Test
+    public void testRotation270CanNotStartOneHanded() {
+        final DisplayLayout testDisplayLayout = new DisplayLayout(mDisplayLayout);
+        testDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_270);
+        when(mMockDisplayAreaOrganizer.isInOneHanded()).thenReturn(false);
+        when(mMockDisplayAreaOrganizer.getDisplayLayout()).thenReturn(testDisplayLayout);
+        mSpiedOneHandedController.setOneHandedEnabled(true);
+        mSpiedOneHandedController.setLockedDisabled(false /* locked */, false /* enabled */);
+        mSpiedOneHandedController.startOneHanded();
+
+        verify(mMockDisplayAreaOrganizer, never()).scheduleOffset(anyInt(), anyInt());
+    }
+
+    @Test
+    public void testDisabled3ButtonGestureWhenKeyguardOn() {
+        final boolean isOneHandedEnabled = true;
+        final boolean isLockWhenKeyguardOn = true;
+        final boolean isEnabledWhenKeyguardOn = false;
+        mSpiedOneHandedController.setOneHandedEnabled(isOneHandedEnabled);
+        mSpiedOneHandedController.setLockedDisabled(isLockWhenKeyguardOn, isEnabledWhenKeyguardOn);
+
+        verify(mMockGestureHandler).onGestureEnabled(isEnabledWhenKeyguardOn);
+    }
+
+    @Test
+    public void testEnabled3ButtonGestureWhenKeyguardGoingAway() {
+        final boolean isOneHandedEnabled = true;
+        final boolean isLockWhenKeyguardOn = false;
+        final boolean isEnabledWhenKeyguardOn = false;
+        mSpiedOneHandedController.setOneHandedEnabled(isOneHandedEnabled);
+        reset(mMockGestureHandler);
+
+        mSpiedOneHandedController.setLockedDisabled(isLockWhenKeyguardOn, isEnabledWhenKeyguardOn);
+
+        verify(mMockGestureHandler).onGestureEnabled(isOneHandedEnabled);
+    }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java
index f897b09..f654bb5 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java
@@ -19,6 +19,9 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.window.DisplayAreaOrganizer.FEATURE_ONE_HANDED;
 
+import static com.android.wm.shell.onehanded.OneHandedAnimationController.TRANSITION_DIRECTION_EXIT;
+import static com.android.wm.shell.onehanded.OneHandedAnimationController.TRANSITION_DIRECTION_TRIGGER;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.anyFloat;
@@ -32,6 +35,7 @@
 import static org.mockito.Mockito.when;
 
 import android.content.res.Configuration;
+import android.graphics.Rect;
 import android.os.Binder;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -47,6 +51,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.DisplayLayout;
 import com.android.wm.shell.common.ShellExecutor;
 
 import org.junit.Before;
@@ -67,6 +72,7 @@
 
     DisplayAreaInfo mDisplayAreaInfo;
     Display mDisplay;
+    DisplayLayout mDisplayLayout;
     OneHandedDisplayAreaOrganizer mSpiedDisplayAreaOrganizer;
     OneHandedTutorialHandler mTutorialHandler;
     OneHandedAnimationController.OneHandedTransitionAnimator mFakeAnimator;
@@ -103,6 +109,7 @@
         mToken = new WindowContainerToken(mMockRealToken);
         mLeash = new SurfaceControl();
         mDisplay = mContext.getDisplay();
+        mDisplayLayout = new DisplayLayout(mContext, mDisplay);
         mDisplayAreaInfo = new DisplayAreaInfo(mToken, DEFAULT_DISPLAY, FEATURE_ONE_HANDED);
         mDisplayAreaInfo.configuration.orientation = Configuration.ORIENTATION_PORTRAIT;
         when(mMockAnimationController.getAnimator(any(), any(), any(), any())).thenReturn(null);
@@ -121,7 +128,7 @@
         when(mMockLeash.getHeight()).thenReturn(DISPLAY_HEIGHT);
 
         mSpiedDisplayAreaOrganizer = spy(new OneHandedDisplayAreaOrganizer(mContext,
-                mWindowManager,
+                mDisplayLayout,
                 mMockAnimationController,
                 mTutorialHandler,
                 mMockBackgroundOrganizer,
@@ -169,20 +176,13 @@
     }
 
     @Test
-    public void testRotation_getNewDisplayBounds() {
-        when(mMockLeash.isValid()).thenReturn(false);
-        // Rotate 0 -> 90
-        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_90,
-                mMockWindowContainerTransaction);
-        verify(mSpiedDisplayAreaOrganizer).getDisplayBounds();
-    }
-
-    @Test
     public void testRotation_portrait_0_to_landscape_90() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 0 -> 90
-        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_90,
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_90,
                 mMockWindowContainerTransaction);
+
+        verify(mSpiedDisplayAreaOrganizer).resetWindowsOffset(mMockWindowContainerTransaction);
         verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
     }
 
@@ -190,8 +190,10 @@
     public void testRotation_portrait_0_to_seascape_270() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 0 -> 270
-        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_270,
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_270,
                 mMockWindowContainerTransaction);
+
+        verify(mSpiedDisplayAreaOrganizer).resetWindowsOffset(mMockWindowContainerTransaction);
         verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
     }
 
@@ -199,8 +201,12 @@
     public void testRotation_portrait_180_to_landscape_90() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 180 -> 90
-        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_90,
+        mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_180);
+        mSpiedDisplayAreaOrganizer.setDisplayLayout(mDisplayLayout);
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_90,
                 mMockWindowContainerTransaction);
+
+        verify(mSpiedDisplayAreaOrganizer).resetWindowsOffset(mMockWindowContainerTransaction);
         verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
     }
 
@@ -208,8 +214,12 @@
     public void testRotation_portrait_180_to_seascape_270() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 180 -> 270
-        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_270,
+        mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_180);
+        mSpiedDisplayAreaOrganizer.setDisplayLayout(mDisplayLayout);
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_270,
                 mMockWindowContainerTransaction);
+
+        verify(mSpiedDisplayAreaOrganizer).resetWindowsOffset(mMockWindowContainerTransaction);
         verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
     }
 
@@ -217,8 +227,12 @@
     public void testRotation_landscape_90_to_portrait_0() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 90 -> 0
-        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_0,
+        mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_90);
+        mSpiedDisplayAreaOrganizer.setDisplayLayout(mDisplayLayout);
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_0,
                 mMockWindowContainerTransaction);
+
+        verify(mSpiedDisplayAreaOrganizer).resetWindowsOffset(mMockWindowContainerTransaction);
         verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
     }
 
@@ -226,26 +240,38 @@
     public void testRotation_landscape_90_to_portrait_180() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 90 -> 180
-        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_180,
+        mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_90);
+        mSpiedDisplayAreaOrganizer.setDisplayLayout(mDisplayLayout);
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_180,
                 mMockWindowContainerTransaction);
+
+        verify(mSpiedDisplayAreaOrganizer).resetWindowsOffset(mMockWindowContainerTransaction);
         verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
     }
 
     @Test
-    public void testRotation_Seascape_270_to_portrait_0() {
+    public void testRotation_seascape_270_to_portrait_0() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 270 -> 0
-        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_0,
+        mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_270);
+        mSpiedDisplayAreaOrganizer.setDisplayLayout(mDisplayLayout);
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_0,
                 mMockWindowContainerTransaction);
+
+        verify(mSpiedDisplayAreaOrganizer).resetWindowsOffset(mMockWindowContainerTransaction);
         verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
     }
 
     @Test
-    public void testRotation_seascape_90_to_portrait_180() {
+    public void testRotation_seascape_270_to_portrait_180() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 270 -> 180
-        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_180,
+        mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_270);
+        mSpiedDisplayAreaOrganizer.setDisplayLayout(mDisplayLayout);
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_180,
                 mMockWindowContainerTransaction);
+
+        verify(mSpiedDisplayAreaOrganizer).resetWindowsOffset(mMockWindowContainerTransaction);
         verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
     }
 
@@ -253,7 +279,10 @@
     public void testRotation_portrait_0_to_portrait_0() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 0 -> 0
-        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_0,
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_0,
+                mMockWindowContainerTransaction);
+
+        verify(mSpiedDisplayAreaOrganizer, never()).resetWindowsOffset(
                 mMockWindowContainerTransaction);
         verify(mSpiedDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
     }
@@ -262,16 +291,23 @@
     public void testRotation_portrait_0_to_portrait_180() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 0 -> 180
-        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_180,
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_180,
                 mMockWindowContainerTransaction);
-        verify(mSpiedDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
+
+        verify(mSpiedDisplayAreaOrganizer).resetWindowsOffset(mMockWindowContainerTransaction);
+        verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
     }
 
     @Test
     public void testRotation_portrait_180_to_portrait_180() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 180 -> 180
-        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_180,
+        mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_180);
+        mSpiedDisplayAreaOrganizer.setDisplayLayout(mDisplayLayout);
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_180,
+                mMockWindowContainerTransaction);
+
+        verify(mSpiedDisplayAreaOrganizer, never()).resetWindowsOffset(
                 mMockWindowContainerTransaction);
         verify(mSpiedDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
     }
@@ -280,16 +316,25 @@
     public void testRotation_portrait_180_to_portrait_0() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 180 -> 0
-        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_0,
+        mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_90);
+        mSpiedDisplayAreaOrganizer.setDisplayLayout(mDisplayLayout);
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_0,
                 mMockWindowContainerTransaction);
-        verify(mSpiedDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
+
+        verify(mSpiedDisplayAreaOrganizer).resetWindowsOffset(mMockWindowContainerTransaction);
+        verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
     }
 
     @Test
     public void testRotation_landscape_90_to_landscape_90() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 90 -> 90
-        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_90,
+        mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_90);
+        mSpiedDisplayAreaOrganizer.setDisplayLayout(mDisplayLayout);
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_90,
+                mMockWindowContainerTransaction);
+
+        verify(mSpiedDisplayAreaOrganizer, never()).resetWindowsOffset(
                 mMockWindowContainerTransaction);
         verify(mSpiedDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
     }
@@ -298,26 +343,60 @@
     public void testRotation_landscape_90_to_seascape_270() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 90 -> 270
-        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_270,
+        mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_90);
+        mSpiedDisplayAreaOrganizer.setDisplayLayout(mDisplayLayout);
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_270,
                 mMockWindowContainerTransaction);
-        verify(mSpiedDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
+
+        verify(mSpiedDisplayAreaOrganizer).resetWindowsOffset(mMockWindowContainerTransaction);
+        verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
     }
 
     @Test
     public void testRotation_seascape_270_to_seascape_270() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 270 -> 270
-        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_270,
+        mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_270);
+        mSpiedDisplayAreaOrganizer.setDisplayLayout(mDisplayLayout);
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_270,
+                mMockWindowContainerTransaction);
+
+        verify(mSpiedDisplayAreaOrganizer, never()).resetWindowsOffset(
                 mMockWindowContainerTransaction);
         verify(mSpiedDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
     }
 
     @Test
-    public void testRotation_seascape_90_to_landscape_90() {
+    public void testRotation_seascape_270_to_landscape_90() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 270 -> 90
-        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_90,
+        mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_270);
+        mSpiedDisplayAreaOrganizer.setDisplayLayout(mDisplayLayout);
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_90,
                 mMockWindowContainerTransaction);
-        verify(mSpiedDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
+
+        verify(mSpiedDisplayAreaOrganizer).resetWindowsOffset(
+                mMockWindowContainerTransaction);
+        verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
+    }
+
+    @Test
+    public void testTriggerOffset() {
+        final Rect testBounds = mSpiedDisplayAreaOrganizer.getLastDisplayBounds();
+        final int offset = 100;
+        testBounds.offsetTo(0, offset);
+        mSpiedDisplayAreaOrganizer.finishOffset(offset, TRANSITION_DIRECTION_TRIGGER);
+
+        assertThat(mSpiedDisplayAreaOrganizer.getLastDisplayBounds()).isEqualTo(testBounds);
+    }
+
+    @Test
+    public void testExitOffsetToZero() {
+        final Rect testBounds = mSpiedDisplayAreaOrganizer.getLastDisplayBounds();
+        final int offset = 100;
+        mSpiedDisplayAreaOrganizer.finishOffset(offset, TRANSITION_DIRECTION_TRIGGER);
+        mSpiedDisplayAreaOrganizer.finishOffset(0, TRANSITION_DIRECTION_EXIT);
+
+        assertThat(mSpiedDisplayAreaOrganizer.getLastDisplayBounds()).isEqualTo(testBounds);
     }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedGestureHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedGestureHandlerTest.java
index f683e4a..5d82a70 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedGestureHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedGestureHandlerTest.java
@@ -16,21 +16,19 @@
 
 package com.android.wm.shell.onehanded;
 
-import static android.view.Display.DEFAULT_DISPLAY;
-
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.testing.AndroidTestingRunner;
 import android.view.Surface;
 import android.view.ViewConfiguration;
-import android.window.WindowContainerTransaction;
 
 import androidx.test.filters.SmallTest;
 
-import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.DisplayLayout;
 import com.android.wm.shell.common.ShellExecutor;
 
@@ -44,24 +42,20 @@
 @RunWith(AndroidTestingRunner.class)
 public class OneHandedGestureHandlerTest extends OneHandedTestCase {
     OneHandedGestureHandler mGestureHandler;
-    @Mock
-    DisplayController mMockDisplayController;
+    DisplayLayout mDisplayLayout;
     @Mock
     DisplayLayout mMockDisplayLayout;
     @Mock
     ShellExecutor mMockShellMainExecutor;
-    @Mock
-    WindowContainerTransaction mMockWct;
 
     @Before
     public void setUp() {
         final int mockNavBarHeight = 100;
         MockitoAnnotations.initMocks(this);
-        mGestureHandler = new OneHandedGestureHandler(mContext, mWindowManager,
-                mMockDisplayController, ViewConfiguration.get(mTestContext),
-                mMockShellMainExecutor);
+        mDisplayLayout = new DisplayLayout(mContext, mContext.getDisplay());
+        mGestureHandler = new OneHandedGestureHandler(mContext, mDisplayLayout,
+                ViewConfiguration.get(mTestContext), mMockShellMainExecutor);
         when(mMockDisplayLayout.navBarFrameHeight()).thenReturn(mockNavBarHeight);
-        when(mMockDisplayController.getDisplayLayout(anyInt())).thenReturn(mMockDisplayLayout);
     }
 
     @Test
@@ -81,7 +75,7 @@
 
     @Test
     public void testOneHandedDisabled_shouldDisposeInputChannel() {
-        mGestureHandler.onOneHandedEnabled(false);
+        mGestureHandler.onGestureEnabled(false);
 
         assertThat(mGestureHandler.mInputMonitor).isNull();
         assertThat(mGestureHandler.mInputEventReceiver).isNull();
@@ -89,7 +83,7 @@
 
     @Test
     public void testChangeNavBarToNon3Button_shouldDisposeInputChannel() {
-        mGestureHandler.onOneHandedEnabled(true);
+        mGestureHandler.onGestureEnabled(true);
         mGestureHandler.onThreeButtonModeEnabled(false);
 
         assertThat(mGestureHandler.mInputMonitor).isNull();
@@ -98,11 +92,38 @@
 
     @Test
     public void testOnlyHandleGestureInPortraitMode() {
-        mGestureHandler.onOneHandedEnabled(true);
-        mGestureHandler.onRotateDisplay(DEFAULT_DISPLAY, Surface.ROTATION_0, Surface.ROTATION_90,
-                mMockWct);
+        mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_90);
+        mGestureHandler.onGestureEnabled(true);
+        mGestureHandler.onRotateDisplay(mDisplayLayout);
 
         assertThat(mGestureHandler.mInputMonitor).isNull();
         assertThat(mGestureHandler.mInputEventReceiver).isNull();
     }
+
+    @Test
+    public void testRotation90ShouldNotRegisterEventReceiver() throws InterruptedException {
+        mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_90);
+        mGestureHandler.onGestureEnabled(true);
+        mGestureHandler.onRotateDisplay(mDisplayLayout);
+
+        verify(mMockShellMainExecutor, never()).executeBlocking(any());
+    }
+
+    @Test
+    public void testRotation180ShouldNotRegisterEventReceiver() throws InterruptedException {
+        mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_180);
+        mGestureHandler.onGestureEnabled(true);
+        mGestureHandler.onRotateDisplay(mDisplayLayout);
+
+        verify(mMockShellMainExecutor, never()).executeBlocking(any());
+    }
+
+    @Test
+    public void testRotation270ShouldNotRegisterEventReceiver() throws InterruptedException {
+        mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_270);
+        mGestureHandler.onGestureEnabled(true);
+        mGestureHandler.onRotateDisplay(mDisplayLayout);
+
+        verify(mMockShellMainExecutor, never()).executeBlocking(any());
+    }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java
index f586dda..2886bb1 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java
@@ -75,7 +75,6 @@
         when(mMockDisplayAreaOrganizer.getDisplayAreaTokenMap()).thenReturn(new ArrayMap<>());
         mOneHandedController = new OneHandedController(
                 mContext,
-                mWindowManager,
                 mMockDisplayController,
                 mMockBackgroundOrganizer,
                 mMockDisplayAreaOrganizer,
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaInserterTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaInserterTest.java
index de353bf..a0d4492 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaInserterTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaInserterTest.java
@@ -24,8 +24,10 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.content.AttributionSource;
 import android.content.ContentProviderClient;
 import android.content.ContentValues;
+import android.content.Context;
 import android.content.IContentProvider;
 import android.media.MediaInserter;
 import android.net.Uri;
@@ -46,7 +48,7 @@
     private MediaInserter mMediaInserter;
     private static final int TEST_BUFFER_SIZE = 10;
     private @Mock IContentProvider mMockProvider;
-    private String mPackageName;
+    private AttributionSource mAttributionSource;
 
     private int mFilesCounter;
     private int mAudioCounter;
@@ -86,11 +88,14 @@
         super.setUp();
         MockitoAnnotations.initMocks(this);
 
-        final ContentProviderClient client = new ContentProviderClient(
-                getInstrumentation().getContext().createFeatureContext(TEST_FEATURE_ID)
+        final Context attributionContext = getInstrumentation().getContext()
+                .createFeatureContext(TEST_FEATURE_ID);
+
+        final ContentProviderClient client = new ContentProviderClient(attributionContext
                         .getContentResolver(), mMockProvider, true);
+
         mMediaInserter = new MediaInserter(client, TEST_BUFFER_SIZE);
-        mPackageName = getInstrumentation().getContext().getPackageName();
+        mAttributionSource = attributionContext.getAttributionSource();
         mFilesCounter = 0;
         mAudioCounter = 0;
         mVideoCounter = 0;
@@ -144,13 +149,13 @@
         fillBuffer(sVideoUri, TEST_BUFFER_SIZE - 2);
         fillBuffer(sImagesUri, TEST_BUFFER_SIZE - 1);
 
-        verify(mMockProvider, never()).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(),
+        verify(mMockProvider, never()).bulkInsert(eq(mAttributionSource), any(),
                 any());
     }
 
     @SmallTest
     public void testInsertContentsEqualToBufferSize() throws Exception {
-        when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(),
+        when(mMockProvider.bulkInsert(eq(mAttributionSource), any(),
                 any())).thenReturn(1);
 
         fillBuffer(sFilesUri, TEST_BUFFER_SIZE);
@@ -158,13 +163,13 @@
         fillBuffer(sVideoUri, TEST_BUFFER_SIZE);
         fillBuffer(sImagesUri, TEST_BUFFER_SIZE);
 
-        verify(mMockProvider, times(4)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(),
+        verify(mMockProvider, times(4)).bulkInsert(eq(mAttributionSource), any(),
                 any());
     }
 
     @SmallTest
     public void testInsertContentsMoreThanBufferSize() throws Exception {
-        when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(),
+        when(mMockProvider.bulkInsert(eq(mAttributionSource), any(),
                 any())).thenReturn(1);
 
         fillBuffer(sFilesUri, TEST_BUFFER_SIZE + 1);
@@ -172,7 +177,7 @@
         fillBuffer(sVideoUri, TEST_BUFFER_SIZE + 3);
         fillBuffer(sImagesUri, TEST_BUFFER_SIZE + 4);
 
-        verify(mMockProvider, times(4)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(),
+        verify(mMockProvider, times(4)).bulkInsert(eq(mAttributionSource), any(),
                 any());
     }
 
@@ -183,7 +188,7 @@
 
     @SmallTest
     public void testFlushAllWithSomeContents() throws Exception {
-        when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(),
+        when(mMockProvider.bulkInsert(eq(mAttributionSource), any(),
                 any())).thenReturn(1);
 
         fillBuffer(sFilesUri, TEST_BUFFER_SIZE - 4);
@@ -192,13 +197,13 @@
         fillBuffer(sImagesUri, TEST_BUFFER_SIZE - 1);
         mMediaInserter.flushAll();
 
-        verify(mMockProvider, times(4)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(),
+        verify(mMockProvider, times(4)).bulkInsert(eq(mAttributionSource), any(),
                 any());
     }
 
     @SmallTest
     public void testInsertContentsAfterFlushAll() throws Exception {
-        when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(),
+        when(mMockProvider.bulkInsert(eq(mAttributionSource), any(),
                 any())).thenReturn(1);
 
         fillBuffer(sFilesUri, TEST_BUFFER_SIZE - 4);
@@ -212,19 +217,19 @@
         fillBuffer(sVideoUri, TEST_BUFFER_SIZE + 3);
         fillBuffer(sImagesUri, TEST_BUFFER_SIZE + 4);
 
-        verify(mMockProvider, times(8)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(),
+        verify(mMockProvider, times(8)).bulkInsert(eq(mAttributionSource), any(),
                 any());
     }
 
     @SmallTest
     public void testInsertContentsWithDifferentSizePerContentType() throws Exception {
-        when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), eqUri(sFilesUri),
+        when(mMockProvider.bulkInsert(eq(mAttributionSource), eqUri(sFilesUri),
                 any())).thenReturn(1);
-        when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), eqUri(sAudioUri),
+        when(mMockProvider.bulkInsert(eq(mAttributionSource), eqUri(sAudioUri),
                 any())).thenReturn(1);
-        when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), eqUri(sVideoUri),
+        when(mMockProvider.bulkInsert(eq(mAttributionSource), eqUri(sVideoUri),
                 any())).thenReturn(1);
-        when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), eqUri(sImagesUri),
+        when(mMockProvider.bulkInsert(eq(mAttributionSource), eqUri(sImagesUri),
                 any())).thenReturn(1);
 
         for (int i = 0; i < TEST_BUFFER_SIZE; ++i) {
@@ -234,13 +239,13 @@
             fillBuffer(sImagesUri, 4);
         }
 
-        verify(mMockProvider, times(1)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID),
+        verify(mMockProvider, times(1)).bulkInsert(eq(mAttributionSource),
                 eqUri(sFilesUri), any());
-        verify(mMockProvider, times(2)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID),
+        verify(mMockProvider, times(2)).bulkInsert(eq(mAttributionSource),
                 eqUri(sAudioUri), any());
-        verify(mMockProvider, times(3)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID),
+        verify(mMockProvider, times(3)).bulkInsert(eq(mAttributionSource),
                 eqUri(sVideoUri), any());
-        verify(mMockProvider, times(4)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID),
+        verify(mMockProvider, times(4)).bulkInsert(eq(mAttributionSource),
                 eqUri(sImagesUri), any());
     }
 }
diff --git a/packages/Connectivity/framework/api/module-lib-current.txt b/packages/Connectivity/framework/api/module-lib-current.txt
index 970a236..2065559 100644
--- a/packages/Connectivity/framework/api/module-lib-current.txt
+++ b/packages/Connectivity/framework/api/module-lib-current.txt
@@ -179,10 +179,12 @@
   }
 
   public final class VpnTransportInfo implements android.os.Parcelable android.net.TransportInfo {
-    ctor public VpnTransportInfo(int);
+    ctor public VpnTransportInfo(int, @Nullable String);
     method public int describeContents();
+    method @NonNull public android.net.VpnTransportInfo makeCopy(long);
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.net.VpnTransportInfo> CREATOR;
+    field @Nullable public final String sessionId;
     field public final int type;
   }
 
diff --git a/packages/Connectivity/framework/api/system-current.txt b/packages/Connectivity/framework/api/system-current.txt
index 95df8b8..6c3b620 100644
--- a/packages/Connectivity/framework/api/system-current.txt
+++ b/packages/Connectivity/framework/api/system-current.txt
@@ -219,7 +219,7 @@
     method public void onAutomaticReconnectDisabled();
     method public void onBandwidthUpdateRequested();
     method public void onNetworkCreated();
-    method public void onNetworkDisconnected();
+    method public void onNetworkDestroyed();
     method public void onNetworkUnwanted();
     method public void onQosCallbackRegistered(int, @NonNull android.net.QosFilter);
     method public void onQosCallbackUnregistered(int);
@@ -238,6 +238,7 @@
     method public final void sendQosSessionLost(int, int, int);
     method public final void sendSocketKeepaliveEvent(int, int);
     method @Deprecated public void setLegacySubtype(int, @NonNull String);
+    method public void setTeardownDelayMs(@IntRange(from=0, to=0x1388) int);
     method public final void setUnderlyingNetworks(@Nullable java.util.List<android.net.Network>);
     method public void unregister();
     field public static final int VALIDATION_STATUS_NOT_VALID = 2; // 0x2
diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
index 3939c7f..350b47f 100644
--- a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
+++ b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
@@ -924,6 +924,7 @@
             BLOCKED_REASON_DOZE,
             BLOCKED_REASON_APP_STANDBY,
             BLOCKED_REASON_RESTRICTED_MODE,
+            BLOCKED_REASON_LOCKDOWN_VPN,
             BLOCKED_METERED_REASON_DATA_SAVER,
             BLOCKED_METERED_REASON_USER_RESTRICTED,
             BLOCKED_METERED_REASON_ADMIN_DISABLED,
@@ -3715,7 +3716,8 @@
         public void onBlockedStatusChanged(@NonNull Network network, boolean blocked) {}
 
         /**
-         * Called when access to the specified network is blocked or unblocked.
+         * Called when access to the specified network is blocked or unblocked, or the reason for
+         * access being blocked changes.
          *
          * If a NetworkCallback object implements this method,
          * {@link #onBlockedStatusChanged(Network, boolean)} will not be called.
diff --git a/packages/Connectivity/framework/src/android/net/INetworkAgent.aidl b/packages/Connectivity/framework/src/android/net/INetworkAgent.aidl
index f9d3994..d941d4b 100644
--- a/packages/Connectivity/framework/src/android/net/INetworkAgent.aidl
+++ b/packages/Connectivity/framework/src/android/net/INetworkAgent.aidl
@@ -47,5 +47,5 @@
     void onQosFilterCallbackRegistered(int qosCallbackId, in QosFilterParcelable filterParcel);
     void onQosCallbackUnregistered(int qosCallbackId);
     void onNetworkCreated();
-    void onNetworkDisconnected();
+    void onNetworkDestroyed();
 }
diff --git a/packages/Connectivity/framework/src/android/net/INetworkAgentRegistry.aidl b/packages/Connectivity/framework/src/android/net/INetworkAgentRegistry.aidl
index cbd6193..26cb1ed 100644
--- a/packages/Connectivity/framework/src/android/net/INetworkAgentRegistry.aidl
+++ b/packages/Connectivity/framework/src/android/net/INetworkAgentRegistry.aidl
@@ -41,4 +41,5 @@
     void sendNrQosSessionAvailable(int callbackId, in QosSession session, in NrQosSessionAttributes attributes);
     void sendQosSessionLost(int qosCallbackId, in QosSession session);
     void sendQosCallbackError(int qosCallbackId, int exceptionType);
+    void sendTeardownDelayMs(int teardownDelayMs);
 }
diff --git a/packages/Connectivity/framework/src/android/net/NetworkAgent.java b/packages/Connectivity/framework/src/android/net/NetworkAgent.java
index 6b55bb7..c57da53 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkAgent.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkAgent.java
@@ -185,6 +185,20 @@
     public static final int EVENT_UNDERLYING_NETWORKS_CHANGED = BASE + 5;
 
     /**
+     * Sent by the NetworkAgent to ConnectivityService to pass the current value of the teardown
+     * delay.
+     * arg1 = teardown delay in milliseconds
+     * @hide
+     */
+    public static final int EVENT_TEARDOWN_DELAY_CHANGED = BASE + 6;
+
+    /**
+     * The maximum value for the teardown delay, in milliseconds.
+     * @hide
+     */
+    public static final int MAX_TEARDOWN_DELAY_MS = 5000;
+
+    /**
      * Sent by ConnectivityService to the NetworkAgent to inform the agent of the
      * networks status - whether we could use the network or could not, due to
      * either a bad network configuration (no internet link) or captive portal.
@@ -197,7 +211,6 @@
      */
     public static final int CMD_REPORT_NETWORK_STATUS = BASE + 7;
 
-
     /**
      * Network validation suceeded.
      * Corresponds to {@link NetworkCapabilities.NET_CAPABILITY_VALIDATED}.
@@ -376,7 +389,7 @@
      *
      * @hide
      */
-    public static final int CMD_NETWORK_DISCONNECTED = BASE + 23;
+    public static final int CMD_NETWORK_DESTROYED = BASE + 23;
 
     private static NetworkInfo getLegacyNetworkInfo(final NetworkAgentConfig config) {
         final NetworkInfo ni = new NetworkInfo(config.legacyType, config.legacySubType,
@@ -581,8 +594,8 @@
                     onNetworkCreated();
                     break;
                 }
-                case CMD_NETWORK_DISCONNECTED: {
-                    onNetworkDisconnected();
+                case CMD_NETWORK_DESTROYED: {
+                    onNetworkDestroyed();
                     break;
                 }
             }
@@ -732,8 +745,8 @@
         }
 
         @Override
-        public void onNetworkDisconnected() {
-            mHandler.sendMessage(mHandler.obtainMessage(CMD_NETWORK_DISCONNECTED));
+        public void onNetworkDestroyed() {
+            mHandler.sendMessage(mHandler.obtainMessage(CMD_NETWORK_DESTROYED));
         }
     }
 
@@ -851,6 +864,29 @@
     }
 
     /**
+     * Sets the value of the teardown delay.
+     *
+     * The teardown delay is the time between when the network disconnects and when the native
+     * network corresponding to this {@code NetworkAgent} is destroyed. By default, the native
+     * network is destroyed immediately. If {@code teardownDelayMs} is non-zero, then when this
+     * network disconnects, the system will instead immediately mark the network as restricted
+     * and unavailable to unprivileged apps, but will defer destroying the native network until the
+     * teardown delay timer expires.
+     *
+     * The interfaces in use by this network will remain in use until the native network is
+     * destroyed and cannot be reused until {@link #onNetworkDestroyed()} is called.
+     *
+     * This method may be called at any time while the network is connected. It has no effect if
+     * the network is already disconnected and the teardown delay timer is running.
+     *
+     * @param teardownDelayMs the teardown delay to set, or 0 to disable teardown delay.
+     */
+    public void setTeardownDelayMs(
+            @IntRange(from = 0, to = MAX_TEARDOWN_DELAY_MS) int teardownDelayMs) {
+        queueOrSendMessage(reg -> reg.sendTeardownDelayMs(teardownDelayMs));
+    }
+
+    /**
      * Change the legacy subtype of this network agent.
      *
      * This is only for backward compatibility and should not be used by non-legacy network agents,
@@ -1053,7 +1089,7 @@
     /**
      * Called when ConnectivityService has successfully destroy this NetworkAgent's native network.
      */
-    public void onNetworkDisconnected() {}
+    public void onNetworkDestroyed() {}
 
     /**
      * Requests that the network hardware send the specified packet at the specified interval.
diff --git a/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java b/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java
index cd8f4c0..ba83a44 100644
--- a/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java
+++ b/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java
@@ -17,11 +17,14 @@
 package android.net;
 
 import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.TextUtils;
 
 import java.util.Objects;
 
@@ -38,8 +41,26 @@
     /** Type of this VPN. */
     public final int type;
 
-    public VpnTransportInfo(int type) {
+    @Nullable
+    public final String sessionId;
+
+    @Override
+    public long getApplicableRedactions() {
+        return REDACT_FOR_NETWORK_SETTINGS;
+    }
+
+    /**
+     * Create a copy of a {@link VpnTransportInfo} with the sessionId redacted if necessary.
+     */
+    @NonNull
+    public VpnTransportInfo makeCopy(long redactions) {
+        return new VpnTransportInfo(type,
+            ((redactions & REDACT_FOR_NETWORK_SETTINGS) != 0) ? null : sessionId);
+    }
+
+    public VpnTransportInfo(int type, @Nullable String sessionId) {
         this.type = type;
+        this.sessionId = sessionId;
     }
 
     @Override
@@ -47,17 +68,17 @@
         if (!(o instanceof VpnTransportInfo)) return false;
 
         VpnTransportInfo that = (VpnTransportInfo) o;
-        return this.type == that.type;
+        return (this.type == that.type) && TextUtils.equals(this.sessionId, that.sessionId);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(type);
+        return Objects.hash(type, sessionId);
     }
 
     @Override
     public String toString() {
-        return String.format("VpnTransportInfo{type=%d}", type);
+        return String.format("VpnTransportInfo{type=%d, sessionId=%s}", type, sessionId);
     }
 
     @Override
@@ -68,12 +89,13 @@
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeInt(type);
+        dest.writeString(sessionId);
     }
 
     public static final @NonNull Creator<VpnTransportInfo> CREATOR =
             new Creator<VpnTransportInfo>() {
         public VpnTransportInfo createFromParcel(Parcel in) {
-            return new VpnTransportInfo(in.readInt());
+            return new VpnTransportInfo(in.readInt(), in.readString());
         }
         public VpnTransportInfo[] newArray(int size) {
             return new VpnTransportInfo[size];
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 087275e..801b490 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.usage.StorageStatsManager;
+import android.content.AttributionSource;
 import android.content.ContentResolver;
 import android.content.UriPermission;
 import android.database.Cursor;
@@ -28,7 +29,6 @@
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Environment;
-import android.os.IBinder;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.storage.DiskInfo;
@@ -141,17 +141,17 @@
     }
 
     @Override
-    protected int enforceReadPermissionInner(Uri uri, String callingPkg,
-            @Nullable String featureId, IBinder callerToken) throws SecurityException {
+    protected int enforceReadPermissionInner(Uri uri,
+            @NonNull AttributionSource attributionSource) throws SecurityException {
         enforceShellRestrictions();
-        return super.enforceReadPermissionInner(uri, callingPkg, featureId, callerToken);
+        return super.enforceReadPermissionInner(uri, attributionSource);
     }
 
     @Override
-    protected int enforceWritePermissionInner(Uri uri, String callingPkg,
-            @Nullable String featureId, IBinder callerToken) throws SecurityException {
+    protected int enforceWritePermissionInner(Uri uri,
+            @NonNull AttributionSource attributionSource) throws SecurityException {
         enforceShellRestrictions();
-        return super.enforceWritePermissionInner(uri, callingPkg, featureId, callerToken);
+        return super.enforceWritePermissionInner(uri, attributionSource);
     }
 
     public void updateVolumes() {
diff --git a/packages/PackageInstaller/res/values-iw/strings.xml b/packages/PackageInstaller/res/values-iw/strings.xml
index 7cabdd5..5b17d74 100644
--- a/packages/PackageInstaller/res/values-iw/strings.xml
+++ b/packages/PackageInstaller/res/values-iw/strings.xml
@@ -21,9 +21,9 @@
     <string name="done" msgid="6632441120016885253">"סיום"</string>
     <string name="cancel" msgid="1018267193425558088">"ביטול"</string>
     <string name="installing" msgid="4921993079741206516">"מתקין…"</string>
-    <string name="installing_app" msgid="1165095864863849422">"מתקין את <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="installing_app" msgid="1165095864863849422">"מתבצעת התקנה של <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="install_done" msgid="5987363587661783896">"האפליקציה הותקנה."</string>
-    <string name="install_confirm_question" msgid="8176284075816604590">"האם ברצונך להתקין אפליקציה זו?"</string>
+    <string name="install_confirm_question" msgid="8176284075816604590">"להתקין את האפליקציה הזו?"</string>
     <string name="install_confirm_question_update" msgid="7942235418781274635">"האם ברצונך להתקין עדכון עבור אפליקציה קיימת זו? הנתונים הקיימים שלך לא יאבדו."</string>
     <string name="install_confirm_question_update_system" msgid="4713001702777910263">"האם ברצונך להתקין עדכון עבור אפליקציה מובנית זו? הנתונים הקיימים שלך לא יאבדו."</string>
     <string name="install_failed" msgid="5777824004474125469">"האפליקציה לא הותקנה."</string>
@@ -31,14 +31,14 @@
     <string name="install_failed_conflict" msgid="3493184212162521426">"האפליקציה לא הותקנה כי החבילה מתנגשת עם חבילה קיימת."</string>
     <string name="install_failed_incompatible" product="tablet" msgid="6019021440094927928">"האפליקציה לא הותקנה כי האפליקציה אינה תואמת לטאבלט."</string>
     <string name="install_failed_incompatible" product="tv" msgid="2890001324362291683">"האפליקציה הזו אינה תואמת לטלוויזיה שלך."</string>
-    <string name="install_failed_incompatible" product="default" msgid="7254630419511645826">"האפליקציה לא הותקנה כי האפליקציה אינה תואמת לטלפון."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7254630419511645826">"האפליקציה לא הותקנה כי היא לא תואמת לטלפון."</string>
     <string name="install_failed_invalid_apk" msgid="8581007676422623930">"האפליקציה לא הותקנה כי נראה שהחבילה לא תקפה."</string>
     <string name="install_failed_msg" product="tablet" msgid="6298387264270562442">"לא ניתן להתקין את <xliff:g id="APP_NAME">%1$s</xliff:g> בטאבלט שלך."</string>
     <string name="install_failed_msg" product="tv" msgid="1920009940048975221">"לא ניתן להתקין את <xliff:g id="APP_NAME">%1$s</xliff:g> בטלוויזיה שלך."</string>
     <string name="install_failed_msg" product="default" msgid="6484461562647915707">"לא ניתן להתקין את <xliff:g id="APP_NAME">%1$s</xliff:g> בטלפון שלך."</string>
     <string name="launch" msgid="3952550563999890101">"פתיחה"</string>
     <string name="unknown_apps_admin_dlg_text" msgid="4456572224020176095">"מנהל המערכת שלך לא מתיר התקנה של אפליקציות ממקורות לא ידועים"</string>
-    <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"למשתמש זה אין הרשאה להתקין אפליקציות שאינן מוכרות"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"למשתמש הזה אין הרשאה להתקין אפליקציות שאינן מוכרות"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"למשתמש הזה אין הרשאה להתקין אפליקציות"</string>
     <string name="ok" msgid="7871959885003339302">"אישור"</string>
     <string name="manage_applications" msgid="5400164782453975580">"ניהול אפליקציות"</string>
@@ -52,16 +52,16 @@
     <string name="generic_error_dlg_text" msgid="5287861443265795232">"לא ניתן היה להסיר את התקנת האפליקציה."</string>
     <string name="uninstall_application_title" msgid="4045420072401428123">"הסרת התקנה של האפליקציה"</string>
     <string name="uninstall_update_title" msgid="824411791011583031">"הסרת התקנה של עדכון"</string>
-    <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> הוא חלק מהאפליקציה הבאה:"</string>
+    <string name="uninstall_activity_text" msgid="1928194674397770771">"הפעילות <xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> היא חלק מהאפליקציה הבאה:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"האם ברצונך להסיר את ההתקנה של אפליקציה זו?"</string>
-    <string name="uninstall_application_text_all_users" msgid="575491774380227119">"האם אתה רוצה להסיר את האפליקציה הזו עבור "<b>"כל"</b>" המשתמשים? האפליקציה והנתונים שלה יוסרו מ"<b>"כל"</b>" המשתמשים במכשיר."</string>
-    <string name="uninstall_application_text_user" msgid="498072714173920526">"האם ברצונך להסיר את התקנתה של אפליקציה זו עבור המשתמש <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_application_text_all_users" msgid="575491774380227119">"להסיר את האפליקציה הזו עבור "<b>"כל"</b>" המשתמשים? האפליקציה והנתונים שלה יוסרו עבור "<b>"כל"</b>" המשתמשים במכשיר."</string>
+    <string name="uninstall_application_text_user" msgid="498072714173920526">"להסיר את ההתקנה של האפליקציה הזו עבור <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_update_text" msgid="863648314632448705">"האם להחליף את האפליקציה הזאת בגרסת היצרן? כל הנתונים יוסרו."</string>
     <string name="uninstall_update_text_multiuser" msgid="8992883151333057227">"האם להחליף את האפליקציה הזאת בגרסת היצרן? כל הנתונים יוסרו. הפעולה תשפיע על כל משתמשי המכשיר, כולל משתמשים בעלי פרופיל עבודה."</string>
     <string name="uninstall_keep_data" msgid="7002379587465487550">"שמירת <xliff:g id="SIZE">%1$s</xliff:g> מנתוני האפליקציה."</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"התקנות בתהליכי הסרה"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"הסרות התקנה שנכשלו"</string>
-    <string name="uninstalling" msgid="8709566347688966845">"מסיר התקנה..."</string>
+    <string name="uninstalling" msgid="8709566347688966845">"בתהליך הסרת התקנה..."</string>
     <string name="uninstalling_app" msgid="8866082646836981397">"מסיר את ההתקנה של <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"הסרת ההתקנה הסתיימה."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"ההתקנה של <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> הוסרה"</string>
diff --git a/packages/PackageInstaller/res/values-sv/strings.xml b/packages/PackageInstaller/res/values-sv/strings.xml
index d0902c3..28ad6aa 100644
--- a/packages/PackageInstaller/res/values-sv/strings.xml
+++ b/packages/PackageInstaller/res/values-sv/strings.xml
@@ -24,8 +24,8 @@
     <string name="installing_app" msgid="1165095864863849422">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> installeras …"</string>
     <string name="install_done" msgid="5987363587661783896">"Appen har installerats."</string>
     <string name="install_confirm_question" msgid="8176284075816604590">"Vill du installera det här programmet?"</string>
-    <string name="install_confirm_question_update" msgid="7942235418781274635">"Vill du installera en uppdatering till den här befintliga appen? Dina befintliga data försvinner inte."</string>
-    <string name="install_confirm_question_update_system" msgid="4713001702777910263">"Vill du installera en uppdatering av den inbyggda appen? Dina befintliga data försvinner inte."</string>
+    <string name="install_confirm_question_update" msgid="7942235418781274635">"Vill du installera en uppdatering till den här befintliga appen? Din befintliga data försvinner inte."</string>
+    <string name="install_confirm_question_update_system" msgid="4713001702777910263">"Vill du installera en uppdatering av den inbyggda appen? Din befintliga data försvinner inte."</string>
     <string name="install_failed" msgid="5777824004474125469">"Appen har inte installerats."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Paketet har blockerats för installation."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Appen har inte installerats på grund av en konflikt mellan detta paket och ett befintligt paket."</string>
diff --git a/packages/PrintSpooler/res/values-iw/strings.xml b/packages/PrintSpooler/res/values-iw/strings.xml
index 64db711..5dcd7f2 100644
--- a/packages/PrintSpooler/res/values-iw/strings.xml
+++ b/packages/PrintSpooler/res/values-iw/strings.xml
@@ -32,10 +32,10 @@
     <string name="template_page_range" msgid="428638530038286328">"טווח של <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"למשל 1–5‏,8,‏11–13"</string>
     <string name="print_preview" msgid="8010217796057763343">"תצוגה מקדימה של הדפסה"</string>
-    <string name="install_for_print_preview" msgid="6366303997385509332">"‏התקן מציג PDF ליצירת תצוגה מקדימה"</string>
+    <string name="install_for_print_preview" msgid="6366303997385509332">"‏התקנה של PDF viewer‏ ליצירת תצוגה מקדימה"</string>
     <string name="printing_app_crashed" msgid="854477616686566398">"אפליקציית ההדפסה קרסה"</string>
     <string name="generating_print_job" msgid="3119608742651698916">"יוצר עבודת הדפסה"</string>
-    <string name="save_as_pdf" msgid="5718454119847596853">"‏שמור כ-PDF"</string>
+    <string name="save_as_pdf" msgid="5718454119847596853">"‏שמירה כ-PDF"</string>
     <string name="all_printers" msgid="5018829726861876202">"כל המדפסות…"</string>
     <string name="print_dialog" msgid="32628687461331979">"תיבת דו שיח של מדפסת"</string>
     <string name="current_page_template" msgid="5145005201131935302">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
@@ -44,7 +44,7 @@
     <string name="expand_handle" msgid="7282974448109280522">"ידית הרחבה"</string>
     <string name="collapse_handle" msgid="6886637989442507451">"ידית כיווץ"</string>
     <string name="print_button" msgid="645164566271246268">"הדפס"</string>
-    <string name="savetopdf_button" msgid="2976186791686924743">"‏שמור כ-PDF"</string>
+    <string name="savetopdf_button" msgid="2976186791686924743">"‏שמירה כ-PDF"</string>
     <string name="print_options_expanded" msgid="6944679157471691859">"אפשרויות ההדפסה הורחבו"</string>
     <string name="print_options_collapsed" msgid="7455930445670414332">"אפשרויות ההדפסה כווצו"</string>
     <string name="search" msgid="5421724265322228497">"חיפוש"</string>
@@ -91,7 +91,7 @@
     <string name="restart" msgid="2472034227037808749">"הפעלה מחדש"</string>
     <string name="no_connection_to_printer" msgid="2159246915977282728">"אין חיבור למדפסת"</string>
     <string name="reason_unknown" msgid="5507940196503246139">"לא ידוע"</string>
-    <string name="print_service_security_warning_title" msgid="2160752291246775320">"האם להשתמש ב-<xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+    <string name="print_service_security_warning_title" msgid="2160752291246775320">"האם להשתמש בשירות <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="print_service_security_warning_summary" msgid="1427434625361692006">"ייתכן שהמסמך שלך יעבור בשרת אחד או יותר בדרכו למדפסת."</string>
   <string-array name="color_mode_labels">
     <item msgid="7602948745415174937">"שחור ולבן"</item>
@@ -107,7 +107,7 @@
     <item msgid="3199660090246166812">"לרוחב"</item>
   </string-array>
     <string name="print_write_error_message" msgid="5787642615179572543">"לא ניתן היה לכתוב לקובץ"</string>
-    <string name="print_error_default_message" msgid="8602678405502922346">"מצטערים, אך זה לא עבד. נסה שוב."</string>
+    <string name="print_error_default_message" msgid="8602678405502922346">"מצטערים, הפעולה לא בוצעה. אפשר לנסות שוב."</string>
     <string name="print_error_retry" msgid="1426421728784259538">"כדאי לנסות שוב"</string>
     <string name="print_error_printer_unavailable" msgid="8985614415253203381">"המדפסת הזו אינה זמינה כעת."</string>
     <string name="print_cannot_load_page" msgid="6179560924492912009">"לא ניתן להציג תצוגה מקדימה"</string>
diff --git a/packages/PrintSpooler/res/values-nl/strings.xml b/packages/PrintSpooler/res/values-nl/strings.xml
index 6448acc..2cd8d9b 100644
--- a/packages/PrintSpooler/res/values-nl/strings.xml
+++ b/packages/PrintSpooler/res/values-nl/strings.xml
@@ -50,7 +50,7 @@
     <string name="search" msgid="5421724265322228497">"Zoeken"</string>
     <string name="all_printers_label" msgid="3178848870161526399">"Alle printers"</string>
     <string name="add_print_service_label" msgid="5356702546188981940">"Service toevoegen"</string>
-    <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Zoekvak weergegeven"</string>
+    <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Zoekvak wordt getoond"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Zoekvak verborgen"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Printer toevoegen"</string>
     <string name="print_select_printer" msgid="7388760939873368698">"Printer selecteren"</string>
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
index 49f6bd8..a2bec33 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
@@ -555,7 +555,7 @@
             bundle.putString(META_DATA_PREFERENCE_KEYHINT, key);
         }
         try {
-            return provider.call(context.getPackageName(), context.getAttributionTag(),
+            return provider.call(context.getAttributionSource(),
                     uri.getAuthority(), method, uri.toString(), bundle);
         } catch (RemoteException e) {
             return null;
diff --git a/packages/SettingsLib/UsageProgressBarPreference/res/layout/preference_usage_progress_bar.xml b/packages/SettingsLib/UsageProgressBarPreference/res/layout/preference_usage_progress_bar.xml
index f45105d..31b3fe5 100644
--- a/packages/SettingsLib/UsageProgressBarPreference/res/layout/preference_usage_progress_bar.xml
+++ b/packages/SettingsLib/UsageProgressBarPreference/res/layout/preference_usage_progress_bar.xml
@@ -70,4 +70,13 @@
         android:scaleY="2"
         android:layout_marginTop="4dp"
         android:max="100"/>
+
+    <TextView
+        android:id="@+id/bottom_summary"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:visibility="gone"
+        android:ellipsize="marquee"
+        android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body1"
+        android:textSize="14sp"/>
 </LinearLayout>
diff --git a/packages/SettingsLib/UsageProgressBarPreference/src/com/android/settingslib/widget/UsageProgressBarPreference.java b/packages/SettingsLib/UsageProgressBarPreference/src/com/android/settingslib/widget/UsageProgressBarPreference.java
index 2185950..a2b1de2 100644
--- a/packages/SettingsLib/UsageProgressBarPreference/src/com/android/settingslib/widget/UsageProgressBarPreference.java
+++ b/packages/SettingsLib/UsageProgressBarPreference/src/com/android/settingslib/widget/UsageProgressBarPreference.java
@@ -44,6 +44,7 @@
 
     private CharSequence mUsageSummary;
     private CharSequence mTotalSummary;
+    private CharSequence mBottomSummary;
     private ImageView mCustomImageView;
     private int mPercent = -1;
 
@@ -101,6 +102,15 @@
         notifyChanged();
     }
 
+    /** Set bottom summary. */
+    public void setBottomSummary(CharSequence bottomSummary) {
+        if (TextUtils.equals(mBottomSummary, bottomSummary)) {
+            return;
+        }
+        mBottomSummary = bottomSummary;
+        notifyChanged();
+    }
+
     /** Set percentage of the progress bar. */
     public void setPercent(long usage, long total) {
         if (total == 0L || usage >  total) {
@@ -147,6 +157,14 @@
             totalSummary.setText(mTotalSummary);
         }
 
+        final TextView bottomSummary = (TextView) holder.findViewById(R.id.bottom_summary);
+        if (TextUtils.isEmpty(mBottomSummary)) {
+            bottomSummary.setVisibility(View.GONE);
+        } else {
+            bottomSummary.setVisibility(View.VISIBLE);
+            bottomSummary.setText(mBottomSummary);
+        }
+
         final ProgressBar progressBar = (ProgressBar) holder.findViewById(android.R.id.progress);
         if (mPercent < 0) {
             progressBar.setIndeterminate(true);
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
index 8f8f859..253629c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
@@ -13,11 +13,14 @@
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
+import android.provider.DeviceConfig;
 import android.provider.MediaStore;
+import android.text.TextUtils;
 import android.util.Log;
 import android.util.Pair;
 
 import androidx.annotation.DrawableRes;
+import androidx.annotation.NonNull;
 import androidx.core.graphics.drawable.IconCompat;
 
 import com.android.settingslib.R;
@@ -34,6 +37,7 @@
     public static final boolean D = true;  // regular logging
 
     public static final int META_INT_ERROR = -1;
+    public static final String BT_ADVANCED_HEADER_ENABLED = "bt_advanced_header_enabled";
 
     private static ErrorListener sErrorListener;
 
@@ -178,14 +182,12 @@
         final Pair<Drawable, String> pair = BluetoothUtils.getBtClassDrawableWithDescription(
                 context, cachedDevice);
         final BluetoothDevice bluetoothDevice = cachedDevice.getDevice();
-        final boolean untetheredHeadset = getBooleanMetaData(
-                bluetoothDevice, BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET);
         final int iconSize = context.getResources().getDimensionPixelSize(
                 R.dimen.bt_nearby_icon_size);
         final Resources resources = context.getResources();
 
-        // Deal with untethered headset
-        if (untetheredHeadset) {
+        // Deal with advanced device icon
+        if (isAdvancedDetailsHeader(bluetoothDevice)) {
             final Uri iconUri = getUriMetaData(bluetoothDevice,
                     BluetoothDevice.METADATA_MAIN_ICON);
             if (iconUri != null) {
@@ -217,6 +219,35 @@
     }
 
     /**
+     * Check if the Bluetooth device supports advanced metadata
+     *
+     * @param bluetoothDevice the BluetoothDevice to get metadata
+     * @return true if it supports advanced metadata, false otherwise.
+     */
+    public static boolean isAdvancedDetailsHeader(@NonNull BluetoothDevice bluetoothDevice) {
+        if (!DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SETTINGS_UI, BT_ADVANCED_HEADER_ENABLED,
+                true)) {
+            Log.d(TAG, "isAdvancedDetailsHeader: advancedEnabled is false");
+            return false;
+        }
+        // The metadata is for Android R
+        if (getBooleanMetaData(bluetoothDevice, BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET)) {
+            Log.d(TAG, "isAdvancedDetailsHeader: untetheredHeadset is true");
+            return true;
+        }
+        // The metadata is for Android S
+        String deviceType = getStringMetaData(bluetoothDevice,
+                BluetoothDevice.METADATA_DEVICE_TYPE);
+        if (TextUtils.equals(deviceType, BluetoothDevice.DEVICE_TYPE_UNTETHERED_HEADSET)
+                || TextUtils.equals(deviceType, BluetoothDevice.DEVICE_TYPE_WATCH)
+                || TextUtils.equals(deviceType, BluetoothDevice.DEVICE_TYPE_DEFAULT)) {
+            Log.d(TAG, "isAdvancedDetailsHeader: deviceType is " + deviceType);
+            return true;
+        }
+        return false;
+    }
+
+    /**
      * Create an Icon pointing to a drawable.
      */
     public static IconCompat createIconWithDrawable(Drawable drawable) {
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/widget/UsageProgressBarPreferenceTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/widget/UsageProgressBarPreferenceTest.java
index fe76b06..cd78add 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/widget/UsageProgressBarPreferenceTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/widget/UsageProgressBarPreferenceTest.java
@@ -92,6 +92,28 @@
     }
 
     @Test
+    public void setBottomSummary_getCorrectSummary() {
+        final String expectedText = "Should last until about 7:45 PM";
+        mUsageProgressBarPreference.setBottomSummary(expectedText);
+
+        mUsageProgressBarPreference.onBindViewHolder(mViewHolder);
+
+        final TextView bottomSummary = (TextView) mViewHolder.findViewById(R.id.bottom_summary);
+        assertThat(bottomSummary.getText()).isEqualTo(expectedText);
+        assertThat(bottomSummary.getVisibility()).isEqualTo(View.VISIBLE);
+    }
+
+    @Test
+    public void setBottomSummary_emptyText_isGone() {
+        mUsageProgressBarPreference.setBottomSummary(null);
+
+        mUsageProgressBarPreference.onBindViewHolder(mViewHolder);
+
+        final TextView bottomSummary = (TextView) mViewHolder.findViewById(R.id.bottom_summary);
+        assertThat(bottomSummary.getVisibility()).isEqualTo(View.GONE);
+    }
+
+    @Test
     public void setPercent_getCorrectProgress() {
         mUsageProgressBarPreference.setPercent(31, 80);
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
index 3a95852c..2e85514 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
@@ -150,4 +150,45 @@
         assertThat(BluetoothUtils.getUriMetaData(mBluetoothDevice,
                 BluetoothDevice.METADATA_MAIN_ICON)).isNull();
     }
+
+    @Test
+    public void isAdvancedDetailsHeader_untetheredHeadset_returnTrue() {
+        when(mBluetoothDevice.getMetadata(
+                BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET)).thenReturn(
+                BOOL_METADATA.getBytes());
+
+        assertThat(BluetoothUtils.isAdvancedDetailsHeader(mBluetoothDevice)).isEqualTo(true);
+    }
+
+    @Test
+    public void isAdvancedDetailsHeader_deviceTypeUntetheredHeadset_returnTrue() {
+        when(mBluetoothDevice.getMetadata(
+                BluetoothDevice.METADATA_DEVICE_TYPE)).thenReturn(
+                BluetoothDevice.DEVICE_TYPE_UNTETHERED_HEADSET.getBytes());
+
+        assertThat(BluetoothUtils.isAdvancedDetailsHeader(mBluetoothDevice)).isEqualTo(true);
+    }
+
+    @Test
+    public void isAdvancedDetailsHeader_deviceTypeWatch_returnTrue() {
+        when(mBluetoothDevice.getMetadata(
+                BluetoothDevice.METADATA_DEVICE_TYPE)).thenReturn(
+                BluetoothDevice.DEVICE_TYPE_WATCH.getBytes());
+
+        assertThat(BluetoothUtils.isAdvancedDetailsHeader(mBluetoothDevice)).isEqualTo(true);
+    }
+
+    @Test
+    public void isAdvancedDetailsHeader_deviceTypeDefault_returnTrue() {
+        when(mBluetoothDevice.getMetadata(
+                BluetoothDevice.METADATA_DEVICE_TYPE)).thenReturn(
+                BluetoothDevice.DEVICE_TYPE_DEFAULT.getBytes());
+
+        assertThat(BluetoothUtils.isAdvancedDetailsHeader(mBluetoothDevice)).isEqualTo(true);
+    }
+
+    @Test
+    public void isAdvancedDetailsHeader_noMetadata_returnFalse() {
+        assertThat(BluetoothUtils.isAdvancedDetailsHeader(mBluetoothDevice)).isEqualTo(false);
+    }
 }
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
index 987e82e..77032ba 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
@@ -72,6 +72,8 @@
         Settings.Global.NOTIFICATION_BUBBLES,
         Settings.Global.CUSTOM_BUGREPORT_HANDLER_APP,
         Settings.Global.CUSTOM_BUGREPORT_HANDLER_USER,
-        Settings.Global.DEVELOPMENT_SETTINGS_ENABLED
+        Settings.Global.DEVELOPMENT_SETTINGS_ENABLED,
+        Settings.Global.USER_DISABLED_HDR_FORMATS,
+        Settings.Global.ARE_USER_DISABLED_HDR_FORMATS_ALLOWED
     };
 }
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/DiscreteValueIntegerListValidator.java b/packages/SettingsProvider/src/android/provider/settings/validators/DiscreteValueIntegerListValidator.java
new file mode 100644
index 0000000..eb38ac5
--- /dev/null
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/DiscreteValueIntegerListValidator.java
@@ -0,0 +1,50 @@
+/*
+ * 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.provider.settings.validators;
+
+/**
+ * Validates the elements in a list with the array of allowed integer values.
+ *
+ * @hide
+ */
+class DiscreteValueIntegerListValidator extends ListValidator {
+    private int[] mAllowedValues;
+
+    DiscreteValueIntegerListValidator(String listSplitRegex, int[] allowedValues) {
+        super(listSplitRegex);
+        mAllowedValues = allowedValues;
+    }
+
+    @Override
+    protected boolean isEntryValid(String entry) {
+        return (entry != null);
+    }
+
+    @Override
+    protected boolean isItemValid(String item) {
+        for (int allowedValue : mAllowedValues) {
+            try {
+                if (Integer.parseInt(item) == allowedValue) {
+                    return true;
+                }
+            } catch (NumberFormatException e) {
+                return false;
+            }
+        }
+        return false;
+    }
+}
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
index ad6a531..0790189 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
@@ -16,16 +16,16 @@
 
 package android.provider.settings.validators;
 
+import static android.media.AudioFormat.SURROUND_SOUND_ENCODING;
 import static android.provider.settings.validators.SettingsValidators.ANY_INTEGER_VALIDATOR;
 import static android.provider.settings.validators.SettingsValidators.ANY_STRING_VALIDATOR;
 import static android.provider.settings.validators.SettingsValidators.BOOLEAN_VALIDATOR;
 import static android.provider.settings.validators.SettingsValidators.PACKAGE_NAME_VALIDATOR;
 import static android.provider.settings.validators.SettingsValidators.PERCENTAGE_INTEGER_VALIDATOR;
+import static android.view.Display.HdrCapabilities.HDR_TYPES;
 
-import android.media.AudioFormat;
 import android.os.BatteryManager;
 import android.provider.Settings.Global;
-import android.text.TextUtils;
 import android.util.ArrayMap;
 
 import java.util.Map;
@@ -88,31 +88,17 @@
                 Global.ENABLE_AUTOMATIC_SYSTEM_SERVER_HEAP_DUMPS,
                 new DiscreteValueValidator(new String[] {"0", "1"}));
         VALIDATORS.put(
+                Global.ARE_USER_DISABLED_HDR_FORMATS_ALLOWED,
+                new DiscreteValueValidator(new String[] {"0", "1"}));
+        VALIDATORS.put(
+                Global.USER_DISABLED_HDR_FORMATS,
+                new DiscreteValueIntegerListValidator(",", HDR_TYPES));
+        VALIDATORS.put(
                 Global.ENCODED_SURROUND_OUTPUT,
                 new DiscreteValueValidator(new String[] {"0", "1", "2", "3"}));
         VALIDATORS.put(
                 Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS,
-                value -> {
-                    try {
-                        String[] surroundFormats = TextUtils.split(value, ",");
-                        for (String format : surroundFormats) {
-                            int audioFormat = Integer.valueOf(format);
-                            boolean isSurroundFormat = false;
-                            for (int sf : AudioFormat.SURROUND_SOUND_ENCODING) {
-                                if (sf == audioFormat) {
-                                    isSurroundFormat = true;
-                                    break;
-                                }
-                            }
-                            if (!isSurroundFormat) {
-                                return false;
-                            }
-                        }
-                        return true;
-                    } catch (NumberFormatException e) {
-                        return false;
-                    }
-                });
+                new DiscreteValueIntegerListValidator(",", SURROUND_SOUND_ENCODING));
         VALIDATORS.put(
                 Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_LEVEL,
                 new InclusiveIntegerRangeValidator(0, 100));
@@ -154,3 +140,4 @@
                         /* last= */Global.ONE_HANDED_KEYGUARD_SIDE_RIGHT));
     }
 }
+
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
index fdbbc39..df6ff73 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
@@ -18,6 +18,7 @@
 
 import android.annotation.SystemApi;
 import android.app.ActivityManager;
+import android.content.AttributionSource;
 import android.content.IContentProvider;
 import android.os.Binder;
 import android.os.Bundle;
@@ -250,7 +251,8 @@
                 Bundle args = new Bundle();
                 args.putInt(Settings.CALL_METHOD_USER_KEY,
                         ActivityManager.getService().getCurrentUser().id);
-                Bundle b = provider.call(resolveCallingPackage(), null, Settings.AUTHORITY,
+                Bundle b = provider.call(new AttributionSource(Process.myUid(),
+                                resolveCallingPackage(), null), Settings.AUTHORITY,
                         Settings.CALL_METHOD_DELETE_CONFIG, compositeKey, args);
                 success = (b != null && b.getInt(SettingsProvider.RESULT_ROWS_DELETED) == 1);
             } catch (RemoteException e) {
@@ -266,7 +268,8 @@
                 Bundle args = new Bundle();
                 args.putInt(Settings.CALL_METHOD_USER_KEY,
                         ActivityManager.getService().getCurrentUser().id);
-                Bundle b = provider.call(resolveCallingPackage(), null, Settings.AUTHORITY,
+                Bundle b = provider.call(new AttributionSource(Process.myUid(),
+                                resolveCallingPackage(), null), Settings.AUTHORITY,
                         Settings.CALL_METHOD_LIST_CONFIG, null, args);
                 if (b != null) {
                     Map<String, String> flagsToValues =
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
index 3b3ca5b..17ebf6f 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
@@ -17,6 +17,7 @@
 package com.android.providers.settings;
 
 import android.app.ActivityManager;
+import android.content.AttributionSource;
 import android.content.IContentProvider;
 import android.content.pm.PackageManager;
 import android.os.Binder;
@@ -309,7 +310,9 @@
             try {
                 Bundle arg = new Bundle();
                 arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
-                Bundle result = provider.call(resolveCallingPackage(), null, Settings.AUTHORITY,
+                final AttributionSource attributionSource = new AttributionSource(
+                        Binder.getCallingUid(), resolveCallingPackage(), /*attributionTag*/ null);
+                Bundle result = provider.call(attributionSource, Settings.AUTHORITY,
                         callListCommand, null, arg);
                 lines.addAll(result.getStringArrayList(SettingsProvider.RESULT_SETTINGS_LIST));
                 Collections.sort(lines);
@@ -334,7 +337,9 @@
             try {
                 Bundle arg = new Bundle();
                 arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
-                Bundle b = provider.call(resolveCallingPackage(), null, Settings.AUTHORITY,
+                final AttributionSource attributionSource = new AttributionSource(
+                        Binder.getCallingUid(), resolveCallingPackage(), /*attributionTag*/ null);
+                Bundle b = provider.call(attributionSource, Settings.AUTHORITY,
                         callGetCommand, key, arg);
                 if (b != null) {
                     result = b.getPairValue();
@@ -372,7 +377,9 @@
                 if (makeDefault) {
                     arg.putBoolean(Settings.CALL_METHOD_MAKE_DEFAULT_KEY, true);
                 }
-                provider.call(resolveCallingPackage(), null, Settings.AUTHORITY,
+                final AttributionSource attributionSource = new AttributionSource(
+                        Binder.getCallingUid(), resolveCallingPackage(), /*attributionTag*/ null);
+                provider.call(attributionSource, Settings.AUTHORITY,
                         callPutCommand, key, arg);
             } catch (RemoteException e) {
                 throw new RuntimeException("Failed in IPC", e);
@@ -396,7 +403,9 @@
             try {
                 Bundle arg = new Bundle();
                 arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
-                Bundle result = provider.call(resolveCallingPackage(), null, Settings.AUTHORITY,
+                final AttributionSource attributionSource = new AttributionSource(
+                        Binder.getCallingUid(), resolveCallingPackage(), /*attributionTag*/ null);
+                Bundle result = provider.call(attributionSource, Settings.AUTHORITY,
                         callDeleteCommand, key, arg);
                 return result.getInt(SettingsProvider.RESULT_ROWS_DELETED);
             } catch (RemoteException e) {
@@ -423,7 +432,9 @@
                 }
                 String packageName = mPackageName != null ? mPackageName : resolveCallingPackage();
                 arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
-                provider.call(packageName, null, Settings.AUTHORITY, callResetCommand, null, arg);
+                final AttributionSource attributionSource = new AttributionSource(
+                        Binder.getCallingUid(), resolveCallingPackage(), /*attributionTag*/ null);
+                provider.call(attributionSource, Settings.AUTHORITY, callResetCommand, null, arg);
             } catch (RemoteException e) {
                 throw new RuntimeException("Failed in IPC", e);
             }
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index cff8ad1..4c56db4 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -35,6 +35,8 @@
     <uses-permission android:name="android.permission.WRITE_CONTACTS" />
     <uses-permission android:name="android.permission.READ_CALENDAR" />
     <uses-permission android:name="android.permission.WRITE_CALENDAR" />
+    <uses-permission android:name="android.permission.READ_CALL_LOG" />
+    <uses-permission android:name="android.permission.WRITE_CALL_LOG" />
     <uses-permission android:name="android.permission.READ_USER_DICTIONARY" />
     <uses-permission android:name="android.permission.WRITE_USER_DICTIONARY" />
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
@@ -194,11 +196,14 @@
     <uses-permission android:name="android.permission.MANAGE_CAMERA" />
     <!-- Permissions needed to test system only camera devices -->
     <uses-permission android:name="android.permission.CAMERA" />
+    <uses-permission android:name="android.permission.BACKGROUND_CAMERA" />
     <uses-permission android:name="android.permission.SYSTEM_CAMERA" />
       <!-- Permissions needed to test onCameraOpened/Closed callbacks -->
     <uses-permission android:name="android.permission.CAMERA_OPEN_CLOSE_LISTENER" />
     <!-- Permissions needed for CTS camera test: RecordingTest.java when assuming shell id -->
     <uses-permission android:name="android.permission.RECORD_AUDIO" />
+    <uses-permission android:name="android.permission.RECORD_BACKGROUND_AUDIO" />
+
     <!-- Permission needed to enable/disable Bluetooth/Wifi -->
     <uses-permission android:name="android.permission.MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED" />
     <uses-permission android:name="android.permission.MANAGE_WIFI_WHEN_WIRELESS_CONSENT_REQUIRED" />
diff --git a/packages/SoundPicker/res/values-pa/strings.xml b/packages/SoundPicker/res/values-pa/strings.xml
index 2653c64..eb630c9 100644
--- a/packages/SoundPicker/res/values-pa/strings.xml
+++ b/packages/SoundPicker/res/values-pa/strings.xml
@@ -17,7 +17,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="ringtone_default" msgid="798836092118824500">"ਪੂਰਵ-ਨਿਰਧਾਰਤ ਰਿੰਗਟੋਨ"</string>
-    <string name="notification_sound_default" msgid="8133121186242636840">"ਪੂਰਵ-ਨਿਰਧਾਰਤ ਸੂਚਨਾ ਧੁਨੀ"</string>
+    <string name="notification_sound_default" msgid="8133121186242636840">"ਪੂਰਵ-ਨਿਰਧਾਰਿਤ ਸੂਚਨਾ ਧੁਨੀ"</string>
     <string name="alarm_sound_default" msgid="4787646764557462649">"ਪੂਰਵ-ਨਿਰਧਾਰਤ ਅਲਾਰਮ ਧੁਨੀ"</string>
     <string name="add_ringtone_text" msgid="6642389991738337529">"ਰਿੰਗਟੋਨ ਸ਼ਾਮਲ ਕਰੋ"</string>
     <string name="add_alarm_text" msgid="3545497316166999225">"ਅਲਾਰਮ ਸ਼ਾਮਲ ਕਰੋ"</string>
diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS
index f884270..835471d 100644
--- a/packages/SystemUI/OWNERS
+++ b/packages/SystemUI/OWNERS
@@ -9,6 +9,7 @@
 awickham@google.com
 beverlyt@google.com
 brockman@google.com
+ccassidy@google.com
 cinek@google.com
 cwren@google.com
 dupin@google.com
@@ -19,10 +20,10 @@
 hyunyoungs@google.com
 jaggies@google.com
 jamesoleary@google.com
+jdemeulenaere@google.com
 jeffdq@google.com
 jjaggi@google.com
 jonmiranda@google.com
-joshmcgrath@google.com
 joshtrask@google.com
 juliacr@google.com
 juliatuttle@google.com
@@ -37,7 +38,6 @@
 mpietal@google.com
 mrcasey@google.com
 mrenouf@google.com
-nbenbernou@google.com
 nesciosquid@google.com
 ogunwale@google.com
 peanutbutter@google.com
@@ -45,6 +45,7 @@
 pixel@google.com
 roosa@google.com
 santie@google.com
+shanh@google.com
 snoeberger@google.com
 sreyasr@google.com
 steell@google.com
@@ -59,6 +60,7 @@
 vadimt@google.com
 victortulias@google.com
 winsonc@google.com
+yurilin@google.com
 xuqiu@google.com
 zakcohen@google.com
 
diff --git a/packages/SystemUI/docs/falsing.md b/packages/SystemUI/docs/falsing.md
new file mode 100644
index 0000000..e224ca8
--- /dev/null
+++ b/packages/SystemUI/docs/falsing.md
@@ -0,0 +1,240 @@
+# Falsing in SystemUI
+
+Phones are easily and often accidentally-activated in owners' pockets ("falsing" or "pocket 
+dialing"). Because a phone's screen can be turned on with a single tap, and because we have further
+actions that be activated with basic tapping and swiping, it is critical that we
+analyze touch events on the screen for intentional vs accidental behavior. With analysis, 
+features within SystemUI have an opportunity to ignore or even undo accidental interactions as they
+are occurring.
+
+## Technical Details
+
+The `FalsingManager` tracks all touch interactions happening on a phone's lock screen.
+
+If you support any sort of touch gestures on the lock screen, you **must**, at a
+minimum, inform the `FalsingManager` of what touches are on touch targets vs not (things that may be
+ intentional). If you do not tell the `FalsingManager`, it will assume touches on your feature are
+always accidental and penalize the session accordingly.
+
+Individual touch targets do not _have_ to be separated out; it's acceptable to
+wrap your whole feature in one virtual block that reports touches to the
+`FalsingManager`, however more granular tracking will result in better results
+across the whole lock screen.
+
+You can _act_ on the results of the `FalsingManager`. Instead of only telling
+the `FalsingManager` that touch events were on touch targets, you can further use the
+returned results to decide if you want to respond to an owner's touch, if you
+want to prompt them to confirm their action, or if you simply want to ignore the
+touch.
+
+The flow through the system looks like such:
+
+1. Gesture on the screen.
+2. The `FalsingManager` makes a note of all of the `MotionEvents`.
+    * If no feature/touch target receives the `MotionEvents`, skip to 4. 
+3. Your touch target receives the `MotionEvents`.
+    * Once your feature is ready to respond to the gesture in a substantive manner, it queries
+      the `FalsingManager`.
+      - Dragging animations, touch ripples, and other purely visual effects should not query.
+      - Query once you are ready to launch a new feature or dialogue, or are otherwise going to
+        change the state of the UI. 
+      - Generally, wait until `MotionEvent.ACTION_UP` to query or `View.OnClickListener#onClick`.
+      - Only query once per gesture, at the end.
+    * If the `FalsingManager` says it looks good, respond to the touch.
+4. The `FalsingManager` checks to see if anyone queried about the gesture. If not, mark it as 
+   accidental. 
+   
+There is also an event fired by the `FalsingManager` that can be listened to by anyone, that 
+indicates that the the `FalsingManager` believes the phone is actively being pocket-dialed. When
+fired, modal features, such as quick settings, keyguard bouncer, and others should retract 
+themselves to prevent further pocket-dialing.  
+
+## Falsing "Belief" and History
+
+The `FalsingManager` maintains a recent history of false analyses. Using
+Bayesian statistics, it updates a "belief" in  whether recent
+gestures are intentional or not. Any gesture that it is not explicitly queried about is treated as
+accidental, increasing the overall belief in
+false-iness. Gestures that are explicitly queried and that pass the relevant heuristics
+reduce belief that falsing is occurring. This information is tracked within the `HistoryTracker`.
+
+Changes in belief may influence internal heurstics within the `FalsingManager`,
+making it easier or harder for an owner to interact with their device. (An owner
+will always be able to interact with their device, but we may require double
+taps, or more deliberate swipes.)
+
+## Responding to Touch Events
+
+The methods below inform the `FalsingManager` that a tap is occurring within an expected touch 
+target. Match the methods with the gesture you expect the device owner to use.
+
+### Single Tap
+
+`FalsingManager#isFalseTap(boolean robustCheck, double falsePenalty)`. This
+method tells the `FalsingManager` that you want to validate a single tap. It
+returns true if it thinks the tap should be rejected (i.e. the tap looks more
+like a swipe) and false otherwise.
+
+`robustCheck` determines what heuristics are used. If set to false, the method
+performs a only very basic checking, checking that observed `MotionEvent`s are
+all within some small x & y region ("touch slop").
+
+When `robustCheck` is set to true, several more advanced rules are additionally
+applied:
+
+1.  If the device recognizes a face (i.e. face-auth) the tap is **accepted**.
+2.  If the tap is the _second_ tap in recent history and looks like a valid Double Tap
+    the tap is **accepted**. This works exactly like `FalsingManager#isFalseDoubleTap`.
+3.  If the `HistoryTracker` reports strong belief in recent falsing, the tap is
+    **rejected**.
+4.  Otherwise the tap is **accepted**.
+
+All the above rules are applied only after first confirming the gesture does
+in fact look like a basic tap.
+
+`falsePenalty` is a measure of how much the `HistoryTracker`'s belief should be
+penalized in the event that the tap is rejected. This value is only used if
+`robustCheck` is set to true.
+
+A value of `0` means no change in belief. A value of `1` means a _very_ strong
+confidence in a false tap. In general, as a single tap on the screen is not
+verifiable, a small value should be supplied - on the order of `0.1`. Pass `0`
+if you don't want to penalize belief at all. Pass a higher value
+the earlier in the UX flow your interaction occurs. Once an owner is farther
+along in a UX flow (multiple taps or swipes), its safer to assume that a single
+accidental tap should cause less of a penalty.
+
+### Double Tap
+
+`FalsingManager#isFalseDoubleTap()`. This method tells the `FalsingManager` that
+your UI wants to validate a double tap. There are no parameters to pass to this method.
+Call this when you explicitly receive and want to verify a double tap, _not_ a single tap.
+
+Note that `FalsingManager#isFalseTap(boolean robustCheck, double falsePenalty)`
+will also check for double taps when `robustCheck` is set to true. If you are
+willing to use single taps, use that instead.
+
+### Swipes and Other Gestures
+
+`FalsingManager#isFalseTouch(@Classifier.InteractionType int interactionType)`.
+Use this for any non-tap interactions. This includes expanding notifications,
+expanding quick settings, pulling up the bouncer, and more. You must pass
+the type of interaction you are evaluating when calling it. A large set of
+heuristics will be applied to analyze the gesture, and the exact rules vary depending upon
+the `InteractionType`.
+
+### Ignoring A Gesture
+
+`FalsingCollector#avoidGesture()`. Tell the `FalsingManager` to pretend like the
+observed gesture never happened. **This method must be called when the observed
+`MotionEvent` is `MotionEvent.ACTION_DOWN`.** Attempting to call this method
+later in a gesture will not work.
+
+Notice that this method is actually a method on `FalsingCollector`. It is
+forcefully telling the `FalsingManager` to wholly pretend the gesture never
+happened. This is intended for security and PII sensitive gestures, such as
+password inputs. Please don't use this as a shortcut for avoiding the
+FalsingManager. Falsing works better the more behavior it is told about.
+
+### Other Considerations
+
+Please try to call the `FalsingManager` only once per gesture. Wait until you
+are ready to act on the owner's action, and then query the `FalsingManager`. The `FalsingManager`
+will update its belief in pocket dialing based only on the last call made, so multiple calls per
+gesture are not well defined.
+
+The `FalsingManager` does not update its belief in pocket-dialing until a new
+gesture starts. That is to say, if the owner makes a bad tap on your feature,
+the belief in pocket dialing will not incorporate this new data until the
+following gesture begins.
+
+If you expect a mix of taps, double taps, and swipes on your feature, segment them
+accordingly. Figure out which `FalsingManager` method you need to call first, rather than relying
+on multiple calls to the `FalsingManager` to act as a sieve.
+
+Don't:
+```
+if (!mFalsingManager.isFalseTap(false, 0)) {
+  // its a tap
+} else if (!mFalsingManager.isFalseTouch(GESTURE_A) {
+  // do thing a
+} else if (!mFalsingManager.isFalseTouch(GESTURE_B) {
+  // do thing b
+} else {
+  // must be a false.
+}
+``` 
+
+Do:
+```
+void onTap() {
+  if (!mFalsingManager.isFalseTap(false, 0)) {
+    // its a tap
+}
+
+void onGestureA() {
+  if (!mFalsingManager.isFalseTouch(GESTURE_A) {
+    // do thing a
+  }
+}
+
+void onGestureB() {
+  if (!mFalsingManager.isFalseTouch(GESTURE_B) {
+    // do thing b
+  }
+}
+``` 
+
+
+## Influencing Belief
+
+`FalsingCollector#updateFalseConfidence(FalsingClassifier.Result result)`. This
+method allows you to directly change the `FalsingManager`'s belief in the state
+of pocket dialing. If the owner does something unusual with their phone that you
+think indicates pocket dialing, you can call:
+
+```
+    mFalsingCollector.updateFalseConfidence(
+      FalsingClassifier.Result.falsed(0.6, "Owner is doing something fishy"));
+```
+
+A belief value of `1` indicates a 100% confidence of false behavior. A belief
+value of `0` would make no change in the `FalsingManager` and should be avoided
+as it simply creates noise in the logs. Generally, a middle value between the
+two extremes makes sense.
+
+A good example of where this is used is in the "Pattern" password input. We
+avoid recording those gestures in the `FalsingManager`, but we have the pattern input update
+the `FalsingManager` directly in some cases. If the owner simply taps on the pattern input, we 
+record it as a false, (patterns are always 4 "cells" long, so single "cell" inputs are penalized).
+
+Conversely, if you think the owner does something that deserves a nice reward:
+
+```
+    mFalsingCollector.updateFalseConfidence(
+       FalsingClassifier.Result.passed(0.6));
+```
+
+Again, useful on password inputs where the FalsingManager is avoiding recording
+the gesture. This is used on the "pin" password input, to recognize successful
+taps on the input buttons.
+
+## Global Falsing Event
+
+If the `FalsingManager`'s belief in falsing crosses some internally defined
+threshold, it will fire an event that other parts of the system can listen for.
+This even indicates that the owner is likely actively pocket-dialing, and any
+currently open activities on the phone should retract themselves.
+
+To subscribe to this event, call
+`FalsingManager#addFalsingBeliefListener(FalsingBeliefListener listener)`.
+`FalsingBeliefListener` is a simple one method interface that will be called
+after when activities should retract themselves.
+
+**Do Listen For This**. Your code will work without it, but it is a handy,
+universal signal that will save the phone owner a lot of accidents. A simple
+implementation looks like:
+
+```
+    mFalsingManager.addFalsingBeliefListener(MyFeatureClass::hide);
+```
diff --git a/packages/SystemUI/res-keyguard/values-iw/strings.xml b/packages/SystemUI/res-keyguard/values-iw/strings.xml
index 8780dc5..56a71d4 100644
--- a/packages/SystemUI/res-keyguard/values-iw/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-iw/strings.xml
@@ -21,17 +21,17 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_name" msgid="514691256816366517">"מגן מקלדת"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"הזן את קוד הגישה"</string>
+    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"יש להזין את קוד האימות"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"‏הזן את קוד ה-PUK של כרטיס ה-SIM ולאחר מכן הזן קוד גישה חדש"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"‏קוד PUK של כרטיס SIM"</string>
     <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"‏קוד גישה חדש לכרטיס ה-SIM"</string>
     <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"גע כדי להזין את הסיסמה"</font></string>
     <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"הזן סיסמה לביטול הנעילה"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"הזן את קוד הגישה לביטול הנעילה"</string>
-    <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"הזנת קוד גישה"</string>
+    <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"צריך להזין קוד אימות"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"יש להזין קו ביטול נעילה"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"יש להזין סיסמה"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"קוד הגישה שגוי"</string>
+    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"קוד האימות שגוי"</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"כרטיס לא חוקי."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"הסוללה טעונה"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה אלחוטית"</string>
@@ -43,14 +43,14 @@
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"לחץ על \'תפריט\' כדי לבטל את הנעילה."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"הרשת נעולה"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"‏אין כרטיס SIM"</string>
-    <string name="keyguard_missing_sim_instructions" msgid="1162120926141335918">"‏הכנס כרטיס SIM."</string>
+    <string name="keyguard_missing_sim_instructions" msgid="1162120926141335918">"‏יש להכניס כרטיס SIM."</string>
     <string name="keyguard_missing_sim_instructions_long" msgid="2712623293749378570">"‏כרטיס ה-SIM חסר או שלא ניתן לקרוא אותו. הכנס כרטיס SIM."</string>
     <string name="keyguard_permanent_disabled_sim_message_short" msgid="5842745213110966962">"‏לא ניתן להשתמש בכרטיס SIM זה."</string>
     <string name="keyguard_permanent_disabled_sim_instructions" msgid="2490584154727897806">"‏כרטיס ה-SIM שלך הושבת לצמיתות.\nפנה לספק השירות האלחוטי שלך לקבלת כרטיס SIM אחר."</string>
     <string name="keyguard_sim_locked_message" msgid="4343544458476911044">"‏כרטיס ה-SIM נעול."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="6253830777745450550">"‏כרטיס ה-SIM נעול באמצעות PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="2394023844117630429">"‏מבטל את הנעילה של כרטיס ה-SIM…"</string>
-    <string name="keyguard_accessibility_pin_area" msgid="7403009340414014734">"אזור לקוד הגישה"</string>
+    <string name="keyguard_accessibility_pin_area" msgid="7403009340414014734">"אזור של קוד האימות"</string>
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"סיסמת מכשיר"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"‏אזור לקוד הגישה של כרטיס ה-SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"‏אזור לקוד הגישה של כרטיס ה-SIM"</string>
@@ -63,7 +63,7 @@
     <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"שכחתי את קו ביטול הנעילה"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"קו ביטול נעילה שגוי"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"סיסמה שגויה"</string>
-    <string name="kg_wrong_pin" msgid="4160978845968732624">"קוד הגישה שגוי"</string>
+    <string name="kg_wrong_pin" msgid="4160978845968732624">"קוד האימות שגוי"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="991400408675793914">
       <item quantity="two">אפשר יהיה לנסות שוב בעוד <xliff:g id="NUMBER">%d</xliff:g> שניות.</item>
       <item quantity="many">אפשר יהיה לנסות שוב בעוד <xliff:g id="NUMBER">%d</xliff:g> שניות.</item>
@@ -72,28 +72,28 @@
     </plurals>
     <string name="kg_pattern_instructions" msgid="5376036737065051736">"שרטט את קו ביטול הנעילה"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"‏הזן את קוד הגישה של כרטיס ה-SIM."</string>
-    <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"‏הזן את קוד הגישה של כרטיס ה-SIM של <xliff:g id="CARRIER">%1$s</xliff:g>."</string>
+    <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"‏יש להזין את קוד האימות של כרטיס ה-SIM של <xliff:g id="CARRIER">%1$s</xliff:g>."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"‏<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> יש להשבית את כרטיס ה-eSIM כדי להשתמש במכשיר ללא שירות סלולרי."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"הזן קוד גישה"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"הזן את הסיסמה"</string>
+    <string name="kg_pin_instructions" msgid="822353548385014361">"יש להזין קוד אימות"</string>
+    <string name="kg_password_instructions" msgid="324455062831719903">"צריך להזין את הסיסמה"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"‏כרטיס ה-SIM מושבת כעת. הזן קוד PUK כדי להמשיך. פנה אל הספק לפרטים."</string>
-    <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"‏ה-SIM של \"<xliff:g id="CARRIER">%1$s</xliff:g>\" מושבת כעת. הזן קוד PUK כדי להמשיך. לפרטים, פנה אל הספק."</string>
+    <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"‏ה-SIM של \"<xliff:g id="CARRIER">%1$s</xliff:g>\" מושבת עכשיו. צריך להזין קוד PUK כדי להמשיך. לפרטים, יש לפנות אל הספק."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"הזן את קוד הגישה הרצוי"</string>
-    <string name="kg_enter_confirm_pin_hint" msgid="4261064020391799132">"אשר את קוד הגישה הרצוי"</string>
-    <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"‏מבטל את הנעילה של כרטיס ה-SIM…"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="4261064020391799132">"צריך לאשר את קוד האימות הרצוי"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"‏מתבצע ביטול נעילה של כרטיס ה-SIM…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"הקלד קוד גישה שאורכו 4 עד 8 ספרות."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"‏קוד PUK צריך להיות בן 8 ספרות או יותר."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"‏הזן את קוד ה-PUK הנכון. ניסיונות חוזרים ישביתו את כרטיס ה-SIM לצמיתות."</string>
+    <string name="kg_invalid_puk" msgid="1774337070084931186">"‏יש להזין את קוד ה-PUK הנכון. ניסיונות חוזרים ישביתו את כרטיס ה-SIM באופן סופי."</string>
     <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"ניסית לשרטט את קו ביטול הנעילה יותר מדי פעמים"</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"הקלדת קוד גישה שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. \n\nנסה שוב בעוד <xliff:g id="NUMBER_1">%2$d</xliff:g> שניות."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"הקלדת קוד גישה שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. \n\nיש לנסות שוב בעוד <xliff:g id="NUMBER_1">%2$d</xliff:g> שניות."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"הקלדת סיסמה שגויה <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים.\n\nנסה שוב בעוד <xliff:g id="NUMBER_1">%2$d</xliff:g> שניות."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"שרטטת קו ביטול נעילה שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. \n\nנסה שוב בעוד <xliff:g id="NUMBER_1">%2$d</xliff:g> שניות."</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"‏קוד הגישה של כרטיס ה-SIM שגוי. צור קשר עם הספק כדי לבטל את נעילת המכשיר."</string>
     <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
-      <item quantity="two">‏קוד הגישה של כרטיס ה-SIM שגוי. נותרו לך עוד <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות.</item>
-      <item quantity="many">‏קוד הגישה של כרטיס ה-SIM שגוי. נותרו לך עוד <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות.</item>
-      <item quantity="other">‏קוד הגישה של כרטיס ה-SIM שגוי. נותרו לך עוד <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות.</item>
-      <item quantity="one">‏קוד הגישה של כרטיס ה-SIM שגוי. נותר לך עוד ניסיון <xliff:g id="NUMBER_0">%d</xliff:g> לפני שיהיה עליך ליצור קשר עם הספק כדי לבטל את נעילת המכשיר.</item>
+      <item quantity="two">‏קוד האימות של כרטיס ה-SIM שגוי. נותרו לך עוד <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות.</item>
+      <item quantity="many">‏קוד האימות של כרטיס ה-SIM שגוי. נותרו לך עוד <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות.</item>
+      <item quantity="other">‏קוד האימות של כרטיס ה-SIM שגוי. נותרו לך עוד <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות.</item>
+      <item quantity="one">‏קוד האימות של כרטיס ה-SIM שגוי. נותר לך עוד ניסיון <xliff:g id="NUMBER_0">%d</xliff:g> לפני שיהיה עליך ליצור קשר עם הספק כדי לבטל את נעילת המכשיר.</item>
     </plurals>
     <string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"‏לא ניתן להשתמש בכרטיס ה-SIM. צור קשר עם הספק."</string>
     <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="3937306685604862886">
@@ -103,27 +103,27 @@
       <item quantity="one">‏קוד ה-PUK של כרטיס ה-SIM שגוי. נותר לך ניסיון <xliff:g id="NUMBER_0">%d</xliff:g> נוסף לפני שכרטיס ה-SIM יינעל לצמיתות.</item>
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"‏פעולת קוד הגישה של כרטיס ה-SIM נכשלה!"</string>
-    <string name="kg_password_puk_failed" msgid="6778867411556937118">"‏פעולת קוד ה-PUK של כרטיס ה-SIM נכשלה!"</string>
+    <string name="kg_password_puk_failed" msgid="6778867411556937118">"‏הניסיון לביטול הנעילה של כרטיס ה-SIM באמצעות קוד PUK נכשל!"</string>
     <string name="kg_pin_accepted" msgid="1625501841604389716">"הקוד התקבל!"</string>
     <string name="keyguard_carrier_default" msgid="6359808469637388586">"אין שירות."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"החלפת שיטת קלט"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"מצב טיסה"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"יש להזין את קו ביטול הנעילה לאחר הפעלה מחדש של המכשיר"</string>
-    <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"יש להזין קוד גישה לאחר הפעלה מחדש של המכשיר"</string>
+    <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"צריך להזין קוד אימות לאחר הפעלה מחדש של המכשיר"</string>
     <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"יש להזין סיסמה לאחר הפעלה מחדש של המכשיר"</string>
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"יש להזין את קו ביטול הנעילה כדי להגביר את רמת האבטחה"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"יש להזין קוד גישה כדי להגביר את רמת האבטחה"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"יש להזין סיסמה כדי להגביר את רמת האבטחה"</string>
     <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"יש להזין את קו ביטול הנעילה בזמן מעבר בין פרופילים"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"יש להזין את קוד הגישה בזמן מעבר בין פרופילים"</string>
+    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"צריך להזין את קוד האימות כשמחליפים פרופיל"</string>
     <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"יש להזין את הסיסמה בזמן מעבר בין פרופילים"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"מנהל המכשיר נעל את המכשיר"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"המכשיר ננעל באופן ידני"</string>
     <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="two">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_1">%d</xliff:g> שעות. הזן את קו ביטול הנעילה.</item>
-      <item quantity="many">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_1">%d</xliff:g> שעות. הזן את קו ביטול הנעילה.</item>
-      <item quantity="other">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_1">%d</xliff:g> שעות. הזן את קו ביטול הנעילה.</item>
-      <item quantity="one">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_0">%d</xliff:g> שעה. הזן את קו ביטול הנעילה.</item>
+      <item quantity="two">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_1">%d</xliff:g> שעות. יש להזין את קו ביטול הנעילה.</item>
+      <item quantity="many">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_1">%d</xliff:g> שעות. יש להזין את קו ביטול הנעילה.</item>
+      <item quantity="other">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_1">%d</xliff:g> שעות. יש להזין את קו ביטול הנעילה.</item>
+      <item quantity="one">נעילת המכשיר לא בוטלה במשך שעה אחת (<xliff:g id="NUMBER_0">%d</xliff:g>). יש להזין את קו ביטול הנעילה.</item>
     </plurals>
     <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
       <item quantity="two">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_1">%d</xliff:g> שעות. הזן את קוד הגישה.</item>
@@ -132,18 +132,18 @@
       <item quantity="one">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_0">%d</xliff:g> שעה. הזן את קוד הגישה.</item>
     </plurals>
     <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="two">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_1">%d</xliff:g> שעות. הזן את הסיסמה.</item>
-      <item quantity="many">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_1">%d</xliff:g> שעות. הזן את הסיסמה.</item>
-      <item quantity="other">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_1">%d</xliff:g> שעות. הזן את הסיסמה.</item>
-      <item quantity="one">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_0">%d</xliff:g> שעה. הזן את הסיסמה.</item>
+      <item quantity="two">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_1">%d</xliff:g> שעות. יש להזין את הסיסמה.</item>
+      <item quantity="many">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_1">%d</xliff:g> שעות. יש להזין את הסיסמה.</item>
+      <item quantity="other">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_1">%d</xliff:g> שעות. יש להזין את הסיסמה.</item>
+      <item quantity="one">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_0">%d</xliff:g> שעה. יש להזין את הסיסמה.</item>
     </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"לא זוהתה"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"לא זוהתה"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
-      <item quantity="two">‏יש להזין קוד גישה לכרטיס SIM. נותרו לך <xliff:g id="NUMBER_1">%d</xliff:g> ניסונות נוספים.</item>
-      <item quantity="many">‏יש להזין קוד גישה לכרטיס SIM. נותרו לך <xliff:g id="NUMBER_1">%d</xliff:g> ניסונות נוספים.</item>
-      <item quantity="other">‏יש להזין קוד גישה לכרטיס SIM. נותרו לך <xliff:g id="NUMBER_1">%d</xliff:g> ניסונות נוספים.</item>
-      <item quantity="one">‏יש להזין קוד גישה לכרטיס SIM. נותר לך <xliff:g id="NUMBER_0">%d</xliff:g> ניסיון נוסף לפני שיהיה צורך ליצור קשר עם הספק כדי לבטל את נעילת המכשיר.</item>
+      <item quantity="two">‏יש להזין קוד אימות של כרטיס SIM. נותרו לך <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות נוספים.</item>
+      <item quantity="many">‏יש להזין קוד אימות של כרטיס SIM. נותרו לך <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות נוספים.</item>
+      <item quantity="other">‏יש להזין קוד אימות של כרטיס SIM. נותרו לך <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות נוספים.</item>
+      <item quantity="one">‏יש להזין קוד אימות של כרטיס SIM. נותר לך ניסיון נוסף (<xliff:g id="NUMBER_0">%d</xliff:g>) לפני שיהיה צורך ליצור קשר עם הספק כדי לבטל את נעילת המכשיר.</item>
     </plurals>
     <plurals name="kg_password_default_puk_message" formatted="false" msgid="571308542462946935">
       <item quantity="two">‏כרטיס ה-SIM מושבת כעת. יש להזין קוד PUK כדי להמשיך. נותרו לך <xliff:g id="_NUMBER_1">%d</xliff:g> ניסיונות נוספים לפני שכרטיס ה-SIM ינעל לצמיתות. למידע נוסף, ניתן לפנות לספק שלך.</item>
diff --git a/packages/SystemUI/res-keyguard/values-pa/strings.xml b/packages/SystemUI/res-keyguard/values-pa/strings.xml
index 04419e0..47b2881 100644
--- a/packages/SystemUI/res-keyguard/values-pa/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pa/strings.xml
@@ -135,7 +135,7 @@
       <item quantity="one">ਸਿਮ ਹੁਣ ਬੰਦ ਹੋ ਗਿਆ ਹੈ। ਜਾਰੀ ਰੱਖਣ ਲਈ PUK ਕੋਡ ਦਾਖਲ ਕਰੋ। ਸਿਮ ਦੇ ਪੱਕੇ ਤੌਰ \'ਤੇ ਬੇਕਾਰ ਹੋ ਜਾਣ ਤੋਂ ਪਹਿਲਾਂ ਤੁਹਾਡੇ ਕੋਲ <xliff:g id="_NUMBER_1">%d</xliff:g> ਕੋਸ਼ਿਸ਼ ਬਾਕੀ ਹੈ। ਵੇਰਵਿਆਂ ਲਈ ਕੈਰੀਅਰ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।</item>
       <item quantity="other">ਸਿਮ ਹੁਣ ਬੰਦ ਹੋ ਗਿਆ ਹੈ। ਜਾਰੀ ਰੱਖਣ ਲਈ PUK ਕੋਡ ਦਾਖਲ ਕਰੋ। ਸਿਮ ਦੇ ਪੱਕੇ ਤੌਰ \'ਤੇ ਬੇਕਾਰ ਹੋ ਜਾਣ ਤੋਂ ਪਹਿਲਾਂ ਤੁਹਾਡੇ ਕੋਲ <xliff:g id="_NUMBER_1">%d</xliff:g> ਕੋਸ਼ਿਸ਼ਾਂ ਬਾਕੀ ਹਨ। ਵੇਰਵਿਆਂ ਲਈ ਕੈਰੀਅਰ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।</item>
     </plurals>
-    <string name="clock_title_default" msgid="6342735240617459864">"ਪੂਰਵ-ਨਿਰਧਾਰਤ"</string>
+    <string name="clock_title_default" msgid="6342735240617459864">"ਪੂਰਵ-ਨਿਰਧਾਰਿਤ"</string>
     <string name="clock_title_bubble" msgid="2204559396790593213">"ਬੁਲਬੁਲਾ"</string>
     <string name="clock_title_analog" msgid="8409262532900918273">"ਐਨਾਲੌਗ"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-iw/strings.xml b/packages/SystemUI/res-product/values-iw/strings.xml
index 4ba8657..3fc8013 100644
--- a/packages/SystemUI/res-product/values-iw/strings.xml
+++ b/packages/SystemUI/res-product/values-iw/strings.xml
@@ -31,15 +31,15 @@
     <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"ניסית לבטל את נעילת הטאבלט <xliff:g id="NUMBER">%d</xliff:g> פעמים. הטאבלט יאופס וכל הנתונים שלו יימחקו."</string>
     <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"ניסית לבטל את נעילת הטלפון <xliff:g id="NUMBER">%d</xliff:g> פעמים. הטלפון יאופס וכל הנתונים שבו יימחקו."</string>
     <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"ניסית לבטל את נעילת הטאבלט <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, משתמש זה יוסר וכל נתוני המשתמש יימחקו."</string>
-    <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"ניסית לבטל את נעילת הטלפון <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, משתמש זה יוסר וכל נתוני המשתמש יימחקו."</string>
+    <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"ניסית לבטל את נעילת הטלפון <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, המשתמש הזה יוסר וכל נתוני המשתמש יימחקו."</string>
     <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"ניסית לבטל את נעילת הטאבלט <xliff:g id="NUMBER">%d</xliff:g> פעמים באופן שגוי. משתמש זה יוסר וכל נתוני המשתמש יימחקו."</string>
-    <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"ניסית לבטל את נעילת הטלפון <xliff:g id="NUMBER">%d</xliff:g> פעמים. משתמש זה יוסר וכל נתוני המשתמש יימחקו."</string>
+    <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"ניסית לבטל את נעילת הטלפון <xliff:g id="NUMBER">%d</xliff:g> פעמים. המשתמש הזה יוסר וכל נתוני המשתמש יימחקו."</string>
     <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"ניסית לבטל את נעילת הטאבלט <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, פרופיל העבודה יוסר וכל נתוני הפרופיל יימחקו."</string>
     <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"ניסית לבטל את נעילת הטלפון <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, פרופיל העבודה יוסר וכל נתוני הפרופיל יימחקו."</string>
     <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"ניסית לבטל את נעילת הטאבלט <xliff:g id="NUMBER">%d</xliff:g> פעמים. פרופיל העבודה יוסר וכל נתוני הפרופיל יימחקו."</string>
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"ניסית לבטל את נעילת הטלפון <xliff:g id="NUMBER">%d</xliff:g> פעמים. פרופיל העבודה יוסר וכל נתוני הפרופיל יימחקו."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"שרטטת קו ביטול נעילה שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, ,תישלח אליך בקשה לבטל את נעילת הטאבלט באמצעות חשבון אימייל‏.\n\n יש לנסות שוב בעוד <xliff:g id="NUMBER_2">%3$d</xliff:g> שניות."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"שרטטת קו ביטול נעילה שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, תשילח אליך בקשה לבטל את נעילת הטלפון באמצעות חשבון אימייל‏.\n\n יש לנסות שוב בעוד <xliff:g id="NUMBER_2">%3$d</xliff:g> שניות."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"שרטטת קו ביטול נעילה שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, תישלח אליך בקשה לבטל את נעילת הטלפון באמצעות חשבון אימייל‏.\n\n יש לנסות שוב בעוד <xliff:g id="NUMBER_2">%3$d</xliff:g> שניות."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"לאפשרויות נוספות, יש לבטל את נעילת הטלפון"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"לאפשרויות נוספות, יש לבטל את נעילת הטאבלט"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"לאפשרויות נוספות, יש לבטל את נעילת המכשיר"</string>
diff --git a/packages/SystemUI/res/color/remote_input_hint.xml b/packages/SystemUI/res/color/remote_input_hint.xml
new file mode 100644
index 0000000..7fe58db
--- /dev/null
+++ b/packages/SystemUI/res/color/remote_input_hint.xml
@@ -0,0 +1,19 @@
+<!--
+  ~ Copyright (C) 2021 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.
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="?android:attr/textColorPrimary" android:alpha=".6" />
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/remote_input_text.xml b/packages/SystemUI/res/color/remote_input_text.xml
index 33eeb77..3622c91 100644
--- a/packages/SystemUI/res/color/remote_input_text.xml
+++ b/packages/SystemUI/res/color/remote_input_text.xml
@@ -16,6 +16,6 @@
   -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="true" android:color="?android:attr/textColorTertiary" />
-    <item android:color="?android:attr/textColorTertiary" android:alpha=".6" />
+    <item android:state_enabled="true" android:color="?android:attr/textColorPrimary" />
+    <item android:color="?android:attr/textColorPrimary" android:alpha=".6" />
 </selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/notif_footer_btn_background.xml b/packages/SystemUI/res/drawable/notif_footer_btn_background.xml
new file mode 100644
index 0000000..f35f5d1
--- /dev/null
+++ b/packages/SystemUI/res/drawable/notif_footer_btn_background.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 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="@color/notif_pill_background"
+        />
+    <corners android:radius="20dp" />
+
+    <padding
+        android:left="20dp"
+        android:right="20dp">
+    </padding>
+
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/privacy_chip_bg.xml b/packages/SystemUI/res/drawable/privacy_chip_bg.xml
index 109442d..9f41dbe 100644
--- a/packages/SystemUI/res/drawable/privacy_chip_bg.xml
+++ b/packages/SystemUI/res/drawable/privacy_chip_bg.xml
@@ -16,6 +16,6 @@
 -->
 
 <shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="#FFFFFF" />
+    <solid android:color="@color/privacy_circle" />
     <corners android:radius="@dimen/ongoing_appops_chip_bg_corner_radius" />
 </shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/privacy_item_circle_camera.xml b/packages/SystemUI/res/drawable/privacy_item_circle_camera.xml
index 5cb6f46..54a66e2 100644
--- a/packages/SystemUI/res/drawable/privacy_item_circle_camera.xml
+++ b/packages/SystemUI/res/drawable/privacy_item_circle_camera.xml
@@ -24,7 +24,7 @@
                 android:height="@dimen/ongoing_appops_dialog_circle_size"
                 android:width="@dimen/ongoing_appops_dialog_circle_size"
             />
-            <solid android:color="@color/privacy_circle_camera" />
+            <solid android:color="@color/privacy_circle" />
         </shape>
     </item>
     <item android:id="@id/icon"
diff --git a/packages/SystemUI/res/drawable/privacy_item_circle_location.xml b/packages/SystemUI/res/drawable/privacy_item_circle_location.xml
index bff9b4b..65f4396 100644
--- a/packages/SystemUI/res/drawable/privacy_item_circle_location.xml
+++ b/packages/SystemUI/res/drawable/privacy_item_circle_location.xml
@@ -24,7 +24,7 @@
                 android:height="@dimen/ongoing_appops_dialog_circle_size"
                 android:width="@dimen/ongoing_appops_dialog_circle_size"
             />
-            <solid android:color="@color/privacy_circle_microphone_location" />
+            <solid android:color="@color/privacy_circle" />
         </shape>
     </item>
     <item android:id="@id/icon"
diff --git a/packages/SystemUI/res/drawable/privacy_item_circle_microphone.xml b/packages/SystemUI/res/drawable/privacy_item_circle_microphone.xml
index 28466c8..1565d2d 100644
--- a/packages/SystemUI/res/drawable/privacy_item_circle_microphone.xml
+++ b/packages/SystemUI/res/drawable/privacy_item_circle_microphone.xml
@@ -24,7 +24,7 @@
                 android:height="@dimen/ongoing_appops_dialog_circle_size"
                 android:width="@dimen/ongoing_appops_dialog_circle_size"
             />
-            <solid android:color="@color/privacy_circle_microphone_location" />
+            <solid android:color="@color/privacy_circle" />
         </shape>
     </item>
     <item android:id="@id/icon"
diff --git a/packages/SystemUI/res/drawable/remote_input_view_text_bg.xml b/packages/SystemUI/res/drawable/remote_input_view_text_bg.xml
new file mode 100644
index 0000000..5d374a9
--- /dev/null
+++ b/packages/SystemUI/res/drawable/remote_input_view_text_bg.xml
@@ -0,0 +1,31 @@
+<!--
+  ~ Copyright (C) 2021 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="?android:attr/colorBackgroundFloating" />
+    <stroke
+        android:width="@dimen/remote_input_view_text_stroke"
+        android:color="?android:attr/colorAccent"/>
+    <padding
+        android:bottom="12dp"
+        android:left="12dp"
+        android:right="12dp"
+        android:top="12dp"/>
+
+    <corners android:radius="24dp" />
+
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/remote_input.xml b/packages/SystemUI/res/layout/remote_input.xml
index 43182eb..ae3adb8 100644
--- a/packages/SystemUI/res/layout/remote_input.xml
+++ b/packages/SystemUI/res/layout/remote_input.xml
@@ -25,26 +25,25 @@
 
     <view class="com.android.systemui.statusbar.policy.RemoteInputView$RemoteEditText"
             android:id="@+id/remote_input_text"
-            android:layout_height="match_parent"
+            android:layout_height="wrap_content"
             android:layout_width="0dp"
             android:layout_weight="1"
             android:paddingTop="2dp"
-            android:paddingBottom="4dp"
             android:paddingStart="16dp"
             android:paddingEnd="12dp"
-            android:layout_marginRight="5dp"
+            android:layout_marginRight="20dp"
             android:layout_marginLeft="20dp"
             android:layout_marginTop="5dp"
-            android:layout_marginBottom="20dp"
-            android:gravity="start|center_vertical"
+            android:layout_marginBottom="16dp"
+            android:layout_gravity="start|center_vertical"
             android:textAppearance="?android:attr/textAppearance"
             android:textColor="@color/remote_input_text"
             android:textColorHint="@color/remote_input_hint"
             android:textSize="16sp"
             android:background="@null"
-            android:singleLine="true"
+            android:maxLines="4"
             android:ellipsize="start"
-            android:inputType="textShortMessage|textAutoCorrect|textCapSentences"
+            android:inputType="textShortMessage|textMultiLine|textAutoCorrect|textCapSentences"
             android:imeOptions="actionSend|flagNoExtractUi|flagNoFullscreen" />
 
     <FrameLayout
@@ -53,12 +52,12 @@
             android:layout_gravity="center_vertical">
 
         <ImageButton
-                android:layout_width="wrap_content"
+        android:layout_width="wrap_content"
                 android:layout_height="match_parent"
                 android:layout_gravity="center"
-                android:paddingBottom="20dp"
-                android:paddingStart="12dp"
-                android:paddingEnd="24dp"
+                android:paddingLeft="10dp"
+                android:layout_marginBottom="12dp"
+                android:layout_marginEnd="12dp"
                 android:id="@+id/remote_input_send"
                 android:src="@drawable/ic_send"
                 android:contentDescription="@*android:string/ime_action_send"
@@ -70,9 +69,8 @@
                 android:id="@+id/remote_input_progress"
                 android:layout_width="24dp"
                 android:layout_height="24dp"
-                android:layout_marginBottom="10dp"
-                android:layout_marginEnd="6dp"
-                android:layout_gravity="center"
+                android:layout_marginBottom="12dp"
+                android:layout_gravity="center_vertical"
                 android:visibility="invisible"
                 android:indeterminate="true"
                 style="?android:attr/progressBarStyleSmall" />
diff --git a/packages/SystemUI/res/layout/status_bar_notification_footer.xml b/packages/SystemUI/res/layout/status_bar_notification_footer.xml
index 5a1e5c4..5c77d16 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_footer.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_footer.xml
@@ -30,9 +30,11 @@
             style="@style/TextAppearance.NotificationSectionHeaderButton"
             android:id="@+id/manage_text"
             android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
+            android:layout_height="40dp"
             android:layout_gravity="start"
+            android:background="@drawable/notif_footer_btn_background"
             android:focusable="true"
+            android:textColor="@color/notif_pill_text"
             android:contentDescription="@string/manage_notifications_history_text"
             android:text="@string/manage_notifications_history_text"
         />
@@ -40,8 +42,9 @@
             style="@style/TextAppearance.NotificationSectionHeaderButton"
             android:id="@+id/dismiss_text"
             android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
+            android:layout_height="40dp"
             android:layout_gravity="end"
+            android:background="@drawable/notif_footer_btn_background"
             android:focusable="true"
             android:contentDescription="@string/accessibility_clear_all"
             android:text="@string/clear_all_notifications_text"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 06e6f29..62c37a2 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Tot sonsopkoms"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Aan om <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Tot <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Verminder helderheid"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is gedeaktiveer"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is geaktiveer"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index d364370..8f67f1b 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ጸሐይ እስክትወጣ ድረስ"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> ላይ ይበራል"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"እስከ <xliff:g id="TIME">%s</xliff:g> ድረስ"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"ብሩህነትን ይቀንሱ"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"ኤንኤፍሲ"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"ኤንኤፍሲ ተሰናክሏል"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"ኤንኤፍሲ ነቅቷል"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"ማሳያ ሁነታን አሳይ"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"ኤተርኔት"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"ማንቂያ"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"ዝግጁ"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"የስራ መገለጫ"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"የአውሮፕላን ሁነታ"</string>
     <string name="add_tile" msgid="6239678623873086686">"ሰቅ ያክሉ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 4e8ba9a..f778c70 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -420,7 +420,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"حتى شروق الشمس"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"تفعيل الوضع في <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"حتى <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"تقليل السطوع"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"تم إيقاف الاتصال القريب المدى"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"تم تفعيل الاتصال القريب المدى"</string>
@@ -664,10 +663,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"عرض الوضع التجريبي"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"إيثرنت"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"المنبّه"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"المحفظة"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"جاهزة"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"الملف الشخصي للعمل"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"وضع الطيران"</string>
     <string name="add_tile" msgid="6239678623873086686">"إضافة فئة"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index e7d838c..2d7b4ac 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"সূৰ্যোদয়লৈকে"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>ত অন কৰক"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> পৰ্যন্ত"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"উজ্জ্বলতা কমাওক"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC নিষ্ক্ৰিয় হৈ আছে"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC সক্ষম হৈ আছে"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"ডেম\' ম\'ড দেখুৱাওক"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"ইথাৰনেট"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"এলাৰ্ম"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"ৱালেট"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"সাজু"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"কৰ্মস্থানৰ প্ৰ\'ফাইল"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"এয়াৰপ্লেইন ম\'ড"</string>
     <string name="add_tile" msgid="6239678623873086686">"টাইল যোগ দিয়ক"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 99b7a60..939d805 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Şəfəq vaxtına qədər"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Bu vaxt aktiv olur: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Bu vaxtadək: <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Parlaqlığı azaldın"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC deaktiv edilib"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC aktiv edilib"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Demo rejimini göstərin"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Zəngli saat"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Pulqabı"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Hazır"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"İş profili"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Təyyarə rejimi"</string>
     <string name="add_tile" msgid="6239678623873086686">"Xana əlavə edin"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index a7c14c9..213fb98 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -414,7 +414,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do izlaska sunca"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Uključuje se u <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Smanjite osvetljenost"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC je onemogućen"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC je omogućen"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 4d49935..8e7b9ae 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -416,7 +416,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Да ўсходу сонца"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Уключана ў <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Да <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Паменшыць яркасць"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC адключаны"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC уключаны"</string>
@@ -658,10 +657,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Паказваць дэманстрацыйны рэжым"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Будзільнік"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Кашалёк"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Гатова"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Працоўны профіль"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Рэжым палёту"</string>
     <string name="add_tile" msgid="6239678623873086686">"Дадаць плітку"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 25c757a..1ca2595 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"До изгрев"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Ще се включи в <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"До <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Намаляване на яркостта"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"КБП е деактивирана"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"КБП е активирана"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Показване на демонстрационния режим"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Будилник"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Портфейл"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Готово"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Потребителски профил в Work"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Самолетен режим"</string>
     <string name="add_tile" msgid="6239678623873086686">"Добавяне на плочка"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index c67d641..2bf9f29 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"সূর্যোদয় পর্যন্ত"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>-এ চালু হবে"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> পর্যন্ত"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"উজ্জ্বলতা কমান"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC অক্ষম করা আছে"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC সক্ষম করা আছে"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"ডেমো মোড দেখান"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"ইথারনেট"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"অ্যালার্ম"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"তৈরি"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"কাজের প্রোফাইল"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"বিমান মোড"</string>
     <string name="add_tile" msgid="6239678623873086686">"টাইল যোগ করুন"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 6936f57..67e58dd 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -414,7 +414,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do svitanja"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Uključuje se u <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Smanjenje osvjetljenja"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC je onemogućen"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC je omogućen"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 8e090ec..6bdf4de 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Fins a l\'alba"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Activat a les <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Fins a les <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Reducció de la brillantor"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"L\'NFC està desactivada"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"L\'NFC està activada"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Mostra el mode de demostració"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Alarma"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"A punt"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Perfil de treball"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Mode d\'avió"</string>
     <string name="add_tile" msgid="6239678623873086686">"Afegeix un mosaic"</string>
@@ -1094,8 +1091,8 @@
     <string name="timestamp" msgid="6577851592534538533">"Fa <xliff:g id="DURATION">%1$s</xliff:g>"</string>
     <string name="less_than_timestamp" msgid="6598972791137724517">"Fa menys de: <xliff:g id="DURATION">%1$s</xliff:g>"</string>
     <string name="over_timestamp" msgid="4765793502859358634">"Fa més de: <xliff:g id="DURATION">%1$s</xliff:g>"</string>
-    <string name="birthday_status" msgid="2596961629465396761">"Natalici"</string>
-    <string name="upcoming_birthday_status" msgid="2005452239256870351">"Natalici aviat"</string>
+    <string name="birthday_status" msgid="2596961629465396761">"Aniversari"</string>
+    <string name="upcoming_birthday_status" msgid="2005452239256870351">"Aniversari aviat"</string>
     <string name="anniversary_status" msgid="1790034157507590838">"Aniversari"</string>
     <string name="location_status" msgid="1294990572202541812">"Compartint la ubicació"</string>
     <string name="new_story_status" msgid="9012195158584846525">"Història nova"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 603ccfa..67901a7 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -416,7 +416,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do svítání"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Zapnout v <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Snížit jas"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC je vypnuto"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC je zapnuto"</string>
@@ -658,10 +657,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Zobrazit ukázkový režim"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Budík"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Peněženka"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Připraveno"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Pracovní profil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Režim Letadlo"</string>
     <string name="add_tile" msgid="6239678623873086686">"Přidat dlaždici"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 724c26f..489fb53 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Indtil solopgang"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Tænd kl. <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Indtil kl. <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Reducer lysstyrken"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC er deaktiveret"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC er aktiveret"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Vis Demotilstand"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Klar"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Arbejdsprofil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Flytilstand"</string>
     <string name="add_tile" msgid="6239678623873086686">"Tilføj et felt"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 9907dfc..61e0758 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Bis Sonnenaufgang"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"An um <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Bis <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Helligkeit verringern"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ist deaktiviert"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ist aktiviert"</string>
@@ -541,8 +540,7 @@
     <string name="monitoring_button_view_policies" msgid="3869724835853502410">"Richtlinien ansehen"</string>
     <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Jugendschutzeinstellungen"</string>
     <string name="monitoring_description_named_management" msgid="505833016545056036">"Dieses Gerät gehört <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nDein IT-Administrator kann Einstellungen, Zugriffsrechte im Unternehmen, Apps, mit diesem Gerät verknüpfte Daten und die Standortdaten deines Geräts sehen und verwalten.\n\nWeitere Informationen erhältst du von deinem IT-Administrator."</string>
-    <!-- no translation found for monitoring_financed_description_named_management (6108439201399938668) -->
-    <skip />
+    <string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"<xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g> kann möglicherweise auf die Daten zugreifen, die mit diesem Gerät verknüpft sind, Apps verwalten und die Geräteeinstellungen ändern.\n\nFalls du Fragen hast, wende dich an <xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g>."</string>
     <string name="monitoring_description_management" msgid="4308879039175729014">"Dieses Gerät gehört deiner Organisation.\n\nDein IT-Administrator kann Einstellungen, Zugriffsrechte im Unternehmen, Apps, mit diesem Gerät verknüpfte Daten und die Standortdaten deines Geräts sehen und verwalten.\n\nWeitere Informationen erhältst du von deinem IT-Administrator."</string>
     <string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Deine Organisation hat ein Zertifikat einer Zertifizierungsstelle auf deinem Gerät installiert. Eventuell wird dein sicherer Netzwerkverkehr überwacht oder bearbeitet."</string>
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Deine Organisation hat ein Zertifikat einer Zertifizierungsstelle in deinem Arbeitsprofil installiert. Eventuell wird dein sicherer Netzwerkverkehr überwacht oder bearbeitet."</string>
@@ -653,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Demomodus anzeigen"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Weckruf"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Bereit"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Arbeitsprofil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Flugmodus"</string>
     <string name="add_tile" msgid="6239678623873086686">"Kachel hinzufügen"</string>
@@ -1021,7 +1017,7 @@
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Teil des Bildschirms vergrößern"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Schalter"</string>
     <string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Die Schaltfläche „Bedienungshilfen“ ersetzt die Touch-Geste für Bedienungshilfen\n\n"<annotation id="link">"Einstellungen aufrufen"</annotation></string>
-    <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Schaltfläche an den Rand bewegen, um sie zeitweise auszublenden"</string>
+    <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Durch Ziehen an den Rand wird die Schaltfläche zeitweise ausgeblendet"</string>
     <string name="quick_controls_title" msgid="6839108006171302273">"Gerätesteuerung"</string>
     <string name="quick_controls_subtitle" msgid="1667408093326318053">"Steuerelemente für verbundene Geräte hinzufügen"</string>
     <string name="quick_controls_setup_title" msgid="8901436655997849822">"Gerätesteuerung einrichten"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index cfae453..45d3f16 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Μέχρι την ανατολή"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Ενεργοποίηση στις <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Έως <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Μείωση φωτεινότητας"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Το NFC είναι απενεργοποιημένο"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Το NFC είναι ενεργοποιημένο"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Εμφάνιση λειτουργίας επίδειξης"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Ξυπνητήρι"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Πορτοφόλι"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Έτοιμο"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Προφίλ εργασίας"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Λειτουργία πτήσης"</string>
     <string name="add_tile" msgid="6239678623873086686">"Προσθήκη πλακιδίου"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index d6d97c1..126b172 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Until sunrise"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Reduce brightness"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is disabled"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is enabled"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index d6ae5c4..455f498 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Until sunrise"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Reduce brightness"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is disabled"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is enabled"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index d6d97c1..126b172 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Until sunrise"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Reduce brightness"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is disabled"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is enabled"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index d6d97c1..126b172 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Until sunrise"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Reduce brightness"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is disabled"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is enabled"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 2a2e518..8212a33 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -89,8 +89,10 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‎‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‎‎‎‏‎‎‏‏‎‏‎‎‎‎‏‎‏‏‎‎‏‎‏‏‏‎‎‎‎‎‎‎‏‏‎‏‏‎Taking screenshots isn\'t allowed by the app or your organization‎‏‎‎‏‎"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‏‎‎‎‎‎‎‏‎‏‎‎‎‎‎‎‏‎‏‏‏‏‏‎‎‎‎‏‏‎‏‏‏‎‏‎‎Edit‎‏‎‎‏‎"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‎‏‎‎‎‎‎‏‏‎‎‎‎‏‎‏‏‎‏‏‏‏‏‏‎‎‎‎‎‏‎‏‎‏‏‎‎‏‏‏‎‏‏‎‏‎‏‎‎‎‏‎‏‎‏‎‎Edit screenshot‎‏‎‎‏‎"</string>
-    <string name="screenshot_scroll_label" msgid="7682877978685434621">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‏‏‏‏‎‎‎‏‎‎‎‎‏‏‎‏‎‎‎‎‏‏‏‎‎‏‎‎‎‎‏‏‎‏‏‏‎‏‏‎‏‎‏‎‏‏‏‏‏‏‎‏‎Scroll‎‏‎‎‏‎"</string>
-    <string name="screenshot_scroll_description" msgid="7855773867093272175">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‏‎‏‎‏‎‏‎‎‎‎‏‎‏‏‎‏‎‏‏‏‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‎‎‏‏‎‎‏‏‎‏‏‏‏‎Scroll screenshot‎‏‎‎‏‎"</string>
+    <!-- no translation found for screenshot_scroll_label (7682877978685434621) -->
+    <skip />
+    <!-- no translation found for screenshot_scroll_description (7855773867093272175) -->
+    <skip />
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‏‎‎‎‎‏‎‎‎‎‏‎‎‏‎‎‏‏‏‎‎‏‎‏‏‏‏‎‏‏‎‏‎‎‎‎‎‏‎‎‎‎‎‏‏‎‎‎‎‏‏‎‎‏‎‎Dismiss screenshot‎‏‎‎‏‎"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‏‏‏‏‏‏‎‎‎‎‎‎‏‎‏‎‏‏‎‎‎‎‎‎‎‏‎‏‏‎‏‎‏‎‏‏‎‏‎‏‏‎‎‎‏‏‎‏‏‎‏‎‎Screenshot preview‎‏‎‎‏‎"</string>
     <string name="screenshot_top_boundary" msgid="1500569103321300856">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‏‏‎‏‎‎‏‏‎‎‎‏‎‏‏‏‏‎‏‎‎‏‏‎‎‎‏‎‏‏‎‎‎‏‏‎‎‏‎‎‎‏‏‏‏‏‏‏‎‏‏‏‏‎‎‎‎Top boundary‎‏‎‎‏‎"</string>
@@ -412,7 +414,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‎‏‎‎‎‎‏‎‏‎‎‏‎‏‏‏‎‏‎‎‎‏‎‎‎‏‎‎‏‎‎‏‎‏‎‎‏‏‎‎‏‎‎‎‎‎‏‏‎‏‏‏‎‎‎‎Until sunrise‎‏‎‎‏‎"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‎‏‎‏‏‎‏‎‎‎‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‏‏‎‎‎‎‎‏‏‏‎‏‎‏‏‏‏‏‏‎On at ‎‏‎‎‏‏‎<xliff:g id="TIME">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‏‎‏‎‎‏‏‏‏‎‎‏‏‏‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‎‎‏‏‎‏‏‎‏‏‎‎‏‎‏‎‏‎Until ‎‏‎‎‏‏‎<xliff:g id="TIME">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‎‏‏‎‏‎‎‎‎‎‏‏‎‏‏‏‎‎‏‎‎‎‎‏‎‏‏‏‎‎‏‏‎‎‎‏‏‎‎‏‏‎‏‏‏‏‎‏‏‎‎‏‏‏‎Reduce brightness‎‏‎‎‏‎"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‎‎‎‏‏‎‏‏‎‎‎‎‎‎‎‏‏‎‏‎‏‎‏‎‎‎‏‎‎‏‎‏‏‏‏‎‏‏‎‏‎‎‎‏‏‏‎‏‎‏‎‏‎NFC‎‏‎‎‏‎"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‎‏‎‏‏‎‎‎‏‎‎‏‏‏‎‎‏‏‎‎‎‏‏‏‏‎‎‎‏‎‏‎‎‎‎‏‎‏‎‎‎‎‎‏‎‏‏‎‎‏‎‏‏‏‎NFC is disabled‎‏‎‎‏‎"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‏‏‏‏‎‎‏‎‎‏‏‎‎‏‎‎‏‏‏‎‎‏‏‏‎‎‏‏‏‏‏‎‎‏‎‏‎‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‎‏‏‎‎NFC is enabled‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 70adb0b..10079a6 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Hasta el amanecer"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"A la(s) <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Hasta la(s) <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Reducir el brillo"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"La tecnología NFC está inhabilitada"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"La tecnología NFC está habilitada"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Ver en modo de demostración"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Alarma"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Listo"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabajo"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Modo de avión"</string>
     <string name="add_tile" msgid="6239678623873086686">"Agregar mosaico"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index ae28e6b..48353ae 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Hasta el amanecer"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"A las <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Hasta las <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Reducir brillo"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"El NFC está desactivado"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"El NFC está activado"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Mostrar modo de demostración"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Alarma"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Listo"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabajo"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Modo avión"</string>
     <string name="add_tile" msgid="6239678623873086686">"Añadir icono"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 09a59e7..e988c71 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Kuni päikesetõusuni"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Sisse kell <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Kuni <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Ereduse vähendamine"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC on keelatud"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC on lubatud"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Kuva demorežiim"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Äratus"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Rahakott"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Valmis"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Tööprofiil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Lennukirežiim"</string>
     <string name="add_tile" msgid="6239678623873086686">"Paani lisamine"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 546679f..00443dc 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Egunsentira arte"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Aktibatze-ordua: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Desaktibatze-ordua: <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Murriztu distira"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Desgaituta dago NFC"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Gaituta dago NFC"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Erakutsi demo modua"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Alarma"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Prest"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Work profila"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Hegaldi modua"</string>
     <string name="add_tile" msgid="6239678623873086686">"Gehitu lauza"</string>
@@ -1019,7 +1016,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Handitu pantaila osoa"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Handitu pantailaren zati bat"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Botoia"</string>
-    <string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Erabilerraztasuna botoiak erabilerraztasun-keinuak ordezkatu ditu\n\n"<annotation id="link">"Ikusi ezarpenak"</annotation></string>
+    <string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Erabilerraztasuna botoiak erabilerraztasun-keinua ordezkatu du\n\n"<annotation id="link">"Ikusi ezarpenak"</annotation></string>
     <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Eraman botoia ertzera aldi baterako ezkutatzeko"</string>
     <string name="quick_controls_title" msgid="6839108006171302273">"Gailuak kontrolatzeko widgetak"</string>
     <string name="quick_controls_subtitle" msgid="1667408093326318053">"Gehitu konektatutako gailuak kontrolatzeko widgetak"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 821c8e7..4f733c2 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"تا طلوع آفتاب"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"ساعت <xliff:g id="TIME">%s</xliff:g> روشن می‌شود"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"تا<xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"کاهش روشنایی"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"‏ارتباط میدان نزدیک (NFC)"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"‏«ارتباط میدان نزدیک» (NFC) غیرفعال است"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"‏«ارتباط میدان نزدیک» (NFC) فعال است"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"نمایش حالت نمایشی"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"اترنت"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"زنگ"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"کیف‌پول"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"آماده"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"نمایه کاری"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"حالت هواپیما"</string>
     <string name="add_tile" msgid="6239678623873086686">"افزودن کاشی"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 28e619c..47b716e 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Auringonnousuun"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Päälle klo <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> asti"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Vähennä kirkkautta"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC on poistettu käytöstä"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC on käytössä"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Näytä esittelytila"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Herätys"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Valmis"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Työprofiili"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Lentokonetila"</string>
     <string name="add_tile" msgid="6239678623873086686">"Lisää ruutu"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 5a2a125..812bee7 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Jusqu\'à l\'aube"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Actif à <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Jusqu\'à <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Réduire la luminosité"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC désactivée"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC activée"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Afficher le mode Démonstration"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Alarme"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Prêt"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Profil professionnel"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Mode Avion"</string>
     <string name="add_tile" msgid="6239678623873086686">"Ajouter la tuile"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 9e4f1ac..8c3854e 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Jusqu\'à l\'aube"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"À partir de <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Jusqu\'à <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Réduire la luminosité"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC désactivée"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"La technologie NFC est activée"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Afficher le mode de démonstration"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Alarme"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Prêt"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Profil professionnel"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Mode Avion"</string>
     <string name="add_tile" msgid="6239678623873086686">"Ajouter un bloc"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 9091f04..334da91 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Ata o amencer"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Activarase ás: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Utilizarase ata as: <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Reducir brillo"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"A opción NFC está desactivada"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"A opción NFC está activada"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Mostrar modo de demostración"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Alarma"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Listo"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Perfil de traballo"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Modo avión"</string>
     <string name="add_tile" msgid="6239678623873086686">"Engade un atallo"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index ec286e1..c8cdff6 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"સૂર્યોદય સુધી"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> વાગ્યે ચાલુ"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> વાગ્યા સુધી"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"બ્રાઇટનેસ ઘટાડો"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC અક્ષમ કરેલ છે"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC સક્ષમ કરેલ છે"</string>
@@ -541,8 +540,7 @@
     <string name="monitoring_button_view_policies" msgid="3869724835853502410">"પૉલિસીઓ જુઓ"</string>
     <string name="monitoring_button_view_controls" msgid="8316440345340701117">"નિયંત્રણો જુઓ"</string>
     <string name="monitoring_description_named_management" msgid="505833016545056036">"આ ડિવાઇસ <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>ની માલિકીનું છે.\n\nતમારા IT વ્યવસ્થાપક સેટિંગ, કૉર્પોરેટ ઍક્સેસ, ઍપ, તમારા ડિવાઇસ સાથે સંકળાયેલો ડેટા અને તમારા ડિવાઇસની સ્થાન માહિતીનું નિરીક્ષણ તેમજ તેને મેનેજ કરી શકે છે.\n\nવધુ માહિતી માટે, તમારા IT વ્યવસ્થાપકનો સંપર્ક કરો."</string>
-    <!-- no translation found for monitoring_financed_description_named_management (6108439201399938668) -->
-    <skip />
+    <string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"<xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g> આ ડિવાઇસ સાથે સંકળાયેલો ડેટા ઍક્સેસ કરી શકશે અને ઍપ મેનેજ કરી શકશે તેમજ આ ડિવાઇસના સેટિંગ બદલી શકશે.\n\nજો તમને કોઈ પ્રશ્ન હોય, તો <xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g>નો સંપર્ક કરો."</string>
     <string name="monitoring_description_management" msgid="4308879039175729014">"આ ડિવાઇસ તમારી સંસ્થાની માલિકીનું છે.\n\nતમારા IT વ્યવસ્થાપક સેટિંગ, કૉર્પોરેટ ઍક્સેસ, ઍપ, તમારા ડિવાઇસ સાથે સંકળાયેલો ડેટા અને તમારા ડિવાઇસની સ્થાન માહિતીનું નિરીક્ષણ તેમજ તેને મેનેજ કરી શકે છે.\n\nવધુ માહિતી માટે, તમારા IT વ્યવસ્થાપકનો સંપર્ક કરો."</string>
     <string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"તમારી સંસ્થાએ આ ઉપકરણ પર પ્રમાણપત્ર સત્તાધિકારી ઇન્સ્ટૉલ કર્યું છે. તમારા સુરક્ષિત નેટવર્ક ટ્રાફિકનું નિયમન થઈ શકે છે અથવા તેમાં ફેરફાર કરવામાં આવી શકે છે."</string>
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"તમારી સંસ્થાએ તમારી કાર્ય પ્રોફાઇલમાં પ્રમાણપત્ર સત્તાધિકારી ઇન્સ્ટૉલ કર્યું છે. તમારા સુરક્ષિત નેટવર્ક ટ્રાફિકનું નિયમન થઈ શકે છે અથવા તેમાં ફેરફાર કરવામાં આવી શકે છે."</string>
@@ -653,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"ડેમો મોડ બતાવો"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"ઇથરનેટ"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"એલાર્મ"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"વૉલેટ"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"તૈયાર છે"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"ઑફિસની પ્રોફાઇલ"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"એરપ્લેન મોડ"</string>
     <string name="add_tile" msgid="6239678623873086686">"ટાઇલ ઉમેરો"</string>
@@ -1021,7 +1017,7 @@
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"સ્ક્રીનનો કોઈ ભાગ મોટો કરો"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"સ્વિચ"</string>
     <string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"ઍક્સેસિબિલિટી સંકેતને ઍક્સેસિબિલિટી બટન વડે બદલવામાં આવ્યા છે\n\n"<annotation id="link">"સેટિંગ જુઓ"</annotation></string>
-    <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"તેને હંગામી રૂપે ખસેડવા માટે બટનને કિનારી ખસેડો"</string>
+    <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"તેને હંગામી રૂપે ખસેડવા માટે બટનને કિનારી પર ખસેડો"</string>
     <string name="quick_controls_title" msgid="6839108006171302273">"ડિવાઇસનાં નિયંત્રણો"</string>
     <string name="quick_controls_subtitle" msgid="1667408093326318053">"તમારા કનેક્ટ કરેલા ડિવાઇસ માટે નિયંત્રણો ઉમેરો"</string>
     <string name="quick_controls_setup_title" msgid="8901436655997849822">"ડિવાઇસનાં નિયંત્રણો સેટઅપ કરો"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 6b0c426..3126959 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -223,9 +223,7 @@
     <string name="accessibility_battery_details" msgid="6184390274150865789">"बैटरी का विवरण खोलें"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> प्रति‍शत बैटरी."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> प्रतिशत बैटरी बची है और आपके इस्तेमाल के हिसाब से यह <xliff:g id="TIME">%2$s</xliff:g> में खत्म हो जाएगी"</string>
-    <!-- String.format failed for translation -->
-    <!-- no translation found for accessibility_battery_level_charging (8892191177774027364) -->
-    <skip />
+    <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"बैटरी चार्ज हो रही है, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> प्रतिशत."</string>
     <string name="accessibility_settings_button" msgid="2197034218538913880">"सिस्टम सेटिंग."</string>
     <string name="accessibility_notifications_button" msgid="3960913924189228831">"सूचनाएं."</string>
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"पूरी सूचनाएं देखें"</string>
@@ -414,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"सुबह तक चालू रहेगी"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> पर चालू हाेगी"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> तक चालू रहेगी"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"स्क्रीन की चमक कम करें"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"एनएफ़सी"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC बंद है"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC चालू है"</string>
@@ -654,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"डेमो मोड दिखाएं"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"ईथरनेट"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"अलार्म"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"वॉलेट"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"तैयार"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"वर्क प्रोफ़ाइल"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"हवाई जहाज़ मोड"</string>
     <string name="add_tile" msgid="6239678623873086686">"टाइल जोड़ें"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 2ce7fb2..0d4c079 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -414,7 +414,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do izlaska sunca"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Uključuje se u <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Smanjenje svjetline"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC je onemogućen"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC je omogućen"</string>
@@ -956,10 +955,10 @@
     <string name="mobile_carrier_text_format" msgid="8912204177152950766">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="MOBILE_DATA_TYPE">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="5389597396308001471">"Wi-Fi je isključen"</string>
     <string name="bt_is_off" msgid="7436344904889461591">"Bluetooth je isključen"</string>
-    <string name="dnd_is_off" msgid="3185706903793094463">"Način Ne ometaj isključen"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="3535469468310002616">"Način Ne ometaj uključilo je automatsko pravilo (<xliff:g id="ID_1">%s</xliff:g>)."</string>
-    <string name="qs_dnd_prompt_app" msgid="4027984447935396820">"Način Ne ometaj uključila je aplikacija (<xliff:g id="ID_1">%s</xliff:g>)."</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="1841469944118486580">"Način Ne ometaj uključilo je automatsko pravilo ili aplikacija."</string>
+    <string name="dnd_is_off" msgid="3185706903793094463">"Način Ne uznemiravaj isključen"</string>
+    <string name="qs_dnd_prompt_auto_rule" msgid="3535469468310002616">"Način Ne uznemiravaj uključilo je automatsko pravilo (<xliff:g id="ID_1">%s</xliff:g>)."</string>
+    <string name="qs_dnd_prompt_app" msgid="4027984447935396820">"Način Ne uznemiravaj uključila je aplikacija (<xliff:g id="ID_1">%s</xliff:g>)."</string>
+    <string name="qs_dnd_prompt_auto_rule_app" msgid="1841469944118486580">"Način Ne uznemiravaj uključilo je automatsko pravilo ili aplikacija."</string>
     <string name="qs_dnd_until" msgid="7844269319043747955">"Do <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="3829697305432866434">"Zadrži"</string>
     <string name="qs_dnd_replace" msgid="7712119051407052689">"Zamijeni"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 66c5a82..51651ac 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Napfelkeltéig"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Be: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Eddig: <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Fényerő csökkentése"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Az NFC ki van kapcsolva"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Az NFC be van kapcsolva"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Demó mód megjelenítése"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Ébresztés"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Kész"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Munkahelyi profil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Repülős üzemmód"</string>
     <string name="add_tile" msgid="6239678623873086686">"Mozaik hozzáadása"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 8a79cc0..1d64b95 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Մինչև լուսաբաց"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Կմիանա՝ <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Մինչև <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Պայծառության նվազեցում"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC-ն անջատված է"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC-ն միացված է"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Ցուցադրական ռեժիմի ցուցադրում"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Զարթուցիչ"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Դրամապանակ"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Պատրաստ է"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Android for Work-ի պրոֆիլ"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Ավիառեժիմ"</string>
     <string name="add_tile" msgid="6239678623873086686">"Սալիկի ավելացում"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 7ec11c3..21851ce 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Sampai pagi"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Aktif pada <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Sampai <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Kurangi kecerahan"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC dinonaktifkan"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC diaktifkan"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Tampilkan mode demo"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Siap"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Profil kerja"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Mode pesawat"</string>
     <string name="add_tile" msgid="6239678623873086686">"Tambahkan ubin"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 304ee76..21ef9cd 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Til sólarupprásar"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Virkt kl. <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Til <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Minnka birtu"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Slökkt á NFC"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Kveikt á NFC"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Sýna prufustillingu"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Vekjari"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Veski"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Tilbúið"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Vinnusnið"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Flugstilling"</string>
     <string name="add_tile" msgid="6239678623873086686">"Bæta reit við"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 0a03577..5b1855b 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Fino all\'alba"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Attivazione alle <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Fino alle <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Riduci la luminosità"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC non attiva"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC attiva"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index dc32c15..8e4390e 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -28,7 +28,7 @@
     <string name="battery_low_percent_format" msgid="4276661262843170964">"נותרו <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_hybrid" msgid="3985614339605686167">"נותרו <xliff:g id="PERCENTAGE">%1$s</xliff:g>, נשארו בערך <xliff:g id="TIME">%2$s</xliff:g> על סמך השימוש במכשיר"</string>
     <string name="battery_low_percent_format_hybrid_short" msgid="5917433188456218857">"נותרו <xliff:g id="PERCENTAGE">%1$s</xliff:g>, נשארו בערך <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="battery_low_percent_format_saver_started" msgid="4968468824040940688">"נותרו <xliff:g id="PERCENTAGE">%s</xliff:g>. הופעלה תכונת החיסכון בסוללה."</string>
+    <string name="battery_low_percent_format_saver_started" msgid="4968468824040940688">"נותרו <xliff:g id="PERCENTAGE">%s</xliff:g>. התכונה \'חיסכון בסוללה\' הופעלה."</string>
     <string name="invalid_charger" msgid="4370074072117767416">"‏לא ניתן לטעון באמצעות USB. ניתן להשתמש במטען שצורף למכשיר שלך."</string>
     <string name="invalid_charger_title" msgid="938685362320735167">"‏לא ניתן לטעון באמצעות USB"</string>
     <string name="invalid_charger_text" msgid="2339310107232691577">"שימוש במטען שסופק עם המכשיר"</string>
@@ -40,7 +40,7 @@
     <string name="status_bar_settings_settings_button" msgid="534331565185171556">"הגדרות"</string>
     <string name="status_bar_settings_wifi_button" msgid="7243072479837270946">"Wi-Fi"</string>
     <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"סיבוב אוטומטי של המסך"</string>
-    <string name="status_bar_settings_mute_label" msgid="914392730086057522">"השתק"</string>
+    <string name="status_bar_settings_mute_label" msgid="914392730086057522">"השתקה"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="2151934479226017725">"אוטומטי"</string>
     <string name="status_bar_settings_notifications" msgid="5285316949980621438">"התראות"</string>
     <string name="bluetooth_tethered" msgid="4171071193052799041">"‏Bluetooth קשור"</string>
@@ -123,8 +123,8 @@
     <string name="screenrecord_start_error" msgid="2200660692479682368">"שגיאה בהפעלה של הקלטת המסך"</string>
     <string name="usb_preference_title" msgid="1439924437558480718">"‏אפשרויות העברת קבצים ב-USB"</string>
     <string name="use_mtp_button_title" msgid="5036082897886518086">"‏טען כנגן מדיה (MTP)"</string>
-    <string name="use_ptp_button_title" msgid="7676427598943446826">"‏טען כמצלמה (PTP)"</string>
-    <string name="installer_cd_button_title" msgid="5499998592841984743">"‏התקן את אפליקציית העברת הקבצים של Android עבור Mac"</string>
+    <string name="use_ptp_button_title" msgid="7676427598943446826">"‏טעינה כמצלמה (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="5499998592841984743">"‏התקנת האפליקציה \'העברת קבצים ב-Android\' עבור Mac"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"הקודם"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"בית"</string>
     <string name="accessibility_menu" msgid="2701163794470513040">"תפריט"</string>
@@ -142,7 +142,7 @@
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"שליחה"</string>
     <string name="accessibility_manage_notification" msgid="582215815790143983">"ניהול התראות"</string>
     <string name="phone_label" msgid="5715229948920451352">"פתח את הטלפון"</string>
-    <string name="voice_assist_label" msgid="3725967093735929020">"פתח את המסייע הקולי"</string>
+    <string name="voice_assist_label" msgid="3725967093735929020">"פתיחת האסיסטנט"</string>
     <string name="camera_label" msgid="8253821920931143699">"פתח את המצלמה"</string>
     <string name="cancel" msgid="1089011503403416730">"ביטול"</string>
     <string name="biometric_dialog_confirm" msgid="2005978443007344895">"אישור"</string>
@@ -164,13 +164,13 @@
     <string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"יש לנסות שוב. ניסיון <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> מתוך <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
     <string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"הנתונים שלך יימחקו"</string>
     <string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"הזנת קו ביטול נעילה שגוי בניסיון הבא תגרום למחיקת הנתונים במכשיר."</string>
-    <string name="biometric_dialog_last_pin_attempt_before_wipe_device" msgid="9151756675698215723">"הזנת קוד גישה שגוי בניסיון הבא תגרום למחיקת הנתונים במכשיר."</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_device" msgid="9151756675698215723">"הזנת קוד אימות שגוי בניסיון הבא תגרום למחיקת הנתונים במכשיר."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_device" msgid="2363778585575998317">"הזנת סיסמה שגויה בניסיון הבא תגרום למחיקת הנתונים במכשיר."</string>
     <string name="biometric_dialog_last_pattern_attempt_before_wipe_user" msgid="8400180746043407270">"הזנת קו ביטול נעילה שגוי בניסיון הבא תגרום למחיקת המשתמש הזה."</string>
     <string name="biometric_dialog_last_pin_attempt_before_wipe_user" msgid="4159878829962411168">"הזנת קוד גישה שגוי בניסיון הבא תגרום למחיקת המשתמש הזה."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_user" msgid="4695682515465063885">"הזנת סיסמה שגויה בניסיון הבא תגרום למחיקת המשתמש הזה."</string>
     <string name="biometric_dialog_last_pattern_attempt_before_wipe_profile" msgid="6045224069529284686">"הזנת קו ביטול נעילה שגוי בניסיון הבא תגרום למחיקת פרופיל העבודה והנתונים המשויכים אליו."</string>
-    <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"הזנת קוד גישה שגוי בניסיון הבא תגרום למחיקת פרופיל העבודה והנתונים המשויכים אליו."</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"הזנה של קוד אימות שגוי בניסיון הבא תגרום למחיקת פרופיל העבודה והנתונים המשויכים אליו."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"הזנת סיסמה שגויה בניסיון הבא תגרום למחיקת פרופיל העבודה והנתונים המשויכים אליו."</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_device" msgid="6585503524026243042">"נעשו יותר מדי ניסיונות שגויים. הנתונים במכשיר יימחקו."</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_user" msgid="7015008539146949115">"נעשו יותר מדי ניסיונות שגויים. המשתמש הזה יימחק."</string>
@@ -208,7 +208,7 @@
     <string name="accessibility_desc_on" msgid="2899626845061427845">"פועל."</string>
     <string name="accessibility_desc_off" msgid="8055389500285421408">"כבוי."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"מחובר."</string>
-    <string name="accessibility_desc_connecting" msgid="8011433412112903614">"מתחבר."</string>
+    <string name="accessibility_desc_connecting" msgid="8011433412112903614">"מתבצע חיבור."</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"נדידה"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
@@ -267,11 +267,11 @@
     <string name="accessibility_quick_settings_bluetooth_changed_off" msgid="3344226652293797283">"‏Bluetooth נכבה."</string>
     <string name="accessibility_quick_settings_bluetooth_changed_on" msgid="1263282011749437549">"‏Bluetooth הופעל."</string>
     <string name="accessibility_quick_settings_location_off" msgid="6122523378294740598">"דיווח מיקום כבוי."</string>
-    <string name="accessibility_quick_settings_location_on" msgid="6869947200325467243">"דיווח מיקום מופעל."</string>
+    <string name="accessibility_quick_settings_location_on" msgid="6869947200325467243">"התכונה \'דיווח מיקום\' מופעלת."</string>
     <string name="accessibility_quick_settings_location_changed_off" msgid="5132776369388699133">"דיווח מיקום נכבה."</string>
     <string name="accessibility_quick_settings_location_changed_on" msgid="7159115433070112154">"דיווח מיקום הופעל."</string>
     <string name="accessibility_quick_settings_alarm" msgid="558094529584082090">"ההתראה נקבעה ל-<xliff:g id="TIME">%s</xliff:g>."</string>
-    <string name="accessibility_quick_settings_close" msgid="2974895537860082341">"סגור לוח."</string>
+    <string name="accessibility_quick_settings_close" msgid="2974895537860082341">"סגירת הלוח."</string>
     <string name="accessibility_quick_settings_more_time" msgid="7646479831704665284">"יותר זמן."</string>
     <string name="accessibility_quick_settings_less_time" msgid="9110364286464977870">"פחות זמן."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="7606563260714825190">"הפנס כבוי."</string>
@@ -301,7 +301,7 @@
     <string name="data_usage_disabled_dialog" msgid="7933201635215099780">"הגעת למגבלת הנתונים שהגדרת. אתה כבר לא משתמש בחבילת גלישה.\n\nאם תמשיך, ייתכנו חיובים על שימוש בנתונים."</string>
     <string name="data_usage_disabled_dialog_enable" msgid="2796648546086408937">"המשך"</string>
     <string name="gps_notification_searching_text" msgid="231304732649348313">"‏מחפש GPS"</string>
-    <string name="gps_notification_found_text" msgid="3145873880174658526">"‏מיקום מוגדר על ידי GPS"</string>
+    <string name="gps_notification_found_text" msgid="3145873880174658526">"‏המיקום מוגדר על ידי GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"בקשות מיקום פעילות"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"ההגדרה \'חיישנים כבויים\' פעילה"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"הסרת כל ההתראות."</string>
@@ -318,7 +318,7 @@
     <string name="accessibility_rotation_lock_off" msgid="3880436123632448930">"המסך יסתובב באופן אוטומטי."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="936972553861524360">"המסך נעול כעת לרוחב."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="2356633398683813837">"המסך נעול כעת לאורך."</string>
-    <string name="accessibility_rotation_lock_off_changed" msgid="5772498370935088261">"המסך יסתובב כעת באופן אוטומטי."</string>
+    <string name="accessibility_rotation_lock_off_changed" msgid="5772498370935088261">"המסך יסתובב עכשיו באופן אוטומטי."</string>
     <string name="accessibility_rotation_lock_on_landscape_changed" msgid="5785739044300729592">"המסך נעול כעת לרוחב."</string>
     <string name="accessibility_rotation_lock_on_portrait_changed" msgid="5580170829728987989">"המסך נעול כעת לאורך."</string>
     <string name="dessert_case" msgid="9104973640704357717">"מזנון קינוחים"</string>
@@ -343,12 +343,12 @@
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"סיבוב אוטומטי"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"סיבוב אוטומטי של המסך"</string>
     <string name="accessibility_quick_settings_rotation_value" msgid="2916484894750819251">"מצב <xliff:g id="ID_1">%s</xliff:g>"</string>
-    <string name="quick_settings_rotation_locked_label" msgid="4420863550666310319">"סיבוב נעול"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="4420863550666310319">"סיבוב המסך נעול"</string>
     <string name="quick_settings_rotation_locked_portrait_label" msgid="1194988975270484482">"לאורך"</string>
     <string name="quick_settings_rotation_locked_landscape_label" msgid="2000295772687238645">"לרוחב"</string>
     <string name="quick_settings_ime_label" msgid="3351174938144332051">"שיטת קלט"</string>
     <string name="quick_settings_location_label" msgid="2621868789013389163">"מיקום"</string>
-    <string name="quick_settings_location_off_label" msgid="7923929131443915919">"מיקום כבוי"</string>
+    <string name="quick_settings_location_off_label" msgid="7923929131443915919">"המיקום מושבת"</string>
     <string name="quick_settings_camera_label" msgid="1367149596242401934">"חסימת המצלמה"</string>
     <string name="quick_settings_mic_label" msgid="8245831073612564953">"השתקת המיקרופון"</string>
     <string name="quick_settings_media_device_label" msgid="8034019242363789941">"מכשיר מדיה"</string>
@@ -368,7 +368,7 @@
     <string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"‏Wi-Fi כבוי"</string>
     <string name="quick_settings_wifi_on_label" msgid="2489928193654318511">"‏Wi-Fi פועל"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="483130889414601732">"‏אין רשתות Wi-Fi זמינות"</string>
-    <string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"ההפעלה מתבצעת…"</string>
+    <string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"בתהליך הפעלה…"</string>
     <string name="quick_settings_cast_title" msgid="2279220930629235211">"העברת מסך"</string>
     <string name="quick_settings_casting" msgid="1435880708719268055">"מעביר"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"מכשיר ללא שם"</string>
@@ -400,13 +400,13 @@
     <string name="quick_settings_cellular_detail_title" msgid="792977203299358893">"חבילת גלישה"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="6105969068871138427">"שימוש בנתונים"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="1136599216568805644">"מכסת נתונים נותרת"</string>
-    <string name="quick_settings_cellular_detail_over_limit" msgid="4561921367680636235">"חריגה מההגבלה"</string>
+    <string name="quick_settings_cellular_detail_over_limit" msgid="4561921367680636235">"חריגה מהמגבלה"</string>
     <string name="quick_settings_cellular_detail_data_used" msgid="6798849610647988987">"<xliff:g id="DATA_USED">%s</xliff:g> בשימוש"</string>
     <string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"הגבלה של <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"אזהרה - <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="2754212289804324685">"פרופיל עבודה"</string>
     <string name="quick_settings_night_display_label" msgid="8180030659141778180">"תאורת לילה"</string>
-    <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"מופעל בשקיעה"</string>
+    <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"התכונה מופעלת בשקיעה"</string>
     <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"עד הזריחה"</string>
     <string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"מופעל בשעה <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"עד <xliff:g id="TIME">%s</xliff:g>"</string>
@@ -416,7 +416,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"עד הזריחה"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"יתחיל בשעה <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"עד <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"הפחתה של עוצמת הבהירות"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"‏NFC מושבת"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"‏NFC מופעל"</string>
@@ -441,10 +440,10 @@
     <string name="zen_alarms_introduction" msgid="3987266042682300470">"כדי לא להפריע לך, המכשיר לא ירטוט ולא ישמיע שום צליל, חוץ מהתראות. המצב הזה לא ישפיע על צלילים שהם חלק מתוכן שבחרת להפעיל, כמו מוזיקה, סרטונים ומשחקים."</string>
     <string name="zen_priority_customize_button" msgid="4119213187257195047">"התאמה אישית"</string>
     <string name="zen_silence_introduction_voice" msgid="853573681302712348">"פעולה זו מבטלת את כל הצלילים והרטט, כולל צלילים ורטט שמקורם בהתראות, מוזיקה, סרטונים ומשחקים. בכל מקרה, עדיין אפשר להתקשר."</string>
-    <string name="zen_silence_introduction" msgid="6117517737057344014">"פעולה זו מבטלת את כל הצלילים והרטט, כולל בהתראות, מוזיקה, סרטונים ומשחקים."</string>
+    <string name="zen_silence_introduction" msgid="6117517737057344014">"הפעולה הזו מבטלת את כל הצלילים והרטט, כולל בהתראות, מוזיקה, סרטונים ומשחקים."</string>
     <string name="keyguard_more_overflow_text" msgid="5819512373606638727">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="7248696377626341060">"התראות בדחיפות נמוכה יותר בהמשך"</string>
-    <string name="notification_tap_again" msgid="4477318164947497249">"הקש שוב כדי לפתוח"</string>
+    <string name="notification_tap_again" msgid="4477318164947497249">"יש להקיש שוב כדי לפתוח את ההתראה"</string>
     <string name="keyguard_unlock" msgid="8031975796351361601">"צריך להחליק כדי לפתוח"</string>
     <string name="keyguard_retry" msgid="886802522584053523">"יש להחליק למעלה כדי לנסות שוב"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"‏יש לבטל את הנעילה כדי להשתמש ב-NFC"</string>
@@ -484,7 +483,7 @@
     <string name="user_logout_notification_title" msgid="3644848998053832589">"ניתוק משתמש"</string>
     <string name="user_logout_notification_text" msgid="7441286737342997991">"צא מהמשתמש הנוכחי"</string>
     <string name="user_logout_notification_action" msgid="7974458760719361881">"נתק משתמש"</string>
-    <string name="user_add_user_title" msgid="4172327541504825032">"האם להוסיף משתמש חדש?"</string>
+    <string name="user_add_user_title" msgid="4172327541504825032">"להוסיף משתמש חדש?"</string>
     <string name="user_add_user_message_short" msgid="2599370307878014791">"בעת הוספת משתמש חדש, על משתמש זה להגדיר את השטח שלו.\n\nכל משתמש יכול לעדכן אפליקציות עבור כל המשתמשים האחרים."</string>
     <string name="user_limit_reached_title" msgid="2429229448830346057">"הגעת למגבלת המשתמשים שניתן להוסיף"</string>
     <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398">
@@ -498,13 +497,13 @@
     <string name="user_remove_user_remove" msgid="8387386066949061256">"הסרה"</string>
     <string name="battery_saver_notification_title" msgid="8419266546034372562">"תכונת החיסכון בסוללה פועלת"</string>
     <string name="battery_saver_notification_text" msgid="2617841636449016951">"מפחית את הביצועים ונתונים ברקע"</string>
-    <string name="battery_saver_notification_action_text" msgid="6022091913807026887">"כיבוי תכונת החיסכון בסוללה"</string>
+    <string name="battery_saver_notification_action_text" msgid="6022091913807026887">"השבתת התכונה \'חיסכון בסוללה\'"</string>
     <string name="media_projection_dialog_text" msgid="1755705274910034772">"‏לאפליקציית <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> תהיה גישה לכל המידע הגלוי במסך שלך ולכל תוכן שמופעל במכשיר שלך בזמן הקלטה או העברה (casting). המידע הזה כולל פרטים כמו סיסמאות, פרטי תשלום, תמונות, הודעות ואודיו שמושמע מהמכשיר."</string>
     <string name="media_projection_dialog_service_text" msgid="958000992162214611">"‏לשירות שמספק את הפונקציה הזו תהיה גישה לכל הפרטים שגלויים במסך שלך או מופעלים מהמכשיר שלך בזמן הקלטה או העברה (cast). זה כולל פרטים כמו סיסמאות, פרטי תשלום, תמונות, הודעות ואודיו שמושמע מהמכשיר."</string>
     <string name="media_projection_dialog_service_title" msgid="2888507074107884040">"‏להתחיל להקליט או להעביר (cast)?"</string>
     <string name="media_projection_dialog_title" msgid="3316063622495360646">"‏להתחיל להקליט או להעביר (cast) באמצעות <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
     <string name="media_projection_remember_text" msgid="6896767327140422951">"אל תציג שוב"</string>
-    <string name="clear_all_notifications_text" msgid="348312370303046130">"ניקוי הכל"</string>
+    <string name="clear_all_notifications_text" msgid="348312370303046130">"ניקוי הכול"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"ניהול"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"היסטוריה"</string>
     <string name="notification_section_header_incoming" msgid="850925217908095197">"התראות חדשות"</string>
@@ -518,9 +517,9 @@
     <string name="profile_owned_footer" msgid="2756770645766113964">"ייתכן שהפרופיל נתון למעקב"</string>
     <string name="vpn_footer" msgid="3457155078010607471">"ייתכן שהרשת נמצאת במעקב"</string>
     <string name="branded_vpn_footer" msgid="816930186313188514">"ייתכן שהרשת מנוטרת"</string>
-    <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"מכשיר זה מנוהל על ידי ההורה שלך"</string>
+    <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"המכשיר הזה מנוהל על ידי ההורה שלך"</string>
     <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"הארגון שלך הוא הבעלים של מכשיר זה והוא עשוי לנטר את התנועה ברשת"</string>
-    <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"הארגון <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> הוא הבעלים של מכשיר זה והוא עשוי לנטר את התנועה ברשת"</string>
+    <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"הארגון <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> הוא הבעלים של המכשיר הזה והוא עשוי לנטר את התנועה ברשת"</string>
     <string name="quick_settings_financed_disclosure_named_management" msgid="2307703784594859524">"המכשיר הזה התקבל מ-<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
     <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"המכשיר הזה שייך לארגון שלך, והוא מחובר ל-<xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"המכשיר הזה שייך לארגון <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> והוא מחובר ל-<xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
@@ -543,19 +542,18 @@
     <string name="monitoring_subtitle_network_logging" msgid="2444199331891219596">"רישום התנועה ברשת"</string>
     <string name="monitoring_subtitle_ca_certificate" msgid="8588092029755175800">"‏אישורי CA"</string>
     <string name="disable_vpn" msgid="482685974985502922">"‏השבת VPN"</string>
-    <string name="disconnect_vpn" msgid="26286850045344557">"‏נתק את ה-VPN"</string>
+    <string name="disconnect_vpn" msgid="26286850045344557">"‏ניתוק ה-VPN"</string>
     <string name="monitoring_button_view_policies" msgid="3869724835853502410">"הצג מדיניות"</string>
     <string name="monitoring_button_view_controls" msgid="8316440345340701117">"לצפייה באמצעי בקרת ההורים"</string>
     <string name="monitoring_description_named_management" msgid="505833016545056036">"‏המכשיר הזה שייך לארגון <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nמנהל ה-IT יכול לנטר ולנהל הגדרות, גישה ארגונית, אפליקציות, נתונים המשויכים למכשיר ומידע על מיקום המכשיר.\n\nלמידע נוסף, יש לפנות למנהל ה-IT."</string>
-    <!-- no translation found for monitoring_financed_description_named_management (6108439201399938668) -->
-    <skip />
+    <string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"ל-<xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g> תהיה אפשרות לגשת לנתונים המשויכים למכשיר הזה, לנהל אפליקציות ולשנות את הגדרות המכשיר.\n\nאם יש לך שאלות, ניתן ליצור קשר עם <xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g>."</string>
     <string name="monitoring_description_management" msgid="4308879039175729014">"‏המכשיר הזה שייך לארגון שלך.\n\nמנהל ה-IT יכול לנטר ולנהל הגדרות, גישה ארגונית, אפליקציות, נתונים המשויכים למכשיר ומידע על מיקום המכשיר.\n\nלמידע נוסף, יש לפנות למנהל ה-IT."</string>
     <string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"הארגון שלך התקין רשות אישורים במכשיר. ניתן לעקוב אחר התנועה ברשת המאובטחת או לשנות אותה."</string>
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"הארגון שלך התקין רשות אישורים בפרופיל העבודה. ניתן לעקוב אחר התנועה ברשת המאובטחת או לשנות אותה."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"במכשיר זה מותקנת רשות אישורים. ניתן לעקוב אחר התנועה ברשת המאובטחת או לשנות אותה."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"מנהל המערכת הפעיל את התכונה \'רישום התנועה ברשת\', שמנטרת את תנועת הנתונים במכשיר."</string>
     <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"מנהל המערכת הפעיל את תכונת רישום התנועה ברשת, שמנטרת את תנועת הנתונים בפרופיל העבודה, אבל לא בפרופיל האישי."</string>
-    <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"אתה מחובר לאפליקציה <xliff:g id="VPN_APP">%1$s</xliff:g>, שיכולה לעקוב אחר הפעילות שלך ברשת, כולל הודעות אימייל, אפליקציות ואתרים."</string>
+    <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"התחברת לאפליקציה <xliff:g id="VPN_APP">%1$s</xliff:g>, שיכולה לעקוב אחר הפעילות שלך ברשת, כולל הודעות אימייל, אפליקציות ואתרים."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"אתה מחובר לאפליקציות <xliff:g id="VPN_APP_0">%1$s</xliff:g> ו-<xliff:g id="VPN_APP_1">%2$s</xliff:g>, שיכולות לעקוב אחר הפעילות שלך ברשת, כולל הודעות אימייל, אפליקציות ואתרים."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"פרופיל העבודה שלך מחובר לאפליקציה <xliff:g id="VPN_APP">%1$s</xliff:g>, שיכולה לעקוב אחר הפעילות שלך ברשת, כולל הודעות אימייל, אפליקציות ואתרים."</string>
     <string name="monitoring_description_personal_profile_named_vpn" msgid="8179722332380953673">"הפרופיל האישי שלך מחובר לאפליקציה <xliff:g id="VPN_APP">%1$s</xliff:g>, שיכולה לעקוב אחר הפעילות שלך ברשת, כולל הודעות אימייל, אפליקציות ואתרים."</string>
@@ -564,23 +562,23 @@
     <string name="monitoring_description_do_body" msgid="7700878065625769970">"מנהל המערכת יכול לנטר ולנהל הגדרות, גישה ארגונית, אפליקציות, נתונים המשויכים למכשיר ומידע על מיקום המכשיר."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="1467280496376492558">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="645149183455573790">"למידע נוסף"</string>
-    <string name="monitoring_description_do_body_vpn" msgid="7699280130070502303">"אתה מחובר לאפליקציה <xliff:g id="VPN_APP">%1$s</xliff:g>, שיכולה לעקוב אחר הפעילות שלך ברשת, כולל הודעות אימייל, אפליקציות ואתרים."</string>
+    <string name="monitoring_description_do_body_vpn" msgid="7699280130070502303">"התחברת לאפליקציה <xliff:g id="VPN_APP">%1$s</xliff:g>, שיכולה לעקוב אחר הפעילות שלך ברשת, כולל הודעות אימייל, אפליקציות ואתרים."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"‏להגדרות ה-VPN"</string>
     <string name="monitoring_description_ca_cert_settings_separator" msgid="7107390013344435439">" "</string>
-    <string name="monitoring_description_ca_cert_settings" msgid="8329781950135541003">"פתח את פרטי הכניסה המהימנים"</string>
+    <string name="monitoring_description_ca_cert_settings" msgid="8329781950135541003">"פתיחה של פרטי הכניסה המהימנים"</string>
     <string name="monitoring_description_network_logging" msgid="577305979174002252">"מנהל המערכת הפעיל את תכונת רישום התנועה ברשת, שמנטרת את תנועת הנתונים במכשיר.\n\nלמידע נוסף, צור קשר עם מנהל המערכת."</string>
     <string name="monitoring_description_vpn" msgid="1685428000684586870">"‏נתת לאפליקציה כלשהי הרשאה להגדיר חיבור ‏VPN‏.\n\nהאפליקציה הזו יכולה לעקוב אחר הפעילות שלך ברשת ובמכשיר, כולל הודעות אימייל, אפליקציות ואתרים."</string>
     <string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"‏פרופיל העבודה שלך מנוהל על-ידי <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\n מנהל המערכת שלך יכול לעקוב אחרי הפעילות שלך ברשת, כולל פעילות באימייל, באפליקציות ובאתרים.\n\n למידע נוסף, צור קשר עם מנהל המערכת.\n\nבנוסף, אתה מחובר ל-VPN, שגם באמצעותו ניתן לעקוב אחרי הפעילות שלך ברשת."</string>
     <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"מכשיר זה מנוהל על ידי ההורה שלך. להורה שלך יש אפשרות לצפות בפרטים כמו האפליקציות שבשימוש, המיקום וזמן המסך שלך, ולנהל אותם."</string>
     <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
     <string name="monitoring_description_app" msgid="376868879287922929">"אתה מחובר לאפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g>, שיכולה לעקוב אחר הפעילות שלך ברשת, כולל הודעות אימייל, אפליקציות ואתרים."</string>
-    <string name="monitoring_description_app_personal" msgid="1970094872688265987">"אתה מחובר לאפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g>, שיכולה לעקוב אחר הפעילות שלך ברשת הפרטית, כולל הודעות אימייל, אפליקציות ואתרים."</string>
+    <string name="monitoring_description_app_personal" msgid="1970094872688265987">"התחברת לאפליקציית <xliff:g id="APPLICATION">%1$s</xliff:g>, שיכולה לעקוב אחר הפעילות שלך ברשת, כולל הודעות אימייל, אפליקציות ואתרים."</string>
     <string name="branded_monitoring_description_app_personal" msgid="1703511985892688885">"אתה מחובר לאפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g>, שיכולה לעקוב אחר הפעילות שלך ברשת הפרטית, כולל הודעות אימייל, אפליקציות ואתרים."</string>
     <string name="monitoring_description_app_work" msgid="3713084153786663662">"פרופיל העבודה שלך מנוהל על ידי <xliff:g id="ORGANIZATION">%1$s</xliff:g>. הפרופיל מחובר לאפליקציה <xliff:g id="APPLICATION">%2$s</xliff:g>, שיכולה לעקוב אחר הפעילות שלך ברשת, כולל הודעות אימייל, אפליקציות ואתרים.\n\nלמידע נוסף, פנה למנהל המערכת."</string>
     <string name="monitoring_description_app_personal_work" msgid="6175816356939166101">"פרופיל העבודה שלך מנוהל על ידי <xliff:g id="ORGANIZATION">%1$s</xliff:g>. הפרופיל מחובר לאפליקציה <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, שיכולה לעקוב אחר הפעילות שלך ברשת, כולל הודעות אימייל, אפליקציות ואתרים.\n\nהפרופיל מחובר גם לאפליקציה <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, שיכולה לעקוב אחר הפעילות שלך ברשת."</string>
     <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"הנעילה נמנעת על ידי סביבה אמינה"</string>
-    <string name="keyguard_indication_trust_disabled" msgid="6820793704816727918">"המכשיר יישאר נעול עד שתבטל את נעילתו באופן ידני"</string>
+    <string name="keyguard_indication_trust_disabled" msgid="6820793704816727918">"המכשיר יישאר נעול עד שהנעילה שלו תבוטל באופן ידני"</string>
     <string name="keyguard_indication_trust_unlocked_plugged_in" msgid="2323452175329362855">"<xliff:g id="KEYGUARD_INDICATION">%1$s</xliff:g>\n<xliff:g id="POWER_INDICATION">%2$s</xliff:g>"</string>
     <string name="hidden_notifications_title" msgid="1782412844777612795">"קבלה מהירה של התראות"</string>
     <string name="hidden_notifications_text" msgid="5899627470450792578">"צפה בהן לפני שתבטל נעילה"</string>
@@ -589,7 +587,7 @@
     <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>‏. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
     <string name="volume_zen_end_now" msgid="5901885672973736563">"כבה עכשיו"</string>
     <string name="accessibility_volume_settings" msgid="1458961116951564784">"הגדרות צליל"</string>
-    <string name="accessibility_volume_expand" msgid="7653070939304433603">"הרחב"</string>
+    <string name="accessibility_volume_expand" msgid="7653070939304433603">"הרחבה"</string>
     <string name="accessibility_volume_collapse" msgid="2746845391013829996">"כווץ"</string>
     <string name="volume_odi_captions_tip" msgid="8825655463280990941">"הוספת כתוביות אוטומטית למדיה"</string>
     <string name="accessibility_volume_close_odi_captions_tip" msgid="8924753283621160480">"סגירת הטיפ לגבי כתוביות"</string>
@@ -613,7 +611,7 @@
     <string name="screen_pinning_start" msgid="7483998671383371313">"האפליקציה הוצמדה"</string>
     <string name="screen_pinning_exit" msgid="4553787518387346893">"הצמדת האפליקציה בוטלה"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="463533331480997595">"להסתיר<xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
-    <string name="quick_settings_reset_confirmation_message" msgid="2320586180785674186">"יופיע מחדש בפעם הבאה שתפעיל את האפשרות בהגדרות."</string>
+    <string name="quick_settings_reset_confirmation_message" msgid="2320586180785674186">"יופיע מחדש בפעם הבאה שהאפשרות הזו תופעל בהגדרות."</string>
     <string name="quick_settings_reset_confirmation_button" msgid="3341477479055016776">"הסתר"</string>
     <string name="stream_voice_call" msgid="7468348170702375660">"שיחה"</string>
     <string name="stream_system" msgid="7663148785370565134">"מערכת"</string>
@@ -631,15 +629,15 @@
     <string name="qs_status_phone_vibrate" msgid="7055409506885541979">"הטלפון במצב רטט"</string>
     <string name="qs_status_phone_muted" msgid="3763664791309544103">"הטלפון מושתק"</string>
     <string name="volume_stream_content_description_unmute" msgid="7729576371406792977">"‏%1$s. הקש כדי לבטל את ההשתקה."</string>
-    <string name="volume_stream_content_description_vibrate" msgid="4858111994183089761">"‏%1$s. הקש כדי להגדיר רטט. ייתכן ששירותי הנגישות מושתקים."</string>
+    <string name="volume_stream_content_description_vibrate" msgid="4858111994183089761">"‏%1$s. צריך להקיש כדי להגדיר רטט. ייתכן ששירותי הנגישות מושתקים."</string>
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"‏%1$s. הקש כדי להשתיק. ייתכן ששירותי הנגישות מושתקים."</string>
-    <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"‏%1$s. הקש כדי להעביר למצב רטט."</string>
-    <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"‏%1$s. הקש כדי להשתיק."</string>
+    <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"‏%1$s. יש להקיש כדי להעביר למצב רטט."</string>
+    <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"‏%1$s. יש להקיש כדי להשתיק."</string>
     <string name="volume_ringer_change" msgid="3574969197796055532">"יש להקיש כדי לשנות את מצב תוכנת הצלצול"</string>
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"השתקה"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"ביטול ההשתקה"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"רטט"</string>
-    <string name="volume_dialog_title" msgid="6502703403483577940">"‏בקרי עוצמת שמע של %s"</string>
+    <string name="volume_dialog_title" msgid="6502703403483577940">"‏בקרי עוצמת קול של %s"</string>
     <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"הטלפון יצלצל כשמתקבלות שיחות והתראות (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string>
     <string name="output_title" msgid="3938776561655668350">"פלט מדיה"</string>
     <string name="output_calls_title" msgid="7085583034267889109">"פלט שיחת טלפון"</string>
@@ -655,20 +653,18 @@
     <string name="status_bar" msgid="4357390266055077437">"שורת סטטוס"</string>
     <string name="overview" msgid="3522318590458536816">"סקירה"</string>
     <string name="demo_mode" msgid="263484519766901593">"מצב הדגמה בממשק המשתמש של המערכת"</string>
-    <string name="enable_demo_mode" msgid="3180345364745966431">"הפעל מצב הדגמה"</string>
-    <string name="show_demo_mode" msgid="3677956462273059726">"הצג מצב הדגמה"</string>
+    <string name="enable_demo_mode" msgid="3180345364745966431">"הפעלת מצב הדגמה"</string>
+    <string name="show_demo_mode" msgid="3677956462273059726">"הצגת מצב הדגמה"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"אתרנט"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"התראה"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"ארנק"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"מוכן"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"פרופיל עבודה"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"מצב טיסה"</string>
-    <string name="add_tile" msgid="6239678623873086686">"הוסף אריח"</string>
+    <string name="add_tile" msgid="6239678623873086686">"הוספת אריח"</string>
     <string name="broadcast_tile" msgid="5224010633596487481">"אריח שידור"</string>
-    <string name="zen_alarm_warning_indef" msgid="5252866591716504287">"לא תשמע את ההתראה הבאה שלך <xliff:g id="WHEN">%1$s</xliff:g>, אלא אם תשבית קודם את ההגדרה הזו"</string>
-    <string name="zen_alarm_warning" msgid="7844303238486849503">"לא תשמע את ההתראה הבאה שלך <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="zen_alarm_warning_indef" msgid="5252866591716504287">"כדי לשמוע את ההתראה הבאה שלך <xliff:g id="WHEN">%1$s</xliff:g>, עליך להשבית את התכונה הזו"</string>
+    <string name="zen_alarm_warning" msgid="7844303238486849503">"לא ניתן יהיה לשמוע את ההתראה הבאה שלך <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="alarm_template" msgid="2234991538018805736">"בשעה <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="alarm_template_far" msgid="3561752195856839456">"ב-<xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_detail" msgid="544463655956179791">"הגדרות מהירות, <xliff:g id="TITLE">%s</xliff:g>."</string>
@@ -682,11 +678,11 @@
     <string name="remove_from_settings" msgid="633775561782209994">"הסר מההגדרות"</string>
     <string name="remove_from_settings_prompt" msgid="551565437265615426">"‏האם להסיר את System UI Tuner ולהפסיק להשתמש בכל התכונות שלו?"</string>
     <string name="activity_not_found" msgid="8711661533828200293">"האפליקציה אינה מותקנת במכשיר"</string>
-    <string name="clock_seconds" msgid="8709189470828542071">"הצג שניות בשעון"</string>
+    <string name="clock_seconds" msgid="8709189470828542071">"הצגת שניות בשעון"</string>
     <string name="clock_seconds_desc" msgid="2415312788902144817">"הצג שניות בשעון בשורת הסטטוס. פעולה זו עשויה להשפיע על אורך חיי הסוללה."</string>
     <string name="qs_rearrange" msgid="484816665478662911">"סידור מחדש של הגדרות מהירות"</string>
     <string name="show_brightness" msgid="6700267491672470007">"הצג בהירות בהגדרות מהירות"</string>
-    <string name="experimental" msgid="3549865454812314826">"ניסיוני"</string>
+    <string name="experimental" msgid="3549865454812314826">"ניסיוניות"</string>
     <string name="enable_bluetooth_title" msgid="866883307336662596">"‏האם להפעיל את ה-Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="6740938333772779717">"‏כדי לחבר את המקלדת לטאבלט, תחילה עליך להפעיל את ה-Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"הפעלה"</string>
@@ -793,7 +789,7 @@
     <string name="battery_panel_title" msgid="5931157246673665963">"שימוש בסוללה"</string>
     <string name="battery_detail_charging_summary" msgid="8821202155297559706">"תכונת החיסכון בסוללה אינה זמינה בעת טעינת המכשיר"</string>
     <string name="battery_detail_switch_title" msgid="6940976502957380405">"חיסכון בסוללה"</string>
-    <string name="battery_detail_switch_summary" msgid="3668748557848025990">"מפחית את רמת הביצועים ואת נתוני הרקע"</string>
+    <string name="battery_detail_switch_summary" msgid="3668748557848025990">"מפחיתה את רמת הביצועים ואת נתוני הרקע"</string>
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"לחצן <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"דף הבית"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"הקודם"</string>
@@ -888,7 +884,7 @@
   <string-array name="clock_options">
     <item msgid="3986445361435142273">"הצג שעות, דקות ושניות"</item>
     <item msgid="1271006222031257266">"הצג שעות ודקות (ברירת מחדל)"</item>
-    <item msgid="6135970080453877218">"אל תציג את הסמל הזה"</item>
+    <item msgid="6135970080453877218">"לא להציג את הסמל הזה"</item>
   </string-array>
   <string-array name="battery_options">
     <item msgid="7714004721411852551">"הצג תמיד באחוזים"</item>
@@ -912,7 +908,7 @@
     <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"פתיחה של \'הגדרות מהירות\'."</string>
     <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"סגירה של \'הגדרות מהירות\'."</string>
     <string name="accessibility_quick_settings_alarm_set" msgid="7237918261045099853">"הגדרת התראה."</string>
-    <string name="accessibility_quick_settings_user" msgid="505821942882668619">"מחובר בתור <xliff:g id="ID_1">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_user" msgid="505821942882668619">"בוצעה כניסה בתור <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"בחירת משתמש"</string>
     <string name="data_connection_no_internet" msgid="691058178914184544">"אין אינטרנט"</string>
     <string name="accessibility_quick_settings_open_details" msgid="4879279912389052142">"פתיחת פרטים."</string>
@@ -924,7 +920,7 @@
     <string name="tuner_lock_screen" msgid="2267383813241144544">"מסך נעילה"</string>
     <string name="thermal_shutdown_title" msgid="2702966892682930264">"הטלפון כבה עקב התחממות"</string>
     <string name="thermal_shutdown_message" msgid="6142269839066172984">"הטלפון פועל כרגיל עכשיו.\nיש להקיש כדי להציג מידע נוסף"</string>
-    <string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"הטלפון שלך התחמם יותר מדי וכבה כדי להתקרר. הטלפון פועל כרגיל עכשיו.\n\nייתכן שהטלפון יתחמם יותר מדי אם:\n	• תשתמש באפליקציות עתירות משאבים (כגון משחקים, אפליקציות וידאו או אפליקציות ניווט)\n	• תוריד או תעלה קבצים גדולים\n	• תשתמש בטלפון בטמפרטורות גבוהות"</string>
+    <string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"הטלפון שלך התחמם יותר מדי וכבה כדי להתקרר. הטלפון פועל כרגיל עכשיו.\n\nייתכן שהטלפון יתחמם יותר מדי אם:\n	• משתמשים באפליקציות עתירות משאבים (כגון משחקים, אפליקציות וידאו או אפליקציות ניווט)\n	• מורידים או מעלים קבצים גדולים\n	• משתמשים בטלפון בסביבה עם טמפרטורות גבוהות"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"לצפייה בשלבי הטיפול"</string>
     <string name="high_temp_title" msgid="2218333576838496100">"הטלפון מתחמם"</string>
     <string name="high_temp_notif_message" msgid="1277346543068257549">"חלק מהתכונות מוגבלות כל עוד הטלפון מתקרר.\nיש להקיש כדי להציג מידע נוסף"</string>
@@ -978,7 +974,7 @@
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"הספק שלך"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"יש אפליקציה שמסתירה את בקשת ההרשאה, ולכן להגדרות אין אפשרות לאמת את התשובה."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"האם לאפשר ל-<xliff:g id="APP_0">%1$s</xliff:g> להציג חלקים מ-<xliff:g id="APP_2">%2$s</xliff:g>?"</string>
-    <string name="slice_permission_text_1" msgid="6675965177075443714">"- תהיה לה אפשרות לקרוא מידע מ-<xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="slice_permission_text_1" msgid="6675965177075443714">"- תהיה לה אפשרות לקרוא מידע מאפליקציית <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="slice_permission_text_2" msgid="6758906940360746983">"- תהיה לה יכולת לנקוט פעולה בתוך <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="slice_permission_checkbox" msgid="4242888137592298523">"יש לאשר ל-<xliff:g id="APP">%1$s</xliff:g> להראות חלקים מכל אפליציה שהיא"</string>
     <string name="slice_permission_allow" msgid="6340449521277951123">"אני רוצה לאשר"</string>
@@ -1048,7 +1044,7 @@
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"סומן כהעדפה, במיקום <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"הוסר מהמועדפים"</string>
     <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"להוסיף למועדפים"</string>
-    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"להוסיף למועדפים"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"להסיר מהמועדפים"</string>
     <string name="accessibility_control_move" msgid="8980344493796647792">"העברה למיקום <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"פקדים"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"יש לבחור פקדים לגישה מתפריט ההפעלה"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 01ad3d3..44fed70 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"日の出まで"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>にオン"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g>まで"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"明るさを下げる"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC は無効です"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC は有効です"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"デモモードを表示"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"イーサネット"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"アラーム"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"ウォレット"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"準備完了"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"仕事用プロファイル"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"機内モード"</string>
     <string name="add_tile" msgid="6239678623873086686">"タイルを追加"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index cd95dd7e..cbed6a8 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"მზის ამოსვლამდე"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"ჩაირთოს <xliff:g id="TIME">%s</xliff:g>-ზე"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g>-მდე"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"სიკაშკაშის შემცირება"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC გათიშულია"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ჩართულია"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"დემო-რეჟიმის ჩვენება"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"ეთერნეტი"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"მაღვიძარა"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"მზადაა"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"სამსახურის პროფილი"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"თვითმფრინავის რეჟიმი"</string>
     <string name="add_tile" msgid="6239678623873086686">"მოზაიკის დამატება"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index ccdc0b6..20a326f 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Күн шыққанға дейін"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Қосылу уақыты: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> дейін"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Жарықтығын азайту"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC өшірулі"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC қосулы"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Демо режимін көрсету"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Дабыл"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Әмиян"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Дайын"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Жұмыс профилі"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Ұшақ режимі"</string>
     <string name="add_tile" msgid="6239678623873086686">"Тақтайша қосу"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 29691d1..93715e2 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"រហូត​ដល់​ពេល​ថ្ងៃរះ"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"បើកនៅម៉ោង <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"រហូតដល់ម៉ោង <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"បន្ថយ​ពន្លឺ"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"បាន​បិទ NFC"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"បាន​បើក NFC"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"បង្ហាញរបៀបសាកល្បង"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"អ៊ីសឺរណិត"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"ម៉ោងរោទ៍"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"កាបូប"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"រួចរាល់"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"ប្រវត្តិរូបការងារ"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"របៀបក្នុងយន្តហោះ"</string>
     <string name="add_tile" msgid="6239678623873086686">"បន្ថែមក្រឡាល្អិត"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 95fb699..ba058f8 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ಸೂರ್ಯೋದಯದವರೆಗೆ"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> ಸಮಯದಲ್ಲಿ"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> ವರೆಗೂ"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"ಪ್ರಖರತೆಯನ್ನು ಕಡಿಮೆ ಮಾಡಿ"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ನಿಷ್ಕ್ರಿಯಗೊಂಡಿದೆ"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ಸಕ್ರಿಯಗೊಂಡಿದೆ"</string>
@@ -541,8 +540,7 @@
     <string name="monitoring_button_view_policies" msgid="3869724835853502410">"ಕಾರ್ಯನೀತಿಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string>
     <string name="monitoring_button_view_controls" msgid="8316440345340701117">"ನಿಯಂತ್ರಣಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string>
     <string name="monitoring_description_named_management" msgid="505833016545056036">"ಈ ಸಾಧನವು <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ಗೆ ಸೇರಿದೆ.\n\nಸೆಟ್ಟಿಂಗ್‌ಗಳು, ಕಾರ್ಪೊರೇಟ್ ಪ್ರವೇಶ, ಆ್ಯಪ್‌ಗಳು, ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಡೇಟಾ ಮತ್ತು ನಿಮ್ಮ ಸಾಧನದ ಸ್ಥಳದ ಮಾಹಿತಿಯನ್ನು ನಿಮ್ಮ IT ನಿರ್ವಾಹಕರು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು ಮತ್ತು ನಿರ್ವಹಿಸಬಹುದು.\n\nಹೆಚ್ಚಿನ ಮಾಹಿತಿಗಾಗಿ ನಿಮ್ಮ IT ನಿರ್ವಾಹಕರನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
-    <!-- no translation found for monitoring_financed_description_named_management (6108439201399938668) -->
-    <skip />
+    <string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"<xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g> ಗೆ ಈ ಸಾಧನದ ಜೊತೆಗೆ ಸಂಯೋಜಿತವಾಗಿರುವ ಡೇಟಾವನ್ನು ಪ್ರವೇಶಿಸಲು, ಆ್ಯಪ್‌ಗಳನ್ನು ನಿರ್ವಹಿಸಲು ಮತ್ತು ಈ ಸಾಧನಗಳ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಬದಲಾಯಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತದೆ.\n\nನಿಮ್ಮ ಬಳಿ ಪ್ರಶ್ನೆಗಳಿದ್ದರೆ, <xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g> ಅನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
     <string name="monitoring_description_management" msgid="4308879039175729014">"ಈ ಸಾಧನವು ನಿಮ್ಮ ಸಂಸ್ಥೆಗೆ ಸೇರಿದೆ.\n\nಸೆಟ್ಟಿಂಗ್‌ಗಳು, ಕಾರ್ಪೊರೇಟ್ ಪ್ರವೇಶ, ಆ್ಯಪ್‌ಗಳು, ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಡೇಟಾ ಮತ್ತು ನಿಮ್ಮ ಸಾಧನದ ಸ್ಥಳದ ಮಾಹಿತಿಯನ್ನು ನಿಮ್ಮ IT ನಿರ್ವಾಹಕರು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು ಮತ್ತು ನಿರ್ವಹಿಸಬಹುದು.\n\nಹೆಚ್ಚಿನ ಮಾಹಿತಿಗಾಗಿ ನಿಮ್ಮ IT ನಿರ್ವಾಹಕರನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
     <string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"ನಿಮ್ಮ ಸಂಸ್ಥೆಯು ಈ ಸಾಧನದಲ್ಲಿ ಪ್ರಮಾಣಪತ್ರ ಅಂಗೀಕಾರವನ್ನು ಸ್ಥಾಪಿಸಿದೆ. ನಿಮ್ಮ ಸುರಕ್ಷಿತ ನೆಟ್‌ವರ್ಕ್ ಟ್ರಾಫಿಕ್ ಅನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು ಅಥವಾ ಮಾರ್ಪಡಿಸಬಹುದು."</string>
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"ನಿಮ್ಮ ಸಂಸ್ಥೆಯು ನಿಮ್ಮ ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್‌ನಲ್ಲಿ ಪ್ರಮಾಣಪತ್ರ ಅಂಗೀಕಾರವನ್ನು ಸ್ಥಾಪಿಸಿದೆ. ನಿಮ್ಮ ಸುರಕ್ಷಿತ ನೆಟ್‌ವರ್ಕ್ ಟ್ರಾಫಿಕ್ ಅನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು ಅಥವಾ ಮಾರ್ಪಡಿಸಬಹುದು."</string>
@@ -653,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"ಡೆಮೊ ಮೋಡ್ ತೋರಿಸು"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"ಇಥರ್ನೆಟ್"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"ಅಲಾರಮ್"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"ವಾಲೆಟ್"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"ಸಿದ್ಧವಾಗಿದೆ"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"ಕೆಲಸದ ಪ್ರೊಫೈಲ್"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"ಏರ್‌ಪ್ಲೇನ್ ಮೋಡ್"</string>
     <string name="add_tile" msgid="6239678623873086686">"ಟೈಲ್ ಸೇರಿಸಿ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 3767888..3a519e5 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"일출까지"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>에 켜짐"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g>까지"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"밝기 낮추기"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC 사용 중지됨"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC 사용 설정됨"</string>
@@ -541,7 +540,7 @@
     <string name="monitoring_button_view_policies" msgid="3869724835853502410">"정책 보기"</string>
     <string name="monitoring_button_view_controls" msgid="8316440345340701117">"제어 기능 보기"</string>
     <string name="monitoring_description_named_management" msgid="505833016545056036">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>에 속한 기기입니다.\n\nIT 관리자가 설정, 기업 액세스, 앱, 기기와 연결된 데이터, 기기 위치 정보를 모니터링 및 관리할 수 있습니다.\n\n자세한 정보를 확인하려면 IT 관리자에게 문의하세요."</string>
-    <string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"<xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g>에서 이 기기와 연결된 데이터에 액세스하고 앱을 관리하고 기기 설정을 변경할 수 있습니다.\n\n궁금한 점이 있으면 <xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g>에 문의하세요."</string>
+    <string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"<xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g>에서 이 기기와 연결된 데이터에 액세스하고 앱을 관리하며 기기 설정을 변경할 수 있습니다.\n\n궁금한 점이 있으면 <xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g>에 문의하세요."</string>
     <string name="monitoring_description_management" msgid="4308879039175729014">"내 조직에 속한 기기입니다.\n\nIT 관리자가 설정, 기업 액세스, 앱, 기기와 연결된 데이터, 기기 위치 정보를 모니터링 및 관리할 수 있습니다.\n\n자세한 정보를 확인하려면 IT 관리자에게 문의하세요."</string>
     <string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"조직에서 이 기기에 인증기관을 설치했습니다. 보안 네트워크 트래픽을 모니터링 또는 수정할 수 있습니다."</string>
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"조직에서 직장 프로필에 인증기관을 설치했습니다. 보안 네트워크 트래픽을 모니터링 또는 수정할 수 있습니다."</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"데모 모드 표시"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"이더넷"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"알람"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"준비됨"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"직장 프로필"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"비행기 모드"</string>
     <string name="add_tile" msgid="6239678623873086686">"타일 추가"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 4897b72..f637222 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Күн чыкканга чейин"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Саат <xliff:g id="TIME">%s</xliff:g> күйөт"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> чейин"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Экрандын жарыктыгын төмөндөтүү"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC өчүрүлгөн"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC иштетилген"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Демо режимин көрсөтүү"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Ойготкуч"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Даяр"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Жумуш профили"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Учак режими"</string>
     <string name="add_tile" msgid="6239678623873086686">"Тайл кошуу"</string>
@@ -675,8 +672,8 @@
     <string name="remove_from_settings" msgid="633775561782209994">"Жөндөөлөрдөн алып салуу"</string>
     <string name="remove_from_settings_prompt" msgid="551565437265615426">"System UI Tuner Жөндөөлөрдөн өчүрүлүп, анын бардык функциялары токтотулсунбу?"</string>
     <string name="activity_not_found" msgid="8711661533828200293">"Колдонмо сиздин түзмөгүңүздө орнотулган эмес"</string>
-    <string name="clock_seconds" msgid="8709189470828542071">"Сааттын секунддары көрсөтүлсүн"</string>
-    <string name="clock_seconds_desc" msgid="2415312788902144817">"Абал тилкесинен сааттын секунддары көрсөтүлсүн. Батареянын кубаты көбүрөөк сарпталышы мүмкүн."</string>
+    <string name="clock_seconds" msgid="8709189470828542071">"Сааттын секунддары көрүнсүн"</string>
+    <string name="clock_seconds_desc" msgid="2415312788902144817">"Абал тилкесинен сааттын секунддары көрүнсүн. Батареянын кубаты көбүрөөк сарпталышы мүмкүн."</string>
     <string name="qs_rearrange" msgid="484816665478662911">"Ыкчам жөндөөлөрдү кайра коюу"</string>
     <string name="show_brightness" msgid="6700267491672470007">"Ыкчам жөндөөлөрдөн жарык деңгээлин көрсөтүү"</string>
     <string name="experimental" msgid="3549865454812314826">"Сынамык"</string>
@@ -685,7 +682,7 @@
     <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Күйгүзүү"</string>
     <string name="show_silently" msgid="5629369640872236299">"Үнсүз көрүнөт"</string>
     <string name="block" msgid="188483833983476566">"Бардык билдирмелерди бөгөттөө"</string>
-    <string name="do_not_silence" msgid="4982217934250511227">"Үнү менен көрсөтүлсүн"</string>
+    <string name="do_not_silence" msgid="4982217934250511227">"Үнү менен көрүнсүн"</string>
     <string name="do_not_silence_block" msgid="4361847809775811849">"Үнү менен көрсөтүлүп бөгөттөлбөсүн"</string>
     <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Эскертмелерди башкаруу каражаттары"</string>
     <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Күйүк"</string>
@@ -825,7 +822,7 @@
     <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Музыка"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="5078136084632450333">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Жылнаама"</string>
-    <string name="tuner_full_zen_title" msgid="5120366354224404511">"Үн көзөмөлдөгүчтөрү менен көрсөтүлсүн"</string>
+    <string name="tuner_full_zen_title" msgid="5120366354224404511">"Үн көзөмөлдөгүчтөрү менен көрүнсүн"</string>
     <string name="volume_and_do_not_disturb" msgid="502044092739382832">"Тынчымды алба"</string>
     <string name="volume_dnd_silent" msgid="4154597281458298093">"Үндү көзөмөлдөөчү баскычтардын кыска жолдору"</string>
     <string name="volume_up_silent" msgid="1035180298885717790">"Үн катуулатылганда \"Тынчымды алба\" режиминен чыгуу"</string>
@@ -880,8 +877,8 @@
     <item msgid="6135970080453877218">"Бул сүрөтчө көрүнбөсүн"</item>
   </string-array>
   <string-array name="battery_options">
-    <item msgid="7714004721411852551">"Ар дайым пайызы көрсөтүлсүн"</item>
-    <item msgid="3805744470661798712">"Кубаттоо учурунда пайызы көрсөтүлсүн (демейки)"</item>
+    <item msgid="7714004721411852551">"Ар дайым пайызы көрүнсүн"</item>
+    <item msgid="3805744470661798712">"Кубаттоо учурунда пайызы көрүнсүн (демейки)"</item>
     <item msgid="8619482474544321778">"Бул сүрөтчө көрүнбөсүн"</item>
   </string-array>
     <string name="tuner_low_priority" msgid="8412666814123009820">"Анча маанилүү эмес билдирменин сүрөтчөлөрүн көрсөтүү"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 7b7c7b1..4c2a5cb 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ຈົນກວ່າຕາເວັນຂຶ້ນ"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"ເປີດເວລາ <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"ຈົນຮອດ <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"ຫຼຸດຄວາມສະຫວ່າງລົງ"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is disabled"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is enabled"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"ສະ​ແດງ​ໂຫມດ​ສາ​ທິດ"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"ອີ​ເທ​ເນັດ"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"ໂມງປຸກ"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"ກະເປົາ"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"ພ້ອມແລ້ວ"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"​ໂປຣ​ໄຟລ໌​ບ່ອນ​ເຮັດ​ວຽກ"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"ໂໝດເຮືອ​ບິນ"</string>
     <string name="add_tile" msgid="6239678623873086686">"ເພີ່ມ​ລາຍ​ຕາ​ກະ​ໂລ່"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 5f17f4d..ca02dc8 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -416,7 +416,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Iki saulėtekio"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Iki <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Šviesumo mažinimas"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"ALR"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"ALR išjungtas"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"ALR įjungtas"</string>
@@ -658,10 +657,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Rodyti demonstraciniu režimu"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Eternetas"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Signalas"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Piniginė"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Paruošta"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Darbo profilis"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Lėktuvo režimas"</string>
     <string name="add_tile" msgid="6239678623873086686">"Pridėti išklotinės elementą"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 4f17905..c355784 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -414,7 +414,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Līdz saullēktam"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Plkst. <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Līdz plkst. <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Samazināt spilgtumu"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ir atspējoti"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ir iespējoti"</string>
@@ -655,10 +654,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Rādīt demonstrācijas režīmu"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Tīkls Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Signāls"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Maks"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Gatavs"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Darba profils"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Lidojuma režīms"</string>
     <string name="add_tile" msgid="6239678623873086686">"Pievienot elementu"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index d571df7..06718c1 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"До изгрејсонце"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Се вклучува во <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"До <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Намалување на осветленоста"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC е оневозможено"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC е овозможено"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Прикажи демо-режим"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Етернет"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Аларм"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Паричник"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Подготвено"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Работен профил"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Авионски режим"</string>
     <string name="add_tile" msgid="6239678623873086686">"Додај плочка"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 131109c..36a8a54 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"സൂര്യോദയം വരെ"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>-ന്"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> വരെ"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"തെളിച്ചം കുറയ്ക്കുക"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC പ്രവർത്തനരഹിതമാക്കി"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC പ്രവർത്തനക്ഷമമാക്കി"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"ഡെമോ മോഡ് കാണിക്കുക"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"ഇതർനെറ്റ്"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"അലാറം"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"തയ്യാറാണ്"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"ഔദ്യോഗിക പ്രൊഫൈൽ"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"ഫ്ലൈറ്റ് മോഡ്"</string>
     <string name="add_tile" msgid="6239678623873086686">"ടൈൽ ചേർക്കുക"</string>
@@ -716,7 +713,7 @@
     <string name="notification_automatic_title" msgid="3745465364578762652">"സ്വയമേവ"</string>
     <string name="notification_channel_summary_low" msgid="4860617986908931158">"ശബ്ദമോ വൈബ്രേഷനോ ഇല്ല"</string>
     <string name="notification_conversation_summary_low" msgid="1734433426085468009">"ശബ്‌ദമോ വൈബ്രേഷനോ ഇല്ല, സംഭാഷണ വിഭാഗത്തിന് താഴെയായി ദൃശ്യമാകും"</string>
-    <string name="notification_channel_summary_default" msgid="3282930979307248890">"ഫോൺ ക്രമീകരണം അടിസ്ഥാനമാക്കി റിംഗ് ചെയ്‌തേക്കാം അല്ലെങ്കിൽ വൈബ്രേറ്റ് ചെയ്‌തേക്കാം"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"ഫോൺ ക്രമീകരണം അടിസ്ഥാനമാക്കി റിംഗ്/വൈബ്രേറ്റ് ചെയ്യും"</string>
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ഫോൺ ക്രമീകരണം അടിസ്ഥാനമാക്കി റിംഗ് ചെയ്‌തേക്കാം അല്ലെങ്കിൽ വൈബ്രേറ്റ് ചെയ്‌തേക്കാം. <xliff:g id="APP_NAME">%1$s</xliff:g>-ൽ നിന്നുള്ള സംഭാഷണങ്ങൾ ഡിഫോൾട്ടായി ബബ്ൾ ആവുന്നു."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ഈ ഉള്ളടക്കത്തിലേക്ക് ഒരു ഫ്ലോട്ടിംഗ് കുറുക്കുവഴി ഉപയോഗിച്ച് നിങ്ങളുടെ ശ്രദ്ധ നിലനിർത്തുന്നു."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"ഈ അറിയിപ്പ് വരുമ്പോൾ ശബ്‌ദിക്കുകയാണോ വൈബ്രേറ്റ് ചെയ്യുകയാണോ വേണ്ടതെന്ന് നിർണ്ണയിക്കാൻ സിസ്‌റ്റത്തെ അനുവദിക്കുക"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index a6b9055..fdf0eab 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Нар мандах хүртэл"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>-д"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> хүртэл"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Гэрэлтүүлгийг багасгах"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC-г цуцалсан"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC-г идэвхжүүлсэн"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Демо горимыг харуулах"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Этернет"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Сэрүүлэг"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Түрийвч"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Бэлэн"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Ажлын профайл"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Нислэгийн горим"</string>
     <string name="add_tile" msgid="6239678623873086686">"Вебсайтын цонх нэмэх"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index d2baefc..8de7c96 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"सूर्योदयापर्यंत"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> वाजता सुरू होते"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> पर्यंत"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"ब्राइटनेस कमी करा"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC अक्षम केले आहे"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC सक्षम केले आहे"</string>
@@ -515,8 +514,7 @@
     <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"हे डिव्हाइस तुमच्या पालकाने व्यवस्थापित केले आहे"</string>
     <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"तुमच्‍या संस्‍थेकडे या डिव्हाइसची मालकी आहे आणि ती नेटवर्क ट्रॅफिकचे परीक्षण करू शकते"</string>
     <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"हे डिव्हाइस <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> च्या मालकीचे आहे आणि ती नेटवर्क ट्रॅफिकचे परीक्षण करू शकते"</string>
-    <!-- no translation found for quick_settings_financed_disclosure_named_management (2307703784594859524) -->
-    <skip />
+    <string name="quick_settings_financed_disclosure_named_management" msgid="2307703784594859524">"हे डिव्हाइस <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> द्वारे पुरवले गेले आहे"</string>
     <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"हे डिव्हाइस तुमच्या संस्थेचे आहे आणि ते <xliff:g id="VPN_APP">%1$s</xliff:g> ला कनेक्ट केले आहे"</string>
     <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"हे डिव्हाइस <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> चे आहे आणि ते <xliff:g id="VPN_APP">%2$s</xliff:g> ला कनेक्ट केले आहे"</string>
     <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"हे डिव्हाइस तुमच्या संस्थेचे आहे"</string>
@@ -530,8 +528,7 @@
     <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"तुमची कार्य प्रोफाइल <xliff:g id="VPN_APP">%1$s</xliff:g> ला कनेक्ट केली"</string>
     <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"तुमची वैयक्‍तिक प्रोफाइल <xliff:g id="VPN_APP">%1$s</xliff:g> ला कनेक्‍ट केली आहे"</string>
     <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"हे डिव्हाइस <xliff:g id="VPN_APP">%1$s</xliff:g> ला कनेक्ट केले आहे"</string>
-    <!-- no translation found for monitoring_title_financed_device (3659962357973919387) -->
-    <skip />
+    <string name="monitoring_title_financed_device" msgid="3659962357973919387">"हे डिव्हाइस <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> द्वारे पुरवले गेले आहे"</string>
     <string name="monitoring_title_device_owned" msgid="7029691083837606324">"डिव्हाइस व्‍यवस्‍थापन"</string>
     <string name="monitoring_title_profile_owned" msgid="6301118649405449568">"प्रोफाईल परीक्षण"</string>
     <string name="monitoring_title" msgid="4063890083735924568">"नेटवर्क परीक्षण"</string>
@@ -654,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"डेमो मोड दर्शवा"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"इथरनेट"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"अलार्म"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"तयार आहे"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"कार्य प्रोफाईल"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"विमान मोड"</string>
     <string name="add_tile" msgid="6239678623873086686">"टाइल जोडा"</string>
@@ -904,8 +899,7 @@
     <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"जलद सेटिंग्ज बंद करा."</string>
     <string name="accessibility_quick_settings_alarm_set" msgid="7237918261045099853">"अलार्म सेट केला."</string>
     <string name="accessibility_quick_settings_user" msgid="505821942882668619">"<xliff:g id="ID_1">%s</xliff:g> म्हणून साइन इन केले"</string>
-    <!-- no translation found for accessibility_quick_settings_choose_user_action (4554388498186576087) -->
-    <skip />
+    <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"वापरकर्ता निवडा"</string>
     <string name="data_connection_no_internet" msgid="691058178914184544">"इंटरनेट नाही"</string>
     <string name="accessibility_quick_settings_open_details" msgid="4879279912389052142">"तपशील उघडा."</string>
     <string name="accessibility_quick_settings_not_available" msgid="6860875849497473854">"<xliff:g id="REASON">%s</xliff:g> मुळे उपलब्ध नाही"</string>
@@ -1022,10 +1016,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"फुल स्क्रीन मॅग्निफाय करा"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"स्क्रीनचा काही भाग मॅग्निफाय करा"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"स्विच करा"</string>
-    <!-- no translation found for accessibility_floating_button_migration_tooltip (4431046858918714564) -->
-    <skip />
-    <!-- no translation found for accessibility_floating_button_docking_tooltip (6814897496767461517) -->
-    <skip />
+    <string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"अ‍ॅक्सेसिबिलिटी जेश्चर हे आता अ‍ॅक्सेसिबिलिटी बटण आहे \n\n"<annotation id="link">"सेटिंग्ज पाहा"</annotation></string>
+    <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"बटण तात्पुरते लपवण्यासाठी ते कोपर्‍यामध्ये हलवा"</string>
     <string name="quick_controls_title" msgid="6839108006171302273">"डिव्हाइस नियंत्रणे"</string>
     <string name="quick_controls_subtitle" msgid="1667408093326318053">"तुमच्या कनेक्ट केलेल्या डिव्हाइससाठी नियंत्रणे जोडा"</string>
     <string name="quick_controls_setup_title" msgid="8901436655997849822">"डिव्हाइस नियंत्रणे सेट करा"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 4855101..50c5e0d 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Hingga matahari trbt"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Dihidupkan pada <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Hingga <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Kurangkan kecerahan"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC dilumpuhkan"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC didayakan"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Tunjukkan mod tunjuk cara"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Penggera"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Sedia"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Profil kerja"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Mod pesawat"</string>
     <string name="add_tile" msgid="6239678623873086686">"Tambahkan jubin"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 91e5110..9e67f1c 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"နေထွက်ချိန် အထိ"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> တွင် ဖွင့်မည်"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> အထိ"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"တောက်ပမှုကို လျှော့ခြင်း"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ကို ပိတ်ထားသည်"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ကို ဖွင့်ထားသည်"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"သရုပ်ပြမုဒ် ပြရန်"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"အီသာနက်"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"နှိုးစက်"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"အဆင်သင့်"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"အလုပ် ပရိုဖိုင်"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"လေယာဉ်ပျံမုဒ်"</string>
     <string name="add_tile" msgid="6239678623873086686">"လေးထောင့်ကွက် ထည့်ရန်"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 5ebf4ae..aa7139b 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Til soloppgang"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Slås på klokken <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Til <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Reduser lysstyrken"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC er slått av"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC er slått på"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Vis demo-modus"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Klar"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Work-profil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Flymodus"</string>
     <string name="add_tile" msgid="6239678623873086686">"Legg til felt"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index b13561c..0f9aa79 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"सूर्योदयसम्म"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> मा सक्रिय"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> सम्म"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"चमक घटाइयोस्"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC लाई असक्षम पारिएको छ"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC लाई सक्षम पारिएको छ"</string>
@@ -502,7 +501,7 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"व्यवस्थित गर्नुहोस्"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"इतिहास"</string>
     <string name="notification_section_header_incoming" msgid="850925217908095197">"नयाँ"</string>
-    <string name="notification_section_header_gentle" msgid="6804099527336337197">"मौन"</string>
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"साइलेन्ट"</string>
     <string name="notification_section_header_alerting" msgid="5581175033680477651">"सूचनाहरू"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"वार्तालापहरू"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"सबै मौन सूचनाहरू हटाउनुहोस्"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"डेमो मोड देखाउनुहोस्"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"इथरनेट"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"अलार्म"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"वालेट"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"तयार छ"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"कार्य प्रोफाइल"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"हवाइजहाज मोड"</string>
     <string name="add_tile" msgid="6239678623873086686">"टाइल थप्नुहोस्"</string>
@@ -705,19 +702,19 @@
     <string name="inline_block_button" msgid="479892866568378793">"रोक लगाउनुहोस्"</string>
     <string name="inline_keep_button" msgid="299631874103662170">"देखाउने क्रम जारी राख्नुहोस्"</string>
     <string name="inline_minimize_button" msgid="1474436209299333445">"सानो बनाउनुहोस्"</string>
-    <string name="inline_silent_button_silent" msgid="525243786649275816">"मौन"</string>
+    <string name="inline_silent_button_silent" msgid="525243786649275816">"साइलेन्ट"</string>
     <string name="inline_silent_button_stay_silent" msgid="2129254868305468743">"मौन रहनुहोस्"</string>
     <string name="inline_silent_button_alert" msgid="5705343216858250354">"सतर्क गराउने"</string>
     <string name="inline_silent_button_keep_alerting" msgid="6577845442184724992">"सर्तक गराइरहनुहोस्"</string>
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"सूचनाहरू निष्क्रिय पार्नुहोस्"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"यो एपका सूचनाहरू देखाउने क्रम जारी राख्ने हो?"</string>
-    <string name="notification_silence_title" msgid="8608090968400832335">"मौन"</string>
+    <string name="notification_silence_title" msgid="8608090968400832335">"साइलेन्ट"</string>
     <string name="notification_alert_title" msgid="3656229781017543655">"पूर्वनिर्धारित"</string>
     <string name="notification_automatic_title" msgid="3745465364578762652">"स्वचालित"</string>
     <string name="notification_channel_summary_low" msgid="4860617986908931158">"न घन्टी बज्छ न त कम्पन नै हुन्छ"</string>
     <string name="notification_conversation_summary_low" msgid="1734433426085468009">"न घन्टी बज्छ न त कम्पन नै हुन्छ र वार्तालाप खण्डको तलतिर देखा पर्छ"</string>
-    <string name="notification_channel_summary_default" msgid="3282930979307248890">"फोनको सेटिङका आधारमा घन्टी बज्न वा कम्पन हुन सक्छ"</string>
-    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"फोनको सेटिङका आधारमा घन्टी बज्न वा कम्पन हुन सक्छ। <xliff:g id="APP_NAME">%1$s</xliff:g> का वार्तालापहरू पूर्वनिर्धारित रूपमा बबलमा देखाइन्छन्।"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"फोनको सेटिङका आधारमा घन्टी बज्न वा भाइब्रेट हुन सक्छ"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"फोनको सेटिङका आधारमा घन्टी बज्न वा भाइब्रेट हुन सक्छ। <xliff:g id="APP_NAME">%1$s</xliff:g> का वार्तालापहरू पूर्वनिर्धारित रूपमा बबलमा देखाइन्छन्।"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"फ्लोटिङ सर्टकटमार्फत यो सामग्रीतर्फ तपाईंको ध्यान आकर्षित गर्दछ।"</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"सिस्टमलाई यो सूचना आउँदा ध्वनि बज्नु पर्छ वा कम्पन हुनु पर्छ भन्ने कुराको निधो गर्न दिनुहोस्"</string>
     <string name="notification_channel_summary_automatic_alerted" msgid="954166812246932240">"&lt;b&gt;स्थिति:&lt;/b&gt; सूचनालाई महत्त्वपूर्ण ठानी पूर्वनिर्धारित मोडमा सेट गरिएको छ"</string>
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
index d571f2f..17fdeb3 100644
--- a/packages/SystemUI/res/values-night/colors.xml
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -33,6 +33,9 @@
     <!-- The color of the text inside a notification -->
     <color name="notification_primary_text_color">@*android:color/notification_primary_text_color_dark</color>
 
+    <color name="notif_pill_background">@android:color/system_neutral1_800</color>
+    <color name="notif_pill_text">@android:color/system_neutral1_50</color>
+
     <color name="notification_guts_link_icon_tint">@color/GM2_grey_500</color>
     <color name="notification_guts_sub_text_color">@color/GM2_grey_300</color>
     <color name="notification_guts_header_text_color">@color/GM2_grey_200</color>
@@ -99,8 +102,7 @@
     <color name="qs_user_switcher_avatar_background">#3C4043</color>
 
     <!-- Colors for privacy dialog. These should be changed to the new palette -->
-    <color name="privacy_circle_camera">#81C995</color> <!-- g300 -->
-    <color name="privacy_circle_microphone_location">#FCAD70</color> <!--o300 -->
+    <color name="privacy_circle">#81C995</color> <!-- g300 -->
 
     <!-- Accessibility floating menu -->
     <color name="accessibility_floating_menu_background">#B3000000</color> <!-- 70% -->
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index c7aabad..523b4c3 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Tot zonsopgang"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Aan om <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Tot <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Helderheid verlagen"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is uitgeschakeld"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is ingeschakeld"</string>
@@ -606,7 +605,7 @@
     <string name="screen_pinning_start" msgid="7483998671383371313">"App vastgezet"</string>
     <string name="screen_pinning_exit" msgid="4553787518387346893">"App losgemaakt"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="463533331480997595">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> verbergen?"</string>
-    <string name="quick_settings_reset_confirmation_message" msgid="2320586180785674186">"Deze wordt opnieuw weergegeven zodra u de instelling weer aanzet."</string>
+    <string name="quick_settings_reset_confirmation_message" msgid="2320586180785674186">"Deze zie je opnieuw zodra je de instelling weer aanzet."</string>
     <string name="quick_settings_reset_confirmation_button" msgid="3341477479055016776">"Verbergen"</string>
     <string name="stream_voice_call" msgid="7468348170702375660">"Bellen"</string>
     <string name="stream_system" msgid="7663148785370565134">"Systeem"</string>
@@ -713,9 +712,9 @@
     <string name="notification_alert_title" msgid="3656229781017543655">"Standaard"</string>
     <string name="notification_automatic_title" msgid="3745465364578762652">"Automatisch"</string>
     <string name="notification_channel_summary_low" msgid="4860617986908931158">"Geen geluid of trilling"</string>
-    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Geen geluid of trilling en wordt lager in het gedeelte met gesprekken weergegeven"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Geen geluid of trilling en wordt lager in het gedeelte met gesprekken getoond"</string>
     <string name="notification_channel_summary_default" msgid="3282930979307248890">"Kan overgaan of trillen op basis van de telefooninstellingen"</string>
-    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Kan overgaan of trillen op basis van de telefooninstellingen. Gesprekken uit <xliff:g id="APP_NAME">%1$s</xliff:g> worden standaard als bubbels weergegeven."</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Kan overgaan of trillen op basis van de telefooninstellingen. Gesprekken uit <xliff:g id="APP_NAME">%1$s</xliff:g> worden standaard als bubbels getoond."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Trekt de aandacht met een zwevende snelkoppeling naar deze content."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Het systeem laten bepalen of deze melding geluid moet maken of moet trillen"</string>
     <string name="notification_channel_summary_automatic_alerted" msgid="954166812246932240">"&lt;b&gt;Status:&lt;/b&gt; opgeschaald naar Standaard"</string>
@@ -1001,7 +1000,7 @@
     <string name="priority_onboarding_behavior" msgid="5342816047020432929">"Prioriteitsgesprekken:"</string>
     <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Worden bovenaan het gespreksgedeelte getoond"</string>
     <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Tonen profielafbeelding op vergrendelscherm"</string>
-    <string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Worden als zwevende ballon weergegeven vóór apps"</string>
+    <string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Zijn als zwevende ballon zichtbaar vóór apps"</string>
     <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Onderbreken \'Niet storen\'"</string>
     <string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"OK"</string>
     <string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Instellingen"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index d4bb3e7..3bbdd30 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ସକାଳ ପର୍ଯ୍ୟନ୍ତ"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>ରେ ଚାଲୁ ହେବ"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> ପର୍ଯ୍ୟନ୍ତ"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"ଉଜ୍ଜ୍ୱଳତା କମ୍ କରନ୍ତୁ"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ଅକ୍ଷମ କରାଯାଇଛି"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ସକ୍ଷମ କରାଯାଇଛି"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"ଡେମୋ ମୋଡ୍‍ ଦେଖାନ୍ତୁ"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"ଇଥରନେଟ୍‌"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"ଆଲାର୍ମ"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"ୱାଲେଟ୍"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"ପ୍ରସ୍ତୁତ"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"ୱର୍କ ପ୍ରୋଫାଇଲ୍‌"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"ଏରୋପ୍ଲେନ୍‍ ମୋଡ୍"</string>
     <string name="add_tile" msgid="6239678623873086686">"ଟାଇଲ୍‍ ଯୋଡ଼ନ୍ତୁ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index b368c28..9a58ef6 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ਸੂਰਜ ਚੜ੍ਹਨ ਤੱਕ"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> ਵਜੇ ਚਾਲੂ"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> ਵਜੇ ਤੱਕ"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"ਚਮਕ ਘਟਾਓ"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ਨੂੰ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ਨੂੰ ਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ"</string>
@@ -515,8 +514,7 @@
     <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ਇਸ ਡੀਵਾਈਸ ਦਾ ਪ੍ਰਬੰਧਨ ਤੁਹਾਡੇ ਮਾਂ-ਪਿਓ ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ"</string>
     <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"ਤੁਹਾਡੀ ਸੰਸਥਾ ਕੋਲ ਇਸ ਡੀਵਾਈਸ ਦੀ ਮਲਕੀਅਤ ਹੈ ਅਤੇ ਇਹ ਨੈੱਟਵਰਕ ਟਰੈਫ਼ਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ"</string>
     <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ਕੋਲ ਇਸ ਡੀਵਾਈਸ ਦੀ ਮਲਕੀਅਤ ਹੈ ਅਤੇ ਇਹ ਨੈੱਟਵਰਕ ਟਰੈਫ਼ਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ"</string>
-    <!-- no translation found for quick_settings_financed_disclosure_named_management (2307703784594859524) -->
-    <skip />
+    <string name="quick_settings_financed_disclosure_named_management" msgid="2307703784594859524">"ਇਹ ਡੀਵਾਈਸ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ਵੱਲੋਂ ਮੁਹੱਈਆ ਕੀਤਾ ਗਿਆ ਹੈ"</string>
     <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"ਇਹ ਡੀਵਾਈਸ ਤੁਹਾਡੀ ਸੰਸਥਾ ਨਾਲ ਸੰਬੰਧਿਤ ਹੈ ਅਤੇ <xliff:g id="VPN_APP">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੈ"</string>
     <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"ਇਹ ਡੀਵਾਈਸ <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ਨਾਲ ਸੰਬੰਧਿਤ ਹੈ ਅਤੇ <xliff:g id="VPN_APP">%2$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੈ"</string>
     <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"ਇਹ ਡੀਵਾਈਸ ਤੁਹਾਡੀ ਸੰਸਥਾ ਨਾਲ ਸੰਬੰਧਿਤ ਹੈ"</string>
@@ -530,8 +528,7 @@
     <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"ਤੁਹਾਡਾ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ <xliff:g id="VPN_APP">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੈ"</string>
     <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"ਤੁਹਾਡਾ ਨਿੱਜੀ ਪ੍ਰੋਫਾਈਲ <xliff:g id="VPN_APP">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੈ"</string>
     <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"ਇਹ ਡੀਵਾਈਸ <xliff:g id="VPN_APP">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੈ"</string>
-    <!-- no translation found for monitoring_title_financed_device (3659962357973919387) -->
-    <skip />
+    <string name="monitoring_title_financed_device" msgid="3659962357973919387">"ਇਹ ਡੀਵਾਈਸ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ਵੱਲੋਂ ਮੁਹੱਈਆ ਕੀਤਾ ਗਿਆ ਹੈ"</string>
     <string name="monitoring_title_device_owned" msgid="7029691083837606324">"ਡੀਵਾਈਸ ਪ੍ਰਬੰਧਨ"</string>
     <string name="monitoring_title_profile_owned" msgid="6301118649405449568">"ਪ੍ਰੋਫਾਈਲ ਦਾ ਨਿਰੀਖਣ ਕਰਨਾ"</string>
     <string name="monitoring_title" msgid="4063890083735924568">"ਨੈੱਟਵਰਕ ਨਿਰੀਖਣ ਕਰ ਰਿਹਾ ਹੈ"</string>
@@ -543,8 +540,7 @@
     <string name="monitoring_button_view_policies" msgid="3869724835853502410">"ਨੀਤੀਆਂ ਦੇਖੋ"</string>
     <string name="monitoring_button_view_controls" msgid="8316440345340701117">"ਕੰਟਰੋਲ ਦੇਖੋ"</string>
     <string name="monitoring_description_named_management" msgid="505833016545056036">"ਇਹ ਡੀਵਾਈਸ <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ਨਾਲ ਸੰਬੰਧਿਤ ਹੈ।\n\nਤੁਹਾਡਾ ਆਈ.ਟੀ. ਪ੍ਰਸ਼ਾਸਕ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਨਾਲ ਸੰਬੰਧਿਤ ਸੈਟਿੰਗਾਂ, ਕਾਰਪੋਰੇਟ ਪਹੁੰਚ, ਐਪਾਂ, ਡਾਟੇ ਅਤੇ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੀ ਟਿਕਾਣਾ ਜਾਣਕਾਰੀ ਦੀ ਨਿਗਰਾਨੀ ਅਤੇ ਪ੍ਰਬੰਧਨ ਕਰ ਸਕਦਾ ਹੈ।\n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣੇ ਆਈ.ਟੀ. ਪ੍ਰਸ਼ਾਸਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
-    <!-- no translation found for monitoring_financed_description_named_management (6108439201399938668) -->
-    <skip />
+    <string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"<xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g> ਇਸ ਡੀਵਾਈਸ ਨਾਲ ਸੰਬੰਧਿਤ ਡਾਟੇ ਤੱਕ ਪਹੁੰਚ ਕਰ ਸਕਦੀ ਹੈ, ਐਪਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰ ਸਕਦੀ ਹੈ ਅਤੇ ਇਸ ਡੀਵਾਈਸ ਦੀਆਂ ਸੈਟਿੰਗਾਂ ਨੂੰ ਬਦਲ ਸਕਦੀ ਹੈ।\n\nਜੇ ਤੁਹਾਡਾ ਕੋਈ ਸਵਾਲ ਹੈ, ਤਾਂ <xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g> ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
     <string name="monitoring_description_management" msgid="4308879039175729014">"ਇਹ ਡੀਵਾਈਸ ਤੁਹਾਡੀ ਸੰਸਥਾ ਨਾਲ ਸੰਬੰਧਿਤ ਹੈ।\n\nਤੁਹਾਡਾ ਆਈ.ਟੀ. ਪ੍ਰਸ਼ਾਸਕ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਨਾਲ ਸੰਬੰਧਿਤ ਸੈਟਿੰਗਾਂ, ਕਾਰਪੋਰੇਟ ਪਹੁੰਚ, ਐਪਾਂ, ਡਾਟੇ ਅਤੇ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੀ ਟਿਕਾਣਾ ਜਾਣਕਾਰੀ ਦੀ ਨਿਗਰਾਨੀ ਅਤੇ ਪ੍ਰਬੰਧਨ ਕਰ ਸਕਦਾ ਹੈ।\n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣੇ ਆਈ.ਟੀ. ਪ੍ਰਸ਼ਾਸਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
     <string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਇੱਕ ਪ੍ਰਮਾਣ-ਪੱਤਰ ਅਥਾਰਟੀ ਸਥਾਪਤ ਕੀਤੀ ਗਈ ਹੈ। ਤੁਹਾਡੇ ਸੁਰੱਖਿਅਤ ਨੈੱਟਵਰਕ ਟਰੈਫਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ ਜਾਂ ਉਸਨੂੰ ਸੋਧਿਆ ਜਾ ਸਕਦਾ ਹੈ।"</string>
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਤੁਹਾਡੇ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਵਿੱਚ ਇੱਕ ਪ੍ਰਮਾਣ-ਪੱਤਰ ਅਥਾਰਟੀ ਸਥਾਪਤ ਕੀਤੀ ਗਈ ਹੈ। ਤੁਹਾਡੇ ਸੁਰੱਖਿਅਤ ਨੈੱਟਵਰਕ ਟਰੈਫਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ ਜਾਂ ਉਸਨੂੰ ਸੋਧਿਆ ਜਾ ਸਕਦਾ ਹੈ।"</string>
@@ -655,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"ਡੈਮੋ ਮੋਡ ਦੇਖੋ"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"ਈਥਰਨੈਟ"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"ਅਲਾਰਮ"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"ਵਾਲੇਟ"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"ਤਿਆਰ"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"ਹਵਾਈ-ਜਹਾਜ਼ ਮੋਡ"</string>
     <string name="add_tile" msgid="6239678623873086686">"ਟਾਇਲ ਸ਼ਾਮਲ ਕਰੋ"</string>
@@ -715,7 +709,7 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"ਸੂਚਨਾਵਾਂ ਬੰਦ ਕਰੋ"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"ਕੀ ਇਸ ਐਪ ਤੋਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਦਿਖਾਉਣਾ ਜਾਰੀ ਰੱਖਣਾ ਹੈ?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"ਸ਼ਾਂਤ"</string>
-    <string name="notification_alert_title" msgid="3656229781017543655">"ਪੂਰਵ-ਨਿਰਧਾਰਤ"</string>
+    <string name="notification_alert_title" msgid="3656229781017543655">"ਪੂਰਵ-ਨਿਰਧਾਰਿਤ"</string>
     <string name="notification_automatic_title" msgid="3745465364578762652">"ਸਵੈਚਲਿਤ"</string>
     <string name="notification_channel_summary_low" msgid="4860617986908931158">"ਕੋਈ ਧੁਨੀ ਜਾਂ ਥਰਥਰਾਹਟ ਨਹੀਂ"</string>
     <string name="notification_conversation_summary_low" msgid="1734433426085468009">"ਕੋਈ ਧੁਨੀ ਜਾਂ ਥਰਥਰਾਹਟ ਨਹੀਂ ਅਤੇ ਸੂਚਨਾਵਾਂ ਗੱਲਬਾਤ ਸੈਕਸ਼ਨ ਵਿੱਚ ਹੇਠਲੇ ਪਾਸੇ ਦਿਸਦੀਆਂ ਹਨ"</string>
@@ -905,8 +899,7 @@
     <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਨੂੰ ਬੰਦ ਕਰੋ।"</string>
     <string name="accessibility_quick_settings_alarm_set" msgid="7237918261045099853">"ਅਲਾਰਮ ਸੈੱਟ ਕੀਤਾ।"</string>
     <string name="accessibility_quick_settings_user" msgid="505821942882668619">"<xliff:g id="ID_1">%s</xliff:g> ਵਜੋਂ ਸਾਈਨ ਇਨ ਕੀਤਾ"</string>
-    <!-- no translation found for accessibility_quick_settings_choose_user_action (4554388498186576087) -->
-    <skip />
+    <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"ਵਰਤੋਂਕਾਰ ਚੁਣੋ"</string>
     <string name="data_connection_no_internet" msgid="691058178914184544">"ਇੰਟਰਨੈੱਟ ਨਹੀਂ।"</string>
     <string name="accessibility_quick_settings_open_details" msgid="4879279912389052142">"ਵੇਰਵੇ ਖੋਲ੍ਹੋ।"</string>
     <string name="accessibility_quick_settings_not_available" msgid="6860875849497473854">"<xliff:g id="REASON">%s</xliff:g> ਦੇ ਕਾਰਨ ਅਣਉਪਲਬਧ ਹੈ"</string>
@@ -1023,10 +1016,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ਪੂਰੀ ਸਕ੍ਰੀਨ ਨੂੰ ਵੱਡਦਰਸ਼ੀ ਕਰੋ"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ਸਕ੍ਰੀਨ ਦੇ ਹਿੱਸੇ ਨੂੰ ਵੱਡਾ ਕਰੋ"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"ਸਵਿੱਚ"</string>
-    <!-- no translation found for accessibility_floating_button_migration_tooltip (4431046858918714564) -->
-    <skip />
-    <!-- no translation found for accessibility_floating_button_docking_tooltip (6814897496767461517) -->
-    <skip />
+    <string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"ਪਹੁੰਚਯੋਗਤਾ ਬਟਨ ਨੂੰ ਪਹੁੰਚਯੋਗਤਾ ਸੰਕੇਤ ਨਾਲ ਬਦਲ ਦਿੱਤਾ ਗਿਆ\n\n"<annotation id="link">"ਸੈਟਿੰਗਾਂ ਦੇਖੋ"</annotation></string>
+    <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ਬਟਨ ਨੂੰ ਅਸਥਾਈ ਤੌਰ \'ਤੇ ਲੁਕਾਉਣ ਲਈ ਕਿਨਾਰੇ \'ਤੇ ਲਿਜਾਓ"</string>
     <string name="quick_controls_title" msgid="6839108006171302273">"ਡੀਵਾਈਸ ਕੰਟਰੋਲ"</string>
     <string name="quick_controls_subtitle" msgid="1667408093326318053">"ਆਪਣੇ ਕਨੈਕਟ ਕੀਤੇ ਡੀਵਾਈਸਾਂ ਲਈ ਕੰਟਰੋਲ ਸ਼ਾਮਲ ਕਰੋ"</string>
     <string name="quick_controls_setup_title" msgid="8901436655997849822">"ਡੀਵਾਈਸ ਕੰਟਰੋਲਾਂ ਦਾ ਸੈੱਟਅੱਪ ਕਰੋ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 6ac5d27..c936dc2 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -416,7 +416,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do wschodu słońca"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Włącz o <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Zmniejsz jasność"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"Komunikacja NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Komunikacja NFC jest wyłączona"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Komunikacja NFC jest włączona"</string>
@@ -658,10 +657,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Pokaż tryb demonstracyjny"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Portfel"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Gotowe"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Profil służbowy"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Tryb samolotowy"</string>
     <string name="add_tile" msgid="6239678623873086686">"Dodaj nazwę"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 3217028..a9c454e 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Até o nascer do sol"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Ativar: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Até: <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Reduzir brilho"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"A NFC está desativada"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"A NFC está ativada"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 8dec9dd..dde6906 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Até ao amanhecer"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Ativado à(s) <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Até à(s) <xliff:g id="TIME">%s</xliff:g>."</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Reduzir o brilho"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"O NFC está desativado"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"O NFC está ativado"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 3217028..a9c454e 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Até o nascer do sol"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Ativar: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Até: <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Reduzir brilho"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"A NFC está desativada"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"A NFC está ativada"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 5b82f0b..d9e48a1 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -414,7 +414,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Până la răsărit"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Activată la <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Până la <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Reduceți luminozitatea"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Serviciul NFC este dezactivat"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Serviciul NFC este activat"</string>
@@ -655,10 +654,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Afișați modul demonstrativ"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Alarmă"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Gata"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Profil de serviciu"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Mod Avion"</string>
     <string name="add_tile" msgid="6239678623873086686">"Adăugați o casetă"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index d59e469..2fb31e7 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -416,7 +416,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"До рассвета"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Включить в <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"До <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Уменьшение яркости"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"Модуль NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Модуль NFC отключен"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Модуль NFC включен"</string>
@@ -658,10 +657,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Перейти в демонстрационный режим"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Будильник"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Кошелек"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Готово"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Рабочий профиль"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Режим полета"</string>
     <string name="add_tile" msgid="6239678623873086686">"Добавить кнопку быстрого доступа"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 9172d50..3e393bf 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"හිරු නගින තෙක්"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>ට ක්‍රියාත්මකයි"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> තෙක්"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"දීප්තිය අඩු කරන්න"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC අබලයි"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC සබලයි"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 1dcf37e..bbca0db 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -416,7 +416,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do východu slnka"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Zapne sa o <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Zníženie jasu"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC je deaktivované"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC je aktivované"</string>
@@ -658,10 +657,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Zobraziť režim ukážky"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Budík"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Peňaženka"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Pripravené"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Pracovný profil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Režim v lietadle"</string>
     <string name="add_tile" msgid="6239678623873086686">"Pridať dlaždicu"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index edb94e3..def787f 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -416,7 +416,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do sončnega vzhoda"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Vklop ob <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Zmanjšanje svetlosti"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Tehnologija NFC je onemogočena"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Tehnologija NFC je omogočena"</string>
@@ -658,10 +657,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Prikaz predstavitvenega načina"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Opozorilo"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Denarnica"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Pripravljeno"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Profil za Android Work"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Način za letalo"</string>
     <string name="add_tile" msgid="6239678623873086686">"Dodajanje ploščice"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 2d84dfd..9e676c4 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Deri në lindje të diellit"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Aktiv në <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Deri në <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Redukto ndriçimin"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC është çaktivizuar"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC është aktivizuar"</string>
@@ -541,8 +540,7 @@
     <string name="monitoring_button_view_policies" msgid="3869724835853502410">"Shiko politikat"</string>
     <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Shiko kontrollet"</string>
     <string name="monitoring_description_named_management" msgid="505833016545056036">"Kjo pajisje i përket <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nAdministratori i teknologjisë së informacionit mund të monitorojë dhe menaxhojë cilësimet, qasjen e korporatës, aplikacionet, të dhënat e lidhura me pajisjen tënde, si dhe informacionet e vendndodhjes së pajisjes tënde.\n\nPër më shumë informacione, kontakto me administratorin e teknologjisë së informacionit."</string>
-    <!-- no translation found for monitoring_financed_description_named_management (6108439201399938668) -->
-    <skip />
+    <string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"<xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g> mund të arrijë të qaset te të dhënat e lidhura me këtë pajisje, të menaxhojë aplikacionet dhe të ndryshojë cilësimet e kësaj pajisjeje.\n\nNëse ke pyetje, kontakto me <xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g>."</string>
     <string name="monitoring_description_management" msgid="4308879039175729014">"Kjo pajisje i përket organizatës sate.\n\nAdministratori i teknologjisë së informacionit mund të monitorojë dhe menaxhojë cilësimet, qasjen e korporatës, aplikacionet, të dhënat e lidhura me pajisjen tënde, si dhe informacionet e vendndodhjes së pajisjes tënde.\n\nPër më shumë informacione, kontakto me administratorin e teknologjisë së informacionit."</string>
     <string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Organizata jote instaloi një autoritet certifikate në këtë pajisje. Trafiku i rrjetit tënd të sigurt mund të monitorohet ose modifikohet."</string>
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Organizata jote instaloi një autoritet certifikate në profilin tënd të punës. Trafiku i rrjetit tënd të sigurt mund të monitorohet ose modifikohet."</string>
@@ -653,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Shfaq modalitetin e demonstrimit"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Eternet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Alarmi"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Gati"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Profili i punës"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Modaliteti i aeroplanit"</string>
     <string name="add_tile" msgid="6239678623873086686">"Shto një pllakëz"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 0ba23f8..5fcb9c79 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -414,7 +414,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"До изласка сунца"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Укључује се у <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"До <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Смањите осветљеност"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC је онемогућен"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC је омогућен"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 59f290c..52d459b 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Till soluppgången"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Aktivera kl. <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Till <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Minska ljusstyrkan"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC är inaktiverat"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC är aktiverat"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Visa demoläge"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Klar"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Jobbprofil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Flygplansläge"</string>
     <string name="add_tile" msgid="6239678623873086686">"Lägg till en ruta"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 588231e..157c576 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Hadi macheo"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Itawashwa saa <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Hadi saa <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Punguza ung\'aavu"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC imezimwa"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC imewashwa"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Onyesha hali ya onyesho"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethaneti"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Kengele"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Tayari"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Wasifu wa kazini"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Hali ya ndegeni"</string>
     <string name="add_tile" msgid="6239678623873086686">"Ongeza kigae"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 511c457..fc632fd 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"காலை வரை"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>க்கு ஆன் செய்"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> வரை"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"ஒளிர்வைக் குறைத்தல்"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC முடக்கப்பட்டது"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC இயக்கப்பட்டது"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"டெமோ முறையைக் காட்டு"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"ஈதர்நெட்"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"அலாரம்"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"வாலட்"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"தயாராக உள்ளது"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"பணிக் கணக்கு"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"விமானப் பயன்முறை"</string>
     <string name="add_tile" msgid="6239678623873086686">"டைலைச் சேர்க்கும்"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 421f596..74326dc 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"సూర్యోదయం వరకు"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> కు ఆన్ అవుతుంది"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> వరకు"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"ప్రకాశాన్ని తగ్గించండి"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC నిలిపివేయబడింది"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ప్రారంభించబడింది"</string>
@@ -515,8 +514,7 @@
     <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ఈ పరికరాన్ని మీ తల్లి/తండ్రి మేనేజ్ చేస్తున్నారు"</string>
     <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"ఈ పరికరం మీ సంస్థకు చెందినది, కాబట్టి అది నెట్‌వర్క్ ట్రాఫిక్‌ను పర్యవేక్షించవచ్చు"</string>
     <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"మీ పరికరం <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>కు చెందినది, కాబట్టి అది నెట్‌వర్క్ ట్రాఫిక్‌ను పర్యవేక్షించవచ్చు"</string>
-    <!-- no translation found for quick_settings_financed_disclosure_named_management (2307703784594859524) -->
-    <skip />
+    <string name="quick_settings_financed_disclosure_named_management" msgid="2307703784594859524">"ఈ పరికరం <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ద్వారా అందించబడింది"</string>
     <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"ఈ పరికరం మీ సంస్థకు చెందినది, ఇది <xliff:g id="VPN_APP">%1$s</xliff:g>కు కనెక్ట్ అయి ఉంది"</string>
     <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"ఈ పరికరం <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>కు చెందినది, ఇది <xliff:g id="VPN_APP">%2$s</xliff:g>కు కనెక్ట్ అయి ఉంది"</string>
     <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"ఈ పరికరం మీ సంస్థకు చెందినది"</string>
@@ -530,8 +528,7 @@
     <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"మీ వర్క్ ప్రొఫైల్ <xliff:g id="VPN_APP">%1$s</xliff:g>కు కనెక్ట్ చేయబడింది"</string>
     <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"<xliff:g id="VPN_APP">%1$s</xliff:g>కు మీ వ్యక్తిగత ప్రొఫైల్ కనెక్ట్ చేయబడింది"</string>
     <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"ఈ పరికరం <xliff:g id="VPN_APP">%1$s</xliff:g>కు కనెక్ట్ అయి ఉంది"</string>
-    <!-- no translation found for monitoring_title_financed_device (3659962357973919387) -->
-    <skip />
+    <string name="monitoring_title_financed_device" msgid="3659962357973919387">"ఈ పరికరం <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ద్వారా అందించబడింది"</string>
     <string name="monitoring_title_device_owned" msgid="7029691083837606324">"పరికర నిర్వహణ"</string>
     <string name="monitoring_title_profile_owned" msgid="6301118649405449568">"ప్రొఫైల్ పర్యవేక్షణ"</string>
     <string name="monitoring_title" msgid="4063890083735924568">"నెట్‌వర్క్ పర్యవేక్షణ"</string>
@@ -543,8 +540,7 @@
     <string name="monitoring_button_view_policies" msgid="3869724835853502410">"విధానాలను వీక్షించండి"</string>
     <string name="monitoring_button_view_controls" msgid="8316440345340701117">"నియంత్రణలను చూడండి"</string>
     <string name="monitoring_description_named_management" msgid="505833016545056036">"ఈ పరికరం <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>కు చెందినది.\n\nసెట్టింగ్‌లను, కార్పొరేట్ యాక్సెస్‌ను, యాప్‌లను, మీ పరికరానికి సంబంధించిన డేటాను, అలాగే మీ పరికరం యొక్క లొకేషన్ సమాచారాన్ని మీ IT అడ్మిన్ పర్యవేక్షించగలరు, మేనేజ్ చేయగలరు.\n\nమరింత సమాచారం కోసం, మీ IT అడ్మిన్‌ను సంప్రదించండి."</string>
-    <!-- no translation found for monitoring_financed_description_named_management (6108439201399938668) -->
-    <skip />
+    <string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"<xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g>, ఈ పరికరంతో అనుబంధించబడిన డేటాను యాక్సెస్ చేయవచ్చు, యాప్‌లను మేనేజ్ చేయవచ్చు అలాగే ఈ పరికరాల సెట్టింగ్‌లను మార్చవచ్చు.\n\nమీకు ఏవైనా సందేహాలు ఉంటే, <xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g>ను కాంటాక్ట్ చేయండి."</string>
     <string name="monitoring_description_management" msgid="4308879039175729014">"ఈ పరికరం మీ సంస్థకు చెందినది.\n\nసెట్టింగ్‌లను, కార్పొరేట్ యాక్సెస్‌ను, యాప్‌లను, మీ పరికరానికి సంబంధించిన డేటాను, అలాగే మీ పరికరం యొక్క లొకేషన్ సమాచారాన్ని మీ IT అడ్మిన్ పర్యవేక్షించగలరు, మేనేజ్ చేయగలరు.\n\nమరింత సమాచారం కోసం, మీ IT అడ్మిన్‌ను సంప్రదించండి."</string>
     <string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"ఈ పరికరంలో మీ సంస్థ ఒక ప్రమాణపత్ర అధికారాన్ని ఇన్‌స్టాల్ చేసింది. మీ సురక్షిత నెట్‌వర్క్ ట్రాఫిక్ పర్యవేక్షించబడవచ్చు లేదా సవరించబడవచ్చు."</string>
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"మీ కార్యాలయ ప్రొఫైల్‌లో మీ సంస్థ ఒక ప్రమాణపత్ర అధికారాన్ని ఇన్‌స్టాల్ చేసింది. మీ సురక్షిత నెట్‌వర్క్ ట్రాఫిక్ పర్యవేక్షించబడవచ్చు లేదా సవరించబడవచ్చు."</string>
@@ -655,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"డెమో మోడ్ చూపు"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"ఈథర్‌నెట్"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"అలారం"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"సిద్ధంగా ఉంది"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"కార్యాలయ ప్రొఫైల్‌"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"ఎయిర్‌ప్లేన్ మోడ్"</string>
     <string name="add_tile" msgid="6239678623873086686">"టైల్‌ను జోడించండి"</string>
@@ -766,7 +760,7 @@
     <string name="notification_conversation_unmute" msgid="2692255619510896710">"అలర్ట్ చేయడం"</string>
     <string name="notification_conversation_bubble" msgid="2242180995373949022">"బబుల్‌ను చూపించు"</string>
     <string name="notification_conversation_unbubble" msgid="6908427185031099868">"బబుల్స్ తీసివేయి"</string>
-    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"హోమ్ స్క్రీన్‌కు జోడించు"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"హోమ్ స్క్రీన్‌కు జోడించండి"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"నోటిఫికేషన్ నియంత్రణలు"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"నోటిఫికేషన్ తాత్కాలిక ఆపివేత ఎంపికలు"</string>
@@ -905,8 +899,7 @@
     <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"శీఘ్ర సెట్టింగ్‌లను మూసివేయండి."</string>
     <string name="accessibility_quick_settings_alarm_set" msgid="7237918261045099853">"అలారం సెట్ చేయబడింది."</string>
     <string name="accessibility_quick_settings_user" msgid="505821942882668619">"<xliff:g id="ID_1">%s</xliff:g> వలె సైన్ ఇన్ చేసారు"</string>
-    <!-- no translation found for accessibility_quick_settings_choose_user_action (4554388498186576087) -->
-    <skip />
+    <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"యూజర్‌ను ఎంపిక చేయండి"</string>
     <string name="data_connection_no_internet" msgid="691058178914184544">"ఇంటర్నెట్ లేదు"</string>
     <string name="accessibility_quick_settings_open_details" msgid="4879279912389052142">"వివరాలను తెరవండి."</string>
     <string name="accessibility_quick_settings_not_available" msgid="6860875849497473854">"<xliff:g id="REASON">%s</xliff:g> కారణంగా అందుబాటులో లేదు"</string>
@@ -1023,10 +1016,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ఫుల్ స్క్రీన్‌ను మ్యాగ్నిఫై చేయండి"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"స్క్రీన్‌లో భాగాన్ని మాగ్నిఫై చేయండి"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"స్విచ్ చేయి"</string>
-    <!-- no translation found for accessibility_floating_button_migration_tooltip (4431046858918714564) -->
-    <skip />
-    <!-- no translation found for accessibility_floating_button_docking_tooltip (6814897496767461517) -->
-    <skip />
+    <string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"యాక్సెసిబిలిటీ బటన్, యాక్సెసిబిలిటీ సంజ్ఞను భర్తీ చేసింది\n\n"<annotation id="link">"సెట్టింగ్‌లను చూడండి"</annotation></string>
+    <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"తాత్కాలికంగా దానిని దాచడానికి బటన్‌ను చివరకు తరలించండి"</string>
     <string name="quick_controls_title" msgid="6839108006171302273">"పరికరం నియంత్రణలు"</string>
     <string name="quick_controls_subtitle" msgid="1667408093326318053">"మీ కనెక్ట్ అయిన పరికరాలకు నియంత్రణలను జోడించండి"</string>
     <string name="quick_controls_setup_title" msgid="8901436655997849822">"పరికరం నియంత్రణలను సెటప్ చేయడం"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 4e01555..2635418 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"จนพระอาทิตย์ขึ้น"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"เปิดเวลา <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"จนถึง <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"ลดความสว่าง"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ถูกปิดใช้งาน"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"เปิดใช้งาน NFC แล้ว"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"แสดงโหมดสาธิต"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"อีเทอร์เน็ต"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"การปลุก"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"พร้อม"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"โปรไฟล์งาน"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"โหมดบนเครื่องบิน"</string>
     <string name="add_tile" msgid="6239678623873086686">"เพิ่มไทล์"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 789c083..57e289f 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Hanggang sunrise"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Ma-o-on nang <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Hanggang <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Bawasan ang liwanag"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Naka-disable ang NFC"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Naka-enable ang NFC"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Ipakita ang demo mode"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Alarma"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Handa na"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Profile sa trabaho"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Airplane mode"</string>
     <string name="add_tile" msgid="6239678623873086686">"Magdagdag ng tile"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index b236418..a36c8d24 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Sabaha kadar"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Açılacağı saat: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Şu saate kadar: <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Parlaklığı azalt"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC devre dışı"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC etkin"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Demo modunu göster"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Cüzdan"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Hazır"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"İş profili"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Uçak modu"</string>
     <string name="add_tile" msgid="6239678623873086686">"Blok ekle"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index bcff82f..f7923eb 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -416,7 +416,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"До сходу сонця"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Вмикається о <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"До <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Зменшення яскравості"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC вимкнено"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ввімкнено"</string>
@@ -658,10 +657,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Показати демонстраційний режим"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Сигнал"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Гаманець"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Готово"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Робочий профіль"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Режим польоту"</string>
     <string name="add_tile" msgid="6239678623873086686">"Додавання опції"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 7590a50..548784d 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"طلوع آفتاب تک"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"آن ہوگی بوقت <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> تک"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"چمک کم کریں"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"‏NFC غیر فعال ہے"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"‏NFC فعال ہے"</string>
@@ -541,8 +540,7 @@
     <string name="monitoring_button_view_policies" msgid="3869724835853502410">"پالیسیاں دیکھیں"</string>
     <string name="monitoring_button_view_controls" msgid="8316440345340701117">"کنٹرولز دیکھیں"</string>
     <string name="monitoring_description_named_management" msgid="505833016545056036">"‏یہ آلہ <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> کا ہے۔\n\nآپ کا IT منتظم ترتیبات، کارپوریٹ رسائی، ایپس، آپ کے آلہ سے وابستہ ڈیٹا اور آپ کے آلہ کے مقام کی معلومات کی نگرانی اور ان کا نظم کر سکتا ہے۔\n\nمزید معلومات کے لیے اپنے IT منتظم سے رابطہ کریں۔"</string>
-    <!-- no translation found for monitoring_financed_description_named_management (6108439201399938668) -->
-    <skip />
+    <string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"<xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g> اس آلے سے وابستہ ڈیٹا تک رسائی حاصل، ایپس کا نظم اور ان آلات کی ترتیبات کو تبدیل کر سکتا ہے۔\n\nاگر آپ سوالات پوچھنا چاہتے ہیں تو <xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g> سے رابطہ کریں۔"</string>
     <string name="monitoring_description_management" msgid="4308879039175729014">"‏یہ آلہ آپ کی تنظیم کا ہے۔\n\nآپ کا IT منتظم ترتیبات، کارپوریٹ رسائی، ایپس، آپ کے آلہ سے وابستہ ڈیٹا اور آپ کے آلہ کے مقام کی معلومات کی نگرانی اور ان کا نظم کر سکتا ہے۔\n\nمزید معلومات کے لیے اپنے IT منتظم سے رابطہ کریں۔"</string>
     <string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"آپ کی تنظیم نے اس آلے پر ایک سرٹیفکیٹ کی اتھارٹی کو انسٹال کیا ہے۔ آپ کا محفوظ نیٹ ورک ٹریفک مانیٹر ہو سکتا ہے یا اس میں ترمیم کی جا سکتی ہے۔"</string>
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"آپ کی تنظیم نے آپ کے دفتری پروفائل میں ایک سرٹیفکیٹ کی اتھارٹی کو انسٹال کیا ہے۔ آپ کا محفوظ نیٹ ورک ٹریفک مانیٹر ہو سکتا ہے یا اس میں ترمیم کی جا سکتی ہے۔"</string>
@@ -653,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"ڈیمو موڈ دکھائیں"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"ایتھرنیٹ"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"الارم"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"تیار ہے"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"دفتری پروفائل"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"ہوائی جہاز وضع"</string>
     <string name="add_tile" msgid="6239678623873086686">"ٹائل شامل کریں"</string>
@@ -1017,8 +1013,7 @@
     <string name="accessibility_control_move_left" msgid="8156206978511401995">"بائیں منتقل کریں"</string>
     <string name="accessibility_control_move_right" msgid="8926821093629582888">"دائیں منتقل کریں"</string>
     <string name="magnification_mode_switch_description" msgid="2698364322069934733">"میگنیفکیشن پر سوئچ کریں"</string>
-    <!-- no translation found for magnification_mode_switch_state_full_screen (5229653514979530561) -->
-    <skip />
+    <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"فُل اسکرین کو بڑا کریں"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"اسکرین کا حصہ بڑا کریں"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"سوئچ کریں"</string>
     <string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"ایکسیسبیلٹی بٹن کو ایکسیسبیلٹی اشارے سے بدل دیا گیا\n\n"<annotation id="link">"ترتیبات دیکھیں"</annotation></string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index eace130..42da6f5 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Quyosh chiqqunicha"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> da yoqiladi"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> gacha"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Yorqinlikni pasaytirish"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC o‘chiq"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC yoniq"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Demo rejimni ko‘rsatish"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Signal"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Tayyor"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Ish profili"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Parvoz rejimi"</string>
     <string name="add_tile" msgid="6239678623873086686">"Tezkor sozlamalar tugmasini qo‘shish"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 4640aa4..a137a12 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Cho đến khi trời sáng"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Bật vào lúc <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Cho đến <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Giảm độ sáng"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC đã được tắt"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC đã được bật"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Hiển thị chế độ trình diễn"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Báo thức"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"Ví"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Sẵn sàng"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Hồ sơ công việc"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Chế độ máy bay"</string>
     <string name="add_tile" msgid="6239678623873086686">"Thêm ô"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 236879a..b78569c 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"在日出时关闭"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"在<xliff:g id="TIME">%s</xliff:g> 开启"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"直到<xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"调低亮度"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC 已停用"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC 已启用"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"显示演示模式"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"以太网"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"闹钟"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"电子钱包"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"已可使用"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"工作资料"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"飞行模式"</string>
     <string name="add_tile" msgid="6239678623873086686">"添加图块"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index c204ffd..f5481df 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"在日出時關閉"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"於<xliff:g id="TIME">%s</xliff:g>開啟"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"直至<xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"調低亮度"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC 已停用"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC 已啟用"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"顯示示範模式"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"以太網"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"鬧鐘"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"電子錢包"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"已可使用"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"工作設定檔"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"飛行模式"</string>
     <string name="add_tile" msgid="6239678623873086686">"加入圖塊"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index fedd3c06..b7cbed1 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"於日出時關閉"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"開啟時間:<xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"關閉時間:<xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"調低亮度"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC 已停用"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC 已啟用"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"顯示示範模式"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"乙太網路"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"鬧鐘"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"電子錢包"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"已可使用"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"工作資料夾"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"飛航模式"</string>
     <string name="add_tile" msgid="6239678623873086686">"新增圖塊"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index aa95cfa..c095383 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -412,7 +412,6 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Kuze kube sekuphumeni kwelanga"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Kuvulwe ngo-<xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Kuze kube ngu-<xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Nciphisa ukukhanya"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"I-NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"I-NFC ikhutshaziwe"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"I-NFC inikwe amandla"</string>
@@ -652,10 +651,8 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Bonisa imodi yedemo"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"I-Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"I-alamu"</string>
-    <!-- no translation found for wallet_title (5369767670735827105) -->
-    <skip />
-    <!-- no translation found for wallet_secondary_label (2017028770884957543) -->
-    <skip />
+    <string name="wallet_title" msgid="5369767670735827105">"I-wallet"</string>
+    <string name="wallet_secondary_label" msgid="2017028770884957543">"Isikulungele"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Iphrofayela yomsebenzi"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Imodi yendiza"</string>
     <string name="add_tile" msgid="6239678623873086686">"Engeza ithayili"</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index a773b22..7a6de75 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -151,8 +151,8 @@
     <color name="minimize_dock_shadow_end">#00000000</color>
 
     <color name="default_remote_input_background">@*android:color/notification_default_color</color>
-    <color name="remote_input_hint">#99ffffff</color>
-
+    <color name="notif_pill_background">@android:color/system_neutral2_100</color>
+    <color name="notif_pill_text">@android:color/system_neutral1_900</color>
     <color name="remote_input_accent">?android:attr/colorAccent</color>
 
     <color name="quick_step_track_background_background_dark">#1F000000</color>
@@ -272,8 +272,7 @@
     <color name="screenrecord_status_color">#E94235</color>
 
     <!-- TODO(b/178093014) Colors for privacy dialog. These should be changed to the new palette -->
-    <color name="privacy_circle_camera">#1E8E3E</color> <!-- g600 -->
-    <color name="privacy_circle_microphone_location">#E8710A</color> <!--o600 -->
+    <color name="privacy_circle">#1E8E3E</color> <!-- g600 -->
 
     <!-- Accessibility floating menu -->
     <color name="accessibility_floating_menu_background">#CCFFFFFF</color> <!-- 80% -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index d5c6398..be00594 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -19,6 +19,8 @@
     <!-- Recommended minimum clickable element dimension -->
     <dimen name="min_clickable_item_size">48dp</dimen>
 
+    <dimen name="remote_input_view_text_stroke">3dp</dimen>
+
     <!-- Amount to offset bottom of notification peek window from top of status bar. -->
     <dimen name="peek_window_y_offset">-12dp</dimen>
 
diff --git a/packages/SystemUI/res/values/flags.xml b/packages/SystemUI/res/values/flags.xml
index 52a97b1..2f3fbe7 100644
--- a/packages/SystemUI/res/values/flags.xml
+++ b/packages/SystemUI/res/values/flags.xml
@@ -45,8 +45,6 @@
 
     <bool name="flag_toast_style">false</bool>
 
-    <bool name="flag_navigation_bar_overlay">false</bool>
-
     <bool name="flag_pm_lite">false</bool>
 
     <bool name="flag_alarm_tile">false</bool>
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java b/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java
index c7ad3e8..47b41f5 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java
@@ -37,6 +37,7 @@
     public static final int GENERIC = 7;
     public static final int BOUNCER_UNLOCK = 8;
     public static final int PULSE_EXPAND = 9;
+    public static final int BRIGHTNESS_SLIDER = 10;
 
     @IntDef({
             QUICK_SETTINGS,
@@ -48,7 +49,8 @@
             RIGHT_AFFORDANCE,
             GENERIC,
             BOUNCER_UNLOCK,
-            PULSE_EXPAND
+            PULSE_EXPAND,
+            BRIGHTNESS_SLIDER
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface InteractionType {}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java
index 5a9c386..80d7863 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java
@@ -148,6 +148,10 @@
     Result calculateFalsingResult(
             @Classifier.InteractionType int interactionType,
             double historyBelief, double historyConfidence) {
+        if (interactionType == Classifier.BRIGHTNESS_SLIDER) {
+            return Result.passed(0);
+        }
+
         return !getPassedFlingThreshold() ? falsed(0.5, getReason()) : Result.passed(0.5);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java
index ac330f0..6f80010 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java
@@ -17,6 +17,7 @@
 package com.android.systemui.classifier;
 
 import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_PROXIMITY_PERCENT_COVERED_THRESHOLD;
+import static com.android.systemui.classifier.Classifier.BRIGHTNESS_SLIDER;
 import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS;
 
 import android.provider.DeviceConfig;
@@ -115,7 +116,7 @@
     Result calculateFalsingResult(
             @Classifier.InteractionType int interactionType,
             double historyBelief, double historyConfidence) {
-        if (interactionType == QUICK_SETTINGS) {
+        if (interactionType == QUICK_SETTINGS || interactionType == BRIGHTNESS_SLIDER) {
             return Result.passed(0);
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java
index 427c2ef..f665565 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java
@@ -18,6 +18,7 @@
 
 
 import static com.android.systemui.classifier.Classifier.BOUNCER_UNLOCK;
+import static com.android.systemui.classifier.Classifier.BRIGHTNESS_SLIDER;
 import static com.android.systemui.classifier.Classifier.LEFT_AFFORDANCE;
 import static com.android.systemui.classifier.Classifier.NOTIFICATION_DISMISS;
 import static com.android.systemui.classifier.Classifier.NOTIFICATION_DRAG_DOWN;
@@ -45,6 +46,7 @@
         boolean up = isUp();
         boolean right = isRight();
 
+        double confidence = 1;
         boolean wrongDirection = true;
         switch (interactionType) {
             case QUICK_SETTINGS:
@@ -52,6 +54,11 @@
             case NOTIFICATION_DRAG_DOWN:
                 wrongDirection = !vertical || up;
                 break;
+            case BRIGHTNESS_SLIDER:
+                confidence = 0;  // Owners may return to original brightness.
+                // A more sophisticated thing to do here would be to look at the size of the
+                // vertical change relative to the screen size. _Some_ amount of vertical
+                // change should be expected.
             case NOTIFICATION_DISMISS:
                 wrongDirection = vertical;
                 break;
@@ -70,7 +77,7 @@
                 break;
         }
 
-        return wrongDirection ? falsed(1, getReason(interactionType)) : Result.passed(0.5);
+        return wrongDirection ? falsed(confidence, getReason(interactionType)) : Result.passed(0.5);
     }
 
     private String getReason(int interactionType) {
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java
index 1d413af..d9197ef 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java
@@ -20,6 +20,7 @@
 import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_ZIGZAG_X_SECONDARY_DEVIANCE;
 import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_ZIGZAG_Y_PRIMARY_DEVIANCE;
 import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_ZIGZAG_Y_SECONDARY_DEVIANCE;
+import static com.android.systemui.classifier.Classifier.BRIGHTNESS_SLIDER;
 
 import android.graphics.Point;
 import android.provider.DeviceConfig;
@@ -87,6 +88,10 @@
     Result calculateFalsingResult(
             @Classifier.InteractionType int interactionType,
             double historyBelief, double historyConfidence) {
+        if (interactionType == BRIGHTNESS_SLIDER) {
+            return Result.passed(0);
+        }
+
         List<MotionEvent> motionEvents = getRecentMotionEvents();
         // Rotate horizontal gestures to be horizontal between their first and last point.
         // Rotate vertical gestures to be vertical between their first and last point.
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 04b4670..aa66b75 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -531,9 +531,13 @@
         Assert.isMainThread();
         mDozeHost.extendPulse(reason);
 
+        // we can't determine the dozing state if we're currently transitioning
+        final DozeMachine.State dozeState =
+                mMachine.isExecutingTransition() ? null : mMachine.getState();
+
         // When already pulsing we're allowed to show the wallpaper directly without
         // requesting a new pulse.
-        if (mMachine.getState() == DozeMachine.State.DOZE_PULSING
+        if (dozeState == DozeMachine.State.DOZE_PULSING
                 && reason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) {
             mMachine.requestState(DozeMachine.State.DOZE_PULSING_BRIGHT);
             return;
@@ -541,8 +545,7 @@
 
         if (mPulsePending || !mAllowPulseTriggers || !canPulse()) {
             if (mAllowPulseTriggers) {
-                mDozeLog.tracePulseDropped(mPulsePending, mMachine.getState(),
-                        mDozeHost.isPulsingBlocked());
+                mDozeLog.tracePulseDropped(mPulsePending, dozeState, mDozeHost.isPulsingBlocked());
             }
             runIfNotNull(onPulseSuppressedListener);
             return;
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarOverlayController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarOverlayController.java
index 62b9458..2d0d5cd 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarOverlayController.java
@@ -21,7 +21,6 @@
 import android.view.View;
 
 import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.statusbar.FeatureFlags;
 
 import java.util.function.Consumer;
 
@@ -32,12 +31,10 @@
 public class NavigationBarOverlayController {
 
     protected final Context mContext;
-    protected final FeatureFlags mFeatureFlags;
 
     @Inject
-    public NavigationBarOverlayController(Context context, FeatureFlags featureFlags) {
+    public NavigationBarOverlayController(Context context) {
         mContext = context;
-        mFeatureFlags = featureFlags;
     }
 
     public Context getContext() {
@@ -45,7 +42,7 @@
     }
 
     public boolean isNavigationBarOverlayEnabled() {
-        return mFeatureFlags.isNavigationBarOverlayEnabled();
+        return false;
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
index bdd37fc..9cd97ff8 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
@@ -33,8 +33,6 @@
     private var iconMargin = 0
     private var iconSize = 0
     private var iconColor = 0
-    private var defaultBackgroundColor = 0
-    private var cameraBackgroundColor = 0
 
     private lateinit var iconsContainer: LinearLayout
 
@@ -75,11 +73,6 @@
         if (!privacyList.isEmpty()) {
             generateContentDescription(builder)
             setIcons(builder, iconsContainer)
-            if (builder.types.contains(PrivacyType.TYPE_CAMERA)) {
-                iconsContainer.background.setTint(cameraBackgroundColor)
-            } else {
-                iconsContainer.background.setTint(defaultBackgroundColor)
-            }
         } else {
             iconsContainer.removeAllViews()
         }
@@ -99,8 +92,6 @@
                 .getDimensionPixelSize(R.dimen.ongoing_appops_chip_icon_size)
         iconColor =
                 Utils.getColorAttrDefaultColor(context, com.android.internal.R.attr.colorPrimary)
-        defaultBackgroundColor = context.getColor(R.color.privacy_circle_microphone_location)
-        cameraBackgroundColor = context.getColor(R.color.privacy_circle_camera)
 
         val padding = context.resources
                 .getDimensionPixelSize(R.dimen.ongoing_appops_chip_side_padding)
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java
index 0b40e22..5d964a4 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java
@@ -27,7 +27,10 @@
 import androidx.annotation.Nullable;
 
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.systemui.Gefingerpoken;
 import com.android.systemui.R;
+import com.android.systemui.classifier.Classifier;
+import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.statusbar.policy.BrightnessMirrorController;
 import com.android.systemui.util.ViewController;
 
@@ -42,9 +45,7 @@
  *
  * @see BrightnessMirrorController
  */
-public class BrightnessSlider
-        extends ViewController<View>
-        implements ToggleSlider {
+public class BrightnessSlider extends ViewController<View> implements ToggleSlider {
 
     private Listener mListener;
     private ToggleSlider mMirror;
@@ -52,15 +53,34 @@
     private BrightnessMirrorController mMirrorController;
     private boolean mTracking;
     private final boolean mUseMirror;
+    private final FalsingManager mFalsingManager;
+
+    private final Gefingerpoken mOnInterceptListener = new Gefingerpoken() {
+        @Override
+        public boolean onInterceptTouchEvent(MotionEvent ev) {
+            int action = ev.getActionMasked();
+            if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+                mFalsingManager.isFalseTouch(Classifier.BRIGHTNESS_SLIDER);
+            }
+
+            return false;
+        }
+
+        @Override
+        public boolean onTouchEvent(MotionEvent ev) {
+            return false;
+        }
+    };
 
     BrightnessSlider(
             View rootView,
             BrightnessSliderView brightnessSliderView,
-            boolean useMirror
-    ) {
+            boolean useMirror,
+            FalsingManager falsingManager) {
         super(rootView);
         mBrightnessSliderView = brightnessSliderView;
         mUseMirror = useMirror;
+        mFalsingManager = falsingManager;
     }
 
     /**
@@ -78,6 +98,7 @@
     protected void onViewAttached() {
         mBrightnessSliderView.setOnSeekBarChangeListener(mSeekListener);
         mBrightnessSliderView.setOnCheckedChangeListener(mCheckListener);
+        mBrightnessSliderView.setOnInterceptListener(mOnInterceptListener);
     }
 
     @Override
@@ -85,6 +106,7 @@
         mBrightnessSliderView.setOnSeekBarChangeListener(null);
         mBrightnessSliderView.setOnCheckedChangeListener(null);
         mBrightnessSliderView.setOnDispatchTouchEventListener(null);
+        mBrightnessSliderView.setOnInterceptListener(null);
     }
 
     @Override
@@ -247,10 +269,12 @@
     public static class Factory {
 
         BrightnessControllerSettings mSettings;
+        private final FalsingManager mFalsingManager;
 
         @Inject
-        public Factory(BrightnessControllerSettings settings) {
+        public Factory(BrightnessControllerSettings settings, FalsingManager falsingManager) {
             mSettings = settings;
+            mFalsingManager = falsingManager;
         }
 
         /**
@@ -270,7 +294,7 @@
         private BrightnessSlider fromTree(ViewGroup root, boolean useMirror) {
             BrightnessSliderView v = root.requireViewById(R.id.brightness_slider);
 
-            return new BrightnessSlider(root, v, useMirror);
+            return new BrightnessSlider(root, v, useMirror, mFalsingManager);
         }
 
         /** Get the layout to inflate based on what slider to use */
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
index cbf4e88..5b71c62 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
@@ -31,6 +31,7 @@
 import androidx.annotation.Nullable;
 
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.systemui.Gefingerpoken;
 import com.android.systemui.R;
 
 /**
@@ -54,6 +55,7 @@
     private TextView mLabel;
     private final CharSequence mText;
     private DispatchTouchEventListener mListener;
+    private Gefingerpoken mOnInterceptListener;
 
     public BrightnessSliderView(Context context) {
         this(context, null);
@@ -105,6 +107,15 @@
         return super.dispatchTouchEvent(ev);
     }
 
+    @Override
+    public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
+        // We prevent disallowing on this view, but bubble it up to our parents.
+        // We need interception to handle falsing.
+        if (mParent != null) {
+            mParent.requestDisallowInterceptTouchEvent(disallowIntercept);
+        }
+    }
+
     /**
      * Attaches a listener to the {@link ToggleSeekBar} in the view so changes can be observed
      * @param seekListener use {@code null} to remove listener
@@ -195,6 +206,18 @@
         return mSlider.getProgress();
     }
 
+    public void setOnInterceptListener(Gefingerpoken onInterceptListener) {
+        mOnInterceptListener = onInterceptListener;
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        if (mOnInterceptListener != null) {
+            return mOnInterceptListener.onInterceptTouchEvent(ev);
+        }
+        return super.onInterceptTouchEvent(ev);
+    }
+
     /**
      * Interface to attach a listener for {@link View#dispatchTouchEvent}.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
index 708bdfe..90c3dfc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
@@ -87,10 +87,6 @@
         return mFlagReader.isEnabled(R.bool.flag_wallet);
     }
 
-    public boolean isNavigationBarOverlayEnabled() {
-        return mFlagReader.isEnabled(R.bool.flag_navigation_bar_overlay);
-    }
-
     public boolean isPMLiteEnabled() {
         return mFlagReader.isEnabled(R.bool.flag_pm_lite);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
index 609ca97c..3728388 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
@@ -25,7 +25,6 @@
 import android.graphics.RectF;
 import android.util.AttributeSet;
 import android.view.View;
-import android.view.ViewGroup;
 import android.view.ViewOutlineProvider;
 
 import com.android.systemui.R;
@@ -102,28 +101,6 @@
         }
     };
 
-    /**
-     * Get the relative start padding of a view relative to this view. This recursively walks up the
-     * hierarchy and does the corresponding measuring.
-     *
-     * @param view the view to get the padding for. The requested view has to be a child of this
-     *             notification.
-     * @return the start padding
-     */
-    public int getRelativeStartPadding(View view) {
-        boolean isRtl = isLayoutRtl();
-        int startPadding = 0;
-        while (view.getParent() instanceof ViewGroup) {
-            View parent = (View) view.getParent();
-            startPadding += isRtl ? parent.getWidth() - view.getRight() : view.getLeft();
-            view = parent;
-            if (view == this) {
-                return startPadding;
-            }
-        }
-        return startPadding;
-    }
-
     protected Path getClipPath(boolean ignoreTranslation) {
         int left;
         int top;
@@ -132,17 +109,15 @@
         int height;
         float topRoundness = mAlwaysRoundBothCorners
                 ? mOutlineRadius : getCurrentBackgroundRadiusTop();
-
         if (!mCustomOutline) {
-            // Extend left/right clip bounds beyond the notification by the
-            // 1) space between the notification and edge of screen
-            // 2) corner radius (so we do not see any rounding as the notification goes off screen)
-            left = (int) (-getRelativeStartPadding(this) - mOutlineRadius);
-            right = (int) (((View) getParent()).getWidth() + mOutlineRadius);
-
+            int translation = mShouldTranslateContents && !ignoreTranslation
+                    ? (int) getTranslation() : 0;
+            int halfExtraWidth = (int) (mExtraWidthForClipping / 2.0f);
+            left = Math.max(translation, 0) - halfExtraWidth;
+            top = mClipTopAmount + mBackgroundTop;
+            right = getWidth() + halfExtraWidth + Math.min(translation, 0);
             // If the top is rounded we want the bottom to be at most at the top roundness, in order
             // to avoid the shadow changing when scrolling up.
-            top = mClipTopAmount + mBackgroundTop;
             bottom = Math.max(mMinimumHeightForClipping,
                     Math.max(getActualHeight() - mClipBottomAmount, (int) (top + topRoundness)));
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
index 1086d67..73e0804 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
@@ -69,8 +69,6 @@
     private float mContentTranslation;
     protected boolean mLastInSection;
     protected boolean mFirstInSection;
-    private float mOutlineRadius;
-    private float mParentWidth;
 
     public ExpandableView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -81,7 +79,6 @@
     private void initDimens() {
         mContentShift = getResources().getDimensionPixelSize(
                 R.dimen.shelf_transform_content_shift);
-        mOutlineRadius = getResources().getDimensionPixelSize(R.dimen.notification_corner_radius);
     }
 
     @Override
@@ -153,9 +150,6 @@
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
-        if (getParent() != null) {
-            mParentWidth = ((View) getParent()).getWidth();
-        }
         updateClipping();
     }
 
@@ -442,15 +436,11 @@
 
     protected void updateClipping() {
         if (mClipToActualHeight && shouldClipToActualHeight()) {
-            final int top = getClipTopAmount();
-            final int bottom = Math.max(Math.max(getActualHeight() + getExtraBottomPadding()
+            int top = getClipTopAmount();
+            int bottom = Math.max(Math.max(getActualHeight() + getExtraBottomPadding()
                     - mClipBottomAmount, top), mMinimumHeightForClipping);
-            // Extend left/right clip bounds beyond the notification by the
-            // 1) space between the notification and edge of screen
-            // 2) corner radius (so we do not see any rounding as the notification goes off screen)
-            final int left = (int) (-getRelativeStartPadding(this) - mOutlineRadius);
-            final int right = (int) (mParentWidth + mOutlineRadius);
-            mClipRect.set(left, top, right, bottom);
+            int halfExtraWidth = (int) (mExtraWidthForClipping / 2.0f);
+            mClipRect.set(-halfExtraWidth, top, getWidth() + halfExtraWidth, bottom);
             setClipBounds(mClipRect);
         } else {
             setClipBounds(null);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
index 3ec8c23..4ed5056 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
@@ -93,6 +93,13 @@
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
+        mDismissButton.setBackground(
+                getResources().getDrawable(R.drawable.notif_footer_btn_background));
+        mDismissButton.setTextColor(getResources().getColor(R.color.notif_pill_text));
+        mManageButton.setBackground(
+                getResources().getDrawable(R.drawable.notif_footer_btn_background));
+        mManageButton.setTextColor(getResources().getColor(R.color.notif_pill_text));
+        mManageButton = findViewById(R.id.manage_text);
         mDismissButton.setText(R.string.clear_all_notifications_text);
         mDismissButton.setContentDescription(
                 mContext.getString(R.string.accessibility_clear_all));
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 55a27b2..c3ccba4 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
@@ -1291,9 +1291,14 @@
                     }
                 }
             }
-
-            if (existing != null && entry.getSbn().getNotification().isColorized()) {
-                existing.overrideBackgroundTintColor(entry.getSbn().getNotification().color);
+            if (existing != null) {
+                if (entry.getSbn().getNotification().isColorized()) {
+                    existing.setBackgroundTintColor(
+                            entry.getSbn().getNotification().color, true);
+                } else {
+                    existing.setBackgroundTintColor(
+                            entry.getRow().getCurrentBackgroundTint(), false);
+                }
             }
             return existing;
         }
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 f72d2ae..6e78059 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -32,7 +32,6 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ShortcutManager;
 import android.content.res.ColorStateList;
-import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Color;
 import android.graphics.Rect;
@@ -74,6 +73,7 @@
 
 import androidx.annotation.NonNull;
 
+import com.android.internal.graphics.ColorUtils;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.internal.statusbar.IStatusBarService;
@@ -130,6 +130,9 @@
     private int mRevealCy;
     private int mRevealR;
 
+    private boolean mColorized;
+    private int mTint;
+
     private boolean mResetting;
     private NotificationViewWrapper mWrapper;
     private Consumer<Boolean> mOnVisibilityChangedListener;
@@ -143,35 +146,63 @@
         mRemoteInputManager = Dependency.get(NotificationRemoteInputManager.class);
         mStatusBarManagerService = IStatusBarService.Stub.asInterface(
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+        TypedArray ta = getContext().getTheme().obtainStyledAttributes(new int[]{
+                com.android.internal.R.attr.colorAccent,
+                com.android.internal.R.attr.colorBackgroundFloating,
+        });
+        mTint = ta.getColor(0, 0);
+        ta.recycle();
     }
 
     /**
      * The remote view needs to adapt to colorized notifications when set
+     * It overrides the background of itself as well as all of its childern
      * @param color colorized notification color
      */
-    public void overrideBackgroundTintColor(int color) {
-        mEditText.setBackgroundTintColor(color);
-        final boolean dark = !ContrastColorUtil.isColorLight(color);
-        int[][] states = new int[][] {
-                new int[] {android.R.attr.state_enabled},
-                new int[] {},
+    public void setBackgroundTintColor(int color, boolean colorized) {
+        if (colorized == mColorized && color == mTint) return;
+        mColorized = colorized;
+        mTint = color;
+        final int[][] states = new int[][]{
+                new int[]{com.android.internal.R.attr.state_enabled},
+                new int[]{},
         };
+        final int[] colors;
+        if (colorized) {
+            final boolean dark = !ContrastColorUtil.isColorLight(color);
+            final int finalColor = dark
+                    ? Color.WHITE
+                    : Color.BLACK;
+            colors = new int[]{
+                    finalColor,
+                    finalColor & 0x4DFFFFFF // %30 opacity
+            };
+            mEditText.setUniformBackgroundTintColor(color);
+            mEditText.setUniformForegroundColor(finalColor);
 
-        final int finalColor = dark
-                ? Color.WHITE
-                : Color.BLACK;
-
-        int[] colors = new int[] {
-                finalColor,
-                finalColor & 0x4DFFFFFF // %30 opacity
-        };
-
-        final ColorStateList tint = new ColorStateList(states, colors);
+        } else {
+            mEditText.setTextColor(mContext.getColor(R.color.remote_input_text));
+            mEditText.setHintTextColor(mContext.getColorStateList(R.color.remote_input_hint));
+            TypedArray ta = getContext().getTheme().obtainStyledAttributes(new int[]{
+                    com.android.internal.R.attr.colorAccent,
+                    com.android.internal.R.attr.colorBackgroundFloating,
+            });
+            int colorAccent = ta.getColor(0, 0);
+            int colorBackgroundFloating = ta.getColor(1, 0);
+            ta.recycle();
+            mEditText.setTextBackgroundColors(colorAccent, colorBackgroundFloating);
+            colors = new int[]{
+                    colorAccent,
+                    colorBackgroundFloating & 0x4DFFFFFF // %30 opacity
+            };
+        }
+        mEditText.setBackgroundColor(color);
+        final ColorStateList  tint = new ColorStateList(states, colors);
         mSendButton.setImageTintList(tint);
         mProgressBar.setProgressTintList(tint);
         mProgressBar.setIndeterminateTintList(tint);
         mProgressBar.setSecondaryProgressTintList(tint);
-        mEditText.setForegroundColor(finalColor);
+        setBackgroundColor(color);
     }
 
     @Override
@@ -326,7 +357,7 @@
                 reveal.addListener(new AnimatorListenerAdapter() {
                     @Override
                     public void onAnimationEnd(Animator animation) {
-                        setVisibility(INVISIBLE);
+                        setVisibility(GONE);
                         if (mWrapper != null) {
                             mWrapper.setRemoteInputVisible(false);
                         }
@@ -334,7 +365,7 @@
                 });
                 reveal.start();
             } else {
-                setVisibility(INVISIBLE);
+                setVisibility(GONE);
                 if (mWrapper != null) {
                     mWrapper.setRemoteInputVisible(false);
                 }
@@ -398,12 +429,6 @@
         }
     }
 
-    @Override
-    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-        mEditText.updateCornerRadius(heightMeasureSpec / 2);
-    }
-
     /** Populates the text field of the remote input with the given content. */
     public void setEditTextContent(@Nullable CharSequence editTextContent) {
         mEditText.setText(editTextContent);
@@ -700,40 +725,15 @@
         boolean mShowImeOnInputConnection;
         private LightBarController mLightBarController;
         private InputMethodManager mInputMethodManager;
-        private int mColor = Notification.COLOR_DEFAULT;
         UserHandle mUser;
-        private int mStokeWidth;
 
         public RemoteEditText(Context context, AttributeSet attrs) {
             super(context, attrs);
             mLightBarController = Dependency.get(LightBarController.class);
-            mTextBackground = createBackground(context, attrs);
+            mTextBackground = (GradientDrawable)
+                    context.getDrawable(R.drawable.remote_input_view_text_bg).mutate();
             mBackgroundColor = new ColorDrawable();
             mBackground = new LayerDrawable(new Drawable[] {mBackgroundColor, mTextBackground});
-            float density = context.getResources().getDisplayMetrics().density;
-            mStokeWidth = (int) (2 * density);
-            setDefaultColors();
-        }
-
-        private void setDefaultColors() {
-            Resources.Theme theme = getContext().getTheme();
-            TypedArray ta = theme.obtainStyledAttributes(
-                    new int[]{android.R.attr.colorAccent,
-                            com.android.internal.R.attr.colorBackgroundFloating});
-            mTextBackground.setStroke(mStokeWidth,
-                    ta.getColor(0, Notification.COLOR_DEFAULT));
-            mColor = ta.getColor(1, Notification.COLOR_DEFAULT);
-            mTextBackground.setColor(mColor);
-        }
-
-        private GradientDrawable createBackground(Context context, AttributeSet attrs) {
-            float density = context.getResources().getDisplayMetrics().density;
-            int padding = (int) (12 * density);
-            GradientDrawable d = new GradientDrawable();
-            d.setShape(GradientDrawable.RECTANGLE);
-            d.setPadding(padding, padding, padding, padding);
-            d.setCornerRadius(padding);
-            return d;
         }
 
         void setSupportedMimeTypes(@Nullable Collection<String> mimeTypes) {
@@ -796,16 +796,17 @@
             }
         }
 
-        protected void setBackgroundTintColor(int color) {
+        protected void setUniformBackgroundTintColor(int color) {
             mBackgroundColor.setColor(color);
             mTextBackground.setColor(color);
         }
 
-        protected void setForegroundColor(int color) {
-            mTextBackground.setStroke(mStokeWidth, color);
+        protected void setUniformForegroundColor(int color) {
+            int stroke = getContext().getResources()
+                    .getDimensionPixelSize(R.dimen.remote_input_view_text_stroke);
+            mTextBackground.setStroke(stroke, color);
             setTextColor(color);
-            // %60
-            setHintTextColor(color & 0x99FFFFFF);
+            setHintTextColor(ColorUtils.setAlphaComponent(color, 0x99));
             setTextCursorDrawable(null);
         }
 
@@ -896,10 +897,6 @@
             setSelection(getText().length());
         }
 
-        void updateCornerRadius(float radius) {
-            mTextBackground.setCornerRadius(radius);
-        }
-
         void setInnerFocusable(boolean focusable) {
             setFocusableInTouchMode(focusable);
             setFocusable(focusable);
@@ -935,5 +932,12 @@
             }
             return remainingItems;
         }
+
+        protected void setTextBackgroundColors(int strokeColor, int textBackground) {
+            mTextBackground.setColor(textBackground);
+            int stroke = getContext().getResources()
+                    .getDimensionPixelSize(R.dimen.remote_input_view_text_stroke);
+            mTextBackground.setStroke(stroke, strokeColor);
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
index 709ccd4..e403cfa 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
@@ -44,6 +44,7 @@
 import com.android.wm.shell.bubbles.Bubbles;
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.DisplayImeController;
+import com.android.wm.shell.common.DisplayLayout;
 import com.android.wm.shell.common.FloatingContentCoordinator;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.SyncTransactionQueue;
@@ -105,6 +106,12 @@
 
     @WMSingleton
     @Provides
+    static DisplayLayout provideDisplayLayout() {
+        return new DisplayLayout();
+    }
+
+    @WMSingleton
+    @Provides
     static DragAndDropController provideDragAndDropController(Context context,
             DisplayController displayController) {
         return new DragAndDropController(context, displayController);
@@ -233,11 +240,13 @@
     @Provides
     static Optional<OneHandedController> provideOneHandedController(Context context,
             WindowManager windowManager, DisplayController displayController,
-            TaskStackListenerImpl taskStackListener, UiEventLogger uiEventLogger,
+            DisplayLayout displayLayout, TaskStackListenerImpl taskStackListener,
+            UiEventLogger uiEventLogger,
             @ShellMainThread ShellExecutor mainExecutor,
             @ShellMainThread Handler mainHandler) {
         return Optional.ofNullable(OneHandedController.create(context, windowManager,
-                displayController, taskStackListener, uiEventLogger, mainExecutor, mainHandler));
+                displayController, displayLayout, taskStackListener, uiEventLogger, mainExecutor,
+                mainHandler));
     }
 
     //
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java
index db06199..c912419 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.classifier;
 
+import static com.android.systemui.classifier.Classifier.BRIGHTNESS_SLIDER;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import android.testing.AndroidTestingRunner;
@@ -96,13 +98,9 @@
     }
 
     @Test
-    public void testPass_swipe() {
-
+    public void testPass_BrightnessSliderAlwaysPasses() {
         mClassifier.onTouchEvent(appendDownEvent(1, 1));
-        assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isTrue();
-
-        mClassifier.onTouchEvent(appendMoveEvent(1, mDataProvider.getYdpi() * 3, 3));
-        mClassifier.onTouchEvent(appendUpEvent(1, mDataProvider.getYdpi() * 3, 300));
-        assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
+        assertThat(mClassifier.classifyGesture(BRIGHTNESS_SLIDER, 0.5, 1).isFalse())
+                .isFalse();
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java
index 52423bd..60786f6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java
@@ -16,11 +16,12 @@
 
 package com.android.systemui.classifier;
 
+import static com.android.systemui.classifier.Classifier.BRIGHTNESS_SLIDER;
 import static com.android.systemui.classifier.Classifier.GENERIC;
 import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS;
 
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.when;
 
 import android.testing.AndroidTestingRunner;
@@ -72,7 +73,7 @@
     public void testPass_uncovered() {
         touchDown();
         touchUp(10);
-        assertThat(mClassifier.classifyGesture(GENERIC, 0.5, 0).isFalse(), is(false));
+        assertThat(mClassifier.classifyGesture(GENERIC, 0.5, 0).isFalse()).isFalse();
     }
 
     @Test
@@ -81,7 +82,7 @@
         mClassifier.onProximityEvent(createSensorEvent(true, 1));
         mClassifier.onProximityEvent(createSensorEvent(false, 2));
         touchUp(20);
-        assertThat(mClassifier.classifyGesture(GENERIC, 0.5, 0).isFalse(), is(false));
+        assertThat(mClassifier.classifyGesture(GENERIC, 0.5, 0).isFalse()).isFalse();
     }
 
     @Test
@@ -90,7 +91,17 @@
         mClassifier.onProximityEvent(createSensorEvent(true, 1));
         mClassifier.onProximityEvent(createSensorEvent(false, 11));
         touchUp(10);
-        assertThat(mClassifier.classifyGesture(QUICK_SETTINGS, 0.5, 0).isFalse(), is(false));
+        assertThat(mClassifier.classifyGesture(QUICK_SETTINGS, 0.5, 0).isFalse()).isFalse();
+    }
+
+    @Test
+    public void testPass_brightnessSlider() {
+        touchDown();
+        mClassifier.onProximityEvent(createSensorEvent(true, 1));
+        mClassifier.onProximityEvent(createSensorEvent(false, 11));
+        touchUp(10);
+        assertThat(mClassifier.classifyGesture(BRIGHTNESS_SLIDER, 0.5, 0).isFalse())
+                .isFalse();
     }
 
     @Test
@@ -99,7 +110,7 @@
         mClassifier.onProximityEvent(createSensorEvent(true, 1));
         mClassifier.onProximityEvent(createSensorEvent(false, 11));
         touchUp(10);
-        assertThat(mClassifier.classifyGesture(GENERIC, 0.5, 0).isFalse(), is(true));
+        assertThat(mClassifier.classifyGesture(GENERIC, 0.5, 0).isFalse()).isTrue();
     }
 
     @Test
@@ -110,7 +121,7 @@
         mClassifier.onProximityEvent(createSensorEvent(true, 96));
         mClassifier.onProximityEvent(createSensorEvent(false, 100));
         touchUp(100);
-        assertThat(mClassifier.classifyGesture(GENERIC, 0.5, 0).isFalse(), is(true));
+        assertThat(mClassifier.classifyGesture(GENERIC, 0.5, 0).isFalse()).isTrue();
     }
 
     @Test
@@ -120,7 +131,7 @@
         mClassifier.onProximityEvent(createSensorEvent(false, 11));
         touchUp(10);
         when(mDistanceClassifier.isLongSwipe()).thenReturn(mPassedResult);
-        assertThat(mClassifier.classifyGesture(GENERIC, 0.5, 0).isFalse(), is(false));
+        assertThat(mClassifier.classifyGesture(GENERIC, 0.5, 0).isFalse()).isFalse();
     }
 
     private void touchDown() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/TypeClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/TypeClassifierTest.java
index 068a1e5..32537b4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/TypeClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/TypeClassifierTest.java
@@ -17,6 +17,7 @@
 package com.android.systemui.classifier;
 
 import static com.android.systemui.classifier.Classifier.BOUNCER_UNLOCK;
+import static com.android.systemui.classifier.Classifier.BRIGHTNESS_SLIDER;
 import static com.android.systemui.classifier.Classifier.LEFT_AFFORDANCE;
 import static com.android.systemui.classifier.Classifier.NOTIFICATION_DISMISS;
 import static com.android.systemui.classifier.Classifier.NOTIFICATION_DRAG_DOWN;
@@ -277,4 +278,46 @@
         when(mDataProvider.isRight()).thenReturn(true);
         assertThat(mClassifier.classifyGesture(RIGHT_AFFORDANCE, 0.5, 0).isFalse()).isTrue();
     }
+
+    @Test
+    public void testPass_BrightnessSlider() {
+        when(mDataProvider.isVertical()).thenReturn(false);
+
+        when(mDataProvider.isUp()).thenReturn(false);  // up and right should cause no effect.
+        when(mDataProvider.isRight()).thenReturn(false);
+        assertThat(mClassifier.classifyGesture(BRIGHTNESS_SLIDER, 0.5, 0).isFalse()).isFalse();
+
+        when(mDataProvider.isUp()).thenReturn(true);
+        when(mDataProvider.isRight()).thenReturn(false);
+        assertThat(mClassifier.classifyGesture(BRIGHTNESS_SLIDER, 0.5, 0).isFalse()).isFalse();
+
+        when(mDataProvider.isUp()).thenReturn(false);
+        when(mDataProvider.isRight()).thenReturn(true);
+        assertThat(mClassifier.classifyGesture(BRIGHTNESS_SLIDER, 0.5, 0).isFalse()).isFalse();
+
+        when(mDataProvider.isUp()).thenReturn(true);
+        when(mDataProvider.isRight()).thenReturn(true);
+        assertThat(mClassifier.classifyGesture(BRIGHTNESS_SLIDER, 0.5, 0).isFalse()).isFalse();
+    }
+
+    @Test
+    public void testFalse_BrightnessSlider() {
+        when(mDataProvider.isVertical()).thenReturn(true);
+
+        when(mDataProvider.isUp()).thenReturn(false);  // up and right should cause no effect.
+        when(mDataProvider.isRight()).thenReturn(false);
+        assertThat(mClassifier.classifyGesture(BRIGHTNESS_SLIDER, 0.5, 0).isFalse()).isTrue();
+
+        when(mDataProvider.isUp()).thenReturn(true);
+        when(mDataProvider.isRight()).thenReturn(false);
+        assertThat(mClassifier.classifyGesture(BRIGHTNESS_SLIDER, 0.5, 0).isFalse()).isTrue();
+
+        when(mDataProvider.isUp()).thenReturn(false);
+        when(mDataProvider.isRight()).thenReturn(true);
+        assertThat(mClassifier.classifyGesture(BRIGHTNESS_SLIDER, 0.5, 0).isFalse()).isTrue();
+
+        when(mDataProvider.isUp()).thenReturn(true);
+        when(mDataProvider.isRight()).thenReturn(true);
+        assertThat(mClassifier.classifyGesture(BRIGHTNESS_SLIDER, 0.5, 0).isFalse()).isTrue();
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java
index e004c30..c343c20 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.classifier;
 
+import static com.android.systemui.classifier.Classifier.BRIGHTNESS_SLIDER;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import android.testing.AndroidTestingRunner;
@@ -82,6 +84,13 @@
         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
     }
 
+    @Test
+    public void testPass_brightnessSliderAlwaysPasses() {
+        appendMoveEvent(0, 0);
+        appendMoveEvent(0, 100);
+        appendMoveEvent(0, 1);
+        assertThat(mClassifier.classifyGesture(BRIGHTNESS_SLIDER, 0.5, 1).isFalse()).isFalse();
+    }
 
     @Test
     public void testFail_minimumTouchesVertical() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderTest.kt
index 0cc2072..95e9d1f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderTest.kt
@@ -25,6 +25,7 @@
 import androidx.test.filters.SmallTest
 import com.android.settingslib.RestrictedLockUtils
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.classifier.FalsingManagerFake
 import com.android.systemui.statusbar.policy.BrightnessMirrorController
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.capture
@@ -75,6 +76,7 @@
     private lateinit var checkedChangeCaptor: ArgumentCaptor<CompoundButton.OnCheckedChangeListener>
     @Mock
     private lateinit var compoundButton: CompoundButton
+    private var mFalsingManager: FalsingManagerFake = FalsingManagerFake()
 
     private lateinit var mController: BrightnessSlider
 
@@ -85,7 +87,7 @@
         whenever(mirrorController.toggleSlider).thenReturn(mirror)
         whenever(motionEvent.copy()).thenReturn(motionEvent)
 
-        mController = BrightnessSlider(rootView, brightnessSliderView, true)
+        mController = BrightnessSlider(rootView, brightnessSliderView, true, mFalsingManager)
         mController.init()
         mController.setOnChangedListener(listener)
     }
@@ -160,7 +162,8 @@
 
     @Test
     fun testSettingMirrorWhenNotUseMirrorIsNoOp() {
-        val otherController = BrightnessSlider(rootView, brightnessSliderView, false)
+        val otherController = BrightnessSlider(
+                rootView, brightnessSliderView, false, mFalsingManager)
         otherController.init()
 
         otherController.setMirrorControllerAndMirror(mirrorController)
diff --git a/services/Android.bp b/services/Android.bp
index 311e8735..c160842 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -9,7 +9,10 @@
 
 filegroup {
     name: "services-main-sources",
-    srcs: ["java/**/*.java"],
+    srcs: [
+        "java/**/*.java",
+        "java/**/package.html",
+    ],
     path: "java",
     visibility: ["//visibility:private"],
 }
@@ -19,6 +22,7 @@
     srcs: [
         ":services.core-sources",
         ":services.core-sources-am-wm",
+        "core/java/com/android/server/am/package.html",
         ":services.accessibility-sources",
         ":services.appprediction-sources",
         ":services.appwidget-sources",
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
index 5b74cbd..1f66bfd 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
@@ -79,7 +79,7 @@
 
     private final ScreenStateObserver mScreenStateObserver;
 
-    private final MagnificationRequestObserver mMagnificationRequestObserver;
+    private final MagnificationInfoChangedCallback mMagnificationInfoChangedCallback;
 
     private int mUserId;
 
@@ -284,6 +284,14 @@
             mControllerCtx.getHandler().sendMessage(m);
         }
 
+        @Override
+        public void onImeWindowVisibilityChanged(boolean shown) {
+            final Message m = PooledLambda.obtainMessage(
+                    FullScreenMagnificationController::notifyImeWindowVisibilityChanged,
+                    FullScreenMagnificationController.this, shown);
+            mControllerCtx.getHandler().sendMessage(m);
+        }
+
         /**
          * Update our copy of the current magnification region
          *
@@ -329,7 +337,7 @@
             final boolean lastMagnificationActivated = mMagnificationActivated;
             mMagnificationActivated = spec.scale > 1.0f;
             if (mMagnificationActivated != lastMagnificationActivated) {
-                mMagnificationRequestObserver.onFullScreenMagnificationActivationState(
+                mMagnificationInfoChangedCallback.onFullScreenMagnificationActivationState(
                         mMagnificationActivated);
             }
         }
@@ -498,7 +506,7 @@
             sendSpecToAnimation(mCurrentMagnificationSpec, animationCallback);
             if (isMagnifying() && (id != INVALID_ID)) {
                 mIdOfLastServiceToMagnify = id;
-                mMagnificationRequestObserver.onRequestMagnificationSpec(mDisplayId,
+                mMagnificationInfoChangedCallback.onRequestMagnificationSpec(mDisplayId,
                         mIdOfLastServiceToMagnify);
             }
             return changed;
@@ -631,12 +639,12 @@
      */
     public FullScreenMagnificationController(@NonNull Context context,
             @NonNull AccessibilityManagerService ams, @NonNull Object lock,
-            @NonNull MagnificationRequestObserver magnificationRequestObserver) {
+            @NonNull MagnificationInfoChangedCallback magnificationInfoChangedCallback) {
         this(new ControllerContext(context, ams,
                 LocalServices.getService(WindowManagerInternal.class),
                 new Handler(context.getMainLooper()),
                 context.getResources().getInteger(R.integer.config_longAnimTime)), lock,
-                magnificationRequestObserver);
+                magnificationInfoChangedCallback);
     }
 
     /**
@@ -645,12 +653,12 @@
     @VisibleForTesting
     public FullScreenMagnificationController(@NonNull ControllerContext ctx,
             @NonNull Object lock,
-            @NonNull MagnificationRequestObserver magnificationRequestObserver) {
+            @NonNull MagnificationInfoChangedCallback magnificationInfoChangedCallback) {
         mControllerCtx = ctx;
         mLock = lock;
         mMainThreadId = mControllerCtx.getContext().getMainLooper().getThread().getId();
         mScreenStateObserver = new ScreenStateObserver(mControllerCtx.getContext(), this);
-        mMagnificationRequestObserver = magnificationRequestObserver;
+        mMagnificationInfoChangedCallback = magnificationInfoChangedCallback;
     }
 
     /**
@@ -1168,6 +1176,16 @@
     }
 
     /**
+     * Notifies that the IME window visibility changed.
+     *
+     * @param shown {@code true} means the IME window shows on the screen. Otherwise it's
+     *                           hidden.
+     */
+    void notifyImeWindowVisibilityChanged(boolean shown) {
+        mMagnificationInfoChangedCallback.onImeWindowVisibilityChanged(shown);
+    }
+
+    /**
      * Returns {@code true} if the magnifiable regions of the display is forced to be shown.
      *
      * @param displayId The logical display id.
@@ -1528,7 +1546,7 @@
         return animate ? STUB_ANIMATION_CALLBACK : null;
     }
 
-    interface  MagnificationRequestObserver {
+    interface  MagnificationInfoChangedCallback {
 
         /**
          * Called when the {@link MagnificationSpec} is changed with non-default
@@ -1545,7 +1563,13 @@
          *
          * @param activated {@code true} if the magnification is activated, otherwise {@code false}.
          */
-        @GuardedBy("mLock")
         void onFullScreenMagnificationActivationState(boolean activated);
+
+        /**
+         * Called when the IME window visibility changed.
+         * @param shown {@code true} means the IME window shows on the screen. Otherwise it's
+         *                           hidden.
+         */
+        void onImeWindowVisibilityChanged(boolean shown);
     }
 }
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
index 2073c70..878ebc5 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
@@ -18,6 +18,7 @@
 
 import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL;
 import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
+import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
 import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
 
 import android.annotation.NonNull;
@@ -33,6 +34,7 @@
 import android.view.accessibility.MagnificationAnimationCallback;
 
 import com.android.internal.accessibility.util.AccessibilityStatsLogUtils;
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.accessibility.AccessibilityManagerService;
 
@@ -58,7 +60,7 @@
  */
 public class MagnificationController implements WindowMagnificationManager.Callback,
         MagnificationGestureHandler.Callback,
-        FullScreenMagnificationController.MagnificationRequestObserver {
+        FullScreenMagnificationController.MagnificationInfoChangedCallback {
 
     private static final boolean DEBUG = false;
     private static final String TAG = "MagnificationController";
@@ -73,6 +75,10 @@
     private WindowMagnificationManager mWindowMagnificationMgr;
     private int mMagnificationCapabilities = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
 
+    @GuardedBy("mLock")
+    private int mActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
+    @GuardedBy("mLock")
+    private boolean mImeWindowVisible = false;
     private long mWindowModeEnabledTime = 0;
     private long mFullScreenModeEnabledTime = 0;
 
@@ -216,9 +222,18 @@
     public void onWindowMagnificationActivationState(boolean activated) {
         if (activated) {
             mWindowModeEnabledTime = SystemClock.uptimeMillis();
+
+            synchronized (mLock) {
+                mActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
+            }
+            logMagnificationModeWithImeOnIfNeeded();
         } else {
             logMagnificationUsageState(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW,
                     SystemClock.uptimeMillis() - mWindowModeEnabledTime);
+
+            synchronized (mLock) {
+                mActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
+            }
         }
     }
 
@@ -226,12 +241,29 @@
     public void onFullScreenMagnificationActivationState(boolean activated) {
         if (activated) {
             mFullScreenModeEnabledTime = SystemClock.uptimeMillis();
+
+            synchronized (mLock) {
+                mActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
+            }
+            logMagnificationModeWithImeOnIfNeeded();
         } else {
             logMagnificationUsageState(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN,
                     SystemClock.uptimeMillis() - mFullScreenModeEnabledTime);
+
+            synchronized (mLock) {
+                mActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
+            }
         }
     }
 
+    @Override
+    public void onImeWindowVisibilityChanged(boolean shown) {
+        synchronized (mLock) {
+            mImeWindowVisible = shown;
+        }
+        logMagnificationModeWithImeOnIfNeeded();
+    }
+
     /**
      * Wrapper method of logging the magnification activated mode and its duration of the usage
      * when the magnification is disabled.
@@ -245,6 +277,17 @@
     }
 
     /**
+     * Wrapper method of logging the activated mode of the magnification when the IME window
+     * is shown on the screen.
+     *
+     * @param mode The activated magnification mode.
+     */
+    @VisibleForTesting
+    public void logMagnificationModeWithIme(int mode) {
+        AccessibilityStatsLogUtils.logMagnificationModeWithImeOn(mode);
+    }
+
+    /**
      * Updates the active user ID of {@link FullScreenMagnificationController} and {@link
      * WindowMagnificationManager}.
      *
@@ -295,6 +338,18 @@
         }
     }
 
+    private void logMagnificationModeWithImeOnIfNeeded() {
+        final int mode;
+
+        synchronized (mLock) {
+            if (!mImeWindowVisible || mActivatedMode == ACCESSIBILITY_MAGNIFICATION_MODE_NONE) {
+                return;
+            }
+            mode = mActivatedMode;
+        }
+        logMagnificationModeWithIme(mode);
+    }
+
     /**
      * Getter of {@link FullScreenMagnificationController}.
      *
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index bbe59c9..ca01c8e 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1570,16 +1570,16 @@
         mNetworkInfoBlockingLogs.log(action + " " + uid);
     }
 
-    private void maybeLogBlockedStatusChanged(NetworkRequestInfo nri, Network net,
-            boolean blocked) {
+    private void maybeLogBlockedStatusChanged(NetworkRequestInfo nri, Network net, int blocked) {
         if (nri == null || net == null || !LOGD_BLOCKED_NETWORKINFO) {
             return;
         }
-        final String action = blocked ? "BLOCKED" : "UNBLOCKED";
+        final String action = (blocked != 0) ? "BLOCKED" : "UNBLOCKED";
         final int requestId = nri.getActiveRequest() != null
                 ? nri.getActiveRequest().requestId : nri.mRequests.get(0).requestId;
         mNetworkInfoBlockingLogs.log(String.format(
-                "%s %d(%d) on netId %d", action, nri.mAsUid, requestId, net.getNetId()));
+                "%s %d(%d) on netId %d: %s", action, nri.mAsUid, requestId, net.getNetId(),
+                blockedReasonsToString(blocked)));
     }
 
     /**
@@ -3137,6 +3137,13 @@
                     }
                     break;
                 }
+                case NetworkAgent.EVENT_TEARDOWN_DELAY_CHANGED: {
+                    if (msg.arg1 >= 0 && msg.arg1 <= NetworkAgent.MAX_TEARDOWN_DELAY_MS) {
+                        nai.teardownDelayMs = msg.arg1;
+                    } else {
+                        logwtf(nai.toShortString() + " set invalid teardown delay " + msg.arg1);
+                    }
+                }
             }
         }
 
@@ -3708,6 +3715,23 @@
         mLegacyTypeTracker.remove(nai, wasDefault);
         rematchAllNetworksAndRequests();
         mLingerMonitor.noteDisconnect(nai);
+
+        // Immediate teardown.
+        if (nai.teardownDelayMs == 0) {
+            destroyNetwork(nai);
+            return;
+        }
+
+        // Delayed teardown.
+        try {
+            mNetd.networkSetPermissionForNetwork(nai.network.netId, INetd.PERMISSION_SYSTEM);
+        } catch (RemoteException e) {
+            Log.d(TAG, "Error marking network restricted during teardown: " + e);
+        }
+        mHandler.postDelayed(() -> destroyNetwork(nai), nai.teardownDelayMs);
+    }
+
+    private void destroyNetwork(NetworkAgentInfo nai) {
         if (nai.created) {
             // Tell netd to clean up the configuration for this network
             // (routing rules, DNS, etc).
@@ -3720,7 +3744,7 @@
             mDnsManager.removeNetwork(nai.network);
         }
         mNetIdManager.releaseNetId(nai.network.getNetId());
-        nai.onNetworkDisconnected();
+        nai.onNetworkDestroyed();
     }
 
     private boolean createNativeNetwork(@NonNull NetworkAgentInfo networkAgent) {
@@ -7354,7 +7378,7 @@
                 break;
             }
             case ConnectivityManager.CALLBACK_BLK_CHANGED: {
-                maybeLogBlockedStatusChanged(nri, networkAgent.network, arg1 != 0);
+                maybeLogBlockedStatusChanged(nri, networkAgent.network, arg1);
                 msg.arg1 = arg1;
                 break;
             }
diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java
index ebd32e8..08bff81 100644
--- a/services/core/java/com/android/server/PinnerService.java
+++ b/services/core/java/com/android/server/PinnerService.java
@@ -265,18 +265,9 @@
      * Handler for on start pinning message
      */
     private void handlePinOnStart() {
-        final String bootImage = SystemProperties.get("dalvik.vm.boot-image", "");
-        String[] filesToPin = null;
-        if (bootImage.endsWith("boot-image.prof")) {
-            // Use the files listed for that specific boot image.
-            // TODO: find a better way to know we're using the JIT zygote configuration.
-            filesToPin = mContext.getResources().getStringArray(
-                  com.android.internal.R.array.config_jitzygoteBootImagePinnerServiceFiles);
-        } else {
-            // Files to pin come from the overlay and can be specified per-device config
-            filesToPin = mContext.getResources().getStringArray(
-                  com.android.internal.R.array.config_defaultPinnerServiceFiles);
-        }
+        // Files to pin come from the overlay and can be specified per-device config
+        String[] filesToPin = mContext.getResources().getStringArray(
+            com.android.internal.R.array.config_defaultPinnerServiceFiles);
         // Continue trying to pin each file even if we fail to pin some of them
         for (String fileToPin : filesToPin) {
             PinnedFile pf = pinFile(fileToPin,
@@ -286,10 +277,32 @@
                 Slog.e(TAG, "Failed to pin file = " + fileToPin);
                 continue;
             }
-
             synchronized (this) {
                 mPinnedFiles.add(pf);
             }
+            if (fileToPin.endsWith(".jar") | fileToPin.endsWith(".apk")) {
+                // Check whether the runtime has compilation artifacts to pin.
+                String arch = VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]);
+                String[] files = null;
+                try {
+                    files = DexFile.getDexFileOutputPaths(fileToPin, arch);
+                } catch (IOException ioe) { }
+                if (files == null) {
+                    continue;
+                }
+                for (String file : files) {
+                    PinnedFile df = pinFile(file,
+                                            Integer.MAX_VALUE,
+                                            /*attemptPinIntrospection=*/false);
+                    if (df == null) {
+                        Slog.i(TAG, "Failed to pin ART file = " + file);
+                        continue;
+                    }
+                    synchronized (this) {
+                        mPinnedFiles.add(df);
+                    }
+                }
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 3ea4458..b42a16d 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -44,6 +44,7 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.provider.DeviceConfig;
+import android.telecom.TelecomManager;
 import android.telephony.Annotation;
 import android.telephony.Annotation.RadioPowerState;
 import android.telephony.Annotation.SrvccState;
@@ -215,6 +216,18 @@
             return Binder.withCleanCallingIdentity(() -> CompatChanges.isChangeEnabled(
                     TelephonyCallback.PHONE_STATE_LISTENER_LIMIT_CHANGE_ID, uid));
         }
+
+        /**
+         * See {@link TelecomManager#ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION} for more
+         * information.
+         * @noinspection ConstantConditions
+         */
+        public boolean isCallStateReadPhoneStateEnforcedInPlatformCompat(String packageName,
+                UserHandle userHandle) {
+            return Binder.withCleanCallingIdentity(() -> CompatChanges.isChangeEnabled(
+                    TelecomManager.ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION, packageName,
+                    userHandle));
+        }
     }
 
     private final Context mContext;
@@ -2947,6 +2960,19 @@
             }
         }
 
+        // Only check READ_PHONE_STATE for CALL_STATE_CHANGED for API 31+.
+        if (mConfigurationProvider.isCallStateReadPhoneStateEnforcedInPlatformCompat(callingPackage,
+                Binder.getCallingUserHandle())) {
+            if (events.contains(TelephonyCallback.EVENT_LEGACY_CALL_STATE_CHANGED)
+                    || events.contains(TelephonyCallback.EVENT_CALL_STATE_CHANGED)) {
+                if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                        mContext, subId, callingPackage, callingFeatureId, message)) {
+                    throw new SecurityException("CALL_STATE_CHANGED event requires "
+                            + "READ_PHONE_STATE");
+                }
+            }
+        }
+
         if (isPrecisePhoneStatePermissionRequired(events)) {
             // check if calling app has either permission READ_PRECISE_PHONE_STATE
             // or with carrier privileges
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 036b88e..2ee5c5a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -188,6 +188,7 @@
 import android.app.usage.UsageStatsManager;
 import android.app.usage.UsageStatsManagerInternal;
 import android.appwidget.AppWidgetManager;
+import android.content.AttributionSource;
 import android.content.AutofillOptions;
 import android.content.BroadcastReceiver;
 import android.content.ComponentCallbacks2;
@@ -254,11 +255,11 @@
 import android.os.Message;
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
+import android.os.PowerExemptionManager.ReasonCode;
+import android.os.PowerExemptionManager.TempAllowListType;
 import android.os.PowerManager;
 import android.os.PowerManager.ServiceType;
 import android.os.PowerManagerInternal;
-import android.os.PowerWhitelistManager.ReasonCode;
-import android.os.PowerWhitelistManager.TempAllowListType;
 import android.os.Process;
 import android.os.RemoteCallback;
 import android.os.RemoteException;
@@ -340,7 +341,11 @@
 import com.android.internal.util.MemInfoReader;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.function.HeptFunction;
+import com.android.internal.util.function.HexFunction;
+import com.android.internal.util.function.OctFunction;
 import com.android.internal.util.function.QuadFunction;
+import com.android.internal.util.function.QuintFunction;
+import com.android.internal.util.function.TriFunction;
 import com.android.server.AlarmManagerInternal;
 import com.android.server.DeviceIdleInternal;
 import com.android.server.DisplayThread;
@@ -367,6 +372,7 @@
 import com.android.server.job.JobSchedulerInternal;
 import com.android.server.os.NativeTombstoneManager;
 import com.android.server.pm.Installer;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
 import com.android.server.pm.permission.PermissionManagerServiceInternal;
 import com.android.server.uri.GrantUri;
 import com.android.server.uri.NeededUriGrants;
@@ -1123,24 +1129,6 @@
     CoreSettingsObserver mCoreSettingsObserver;
 
     /**
-     * Thread-local storage used to carry caller permissions over through
-     * indirect content-provider access.
-     */
-    private class Identity {
-        public final IBinder token;
-        public final int pid;
-        public final int uid;
-
-        Identity(IBinder _token, int _pid, int _uid) {
-            token = _token;
-            pid = _pid;
-            uid = _uid;
-        }
-    }
-
-    private static final ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
-
-    /**
      * All information we have collected about the runtime performance of
      * any user id that can impact battery performance.
      */
@@ -5344,26 +5332,6 @@
         return checkComponentPermission(permission, pid, uid, -1, true);
     }
 
-    @Override
-    public int checkPermissionWithToken(String permission, int pid, int uid, IBinder callerToken) {
-        if (permission == null) {
-            return PackageManager.PERMISSION_DENIED;
-        }
-
-        // We might be performing an operation on behalf of an indirect binder
-        // invocation, e.g. via {@link #openContentUri}.  Check and adjust the
-        // client identity accordingly before proceeding.
-        Identity tlsIdentity = sCallerIdentity.get();
-        if (tlsIdentity != null && tlsIdentity.token == callerToken) {
-            Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
-                    + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
-            uid = tlsIdentity.uid;
-            pid = tlsIdentity.pid;
-        }
-
-        return checkComponentPermission(permission, pid, uid, -1, true);
-    }
-
     /**
      * Binder IPC calls go through the public entry point.
      * This can be called with or without the global lock held.
@@ -5618,14 +5586,6 @@
             final int modeFlags, int userId, IBinder callerToken) {
         enforceNotIsolatedCaller("checkUriPermission");
 
-        // Another redirected-binder-call permissions check as in
-        // {@link checkPermissionWithToken}.
-        Identity tlsIdentity = sCallerIdentity.get();
-        if (tlsIdentity != null && tlsIdentity.token == callerToken) {
-            uid = tlsIdentity.uid;
-            pid = tlsIdentity.pid;
-        }
-
         // Our own process gets to do everything.
         if (pid == MY_PID) {
             return PackageManager.PERMISSION_GRANTED;
@@ -6159,23 +6119,22 @@
                 Binder.getCallingUid(), "*opencontent*", userId);
         ParcelFileDescriptor pfd = null;
         if (cph != null) {
-            // We record the binder invoker's uid in thread-local storage before
-            // going to the content provider to open the file.  Later, in the code
-            // that handles all permissions checks, we look for this uid and use
-            // that rather than the Activity Manager's own uid.  The effect is that
-            // we do the check against the caller's permissions even though it looks
-            // to the content provider like the Activity Manager itself is making
-            // the request.
-            Binder token = new Binder();
-            sCallerIdentity.set(new Identity(
-                    token, Binder.getCallingPid(), Binder.getCallingUid()));
             try {
-                pfd = cph.provider.openFile(null, null, uri, "r", null, token);
+                // This method is exposed to the VNDK and to avoid changing its
+                // signature we just use the first package in the UID. For shared
+                // UIDs we may blame the wrong app but that is Okay as they are
+                // in the same security/privacy sandbox.
+                final AndroidPackage androidPackage = mPackageManagerInt
+                        .getPackage(Binder.getCallingUid());
+                if (androidPackage == null) {
+                    return null;
+                }
+                final AttributionSource attributionSource = new AttributionSource(
+                        Binder.getCallingUid(), androidPackage.getPackageName(), null);
+                pfd = cph.provider.openFile(attributionSource, uri, "r", null);
             } catch (FileNotFoundException e) {
                 // do nothing; pfd will be returned null
             } finally {
-                // Ensure that whatever happens, we clean up the identity state
-                sCallerIdentity.remove();
                 // Ensure we're done with the provider.
                 mCpHelper.removeContentProviderExternalUnchecked(name, null, userId);
             }
@@ -16639,6 +16598,74 @@
                     message, shouldCollectMessage);
         }
 
+        @Override
+        public int noteProxyOperation(int code, @NonNull AttributionSource attributionSource,
+                boolean shouldCollectAsyncNotedOp, @Nullable String message,
+                boolean shouldCollectMessage, boolean skiProxyOperation,
+                @NonNull HexFunction<Integer, AttributionSource, Boolean, String, Boolean,
+                                Boolean, Integer> superImpl) {
+            if (attributionSource.getUid() == mTargetUid && isTargetOp(code)) {
+                final int shellUid = UserHandle.getUid(UserHandle.getUserId(
+                        attributionSource.getUid()), Process.SHELL_UID);
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    return superImpl.apply(code, new AttributionSource(shellUid,
+                            "com.android.shell", attributionSource.getAttributionTag(),
+                            attributionSource.getNext()),
+                            shouldCollectAsyncNotedOp, message, shouldCollectMessage,
+                            skiProxyOperation);
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
+            }
+            return superImpl.apply(code, attributionSource, shouldCollectAsyncNotedOp,
+                    message, shouldCollectMessage, skiProxyOperation);
+        }
+
+        @Override
+        public int startProxyOperation(IBinder token, int code,
+                @NonNull AttributionSource attributionSource, boolean startIfModeDefault,
+                boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
+                boolean skipProsyOperation, @NonNull OctFunction<IBinder, Integer,
+                        AttributionSource, Boolean, Boolean, String, Boolean, Boolean,
+                        Integer> superImpl) {
+            if (attributionSource.getUid() == mTargetUid && isTargetOp(code)) {
+                final int shellUid = UserHandle.getUid(UserHandle.getUserId(
+                        attributionSource.getUid()), Process.SHELL_UID);
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    return superImpl.apply(token, code, new AttributionSource(shellUid,
+                                    "com.android.shell", attributionSource.getAttributionTag(),
+                                    attributionSource.getNext()), startIfModeDefault,
+                            shouldCollectAsyncNotedOp, message, shouldCollectMessage,
+                            skipProsyOperation);
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
+            }
+            return superImpl.apply(token, code, attributionSource, startIfModeDefault,
+                    shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProsyOperation);
+        }
+
+        @Override
+        public void finishProxyOperation(IBinder clientId, int code,
+                @NonNull AttributionSource attributionSource,
+                @NonNull TriFunction<IBinder, Integer, AttributionSource, Void> superImpl) {
+            if (attributionSource.getUid() == mTargetUid && isTargetOp(code)) {
+                final int shellUid = UserHandle.getUid(UserHandle.getUserId(
+                        attributionSource.getUid()), Process.SHELL_UID);
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    superImpl.apply(clientId, code, new AttributionSource(shellUid,
+                            "com.android.shell", attributionSource.getAttributionTag(),
+                            attributionSource.getNext()));
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
+            }
+            superImpl.apply(clientId, code, attributionSource);
+        }
+
         private boolean isTargetOp(int code) {
             // null permissions means all ops are targeted
             if (mPermissions == null) {
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 9ecae42..7f2eae8 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -45,8 +45,8 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
-import android.os.PowerWhitelistManager;
-import android.os.PowerWhitelistManager.TempAllowListType;
+import android.os.PowerExemptionManager.ReasonCode;
+import android.os.PowerExemptionManager.TempAllowListType;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
@@ -908,7 +908,7 @@
     }
 
     final void scheduleTempAllowlistLocked(int uid, long duration, BroadcastRecord r,
-            @TempAllowListType int type, @PowerWhitelistManager.ReasonCode int reasonCode,
+            @TempAllowListType int type, @ReasonCode int reasonCode,
             @Nullable String reason) {
         if (duration > Integer.MAX_VALUE) {
             duration = Integer.MAX_VALUE;
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index ee4526b..b44699b 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -33,6 +33,7 @@
 import android.app.ContentProviderHolder;
 import android.app.IApplicationThread;
 import android.app.usage.UsageEvents.Event;
+import android.content.AttributionSource;
 import android.content.ComponentName;
 import android.content.ContentProvider;
 import android.content.ContentResolver;
@@ -42,6 +43,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.PathPermission;
 import android.content.pm.ProviderInfo;
 import android.database.ContentObserver;
@@ -67,7 +69,9 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.ArrayUtils;
+import com.android.server.LocalServices;
 import com.android.server.RescueParty;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -1037,7 +1041,19 @@
             holder = getContentProviderExternalUnchecked(name, null, callingUid,
                     "*checkContentProviderUriPermission*", userId);
             if (holder != null) {
-                return holder.provider.checkUriPermission(null, null, uri, callingUid, modeFlags);
+
+                final PackageManagerInternal packageManagerInt = LocalServices.getService(
+                        PackageManagerInternal.class);
+                final AndroidPackage androidPackage = packageManagerInt
+                        .getPackage(Binder.getCallingUid());
+                if (androidPackage == null) {
+                    return PackageManager.PERMISSION_DENIED;
+                }
+
+                final AttributionSource attributionSource = new AttributionSource(
+                        callingUid, androidPackage.getPackageName(), null);
+                return holder.provider.checkUriPermission(attributionSource, uri, callingUid,
+                        modeFlags);
             }
         } catch (RemoteException e) {
             Log.w(TAG, "Content provider dead retrieving " + uri, e);
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index 51666ac..f7c777e 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -66,7 +66,7 @@
     /**
      * Map IBinder to duration specified as Pair<Long, Integer>, Long is allowlist duration in
      * milliseconds, Integer is allowlist type defined at
-     * {@link android.os.PowerWhitelistManager.TempAllowListType}
+     * {@link android.os.PowerExemptionManager.TempAllowListType}
      */
     private ArrayMap<IBinder, TempAllowListDuration> mAllowlistDuration;
     private RemoteCallbackList<IResultReceiver> mCancelCallbacks;
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 7bc7105..07ee5a2 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -94,6 +94,7 @@
 import android.app.RuntimeAppOpAccessMessage;
 import android.app.SyncNotedAppOp;
 import android.app.admin.DevicePolicyManagerInternal;
+import android.content.AttributionSource;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -131,6 +132,7 @@
 import android.util.ArraySet;
 import android.util.AtomicFile;
 import android.util.KeyValueListParser;
+import android.util.Log;
 import android.util.LongSparseArray;
 import android.util.Pair;
 import android.util.Pools;
@@ -159,6 +161,9 @@
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.XmlUtils;
+import com.android.internal.util.function.HeptFunction;
+import com.android.internal.util.function.QuintFunction;
+import com.android.internal.util.function.TriFunction;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.LocalServices;
 import com.android.server.LockGuard;
@@ -1999,8 +2004,10 @@
 
     @Override
     public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) {
-        mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
-                Binder.getCallingPid(), Binder.getCallingUid(), null);
+        final int callingUid = Binder.getCallingUid();
+        final boolean hasAllPackageAccess = mContext.checkPermission(
+                Manifest.permission.GET_APP_OPS_STATS, Binder.getCallingPid(),
+                Binder.getCallingUid(), null) == PackageManager.PERMISSION_GRANTED;
         ArrayList<AppOpsManager.PackageOps> res = null;
         synchronized (this) {
             final int uidStateCount = mUidStates.size();
@@ -2016,11 +2023,14 @@
                     ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops);
                     if (resOps != null) {
                         if (res == null) {
-                            res = new ArrayList<AppOpsManager.PackageOps>();
+                            res = new ArrayList<>();
                         }
                         AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps(
                                 pkgOps.packageName, pkgOps.uidState.uid, resOps);
-                        res.add(resPackage);
+                        // Caller can always see their packages and with a permission all.
+                        if (hasAllPackageAccess || callingUid == pkgOps.uidState.uid) {
+                            res.add(resPackage);
+                        }
                     }
                 }
             }
@@ -2031,8 +2041,7 @@
     @Override
     public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName,
             int[] ops) {
-        mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
-                Binder.getCallingPid(), Binder.getCallingUid(), null);
+        enforceGetAppOpsStatsPermissionIfNeeded(uid,packageName);
         String resolvedPackageName = resolvePackageName(uid, packageName);
         if (resolvedPackageName == null) {
             return Collections.emptyList();
@@ -2054,6 +2063,22 @@
         }
     }
 
+    private void enforceGetAppOpsStatsPermissionIfNeeded(int uid, String packageName) {
+        final int callingUid = Binder.getCallingUid();
+        // We get to access everything
+        if (callingUid == Process.myPid()) {
+            return;
+        }
+        // Apps can access their own data
+        if (uid == callingUid && packageName != null
+                && checkPackage(uid, packageName) == MODE_ALLOWED) {
+            return;
+        }
+        // Otherwise, you need a permission...
+        mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
+                Binder.getCallingPid(), callingUid, null);
+    }
+
     /**
      * Verify that historical appop request arguments are valid.
      */
@@ -3078,15 +3103,52 @@
     }
 
     @Override
-    public int noteProxyOperation(int code, int proxiedUid, String proxiedPackageName,
-            String proxiedAttributionTag, int proxyUid, String proxyPackageName,
-            String proxyAttributionTag, boolean shouldCollectAsyncNotedOp, String message,
-            boolean shouldCollectMessage) {
-        verifyIncomingUid(proxyUid);
+    public int noteProxyOperation(int code, AttributionSource attributionSource,
+            boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
+            boolean skipProxyOperation) {
+        final CheckOpsDelegate policy;
+        final CheckOpsDelegateDispatcher delegateDispatcher;
+        synchronized (AppOpsService.this) {
+            policy = mAppOpsPolicy;
+            delegateDispatcher = mCheckOpsDelegateDispatcher;
+        }
+        if (policy != null) {
+            if (delegateDispatcher != null) {
+                return policy.noteProxyOperation(code, attributionSource,
+                        shouldCollectAsyncNotedOp, message, shouldCollectMessage,
+                        skipProxyOperation, delegateDispatcher::noteProxyOperationImpl);
+            } else {
+                return policy.noteProxyOperation(code, attributionSource,
+                        shouldCollectAsyncNotedOp, message, shouldCollectMessage,
+                        skipProxyOperation, AppOpsService.this::noteProxyOperationImpl);
+            }
+        } else if (delegateDispatcher != null) {
+            delegateDispatcher.getCheckOpsDelegate().noteProxyOperation(code,
+                    attributionSource, shouldCollectAsyncNotedOp, message,
+                    shouldCollectMessage, skipProxyOperation,
+                    AppOpsService.this::noteProxyOperationImpl);
+        }
+        return noteProxyOperationImpl(code, attributionSource, shouldCollectAsyncNotedOp,
+                message, shouldCollectMessage,skipProxyOperation);
+    }
+
+    private int noteProxyOperationImpl(int code, AttributionSource attributionSource,
+            boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
+            boolean skipProxyOperation) {
+        final int proxyUid = attributionSource.getUid();
+        final String proxyPackageName = attributionSource.getPackageName();
+        final String proxyAttributionTag = attributionSource.getAttributionTag();
+        final int proxiedUid = attributionSource.getNextUid();
+        final String proxiedPackageName = attributionSource.getNextPackageName();
+        final String proxiedAttributionTag = attributionSource.getNextAttributionTag();
+
+        verifyIncomingProxyUid(attributionSource);
         verifyIncomingOp(code);
         verifyIncomingPackage(proxiedPackageName, UserHandle.getUserId(proxiedUid));
         verifyIncomingPackage(proxyPackageName, UserHandle.getUserId(proxyUid));
 
+        skipProxyOperation = resolveSkipProxyOperation(skipProxyOperation, attributionSource);
+
         String resolveProxyPackageName = resolvePackageName(proxyUid, proxyPackageName);
         if (resolveProxyPackageName == null) {
             return AppOpsManager.MODE_IGNORED;
@@ -3097,19 +3159,23 @@
                 Manifest.permission.UPDATE_APP_OPS_STATS, -1, proxyUid)
                 == PackageManager.PERMISSION_GRANTED || isSelfBlame;
 
-        final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY
-                : AppOpsManager.OP_FLAG_UNTRUSTED_PROXY;
-        final int proxyMode = noteOperationUnchecked(code, proxyUid, resolveProxyPackageName,
-                proxyAttributionTag, Process.INVALID_UID, null, null, proxyFlags,
-                !isProxyTrusted, "proxy " + message, shouldCollectMessage);
-        if (proxyMode != AppOpsManager.MODE_ALLOWED) {
-            return proxyMode;
+        if (!skipProxyOperation) {
+            final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY
+                    : AppOpsManager.OP_FLAG_UNTRUSTED_PROXY;
+
+            final int proxyMode = noteOperationUnchecked(code, proxyUid, resolveProxyPackageName,
+                    proxyAttributionTag, Process.INVALID_UID, null, null, proxyFlags,
+                    !isProxyTrusted, "proxy " + message, shouldCollectMessage);
+            if (proxyMode != AppOpsManager.MODE_ALLOWED) {
+                return proxyMode;
+            }
         }
 
         String resolveProxiedPackageName = resolvePackageName(proxiedUid, proxiedPackageName);
         if (resolveProxiedPackageName == null) {
             return AppOpsManager.MODE_IGNORED;
         }
+
         final int proxiedFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXIED
                 : AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED;
         return noteOperationUnchecked(code, proxiedUid, resolveProxiedPackageName,
@@ -3558,16 +3624,56 @@
     }
 
     @Override
-    public int startProxyOperation(IBinder clientId, int code, int proxiedUid,
-            String proxiedPackageName, @Nullable String proxiedAttributionTag, int proxyUid,
-            String proxyPackageName, @Nullable String proxyAttributionTag,
+    public int startProxyOperation(IBinder clientId, int code,
+            @NonNull AttributionSource attributionSource, boolean startIfModeDefault,
+            boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
+            boolean skipProxyOperation) {
+        final CheckOpsDelegate policy;
+        final CheckOpsDelegateDispatcher delegateDispatcher;
+        synchronized (AppOpsService.this) {
+            policy = mAppOpsPolicy;
+            delegateDispatcher = mCheckOpsDelegateDispatcher;
+        }
+        if (policy != null) {
+            if (delegateDispatcher != null) {
+                return policy.startProxyOperation(clientId, code, attributionSource,
+                        startIfModeDefault, shouldCollectAsyncNotedOp, message,
+                        shouldCollectMessage, skipProxyOperation,
+                        delegateDispatcher::startProxyOperationImpl);
+            } else {
+                return policy.startProxyOperation(clientId, code, attributionSource,
+                        startIfModeDefault, shouldCollectAsyncNotedOp, message,
+                        shouldCollectMessage, skipProxyOperation,
+                        AppOpsService.this::startProxyOperationImpl);
+            }
+        } else if (delegateDispatcher != null) {
+            delegateDispatcher.getCheckOpsDelegate().startProxyOperation(clientId, code,
+                    attributionSource, startIfModeDefault, shouldCollectAsyncNotedOp, message,
+                    shouldCollectMessage, skipProxyOperation,
+                    AppOpsService.this::startProxyOperationImpl);
+        }
+        return startProxyOperationImpl(clientId, code, attributionSource, startIfModeDefault,
+                shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation);
+    }
+
+    private int startProxyOperationImpl(IBinder clientId, int code,
+            @NonNull AttributionSource attributionSource,
             boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message,
-            boolean shouldCollectMessage) {
-        verifyIncomingUid(proxyUid);
+            boolean shouldCollectMessage, boolean skipProxyOperation) {
+        final int proxyUid = attributionSource.getUid();
+        final String proxyPackageName = attributionSource.getPackageName();
+        final String proxyAttributionTag = attributionSource.getAttributionTag();
+        final int proxiedUid = attributionSource.getNextUid();
+        final String proxiedPackageName = attributionSource.getNextPackageName();
+        final String proxiedAttributionTag = attributionSource.getNextAttributionTag();
+
+        verifyIncomingProxyUid(attributionSource);
         verifyIncomingOp(code);
         verifyIncomingPackage(proxyPackageName, UserHandle.getUserId(proxyUid));
         verifyIncomingPackage(proxiedPackageName, UserHandle.getUserId(proxiedUid));
 
+        skipProxyOperation = resolveSkipProxyOperation(skipProxyOperation, attributionSource);
+
         String resolvedProxyPackageName = resolvePackageName(proxyUid, proxyPackageName);
         if (resolvedProxyPackageName == null) {
             return AppOpsManager.MODE_IGNORED;
@@ -3578,31 +3684,34 @@
                 Manifest.permission.UPDATE_APP_OPS_STATS, -1, proxyUid)
                 == PackageManager.PERMISSION_GRANTED || isSelfBlame;
 
-        final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY
-                : AppOpsManager.OP_FLAG_UNTRUSTED_PROXY;
-
         String resolvedProxiedPackageName = resolvePackageName(proxiedUid, proxiedPackageName);
         if (resolvedProxiedPackageName == null) {
             return AppOpsManager.MODE_IGNORED;
         }
+
         final int proxiedFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXIED
                 : AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED;
 
-        // Test if the proxied operation will succeed before starting the proxy operation
-        final int testProxiedMode = startOperationUnchecked(clientId, code, proxiedUid,
-                resolvedProxiedPackageName, proxiedAttributionTag, proxyUid,
-                resolvedProxyPackageName, proxyAttributionTag, proxiedFlags, startIfModeDefault,
-                shouldCollectAsyncNotedOp, message, shouldCollectMessage, true);
-        if (!shouldStartForMode(testProxiedMode, startIfModeDefault)) {
-            return testProxiedMode;
-        }
+        if (!skipProxyOperation) {
+            // Test if the proxied operation will succeed before starting the proxy operation
+            final int testProxiedMode = startOperationUnchecked(clientId, code, proxiedUid,
+                    resolvedProxiedPackageName, proxiedAttributionTag, proxyUid,
+                    resolvedProxyPackageName, proxyAttributionTag, proxiedFlags, startIfModeDefault,
+                    shouldCollectAsyncNotedOp, message, shouldCollectMessage, true);
+            if (!shouldStartForMode(testProxiedMode, startIfModeDefault)) {
+                return testProxiedMode;
+            }
 
-        final int proxyMode = startOperationUnchecked(clientId, code, proxyUid,
-                resolvedProxyPackageName, proxyAttributionTag, Process.INVALID_UID, null, null,
-                proxyFlags, startIfModeDefault, !isProxyTrusted, "proxy " + message,
-                shouldCollectMessage, false);
-        if (!shouldStartForMode(proxyMode, startIfModeDefault)) {
-            return proxyMode;
+            final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY
+                    : AppOpsManager.OP_FLAG_UNTRUSTED_PROXY;
+
+            final int proxyMode = startOperationUnchecked(clientId, code, proxyUid,
+                    resolvedProxyPackageName, proxyAttributionTag, Process.INVALID_UID, null, null,
+                    proxyFlags, startIfModeDefault, !isProxyTrusted, "proxy " + message,
+                    shouldCollectMessage, false);
+            if (!shouldStartForMode(proxyMode, startIfModeDefault)) {
+                return proxyMode;
+            }
         }
 
         return startOperationUnchecked(clientId, code, proxiedUid, resolvedProxiedPackageName,
@@ -3723,9 +3832,38 @@
     }
 
     @Override
-    public void finishProxyOperation(IBinder clientId, int code, int proxiedUid,
-            String proxiedPackageName, @Nullable String proxiedAttributionTag, int proxyUid,
-            @Nullable String proxyPackageName, @Nullable String proxyAttributionTag) {
+    public void finishProxyOperation(IBinder clientId, int code,
+            @NonNull AttributionSource attributionSource) {
+        final CheckOpsDelegate policy;
+        final CheckOpsDelegateDispatcher delegateDispatcher;
+        synchronized (AppOpsService.this) {
+            policy = mAppOpsPolicy;
+            delegateDispatcher = mCheckOpsDelegateDispatcher;
+        }
+        if (policy != null) {
+            if (delegateDispatcher != null) {
+                policy.finishProxyOperation(clientId, code, attributionSource,
+                        delegateDispatcher::finishProxyOperationImpl);
+            } else {
+                policy.finishProxyOperation(clientId, code, attributionSource,
+                        AppOpsService.this::finishProxyOperationImpl);
+            }
+        } else if (delegateDispatcher != null) {
+            delegateDispatcher.getCheckOpsDelegate().finishProxyOperation(clientId, code,
+                    attributionSource, AppOpsService.this::finishProxyOperationImpl);
+        }
+        finishProxyOperationImpl(clientId, code, attributionSource);
+    }
+
+    private Void finishProxyOperationImpl(IBinder clientId, int code,
+            @NonNull AttributionSource attributionSource) {
+        final int proxyUid = attributionSource.getUid();
+        final String proxyPackageName = attributionSource.getPackageName();
+        final String proxyAttributionTag = attributionSource.getAttributionTag();
+        final int proxiedUid = attributionSource.getNextUid();
+        final String proxiedPackageName = attributionSource.getNextPackageName();
+        final String proxiedAttributionTag = attributionSource.getNextAttributionTag();
+
         verifyIncomingUid(proxyUid);
         verifyIncomingOp(code);
         verifyIncomingPackage(proxyPackageName, UserHandle.getUserId(proxyUid));
@@ -3733,7 +3871,7 @@
 
         String resolvedProxyPackageName = resolvePackageName(proxyUid, proxyPackageName);
         if (resolvedProxyPackageName == null) {
-            return;
+            return null;
         }
 
         finishOperationUnchecked(clientId, code, proxyUid, resolvedProxyPackageName,
@@ -3741,11 +3879,13 @@
 
         String resolvedProxiedPackageName = resolvePackageName(proxiedUid, proxiedPackageName);
         if (resolvedProxiedPackageName == null) {
-            return;
+            return null;
         }
 
         finishOperationUnchecked(clientId, code, proxiedUid, resolvedProxiedPackageName,
                 proxiedAttributionTag);
+
+        return null;
     }
 
     private void finishOperationUnchecked(IBinder clientId, int code, int uid, String packageName,
@@ -3953,6 +4093,20 @@
                 || (permInfo.getProtectionFlags() & PROTECTION_FLAG_APPOP) != 0;
     }
 
+    private void verifyIncomingProxyUid(@NonNull AttributionSource attributionSource) {
+        if (attributionSource.getUid() == Binder.getCallingUid()) {
+            return;
+        }
+        if (Binder.getCallingPid() == Process.myPid()) {
+            return;
+        }
+        if (attributionSource.isTrusted(mContext)) {
+            return;
+        }
+        mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
+                Binder.getCallingPid(), Binder.getCallingUid(), null);
+    }
+
     private void verifyIncomingUid(int uid) {
         if (uid == Binder.getCallingUid()) {
             return;
@@ -3979,6 +4133,20 @@
         }
     }
 
+    private boolean resolveSkipProxyOperation(boolean requestsSkipProxyOperation,
+            @NonNull AttributionSource attributionSource) {
+        if (!requestsSkipProxyOperation) {
+            return false;
+        }
+        if (attributionSource.getUid() != Binder.getCallingUid()
+                && attributionSource.isTrusted(mContext)) {
+            return true;
+        }
+        return mContext.checkPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
+                Binder.getCallingPid(), Binder.getCallingUid(), null)
+                == PackageManager.PERMISSION_GRANTED;
+    }
+
     private @Nullable UidState getUidStateLocked(int uid, boolean edit) {
         UidState uidState = mUidStates.get(uid);
         if (uidState == null) {
@@ -4098,7 +4266,6 @@
     /**
      * Create a restriction description matching the properties of the package.
      *
-     * @param context A context to use
      * @param pkg The package to create the restriction description for
      *
      * @return The restriction matching the package
@@ -4141,15 +4308,25 @@
 
         int callingUid = Binder.getCallingUid();
         int userId = UserHandle.getUserId(uid);
-
         RestrictionBypass bypass = null;
+
+        // Allow any attribution tag for resolvable uids
+        int pkgUid = resolveUid(packageName);
+        if (pkgUid != Process.INVALID_UID) {
+            // Special case for the shell which is a package but should be able
+            // to bypass app attribution tag restrictions.
+            if (pkgUid != UserHandle.getAppId(uid)) {
+                throw new SecurityException("Specified package " + packageName + " under uid "
+                        +  UserHandle.getAppId(uid) + " but it is really " + pkgUid);
+            }
+            return RestrictionBypass.UNRESTRICTED;
+        }
+
         final long ident = Binder.clearCallingIdentity();
         try {
-            int pkgUid;
-            AndroidPackage pkg = LocalServices.getService(PackageManagerInternal.class).getPackage(
-                    packageName);
             boolean isAttributionTagValid = false;
-
+            AndroidPackage pkg = LocalServices.getService(PackageManagerInternal.class)
+                    .getPackage(packageName);
             if (pkg != null) {
                 if (attributionTag == null) {
                     isAttributionTagValid = true;
@@ -4166,20 +4343,7 @@
 
                 pkgUid = UserHandle.getUid(userId, UserHandle.getAppId(pkg.getUid()));
                 bypass = getBypassforPackage(pkg);
-            } else {
-                // Allow any attribution tag for resolvable uids
-                isAttributionTagValid = true;
-
-                pkgUid = resolveUid(packageName);
-                if (pkgUid >= 0) {
-                    bypass = RestrictionBypass.UNRESTRICTED;
-                }
             }
-            if (pkgUid != uid) {
-                throw new SecurityException("Specified package " + packageName + " under uid " + uid
-                        + " but it is really " + pkgUid);
-            }
-
             if (!isAttributionTagValid) {
                 String msg = "attributionTag " + attributionTag + " not declared in"
                         + " manifest of " + packageName;
@@ -4187,7 +4351,7 @@
                     if (mPlatformCompat.isChangeEnabledByPackageName(
                             SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE, packageName,
                             userId) && mPlatformCompat.isChangeEnabledByUid(
-                            SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE, callingUid)) {
+                                    SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE, callingUid)) {
                         throw new SecurityException(msg);
                     } else {
                         Slog.e(TAG, msg);
@@ -4199,6 +4363,11 @@
             Binder.restoreCallingIdentity(ident);
         }
 
+        if (pkgUid != uid) {
+            throw new SecurityException("Specified package " + packageName + " under uid " + uid
+                    + " but it is really " + pkgUid);
+        }
+
         return bypass;
     }
 
@@ -6103,6 +6272,57 @@
     }
 
     @Override
+    public boolean isProxying(int op, @NonNull String proxyPackageName,
+            @NonNull String proxyAttributionTag, int proxiedUid,
+            @NonNull String proxiedPackageName) {
+        Objects.requireNonNull(proxyPackageName);
+        Objects.requireNonNull(proxiedPackageName);
+        Binder.withCleanCallingIdentity(() -> {
+            final List<AppOpsManager.PackageOps> packageOps = getOpsForPackage(proxiedUid,
+                    proxiedPackageName, new int[] {op});
+            if (packageOps == null || packageOps.isEmpty()) {
+                return false;
+            }
+            final List<OpEntry> opEntries = packageOps.get(0).getOps();
+            if (opEntries.isEmpty()) {
+                return false;
+            }
+            final OpEntry opEntry = opEntries.get(0);
+            if (!opEntry.isRunning()) {
+                return false;
+            }
+            final OpEventProxyInfo proxyInfo = opEntry.getLastProxyInfo(
+                    AppOpsManager.OP_FLAG_TRUSTED_PROXY
+                            | AppOpsManager.OP_FLAG_UNTRUSTED_PROXY);
+            return proxyInfo != null && Binder.getCallingUid() == proxyInfo.getUid()
+                    && proxyPackageName.equals(proxyInfo.getPackageName())
+                    && Objects.equals(proxyAttributionTag, proxyInfo.getAttributionTag());
+        });
+        return false;
+    }
+
+    @Override
+    public void resetPackageOpsNoHistory(@NonNull String packageName) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
+                "resetPackageOpsNoHistory");
+        synchronized (AppOpsService.this) {
+            final int uid = mPackageManagerInternal.getPackageUid(packageName, 0,
+                    UserHandle.getCallingUserId());
+            if (uid == Process.INVALID_UID) {
+                return;
+            }
+            UidState uidState = mUidStates.get(uid);
+            if (uidState == null || uidState.pkgOps == null) {
+                return;
+            }
+            Ops removedOps = uidState.pkgOps.remove(packageName);
+            if (removedOps != null) {
+                scheduleFastWriteLocked();
+            }
+        }
+    }
+
+    @Override
     public void setHistoryParameters(@AppOpsManager.HistoricalMode int mode,
             long baseSnapshotInterval, int compressionStep) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
@@ -6455,6 +6675,7 @@
                 return Process.ROOT_UID;
             case "shell":
             case "dumpstate":
+            case "com.android.shell":
                 return Process.SHELL_UID;
             case "media":
                 return Process.MEDIA_UID;
@@ -6831,5 +7052,29 @@
                     shouldCollectAsyncNotedOp, message, shouldCollectMessage,
                     AppOpsService.this::noteOperationImpl);
         }
+
+        public int noteProxyOperationImpl(int code, @NonNull AttributionSource attributionSource,
+                boolean shouldCollectAsyncNotedOp, @Nullable String message,
+                boolean shouldCollectMessage, boolean skipProxyOperation) {
+            return mCheckOpsDelegate.noteProxyOperation(code, attributionSource,
+                    shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation,
+                    AppOpsService.this::noteProxyOperationImpl);
+        }
+
+        public int startProxyOperationImpl(IBinder token, int code,
+                @NonNull AttributionSource attributionSource, boolean startIfModeDefault,
+                boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
+                boolean skipProxyOperation) {
+            return mCheckOpsDelegate.startProxyOperation(token, code, attributionSource,
+                    startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage,
+                    skipProxyOperation, AppOpsService.this::startProxyOperationImpl);
+        }
+
+        public Void finishProxyOperationImpl(IBinder clientId, int code,
+                @NonNull AttributionSource attributionSource) {
+            mCheckOpsDelegate.finishProxyOperation(clientId, code, attributionSource,
+                    AppOpsService.this::finishProxyOperationImpl);
+            return null;
+        }
     }
 }
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index b31fa70..d16a2de 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -201,6 +201,9 @@
     // Set to true when partial connectivity was detected.
     public boolean partialConnectivity;
 
+    // Delay between when the network is disconnected and when the native network is destroyed.
+    public int teardownDelayMs;
+
     // Captive portal info of the network from RFC8908, if any.
     // Obtained by ConnectivityService and merged into NetworkAgent-provided information.
     public CaptivePortalData capportApiData;
@@ -589,13 +592,13 @@
     }
 
     /**
-     * Notify the NetworkAgent that the network is disconnected and destroyed.
+     * Notify the NetworkAgent that the native network has been destroyed.
      */
-    public void onNetworkDisconnected() {
+    public void onNetworkDestroyed() {
         try {
-            networkAgent.onNetworkDisconnected();
+            networkAgent.onNetworkDestroyed();
         } catch (RemoteException e) {
-            Log.e(TAG, "Error sending network disconnected event", e);
+            Log.e(TAG, "Error sending network destroyed event", e);
         }
     }
 
@@ -675,6 +678,12 @@
                 @QosCallbackException.ExceptionType final int exceptionType) {
             mQosCallbackTracker.sendEventQosCallbackError(qosCallbackId, exceptionType);
         }
+
+        @Override
+        public void sendTeardownDelayMs(int teardownDelayMs) {
+            mHandler.obtainMessage(NetworkAgent.EVENT_TEARDOWN_DELAY_CHANGED,
+                    teardownDelayMs, 0, new Pair<>(NetworkAgentInfo.this, null)).sendToTarget();
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index a070f27..820198c 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -464,7 +464,7 @@
                 .addTransportType(NetworkCapabilities.TRANSPORT_VPN)
                 .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
                 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
-                .setTransportInfo(new VpnTransportInfo(VpnManager.TYPE_VPN_NONE))
+                .setTransportInfo(new VpnTransportInfo(VpnManager.TYPE_VPN_NONE, null))
                 .build();
 
         loadAlwaysOnPackage();
@@ -528,7 +528,7 @@
     private void resetNetworkCapabilities() {
         mNetworkCapabilities = new NetworkCapabilities.Builder(mNetworkCapabilities)
                 .setUids(null)
-                .setTransportInfo(new VpnTransportInfo(VpnManager.TYPE_VPN_NONE))
+                .setTransportInfo(new VpnTransportInfo(VpnManager.TYPE_VPN_NONE, null))
                 .build();
     }
 
@@ -1259,7 +1259,7 @@
         capsBuilder.setUids(createUserAndRestrictedProfilesRanges(mUserId,
                 mConfig.allowedApplications, mConfig.disallowedApplications));
 
-        capsBuilder.setTransportInfo(new VpnTransportInfo(getActiveVpnType()));
+        capsBuilder.setTransportInfo(new VpnTransportInfo(getActiveVpnType(), mConfig.session));
 
         // Only apps targeting Q and above can explicitly declare themselves as metered.
         // These VPNs are assumed metered unless they state otherwise.
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index e4e520f..9d02576 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -203,6 +203,8 @@
     private WindowManagerInternal mWindowManagerInternal;
     private InputManagerInternal mInputManagerInternal;
     private IMediaProjectionManager mProjectionService;
+    private int[] mUserDisabledHdrTypes = {};
+    private boolean mAreUserDisabledHdrTypesAllowed = true;
 
     // The synchronization root for the display manager.
     // This lock guards most of the display manager's state.
@@ -557,6 +559,8 @@
             recordTopInsetLocked(mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY));
 
             updateSettingsLocked();
+
+            updateUserDisabledHdrTypesFromSettingsLocked();
         }
 
         mDisplayModeDirector.setDesiredDisplayModeSpecsListener(
@@ -566,6 +570,7 @@
         mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
 
         mSettingsObserver = new SettingsObserver();
+
         mBrightnessSynchronizer.startSynchronizing();
     }
 
@@ -737,6 +742,42 @@
                 Settings.Secure.MINIMAL_POST_PROCESSING_ALLOWED, 1, UserHandle.USER_CURRENT) != 0;
     }
 
+    private void updateUserDisabledHdrTypesFromSettingsLocked() {
+        mAreUserDisabledHdrTypesAllowed = (Settings.Global.getInt(
+                mContext.getContentResolver(),
+                Settings.Global.ARE_USER_DISABLED_HDR_FORMATS_ALLOWED,
+                1) != 0);
+
+        String userDisabledHdrTypes = Settings.Global.getString(mContext.getContentResolver(),
+                Settings.Global.USER_DISABLED_HDR_FORMATS);
+
+        if (userDisabledHdrTypes != null) {
+            try {
+                String[] userDisabledHdrTypeStrings =
+                        TextUtils.split(userDisabledHdrTypes, ",");
+                mUserDisabledHdrTypes = new int[userDisabledHdrTypeStrings.length];
+                for (int i = 0; i < userDisabledHdrTypeStrings.length; i++) {
+                    mUserDisabledHdrTypes[i] = Integer.parseInt(userDisabledHdrTypeStrings[i]);
+                }
+            } catch (NumberFormatException e) {
+                Slog.e(TAG,
+                        "Failed to parse USER_DISABLED_HDR_FORMATS. "
+                                + "Clearing the setting.", e);
+                clearUserDisabledHdrTypesLocked();
+            }
+        } else {
+            clearUserDisabledHdrTypesLocked();
+        }
+    }
+
+    private void clearUserDisabledHdrTypesLocked() {
+        mUserDisabledHdrTypes = new int[]{};
+        synchronized (mSyncRoot) {
+            Settings.Global.putString(mContext.getContentResolver(),
+                    Settings.Global.USER_DISABLED_HDR_FORMATS, "");
+        }
+    }
+
     private DisplayInfo getDisplayInfoForFrameRateOverride(DisplayEventReceiver.FrameRateOverride[]
             frameRateOverrides, DisplayInfo info, int callingUid) {
         float frameRateHz = 0;
@@ -957,6 +998,61 @@
         }
     }
 
+    private void setUserDisabledHdrTypesInternal(int[] userDisabledHdrTypes) {
+        synchronized (mSyncRoot) {
+            if (userDisabledHdrTypes == null) {
+                Slog.e(TAG, "Null is not an expected argument to "
+                        + "setUserDisabledHdrTypesInternal");
+                return;
+            }
+            Arrays.sort(userDisabledHdrTypes);
+            if (Arrays.equals(mUserDisabledHdrTypes, userDisabledHdrTypes)) {
+                return;
+            }
+            String userDisabledFormatsString = "";
+            if (userDisabledHdrTypes.length != 0) {
+                userDisabledFormatsString = TextUtils.join(",",
+                        Arrays.stream(userDisabledHdrTypes).boxed().toArray());
+            }
+            Settings.Global.putString(mContext.getContentResolver(),
+                    Settings.Global.USER_DISABLED_HDR_FORMATS, userDisabledFormatsString);
+            mUserDisabledHdrTypes = userDisabledHdrTypes;
+            if (!mAreUserDisabledHdrTypesAllowed) {
+                mLogicalDisplayMapper.forEachLocked(
+                        display -> {
+                            display.setUserDisabledHdrTypes(userDisabledHdrTypes);
+                            handleLogicalDisplayChangedLocked(display);
+                        });
+            }
+        }
+    }
+
+    private void setAreUserDisabledHdrTypesAllowedInternal(
+            boolean areUserDisabledHdrTypesAllowed) {
+        synchronized (mSyncRoot) {
+            if (mAreUserDisabledHdrTypesAllowed == areUserDisabledHdrTypesAllowed) {
+                return;
+            }
+            mAreUserDisabledHdrTypesAllowed = areUserDisabledHdrTypesAllowed;
+            if (mUserDisabledHdrTypes.length == 0) {
+                return;
+            }
+            Settings.Global.putInt(mContext.getContentResolver(),
+                    Settings.Global.ARE_USER_DISABLED_HDR_FORMATS_ALLOWED,
+                    areUserDisabledHdrTypesAllowed ? 1 : 0);
+            int userDisabledHdrTypes[] = {};
+            if (!mAreUserDisabledHdrTypesAllowed) {
+                userDisabledHdrTypes = mUserDisabledHdrTypes;
+            }
+            int[] finalUserDisabledHdrTypes = userDisabledHdrTypes;
+            mLogicalDisplayMapper.forEachLocked(
+                    display -> {
+                        display.setUserDisabledHdrTypes(finalUserDisabledHdrTypes);
+                        handleLogicalDisplayChangedLocked(display);
+                    });
+        }
+    }
+
     private void requestColorModeInternal(int displayId, int colorMode) {
         synchronized (mSyncRoot) {
             final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
@@ -1130,6 +1226,9 @@
         final int displayId = display.getDisplayIdLocked();
         final boolean isDefault = displayId == Display.DEFAULT_DISPLAY;
         configureColorModeLocked(display, device);
+        if (!mAreUserDisabledHdrTypesAllowed) {
+            display.setUserDisabledHdrTypes(mUserDisabledHdrTypes);
+        }
         if (isDefault) {
             recordStableDisplayStatsIfNeededLocked(display);
             recordTopInsetLocked(display);
@@ -1810,6 +1909,14 @@
             pw.println("  mMinimumBrightnessCurve=" + mMinimumBrightnessCurve);
 
             pw.println();
+            if (!mAreUserDisabledHdrTypesAllowed) {
+                pw.println("  mUserDisabledHdrTypes: size=" + mUserDisabledHdrTypes.length);
+                for (int type : mUserDisabledHdrTypes) {
+                    pw.println("  " + type);
+                }
+            }
+
+            pw.println();
             final int displayStateCount = mDisplayStates.size();
             pw.println("Display States: size=" + displayStateCount);
             for (int i = 0; i < displayStateCount; i++) {
@@ -2337,6 +2444,45 @@
         }
 
         @Override // Binder call
+        public void setUserDisabledHdrTypes(int[] userDisabledFormats) {
+            mContext.enforceCallingOrSelfPermission(
+                    Manifest.permission.WRITE_SECURE_SETTINGS,
+                    "Permission required to write the user settings.");
+
+            final long token = Binder.clearCallingIdentity();
+            try {
+                setUserDisabledHdrTypesInternal(userDisabledFormats);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override // Binder call
+        public void setAreUserDisabledHdrTypesAllowed(boolean areUserDisabledHdrTypesAllowed) {
+            mContext.enforceCallingOrSelfPermission(
+                    Manifest.permission.WRITE_SECURE_SETTINGS,
+                    "Permission required to write the user settings.");
+            final long token = Binder.clearCallingIdentity();
+            try {
+                setAreUserDisabledHdrTypesAllowedInternal(areUserDisabledHdrTypesAllowed);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override // Binder call
+        public boolean areUserDisabledHdrTypesAllowed() {
+            synchronized (mSyncRoot) {
+                return mAreUserDisabledHdrTypesAllowed;
+            }
+        }
+
+        @Override // Binder call
+        public int[] getUserDisabledHdrTypes() {
+            return mUserDisabledHdrTypes;
+        }
+
+        @Override // Binder call
         public void requestColorMode(int displayId, int colorMode) {
             mContext.enforceCallingOrSelfPermission(
                     Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE,
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index d9570c7..1589419 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -102,6 +102,8 @@
     private int mRequestedColorMode;
     private boolean mRequestedMinimalPostProcessing;
 
+    private int[] mUserDisabledHdrTypes = {};
+
     private DisplayModeDirector.DesiredDisplayModeSpecs mDesiredDisplayModeSpecs =
             new DisplayModeDirector.DesiredDisplayModeSpecs();
 
@@ -367,6 +369,7 @@
                     deviceInfo.supportedColorModes,
                     deviceInfo.supportedColorModes.length);
             mBaseDisplayInfo.hdrCapabilities = deviceInfo.hdrCapabilities;
+            mBaseDisplayInfo.userDisabledHdrTypes = mUserDisabledHdrTypes;
             mBaseDisplayInfo.minimalPostProcessingSupported =
                     deviceInfo.allmSupported || deviceInfo.gameContentTypeSupported;
             mBaseDisplayInfo.logicalDensityDpi = deviceInfo.densityDpi;
@@ -680,6 +683,14 @@
         mDisplayScalingDisabled = disableScaling;
     }
 
+    public void setUserDisabledHdrTypes(@NonNull int[] userDisabledHdrTypes) {
+        if (mUserDisabledHdrTypes != userDisabledHdrTypes) {
+            mUserDisabledHdrTypes = userDisabledHdrTypes;
+            mBaseDisplayInfo.userDisabledHdrTypes = userDisabledHdrTypes;
+            mInfo.set(null);
+        }
+    }
+
     /**
      * Swap the underlying {@link DisplayDevice} with the specified LogicalDisplay.
      *
diff --git a/services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java b/services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java
index 6201b94..5abc438 100644
--- a/services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java
+++ b/services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java
@@ -52,7 +52,8 @@
 
     // Entries added by LockSettingsService once a user's synthetic password is known. At this point
     // things are still keyed by userId.
-    @NonNull private final ArrayList<UserAuthInfo> mPendingResetLockouts;
+    @NonNull private final ArrayList<UserAuthInfo> mPendingResetLockoutsForFingerprint;
+    @NonNull private final ArrayList<UserAuthInfo> mPendingResetLockoutsForFace;
 
     /**
      * Authentication info for a successful user unlock via Synthetic Password. This can be used to
@@ -151,7 +152,8 @@
         mContext = context;
         mSpManager = spManager;
         mHandler = handler;
-        mPendingResetLockouts = new ArrayList<>();
+        mPendingResetLockoutsForFingerprint = new ArrayList<>();
+        mPendingResetLockoutsForFace = new ArrayList<>();
     }
 
     public void systemReady(@Nullable FingerprintManager fingerprintManager,
@@ -173,17 +175,34 @@
      */
     void addPendingLockoutResetForUser(int userId, @NonNull byte[] gatekeeperPassword) {
         mHandler.post(() -> {
-            Slog.d(TAG, "addPendingLockoutResetForUser: " + userId);
-            mPendingResetLockouts.add(new UserAuthInfo(userId, gatekeeperPassword));
+            if (mFaceManager != null && mFaceManager.hasEnrolledTemplates(userId)) {
+                Slog.d(TAG, "Face addPendingLockoutResetForUser: " + userId);
+                mPendingResetLockoutsForFace.add(new UserAuthInfo(userId, gatekeeperPassword));
+            }
+
+            if (mFingerprintManager != null
+                    && mFingerprintManager.hasEnrolledFingerprints(userId)) {
+                Slog.d(TAG, "Fingerprint addPendingLockoutResetForUser: " + userId);
+                mPendingResetLockoutsForFingerprint.add(new UserAuthInfo(userId,
+                        gatekeeperPassword));
+            }
         });
     }
 
     void processPendingLockoutResets() {
         mHandler.post(() -> {
-            Slog.d(TAG, "processPendingLockoutResets: " + mPendingResetLockouts.size());
-            processPendingLockoutsForFingerprint(new ArrayList<>(mPendingResetLockouts));
-            processPendingLockoutsForFace(new ArrayList<>(mPendingResetLockouts));
-            mPendingResetLockouts.clear();
+            if (!mPendingResetLockoutsForFace.isEmpty()) {
+                Slog.d(TAG, "Processing pending resetLockout for face");
+                processPendingLockoutsForFace(new ArrayList<>(mPendingResetLockoutsForFace));
+                mPendingResetLockoutsForFace.clear();
+            }
+
+            if (!mPendingResetLockoutsForFingerprint.isEmpty()) {
+                Slog.d(TAG, "Processing pending resetLockout for fingerprint");
+                processPendingLockoutsForFingerprint(
+                        new ArrayList<>(mPendingResetLockoutsForFingerprint));
+                mPendingResetLockoutsForFingerprint.clear();
+            }
         });
     }
 
diff --git a/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java b/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java
index cb0a6688..bb996a0 100644
--- a/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java
+++ b/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java
@@ -64,13 +64,6 @@
     private static final int PACKAGE_MANAGER_COMMON_FLAGS =
             PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
 
-    /**
-     * Denotes the duration during which a media button receiver will be exempted from
-     * FGS-from-BG restriction and so will be allowed to start an FGS even if it is in the
-     * background state while it receives a media key event.
-     */
-    private static final long FGS_STARTS_TEMP_ALLOWLIST_DURATION_MS = 10_000;
-
     private final int mUserId;
     private final PendingIntent mPendingIntent;
     private final ComponentName mComponentName;
@@ -185,10 +178,13 @@
      *                           Ignored if there's no valid pending intent.
      * @param handler handler to be used to call onFinishedListener
      *                Ignored if there's no valid pending intent.
+     * @param fgsAllowlistDurationMs duration for which the media button receiver will be
+     *                               allowed to start FGS from BG.
      * @see PendingIntent#send(Context, int, Intent, PendingIntent.OnFinished, Handler)
      */
     public boolean send(Context context, KeyEvent keyEvent, String callingPackageName,
-            int resultCode, PendingIntent.OnFinished onFinishedListener, Handler handler) {
+            int resultCode, PendingIntent.OnFinished onFinishedListener, Handler handler,
+            long fgsAllowlistDurationMs) {
         Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
         mediaButtonIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
         mediaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
@@ -196,7 +192,7 @@
         mediaButtonIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, callingPackageName);
 
         final BroadcastOptions options = BroadcastOptions.makeBasic();
-        options.setTemporaryAppAllowlist(FGS_STARTS_TEMP_ALLOWLIST_DURATION_MS,
+        options.setTemporaryAppAllowlist(fgsAllowlistDurationMs,
                 PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
                 PowerWhitelistManager.REASON_MEDIA_BUTTON, "");
         if (mPendingIntent != null) {
diff --git a/services/core/java/com/android/server/media/MediaSessionDeviceConfig.java b/services/core/java/com/android/server/media/MediaSessionDeviceConfig.java
new file mode 100644
index 0000000..9bb8e2e
--- /dev/null
+++ b/services/core/java/com/android/server/media/MediaSessionDeviceConfig.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2021 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.media;
+
+import android.content.Context;
+import android.provider.DeviceConfig;
+import android.text.TextUtils;
+
+import java.io.PrintWriter;
+import java.util.Set;
+
+class MediaSessionDeviceConfig {
+    /**
+     * Denotes the duration for which a media button receiver will be exempted from
+     * FGS-from-BG restriction and so will be allowed to start an FGS even if it is in the
+     * background state while it receives a media key event.
+     */
+    private static final String KEY_MEDIA_BUTTON_RECEIVER_FGS_ALLOWLIST_DURATION_MS =
+            "media_button_receiver_fgs_allowlist_duration_ms";
+    private static final long DEFAULT_MEDIA_BUTTON_RECEIVER_FGS_ALLOWLIST_DURATION_MS = 10_000;
+    private static volatile long sMediaButtonReceiverFgsAllowlistDurationMs =
+            DEFAULT_MEDIA_BUTTON_RECEIVER_FGS_ALLOWLIST_DURATION_MS;
+
+    /**
+     * Denotes the duration for which an app receiving a media session callback will be
+     * exempted from FGS-from-BG restriction and so will be allowed to start an FGS even if
+     * it is in the background state while it receives a media session callback.
+     */
+    private static final String KEY_MEDIA_SESSION_CALLBACK_FGS_ALLOWLIST_DURATION_MS =
+            "media_session_calback_fgs_allowlist_duration_ms";
+    private static final long DEFAULT_MEDIA_SESSION_CALLBACK_FGS_ALLOWLIST_DURATION_MS = 10_000;
+    private static volatile long sMediaSessionCallbackFgsAllowlistDurationMs =
+            DEFAULT_MEDIA_SESSION_CALLBACK_FGS_ALLOWLIST_DURATION_MS;
+
+    private static void refresh(DeviceConfig.Properties properties) {
+        final Set<String> keys = properties.getKeyset();
+        properties.getKeyset().forEach(key -> {
+            switch (key) {
+                case KEY_MEDIA_BUTTON_RECEIVER_FGS_ALLOWLIST_DURATION_MS:
+                    sMediaButtonReceiverFgsAllowlistDurationMs = properties.getLong(key,
+                            DEFAULT_MEDIA_BUTTON_RECEIVER_FGS_ALLOWLIST_DURATION_MS);
+                    break;
+                case KEY_MEDIA_SESSION_CALLBACK_FGS_ALLOWLIST_DURATION_MS:
+                    sMediaSessionCallbackFgsAllowlistDurationMs = properties.getLong(key,
+                            DEFAULT_MEDIA_SESSION_CALLBACK_FGS_ALLOWLIST_DURATION_MS);
+                    break;
+            }
+        });
+    }
+
+    public static void initialize(Context context) {
+        DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_MEDIA,
+                context.getMainExecutor(), properties -> refresh(properties));
+        refresh(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_MEDIA));
+    }
+
+    /**
+     * Returns the duration for which a media button receiver will be exempted from
+     * FGS-from-BG restriction and so will be allowed to start an FGS even if it is in the
+     * background state while it receives a media key event.
+     */
+    public static long getMediaButtonReceiverFgsAllowlistDurationMs() {
+        return sMediaButtonReceiverFgsAllowlistDurationMs;
+    }
+
+    /**
+     * Returns the duration for which an app receiving a media session callback will be
+     * exempted from FGS-from-BG restriction and so will be allowed to start an FGS even if
+     * it is in the background state while it receives a media session callback.
+     */
+    public static long getMediaSessionCallbackFgsAllowlistDurationMs() {
+        return sMediaSessionCallbackFgsAllowlistDurationMs;
+    }
+
+    public static void dump(PrintWriter pw, String prefix) {
+        pw.println("Media session config:");
+        final String dumpFormat = prefix + "  %s: [cur: %s, def: %s]";
+        pw.println(TextUtils.formatSimple(dumpFormat,
+                KEY_MEDIA_BUTTON_RECEIVER_FGS_ALLOWLIST_DURATION_MS,
+                sMediaButtonReceiverFgsAllowlistDurationMs,
+                DEFAULT_MEDIA_BUTTON_RECEIVER_FGS_ALLOWLIST_DURATION_MS));
+        pw.println(TextUtils.formatSimple(dumpFormat,
+                KEY_MEDIA_SESSION_CALLBACK_FGS_ALLOWLIST_DURATION_MS,
+                sMediaSessionCallbackFgsAllowlistDurationMs,
+                DEFAULT_MEDIA_SESSION_CALLBACK_FGS_ALLOWLIST_DURATION_MS));
+    }
+}
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index a30d993..50cfe1f 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -117,13 +117,6 @@
      */
     private static final String MEDIA_BUTTON_RECEIVER = "media_button_receiver";
 
-    /**
-     * Denotes the duration during which an app receiving a media session callback will be
-     * exempted from FGS-from-BG restriction and so will be allowed to start an FGS even if it is
-     * in the background state while it receives a media session callback.
-     */
-    private static final long FGS_STARTS_TEMP_ALLOWLIST_DURATION_MS = 10_000;
-
     private final Context mContext;
     private final SessionManagerImpl mSessionManagerImpl;
     private final MessageHandler mHandler = new MessageHandler();
@@ -244,6 +237,9 @@
                 mCommunicationManager.registerSessionCallback(new HandlerExecutor(mHandler),
                         mSession2TokenCallback);
                 break;
+            case PHASE_ACTIVITY_MANAGER_READY:
+                MediaSessionDeviceConfig.initialize(mContext);
+                break;
         }
     }
 
@@ -564,7 +560,7 @@
                         PowerExemptionManager.class);
                 powerExemptionManager.addToTemporaryAllowList(targetPackage,
                         PowerExemptionManager.REASON_MEDIA_SESSION_CALLBACK, reason,
-                        FGS_STARTS_TEMP_ALLOWLIST_DURATION_MS);
+                        MediaSessionDeviceConfig.getMediaSessionCallbackFgsAllowlistDurationMs());
             }
         } finally {
             Binder.restoreCallingIdentity(token);
@@ -1979,6 +1975,7 @@
                 }
                 mAudioPlayerStateMonitor.dump(mContext, pw, "");
             }
+            MediaSessionDeviceConfig.dump(pw, "");
         }
 
         /**
@@ -2262,7 +2259,8 @@
                 boolean sent = mediaButtonReceiverHolder.send(
                         mContext, keyEvent, callingPackageName,
                         needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1, mKeyEventReceiver,
-                        mHandler);
+                        mHandler,
+                        MediaSessionDeviceConfig.getMediaButtonReceiverFgsAllowlistDurationMs());
                 if (sent) {
                     String pkgName = mediaButtonReceiverHolder.getPackageName();
                     for (FullUserRecord.OnMediaKeyEventDispatchedListenerRecord cr
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index de5aae0..19f5e3c 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -24,6 +24,7 @@
 import static android.content.Intent.ACTION_USER_REMOVED;
 import static android.content.Intent.EXTRA_UID;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.net.NetworkIdentity.SUBTYPE_COMBINED;
 import static android.net.NetworkStack.checkNetworkStackPermission;
 import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
@@ -65,6 +66,7 @@
 import static android.provider.Settings.Global.NETSTATS_UID_TAG_DELETE_AGE;
 import static android.provider.Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES;
 import static android.provider.Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE;
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 import static android.text.format.DateUtils.DAY_IN_MILLIS;
 import static android.text.format.DateUtils.HOUR_IN_MILLIS;
 import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
@@ -100,7 +102,9 @@
 import android.net.NetworkStats;
 import android.net.NetworkStats.NonMonotonicObserver;
 import android.net.NetworkStatsHistory;
+import android.net.NetworkSpecifier;
 import android.net.NetworkTemplate;
+import android.net.TelephonyNetworkSpecifier;
 import android.net.TrafficStats;
 import android.net.UnderlyingNetworkInfo;
 import android.net.Uri;
@@ -1320,8 +1324,9 @@
                             ident.getSubType(), ident.getSubscriberId(), ident.getNetworkId(),
                             ident.getRoaming(), true /* metered */,
                             true /* onDefaultNetwork */, ident.getOemManaged());
-                    findOrCreateNetworkIdentitySet(mActiveIfaces, IFACE_VT).add(vtIdent);
-                    findOrCreateNetworkIdentitySet(mActiveUidIfaces, IFACE_VT).add(vtIdent);
+                    final String ifaceVt = IFACE_VT + getSubIdForMobile(snapshot);
+                    findOrCreateNetworkIdentitySet(mActiveIfaces, ifaceVt).add(vtIdent);
+                    findOrCreateNetworkIdentitySet(mActiveUidIfaces, ifaceVt).add(vtIdent);
                 }
 
                 if (isMobile) {
@@ -1377,6 +1382,20 @@
         mMobileIfaces = mobileIfaces.toArray(new String[mobileIfaces.size()]);
     }
 
+    private static int getSubIdForMobile(@NonNull NetworkStateSnapshot state) {
+        if (!state.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
+            throw new IllegalArgumentException("Mobile state need capability TRANSPORT_CELLULAR");
+        }
+
+        final NetworkSpecifier spec = state.networkCapabilities.getNetworkSpecifier();
+        if (spec instanceof TelephonyNetworkSpecifier) {
+             return ((TelephonyNetworkSpecifier) spec).getSubscriptionId();
+        } else {
+            Slog.wtf(TAG, "getSubIdForState invalid NetworkSpecifier");
+            return INVALID_SUBSCRIPTION_ID;
+        }
+    }
+
     /**
      * For networks with {@code TRANSPORT_CELLULAR}, get subType that was obtained through
      * {@link PhoneStateListener}. Otherwise, return 0 given that other networks with different
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 4fc97ef..68990ba 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3617,34 +3617,6 @@
         }
 
         @Override
-        public void deleteConversationNotificationChannels(String pkg, int uid,
-                String conversationId) {
-            checkCallerIsSystem();
-            List<NotificationChannel> channels =
-                    mPreferencesHelper.getNotificationChannelsByConversationId(
-                            pkg, uid, conversationId);
-            if (!channels.isEmpty()) {
-                // Preflight for fg service notifications in these channels:  do nothing
-                // unless they're all eligible
-                final int appUserId = UserHandle.getUserId(uid);
-                for (NotificationChannel nc : channels) {
-                    final String channelId = nc.getId();
-                    mAmi.stopForegroundServicesForChannel(pkg, appUserId, channelId);
-                    cancelAllNotificationsInt(MY_UID, MY_PID, pkg, nc.getId(), 0, 0, true,
-                            appUserId, REASON_CHANNEL_REMOVED, null);
-                    mPreferencesHelper.deleteNotificationChannel(pkg, uid, channelId);
-                    mListeners.notifyNotificationChannelChanged(pkg,
-                            UserHandle.getUserHandleForUid(uid),
-                            mPreferencesHelper.getNotificationChannel(
-                                    pkg, uid, channelId, true),
-                            NOTIFICATION_CHANNEL_OR_GROUP_DELETED);
-                }
-                handleSavePolicyFile();
-            }
-        }
-
-
-        @Override
         public NotificationChannelGroup getNotificationChannelGroup(String pkg, String groupId) {
             checkCallerIsSystemOrSameApp(pkg);
             return mPreferencesHelper.getNotificationChannelGroupWithChannels(
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index e0a39f3..b02b8f2 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -258,23 +258,22 @@
                         packageStats, options.isDowngrade(), profileName, dexMetadataPath,
                         options.getCompilationReason());
 
-                // Only report metrics for base apk for now.
-                // TODO: add ISA and APK type to metrics.
                 // OTAPreopt doesn't have stats so don't report in that case.
-                if (pkg.getBaseApkPath().equals(path) && packageStats != null) {
+                if (packageStats != null) {
                     Trace.traceBegin(Trace.TRACE_TAG_PACKAGE_MANAGER, "dex2oat-metrics");
                     try {
                         long sessionId = Math.randomLongInternal();
                         ArtStatsLogUtils.writeStatsLog(
                                 mArtStatsLogger,
                                 sessionId,
-                                path,
                                 compilerFilter,
                                 sharedGid,
                                 packageStats.getCompileTime(path),
                                 dexMetadataPath,
                                 options.getCompilationReason(),
-                                newResult);
+                                newResult,
+                                ArtStatsLogUtils.getApkType(path),
+                                dexCodeIsa);
                     } finally {
                         Trace.traceEnd(Trace.TRACE_TAG_PACKAGE_MANAGER);
                     }
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index e1d1c26..d86438b 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -171,7 +171,7 @@
     static final int DEFAULT_MAX_UPDATES_PER_INTERVAL = 10;
 
     @VisibleForTesting
-    static final int DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY = Integer.MAX_VALUE;
+    static final int DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY = 15;
 
     @VisibleForTesting
     static final int DEFAULT_MAX_ICON_DIMENSION_DP = 96;
@@ -270,6 +270,7 @@
     final Context mContext;
 
     private final Object mLock = new Object();
+    private final Object mNonPersistentUsersLock = new Object();
 
     private static List<ResolveInfo> EMPTY_RESOLVE_INFO = new ArrayList<>(0);
 
@@ -310,8 +311,10 @@
 
     /**
      * User ID -> ShortcutNonPersistentUser
+     *
+     * Note we use a fine-grained lock for {@link #mShortcutNonPersistentUsers} due to b/183618378.
      */
-    @GuardedBy("mLock")
+    @GuardedBy("mNonPersistentUsersLock")
     private final SparseArray<ShortcutNonPersistentUser> mShortcutNonPersistentUsers =
             new SparseArray<>();
 
@@ -1308,7 +1311,7 @@
     }
 
     /** Return the non-persistent per-user state. */
-    @GuardedBy("mLock")
+    @GuardedBy("mNonPersistentUsersLock")
     @NonNull
     ShortcutNonPersistentUser getNonPersistentUserLocked(@UserIdInt int userId) {
         ShortcutNonPersistentUser ret = mShortcutNonPersistentUsers.get(userId);
@@ -2748,7 +2751,7 @@
         if (injectHasAccessShortcutsPermission(callingPid, callingUid)) {
             return true;
         }
-        synchronized (mLock) {
+        synchronized (mNonPersistentUsersLock) {
             return getNonPersistentUserLocked(userId).hasHostPackage(callingPackage);
         }
     }
@@ -2831,7 +2834,7 @@
 
     public void setShortcutHostPackage(@NonNull String type, @Nullable String packageName,
             int userId) {
-        synchronized (mLock) {
+        synchronized (mNonPersistentUsersLock) {
             getNonPersistentUserLocked(userId).setShortcutHostPackage(type, packageName);
         }
     }
diff --git a/services/core/java/com/android/server/pm/ShortcutUser.java b/services/core/java/com/android/server/pm/ShortcutUser.java
index ce49d88..5f0aa03 100644
--- a/services/core/java/com/android/server/pm/ShortcutUser.java
+++ b/services/core/java/com/android/server/pm/ShortcutUser.java
@@ -333,10 +333,7 @@
 
         if (!shortcutPackage.rescanPackageIfNeeded(isNewApp, forceRescan)) {
             if (isNewApp) {
-                final ShortcutPackage sp = mPackages.remove(packageName);
-                if (sp != null) {
-                    sp.removeShortcuts();
-                }
+                mPackages.remove(packageName);
             }
         }
     }
diff --git a/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java b/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java
index c8dc1b1..f99a3c3 100644
--- a/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java
+++ b/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java
@@ -39,6 +39,7 @@
     private static final String TAG = ArtStatsLogUtils.class.getSimpleName();
     private static final String PROFILE_DEX_METADATA = "primary.prof";
     private static final String VDEX_DEX_METADATA = "primary.vdex";
+    private static final String BASE_APK= "base.apk";
 
 
     private static final int ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY =
@@ -122,16 +123,34 @@
                 ART_COMPILATION_FILTER_FAKE_RUN_FROM_VDEX_FALLBACK);
     }
 
+    private static final Map<String, Integer> ISA_MAP = new HashMap();
+
+    static {
+        COMPILE_FILTER_MAP.put("arm", ArtStatsLog.
+                ART_DATUM_REPORTED__ISA__ART_ISA_ARM);
+        COMPILE_FILTER_MAP.put("arm64", ArtStatsLog.
+                ART_DATUM_REPORTED__ISA__ART_ISA_ARM64);
+        COMPILE_FILTER_MAP.put("x86", ArtStatsLog.
+                ART_DATUM_REPORTED__ISA__ART_ISA_X86);
+        COMPILE_FILTER_MAP.put("x86_64", ArtStatsLog.
+                ART_DATUM_REPORTED__ISA__ART_ISA_X86_64);
+        COMPILE_FILTER_MAP.put("mips", ArtStatsLog.
+                ART_DATUM_REPORTED__ISA__ART_ISA_MIPS);
+        COMPILE_FILTER_MAP.put("mips64", ArtStatsLog.
+                ART_DATUM_REPORTED__ISA__ART_ISA_MIPS64);
+    }
+
     public static void writeStatsLog(
             ArtStatsLogger logger,
             long sessionId,
-            String path,
             String compilerFilter,
             int uid,
             long compileTime,
             String dexMetadataPath,
             int compilationReason,
-            int result) {
+            int result,
+            int apkType,
+            String isa) {
         int dexMetadataType = getDexMetadataType(dexMetadataPath);
         logger.write(
                 sessionId,
@@ -140,7 +159,9 @@
                 compilerFilter,
                 ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_RESULT_CODE,
                 result,
-                dexMetadataType);
+                dexMetadataType,
+                apkType,
+                isa);
         logger.write(
                 sessionId,
                 uid,
@@ -148,7 +169,16 @@
                 compilerFilter,
                 ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_TOTAL_TIME,
                 compileTime,
-                dexMetadataType);
+                dexMetadataType,
+                apkType,
+                isa);
+    }
+
+    public static int getApkType(String path) {
+        if (path.equals(BASE_APK)) {
+            return ArtStatsLog.ART_DATUM_REPORTED__APK_TYPE__ART_APK_TYPE_BASE;
+        }
+        return ArtStatsLog.ART_DATUM_REPORTED__APK_TYPE__ART_APK_TYPE_SPLIT;
     }
 
     private static int getDexMetadataType(String dexMetadataPath) {
@@ -207,7 +237,9 @@
                 String compilerFilter,
                 int kind,
                 long value,
-                int dexMetadataType) {
+                int dexMetadataType,
+                int apkType,
+                String isa) {
             ArtStatsLog.write(
                     ArtStatsLog.ART_DATUM_REPORTED,
                     sessionId,
@@ -220,7 +252,10 @@
                     ArtStatsLog.ART_DATUM_REPORTED__THREAD_TYPE__ART_THREAD_MAIN,
                     kind,
                     value,
-                    dexMetadataType);
+                    dexMetadataType,
+                    apkType,
+                    ISA_MAP.getOrDefault(isa,
+                            ArtStatsLog.ART_DATUM_REPORTED__ISA__ART_ISA_UNKNOWN));
         }
     }
 }
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index e16c67f..9bc9d9f 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -278,7 +278,7 @@
             try {
                 return mContext.getPackageManager().getPermissionInfo(permissionName, 0);
             } catch (NameNotFoundException e) {
-                Slog.e(TAG, "Permission not found: " + permissionName);
+                Slog.w(TAG, "Permission not found: " + permissionName);
                 return null;
             }
         }
@@ -737,10 +737,9 @@
                 grantPermissionsToSystemPackage(pm, packageName, userId,
                         CONTACTS_PERMISSIONS, CALENDAR_PERMISSIONS, MICROPHONE_PERMISSIONS,
                         PHONE_PERMISSIONS, SMS_PERMISSIONS, CAMERA_PERMISSIONS,
-                        SENSORS_PERMISSIONS, STORAGE_PERMISSIONS);
+                        SENSORS_PERMISSIONS, STORAGE_PERMISSIONS, NEARBY_DEVICES_PERMISSIONS);
                 grantSystemFixedPermissionsToSystemPackage(pm, packageName, userId,
-                        ALWAYS_LOCATION_PERMISSIONS, NEARBY_DEVICES_PERMISSIONS,
-                        ACTIVITY_RECOGNITION_PERMISSIONS);
+                        ALWAYS_LOCATION_PERMISSIONS, ACTIVITY_RECOGNITION_PERMISSIONS);
             }
         }
         if (locationExtraPackageNames != null) {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 0eccf3e..142b36e 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -85,11 +85,13 @@
 import android.content.pm.permission.SplitPermissionInfoParcelable;
 import android.metrics.LogMaker;
 import android.os.AsyncTask;
+import android.content.AttributionSource;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Debug;
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
 import android.os.Process;
@@ -159,6 +161,7 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import java.util.WeakHashMap;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
@@ -254,6 +257,10 @@
     @NonNull
     private final PermissionRegistry mRegistry = new PermissionRegistry();
 
+    @NonNull
+    private final AttributionSourceRegistry mAttributionSourceRegistry =
+            new AttributionSourceRegistry();
+
     @GuardedBy("mLock")
     @Nullable
     private ArraySet<String> mPrivappPermissionsViolations;
@@ -1849,8 +1856,7 @@
                 synchronized (mLock) {
                     final Permission perm =
                             mRegistry.getPermission(splitPerm.getSplitPermission());
-                    return perm != null && perm.getType() != Permission.TYPE_CONFIG
-                            && !perm.isRuntime();
+                    return perm != null && !perm.isRuntime();
                 }
             }
         }
@@ -3232,6 +3238,16 @@
     }
 
     @Override
+    public @NonNull AttributionSource registerAttributionSource(@NonNull AttributionSource source) {
+        return mAttributionSourceRegistry.registerAttributionSource(source);
+    }
+
+    @Override
+    public boolean isRegisteredAttributionSource(@NonNull AttributionSource source) {
+        return mAttributionSourceRegistry.isRegisteredAttributionSource(source);
+    }
+
+    @Override
     public List<String> getAutoRevokeExemptionRequestedPackages(int userId) {
         return getPackagesWithAutoRevokePolicy(AUTO_REVOKE_DISCOURAGED, userId);
     }
@@ -5266,4 +5282,73 @@
                     || mDelegatedPermissionNames.contains(permissionName);
         }
     }
+
+    private static final class AttributionSourceRegistry {
+        private final Object mLock = new Object();
+
+        private final WeakHashMap<IBinder, AttributionSource> mAttributions = new WeakHashMap<>();
+
+        public @NonNull AttributionSource registerAttributionSource(
+                @NonNull AttributionSource source) {
+            //   Here we keep track of attribution sources that were created by an app
+            // from an attribution chain that called into the app and the apps's
+            // own attribution source. An app can register an attribution chain up
+            // to itself inclusive if and only if it is adding a node for itself which
+            // optionally points to an attribution chain that was created by each
+            // preceding app recursively up to the beginning of the chain.
+            //   The only special case is when the first app in the attribution chain
+            // creates a source that points to another app (not a chain of apps). We
+            // allow this even if the source the app points to is not registered since
+            // in app ops we allow every app to blame every other app (untrusted if not
+            // holding a special permission).
+            //  This technique ensures that a bad actor in the middle of the attribution
+            // chain can neither prepend nor append an invalid attribution sequence, i.e.
+            // a sequence that is not constructed by trusted sources up to the that bad
+            // actor's app.
+            //   Note that passing your attribution source to another app means you allow
+            // it to blame private data access on your app. This can be mediated by the OS
+            // in, which case security is already enforced; by other app's code running in
+            // your process calling into the other app, in which case it can already access
+            // the private data in your process; or by you explicitly calling to another
+            // app passing the source, in which case you must trust the other side;
+
+            final int callingUid = Binder.getCallingUid();
+            if (source.getUid() != callingUid) {
+                throw new SecurityException("Cannot register attribution source for uid:"
+                        + source.getUid() + " from uid:" + callingUid);
+            }
+
+            final PackageManagerInternal packageManagerInternal = LocalServices.getService(
+                    PackageManagerInternal.class);
+            if (packageManagerInternal.getPackageUid(source.getPackageName(), 0,
+                    UserHandle.getUserId(callingUid)) != source.getUid()) {
+                throw new SecurityException("Cannot register attribution source for package:"
+                        + source.getPackageName() + " from uid:" + callingUid);
+            }
+
+            final AttributionSource next = source.getNext();
+            if (next != null && next.getNext() != null
+                    && !isRegisteredAttributionSource(next)) {
+                throw new SecurityException("Cannot register forged attribution source:"
+                        + source);
+            }
+
+            synchronized (mLock) {
+                final IBinder token = new Binder();
+                final AttributionSource result = source.withToken(token);
+                mAttributions.put(token, result);
+                return result;
+            }
+        }
+
+        public boolean isRegisteredAttributionSource(@NonNull AttributionSource source) {
+            synchronized (mLock) {
+                final AttributionSource cachedSource = mAttributions.get(source.getToken());
+                if (cachedSource != null) {
+                    return cachedSource.equals(source);
+                }
+                return false;
+            }
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
index 1b2ff08..63515b9 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
@@ -24,7 +24,6 @@
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.compat.annotation.ChangeId;
-import android.compat.annotation.Disabled;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.IntentFilterVerificationInfo;
@@ -92,7 +91,6 @@
      * commands.
      */
     @ChangeId
-    @Disabled
     private static final long SETTINGS_API_V2 = 178111421;
 
     /**
diff --git a/services/core/java/com/android/server/policy/AppOpsPolicy.java b/services/core/java/com/android/server/policy/AppOpsPolicy.java
index c965390..5db63c6 100644
--- a/services/core/java/com/android/server/policy/AppOpsPolicy.java
+++ b/services/core/java/com/android/server/policy/AppOpsPolicy.java
@@ -20,13 +20,18 @@
 import android.annotation.Nullable;
 import android.app.AppOpsManager;
 import android.app.AppOpsManagerInternal;
+import android.content.AttributionSource;
 import android.location.LocationManagerInternal;
+import android.os.IBinder;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.function.HeptFunction;
+import com.android.internal.util.function.HexFunction;
+import com.android.internal.util.function.OctFunction;
 import com.android.internal.util.function.QuadFunction;
+import com.android.internal.util.function.TriFunction;
 import com.android.server.LocalServices;
 
 import java.util.Set;
@@ -52,7 +57,7 @@
     @GuardedBy("mLock - writes only - see above")
     @NonNull
     private final ConcurrentHashMap<Integer, ArrayMap<String, ArraySet<String>>> mLocationTags =
-            new ConcurrentHashMap();
+            new ConcurrentHashMap<>();
 
     public AppOpsPolicy() {
         final LocationManagerInternal locationManagerInternal = LocalServices.getService(
@@ -112,22 +117,59 @@
 
     @Override
     public int noteOperation(int code, int uid, @Nullable String packageName,
-            @Nullable String featureId, boolean shouldCollectAsyncNotedOp, @Nullable String message,
-            boolean shouldCollectMessage, @NonNull HeptFunction<Integer, Integer, String, String,
-                    Boolean, String, Boolean, Integer> superImpl) {
-        if (isHandledOp(code)) {
+            @Nullable String attributionTag, boolean shouldCollectAsyncNotedOp, @Nullable
+            String message, boolean shouldCollectMessage, @NonNull HeptFunction<Integer, Integer,
+                    String, String, Boolean, String, Boolean, Integer> superImpl) {
+        return superImpl.apply(resolveOpCode(code, uid, packageName, attributionTag), uid,
+                packageName, attributionTag, shouldCollectAsyncNotedOp,
+                message, shouldCollectMessage);
+    }
+
+    @Override
+    public int noteProxyOperation(int code, @NonNull AttributionSource attributionSource,
+            boolean shouldCollectAsyncNotedOp, @Nullable String message,
+            boolean shouldCollectMessage, boolean skipProxyOperation, @NonNull HexFunction<Integer,
+                    AttributionSource, Boolean, String, Boolean, Boolean, Integer> superImpl) {
+        return superImpl.apply(resolveOpCode(code, attributionSource.getUid(),
+                attributionSource.getPackageName(), attributionSource.getAttributionTag()),
+                attributionSource, shouldCollectAsyncNotedOp, message, shouldCollectMessage,
+                skipProxyOperation);
+    }
+
+    @Override
+    public int startProxyOperation(IBinder token, int code,
+            @NonNull AttributionSource attributionSource, boolean startIfModeDefault,
+            boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
+            boolean skipProxyOperation, @NonNull OctFunction<IBinder, Integer, AttributionSource,
+                    Boolean, Boolean, String, Boolean, Boolean, Integer> superImpl) {
+        return superImpl.apply(token, resolveOpCode(code, attributionSource.getUid(),
+                attributionSource.getPackageName(), attributionSource.getAttributionTag()),
+                attributionSource, startIfModeDefault, shouldCollectAsyncNotedOp, message,
+                shouldCollectMessage, skipProxyOperation);
+    }
+
+    @Override
+    public void finishProxyOperation(IBinder clientId, int code,
+            @NonNull AttributionSource attributionSource,
+            @NonNull TriFunction<IBinder, Integer, AttributionSource, Void> superImpl) {
+        superImpl.apply(clientId, resolveOpCode(code, attributionSource.getUid(),
+                attributionSource.getPackageName(), attributionSource.getAttributionTag()),
+                attributionSource);
+    }
+
+    private int resolveOpCode(int code, int uid, @NonNull String packageName,
+            @Nullable String attributionTag) {
+        if (isHandledOp(code) && attributionTag != null) {
             // Only a single lookup from the underlying concurrent data structure
             final ArrayMap<String, ArraySet<String>> uidTags = mLocationTags.get(uid);
             if (uidTags != null) {
                 final ArraySet<String> packageTags = uidTags.get(packageName);
-                if (packageTags != null && packageTags.contains(featureId)) {
-                    return superImpl.apply(resolveLocationOp(code), uid, packageName, featureId,
-                            shouldCollectAsyncNotedOp, message, shouldCollectMessage);
+                if (packageTags != null && packageTags.contains(attributionTag)) {
+                    return resolveHandledOp(code);
                 }
             }
         }
-        return superImpl.apply(code, uid, packageName, featureId, shouldCollectAsyncNotedOp,
-                message, shouldCollectMessage);
+        return code;
     }
 
     private static boolean isHandledOp(int code) {
@@ -139,7 +181,7 @@
         return false;
     }
 
-    private static int resolveLocationOp(int code) {
+    private static int resolveHandledOp(int code) {
         switch (code) {
             case AppOpsManager.OP_FINE_LOCATION:
                 return AppOpsManager.OP_FINE_LOCATION_SOURCE;
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 9077433..89d5415 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -578,7 +578,7 @@
         private final @NonNull AppOpsManager mAppOpsManager;
         private final @NonNull AppOpsManagerInternal mAppOpsManagerInternal;
 
-        private final @NonNull ArrayMap<String, PermissionInfo> mRuntimePermissionInfos;
+        private final @NonNull ArrayMap<String, PermissionInfo> mRuntimeAndTheirBgPermissionInfos;
 
         /**
          * All ops that need to be flipped to allow.
@@ -618,7 +618,7 @@
             mAppOpsManager = context.getSystemService(AppOpsManager.class);
             mAppOpsManagerInternal = LocalServices.getService(AppOpsManagerInternal.class);
 
-            mRuntimePermissionInfos = new ArrayMap<>();
+            mRuntimeAndTheirBgPermissionInfos = new ArrayMap<>();
             PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService(
                     PermissionManagerServiceInternal.class);
             List<PermissionInfo> permissionInfos =
@@ -627,7 +627,30 @@
             int permissionInfosSize = permissionInfos.size();
             for (int i = 0; i < permissionInfosSize; i++) {
                 PermissionInfo permissionInfo = permissionInfos.get(i);
-                mRuntimePermissionInfos.put(permissionInfo.name, permissionInfo);
+                mRuntimeAndTheirBgPermissionInfos.put(permissionInfo.name, permissionInfo);
+                // Make sure we scoop up all background permissions as they may not be runtime
+                if (permissionInfo.backgroundPermission != null) {
+                    String backgroundNonRuntimePermission = permissionInfo.backgroundPermission;
+                    for (int j = 0; j < permissionInfosSize; j++) {
+                        PermissionInfo bgPermissionCandidate = permissionInfos.get(j);
+                        if (permissionInfo.backgroundPermission.equals(
+                                bgPermissionCandidate.name)) {
+                            backgroundNonRuntimePermission = null;
+                            break;
+                        }
+                    }
+                    if (backgroundNonRuntimePermission != null) {
+                        try {
+                            PermissionInfo backgroundPermissionInfo = mPackageManager
+                                    .getPermissionInfo(backgroundNonRuntimePermission, 0);
+                            mRuntimeAndTheirBgPermissionInfos.put(backgroundPermissionInfo.name,
+                                    backgroundPermissionInfo);
+                        } catch (NameNotFoundException e) {
+                            Slog.w(LOG_TAG, "Unknown background permission: "
+                                    + backgroundNonRuntimePermission);
+                        }
+                    }
+                }
             }
         }
 
@@ -691,7 +714,7 @@
          */
         private void addAppOps(@NonNull PackageInfo packageInfo, @NonNull AndroidPackage pkg,
                 @NonNull String permissionName) {
-            PermissionInfo permissionInfo = mRuntimePermissionInfos.get(permissionName);
+            PermissionInfo permissionInfo = mRuntimeAndTheirBgPermissionInfos.get(permissionName);
             if (permissionInfo == null) {
                 return;
             }
@@ -726,7 +749,7 @@
             boolean shouldGrantAppOp = shouldGrantAppOp(packageInfo, pkg, permissionInfo);
             if (shouldGrantAppOp) {
                 if (permissionInfo.backgroundPermission != null) {
-                    PermissionInfo backgroundPermissionInfo = mRuntimePermissionInfos.get(
+                    PermissionInfo backgroundPermissionInfo = mRuntimeAndTheirBgPermissionInfos.get(
                             permissionInfo.backgroundPermission);
                     boolean shouldGrantBackgroundAppOp = backgroundPermissionInfo != null
                             && shouldGrantAppOp(packageInfo, pkg, backgroundPermissionInfo);
diff --git a/services/core/java/com/android/server/power/DisplayGroupPowerStateMapper.java b/services/core/java/com/android/server/power/DisplayGroupPowerStateMapper.java
index 9732eba3..ea93324 100644
--- a/services/core/java/com/android/server/power/DisplayGroupPowerStateMapper.java
+++ b/services/core/java/com/android/server/power/DisplayGroupPowerStateMapper.java
@@ -125,6 +125,10 @@
         return mDisplayGroupIds;
     }
 
+    int getDisplayGroupCountLocked() {
+        return mDisplayGroupIds.length;
+    }
+
     int getWakefulnessLocked(int groupId) {
         return mDisplayGroupInfos.get(groupId).wakefulness;
     }
@@ -272,6 +276,14 @@
         mDisplayGroupInfos.get(groupId).userActivitySummary = summary;
     }
 
+    int getWakeLockSummaryLocked(int groupId) {
+        return mDisplayGroupInfos.get(groupId).wakeLockSummary;
+    }
+
+    void setWakeLockSummaryLocked(int groupId, int summary) {
+        mDisplayGroupInfos.get(groupId).wakeLockSummary = summary;
+    }
+
     /**
      * Interface through which an interested party may be informed of {@link DisplayGroup} events.
      */
@@ -292,6 +304,7 @@
         public long lastUserActivityTime;
         public long lastUserActivityTimeNoChangeLights;
         public int userActivitySummary;
+        public int wakeLockSummary;
 
         /** {@code true} if this DisplayGroup supports dreaming; otherwise {@code false}. */
         public boolean supportsSandman;
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 54d5b7a..8052522 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -1348,9 +1348,20 @@
         updatePowerStateLocked();
     }
 
-    private void acquireWakeLockInternal(IBinder lock, int flags, String tag, String packageName,
-            WorkSource ws, String historyTag, int uid, int pid) {
+    private void acquireWakeLockInternal(IBinder lock, int displayId, int flags, String tag,
+            String packageName, WorkSource ws, String historyTag, int uid, int pid) {
         synchronized (mLock) {
+            if (displayId != Display.INVALID_DISPLAY) {
+                final DisplayInfo displayInfo =
+                        mSystemReady ? mDisplayManagerInternal.getDisplayInfo(displayId) : null;
+                if (displayInfo == null) {
+                    Slog.wtf(TAG, "Tried to acquire wake lock for invalid display: " + displayId);
+                    return;
+                } else if (!displayInfo.hasAccess(uid)) {
+                    throw new SecurityException("Caller does not have access to display");
+                }
+            }
+
             if (DEBUG_SPEW) {
                 Slog.d(TAG, "acquireWakeLockInternal: lock=" + Objects.hashCode(lock)
                         + ", flags=0x" + Integer.toHexString(flags)
@@ -1377,8 +1388,8 @@
                     mUidState.put(uid, state);
                 }
                 state.mNumWakeLocks++;
-                wakeLock = new WakeLock(lock, flags, tag, packageName, ws, historyTag, uid, pid,
-                        state);
+                wakeLock = new WakeLock(lock, displayId, flags, tag, packageName, ws, historyTag,
+                        uid, pid, state);
                 try {
                     lock.linkToDeath(wakeLock, 0);
                 } catch (RemoteException ex) {
@@ -2047,6 +2058,11 @@
         return mWakefulnessRaw;
     }
 
+    @VisibleForTesting
+    int getWakefulnessLocked(int groupId) {
+        return mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId);
+    }
+
     /**
      * Logs the time the device would have spent awake before user activity timeout,
      * had the system not been told the user was inactive.
@@ -2293,7 +2309,9 @@
      */
     @SuppressWarnings("deprecation")
     private void updateWakeLockSummaryLocked(int dirty) {
-        if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_WAKEFULNESS)) != 0) {
+        if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_WAKEFULNESS | DIRTY_DISPLAY_GROUP_WAKEFULNESS))
+                != 0) {
+
             mWakeLockSummary = 0;
 
             final int numProfiles = mProfilePowerState.size();
@@ -2301,11 +2319,28 @@
                 mProfilePowerState.valueAt(i).mWakeLockSummary = 0;
             }
 
+            for (int groupId : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) {
+                mDisplayGroupPowerStateMapper.setWakeLockSummaryLocked(groupId, 0);
+            }
+
+            int invalidGroupWakeLockSummary = 0;
             final int numWakeLocks = mWakeLocks.size();
             for (int i = 0; i < numWakeLocks; i++) {
                 final WakeLock wakeLock = mWakeLocks.get(i);
                 final int wakeLockFlags = getWakeLockSummaryFlags(wakeLock);
                 mWakeLockSummary |= wakeLockFlags;
+
+                final int groupId = wakeLock.getDisplayGroupId();
+                if (groupId != Display.INVALID_DISPLAY_GROUP) {
+                    int wakeLockSummary = mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(
+                            groupId);
+                    wakeLockSummary |= wakeLockFlags;
+                    mDisplayGroupPowerStateMapper.setWakeLockSummaryLocked(groupId,
+                            wakeLockSummary);
+                } else {
+                    invalidGroupWakeLockSummary |= wakeLockFlags;
+                }
+
                 for (int j = 0; j < numProfiles; j++) {
                     final ProfilePowerState profile = mProfilePowerState.valueAt(j);
                     if (wakeLockAffectsUser(wakeLock, profile.mUserId)) {
@@ -2314,10 +2349,21 @@
                 }
             }
 
-            mWakeLockSummary = adjustWakeLockSummaryLocked(mWakeLockSummary);
+            for (int groupId : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) {
+                final int wakeLockSummary = adjustWakeLockSummaryLocked(
+                        mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId),
+                        invalidGroupWakeLockSummary
+                                | mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(groupId));
+                mDisplayGroupPowerStateMapper.setWakeLockSummaryLocked(groupId, wakeLockSummary);
+            }
+
+            mWakeLockSummary = adjustWakeLockSummaryLocked(getWakefulnessLocked(),
+                    mWakeLockSummary);
+
             for (int i = 0; i < numProfiles; i++) {
                 final ProfilePowerState profile = mProfilePowerState.valueAt(i);
-                profile.mWakeLockSummary = adjustWakeLockSummaryLocked(profile.mWakeLockSummary);
+                profile.mWakeLockSummary = adjustWakeLockSummaryLocked(getWakefulnessLocked(),
+                        profile.mWakeLockSummary);
             }
 
             if (DEBUG_SPEW) {
@@ -2328,25 +2374,25 @@
         }
     }
 
-    private int adjustWakeLockSummaryLocked(int wakeLockSummary) {
+    private static int adjustWakeLockSummaryLocked(int wakefulness, int wakeLockSummary) {
         // Cancel wake locks that make no sense based on the current state.
-        if (getWakefulnessLocked() != WAKEFULNESS_DOZING) {
+        if (wakefulness != WAKEFULNESS_DOZING) {
             wakeLockSummary &= ~(WAKE_LOCK_DOZE | WAKE_LOCK_DRAW);
         }
-        if (getWakefulnessLocked() == WAKEFULNESS_ASLEEP
+        if (wakefulness == WAKEFULNESS_ASLEEP
                 || (wakeLockSummary & WAKE_LOCK_DOZE) != 0) {
             wakeLockSummary &= ~(WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM
                     | WAKE_LOCK_BUTTON_BRIGHT);
-            if (getWakefulnessLocked() == WAKEFULNESS_ASLEEP) {
+            if (wakefulness == WAKEFULNESS_ASLEEP) {
                 wakeLockSummary &= ~WAKE_LOCK_PROXIMITY_SCREEN_OFF;
             }
         }
 
         // Infer implied wake locks where necessary based on the current state.
         if ((wakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM)) != 0) {
-            if (getWakefulnessLocked() == WAKEFULNESS_AWAKE) {
+            if (wakefulness == WAKEFULNESS_AWAKE) {
                 wakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_STAY_AWAKE;
-            } else if (getWakefulnessLocked() == WAKEFULNESS_DREAMING) {
+            } else if (wakefulness == WAKEFULNESS_DREAMING) {
                 wakeLockSummary |= WAKE_LOCK_CPU;
             }
         }
@@ -2531,7 +2577,8 @@
                 }
 
                 if ((groupUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0
-                        && (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) == 0) {
+                        && (mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(groupId)
+                        & WAKE_LOCK_STAY_AWAKE) == 0) {
                     groupNextTimeout = mAttentionDetector.updateUserActivity(groupNextTimeout,
                             screenDimDuration);
                 }
@@ -2831,7 +2878,8 @@
     private boolean isBeingKeptAwakeLocked(int groupId) {
         return mStayOn
                 || mProximityPositive
-                || (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0
+                || (mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(groupId)
+                & WAKE_LOCK_STAY_AWAKE) != 0
                 || (mDisplayGroupPowerStateMapper.getUserActivitySummaryLocked(groupId) & (
                 USER_ACTIVITY_SCREEN_BRIGHT | USER_ACTIVITY_SCREEN_DIM)) != 0
                 || mScreenBrightnessBoostInProgress;
@@ -3101,8 +3149,8 @@
 
                 if (displayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
                     displayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;
-                    if ((mWakeLockSummary & WAKE_LOCK_DRAW) != 0
-                            && !mDrawWakeLockOverrideFromSidekick) {
+                    if ((mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(groupId)
+                            & WAKE_LOCK_DRAW) != 0 && !mDrawWakeLockOverrideFromSidekick) {
                         if (displayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND) {
                             displayPowerRequest.dozeScreenState = Display.STATE_DOZE;
                         }
@@ -3128,7 +3176,8 @@
                             + ", mWakefulness="
                             + PowerManagerInternal.wakefulnessToString(
                             mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId))
-                            + ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary)
+                            + ", mWakeLockSummary=0x" + Integer.toHexString(
+                            mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(groupId))
                             + ", mUserActivitySummary=0x" + Integer.toHexString(
                             mDisplayGroupPowerStateMapper.getUserActivitySummaryLocked(groupId))
                             + ", mBootCompleted=" + mBootCompleted
@@ -3193,10 +3242,11 @@
     @VisibleForTesting
     int getDesiredScreenPolicyLocked(int groupId) {
         final int wakefulness = mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId);
+        final int wakeLockSummary = mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(groupId);
         if (wakefulness == WAKEFULNESS_ASLEEP || sQuiescent) {
             return DisplayPowerRequest.POLICY_OFF;
         } else if (wakefulness == WAKEFULNESS_DOZING) {
-            if ((mWakeLockSummary & WAKE_LOCK_DOZE) != 0) {
+            if ((wakeLockSummary & WAKE_LOCK_DOZE) != 0) {
                 return DisplayPowerRequest.POLICY_DOZE;
             }
             if (mDozeAfterScreenOff) {
@@ -3213,7 +3263,7 @@
             return DisplayPowerRequest.POLICY_VR;
         }
 
-        if ((mWakeLockSummary & WAKE_LOCK_SCREEN_BRIGHT) != 0
+        if ((wakeLockSummary & WAKE_LOCK_SCREEN_BRIGHT) != 0
                 || !mBootCompleted
                 || (mDisplayGroupPowerStateMapper.getUserActivitySummaryLocked(groupId)
                 & USER_ACTIVITY_SCREEN_BRIGHT) != 0
@@ -3292,7 +3342,9 @@
     };
 
     private boolean shouldUseProximitySensorLocked() {
-        return !mIsVrModeEnabled && (mWakeLockSummary & WAKE_LOCK_PROXIMITY_SCREEN_OFF) != 0;
+        // Use default display group for proximity sensor.
+        return !mIsVrModeEnabled && (mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(
+                Display.DEFAULT_DISPLAY_GROUP) & WAKE_LOCK_PROXIMITY_SCREEN_OFF) != 0;
     }
 
     /**
@@ -4248,6 +4300,8 @@
                 pw.println("  lastUserActivityTimeNoChangeLights=" + TimeUtils.formatUptime(
                         mDisplayGroupPowerStateMapper.getLastUserActivityTimeNoChangeLightsLocked(
                                 id)));
+                pw.println("  mWakeLockSummary=0x" + Integer.toHexString(
+                        mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(id)));
             }
 
             wcd = mWirelessChargerDetector;
@@ -4738,6 +4792,7 @@
      */
     /* package */ final class WakeLock implements IBinder.DeathRecipient {
         public final IBinder mLock;
+        public final int mDisplayId;
         public int mFlags;
         public String mTag;
         public final String mPackageName;
@@ -4751,10 +4806,11 @@
         public boolean mNotifiedLong;
         public boolean mDisabled;
 
-        public WakeLock(IBinder lock, int flags, String tag, String packageName,
+        public WakeLock(IBinder lock, int displayId, int flags, String tag, String packageName,
                 WorkSource workSource, String historyTag, int ownerUid, int ownerPid,
                 UidState uidState) {
             mLock = lock;
+            mDisplayId = displayId;
             mFlags = flags;
             mTag = tag;
             mPackageName = packageName;
@@ -4807,6 +4863,15 @@
             mWorkSource = copyWorkSource(workSource);
         }
 
+        public int getDisplayGroupId() {
+            if (!mSystemReady || mDisplayId == Display.INVALID_DISPLAY) {
+                return Display.INVALID_DISPLAY_GROUP;
+            }
+
+            final DisplayInfo displayInfo = mDisplayManagerInternal.getDisplayInfo(mDisplayId);
+            return displayInfo == null ? Display.INVALID_DISPLAY_GROUP : displayInfo.displayGroupId;
+        }
+
         @Override
         public String toString() {
             StringBuilder sb = new StringBuilder();
@@ -4996,11 +5061,11 @@
 
         @Override // Binder call
         public void acquireWakeLockWithUid(IBinder lock, int flags, String tag,
-                String packageName, int uid) {
+                String packageName, int uid, int displayId) {
             if (uid < 0) {
                 uid = Binder.getCallingUid();
             }
-            acquireWakeLock(lock, flags, tag, packageName, new WorkSource(uid), null);
+            acquireWakeLock(lock, flags, tag, packageName, new WorkSource(uid), null, displayId);
         }
 
         @Override // Binder call
@@ -5035,7 +5100,7 @@
 
         @Override // Binder call
         public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName,
-                WorkSource ws, String historyTag) {
+                WorkSource ws, String historyTag, int displayId) {
             if (lock == null) {
                 throw new IllegalArgumentException("lock must not be null");
             }
@@ -5060,7 +5125,8 @@
             final int pid = Binder.getCallingPid();
             final long ident = Binder.clearCallingIdentity();
             try {
-                acquireWakeLockInternal(lock, flags, tag, packageName, ws, historyTag, uid, pid);
+                acquireWakeLockInternal(lock, displayId, flags, tag, packageName, ws, historyTag,
+                        uid, pid);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -5069,7 +5135,7 @@
         @Override // Binder call
         public void acquireWakeLockAsync(IBinder lock, int flags, String tag, String packageName,
                 WorkSource ws, String historyTag) {
-            acquireWakeLock(lock, flags, tag, packageName, ws, historyTag);
+            acquireWakeLock(lock, flags, tag, packageName, ws, historyTag, Display.INVALID_DISPLAY);
         }
 
         @Override // Binder call
diff --git a/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java b/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java
index 3f20302..9c8ff68 100644
--- a/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java
+++ b/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java
@@ -18,12 +18,12 @@
 
 import static com.android.internal.infra.AbstractRemoteService.PERMANENT_BOUND_TIMEOUT_MS;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.AppOpsManager;
+import android.content.AttributionSource;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.os.Binder;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.speech.IRecognitionListener;
@@ -40,10 +40,6 @@
     private static final String TAG = RemoteSpeechRecognitionService.class.getSimpleName();
     private static final boolean DEBUG = false;
 
-    private static final String APP_OP_MESSAGE = "Recording audio for speech recognition";
-    private static final String RECORD_AUDIO_APP_OP =
-            AppOpsManager.permissionToOp(android.Manifest.permission.RECORD_AUDIO);
-
     private final Object mLock = new Object();
 
     private boolean mConnected = false;
@@ -53,14 +49,6 @@
 
     @Nullable
     @GuardedBy("mLock")
-    private String mPackageName;
-
-    @Nullable
-    @GuardedBy("mLock")
-    private String mFeatureId;
-
-    @Nullable
-    @GuardedBy("mLock")
     private DelegatingListener mDelegatingListener;
 
     // Makes sure we can block startListening() if session is still in progress.
@@ -72,7 +60,6 @@
     private boolean mRecordingInProgress = false;
 
     private final int mCallingUid;
-    private final AppOpsManager mAppOpsManager;
     private final ComponentName mComponentName;
 
     RemoteSpeechRecognitionService(
@@ -87,7 +74,6 @@
                 IRecognitionService.Stub::asInterface);
 
         mCallingUid = callingUid;
-        mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
         mComponentName = serviceName;
 
         if (DEBUG) {
@@ -99,11 +85,12 @@
         return mComponentName;
     }
 
-    void startListening(Intent recognizerIntent, IRecognitionListener listener, String packageName,
-            String featureId) {
+    void startListening(Intent recognizerIntent, IRecognitionListener listener,
+            @NonNull AttributionSource attributionSource) {
         if (DEBUG) {
             Slog.i(TAG, String.format("#startListening for package: %s, feature=%s, callingUid=%d",
-                    packageName, featureId, mCallingUid));
+                    attributionSource.getPackageName(), attributionSource.getAttributionTag(),
+                    mCallingUid));
         }
 
         if (listener == null) {
@@ -123,10 +110,6 @@
                 return;
             }
 
-            if (startProxyOp(packageName, featureId) != AppOpsManager.MODE_ALLOWED) {
-                tryRespondWithError(listener, SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS);
-                return;
-            }
             mSessionInProgress = true;
             mRecordingInProgress = true;
 
@@ -141,23 +124,18 @@
                     resetStateLocked();
                 }
             });
-            mPackageName = packageName;
-            mFeatureId = featureId;
 
             run(service ->
                     service.startListening(
                             recognizerIntent,
                             mDelegatingListener,
-                            packageName,
-                            featureId,
-                            mCallingUid));
+                            attributionSource));
         }
     }
 
-    void stopListening(
-            IRecognitionListener listener, String packageName, String featureId) {
+    void stopListening(IRecognitionListener listener) {
         if (DEBUG) {
-            Slog.i(TAG, "#stopListening for package: " + packageName + ", feature=" + featureId);
+            Slog.i(TAG, "#stopListening");
         }
 
         if (!mConnected) {
@@ -184,19 +162,13 @@
             }
             mRecordingInProgress = false;
 
-            finishProxyOp(packageName, featureId);
-
-            run(service -> service.stopListening(mDelegatingListener, packageName, featureId));
+            run(service -> service.stopListening(mDelegatingListener));
         }
     }
 
-    void cancel(
-            IRecognitionListener listener,
-            String packageName,
-            String featureId,
-            boolean isShutdown) {
+    void cancel(IRecognitionListener listener, boolean isShutdown) {
         if (DEBUG) {
-            Slog.i(TAG, "#cancel for package: " + packageName + ", feature=" + featureId);
+            Slog.i(TAG, "#cancel");
         }
 
         if (!mConnected) {
@@ -220,11 +192,8 @@
             // Temporary reference to allow for resetting the hard link mDelegatingListener to null.
             IRecognitionListener delegatingListener = mDelegatingListener;
 
-            run(service -> service.cancel(delegatingListener, packageName, featureId, isShutdown));
+            run(service -> service.cancel(delegatingListener, isShutdown));
 
-            if (mRecordingInProgress) {
-                finishProxyOp(packageName, featureId);
-            }
             mRecordingInProgress = false;
             mSessionInProgress = false;
 
@@ -249,7 +218,7 @@
             }
         }
 
-        cancel(mListener, mPackageName, mFeatureId, true /* isShutdown */);
+        cancel(mListener, true /* isShutdown */);
     }
 
     @Override // from ServiceConnector.Impl
@@ -286,40 +255,12 @@
     }
 
     private void resetStateLocked() {
-        if (mRecordingInProgress && mPackageName != null) {
-            finishProxyOp(mPackageName, mFeatureId);
-        }
-
         mListener = null;
         mDelegatingListener = null;
         mSessionInProgress = false;
         mRecordingInProgress = false;
     }
 
-    private int startProxyOp(String packageName, String featureId) {
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            return mAppOpsManager.startProxyOp(
-                    RECORD_AUDIO_APP_OP,
-                    mCallingUid,
-                    packageName,
-                    featureId,
-                    APP_OP_MESSAGE);
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
-    }
-
-    private void finishProxyOp(String packageName, String featureId) {
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            mAppOpsManager.finishProxyOp(
-                    RECORD_AUDIO_APP_OP, mCallingUid, packageName, featureId);
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
-    }
-
     private static void tryRespondWithError(IRecognitionListener listener, int errorCode) {
         if (DEBUG) {
             Slog.i(TAG, "Responding with error " + errorCode);
diff --git a/services/core/java/com/android/server/speech/SpeechRecognitionManagerService.java b/services/core/java/com/android/server/speech/SpeechRecognitionManagerService.java
index 52c1467b..22eeb34 100644
--- a/services/core/java/com/android/server/speech/SpeechRecognitionManagerService.java
+++ b/services/core/java/com/android/server/speech/SpeechRecognitionManagerService.java
@@ -75,7 +75,7 @@
     @Override
     protected SpeechRecognitionManagerServiceImpl newServiceLocked(
             @UserIdInt int resolvedUserId, boolean disabled) {
-        return new SpeechRecognitionManagerServiceImpl(this, mLock, resolvedUserId, disabled);
+        return new SpeechRecognitionManagerServiceImpl(this, mLock, resolvedUserId);
     }
 
     final class SpeechRecognitionManagerServiceStub extends IRecognitionServiceManager.Stub {
diff --git a/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java b/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java
index 769e049..eee08c2 100644
--- a/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java
@@ -20,6 +20,7 @@
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.AppGlobals;
+import android.content.AttributionSource;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.PackageManager;
@@ -36,8 +37,6 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.server.infra.AbstractPerUserSystemService;
 
-import com.google.android.collect.Sets;
-
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -60,7 +59,7 @@
 
     SpeechRecognitionManagerServiceImpl(
             @NonNull SpeechRecognitionManagerService master,
-            @NonNull Object lock, @UserIdInt int userId, boolean disabled) {
+            @NonNull Object lock, @UserIdInt int userId) {
         super(master, lock, userId);
     }
 
@@ -108,10 +107,6 @@
         }
 
         final int creatorCallingUid = Binder.getCallingUid();
-        Set<String> creatorPackageNames =
-                Sets.newArraySet(
-                        getContext().getPackageManager().getPackagesForUid(creatorCallingUid));
-
         RemoteSpeechRecognitionService service = createService(creatorCallingUid, serviceComponent);
 
         if (service == null) {
@@ -127,6 +122,7 @@
         } catch (RemoteException e) {
             // RemoteException == binder already died, schedule disconnect anyway.
             handleClientDeath(creatorCallingUid, service, true /* invoke #cancel */);
+            return;
         }
 
         service.connect().thenAccept(binderService -> {
@@ -137,41 +133,24 @@
                         public void startListening(
                                 Intent recognizerIntent,
                                 IRecognitionListener listener,
-                                String packageName,
-                                String featureId,
-                                int callingUid) throws RemoteException {
-                            verifyCallerIdentity(
-                                    creatorCallingUid, packageName, creatorPackageNames, listener);
-                            if (callingUid != creatorCallingUid) {
-                                listener.onError(SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS);
-                                return;
-                            }
-
-                            service.startListening(
-                                    recognizerIntent, listener, packageName, featureId);
+                                @NonNull AttributionSource attributionSource)
+                                        throws RemoteException {
+                            attributionSource.enforceCallingUid();
+                            service.startListening(recognizerIntent, listener, attributionSource);
                         }
 
                         @Override
                         public void stopListening(
-                                IRecognitionListener listener,
-                                String packageName,
-                                String featureId) throws RemoteException {
-                            verifyCallerIdentity(
-                                    creatorCallingUid, packageName, creatorPackageNames, listener);
-
-                            service.stopListening(listener, packageName, featureId);
+                                IRecognitionListener listener) throws RemoteException {
+                            service.stopListening(listener);
                         }
 
                         @Override
                         public void cancel(
                                 IRecognitionListener listener,
-                                String packageName,
-                                String featureId,
                                 boolean isShutdown) throws RemoteException {
-                            verifyCallerIdentity(
-                                    creatorCallingUid, packageName, creatorPackageNames, listener);
 
-                            service.cancel(listener, packageName, featureId, isShutdown);
+                            service.cancel(listener, isShutdown);
 
                             if (isShutdown) {
                                 handleClientDeath(
@@ -192,17 +171,6 @@
         });
     }
 
-    private void verifyCallerIdentity(
-            int creatorCallingUid,
-            String packageName,
-            Set<String> creatorPackageNames,
-            IRecognitionListener listener) throws RemoteException {
-        if (creatorCallingUid != Binder.getCallingUid()
-                || !creatorPackageNames.contains(packageName)) {
-            listener.onError(SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS);
-        }
-    }
-
     private void handleClientDeath(
             int callingUid,
             RemoteSpeechRecognitionService service, boolean invokeCancel) {
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index b947c88..16692e1 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -514,6 +514,18 @@
         }
     }
 
+    void onImeSurfaceShownChanged(WindowState windowState, boolean shown) {
+        if (mAccessibilityTracing.isEnabled()) {
+            mAccessibilityTracing.logState(TAG + ".onImeSurfaceShownChanged",
+                    "windowState=" + windowState + "; shown=" + shown);
+        }
+        final int displayId = windowState.getDisplayId();
+        final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
+        if (displayMagnifier != null) {
+            displayMagnifier.onImeSurfaceShownChanged(shown);
+        }
+    }
+
     private static void populateTransformationMatrix(WindowState windowState,
             Matrix outMatrix) {
         windowState.getTransformationMatrix(sTempFloats, outMatrix);
@@ -766,6 +778,15 @@
             }
         }
 
+        void onImeSurfaceShownChanged(boolean shown) {
+            if (mAccessibilityTracing.isEnabled()) {
+                mAccessibilityTracing.logState(
+                        LOG_TAG + ".onImeSurfaceShownChanged", "shown=" + shown);
+            }
+            mHandler.obtainMessage(MyHandler.MESSAGE_NOTIFY_IME_WINDOW_VISIBILITY_CHANGED,
+                    shown ? 1 : 0, 0).sendToTarget();
+        }
+
         MagnificationSpec getMagnificationSpecForWindow(WindowState windowState) {
             if (mAccessibilityTracing.isEnabled()) {
                 mAccessibilityTracing.logState(LOG_TAG + ".getMagnificationSpecForWindow",
@@ -1337,6 +1358,7 @@
             public static final int MESSAGE_NOTIFY_USER_CONTEXT_CHANGED = 3;
             public static final int MESSAGE_NOTIFY_ROTATION_CHANGED = 4;
             public static final int MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED = 5;
+            public static final int MESSAGE_NOTIFY_IME_WINDOW_VISIBILITY_CHANGED = 6;
 
             MyHandler(Looper looper) {
                 super(looper);
@@ -1380,6 +1402,11 @@
                             }
                         }
                     } break;
+
+                    case MESSAGE_NOTIFY_IME_WINDOW_VISIBILITY_CHANGED: {
+                        final boolean shown = message.arg1 == 1;
+                        mCallbacks.onImeWindowVisibilityChanged(shown);
+                    } break;
                 }
             }
         }
@@ -2123,5 +2150,4 @@
             }
         }
     }
-
 }
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 6046cc6..9ff701c 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -1539,20 +1539,6 @@
             }
         }
 
-        @Override
-        public boolean canUseRotationResolver() {
-            if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) return false;
-
-            switch (mCurrentAppOrientation) {
-                case ActivityInfo.SCREEN_ORIENTATION_FULL_USER:
-                case ActivityInfo.SCREEN_ORIENTATION_USER:
-                case ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED:
-                case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
-                case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
-                    return true;
-            }
-            return false;
-        }
 
         @Override
         public void onProposedRotationChanged(int rotation) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index 8148f15..ab515d4 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -113,7 +113,7 @@
          *
          * @param magnificationRegion the current magnification region
          */
-        public void onMagnificationRegionChanged(Region magnificationRegion);
+        void onMagnificationRegionChanged(Region magnificationRegion);
 
         /**
          * Called when an application requests a rectangle on the screen to allow
@@ -124,20 +124,27 @@
          * @param right The rectangle right.
          * @param bottom The rectangle bottom.
          */
-        public void onRectangleOnScreenRequested(int left, int top, int right, int bottom);
+        void onRectangleOnScreenRequested(int left, int top, int right, int bottom);
 
         /**
          * Notifies that the rotation changed.
          *
          * @param rotation The current rotation.
          */
-        public void onRotationChanged(int rotation);
+        void onRotationChanged(int rotation);
 
         /**
          * Notifies that the context of the user changed. For example, an application
          * was started.
          */
-        public void onUserContextChanged();
+        void onUserContextChanged();
+
+        /**
+         * Notifies that the IME window visibility changed.
+         * @param shown {@code true} means the IME window shows on the screen. Otherwise it's
+         *                           hidden.
+         */
+        void onImeWindowVisibilityChanged(boolean shown);
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/WindowOrientationListener.java b/services/core/java/com/android/server/wm/WindowOrientationListener.java
index 49e704f..b971cab 100644
--- a/services/core/java/com/android/server/wm/WindowOrientationListener.java
+++ b/services/core/java/com/android/server/wm/WindowOrientationListener.java
@@ -275,19 +275,6 @@
         }
     }
 
-    /**
-     * Returns true if the current status of the phone is suitable for using rotation resolver
-     * service.
-     *
-     * To reduce the power consumption of rotation resolver service, rotation query should run less
-     * frequently than other low power orientation sensors. This method is used to check whether
-     * the current status of the phone is necessary to request a suggested screen rotation from the
-     * rotation resolver service. Note that it always returns {@code false} in the base class. It
-     * should be overridden in the derived classes.
-     */
-    public boolean canUseRotationResolver() {
-        return false;
-    }
 
     /**
      * Returns true if the rotation resolver feature is enabled by setting. It means {@link
@@ -1155,7 +1142,7 @@
                 }
             }
 
-            if (isRotationResolverEnabled() && canUseRotationResolver()) {
+            if (isRotationResolverEnabled()) {
                 if (mRotationResolverService == null) {
                     mRotationResolverService = LocalServices.getService(
                             RotationResolverInternal.class);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index eb83152..92c9522 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3462,6 +3462,9 @@
         if (mAttrs.type >= FIRST_SYSTEM_WINDOW && mAttrs.type != TYPE_TOAST) {
             mWmService.mAtmService.mActiveUids.onNonAppSurfaceVisibilityChanged(mOwnerUid, shown);
         }
+        if (mIsImWindow && mWmService.mAccessibilityController != null) {
+            mWmService.mAccessibilityController.onImeSurfaceShownChanged(this, shown);
+        }
     }
 
     private void logExclusionRestrictions(int side) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
index 56e2385..a419bf8 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
@@ -16,6 +16,7 @@
 
 package com.android.server.devicepolicy;
 
+import static android.app.admin.DevicePolicyManager.NEARBY_STREAMING_DISABLED;
 import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
 
@@ -69,6 +70,10 @@
             "disable-bt-contacts-sharing";
     private static final String TAG_DISABLE_SCREEN_CAPTURE = "disable-screen-capture";
     private static final String TAG_DISABLE_ACCOUNT_MANAGEMENT = "disable-account-management";
+    private static final String TAG_NEARBY_NOTIFICATION_STREAMING_POLICY =
+            "nearby-notification-streaming-policy";
+    private static final String TAG_NEARBY_APP_STREAMING_POLICY =
+            "nearby-app-streaming-policy";
     private static final String TAG_REQUIRE_AUTO_TIME = "require_auto_time";
     private static final String TAG_FORCE_EPHEMERAL_USERS = "force_ephemeral_users";
     private static final String TAG_IS_NETWORK_LOGGING_ENABLED = "is_network_logging_enabled";
@@ -159,6 +164,12 @@
     @DevicePolicyManager.PasswordComplexity
     int mPasswordComplexity = PASSWORD_COMPLEXITY_NONE;
 
+    @DevicePolicyManager.NearbyStreamingPolicy
+    int mNearbyNotificationStreamingPolicy = NEARBY_STREAMING_DISABLED;
+
+    @DevicePolicyManager.NearbyStreamingPolicy
+    int mNearbyAppStreamingPolicy = NEARBY_STREAMING_DISABLED;
+
     @Nullable
     FactoryResetProtectionPolicy mFactoryResetProtectionPolicy = null;
 
@@ -549,6 +560,14 @@
         if (mPasswordComplexity != PASSWORD_COMPLEXITY_NONE) {
             writeAttributeValueToXml(out, TAG_PASSWORD_COMPLEXITY, mPasswordComplexity);
         }
+        if (mNearbyNotificationStreamingPolicy != NEARBY_STREAMING_DISABLED) {
+            writeAttributeValueToXml(out, TAG_NEARBY_NOTIFICATION_STREAMING_POLICY,
+                    mNearbyNotificationStreamingPolicy);
+        }
+        if (mNearbyAppStreamingPolicy != NEARBY_STREAMING_DISABLED) {
+            writeAttributeValueToXml(out, TAG_NEARBY_APP_STREAMING_POLICY,
+                    mNearbyAppStreamingPolicy);
+        }
         if (!TextUtils.isEmpty(mOrganizationId)) {
             writeTextToXml(out, TAG_ORGANIZATION_ID, mOrganizationId);
         }
@@ -794,6 +813,10 @@
                 mCommonCriteriaMode = parser.getAttributeBoolean(null, ATTR_VALUE, false);
             } else if (TAG_PASSWORD_COMPLEXITY.equals(tag)) {
                 mPasswordComplexity = parser.getAttributeInt(null, ATTR_VALUE);
+            } else if (TAG_NEARBY_NOTIFICATION_STREAMING_POLICY.equals(tag)) {
+                mNearbyNotificationStreamingPolicy = parser.getAttributeInt(null, ATTR_VALUE);
+            } else if (TAG_NEARBY_APP_STREAMING_POLICY.equals(tag)) {
+                mNearbyAppStreamingPolicy = parser.getAttributeInt(null, ATTR_VALUE);
             } else if (TAG_ORGANIZATION_ID.equals(tag)) {
                 type = parser.next();
                 if (type == TypedXmlPullParser.TEXT) {
@@ -1154,6 +1177,12 @@
         pw.print("mPasswordComplexity=");
         pw.println(mPasswordComplexity);
 
+        pw.print("mNearbyNotificationStreamingPolicy=");
+        pw.println(mNearbyNotificationStreamingPolicy);
+
+        pw.print("mNearbyAppStreamingPolicy=");
+        pw.println(mNearbyAppStreamingPolicy);
+
         if (!TextUtils.isEmpty(mOrganizationId)) {
             pw.print("mOrganizationId=");
             pw.println(mOrganizationId);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 8739a01..1858712 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -63,6 +63,7 @@
 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_HOME;
 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS;
 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW;
+import static android.app.admin.DevicePolicyManager.NEARBY_STREAMING_DISABLED;
 import static android.app.admin.DevicePolicyManager.NON_ORG_OWNED_PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER;
 import static android.app.admin.DevicePolicyManager.OPERATION_SAFETY_REASON_NONE;
 import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_HIGH;
@@ -7472,6 +7473,78 @@
         });
     }
 
+    @Override
+    public void setNearbyNotificationStreamingPolicy(int policy) {
+        if (!mHasFeature) {
+            return;
+        }
+
+        final CallerIdentity caller = getCallerIdentity();
+        Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+
+        synchronized (getLockObject()) {
+            final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller);
+            if (admin.mNearbyNotificationStreamingPolicy != policy) {
+                admin.mNearbyNotificationStreamingPolicy = policy;
+                saveSettingsLocked(caller.getUserId());
+            }
+        }
+    }
+
+    @Override
+    public int getNearbyNotificationStreamingPolicy() {
+        if (!mHasFeature) {
+            return NEARBY_STREAMING_DISABLED;
+        }
+
+        final CallerIdentity caller = getCallerIdentity();
+        Preconditions.checkCallAuthorization(
+                isDeviceOwner(caller)
+                    || isProfileOwner(caller)
+                    || hasCallingOrSelfPermission(permission.READ_NEARBY_STREAMING_POLICY));
+
+        synchronized (getLockObject()) {
+            final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller);
+            return admin.mNearbyNotificationStreamingPolicy;
+        }
+    }
+
+    @Override
+    public void setNearbyAppStreamingPolicy(int policy) {
+        if (!mHasFeature) {
+            return;
+        }
+
+        final CallerIdentity caller = getCallerIdentity();
+        Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+
+        synchronized (getLockObject()) {
+            final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller);
+            if (admin.mNearbyAppStreamingPolicy != policy) {
+                admin.mNearbyAppStreamingPolicy = policy;
+                saveSettingsLocked(caller.getUserId());
+            }
+        }
+    }
+
+    @Override
+    public int getNearbyAppStreamingPolicy() {
+        if (!mHasFeature) {
+            return NEARBY_STREAMING_DISABLED;
+        }
+
+        final CallerIdentity caller = getCallerIdentity();
+        Preconditions.checkCallAuthorization(
+                isDeviceOwner(caller)
+                    || isProfileOwner(caller)
+                    || hasCallingOrSelfPermission(permission.READ_NEARBY_STREAMING_POLICY));
+
+        synchronized (getLockObject()) {
+            final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller);
+            return admin.mNearbyAppStreamingPolicy;
+        }
+    }
+
     /**
      * Set whether auto time is required by the specified admin (must be device or profile owner).
      */
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
index 29691fb..502f64a 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
@@ -16,7 +16,7 @@
 
 package com.android.server.accessibility.magnification;
 
-import static com.android.server.accessibility.magnification.FullScreenMagnificationController.MagnificationRequestObserver;
+import static com.android.server.accessibility.magnification.FullScreenMagnificationController.MagnificationInfoChangedCallback;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -96,8 +96,8 @@
     final WindowManagerInternal mMockWindowManager = mock(WindowManagerInternal.class);
     private final MagnificationAnimationCallback mAnimationCallback = mock(
             MagnificationAnimationCallback.class);
-    private final MagnificationRequestObserver mRequestObserver = mock(
-            MagnificationRequestObserver.class);
+    private final MagnificationInfoChangedCallback mRequestObserver = mock(
+            MagnificationInfoChangedCallback.class);
     final MessageCapturingHandler mMessageCapturingHandler = new MessageCapturingHandler(null);
 
     ValueAnimator mMockValueAnimator;
@@ -1145,6 +1145,15 @@
         verify(mRequestObserver).onFullScreenMagnificationActivationState(eq(false));
     }
 
+    @Test
+    public void testImeWindowIsShown_serviceNotified() {
+        register(DISPLAY_0);
+        MagnificationCallbacks callbacks = getMagnificationCallbacks(DISPLAY_0);
+        callbacks.onImeWindowVisibilityChanged(true);
+        mMessageCapturingHandler.sendAllMessages();
+        verify(mRequestObserver).onImeWindowVisibilityChanged(eq(true));
+    }
+
     private void setScaleToMagnifying() {
         register(DISPLAY_0);
         float scale = 2.0f;
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
index 28a6ff7..f881f04 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
@@ -53,7 +53,7 @@
 
 import com.android.server.accessibility.AccessibilityManagerService;
 import com.android.server.accessibility.EventStreamTransformation;
-import com.android.server.accessibility.magnification.FullScreenMagnificationController.MagnificationRequestObserver;
+import com.android.server.accessibility.magnification.FullScreenMagnificationController.MagnificationInfoChangedCallback;
 import com.android.server.testutils.OffsettableClock;
 import com.android.server.testutils.TestHandler;
 import com.android.server.wm.WindowManagerInternal;
@@ -126,7 +126,7 @@
     @Mock
     MagnificationGestureHandler.Callback mMockCallback;
     @Mock
-    MagnificationRequestObserver mMagnificationRequestObserver;
+    MagnificationInfoChangedCallback mMagnificationInfoChangedCallback;
     @Mock
     WindowMagnificationPromptController mWindowMagnificationPromptController;
 
@@ -151,7 +151,7 @@
         when(mockController.getAnimationDuration()).thenReturn(1000L);
         when(mockWindowManager.setMagnificationCallbacks(eq(DISPLAY_0), any())).thenReturn(true);
         mFullScreenMagnificationController = new FullScreenMagnificationController(mockController,
-                new Object(), mMagnificationRequestObserver) {
+                new Object(), mMagnificationInfoChangedCallback) {
             @Override
             public boolean magnificationRegionContains(int displayId, float x, float y) {
                 return true;
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
index cf23197..3dff36e 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
@@ -486,6 +486,47 @@
                 eq(MODE_WINDOW));
     }
 
+    @Test
+    public void imeWindowStateShown_windowMagnifying_logWindowMode() {
+        mMagnificationController.onWindowMagnificationActivationState(true);
+
+        mMagnificationController.onImeWindowVisibilityChanged(true);
+
+        verify(mMagnificationController).logMagnificationModeWithIme(
+                eq(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW));
+    }
+
+    @Test
+    public void imeWindowStateShown_fullScreenMagnifying_logFullScreenMode() {
+        mMagnificationController.onFullScreenMagnificationActivationState(true);
+
+        mMagnificationController.onImeWindowVisibilityChanged(true);
+
+        verify(mMagnificationController).logMagnificationModeWithIme(
+                eq(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN));
+    }
+
+    @Test
+    public void imeWindowStateShown_noMagnifying_noLogAnyMode() {
+        mMagnificationController.onImeWindowVisibilityChanged(true);
+
+        verify(mMagnificationController, never()).logMagnificationModeWithIme(anyInt());
+    }
+
+    @Test
+    public void imeWindowStateHidden_windowMagnifying_noLogAnyMode() {
+        mMagnificationController.onFullScreenMagnificationActivationState(true);
+
+        verify(mMagnificationController, never()).logMagnificationModeWithIme(anyInt());
+    }
+
+    @Test
+    public void imeWindowStateHidden_fullScreenMagnifying_noLogAnyMode() {
+        mMagnificationController.onWindowMagnificationActivationState(true);
+
+        verify(mMagnificationController, never()).logMagnificationModeWithIme(anyInt());
+    }
+
     private void setMagnificationEnabled(int mode) throws RemoteException {
 
         setMagnificationEnabled(mode, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y);
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 02b8ddd..88b0651 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -55,6 +55,7 @@
 import android.app.appsearch.IAppSearchResultCallback;
 import android.app.appsearch.PackageIdentifier;
 import android.app.appsearch.SearchResultPage;
+import android.app.appsearch.SetSchemaResponse;
 import android.app.role.OnRoleHoldersChangedListener;
 import android.app.usage.UsageStatsManagerInternal;
 import android.content.ActivityNotFoundException;
@@ -672,7 +673,8 @@
                     packageIdentifiers.add(new PackageIdentifier(entry.getValue().get(i)));
                 }
             }
-            callback.onResult(AppSearchResult.newSuccessfulResult(null));
+            final SetSchemaResponse response = new SetSchemaResponse.Builder().build();
+            callback.onResult(AppSearchResult.newSuccessfulResult(response.getBundle()));
         }
 
         @Override
@@ -848,6 +850,12 @@
         }
 
         @Override
+        public void getStorageInfo(String packageName, String databaseName, int userId,
+                IAppSearchResultCallback callback) throws RemoteException {
+            ignore(callback);
+        }
+
+        @Override
         public void persistToDisk(int userId) throws RemoteException {
 
         }
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java
index 13d75a7..f014119 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java
@@ -22,6 +22,7 @@
 import com.android.server.pm.dex.ArtStatsLogUtils.ArtStatsLogger;
 
 import org.junit.AfterClass;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -49,6 +50,9 @@
     private static final String COMPILER_FILTER = "space-profile";
     private static final String PROFILE_DEX_METADATA = "primary.prof";
     private static final String VDEX_DEX_METADATA = "primary.vdex";
+    private static final String INSTRUCTION_SET = "arm64";
+    private static final String BASE_APK = "base.apk";
+    private static final String SPLIT_APK = "split.apk";
     private static final byte[] DEX_CONTENT = "dexData".getBytes();
     private static final int COMPILATION_REASON = 1;
     private static final int RESULT_CODE = 222;
@@ -97,17 +101,18 @@
             ArtStatsLogUtils.writeStatsLog(
                     mockLogger,
                     SESSION_ID,
-                    apk.toString(),
                     COMPILER_FILTER,
                     UID,
                     COMPILE_TIME,
                     dexMetadataPath.toString(),
                     COMPILATION_REASON,
-                    RESULT_CODE);
+                    RESULT_CODE,
+                    ArtStatsLog.ART_DATUM_REPORTED__APK_TYPE__ART_APK_TYPE_BASE,
+                    INSTRUCTION_SET);
 
             // Assert
             verifyWrites(ArtStatsLog.
-                ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_PROFILE_AND_VDEX);
+                    ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_PROFILE_AND_VDEX);
         } finally {
             deleteSliently(dexMetadataPath);
             deleteSliently(apk);
@@ -127,17 +132,18 @@
             ArtStatsLogUtils.writeStatsLog(
                     mockLogger,
                     SESSION_ID,
-                    apk.toString(),
                     COMPILER_FILTER,
                     UID,
                     COMPILE_TIME,
                     dexMetadataPath.toString(),
                     COMPILATION_REASON,
-                    RESULT_CODE);
+                    RESULT_CODE,
+                    ArtStatsLog.ART_DATUM_REPORTED__APK_TYPE__ART_APK_TYPE_BASE,
+                    INSTRUCTION_SET);
 
             // Assert
             verifyWrites(ArtStatsLog.
-                ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_PROFILE);
+                    ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_PROFILE);
         } finally {
             deleteSliently(dexMetadataPath);
             deleteSliently(apk);
@@ -157,17 +163,18 @@
             ArtStatsLogUtils.writeStatsLog(
                     mockLogger,
                     SESSION_ID,
-                    apk.toString(),
                     COMPILER_FILTER,
                     UID,
                     COMPILE_TIME,
                     dexMetadataPath.toString(),
                     COMPILATION_REASON,
-                    RESULT_CODE);
+                    RESULT_CODE,
+                    ArtStatsLog.ART_DATUM_REPORTED__APK_TYPE__ART_APK_TYPE_BASE,
+                    INSTRUCTION_SET);
 
             // Assert
             verifyWrites(ArtStatsLog.
-                ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_VDEX);
+                    ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_VDEX);
         } finally {
             deleteSliently(dexMetadataPath);
             deleteSliently(apk);
@@ -185,17 +192,18 @@
             ArtStatsLogUtils.writeStatsLog(
                     mockLogger,
                     SESSION_ID,
-                    apk.toString(),
                     COMPILER_FILTER,
                     UID,
                     COMPILE_TIME,
                     /*dexMetadataPath=*/ null,
                     COMPILATION_REASON,
-                    RESULT_CODE);
+                    RESULT_CODE,
+                    ArtStatsLog.ART_DATUM_REPORTED__APK_TYPE__ART_APK_TYPE_BASE,
+                    INSTRUCTION_SET);
 
             // Assert
             verifyWrites(ArtStatsLog.
-                ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_NONE);
+                    ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_NONE);
         } finally {
             deleteSliently(apk);
         }
@@ -214,23 +222,35 @@
             ArtStatsLogUtils.writeStatsLog(
                     mockLogger,
                     SESSION_ID,
-                    apk.toString(),
                     COMPILER_FILTER,
                     UID,
                     COMPILE_TIME,
                     dexMetadataPath.toString(),
                     COMPILATION_REASON,
-                    RESULT_CODE);
+                    RESULT_CODE,
+                    ArtStatsLog.ART_DATUM_REPORTED__APK_TYPE__ART_APK_TYPE_BASE,
+                    INSTRUCTION_SET);
 
             // Assert
             verifyWrites(ArtStatsLog.
-                ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_UNKNOWN);
+                    ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_UNKNOWN);
         } finally {
             deleteSliently(dexMetadataPath);
             deleteSliently(apk);
         }
     }
 
+    @Test
+    public void testGetApkType() {
+        // Act
+        int result1 = ArtStatsLogUtils.getApkType(BASE_APK);
+        int result2 = ArtStatsLogUtils.getApkType(SPLIT_APK);
+
+        // Assert
+        Assert.assertEquals(result1, ArtStatsLog.ART_DATUM_REPORTED__APK_TYPE__ART_APK_TYPE_BASE);
+        Assert.assertEquals(result2, ArtStatsLog.ART_DATUM_REPORTED__APK_TYPE__ART_APK_TYPE_SPLIT);
+    }
+
     private void verifyWrites(int dexMetadataType) {
         InOrder inorder = inOrder(mockLogger);
         inorder.verify(mockLogger).write(
@@ -239,7 +259,9 @@
                 COMPILER_FILTER,
                 ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_RESULT_CODE,
                 RESULT_CODE,
-                dexMetadataType);
+                dexMetadataType,
+                ArtStatsLog.ART_DATUM_REPORTED__APK_TYPE__ART_APK_TYPE_BASE,
+                INSTRUCTION_SET);
         inorder.verify(mockLogger).write(
                 SESSION_ID,
                 UID,
@@ -247,7 +269,9 @@
                 COMPILER_FILTER,
                 ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_TOTAL_TIME,
                 COMPILE_TIME,
-                dexMetadataType);
+                dexMetadataType,
+                ArtStatsLog.ART_DATUM_REPORTED__APK_TYPE__ART_APK_TYPE_BASE,
+                INSTRUCTION_SET);
     }
 
     private Path zipFiles(String suffix, Path... files) throws IOException {
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index 2df6c5a..874f8dc 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -467,21 +467,21 @@
         // First, ensure that a normal full wake lock does not cause a wakeup
         int flags = PowerManager.FULL_WAKE_LOCK;
         mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
-                null /* workSource */, null /* historyTag */);
+                null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY);
         assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
         mService.getBinderServiceInstance().releaseWakeLock(token, 0 /* flags */);
 
         // Ensure that the flag does *NOT* work with a partial wake lock.
         flags = PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP;
         mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
-                null /* workSource */, null /* historyTag */);
+                null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY);
         assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
         mService.getBinderServiceInstance().releaseWakeLock(token, 0 /* flags */);
 
         // Verify that flag forces a wakeup when paired to a FULL_WAKE_LOCK
         flags = PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP;
         mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
-                null /* workSource */, null /* historyTag */);
+                null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY);
         assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
         mService.getBinderServiceInstance().releaseWakeLock(token, 0 /* flags */);
     }
@@ -669,7 +669,7 @@
 
         // Create a wakelock
         mService.getBinderServiceInstance().acquireWakeLock(new Binder(), flags, tag, pkg,
-                null /* workSource */, null /* historyTag */);
+                null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY);
         assertThat(wakelockMap.get(tag)).isEqualTo(flags);  // Verify wakelock is active.
 
         // Confirm that the wakelocks have been disabled when the forceSuspend is in flight.
@@ -727,7 +727,7 @@
         // Take a nap and verify we no longer hold the blocker
         int flags = PowerManager.DOZE_WAKE_LOCK;
         mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
-                null /* workSource */, null /* historyTag */);
+                null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY);
         when(mDreamManagerInternalMock.isDreaming()).thenReturn(true);
         mService.getBinderServiceInstance().goToSleep(mClock.now(),
                 PowerManager.GO_TO_SLEEP_REASON_APPLICATION, 0);
@@ -835,13 +835,94 @@
 
         mService.getBinderServiceInstance().acquireWakeLock(token,
                 PowerManager.SCREEN_BRIGHT_WAKE_LOCK, tag, pkg,
-                null /* workSource */, null /* historyTag */);
+                null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY);
 
+        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
         advanceTime(60);
         assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
     }
 
     @Test
+    public void testWakeLock_affectsProperDisplayGroup() throws Exception {
+        final int nonDefaultDisplayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1;
+        final AtomicReference<DisplayManagerInternal.DisplayGroupListener> listener =
+                new AtomicReference<>();
+        doAnswer((Answer<Void>) invocation -> {
+            listener.set(invocation.getArgument(0));
+            return null;
+        }).when(mDisplayManagerInternalMock).registerDisplayGroupListener(any());
+        final DisplayInfo info = new DisplayInfo();
+        info.displayGroupId = Display.DEFAULT_DISPLAY_GROUP;
+        when(mDisplayManagerInternalMock.getDisplayInfo(Display.DEFAULT_DISPLAY)).thenReturn(info);
+
+        final String pkg = mContextSpy.getOpPackageName();
+        final Binder token = new Binder();
+        final String tag = "testWakeLock_affectsProperDisplayGroup";
+
+        setMinimumScreenOffTimeoutConfig(5);
+        createService();
+        startSystem();
+        listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId);
+
+        mService.getBinderServiceInstance().acquireWakeLock(token,
+                PowerManager.SCREEN_BRIGHT_WAKE_LOCK, tag, pkg,
+                null /* workSource */, null /* historyTag */, Display.DEFAULT_DISPLAY);
+
+        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo(
+                WAKEFULNESS_AWAKE);
+        assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo(
+                WAKEFULNESS_AWAKE);
+
+        advanceTime(15000);
+        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo(
+                WAKEFULNESS_AWAKE);
+        assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo(
+                WAKEFULNESS_DOZING);
+    }
+
+    @Test
+    public void testInvalidDisplayGroupWakeLock_affectsAllDisplayGroups() throws Exception {
+        final int nonDefaultDisplayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1;
+        final AtomicReference<DisplayManagerInternal.DisplayGroupListener> listener =
+                new AtomicReference<>();
+        doAnswer((Answer<Void>) invocation -> {
+            listener.set(invocation.getArgument(0));
+            return null;
+        }).when(mDisplayManagerInternalMock).registerDisplayGroupListener(any());
+        final DisplayInfo info = new DisplayInfo();
+        info.displayGroupId = Display.DEFAULT_DISPLAY_GROUP;
+        when(mDisplayManagerInternalMock.getDisplayInfo(Display.DEFAULT_DISPLAY)).thenReturn(info);
+
+        final String pkg = mContextSpy.getOpPackageName();
+        final Binder token = new Binder();
+        final String tag = "testInvalidDisplayGroupWakeLock_affectsAllDisplayGroups";
+
+        setMinimumScreenOffTimeoutConfig(5);
+        createService();
+        startSystem();
+        listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId);
+
+        mService.getBinderServiceInstance().acquireWakeLock(token,
+                PowerManager.SCREEN_BRIGHT_WAKE_LOCK, tag, pkg,
+                null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY);
+
+        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo(
+                WAKEFULNESS_AWAKE);
+        assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo(
+                WAKEFULNESS_AWAKE);
+
+        advanceTime(15000);
+        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo(
+                WAKEFULNESS_AWAKE);
+        assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo(
+                WAKEFULNESS_AWAKE);
+    }
+
+    @Test
     public void testBoot_ShouldBeAwake() throws Exception {
         createService();
         startSystem();
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowOrientationListenerTest.java b/services/tests/servicestests/src/com/android/server/wm/WindowOrientationListenerTest.java
index f5d0ca7..584bcf4 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowOrientationListenerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowOrientationListenerTest.java
@@ -58,7 +58,6 @@
     private com.android.server.wm.WindowOrientationListener mWindowOrientationListener;
     private int mFinalizedRotation;
     private boolean mRotationResolverEnabled;
-    private boolean mCanUseRotationResolver;
     private SensorEvent mFakeSensorEvent;
     private Sensor mFakeSensor;
 
@@ -66,7 +65,6 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mRotationResolverEnabled = true;
-        mCanUseRotationResolver = true;
 
         mFakeRotationResolverInternal = new TestableRotationResolver();
         doReturn(mMockSensorManager).when(mMockContext).getSystemService(Context.SENSOR_SERVICE);
@@ -89,16 +87,6 @@
     }
 
     @Test
-    public void testOnSensorChanged_cannotUseRotationResolver_useSensorResult() {
-        mCanUseRotationResolver = false;
-
-        mWindowOrientationListener.mOrientationJudge.onSensorChanged(mFakeSensorEvent);
-
-        assertThat(mFinalizedRotation).isEqualTo(Surface.ROTATION_90);
-
-    }
-
-    @Test
     public void testOnSensorChanged_normalCase() {
         mFakeRotationResolverInternal.mResult = Surface.ROTATION_180;
 
@@ -139,11 +127,6 @@
         }
 
         @Override
-        public boolean canUseRotationResolver() {
-            return mCanUseRotationResolver;
-        }
-
-        @Override
         public boolean isRotationResolverEnabled() {
             return mRotationResolverEnabled;
         }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 55ebe11..bb70c79 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -6972,51 +6972,6 @@
     }
 
     @Test
-    public void deleteConversationNotificationChannels() throws Exception {
-        NotificationChannel messagesParent =
-                new NotificationChannel("messages", "messages", IMPORTANCE_HIGH);
-        Parcel msgParcel = Parcel.obtain();
-        messagesParent.writeToParcel(msgParcel, 0);
-        msgParcel.setDataPosition(0);
-
-        NotificationChannel callsParent =
-                new NotificationChannel("calls", "calls", IMPORTANCE_HIGH);
-        Parcel callParcel = Parcel.obtain();
-        callsParent.writeToParcel(callParcel, 0);
-        callParcel.setDataPosition(0);
-
-        mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(
-                messagesParent, callsParent)));
-
-        String conversationId = "friend";
-
-        mBinderService.createConversationNotificationChannelForPackage(
-                PKG, mUid, NotificationChannel.CREATOR.createFromParcel(msgParcel),
-                conversationId);
-        mBinderService.createConversationNotificationChannelForPackage(
-                PKG, mUid, NotificationChannel.CREATOR.createFromParcel(callParcel),
-                conversationId);
-
-        NotificationChannel messagesChild = mBinderService.getConversationNotificationChannel(
-                PKG, 0, PKG, messagesParent.getId(), false, conversationId);
-        NotificationChannel callsChild = mBinderService.getConversationNotificationChannel(
-                PKG, 0, PKG, callsParent.getId(), false, conversationId);
-
-        assertEquals(messagesParent.getId(), messagesChild.getParentChannelId());
-        assertEquals(conversationId, messagesChild.getConversationId());
-
-        assertEquals(callsParent.getId(), callsChild.getParentChannelId());
-        assertEquals(conversationId, callsChild.getConversationId());
-
-        mBinderService.deleteConversationNotificationChannels(PKG, mUid, conversationId);
-
-        assertNull(mBinderService.getConversationNotificationChannel(
-                PKG, 0, PKG, messagesParent.getId(), false, conversationId));
-        assertNull(mBinderService.getConversationNotificationChannel(
-                PKG, 0, PKG, callsParent.getId(), false, conversationId));
-    }
-
-    @Test
     public void testCorrectCategory_systemOn_appCannotTurnOff() {
         int requested = 0;
         int system = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index acda4d5..04c144a 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -71,6 +71,7 @@
 import android.app.NotificationChannel;
 import android.app.NotificationChannelGroup;
 import android.app.NotificationManager;
+import android.content.AttributionSource;
 import android.content.ContentProvider;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -86,6 +87,7 @@
 import android.os.AsyncTask;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.Process;
 import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -207,37 +209,35 @@
             throw new UnsupportedOperationException("unimplemented mock method");
         });
         doAnswer(invocation -> {
-            String callingPkg = invocation.getArgument(0);
-            String featureId = invocation.getArgument(1);
-            Uri uri = invocation.getArgument(2);
-            RemoteCallback cb = invocation.getArgument(3);
+            AttributionSource attributionSource = invocation.getArgument(0);
+            Uri uri = invocation.getArgument(1);
+            RemoteCallback cb = invocation.getArgument(2);
             IContentProvider mock = (IContentProvider) (invocation.getMock());
             AsyncTask.SERIAL_EXECUTOR.execute(() -> {
                 final Bundle bundle = new Bundle();
                 try {
                     bundle.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT,
-                            mock.canonicalize(callingPkg, featureId, uri));
+                            mock.canonicalize(attributionSource, uri));
                 } catch (RemoteException e) { /* consume */ }
                 cb.sendResult(bundle);
             });
             return null;
-        }).when(mTestIContentProvider).canonicalizeAsync(any(), any(), any(), any());
+        }).when(mTestIContentProvider).canonicalizeAsync(any(), any(), any());
         doAnswer(invocation -> {
-            String callingPkg = invocation.getArgument(0);
-            String featureId = invocation.getArgument(1);
-            Uri uri = invocation.getArgument(2);
-            RemoteCallback cb = invocation.getArgument(3);
+            AttributionSource attributionSource = invocation.getArgument(0);
+            Uri uri = invocation.getArgument(1);
+            RemoteCallback cb = invocation.getArgument(2);
             IContentProvider mock = (IContentProvider) (invocation.getMock());
             AsyncTask.SERIAL_EXECUTOR.execute(() -> {
                 final Bundle bundle = new Bundle();
                 try {
                     bundle.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT,
-                            mock.uncanonicalize(callingPkg, featureId, uri));
+                            mock.uncanonicalize(attributionSource, uri));
                 } catch (RemoteException e) { /* consume */ }
                 cb.sendResult(bundle);
             });
             return null;
-        }).when(mTestIContentProvider).uncanonicalizeAsync(any(), any(), any(), any());
+        }).when(mTestIContentProvider).uncanonicalizeAsync(any(), any(), any());
         doAnswer(invocation -> {
             Uri uri = invocation.getArgument(0);
             RemoteCallback cb = invocation.getArgument(1);
@@ -256,11 +256,11 @@
         contentResolver.addProvider(TEST_AUTHORITY, testContentProvider);
 
         doReturn(CANONICAL_SOUND_URI)
-                .when(mTestIContentProvider).canonicalize(any(), any(), eq(SOUND_URI));
+                .when(mTestIContentProvider).canonicalize(any(), eq(SOUND_URI));
         doReturn(CANONICAL_SOUND_URI)
-                .when(mTestIContentProvider).canonicalize(any(), any(), eq(CANONICAL_SOUND_URI));
+                .when(mTestIContentProvider).canonicalize(any(), eq(CANONICAL_SOUND_URI));
         doReturn(SOUND_URI)
-                .when(mTestIContentProvider).uncanonicalize(any(), any(), eq(CANONICAL_SOUND_URI));
+                .when(mTestIContentProvider).uncanonicalize(any(), eq(CANONICAL_SOUND_URI));
 
         mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0,
                 NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND, 0);
@@ -594,7 +594,7 @@
 
         // Testing that in restore we are given the canonical version
         loadStreamXml(baos, true, UserHandle.USER_SYSTEM);
-        verify(mTestIContentProvider).uncanonicalize(any(), any(), eq(CANONICAL_SOUND_URI));
+        verify(mTestIContentProvider).uncanonicalize(any(), eq(CANONICAL_SOUND_URI));
     }
 
     @Test
@@ -605,12 +605,11 @@
                 .appendQueryParameter("canonical", "1")
                 .build();
         doReturn(canonicalBasedOnLocal)
-                .when(mTestIContentProvider).canonicalize(any(), any(), eq(CANONICAL_SOUND_URI));
+                .when(mTestIContentProvider).canonicalize(any(), eq(CANONICAL_SOUND_URI));
         doReturn(localUri)
-                .when(mTestIContentProvider).uncanonicalize(any(), any(), eq(CANONICAL_SOUND_URI));
+                .when(mTestIContentProvider).uncanonicalize(any(), eq(CANONICAL_SOUND_URI));
         doReturn(localUri)
-                .when(mTestIContentProvider).uncanonicalize(any(), any(),
-                eq(canonicalBasedOnLocal));
+                .when(mTestIContentProvider).uncanonicalize(any(), eq(canonicalBasedOnLocal));
 
         NotificationChannel channel =
                 new NotificationChannel("id", "name", IMPORTANCE_LOW);
@@ -630,9 +629,9 @@
     public void testRestoreXml_withNonExistentCanonicalizedSoundUri() throws Exception {
         Thread.sleep(3000);
         doReturn(null)
-                .when(mTestIContentProvider).canonicalize(any(), any(), eq(CANONICAL_SOUND_URI));
+                .when(mTestIContentProvider).canonicalize(any(), eq(CANONICAL_SOUND_URI));
         doReturn(null)
-                .when(mTestIContentProvider).uncanonicalize(any(), any(), eq(CANONICAL_SOUND_URI));
+                .when(mTestIContentProvider).uncanonicalize(any(), eq(CANONICAL_SOUND_URI));
 
         NotificationChannel channel =
                 new NotificationChannel("id", "name", IMPORTANCE_LOW);
@@ -657,7 +656,7 @@
     public void testRestoreXml_withUncanonicalizedNonLocalSoundUri() throws Exception {
         // Not a local uncanonicalized uri, simulating that it fails to exist locally
         doReturn(null)
-                .when(mTestIContentProvider).canonicalize(any(), any(), eq(SOUND_URI));
+                .when(mTestIContentProvider).canonicalize(any(), eq(SOUND_URI));
         String id = "id";
         String backupWithUncanonicalizedSoundUri = "<ranking version=\"1\">\n"
                 + "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n"
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
index 5018166..b83f9f2 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
@@ -132,11 +132,11 @@
         when(testContentProvider.getIContentProvider()).thenReturn(mTestIContentProvider);
         contentResolver.addProvider(TEST_AUTHORITY, testContentProvider);
 
-        when(mTestIContentProvider.canonicalize(any(), any(), eq(SOUND_URI)))
+        when(mTestIContentProvider.canonicalize(any(), eq(SOUND_URI)))
                 .thenReturn(CANONICAL_SOUND_URI);
-        when(mTestIContentProvider.canonicalize(any(), any(), eq(CANONICAL_SOUND_URI)))
+        when(mTestIContentProvider.canonicalize(any(), eq(CANONICAL_SOUND_URI)))
                 .thenReturn(CANONICAL_SOUND_URI);
-        when(mTestIContentProvider.uncanonicalize(any(), any(), eq(CANONICAL_SOUND_URI)))
+        when(mTestIContentProvider.uncanonicalize(any(), eq(CANONICAL_SOUND_URI)))
                 .thenReturn(SOUND_URI);
 
         mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0,
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
index aceed86..baae25c 100644
--- a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
@@ -110,7 +110,7 @@
         mPinnedSliceManager.pin("pkg", FIRST_SPECS, mToken);
         TestableLooper.get(this).processAllMessages();
 
-        verify(mIContentProvider).call(anyString(), nullable(String.class), anyString(),
+        verify(mIContentProvider).call(any(), anyString(),
                 eq(SliceProvider.METHOD_PIN), eq(null), argThat(b -> {
                     assertEquals(TEST_URI, b.getParcelable(SliceProvider.EXTRA_BIND_URI));
                     return true;
@@ -168,8 +168,8 @@
         // Throw exception when trying to pin
         doAnswer(invocation -> {
             throw new Exception("Pin failed");
-        }).when(mIContentProvider).call(anyString(), nullable(String.class), anyString(),
-                anyString(), eq(null), any());
+        }).when(mIContentProvider).call(any(), anyString(), anyString(),
+                nullable(String.class), any());
 
         TestableLooper.get(this).processAllMessages();
 
@@ -177,7 +177,7 @@
         mPinnedSliceManager.pin("pkg", FIRST_SPECS, mToken);
         TestableLooper.get(this).processAllMessages();
 
-        verify(mIContentProvider).call(anyString(), nullable(String.class), anyString(),
+        verify(mIContentProvider).call(any(), anyString(),
                 eq(SliceProvider.METHOD_PIN), eq(null), argThat(b -> {
                     assertEquals(TEST_URI, b.getParcelable(SliceProvider.EXTRA_BIND_URI));
                     return true;
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
index bbfb0d6..5d541e9 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
@@ -93,7 +93,7 @@
 
     HotwordDetectionConnection(Object lock, Context context, ComponentName serviceName,
             int userId, boolean bindInstantServiceAllowed, @Nullable PersistableBundle options,
-            @Nullable SharedMemory sharedMemory) {
+            @Nullable SharedMemory sharedMemory, IHotwordRecognitionStatusCallback callback) {
         mLock = lock;
         mContext = context;
         mDetectionComponentName = serviceName;
@@ -111,7 +111,7 @@
                     mBound = connected;
                     if (connected) {
                         try {
-                            service.updateState(options, sharedMemory);
+                            service.updateState(options, sharedMemory, callback);
                         } catch (RemoteException e) {
                             // TODO: (b/181842909) Report an error to voice interactor
                             Slog.w(TAG, "Failed to updateState for HotwordDetectionService", e);
@@ -146,7 +146,7 @@
 
     void updateStateLocked(PersistableBundle options, SharedMemory sharedMemory) {
         mRemoteHotwordDetectionService.run(
-                service -> service.updateState(options, sharedMemory));
+                service -> service.updateState(options, sharedMemory, null /* callback */));
     }
 
     void startListeningFromMic(
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index d66f21f..ccaeaf9 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -1026,7 +1026,7 @@
 
         @Override
         public void updateState(@Nullable PersistableBundle options,
-                @Nullable SharedMemory sharedMemory) {
+                @Nullable SharedMemory sharedMemory, IHotwordRecognitionStatusCallback callback) {
             enforceCallingPermission(Manifest.permission.MANAGE_HOTWORD_DETECTION);
             synchronized (this) {
                 enforceIsCurrentVoiceInteractionService();
@@ -1037,7 +1037,7 @@
                 }
                 final long caller = Binder.clearCallingIdentity();
                 try {
-                    mImpl.updateStateLocked(options, sharedMemory);
+                    mImpl.updateStateLocked(options, sharedMemory, callback);
                 } finally {
                     Binder.restoreCallingIdentity(caller);
                 }
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index efa7f78..6922ccc 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -405,7 +405,7 @@
     }
 
     public void updateStateLocked(@Nullable PersistableBundle options,
-            @Nullable SharedMemory sharedMemory) {
+            @Nullable SharedMemory sharedMemory, IHotwordRecognitionStatusCallback callback) {
         if (DEBUG) {
             Slog.d(TAG, "updateStateLocked");
         }
@@ -427,7 +427,7 @@
         if (mHotwordDetectionConnection == null) {
             mHotwordDetectionConnection = new HotwordDetectionConnection(mServiceStub, mContext,
                     mHotwordDetectionComponentName, mUser, /* bindInstantServiceAllowed= */ false,
-                    options, sharedMemory);
+                    options, sharedMemory, callback);
         } else {
             mHotwordDetectionConnection.updateStateLocked(options, sharedMemory);
         }
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 1677c8c..4886789 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -25,6 +25,8 @@
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
@@ -1004,6 +1006,17 @@
             PRESENTATION_PAYPHONE})
     public @interface Presentation {}
 
+
+    /**
+     * Enable READ_PHONE_STATE protection on APIs querying and notifying call state, such as
+     * {@code TelecomManager#getCallState}, {@link TelephonyManager#getCallStateForSubscription()},
+     * and {@link android.telephony.TelephonyCallback.CallStateListener}.
+     */
+    @ChangeId
+    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.S)
+    // this magic number is a bug ID
+    public static final long ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION = 157233955L;
+
     private static final String TAG = "TelecomManager";
 
 
@@ -1758,21 +1771,23 @@
      * {@link TelephonyManager#CALL_STATE_OFFHOOK}
      * {@link TelephonyManager#CALL_STATE_IDLE}
      *
-     * Note that this API does not require the
-     * {@link android.Manifest.permission#READ_PHONE_STATE} permission. This is intentional, to
-     * preserve the behavior of {@link TelephonyManager#getCallState()}, which also did not require
-     * the permission.
-     *
      * Takes into consideration both managed and self-managed calls.
+     * <p>
+     * Requires Permission:
+     * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} for applications
+     * targeting API level 31+.
      *
      * @hide
      */
+    @RequiresPermission(anyOf = {READ_PRIVILEGED_PHONE_STATE,
+            android.Manifest.permission.READ_PHONE_STATE}, conditional = true)
     @SystemApi
     public @CallState int getCallState() {
         ITelecomService service = getTelecomService();
         if (service != null) {
             try {
-                return service.getCallState();
+                return service.getCallStateUsingPackage(mContext.getPackageName(),
+                        mContext.getAttributionTag());
             } catch (RemoteException e) {
                 Log.d(TAG, "RemoteException calling getCallState().", e);
             }
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 78283fa..18afde7 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -195,11 +195,18 @@
 
     /**
      * @see TelecomServiceImpl#getCallState
+     * Note: only kept around to not break app compat, however this will throw a SecurityException
+     * on API 31+.
      */
     @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
     int getCallState();
 
     /**
+     * @see TelecomServiceImpl#getCallState
+     */
+    int getCallStateUsingPackage(String callingPackage, String callingFeatureId);
+
+    /**
      * @see TelecomServiceImpl#endCall
      */
     boolean endCall(String callingPackage);
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index d2da51a..653aa9c 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -105,6 +105,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
 import com.android.internal.telephony.CellNetworkScanResult;
 import com.android.internal.telephony.IBooleanConsumer;
 import com.android.internal.telephony.ICallForwardingInfoCallback;
@@ -139,6 +140,7 @@
 import java.util.Objects;
 import java.util.UUID;
 import java.util.concurrent.Executor;
+import java.util.concurrent.RejectedExecutionException;
 import java.util.function.Consumer;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
@@ -431,6 +433,27 @@
     }
 
     /**
+     * Post a runnable to the BackgroundThread.
+     *
+     * Used to invoke user callbacks without calling into the caller's executor from the caller's
+     * calling thread context, for example to provide asynchronous error information that is
+     * generated locally (not over a binder thread).
+     *
+     * <p>This is not necessary unless you are invoking caller's code asynchronously from within
+     * the caller's thread context.
+     *
+     * @param r a runnable.
+     */
+    private static void runOnBackgroundThread(@NonNull Runnable r) {
+        try {
+            BackgroundThread.getExecutor().execute(r);
+        } catch (RejectedExecutionException e) {
+            throw new IllegalStateException(
+                    "Failed to post a callback from the caller's thread context.", e);
+        }
+    }
+
+    /**
      * Returns the multi SIM variant
      * Returns DSDS for Dual SIM Dual Standby
      * Returns DSDA for Dual SIM Dual Active
@@ -5702,9 +5725,20 @@
      * Note: The call state returned via this method may differ from what is reported by
      * {@link PhoneStateListener#onCallStateChanged(int, String)}, as that callback only considers
      * Telephony (mobile) calls.
+     * <p>
+     * Requires Permission:
+     * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} for applications
+     * targeting API level 31+.
      *
      * @return the current call state.
+     * @deprecated Use {@link #getCallStateForSubscription} to retrieve the call state for a
+     * specific telephony subscription (which allows carrier privileged apps),
+     * {@link TelephonyCallback.CallStateListener} for real-time call state updates, or
+     * {@link TelecomManager#isInCall()}, which supplies an aggregate "in call" state for the entire
+     * device.
      */
+    @RequiresPermission(value = android.Manifest.permission.READ_PHONE_STATE, conditional = true)
+    @Deprecated
     public @CallState int getCallState() {
         if (mContext != null) {
             TelecomManager telecomManager = mContext.getSystemService(TelecomManager.class);
@@ -5716,19 +5750,48 @@
     }
 
     /**
+     * Retrieve the call state for a specific subscription that was specified when this
+     * TelephonyManager instance was created.
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} or that the calling
+     * application has carrier privileges (see {@link #hasCarrierPrivileges}).
+     * @see TelephonyManager#createForSubscriptionId(int)
+     * @see TelephonyManager#createForPhoneAccountHandle(PhoneAccountHandle)
+     * @return The call state of the subscription associated with this TelephonyManager instance.
+     */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    public @CallState int getCallStateForSubscription() {
+        return getCallState(getSubId());
+    }
+
+    /**
      * Returns the Telephony call state for calls on a specific subscription.
      * <p>
      * Note: This method considers ONLY telephony/mobile calls, where {@link #getCallState()}
      * considers the state of calls from other {@link android.telecom.ConnectionService}
      * implementations.
+     * <p>
+     * Requires Permission:
+     * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} for applications
+     * targeting API level 31+ or that the calling application has carrier privileges
+     * (see {@link #hasCarrierPrivileges()}).
      *
      * @param subId the subscription to check call state for.
      * @hide
      */
     @UnsupportedAppUsage
+    @RequiresPermission(value = android.Manifest.permission.READ_PHONE_STATE, conditional = true)
     public @CallState int getCallState(int subId) {
-        int phoneId = SubscriptionManager.getPhoneId(subId);
-        return getCallStateForSlot(phoneId);
+        ITelephony telephony = getITelephony();
+        if (telephony == null) {
+            return CALL_STATE_IDLE;
+        }
+        try {
+            return telephony.getCallStateForSubscription(subId, mContext.getPackageName(),
+                    mContext.getAttributionTag());
+        } catch (RemoteException e) {
+            return CALL_STATE_IDLE;
+        }
     }
 
     /**
@@ -5745,22 +5808,28 @@
      * Note: This method considers ONLY telephony/mobile calls, where {@link #getCallState()}
      * considers the state of calls from other {@link android.telecom.ConnectionService}
      * implementations.
+     * <p>
+     * Requires Permission:
+     * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} for applications
+     * targeting API level 31+ or that the calling application has carrier privileges
+     * (see {@link #hasCarrierPrivileges()}).
      *
      * @param slotIndex the SIM slot index to check call state for.
      * @hide
      */
+    @RequiresPermission(value = android.Manifest.permission.READ_PHONE_STATE, conditional = true)
     public @CallState int getCallStateForSlot(int slotIndex) {
         try {
+            int[] subId = SubscriptionManager.getSubId(slotIndex);
             ITelephony telephony = getITelephony();
-            if (telephony == null)
+            if (telephony == null || subId == null || subId.length  == 0) {
                 return CALL_STATE_IDLE;
-            return telephony.getCallStateForSlot(slotIndex);
-        } catch (RemoteException ex) {
+            }
+            return telephony.getCallStateForSubscription(subId[0], mContext.getPackageName(),
+                    mContext.getAttributionTag());
+        } catch (RemoteException | NullPointerException ex) {
             // the phone process is restarting.
             return CALL_STATE_IDLE;
-        } catch (NullPointerException ex) {
-          // the phone process is restarting.
-          return CALL_STATE_IDLE;
         }
     }
 
@@ -6240,7 +6309,7 @@
 
         /**
          * Error response to
-         * {@link android.telephony.TelephonyManager#requestCellInfoUpdate requestCellInfoUpdate()}.
+         * {@link TelephonyManager#requestCellInfoUpdate requestCellInfoUpdate()}.
          *
          * Invoked when an error condition prevents updated {@link CellInfo} from being fetched
          * and returned from the modem. Callers of requestCellInfoUpdate() should override this
@@ -6258,6 +6327,20 @@
     };
 
     /**
+     * Used for checking if the target SDK version for the current process is S or above.
+     *
+     * <p> Applies to the following methods:
+     * {@link #requestCellInfoUpdate},
+     * {@link #setPreferredOpportunisticDataSubscription},
+     * {@link #updateAvailableNetworks},
+     * requestNumberVerification(),
+     * setSimPowerStateForSlot(),
+     */
+    @ChangeId
+    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.R)
+    private static final long NULL_TELEPHONY_THROW_NO_CB = 182185642L;
+
+    /**
      * Requests all available cell information from the current subscription for observed
      * camped/registered, serving, and neighboring cells.
      *
@@ -6277,7 +6360,14 @@
             @NonNull @CallbackExecutor Executor executor, @NonNull CellInfoCallback callback) {
         try {
             ITelephony telephony = getITelephony();
-            if (telephony == null) return;
+            if (telephony == null) {
+                if (Compatibility.isChangeEnabled(NULL_TELEPHONY_THROW_NO_CB)) {
+                    throw new IllegalStateException("Telephony is null");
+                } else {
+                    return;
+                }
+            }
+
             telephony.requestCellInfoUpdate(
                     getSubId(),
                     new ICellInfoCallback.Stub() {
@@ -6304,6 +6394,8 @@
                         }
                     }, getOpPackageName(), getAttributionTag());
         } catch (RemoteException ex) {
+            runOnBackgroundThread(() -> executor.execute(
+                    () -> callback.onError(CellInfoCallback.ERROR_MODEM_ERROR, ex)));
         }
     }
 
@@ -6331,7 +6423,14 @@
             @NonNull @CallbackExecutor Executor executor, @NonNull CellInfoCallback callback) {
         try {
             ITelephony telephony = getITelephony();
-            if (telephony == null) return;
+            if (telephony == null) {
+                if (Compatibility.isChangeEnabled(NULL_TELEPHONY_THROW_NO_CB)) {
+                    throw new IllegalStateException("Telephony is null");
+                } else {
+                    return;
+                }
+            }
+
             telephony.requestCellInfoUpdateWithWorkSource(
                     getSubId(),
                     new ICellInfoCallback.Stub() {
@@ -6359,6 +6458,8 @@
                         }
                     }, getOpPackageName(), getAttributionTag(), workSource);
         } catch (RemoteException ex) {
+            runOnBackgroundThread(() -> executor.execute(
+                    () -> callback.onError(CellInfoCallback.ERROR_MODEM_ERROR, ex)));
         }
     }
 
@@ -7325,14 +7426,21 @@
 
         try {
             ITelephony telephony = getITelephony();
-            if (telephony != null) {
-                telephony.requestNumberVerification(range, timeoutMillis, internalCallback,
-                        getOpPackageName());
+            if (telephony == null) {
+                if (Compatibility.isChangeEnabled(NULL_TELEPHONY_THROW_NO_CB)) {
+                    throw new IllegalStateException("Telephony is null");
+                } else {
+                    return;
+                }
             }
+
+            telephony.requestNumberVerification(range, timeoutMillis, internalCallback,
+                    getOpPackageName());
         } catch (RemoteException ex) {
             Rlog.e(TAG, "requestNumberVerification RemoteException", ex);
-            executor.execute(() ->
-                    callback.onVerificationFailed(NumberVerificationCallback.REASON_UNSPECIFIED));
+            runOnBackgroundThread(() -> executor.execute(
+                    () -> callback.onVerificationFailed(
+                            NumberVerificationCallback.REASON_UNSPECIFIED)));
         }
     }
 
@@ -10701,6 +10809,8 @@
         }
         try {
             ITelephony telephony = getITelephony();
+            if (telephony == null) throw new IllegalStateException("Telephony is null.");
+
             IIntegerConsumer internalCallback = new IIntegerConsumer.Stub() {
                 @Override
                 public void accept(int result) {
@@ -10708,11 +10818,18 @@
                             Binder.withCleanCallingIdentity(() -> callback.accept(result)));
                 }
             };
-            if (telephony != null) {
-                telephony.setSimPowerStateForSlotWithCallback(slotIndex, state, internalCallback);
+            if (telephony == null) {
+                if (Compatibility.isChangeEnabled(NULL_TELEPHONY_THROW_NO_CB)) {
+                    throw new IllegalStateException("Telephony is null");
+                } else {
+                    return;
+                }
             }
+            telephony.setSimPowerStateForSlotWithCallback(slotIndex, state, internalCallback);
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling ITelephony#setSimPowerStateForSlot", e);
+            runOnBackgroundThread(() -> executor.execute(
+                    () -> callback.accept(SET_SIM_POWER_STATE_MODEM_ERROR)));
         } catch (SecurityException e) {
             Log.e(TAG, "Permission error calling ITelephony#setSimPowerStateForSlot",
                     e);
@@ -13285,22 +13402,12 @@
         try {
             IOns iOpportunisticNetworkService = getIOns();
             if (iOpportunisticNetworkService == null) {
-                if (executor == null || callback == null) {
-                    return;
+                if (Compatibility.isChangeEnabled(NULL_TELEPHONY_THROW_NO_CB)) {
+                    throw new IllegalStateException("Opportunistic Network Service is null");
+                } else {
+                    // Let the general remote exception handling catch this.
+                    throw new RemoteException("Null Opportunistic Network Service!");
                 }
-                final long identity = Binder.clearCallingIdentity();
-                try {
-                    executor.execute(() -> {
-                        if (Compatibility.isChangeEnabled(CALLBACK_ON_MORE_ERROR_CODE_CHANGE)) {
-                            callback.accept(SET_OPPORTUNISTIC_SUB_REMOTE_SERVICE_EXCEPTION);
-                        } else {
-                            callback.accept(SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION);
-                        }
-                    });
-                } finally {
-                    Binder.restoreCallingIdentity(identity);
-                }
-                return;
             }
             ISetOpportunisticDataCallback callbackStub = new ISetOpportunisticDataCallback.Stub() {
                 @Override
@@ -13323,9 +13430,18 @@
                     .setPreferredDataSubscriptionId(subId, needValidation, callbackStub,
                             pkgForDebug);
         } catch (RemoteException ex) {
-            Rlog.e(TAG, "setPreferredDataSubscriptionId RemoteException", ex);
+            Rlog.e(TAG, "setPreferredOpportunisticDataSubscription RemoteException", ex);
+            if (executor == null || callback == null) {
+                return;
+            }
+            runOnBackgroundThread(() -> executor.execute(() -> {
+                if (Compatibility.isChangeEnabled(CALLBACK_ON_MORE_ERROR_CODE_CHANGE)) {
+                    callback.accept(SET_OPPORTUNISTIC_SUB_REMOTE_SERVICE_EXCEPTION);
+                } else {
+                    callback.accept(SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION);
+                }
+            }));
         }
-        return;
     }
 
     /**
@@ -13382,37 +13498,18 @@
             @Nullable @CallbackExecutor Executor executor,
             @UpdateAvailableNetworksResult @Nullable Consumer<Integer> callback) {
         String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+        Objects.requireNonNull(availableNetworks, "availableNetworks must not be null.");
         try {
             IOns iOpportunisticNetworkService = getIOns();
-            if (iOpportunisticNetworkService == null || availableNetworks == null) {
-                if (executor == null || callback == null) {
-                    return;
-                }
-                if (iOpportunisticNetworkService == null) {
-                    final long identity = Binder.clearCallingIdentity();
-                    try {
-                        executor.execute(() -> {
-                            if (Compatibility.isChangeEnabled(CALLBACK_ON_MORE_ERROR_CODE_CHANGE)) {
-                                callback.accept(UPDATE_AVAILABLE_NETWORKS_REMOTE_SERVICE_EXCEPTION);
-                            } else {
-                                callback.accept(UPDATE_AVAILABLE_NETWORKS_UNKNOWN_FAILURE);
-                            }
-                        });
-                    } finally {
-                        Binder.restoreCallingIdentity(identity);
-                    }
+            if (iOpportunisticNetworkService == null) {
+                if (Compatibility.isChangeEnabled(NULL_TELEPHONY_THROW_NO_CB)) {
+                    throw new IllegalStateException("Opportunistic Network Service is null");
                 } else {
-                    final long identity = Binder.clearCallingIdentity();
-                    try {
-                        executor.execute(() -> {
-                            callback.accept(UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS);
-                        });
-                    } finally {
-                        Binder.restoreCallingIdentity(identity);
-                    }
+                    // Let the general remote exception handling catch this.
+                    throw new RemoteException("Null Opportunistic Network Service!");
                 }
-                return;
             }
+
             IUpdateAvailableNetworksCallback callbackStub =
                     new IUpdateAvailableNetworksCallback.Stub() {
                         @Override
@@ -13420,20 +13517,25 @@
                             if (executor == null || callback == null) {
                                 return;
                             }
-                            final long identity = Binder.clearCallingIdentity();
-                            try {
-                                executor.execute(() -> {
-                                    callback.accept(result);
-                                });
-                            } finally {
-                                Binder.restoreCallingIdentity(identity);
-                            }
+                            Binder.withCleanCallingIdentity(() -> {
+                                executor.execute(() -> callback.accept(result));
+                            });
                         }
                     };
-            iOpportunisticNetworkService.updateAvailableNetworks(availableNetworks, callbackStub,
-                    pkgForDebug);
+            iOpportunisticNetworkService
+                    .updateAvailableNetworks(availableNetworks, callbackStub, pkgForDebug);
         } catch (RemoteException ex) {
             Rlog.e(TAG, "updateAvailableNetworks RemoteException", ex);
+            if (executor == null || callback == null) {
+                return;
+            }
+            runOnBackgroundThread(() -> executor.execute(() -> {
+                if (Compatibility.isChangeEnabled(CALLBACK_ON_MORE_ERROR_CODE_CHANGE)) {
+                    callback.accept(UPDATE_AVAILABLE_NETWORKS_REMOTE_SERVICE_EXCEPTION);
+                } else {
+                    callback.accept(UPDATE_AVAILABLE_NETWORKS_UNKNOWN_FAILURE);
+                }
+            }));
         }
     }
 
diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java
index 6315b24..b384e50 100644
--- a/telephony/java/android/telephony/ims/feature/RcsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java
@@ -391,6 +391,7 @@
      * event to the framework.
      * @return An instance of {@link RcsCapabilityExchangeImplBase} that implements capability
      * exchange if it is supported by the device.
+     * @hide
      */
     public @NonNull RcsCapabilityExchangeImplBase createCapabilityExchangeImpl(
             @NonNull Executor executor, @NonNull CapabilityExchangeEventListener listener) {
@@ -399,14 +400,45 @@
     }
 
     /**
+     * Retrieve the implementation of UCE for this {@link RcsFeature}, which can use either
+     * presence or OPTIONS for capability exchange.
+     *
+     * Will only be requested by the framework if capability exchange is configured
+     * as capable during a
+     * {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)}
+     * operation and the RcsFeature sets the status of the capability to true using
+     * {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)}.
+     *
+     * @param listener A {@link CapabilityExchangeEventListener} to send the capability exchange
+     * event to the framework.
+     * @return An instance of {@link RcsCapabilityExchangeImplBase} that implements capability
+     * exchange if it is supported by the device.
+     */
+    public @NonNull RcsCapabilityExchangeImplBase createCapabilityExchangeImpl(
+            @NonNull CapabilityExchangeEventListener listener) {
+        // Base Implementation, override to implement functionality
+        return new RcsCapabilityExchangeImplBase();
+    }
+
+    /**
      * Remove the given CapabilityExchangeImplBase instance.
      * @param capExchangeImpl The {@link RcsCapabilityExchangeImplBase} instance to be removed.
+     * @hide
      */
     public void removeCapabilityExchangeImpl(
             @NonNull RcsCapabilityExchangeImplBase capExchangeImpl) {
         // Override to implement the process of removing RcsCapabilityExchangeImplBase instance.
     }
 
+    /**
+     * Remove the given CapabilityExchangeImplBase instance.
+     * @param capExchangeImpl The {@link RcsCapabilityExchangeImplBase} instance to be destroyed.
+     */
+    public void destroyCapabilityExchangeImpl(
+            @NonNull RcsCapabilityExchangeImplBase capExchangeImpl) {
+        // Override to implement the process of destroying RcsCapabilityExchangeImplBase instance.
+    }
+
     /**{@inheritDoc}*/
     @Override
     public void onFeatureRemoved() {
diff --git a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java
index 25b9446..a117adc 100644
--- a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java
@@ -356,12 +356,13 @@
         void onTerminated(@NonNull String reason, long retryAfterMilliseconds) throws ImsException;
     }
 
-    private final Executor mBinderExecutor;
+    private Executor mBinderExecutor;
 
     /**
      * Create a new RcsCapabilityExchangeImplBase instance.
      *
      * @param executor The executor that remote calls from the framework will be called on.
+     * @hide
      */
     public RcsCapabilityExchangeImplBase(@NonNull Executor executor) {
         if (executor == null) {
@@ -371,6 +372,12 @@
     }
 
     /**
+     * Create a new RcsCapabilityExchangeImplBase instance.
+     */
+    public RcsCapabilityExchangeImplBase() {
+    }
+
+    /**
      * The user capabilities of one or multiple contacts have been requested by the framework.
      * <p>
      * The implementer must follow up this call with an
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 46752b7..afc538d 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -298,9 +298,9 @@
     int getCallState();
 
     /**
-     * Returns the call state for a slot.
+     * Returns the call state for a specific subscriiption.
      */
-    int getCallStateForSlot(int slotIndex);
+    int getCallStateForSubscription(int subId, String callingPackage, String featureId);
 
     /**
      * Replaced by getDataActivityForSubId.
diff --git a/test-mock/src/android/test/mock/MockContentProvider.java b/test-mock/src/android/test/mock/MockContentProvider.java
index 5b9f67e..7be42f4 100644
--- a/test-mock/src/android/test/mock/MockContentProvider.java
+++ b/test-mock/src/android/test/mock/MockContentProvider.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.AttributionSource;
 import android.content.ContentProvider;
 import android.content.ContentProviderOperation;
 import android.content.ContentProviderResult;
@@ -60,21 +61,20 @@
      */
     private class InversionIContentProvider implements IContentProvider {
         @Override
-        public ContentProviderResult[] applyBatch(String callingPackage,
-                @Nullable String featureId, String authority,
-                ArrayList<ContentProviderOperation> operations)
+        public ContentProviderResult[] applyBatch(@NonNull AttributionSource attributionSource,
+                String authority, ArrayList<ContentProviderOperation> operations)
                 throws RemoteException, OperationApplicationException {
             return MockContentProvider.this.applyBatch(authority, operations);
         }
 
         @Override
-        public int bulkInsert(String callingPackage, @Nullable String featureId, Uri url,
+        public int bulkInsert(@NonNull AttributionSource attributionSource, Uri url,
                 ContentValues[] initialValues) throws RemoteException {
             return MockContentProvider.this.bulkInsert(url, initialValues);
         }
 
         @Override
-        public int delete(String callingPackage, @Nullable String featureId, Uri url,
+        public int delete(@NonNull AttributionSource attributionSource, Uri url,
                 Bundle extras) throws RemoteException {
             return MockContentProvider.this.delete(url, extras);
         }
@@ -90,40 +90,40 @@
         }
 
         @Override
-        public Uri insert(String callingPackage, @Nullable String featureId, Uri url,
+        public Uri insert(@NonNull AttributionSource attributionSource, Uri url,
                 ContentValues initialValues, Bundle extras) throws RemoteException {
             return MockContentProvider.this.insert(url, initialValues, extras);
         }
 
         @Override
-        public AssetFileDescriptor openAssetFile(String callingPackage,
-                @Nullable String featureId, Uri url, String mode, ICancellationSignal signal)
+        public AssetFileDescriptor openAssetFile(@NonNull AttributionSource attributionSource,
+                Uri url, String mode, ICancellationSignal signal)
                 throws RemoteException, FileNotFoundException {
             return MockContentProvider.this.openAssetFile(url, mode);
         }
 
         @Override
-        public ParcelFileDescriptor openFile(String callingPackage, @Nullable String featureId,
-                Uri url, String mode, ICancellationSignal signal, IBinder callerToken)
+        public ParcelFileDescriptor openFile(@NonNull AttributionSource attributionSource,
+                Uri url, String mode, ICancellationSignal signal)
                 throws RemoteException, FileNotFoundException {
             return MockContentProvider.this.openFile(url, mode);
         }
 
         @Override
-        public Cursor query(String callingPackage, @Nullable String featureId, Uri url,
+        public Cursor query(@NonNull AttributionSource attributionSource, Uri url,
                 @Nullable String[] projection, @Nullable Bundle queryArgs,
                 @Nullable ICancellationSignal cancellationSignal) throws RemoteException {
             return MockContentProvider.this.query(url, projection, queryArgs, null);
         }
 
         @Override
-        public int update(String callingPackage, @Nullable String featureId, Uri url,
+        public int update(@NonNull AttributionSource attributionSource, Uri url,
                 ContentValues values, Bundle extras) throws RemoteException {
             return MockContentProvider.this.update(url, values, extras);
         }
 
         @Override
-        public Bundle call(String callingPackage, @Nullable String featureId, String authority,
+        public Bundle call(@NonNull AttributionSource attributionSource, String authority,
                 String method, String request, Bundle args) throws RemoteException {
             return MockContentProvider.this.call(authority, method, request, args);
         }
@@ -139,9 +139,10 @@
         }
 
         @Override
-        public AssetFileDescriptor openTypedAssetFile(String callingPackage,
-                @Nullable String featureId, Uri url, String mimeType, Bundle opts,
-                ICancellationSignal signal) throws RemoteException, FileNotFoundException {
+        public AssetFileDescriptor openTypedAssetFile(
+                @NonNull AttributionSource attributionSource, Uri url, String mimeType,
+                Bundle opts, ICancellationSignal signal)
+                throws RemoteException, FileNotFoundException {
             return MockContentProvider.this.openTypedAssetFile(url, mimeType, opts);
         }
 
@@ -151,37 +152,37 @@
         }
 
         @Override
-        public Uri canonicalize(String callingPkg, @Nullable String featureId, Uri uri)
+        public Uri canonicalize(@NonNull AttributionSource attributionSource, Uri uri)
                 throws RemoteException {
             return MockContentProvider.this.canonicalize(uri);
         }
 
         @Override
-        public void canonicalizeAsync(String callingPkg, String featureId, Uri uri,
+        public void canonicalizeAsync(@NonNull AttributionSource attributionSource, Uri uri,
                 RemoteCallback callback) {
             MockContentProvider.this.canonicalizeAsync(uri, callback);
         }
 
         @Override
-        public Uri uncanonicalize(String callingPkg, @Nullable String featureId, Uri uri)
+        public Uri uncanonicalize(@NonNull AttributionSource attributionSource, Uri uri)
                 throws RemoteException {
             return MockContentProvider.this.uncanonicalize(uri);
         }
 
         @Override
-        public void uncanonicalizeAsync(String callingPkg, String featureId, Uri uri,
+        public void uncanonicalizeAsync(@NonNull AttributionSource attributionSource, Uri uri,
                 RemoteCallback callback) {
             MockContentProvider.this.uncanonicalizeAsync(uri, callback);
         }
 
         @Override
-        public boolean refresh(String callingPkg, @Nullable String featureId, Uri url,
+        public boolean refresh(@NonNull AttributionSource attributionSource, Uri url,
                 Bundle args, ICancellationSignal cancellationSignal) throws RemoteException {
             return MockContentProvider.this.refresh(url, args);
         }
 
         @Override
-        public int checkUriPermission(String callingPkg, @Nullable String featureId, Uri uri,
+        public int checkUriPermission(@NonNull AttributionSource attributionSource, Uri uri,
                 int uid, int modeFlags) {
             return MockContentProvider.this.checkUriPermission(uri, uid, modeFlags);
         }
diff --git a/test-mock/src/android/test/mock/MockIContentProvider.java b/test-mock/src/android/test/mock/MockIContentProvider.java
index 82a1cf7..b81c707 100644
--- a/test-mock/src/android/test/mock/MockIContentProvider.java
+++ b/test-mock/src/android/test/mock/MockIContentProvider.java
@@ -16,7 +16,9 @@
 
 package android.test.mock;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.AttributionSource;
 import android.content.ContentProviderOperation;
 import android.content.ContentProviderResult;
 import android.content.ContentResolver;
@@ -46,14 +48,14 @@
  */
 public class MockIContentProvider implements IContentProvider {
     @Override
-    public int bulkInsert(String callingPackage, @Nullable String featureId, Uri url,
+    public int bulkInsert(@NonNull AttributionSource attributionSource, Uri url,
             ContentValues[] initialValues) {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
     @Override
     @SuppressWarnings("unused")
-    public int delete(String callingPackage, @Nullable String featureId, Uri url,
+    public int delete(@NonNull AttributionSource attributionSource, Uri url,
             Bundle extras) throws RemoteException {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
@@ -75,31 +77,31 @@
 
     @Override
     @SuppressWarnings("unused")
-    public Uri insert(String callingPackage, @Nullable String featureId, Uri url,
+    public Uri insert(@NonNull AttributionSource attributionSource, Uri url,
             ContentValues initialValues, Bundle extras) throws RemoteException {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
     @Override
-    public ParcelFileDescriptor openFile(String callingPackage, @Nullable String featureId,
-            Uri url, String mode, ICancellationSignal signal, IBinder callerToken) {
+    public ParcelFileDescriptor openFile(@NonNull AttributionSource attributionSource,
+            Uri url, String mode, ICancellationSignal signal) {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
     @Override
-    public AssetFileDescriptor openAssetFile(String callingPackage, @Nullable String featureId,
+    public AssetFileDescriptor openAssetFile(@NonNull AttributionSource attributionSource,
             Uri uri, String mode, ICancellationSignal signal) {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
     @Override
-    public ContentProviderResult[] applyBatch(String callingPackage, @Nullable String featureId,
+    public ContentProviderResult[] applyBatch(@NonNull AttributionSource attributionSource,
             String authority, ArrayList<ContentProviderOperation> operations) {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
     @Override
-    public Cursor query(String callingPackage, @Nullable String featureId, Uri url,
+    public Cursor query(@NonNull AttributionSource attributionSource, Uri url,
             @Nullable String[] projection, @Nullable Bundle queryArgs,
             @Nullable ICancellationSignal cancellationSignal) {
         throw new UnsupportedOperationException("unimplemented mock method");
@@ -111,13 +113,13 @@
     }
 
     @Override
-    public int update(String callingPackage, @Nullable String featureId, Uri url,
+    public int update(@NonNull AttributionSource attributionSource, Uri url,
             ContentValues values, Bundle extras) throws RemoteException {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
     @Override
-    public Bundle call(String callingPackage, @Nullable String featureId, String authority,
+    public Bundle call(@NonNull AttributionSource attributionSource, String authority,
             String method, String request, Bundle args) throws RemoteException {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
@@ -133,9 +135,9 @@
     }
 
     @Override
-    public AssetFileDescriptor openTypedAssetFile(String callingPackage,
-            @Nullable String featureId, Uri url, String mimeType, Bundle opts,
-            ICancellationSignal signal) throws RemoteException, FileNotFoundException {
+    public AssetFileDescriptor openTypedAssetFile(@NonNull AttributionSource attributionSource,
+            Uri url, String mimeType, Bundle opts, ICancellationSignal signal)
+            throws RemoteException, FileNotFoundException {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
@@ -145,48 +147,48 @@
     }
 
     @Override
-    public Uri canonicalize(String callingPkg, @Nullable String featureId, Uri uri) {
+    public Uri canonicalize(@NonNull AttributionSource attributionSource, Uri uri) {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
     @Override
     @SuppressWarnings("deprecation")
-    public void canonicalizeAsync(String callingPkg, String featureId, Uri uri,
+    public void canonicalizeAsync(@NonNull AttributionSource attributionSource, Uri uri,
             RemoteCallback remoteCallback) {
         AsyncTask.SERIAL_EXECUTOR.execute(() -> {
             final Bundle bundle = new Bundle();
             bundle.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT,
-                    canonicalize(callingPkg, featureId, uri));
+                    canonicalize(attributionSource, uri));
             remoteCallback.sendResult(bundle);
         });
     }
 
     @Override
-    public Uri uncanonicalize(String callingPkg, @Nullable String featureId, Uri uri) {
+    public Uri uncanonicalize(@NonNull AttributionSource attributionSource, Uri uri) {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
     @Override
     @SuppressWarnings("deprecation")
-    public void uncanonicalizeAsync(String callingPkg, String featureId, Uri uri,
+    public void uncanonicalizeAsync(@NonNull AttributionSource attributionSource, Uri uri,
             RemoteCallback remoteCallback) {
         AsyncTask.SERIAL_EXECUTOR.execute(() -> {
             final Bundle bundle = new Bundle();
             bundle.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT,
-                    uncanonicalize(callingPkg, featureId, uri));
+                    uncanonicalize(attributionSource, uri));
             remoteCallback.sendResult(bundle);
         });
     }
 
     @Override
-    public boolean refresh(String callingPkg, @Nullable String featureId, Uri url, Bundle args,
+    public boolean refresh(@NonNull AttributionSource attributionSource, Uri url, Bundle args,
             ICancellationSignal cancellationSignal) throws RemoteException {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
     /** {@hide} */
     @Override
-    public int checkUriPermission(String callingPkg, @Nullable String featureId, Uri uri, int uid,
+    public int checkUriPermission(@NonNull AttributionSource attributionSource, Uri uri, int uid,
             int modeFlags) {
         throw new UnsupportedOperationException("unimplemented mock method call");
     }
diff --git a/tests/net/java/android/net/VpnTransportInfoTest.java b/tests/net/java/android/net/VpnTransportInfoTest.java
index b7a42ec..fee65f0 100644
--- a/tests/net/java/android/net/VpnTransportInfoTest.java
+++ b/tests/net/java/android/net/VpnTransportInfoTest.java
@@ -16,6 +16,9 @@
 
 package android.net;
 
+import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
+import static android.net.NetworkCapabilities.REDACT_NONE;
+
 import static com.android.testutils.ParcelUtils.assertParcelSane;
 
 import static org.junit.Assert.assertEquals;
@@ -33,23 +36,33 @@
 
     @Test
     public void testParceling() {
-        VpnTransportInfo v = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM);
-        assertParcelSane(v, 1 /* fieldCount */);
+        VpnTransportInfo v = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, "12345");
+        assertParcelSane(v, 2 /* fieldCount */);
     }
 
     @Test
     public void testEqualsAndHashCode() {
-        VpnTransportInfo v1 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM);
-        VpnTransportInfo v2 = new VpnTransportInfo(VpnManager.TYPE_VPN_SERVICE);
-        VpnTransportInfo v3 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM);
-        VpnTransportInfo v4 = new VpnTransportInfo(VpnManager.TYPE_VPN_LEGACY);
-        VpnTransportInfo v5 = new VpnTransportInfo(VpnManager.TYPE_VPN_OEM);
+        String session1 = "12345";
+        String session2 = "6789";
+        VpnTransportInfo v11 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, session1);
+        VpnTransportInfo v12 = new VpnTransportInfo(VpnManager.TYPE_VPN_SERVICE, session1);
+        VpnTransportInfo v13 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, session1);
+        VpnTransportInfo v14 = new VpnTransportInfo(VpnManager.TYPE_VPN_LEGACY, session1);
+        VpnTransportInfo v15 = new VpnTransportInfo(VpnManager.TYPE_VPN_OEM, session1);
+        VpnTransportInfo v21 = new VpnTransportInfo(VpnManager.TYPE_VPN_LEGACY, session2);
 
-        assertNotEquals(v1, v2);
-        assertNotEquals(v3, v4);
-        assertNotEquals(v4, v5);
+        VpnTransportInfo v31 = v11.makeCopy(REDACT_FOR_NETWORK_SETTINGS);
+        VpnTransportInfo v32 = v13.makeCopy(REDACT_FOR_NETWORK_SETTINGS);
 
-        assertEquals(v1, v3);
-        assertEquals(v1.hashCode(), v3.hashCode());
+        assertNotEquals(v11, v12);
+        assertNotEquals(v13, v14);
+        assertNotEquals(v14, v15);
+        assertNotEquals(v14, v21);
+
+        assertEquals(v11, v13);
+        assertEquals(v31, v32);
+        assertEquals(v11.hashCode(), v13.hashCode());
+        assertEquals(REDACT_FOR_NETWORK_SETTINGS, v32.getApplicableRedactions());
+        assertEquals(session1, v15.makeCopy(REDACT_NONE).sessionId);
     }
-}
\ No newline at end of file
+}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index e6ff5d8..8254f6b3 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -31,6 +31,7 @@
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN;
 import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_DATA_SAVER;
+import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_MASK;
 import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_USER_RESTRICTED;
 import static android.net.ConnectivityManager.BLOCKED_REASON_BATTERY_SAVER;
 import static android.net.ConnectivityManager.BLOCKED_REASON_NONE;
@@ -716,6 +717,9 @@
         private int mProbesSucceeded;
         private String mNmValidationRedirectUrl = null;
         private boolean mNmProvNotificationRequested = false;
+        private Runnable mCreatedCallback;
+        private Runnable mUnwantedCallback;
+        private Runnable mDisconnectedCallback;
 
         private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
         // Contains the redirectUrl from networkStatus(). Before reading, wait for
@@ -770,6 +774,24 @@
                     mRedirectUrl = redirectUrl;
                     mNetworkStatusReceived.open();
                 }
+
+                @Override
+                public void onNetworkCreated() {
+                    super.onNetworkCreated();
+                    if (mCreatedCallback != null) mCreatedCallback.run();
+                }
+
+                @Override
+                public void onNetworkUnwanted() {
+                    super.onNetworkUnwanted();
+                    if (mUnwantedCallback != null) mUnwantedCallback.run();
+                }
+
+                @Override
+                public void onNetworkDestroyed() {
+                    super.onNetworkDestroyed();
+                    if (mDisconnectedCallback != null) mDisconnectedCallback.run();
+                }
             };
 
             assertEquals(na.getNetwork().netId, nmNetworkCaptor.getValue().netId);
@@ -971,6 +993,18 @@
             p.timestampMillis = DATA_STALL_TIMESTAMP;
             mNmCallbacks.notifyDataStallSuspected(p);
         }
+
+        public void setCreatedCallback(Runnable r) {
+            mCreatedCallback = r;
+        }
+
+        public void setUnwantedCallback(Runnable r) {
+            mUnwantedCallback = r;
+        }
+
+        public void setDisconnectedCallback(Runnable r) {
+            mDisconnectedCallback = r;
+        }
     }
 
     /**
@@ -1181,10 +1215,12 @@
             if (mAgentRegistered) throw new IllegalStateException("already registered");
             updateState(NetworkInfo.DetailedState.CONNECTING, "registerAgent");
             mConfig = new VpnConfig();
+            mConfig.session = "MySession12345";
             setUids(uids);
             if (!isAlwaysMetered) mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
             mInterface = VPN_IFNAME;
-            mNetworkCapabilities.setTransportInfo(new VpnTransportInfo(getActiveVpnType()));
+            mNetworkCapabilities.setTransportInfo(new VpnTransportInfo(getActiveVpnType(),
+                    mConfig.session));
             mMockNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp,
                     mNetworkCapabilities);
             mMockNetworkAgent.waitForIdle(TIMEOUT_MS);
@@ -1361,10 +1397,21 @@
     }
 
     private void mockUidNetworkingBlocked() {
-        doAnswer(i -> NetworkPolicyManager.isUidBlocked(mBlockedReasons, i.getArgument(1))
+        doAnswer(i -> isUidBlocked(mBlockedReasons, i.getArgument(1))
         ).when(mNetworkPolicyManager).isUidNetworkingBlocked(anyInt(), anyBoolean());
     }
 
+    private boolean isUidBlocked(int blockedReasons, boolean meteredNetwork) {
+        final int blockedOnAllNetworksReason = (blockedReasons & ~BLOCKED_METERED_REASON_MASK);
+        if (blockedOnAllNetworksReason != BLOCKED_REASON_NONE) {
+            return true;
+        }
+        if (meteredNetwork) {
+            return blockedReasons != BLOCKED_REASON_NONE;
+        }
+        return false;
+    }
+
     private void setBlockedReasonChanged(int blockedReasons) {
         mBlockedReasons = blockedReasons;
         mPolicyCallback.onUidBlockedReasonChanged(Process.myUid(), blockedReasons);
@@ -2788,6 +2835,94 @@
     }
 
     @Test
+    public void testNetworkAgentCallbacks() throws Exception {
+        // Keeps track of the order of events that happen in this test.
+        final LinkedBlockingQueue<String> eventOrder = new LinkedBlockingQueue<>();
+
+        final NetworkRequest request = new NetworkRequest.Builder()
+                .addTransportType(TRANSPORT_WIFI).build();
+        final TestNetworkCallback callback = new TestNetworkCallback();
+        final AtomicReference<Network> wifiNetwork = new AtomicReference<>();
+        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+
+        // Expectations for state when various callbacks fire. These expectations run on the handler
+        // thread and not on the test thread because they need to prevent the handler thread from
+        // advancing while they examine state.
+
+        // 1. When onCreated fires, netd has been told to create the network.
+        mWiFiNetworkAgent.setCreatedCallback(() -> {
+            eventOrder.offer("onNetworkCreated");
+            wifiNetwork.set(mWiFiNetworkAgent.getNetwork());
+            assertNotNull(wifiNetwork.get());
+            try {
+                verify(mMockNetd).networkCreatePhysical(wifiNetwork.get().getNetId(),
+                        INetd.PERMISSION_NONE);
+            } catch (RemoteException impossible) {
+                fail();
+            }
+        });
+
+        // 2. onNetworkUnwanted isn't precisely ordered with respect to any particular events. Just
+        //    check that it is fired at some point after disconnect.
+        mWiFiNetworkAgent.setUnwantedCallback(() -> eventOrder.offer("onNetworkUnwanted"));
+
+        // 3. While the teardown timer is running, connectivity APIs report the network is gone, but
+        //    netd has not yet been told to destroy it.
+        final Runnable duringTeardown = () -> {
+            eventOrder.offer("timePasses");
+            assertNull(mCm.getLinkProperties(wifiNetwork.get()));
+            try {
+                verify(mMockNetd, never()).networkDestroy(wifiNetwork.get().getNetId());
+            } catch (RemoteException impossible) {
+                fail();
+            }
+        };
+
+        // 4. After onNetworkDisconnected is called, connectivity APIs report the network is gone,
+        // and netd has been told to destroy it.
+        mWiFiNetworkAgent.setDisconnectedCallback(() -> {
+            eventOrder.offer("onNetworkDisconnected");
+            assertNull(mCm.getLinkProperties(wifiNetwork.get()));
+            try {
+                verify(mMockNetd).networkDestroy(wifiNetwork.get().getNetId());
+            } catch (RemoteException impossible) {
+                fail();
+            }
+        });
+
+        // Connect a network, and file a request for it after it has come up, to ensure the nascent
+        // timer is cleared and the test does not have to wait for it. Filing the request after the
+        // network has come up is necessary because ConnectivityService does not appear to clear the
+        // nascent timer if the first request satisfied by the network was filed before the network
+        // connected.
+        // TODO: fix this bug, file the request before connecting, and remove the waitForIdle.
+        mWiFiNetworkAgent.connectWithoutInternet();
+        waitForIdle();
+        mCm.requestNetwork(request, callback);
+        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+
+        // Set teardown delay and make sure CS has processed it.
+        mWiFiNetworkAgent.getNetworkAgent().setTeardownDelayMs(300);
+        waitForIdle();
+
+        // Post the duringTeardown lambda to the handler so it fires while teardown is in progress.
+        // The delay must be long enough it will run after the unregisterNetworkCallback has torn
+        // down the network and started the teardown timer, and short enough that the lambda is
+        // scheduled to run before the teardown timer.
+        final Handler h = new Handler(mCsHandlerThread.getLooper());
+        h.postDelayed(duringTeardown, 150);
+
+        // Disconnect the network and check that events happened in the right order.
+        mCm.unregisterNetworkCallback(callback);
+        assertEquals("onNetworkCreated", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertEquals("onNetworkUnwanted", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertEquals("timePasses", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertEquals("onNetworkDisconnected", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+        mCm.unregisterNetworkCallback(callback);
+    }
+
+    @Test
     public void testExplicitlySelected() throws Exception {
         NetworkRequest request = new NetworkRequest.Builder()
                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index 9334e2c..eeeb4fb 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -89,6 +89,7 @@
 import android.net.NetworkStatsHistory;
 import android.net.NetworkTemplate;
 import android.net.UnderlyingNetworkInfo;
+import android.net.TelephonyNetworkSpecifier;
 import android.net.netstats.provider.INetworkStatsProviderCallback;
 import android.os.ConditionVariable;
 import android.os.Handler;
@@ -1280,6 +1281,77 @@
     }
 
     @Test
+    public void testDualVilteProviderStats() throws Exception {
+        // Pretend that network comes online.
+        expectDefaultSettings();
+        final int subId1 = 1;
+        final int subId2 = 2;
+        final NetworkStateSnapshot[] states = new NetworkStateSnapshot[]{
+                buildImsState(IMSI_1, subId1, TEST_IFACE),
+                buildImsState(IMSI_2, subId2, TEST_IFACE2)};
+        expectNetworkStatsSummary(buildEmptyStats());
+        expectNetworkStatsUidDetail(buildEmptyStats());
+
+        // Register custom provider and retrieve callback.
+        final TestableNetworkStatsProviderBinder provider =
+                new TestableNetworkStatsProviderBinder();
+        final INetworkStatsProviderCallback cb =
+                mService.registerNetworkStatsProvider("TEST", provider);
+        assertNotNull(cb);
+
+        mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+                new UnderlyingNetworkInfo[0]);
+
+        // Verifies that one requestStatsUpdate will be called during iface update.
+        provider.expectOnRequestStatsUpdate(0 /* unused */);
+
+        // Create some initial traffic and report to the service.
+        incrementCurrentTime(HOUR_IN_MILLIS);
+        final String vtIface1 = NetworkStats.IFACE_VT + subId1;
+        final String vtIface2 = NetworkStats.IFACE_VT + subId2;
+        final NetworkStats expectedStats = new NetworkStats(0L, 1)
+                .addEntry(new NetworkStats.Entry(vtIface1, UID_RED, SET_DEFAULT,
+                        TAG_NONE, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_YES,
+                        128L, 2L, 128L, 2L, 1L))
+                .addEntry(new NetworkStats.Entry(vtIface2, UID_RED, SET_DEFAULT,
+                        TAG_NONE, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_YES,
+                        64L, 1L, 64L, 1L, 1L));
+        cb.notifyStatsUpdated(0 /* unused */, expectedStats, expectedStats);
+
+        // Make another empty mutable stats object. This is necessary since the new NetworkStats
+        // object will be used to compare with the old one in NetworkStatsRecoder, two of them
+        // cannot be the same object.
+        expectNetworkStatsUidDetail(buildEmptyStats());
+
+        forcePollAndWaitForIdle();
+
+        // Verifies that one requestStatsUpdate and setAlert will be called during polling.
+        provider.expectOnRequestStatsUpdate(0 /* unused */);
+        provider.expectOnSetAlert(MB_IN_BYTES);
+
+        // Verifies that service recorded history, does not verify uid tag part.
+        assertUidTotal(sTemplateImsi1, UID_RED, 128L, 2L, 128L, 2L, 1);
+
+        // Verifies that onStatsUpdated updates the stats accordingly.
+        NetworkStats stats = mSession.getSummaryForAllUid(
+                sTemplateImsi1, Long.MIN_VALUE, Long.MAX_VALUE, true);
+        assertEquals(1, stats.size());
+        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+                DEFAULT_NETWORK_YES, 128L, 2L, 128L, 2L, 1L);
+
+        stats = mSession.getSummaryForAllUid(
+                sTemplateImsi2, Long.MIN_VALUE, Long.MAX_VALUE, true);
+        assertEquals(1, stats.size());
+        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+                DEFAULT_NETWORK_YES, 64L, 1L, 64L, 1L, 1L);
+
+        // Verifies that unregister the callback will remove the provider from service.
+        cb.unregister();
+        forcePollAndWaitForIdle();
+        provider.assertNoCallback();
+    }
+
+    @Test
     public void testStatsProviderSetAlert() throws Exception {
         // Pretend that network comes online.
         expectDefaultSettings();
@@ -1616,6 +1688,20 @@
                 TYPE_MOBILE);
     }
 
+    private static NetworkStateSnapshot buildImsState(
+            String subscriberId, int subId, String ifaceName) {
+        final LinkProperties prop = new LinkProperties();
+        prop.setInterfaceName(ifaceName);
+        final NetworkCapabilities capabilities = new NetworkCapabilities();
+        capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, true);
+        capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true);
+        capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_IMS, true);
+        capabilities.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+        capabilities.setNetworkSpecifier(new TelephonyNetworkSpecifier(subId));
+        return new NetworkStateSnapshot(
+                MOBILE_NETWORK, capabilities, prop, subscriberId, TYPE_MOBILE);
+    }
+
     private long getElapsedRealtime() {
         return mElapsedRealtime;
     }
diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp
index 82da249..351e420 100644
--- a/tools/aapt2/Debug.cpp
+++ b/tools/aapt2/Debug.cpp
@@ -256,53 +256,35 @@
 
 void Debug::PrintTable(const ResourceTable& table, const DebugPrintTableOptions& options,
                        Printer* printer) {
-  for (const auto& package : table.packages) {
-    ValueHeadlinePrinter headline_printer(package->name, printer);
-    ValueBodyPrinter body_printer(package->name, printer);
+  const auto table_view = table.GetPartitionedView();
+  for (const auto& package : table_view.packages) {
+    ValueHeadlinePrinter headline_printer(package.name, printer);
+    ValueBodyPrinter body_printer(package.name, printer);
 
     printer->Print("Package name=");
-    printer->Print(package->name);
-    if (package->id) {
-      printer->Print(StringPrintf(" id=%02x", package->id.value()));
+    printer->Print(package.name);
+    if (package.id) {
+      printer->Print(StringPrintf(" id=%02x", package.id.value()));
     }
     printer->Println();
 
     printer->Indent();
-    for (const auto& type : package->types) {
+    for (const auto& type : package.types) {
       printer->Print("type ");
-      printer->Print(to_string(type->type));
-      if (type->id) {
-        printer->Print(StringPrintf(" id=%02x", type->id.value()));
+      printer->Print(to_string(type.type));
+      if (type.id) {
+        printer->Print(StringPrintf(" id=%02x", type.id.value()));
       }
-      printer->Println(StringPrintf(" entryCount=%zd", type->entries.size()));
-
-      std::vector<const ResourceEntry*> sorted_entries;
-      for (const auto& entry : type->entries) {
-        auto iter = std::lower_bound(
-            sorted_entries.begin(), sorted_entries.end(), entry.get(),
-            [](const ResourceEntry* a, const ResourceEntry* b) -> bool {
-              if (a->id && b->id) {
-                return a->id.value() < b->id.value();
-              } else if (a->id) {
-                return true;
-              } else {
-                return false;
-              }
-            });
-        sorted_entries.insert(iter, entry.get());
-      }
+      printer->Println(StringPrintf(" entryCount=%zd", type.entries.size()));
 
       printer->Indent();
-      for (const ResourceEntry* entry : sorted_entries) {
-        const ResourceId id(package->id.value_or_default(0), type->id.value_or_default(0),
-                            entry->id.value_or_default(0));
-
+      for (const ResourceEntry* entry : type.entries) {
         printer->Print("resource ");
-        printer->Print(id.to_string());
+        printer->Print(entry->id.value_or_default(0).to_string());
         printer->Print(" ");
 
         // Write the name without the package (this is obvious and too verbose).
-        printer->Print(to_string(type->type));
+        printer->Print(to_string(type.type));
         printer->Print("/");
         printer->Print(entry->name);
 
diff --git a/tools/aapt2/LoadedApk.cpp b/tools/aapt2/LoadedApk.cpp
index e930b47..830bc5f 100644
--- a/tools/aapt2/LoadedApk.cpp
+++ b/tools/aapt2/LoadedApk.cpp
@@ -113,7 +113,7 @@
     }
 
     std::string error;
-    table = util::make_unique<ResourceTable>(/** validate_resources **/ false);
+    table = util::make_unique<ResourceTable>(ResourceTable::Validation::kDisabled);
     if (!DeserializeTableFromPb(pb_table, collection.get(), table.get(), &error)) {
       diag->Error(DiagMessage(source)
                   << "failed to deserialize " << kProtoResourceTablePath << ": " << error);
@@ -157,7 +157,7 @@
 
   io::IFile* table_file = collection->FindFile(kApkResourceTablePath);
   if (table_file != nullptr) {
-    table = util::make_unique<ResourceTable>(/** validate_resources **/ false);
+    table = util::make_unique<ResourceTable>(ResourceTable::Validation::kDisabled);
     std::unique_ptr<io::IData> data = table_file->OpenAsData();
     if (data == nullptr) {
       diag->Error(DiagMessage(source) << "failed to open " << kApkResourceTablePath);
diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h
index 8fe0eb3..cf93870 100644
--- a/tools/aapt2/Resource.h
+++ b/tools/aapt2/Resource.h
@@ -138,7 +138,7 @@
   uint32_t id;
 
   ResourceId();
-  ResourceId(const ResourceId& rhs);
+  ResourceId(const ResourceId& rhs) = default;
   ResourceId(uint32_t res_id);  // NOLINT(google-explicit-constructor)
   ResourceId(uint8_t p, uint8_t t, uint16_t e);
 
@@ -222,8 +222,6 @@
 
 inline ResourceId::ResourceId() : id(0) {}
 
-inline ResourceId::ResourceId(const ResourceId& rhs) : id(rhs.id) {}
-
 inline ResourceId::ResourceId(uint32_t res_id) : id(res_id) {}
 
 inline ResourceId::ResourceId(uint8_t p, uint8_t t, uint16_t e)
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 3d9be59..a447cef 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -118,43 +118,43 @@
     res->comment = trimmed_comment.to_string();
   }
 
+  NewResourceBuilder res_builder(res->name);
   if (res->visibility_level != Visibility::Level::kUndefined) {
     Visibility visibility;
     visibility.level = res->visibility_level;
     visibility.source = res->source;
     visibility.comment = res->comment;
-    if (!table->SetVisibilityWithId(res->name, visibility, res->id, diag)) {
-      return false;
-    }
+    res_builder.SetVisibility(visibility);
+  }
+
+  if (res->id.is_valid()) {
+    res_builder.SetId(res->id);
   }
 
   if (res->allow_new) {
     AllowNew allow_new;
     allow_new.source = res->source;
     allow_new.comment = res->comment;
-    if (!table->SetAllowNew(res->name, allow_new, diag)) {
-      return false;
-    }
+    res_builder.SetAllowNew(allow_new);
   }
 
   if (res->overlayable_item) {
-    if (!table->SetOverlayable(res->name, res->overlayable_item.value(), diag)) {
-      return false;
-    }
+    res_builder.SetOverlayable(res->overlayable_item.value());
   }
 
   if (res->value != nullptr) {
     // Attach the comment, source and config to the value.
     res->value->SetComment(std::move(res->comment));
     res->value->SetSource(std::move(res->source));
-
-    if (!table->AddResourceWithId(res->name, res->id, res->config, res->product,
-                                  std::move(res->value), diag)) {
-      return false;
-    }
+    res_builder.SetValue(std::move(res->value), res->config, res->product);
   }
 
   bool error = false;
+  if (!res->name.entry.empty()) {
+    if (!table->AddResource(res_builder.Build(), diag)) {
+      return false;
+    }
+  }
   for (ParsedResource& child : res->child_resources) {
     error |= !AddResourcesToTable(table, diag, &child);
   }
@@ -751,7 +751,7 @@
     // table.
     std::unique_ptr<Id> id = util::make_unique<Id>();
     id->SetSource(source_.WithLine(begin_xml_line));
-    table_->AddResource(name, {}, {}, std::move(id), diag_);
+    table_->AddResource(NewResourceBuilder(name).SetValue(std::move(id)).Build(), diag_);
   };
 
   // Process the raw value.
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index 9b70079..53bfa0b 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -831,25 +831,13 @@
 
   Maybe<ResourceTable::SearchResult> result = table_.FindResource(test::ParseNameOrDie("attr/foo"));
   ASSERT_TRUE(result);
-
-  ASSERT_TRUE(result.value().package->id);
-  ASSERT_TRUE(result.value().type->id);
   ASSERT_TRUE(result.value().entry->id);
-  ResourceId actual_id(result.value().package->id.value(),
-                       result.value().type->id.value(),
-                       result.value().entry->id.value());
-  EXPECT_THAT(actual_id, Eq(ResourceId(0x01010040)));
+  EXPECT_THAT(result.value().entry->id.value(), Eq(ResourceId(0x01010040)));
 
   result = table_.FindResource(test::ParseNameOrDie("attr/bar"));
   ASSERT_TRUE(result);
-
-  ASSERT_TRUE(result.value().package->id);
-  ASSERT_TRUE(result.value().type->id);
   ASSERT_TRUE(result.value().entry->id);
-  actual_id = ResourceId(result.value().package->id.value(),
-                         result.value().type->id.value(),
-                         result.value().entry->id.value());
-  EXPECT_THAT(actual_id, Eq(ResourceId(0x01010041)));
+  EXPECT_THAT(result.value().entry->id.value(), Eq(ResourceId(0x01010041)));
 }
 
 TEST_F(ResourceParserTest, StrongestSymbolVisibilityWins) {
diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp
index e0a9a31e..cff9872 100644
--- a/tools/aapt2/ResourceTable.cpp
+++ b/tools/aapt2/ResourceTable.cpp
@@ -18,20 +18,18 @@
 
 #include <algorithm>
 #include <memory>
-#include <string>
 #include <tuple>
 
 #include "android-base/logging.h"
-#include "android-base/stringprintf.h"
 #include "androidfw/ConfigDescription.h"
 #include "androidfw/ResourceTypes.h"
 
-#include "Debug.h"
 #include "NameMangler.h"
+#include "ResourceUtils.h"
 #include "ResourceValues.h"
 #include "ValueVisitor.h"
-#include "trace/TraceBuffer.h"
 #include "text/Unicode.h"
+#include "trace/TraceBuffer.h"
 #include "util/Util.h"
 
 using ::aapt::text::IsValidResourceEntryName;
@@ -43,135 +41,108 @@
 
 const char* Overlayable::kActorScheme = "overlay";
 
-static bool less_than_type_and_id(const std::unique_ptr<ResourceTableType>& lhs,
-                                  const std::pair<ResourceType, Maybe<uint8_t>>& rhs) {
-  return lhs->type < rhs.first || (lhs->type == rhs.first && rhs.second && lhs->id < rhs.second);
+namespace {
+bool less_than_type(const std::unique_ptr<ResourceTableType>& lhs, ResourceType rhs) {
+  return lhs->type < rhs;
 }
 
 template <typename T>
-static bool less_than_struct_with_name(const std::unique_ptr<T>& lhs, const StringPiece& rhs) {
+bool less_than_type_and_id(const T& lhs, const std::pair<ResourceType, Maybe<uint8_t>>& rhs) {
+  return lhs.id != rhs.second ? lhs.id < rhs.second : lhs.type < rhs.first;
+}
+
+template <typename T>
+bool less_than_struct_with_name(const std::unique_ptr<T>& lhs, const StringPiece& rhs) {
   return lhs->name.compare(0, lhs->name.size(), rhs.data(), rhs.size()) < 0;
 }
 
 template <typename T>
-static bool less_than_struct_with_name_and_id(const std::unique_ptr<T>& lhs,
-                                              const std::pair<StringPiece, Maybe<uint16_t>>& rhs) {
-  int name_cmp = lhs->name.compare(0, lhs->name.size(), rhs.first.data(), rhs.first.size());
-  return name_cmp < 0 || (name_cmp == 0 && rhs.second && lhs->id < rhs.second);
+bool greater_than_struct_with_name(const StringPiece& lhs, const std::unique_ptr<T>& rhs) {
+  return rhs->name.compare(0, rhs->name.size(), lhs.data(), lhs.size()) > 0;
 }
 
-ResourceTablePackage* ResourceTable::FindPackage(const StringPiece& name) const {
-  const auto last = packages.end();
-  auto iter = std::lower_bound(packages.begin(), last, name,
-                               less_than_struct_with_name<ResourceTablePackage>);
-  if (iter != last && name == (*iter)->name) {
-    return iter->get();
+template <typename T>
+struct NameEqualRange {
+  bool operator()(const std::unique_ptr<T>& lhs, const StringPiece& rhs) const {
+    return less_than_struct_with_name<T>(lhs, rhs);
   }
-  return nullptr;
+  bool operator()(const StringPiece& lhs, const std::unique_ptr<T>& rhs) const {
+    return greater_than_struct_with_name<T>(lhs, rhs);
+  }
+};
+
+template <typename T, typename U>
+bool less_than_struct_with_name_and_id(const T& lhs,
+                                       const std::pair<std::string_view, Maybe<U>>& rhs) {
+  if (lhs.id != rhs.second) {
+    return lhs.id < rhs.second;
+  }
+  return lhs.name.compare(0, lhs.name.size(), rhs.first.data(), rhs.first.size()) < 0;
 }
 
-ResourceTablePackage* ResourceTable::FindPackageById(uint8_t id) const {
-  for (auto& package : packages) {
-    if (package->id && package->id.value() == id) {
-      return package.get();
-    }
-  }
-  return nullptr;
+template <typename T, typename U>
+bool less_than_struct_with_name_and_id_pointer(const T* lhs,
+                                               const std::pair<std::string_view, Maybe<U>>& rhs) {
+  return less_than_struct_with_name_and_id(*lhs, rhs);
 }
 
-ResourceTablePackage* ResourceTable::CreatePackage(const StringPiece& name, Maybe<uint8_t> id) {
-  TRACE_CALL();
-  ResourceTablePackage* package = FindOrCreatePackage(name);
-  if (id && !package->id) {
-    package->id = id;
-    return package;
-  }
-
-  if (id && package->id && package->id.value() != id.value()) {
-    return nullptr;
-  }
-  return package;
+template <typename T, typename Func, typename Elements>
+T* FindElementsRunAction(const android::StringPiece& name, Elements& entries, Func action) {
+  const auto iter =
+      std::lower_bound(entries.begin(), entries.end(), name, less_than_struct_with_name<T>);
+  const bool found = iter != entries.end() && name == (*iter)->name;
+  return action(found, iter);
 }
 
-ResourceTablePackage* ResourceTable::CreatePackageAllowingDuplicateNames(const StringPiece& name,
-                                                                         const Maybe<uint8_t> id) {
-  const auto last = packages.end();
-  auto iter = std::lower_bound(packages.begin(), last, std::make_pair(name, id),
-                               less_than_struct_with_name_and_id<ResourceTablePackage>);
+}  // namespace
 
-  if (iter != last && name == (*iter)->name && id == (*iter)->id) {
-    return iter->get();
-  }
-
-  std::unique_ptr<ResourceTablePackage> new_package = util::make_unique<ResourceTablePackage>();
-  new_package->name = name.to_string();
-  new_package->id = id;
-  return packages.emplace(iter, std::move(new_package))->get();
+ResourceTable::ResourceTable(ResourceTable::Validation validation) : validation_(validation) {
 }
 
-ResourceTablePackage* ResourceTable::FindOrCreatePackage(const StringPiece& name) {
-  const auto last = packages.end();
-  auto iter = std::lower_bound(packages.begin(), last, name,
-                               less_than_struct_with_name<ResourceTablePackage>);
-  if (iter != last && name == (*iter)->name) {
-    return iter->get();
-  }
-
-  std::unique_ptr<ResourceTablePackage> new_package = util::make_unique<ResourceTablePackage>();
-  new_package->name = name.to_string();
-  return packages.emplace(iter, std::move(new_package))->get();
+ResourceTablePackage* ResourceTable::FindPackage(const android::StringPiece& name) const {
+  return FindElementsRunAction<ResourceTablePackage>(
+      name, packages, [&](bool found, auto& iter) { return found ? iter->get() : nullptr; });
 }
 
-ResourceTableType* ResourceTablePackage::FindType(ResourceType type, const Maybe<uint8_t> id) {
-  const auto last = types.end();
-  auto iter = std::lower_bound(types.begin(), last, std::make_pair(type, id),
-                               less_than_type_and_id);
-  if (iter != last && (*iter)->type == type && (!id || id == (*iter)->id)) {
-    return iter->get();
-  }
-  return nullptr;
+ResourceTablePackage* ResourceTable::FindOrCreatePackage(const android::StringPiece& name) {
+  return FindElementsRunAction<ResourceTablePackage>(name, packages, [&](bool found, auto& iter) {
+    return found ? iter->get() : packages.emplace(iter, new ResourceTablePackage(name))->get();
+  });
 }
 
-ResourceTableType* ResourceTablePackage::FindOrCreateType(ResourceType type,
-                                                          const Maybe<uint8_t> id) {
-  const auto last = types.end();
-  auto iter = std::lower_bound(types.begin(), last, std::make_pair(type, id),
-                               less_than_type_and_id);
-  if (iter != last && (*iter)->type == type && (!id || id == (*iter)->id)) {
-    return iter->get();
-  }
-
-  auto new_type = new ResourceTableType(type);
-  new_type->id = id;
-  return types.emplace(iter, std::move(new_type))->get();
+template <typename Func, typename Elements>
+static ResourceTableType* FindTypeRunAction(ResourceType type, Elements& entries, Func action) {
+  const auto iter = std::lower_bound(entries.begin(), entries.end(), type, less_than_type);
+  const bool found = iter != entries.end() && type == (*iter)->type;
+  return action(found, iter);
 }
 
-ResourceEntry* ResourceTableType::FindEntry(const StringPiece& name, const Maybe<uint16_t> id) {
-  const auto last = entries.end();
-  auto iter = std::lower_bound(entries.begin(), last, std::make_pair(name, id),
-      less_than_struct_with_name_and_id<ResourceEntry>);
-  if (iter != last && name == (*iter)->name && (!id || id == (*iter)->id)) {
-    return iter->get();
-  }
-  return nullptr;
+ResourceTableType* ResourceTablePackage::FindType(ResourceType type) const {
+  return FindTypeRunAction(type, types,
+                           [&](bool found, auto& iter) { return found ? iter->get() : nullptr; });
 }
 
-ResourceEntry* ResourceTableType::FindOrCreateEntry(const StringPiece& name,
-                                                    const Maybe<uint16_t > id) {
-  auto last = entries.end();
-  auto iter = std::lower_bound(entries.begin(), last, std::make_pair(name, id),
-                               less_than_struct_with_name_and_id<ResourceEntry>);
-  if (iter != last && name == (*iter)->name && (!id || id == (*iter)->id)) {
-    return iter->get();
-  }
-
-  auto new_entry = new ResourceEntry(name);
-  new_entry->id = id;
-  return entries.emplace(iter, std::move(new_entry))->get();
+ResourceTableType* ResourceTablePackage::FindOrCreateType(ResourceType type) {
+  return FindTypeRunAction(type, types, [&](bool found, auto& iter) {
+    return found ? iter->get() : types.emplace(iter, new ResourceTableType(type))->get();
+  });
 }
 
-ResourceConfigValue* ResourceEntry::FindValue(const ConfigDescription& config) {
-  return FindValue(config, StringPiece());
+ResourceEntry* ResourceTableType::CreateEntry(const android::StringPiece& name) {
+  return FindElementsRunAction<ResourceEntry>(name, entries, [&](bool found, auto& iter) {
+    return entries.emplace(iter, new ResourceEntry(name))->get();
+  });
+}
+
+ResourceEntry* ResourceTableType::FindEntry(const android::StringPiece& name) const {
+  return FindElementsRunAction<ResourceEntry>(
+      name, entries, [&](bool found, auto& iter) { return found ? iter->get() : nullptr; });
+}
+
+ResourceEntry* ResourceTableType::FindOrCreateEntry(const android::StringPiece& name) {
+  return FindElementsRunAction<ResourceEntry>(name, entries, [&](bool found, auto& iter) {
+    return found ? iter->get() : entries.emplace(iter, new ResourceEntry(name))->get();
+  });
 }
 
 struct ConfigKey {
@@ -188,7 +159,20 @@
 }
 
 ResourceConfigValue* ResourceEntry::FindValue(const ConfigDescription& config,
-                                              const StringPiece& product) {
+                                              android::StringPiece product) {
+  auto iter = std::lower_bound(values.begin(), values.end(), ConfigKey{&config, product},
+                               lt_config_key_ref);
+  if (iter != values.end()) {
+    ResourceConfigValue* value = iter->get();
+    if (value->config == config && StringPiece(value->product) == product) {
+      return value;
+    }
+  }
+  return nullptr;
+}
+
+const ResourceConfigValue* ResourceEntry::FindValue(const android::ConfigDescription& config,
+                                                    android::StringPiece product) const {
   auto iter = std::lower_bound(values.begin(), values.end(), ConfigKey{&config, product},
                                lt_config_key_ref);
   if (iter != values.end()) {
@@ -323,303 +307,174 @@
   return CollisionResult::kConflict;
 }
 
-ResourceTable::CollisionResult ResourceTable::IgnoreCollision(Value* /** existing **/,
-                                                              Value* /** incoming **/) {
-  return CollisionResult::kKeepBoth;
-}
+ResourceTableView ResourceTable::GetPartitionedView() const {
+  ResourceTableView view;
+  for (const auto& package : packages) {
+    for (const auto& type : package->types) {
+      for (const auto& entry : type->entries) {
+        std::pair<std::string_view, Maybe<uint8_t>> package_key(package->name, {});
+        std::pair<std::string_view, Maybe<ResourceId>> entry_key(entry->name, {});
+        std::pair<ResourceType, Maybe<uint8_t>> type_key(type->type, {});
+        if (entry->id) {
+          // If the entry has a defined id, use the id to determine insertion position.
+          package_key.second = entry->id.value().package_id();
+          type_key.second = entry->id.value().type_id();
+          entry_key.second = entry->id.value();
+        }
 
-static StringPiece ResourceNameValidator(const StringPiece& name) {
-  if (!IsValidResourceEntryName(name)) {
-    return name;
-  }
-  return {};
-}
+        auto package_it =
+            std::lower_bound(view.packages.begin(), view.packages.end(), package_key,
+                             less_than_struct_with_name_and_id<ResourceTablePackageView, uint8_t>);
+        if (package_it == view.packages.end() || package_it->name != package_key.first ||
+            package_it->id != package_key.second) {
+          ResourceTablePackageView new_package{std::string(package_key.first), package_key.second};
+          package_it = view.packages.insert(package_it, new_package);
+        }
 
-static StringPiece SkipNameValidator(const StringPiece& /*name*/) {
-  return {};
-}
+        auto type_it = std::lower_bound(package_it->types.begin(), package_it->types.end(),
+                                        type_key, less_than_type_and_id<ResourceTableTypeView>);
+        if (type_it == package_it->types.end() || type_key.first != type_it->type ||
+            type_it->id != type_key.second) {
+          ResourceTableTypeView new_type{type_key.first, type_key.second};
+          type_it = package_it->types.insert(type_it, new_type);
+        }
 
-bool ResourceTable::AddResource(const ResourceNameRef& name,
-                                const ConfigDescription& config,
-                                const StringPiece& product,
-                                std::unique_ptr<Value> value,
-                                IDiagnostics* diag) {
-  return AddResourceImpl(name, ResourceId{}, config, product, std::move(value),
-                         (validate_resources_ ? ResourceNameValidator : SkipNameValidator),
-                         (validate_resources_ ? ResolveValueCollision : IgnoreCollision), diag);
-}
+        if (entry->visibility.level == Visibility::Level::kPublic) {
+          // Only mark the type visibility level as public, it doesn't care about being private.
+          type_it->visibility_level = Visibility::Level::kPublic;
+        }
 
-bool ResourceTable::AddResourceWithId(const ResourceNameRef& name, const ResourceId& res_id,
-                                      const ConfigDescription& config, const StringPiece& product,
-                                      std::unique_ptr<Value> value, IDiagnostics* diag) {
-  return AddResourceImpl(name, res_id, config, product, std::move(value),
-                         (validate_resources_ ? ResourceNameValidator : SkipNameValidator),
-                         (validate_resources_ ? ResolveValueCollision : IgnoreCollision), diag);
-}
-
-bool ResourceTable::AddResourceMangled(const ResourceNameRef& name, const ConfigDescription& config,
-                                       const StringPiece& product, std::unique_ptr<Value> value,
-                                       IDiagnostics* diag) {
-  return AddResourceImpl(name, ResourceId{}, config, product, std::move(value), SkipNameValidator,
-                         (validate_resources_ ? ResolveValueCollision : IgnoreCollision), diag);
-}
-
-bool ResourceTable::AddResourceWithIdMangled(const ResourceNameRef& name, const ResourceId& id,
-                                             const ConfigDescription& config,
-                                             const StringPiece& product,
-                                             std::unique_ptr<Value> value, IDiagnostics* diag) {
-  return AddResourceImpl(name, id, config, product, std::move(value), SkipNameValidator,
-                         (validate_resources_ ? ResolveValueCollision : IgnoreCollision), diag);
-}
-
-bool ResourceTable::ValidateName(NameValidator name_validator, const ResourceNameRef& name,
-                                 const Source& source, IDiagnostics* diag) {
-  const StringPiece bad_char = name_validator(name.entry);
-  if (!bad_char.empty()) {
-    diag->Error(DiagMessage(source) << "resource '" << name << "' has invalid entry name '"
-                                    << name.entry << "'. Invalid character '" << bad_char << "'");
-    return false;
-  }
-  return true;
-}
-
-bool ResourceTable::AddResourceImpl(const ResourceNameRef& name, const ResourceId& res_id,
-                                    const ConfigDescription& config, const StringPiece& product,
-                                    std::unique_ptr<Value> value, NameValidator name_validator,
-                                    const CollisionResolverFunc& conflict_resolver,
-                                    IDiagnostics* diag) {
-  CHECK(value != nullptr);
-  CHECK(diag != nullptr);
-
-  const Source& source = value->GetSource();
-  if (!ValidateName(name_validator, name, source, diag)) {
-    return false;
-  }
-
-  // Check for package names appearing twice with two different package ids
-  ResourceTablePackage* package = FindOrCreatePackage(name.package);
-  if (res_id.is_valid() && package->id && package->id.value() != res_id.package_id()) {
-    diag->Error(DiagMessage(source)
-                    << "trying to add resource '" << name << "' with ID " << res_id
-                    << " but package '" << package->name << "' already has ID "
-                    << StringPrintf("%02x", package->id.value()));
-    return false;
-  }
-
-  // Whether or not to error on duplicate resources
-  bool check_id = validate_resources_ && res_id.is_valid();
-  // Whether or not to create a duplicate resource if the id does not match
-  bool use_id = !validate_resources_ && res_id.is_valid();
-
-  ResourceTableType* type = package->FindOrCreateType(name.type, use_id ? res_id.type_id()
-                                                                        : Maybe<uint8_t>());
-
-  // Check for types appearing twice with two different type ids
-  if (check_id && type->id && type->id.value() != res_id.type_id()) {
-    diag->Error(DiagMessage(source)
-                    << "trying to add resource '" << name << "' with ID " << res_id
-                    << " but type '" << type->type << "' already has ID "
-                    << StringPrintf("%02x", type->id.value()));
-    return false;
-  }
-
-  ResourceEntry* entry = type->FindOrCreateEntry(name.entry, use_id ? res_id.entry_id()
-                                                                    : Maybe<uint16_t>());
-
-  // Check for entries appearing twice with two different entry ids
-  if (check_id && entry->id && entry->id.value() != res_id.entry_id()) {
-    diag->Error(DiagMessage(source)
-                    << "trying to add resource '" << name << "' with ID " << res_id
-                    << " but resource already has ID "
-                    << ResourceId(package->id.value(), type->id.value(), entry->id.value()));
-    return false;
-  }
-
-  ResourceConfigValue* config_value = entry->FindOrCreateValue(config, product);
-  if (!config_value->value) {
-    // Resource does not exist, add it now.
-    config_value->value = std::move(value);
-  } else {
-    switch (conflict_resolver(config_value->value.get(), value.get())) {
-      case CollisionResult::kKeepBoth:
-        // Insert the value ignoring for duplicate configurations
-        entry->values.push_back(util::make_unique<ResourceConfigValue>(config, product));
-        entry->values.back()->value = std::move(value);
-        break;
-
-      case CollisionResult::kTakeNew:
-        // Take the incoming value.
-        config_value->value = std::move(value);
-        break;
-
-      case CollisionResult::kConflict:
-        diag->Error(DiagMessage(source) << "duplicate value for resource '" << name << "' "
-                                        << "with config '" << config << "'");
-        diag->Error(DiagMessage(source) << "resource previously defined here");
-        return false;
-
-      case CollisionResult::kKeepOriginal:
-        break;
+        auto entry_it =
+            std::lower_bound(type_it->entries.begin(), type_it->entries.end(), entry_key,
+                             less_than_struct_with_name_and_id_pointer<ResourceEntry, ResourceId>);
+        type_it->entries.insert(entry_it, entry.get());
+      }
     }
   }
 
-  if (res_id.is_valid()) {
-    package->id = res_id.package_id();
-    type->id = res_id.type_id();
-    entry->id = res_id.entry_id();
-  }
-
-  return true;
+  return view;
 }
 
-bool ResourceTable::GetValidateResources() {
-  return validate_resources_;
-}
+bool ResourceTable::AddResource(NewResource&& res, IDiagnostics* diag) {
+  CHECK(diag != nullptr) << "Diagnostic pointer is null";
 
-bool ResourceTable::SetVisibility(const ResourceNameRef& name, const Visibility& visibility,
-                                  IDiagnostics* diag) {
-  return SetVisibilityImpl(name, visibility, {}, ResourceNameValidator, diag);
-}
-
-bool ResourceTable::SetVisibilityWithId(const ResourceNameRef& name, const Visibility& visibility,
-                                        const ResourceId& res_id, IDiagnostics* diag) {
-  return SetVisibilityImpl(name, visibility, res_id, ResourceNameValidator, diag);
-}
-
-bool ResourceTable::SetVisibilityWithIdMangled(const ResourceNameRef& name,
-                                               const Visibility& visibility,
-                                               const ResourceId& res_id, IDiagnostics* diag) {
-  return SetVisibilityImpl(name, visibility, res_id, SkipNameValidator, diag);
-}
-
-bool ResourceTable::SetVisibilityImpl(const ResourceNameRef& name, const Visibility& visibility,
-                                      const ResourceId& res_id, NameValidator name_validator,
-                                      IDiagnostics* diag) {
-  CHECK(diag != nullptr);
-
-  const Source& source = visibility.source;
-  if (!ValidateName(name_validator, name, source, diag)) {
-    return false;
-  }
-
-  // Check for package names appearing twice with two different package ids
-  ResourceTablePackage* package = FindOrCreatePackage(name.package);
-  if (res_id.is_valid() && package->id && package->id.value() != res_id.package_id()) {
+  const bool validate = validation_ == Validation::kEnabled;
+  const Source source = res.value ? res.value->GetSource() : Source{};
+  if (validate && !res.allow_mangled && !IsValidResourceEntryName(res.name.entry)) {
     diag->Error(DiagMessage(source)
-                    << "trying to add resource '" << name << "' with ID " << res_id
-                    << " but package '" << package->name << "' already has ID "
-                    << StringPrintf("%02x", package->id.value()));
+                << "resource '" << res.name << "' has invalid entry name '" << res.name.entry);
     return false;
   }
 
-  // Whether or not to error on duplicate resources
-  bool check_id = validate_resources_ && res_id.is_valid();
-  // Whether or not to create a duplicate resource if the id does not match
-  bool use_id = !validate_resources_ && res_id.is_valid();
-
-  ResourceTableType* type = package->FindOrCreateType(name.type, use_id ? res_id.type_id()
-                                                                        : Maybe<uint8_t>());
-
-  // Check for types appearing twice with two different type ids
-  if (check_id && type->id && type->id.value() != res_id.type_id()) {
-    diag->Error(DiagMessage(source)
-                    << "trying to add resource '" << name << "' with ID " << res_id
-                    << " but type '" << type->type << "' already has ID "
-                    << StringPrintf("%02x", type->id.value()));
+  if (res.id.has_value() && !res.id->first.is_valid()) {
+    diag->Error(DiagMessage(source) << "trying to add resource '" << res.name << "' with ID "
+                                    << res.id->first << " but that ID is invalid");
     return false;
   }
 
-  ResourceEntry* entry = type->FindOrCreateEntry(name.entry, use_id ? res_id.entry_id()
-                                                                    : Maybe<uint16_t>());
+  auto package = FindOrCreatePackage(res.name.package);
+  auto type = package->FindOrCreateType(res.name.type);
+  auto entry_it = std::equal_range(type->entries.begin(), type->entries.end(), res.name.entry,
+                                   NameEqualRange<ResourceEntry>{});
+  const size_t entry_count = std::distance(entry_it.first, entry_it.second);
 
-  // Check for entries appearing twice with two different entry ids
-  if (check_id && entry->id && entry->id.value() != res_id.entry_id()) {
-    diag->Error(DiagMessage(source)
-                    << "trying to add resource '" << name << "' with ID " << res_id
-                    << " but resource already has ID "
-                    << ResourceId(package->id.value(), type->id.value(), entry->id.value()));
-    return false;
+  ResourceEntry* entry;
+  if (entry_count == 0) {
+    // Adding a new resource
+    entry = type->CreateEntry(res.name.entry);
+  } else if (entry_count == 1) {
+    // Assume that the existing resource is being modified
+    entry = entry_it.first->get();
+  } else {
+    // Multiple resources with the same name exist in the resource table. The only way to
+    // distinguish between them is using resource id since each resource should have a unique id.
+    CHECK(res.id.has_value()) << "ambiguous modification of resource entry '" << res.name
+                              << "' without specifying a resource id.";
+    entry = entry_it.first->get();
+    for (auto it = entry_it.first; it != entry_it.second; ++it) {
+      CHECK((bool)(*it)->id) << "ambiguous modification of resource entry '" << res.name
+                             << "' with multiple entries without resource ids";
+      if ((*it)->id == res.id->first) {
+        entry = it->get();
+        break;
+      }
+    }
   }
 
-  if (res_id.is_valid()) {
-    package->id = res_id.package_id();
-    type->id = res_id.type_id();
-    entry->id = res_id.entry_id();
+  if (res.id.has_value()) {
+    if (entry->id && entry->id.value() != res.id->first) {
+      if (res.id->second != OnIdConflict::CREATE_ENTRY) {
+        diag->Error(DiagMessage(source)
+                    << "trying to add resource '" << res.name << "' with ID " << res.id->first
+                    << " but resource already has ID " << entry->id.value());
+        return false;
+      }
+      entry = type->CreateEntry(res.name.entry);
+    }
+    entry->id = res.id->first;
   }
 
-  // Only mark the type visibility level as public, it doesn't care about being private.
-  if (visibility.level == Visibility::Level::kPublic) {
-    type->visibility_level = Visibility::Level::kPublic;
+  if (res.visibility.has_value()) {
+    // Only mark the type visibility level as public, it doesn't care about being private.
+    if (res.visibility->level == Visibility::Level::kPublic) {
+      type->visibility_level = Visibility::Level::kPublic;
+    }
+
+    if (res.visibility->level > entry->visibility.level) {
+      // This symbol definition takes precedence, replace.
+      entry->visibility = res.visibility.value();
+    }
   }
 
-  if (visibility.level == Visibility::Level::kUndefined &&
-      entry->visibility.level != Visibility::Level::kUndefined) {
-    // We can't undefine a symbol (remove its visibility). Ignore.
-    return true;
+  if (res.overlayable.has_value()) {
+    if (entry->overlayable_item) {
+      diag->Error(DiagMessage(res.overlayable->source)
+                  << "duplicate overlayable declaration for resource '" << res.name << "'");
+      diag->Error(DiagMessage(entry->overlayable_item.value().source)
+                  << "previous declaration here");
+      return false;
+    }
+    entry->overlayable_item = res.overlayable.value();
   }
 
-  if (visibility.level < entry->visibility.level) {
-    // We can't downgrade public to private. Ignore.
-    return true;
+  if (res.allow_new.has_value()) {
+    entry->allow_new = res.allow_new.value();
   }
 
-  // This symbol definition takes precedence, replace.
-  entry->visibility = visibility;
-  return true;
-}
+  if (res.value != nullptr) {
+    auto config_value = entry->FindOrCreateValue(res.config, res.product);
+    if (!config_value->value) {
+      // Resource does not exist, add it now.
+      config_value->value = std::move(res.value);
+    } else {
+      // When validation is enabled, ensure that a resource cannot have multiple values defined for
+      // the same configuration.
+      auto result = validate ? ResolveValueCollision(config_value->value.get(), res.value.get())
+                             : CollisionResult::kKeepBoth;
+      switch (result) {
+        case CollisionResult::kKeepBoth:
+          // Insert the value ignoring for duplicate configurations
+          entry->values.push_back(util::make_unique<ResourceConfigValue>(res.config, res.product));
+          entry->values.back()->value = std::move(res.value);
+          break;
 
-bool ResourceTable::SetAllowNew(const ResourceNameRef& name, const AllowNew& allow_new,
-                                IDiagnostics* diag) {
-  return SetAllowNewImpl(name, allow_new, ResourceNameValidator, diag);
-}
+        case CollisionResult::kTakeNew:
+          // Take the incoming value.
+          config_value->value = std::move(res.value);
+          break;
 
-bool ResourceTable::SetAllowNewMangled(const ResourceNameRef& name, const AllowNew& allow_new,
-                                       IDiagnostics* diag) {
-  return SetAllowNewImpl(name, allow_new, SkipNameValidator, diag);
-}
+        case CollisionResult::kConflict:
+          diag->Error(DiagMessage(source) << "duplicate value for resource '" << res.name << "' "
+                                          << "with config '" << res.config << "'");
+          diag->Error(DiagMessage(source) << "resource previously defined here");
+          return false;
 
-bool ResourceTable::SetAllowNewImpl(const ResourceNameRef& name, const AllowNew& allow_new,
-                                    NameValidator name_validator, IDiagnostics* diag) {
-  CHECK(diag != nullptr);
-
-  if (!ValidateName(name_validator, name, allow_new.source, diag)) {
-    return false;
+        case CollisionResult::kKeepOriginal:
+          break;
+      }
+    }
   }
 
-  ResourceTablePackage* package = FindOrCreatePackage(name.package);
-  ResourceTableType* type = package->FindOrCreateType(name.type);
-  ResourceEntry* entry = type->FindOrCreateEntry(name.entry);
-  entry->allow_new = allow_new;
-  return true;
-}
-
-bool ResourceTable::SetOverlayable(const ResourceNameRef& name, const OverlayableItem& overlayable,
-                                   IDiagnostics* diag) {
-  return SetOverlayableImpl(name, overlayable, ResourceNameValidator, diag);
-}
-
-bool ResourceTable::SetOverlayableImpl(const ResourceNameRef& name,
-                                       const OverlayableItem& overlayable,
-                                       NameValidator name_validator, IDiagnostics *diag) {
-  CHECK(diag != nullptr);
-
-  if (!ValidateName(name_validator, name, overlayable.source, diag)) {
-    return false;
-  }
-
-  ResourceTablePackage* package = FindOrCreatePackage(name.package);
-  ResourceTableType* type = package->FindOrCreateType(name.type);
-  ResourceEntry* entry = type->FindOrCreateEntry(name.entry);
-
-  if (entry->overlayable_item) {
-    diag->Error(DiagMessage(overlayable.source)
-                << "duplicate overlayable declaration for resource '" << name << "'");
-    diag->Error(DiagMessage(entry->overlayable_item.value().source)
-                << "previous declaration here");
-    return false;
-  }
-
-  entry->overlayable_item = overlayable;
   return true;
 }
 
@@ -641,17 +496,38 @@
   return SearchResult{package, type, entry};
 }
 
+Maybe<ResourceTable::SearchResult> ResourceTable::FindResource(const ResourceNameRef& name,
+                                                               ResourceId id) const {
+  ResourceTablePackage* package = FindPackage(name.package);
+  if (package == nullptr) {
+    return {};
+  }
+
+  ResourceTableType* type = package->FindType(name.type);
+  if (type == nullptr) {
+    return {};
+  }
+
+  auto entry_it = std::equal_range(type->entries.begin(), type->entries.end(), name.entry,
+                                   NameEqualRange<ResourceEntry>{});
+  for (auto it = entry_it.first; it != entry_it.second; ++it) {
+    if ((*it)->id == id) {
+      return SearchResult{package, type, it->get()};
+    }
+  }
+  return {};
+}
+
 std::unique_ptr<ResourceTable> ResourceTable::Clone() const {
   std::unique_ptr<ResourceTable> new_table = util::make_unique<ResourceTable>();
   for (const auto& pkg : packages) {
-    ResourceTablePackage* new_pkg = new_table->CreatePackage(pkg->name, pkg->id);
+    ResourceTablePackage* new_pkg = new_table->FindOrCreatePackage(pkg->name);
     for (const auto& type : pkg->types) {
       ResourceTableType* new_type = new_pkg->FindOrCreateType(type->type);
-      new_type->id = type->id;
       new_type->visibility_level = type->visibility_level;
 
       for (const auto& entry : type->entries) {
-        ResourceEntry* new_entry = new_type->FindOrCreateEntry(entry->name);
+        ResourceEntry* new_entry = new_type->CreateEntry(entry->name);
         new_entry->id = entry->id;
         new_entry->visibility = entry->visibility;
         new_entry->allow_new = entry->allow_new;
@@ -668,4 +544,51 @@
   return new_table;
 }
 
+NewResourceBuilder::NewResourceBuilder(const ResourceNameRef& name) {
+  res_.name = name.ToResourceName();
+}
+
+NewResourceBuilder::NewResourceBuilder(const std::string& name) {
+  ResourceNameRef ref;
+  CHECK(ResourceUtils::ParseResourceName(name, &ref)) << "invalid resource name: " << name;
+  res_.name = ref.ToResourceName();
+}
+
+NewResourceBuilder& NewResourceBuilder::SetValue(std::unique_ptr<Value> value,
+                                                 android::ConfigDescription config,
+                                                 std::string product) {
+  res_.value = std::move(value);
+  res_.config = std::move(config);
+  res_.product = std::move(product);
+  return *this;
+}
+
+NewResourceBuilder& NewResourceBuilder::SetId(ResourceId id, OnIdConflict on_conflict) {
+  res_.id = std::make_pair(id, on_conflict);
+  return *this;
+}
+
+NewResourceBuilder& NewResourceBuilder::SetVisibility(Visibility visibility) {
+  res_.visibility = std::move(visibility);
+  return *this;
+}
+
+NewResourceBuilder& NewResourceBuilder::SetOverlayable(OverlayableItem overlayable) {
+  res_.overlayable = std::move(overlayable);
+  return *this;
+}
+NewResourceBuilder& NewResourceBuilder::SetAllowNew(AllowNew allow_new) {
+  res_.allow_new = std::move(allow_new);
+  return *this;
+}
+
+NewResourceBuilder& NewResourceBuilder::SetAllowMangled(bool allow_mangled) {
+  res_.allow_mangled = allow_mangled;
+  return *this;
+}
+
+NewResource NewResourceBuilder::Build() {
+  return std::move(res_);
+}
+
 }  // namespace aapt
diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h
index 93a7a31..49392a5 100644
--- a/tools/aapt2/ResourceTable.h
+++ b/tools/aapt2/ResourceTable.h
@@ -109,7 +109,7 @@
   const std::string name;
 
   // The entry ID for this resource (the EEEE in 0xPPTTEEEE).
-  Maybe<uint16_t> id;
+  Maybe<ResourceId> id;
 
   // Whether this resource is public (and must maintain the same entry ID across builds).
   Visibility visibility;
@@ -124,10 +124,10 @@
 
   explicit ResourceEntry(const android::StringPiece& name) : name(name.to_string()) {}
 
-  ResourceConfigValue* FindValue(const android::ConfigDescription& config);
-
   ResourceConfigValue* FindValue(const android::ConfigDescription& config,
-                                 const android::StringPiece& product);
+                                 android::StringPiece product = {});
+  const ResourceConfigValue* FindValue(const android::ConfigDescription& config,
+                                       android::StringPiece product = {}) const;
 
   ResourceConfigValue* FindOrCreateValue(const android::ConfigDescription& config,
                                          const android::StringPiece& product);
@@ -156,9 +156,6 @@
   // The logical type of resource (string, drawable, layout, etc.).
   const ResourceType type;
 
-  // The type ID for this resource (the TT in 0xPPTTEEEE).
-  Maybe<uint8_t> id;
-
   // Whether this type is public (and must maintain the same type ID across builds).
   Visibility::Level visibility_level = Visibility::Level::kUndefined;
 
@@ -167,10 +164,9 @@
 
   explicit ResourceTableType(const ResourceType type) : type(type) {}
 
-  ResourceEntry* FindEntry(const android::StringPiece& name,
-                           Maybe<uint16_t> id = Maybe<uint16_t>());
-  ResourceEntry* FindOrCreateEntry(const android::StringPiece& name,
-                                   Maybe<uint16_t> id = Maybe<uint16_t>());
+  ResourceEntry* CreateEntry(const android::StringPiece& name);
+  ResourceEntry* FindEntry(const android::StringPiece& name) const;
+  ResourceEntry* FindOrCreateEntry(const android::StringPiece& name);
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ResourceTableType);
@@ -180,70 +176,99 @@
  public:
   std::string name;
 
-  // The package ID (the PP in 0xPPTTEEEE).
-  Maybe<uint8_t> id;
-
   std::vector<std::unique_ptr<ResourceTableType>> types;
 
+  explicit ResourceTablePackage(const android::StringPiece& name) : name(name.to_string()) {
+  }
+
   ResourceTablePackage() = default;
-  ResourceTableType* FindType(ResourceType type, Maybe<uint8_t> id = Maybe<uint8_t>());
-  ResourceTableType* FindOrCreateType(const ResourceType type,
-                                      Maybe<uint8_t> id = Maybe<uint8_t>());
+  ResourceTableType* FindType(ResourceType type) const;
+  ResourceTableType* FindOrCreateType(ResourceType type);
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ResourceTablePackage);
 };
 
+struct ResourceTableTypeView {
+  ResourceType type;
+  Maybe<uint8_t> id;
+  Visibility::Level visibility_level = Visibility::Level::kUndefined;
+
+  // Entries sorted in ascending entry id order. If ids have not been assigned, the entries are
+  //  // sorted lexicographically.
+  std::vector<const ResourceEntry*> entries;
+};
+
+struct ResourceTablePackageView {
+  std::string name;
+  Maybe<uint8_t> id;
+  // Types sorted in ascending type id order. If ids have not been assigned, the types are sorted by
+  // their declaration order in the ResourceType enum.
+  std::vector<ResourceTableTypeView> types;
+};
+
+struct ResourceTableView {
+  // Packages sorted in ascending package id order. If ids have not been assigned, the packages are
+  // sorted lexicographically.
+  std::vector<ResourceTablePackageView> packages;
+};
+
+enum class OnIdConflict {
+  // If the resource entry already exists but has a different resource id, the resource value will
+  // not be added to the table.
+  ERROR,
+
+  // If the resource entry already exists but has a different resource id, create a new resource
+  // with this resource name and id combination.
+  CREATE_ENTRY,
+};
+
+struct NewResource {
+  ResourceName name;
+  std::unique_ptr<Value> value;
+  android::ConfigDescription config;
+  std::string product;
+  std::optional<std::pair<ResourceId, OnIdConflict>> id;
+  std::optional<Visibility> visibility;
+  std::optional<OverlayableItem> overlayable;
+  std::optional<AllowNew> allow_new;
+  bool allow_mangled = false;
+};
+
+struct NewResourceBuilder {
+  explicit NewResourceBuilder(const ResourceNameRef& name);
+  explicit NewResourceBuilder(const std::string& name);
+  NewResourceBuilder& SetValue(std::unique_ptr<Value> value, android::ConfigDescription config = {},
+                               std::string product = {});
+  NewResourceBuilder& SetId(ResourceId id, OnIdConflict on_conflict = OnIdConflict::ERROR);
+  NewResourceBuilder& SetVisibility(Visibility id);
+  NewResourceBuilder& SetOverlayable(OverlayableItem overlayable);
+  NewResourceBuilder& SetAllowNew(AllowNew allow_new);
+  NewResourceBuilder& SetAllowMangled(bool allow_mangled);
+  NewResource Build();
+
+ private:
+  NewResource res_;
+};
+
 // The container and index for all resources defined for an app.
 class ResourceTable {
  public:
-  ResourceTable() = default;
-  explicit ResourceTable(bool validate_resources) : validate_resources_(validate_resources) {}
+  enum class Validation {
+    kEnabled,
+    kDisabled,
+  };
 
   enum class CollisionResult { kKeepBoth, kKeepOriginal, kConflict, kTakeNew };
 
-  using CollisionResolverFunc = std::function<CollisionResult(Value*, Value*)>;
+  ResourceTable() = default;
+  explicit ResourceTable(Validation validation);
 
-  // When a collision of resources occurs, this method decides which value to keep.
-  static CollisionResult ResolveValueCollision(Value* existing, Value* incoming);
+  bool AddResource(NewResource&& res, IDiagnostics* diag);
 
-  // When a collision of resources occurs, this method keeps both values
-  static CollisionResult IgnoreCollision(Value* existing, Value* incoming);
-
-  bool AddResource(const ResourceNameRef& name, const android::ConfigDescription& config,
-                   const android::StringPiece& product, std::unique_ptr<Value> value,
-                   IDiagnostics* diag);
-
-  bool AddResourceWithId(const ResourceNameRef& name, const ResourceId& res_id,
-                         const android::ConfigDescription& config,
-                         const android::StringPiece& product, std::unique_ptr<Value> value,
-                         IDiagnostics* diag);
-
-  // Same as AddResource, but doesn't verify the validity of the name. This is used
-  // when loading resources from an existing binary resource table that may have mangled names.
-  bool AddResourceMangled(const ResourceNameRef& name, const android::ConfigDescription& config,
-                          const android::StringPiece& product, std::unique_ptr<Value> value,
-                          IDiagnostics* diag);
-
-  bool AddResourceWithIdMangled(const ResourceNameRef& name, const ResourceId& id,
-                                const android::ConfigDescription& config,
-                                const android::StringPiece& product, std::unique_ptr<Value> value,
-                                IDiagnostics* diag);
-
-  bool GetValidateResources();
-
-  bool SetVisibility(const ResourceNameRef& name, const Visibility& visibility, IDiagnostics* diag);
-  bool SetVisibilityWithId(const ResourceNameRef& name, const Visibility& visibility,
-                           const ResourceId& res_id, IDiagnostics* diag);
-  bool SetVisibilityWithIdMangled(const ResourceNameRef& name, const Visibility& visibility,
-                                  const ResourceId& res_id, IDiagnostics* diag);
-
-  bool SetOverlayable(const ResourceNameRef& name, const OverlayableItem& overlayable,
-                      IDiagnostics *diag);
-
-  bool SetAllowNew(const ResourceNameRef& name, const AllowNew& allow_new, IDiagnostics* diag);
-  bool SetAllowNewMangled(const ResourceNameRef& name, const AllowNew& allow_new,
-                          IDiagnostics* diag);
+  // Retrieves a sorted a view of the packages, types, and entries sorted in ascending resource id
+  // order.
+  ResourceTableView GetPartitionedView() const;
 
   struct SearchResult {
     ResourceTablePackage* package;
@@ -252,23 +277,19 @@
   };
 
   Maybe<SearchResult> FindResource(const ResourceNameRef& name) const;
+  Maybe<SearchResult> FindResource(const ResourceNameRef& name, ResourceId id) const;
 
   // Returns the package struct with the given name, or nullptr if such a package does not
   // exist. The empty string is a valid package and typically is used to represent the
   // 'current' package before it is known to the ResourceTable.
   ResourceTablePackage* FindPackage(const android::StringPiece& name) const;
-
-  ResourceTablePackage* FindPackageById(uint8_t id) const;
-
-  ResourceTablePackage* CreatePackage(const android::StringPiece& name, Maybe<uint8_t> id = {});
-
-  // Attempts to find a package having the specified name and ID. If not found, a new package
-  // of the specified parameters is created and returned.
-  ResourceTablePackage* CreatePackageAllowingDuplicateNames(const android::StringPiece& name,
-                                                            const Maybe<uint8_t> id);
+  ResourceTablePackage* FindOrCreatePackage(const android::StringPiece& name);
 
   std::unique_ptr<ResourceTable> Clone() const;
 
+  // When a collision of resources occurs, this method decides which value to keep.
+  static CollisionResult ResolveValueCollision(Value* existing, Value* incoming);
+
   // The string pool used by this resource table. Values that reference strings must use
   // this pool to create their strings.
   // NOTE: `string_pool` must come before `packages` so that it is destroyed after.
@@ -286,36 +307,9 @@
   std::map<size_t, std::string> included_packages_;
 
  private:
-  // The function type that validates a symbol name. Returns a non-empty StringPiece representing
-  // the offending character (which may be more than one byte in UTF-8). Returns an empty string
-  // if the name was valid.
-  using NameValidator = android::StringPiece(const android::StringPiece&);
-
-  ResourceTablePackage* FindOrCreatePackage(const android::StringPiece& name);
-
-  bool ValidateName(NameValidator validator, const ResourceNameRef& name, const Source& source,
-                    IDiagnostics* diag);
-
-  bool AddResourceImpl(const ResourceNameRef& name, const ResourceId& res_id,
-                       const android::ConfigDescription& config,
-                       const android::StringPiece& product, std::unique_ptr<Value> value,
-                       NameValidator name_validator, const CollisionResolverFunc& conflict_resolver,
-                       IDiagnostics* diag);
-
-  bool SetVisibilityImpl(const ResourceNameRef& name, const Visibility& visibility,
-                         const ResourceId& res_id, NameValidator name_validator,
-                         IDiagnostics* diag);
-
-  bool SetAllowNewImpl(const ResourceNameRef& name, const AllowNew& allow_new,
-                       NameValidator name_validator, IDiagnostics* diag);
-
-  bool SetOverlayableImpl(const ResourceNameRef &name, const OverlayableItem& overlayable,
-                          NameValidator name_validator, IDiagnostics *diag);
-
-  // Controls whether the table validates resource names and prevents duplicate resource names
-  bool validate_resources_ = true;
-
   DISALLOW_COPY_AND_ASSIGN(ResourceTable);
+
+  Validation validation_ = Validation::kEnabled;
 };
 
 }  // namespace aapt
diff --git a/tools/aapt2/ResourceTable_test.cpp b/tools/aapt2/ResourceTable_test.cpp
index 9271a7e..38391c9 100644
--- a/tools/aapt2/ResourceTable_test.cpp
+++ b/tools/aapt2/ResourceTable_test.cpp
@@ -37,31 +37,32 @@
 TEST(ResourceTableTest, FailToAddResourceWithBadName) {
   ResourceTable table;
 
-  EXPECT_FALSE(table.AddResource(
-      test::ParseNameOrDie("android:id/hey,there"), ConfigDescription{}, "",
-      test::ValueBuilder<Id>().SetSource("test.xml", 21u).Build(),
-      test::GetDiagnostics()));
+  EXPECT_FALSE(
+      table.AddResource(NewResourceBuilder(test::ParseNameOrDie("android:id/hey,there")).Build(),
+                        test::GetDiagnostics()));
 
-  EXPECT_FALSE(table.AddResource(
-      test::ParseNameOrDie("android:id/hey:there"), ConfigDescription{}, "",
-      test::ValueBuilder<Id>().SetSource("test.xml", 21u).Build(),
-      test::GetDiagnostics()));
+  EXPECT_FALSE(
+      table.AddResource(NewResourceBuilder(test::ParseNameOrDie("android:id/hey:there")).Build(),
+                        test::GetDiagnostics()));
 }
 
 TEST(ResourceTableTest, AddResourceWithWeirdNameWhenAddingMangledResources) {
   ResourceTable table;
 
-  EXPECT_TRUE(table.AddResourceMangled(
-      test::ParseNameOrDie("android:id/heythere       "), ConfigDescription{}, "",
-      test::ValueBuilder<Id>().SetSource("test.xml", 21u).Build(), test::GetDiagnostics()));
+  EXPECT_TRUE(
+      table.AddResource(NewResourceBuilder(test::ParseNameOrDie("android:id/heythere       "))
+                            .SetAllowMangled(true)
+                            .Build(),
+                        test::GetDiagnostics()));
 }
 
 TEST(ResourceTableTest, AddOneResource) {
   ResourceTable table;
 
   EXPECT_TRUE(table.AddResource(
-      test::ParseNameOrDie("android:attr/id"), ConfigDescription{}, "",
-      test::ValueBuilder<Id>().SetSource("test/path/file.xml", 23u).Build(),
+      NewResourceBuilder(test::ParseNameOrDie("android:attr/id"))
+          .SetValue(test::ValueBuilder<Id>().SetSource("test/path/file.xml", 23u).Build())
+          .Build(),
       test::GetDiagnostics()));
 
   EXPECT_THAT(test::GetValue<Id>(&table, "android:attr/id"), NotNull());
@@ -70,32 +71,36 @@
 TEST(ResourceTableTest, AddMultipleResources) {
   ResourceTable table;
 
-  ConfigDescription config;
   ConfigDescription language_config;
   memcpy(language_config.language, "pl", sizeof(language_config.language));
 
   EXPECT_TRUE(table.AddResource(
-      test::ParseNameOrDie("android:attr/layout_width"), config, "",
-      test::ValueBuilder<Id>().SetSource("test/path/file.xml", 10u).Build(),
-      test::GetDiagnostics()));
-
-  EXPECT_TRUE(table.AddResource(
-      test::ParseNameOrDie("android:attr/id"), config, "",
-      test::ValueBuilder<Id>().SetSource("test/path/file.xml", 12u).Build(),
-      test::GetDiagnostics()));
-
-  EXPECT_TRUE(table.AddResource(
-      test::ParseNameOrDie("android:string/ok"), config, "",
-      test::ValueBuilder<Id>().SetSource("test/path/file.xml", 14u).Build(),
-      test::GetDiagnostics()));
-
-  EXPECT_TRUE(table.AddResource(
-      test::ParseNameOrDie("android:string/ok"), language_config, "",
-      test::ValueBuilder<BinaryPrimitive>(android::Res_value{})
-          .SetSource("test/path/file.xml", 20u)
+      NewResourceBuilder(test::ParseNameOrDie("android:attr/layout_width"))
+          .SetValue(test::ValueBuilder<Id>().SetSource("test/path/file.xml", 10u).Build())
           .Build(),
       test::GetDiagnostics()));
 
+  EXPECT_TRUE(table.AddResource(
+      NewResourceBuilder(test::ParseNameOrDie("android:attr/id"))
+          .SetValue(test::ValueBuilder<Id>().SetSource("test/path/file.xml", 12u).Build())
+          .Build(),
+      test::GetDiagnostics()));
+
+  EXPECT_TRUE(table.AddResource(
+      NewResourceBuilder(test::ParseNameOrDie("android:string/ok"))
+          .SetValue(test::ValueBuilder<Id>().SetSource("test/path/file.xml", 14u).Build())
+          .Build(),
+      test::GetDiagnostics()));
+
+  EXPECT_TRUE(
+      table.AddResource(NewResourceBuilder(test::ParseNameOrDie("android:string/ok"))
+                            .SetValue(test::ValueBuilder<BinaryPrimitive>(android::Res_value{})
+                                          .SetSource("test/path/file.xml", 20u)
+                                          .Build(),
+                                      language_config)
+                            .Build(),
+                        test::GetDiagnostics()));
+
   EXPECT_THAT(test::GetValue<Id>(&table, "android:attr/layout_width"), NotNull());
   EXPECT_THAT(test::GetValue<Id>(&table, "android:attr/id"), NotNull());
   EXPECT_THAT(test::GetValue<Id>(&table, "android:string/ok"), NotNull());
@@ -104,17 +109,19 @@
 
 TEST(ResourceTableTest, OverrideWeakResourceValue) {
   ResourceTable table;
-
-  ASSERT_TRUE(table.AddResource(test::ParseNameOrDie("android:attr/foo"), ConfigDescription{}, "",
-                                test::AttributeBuilder().SetWeak(true).Build(),
+  ASSERT_TRUE(table.AddResource(NewResourceBuilder(test::ParseNameOrDie("android:attr/foo"))
+                                    .SetValue(test::AttributeBuilder().SetWeak(true).Build())
+                                    .Build(),
                                 test::GetDiagnostics()));
 
   Attribute* attr = test::GetValue<Attribute>(&table, "android:attr/foo");
   ASSERT_THAT(attr, NotNull());
   EXPECT_TRUE(attr->IsWeak());
 
-  ASSERT_TRUE(table.AddResource(test::ParseNameOrDie("android:attr/foo"), ConfigDescription{}, "",
-                                util::make_unique<Attribute>(), test::GetDiagnostics()));
+  ASSERT_TRUE(table.AddResource(NewResourceBuilder(test::ParseNameOrDie("android:attr/foo"))
+                                    .SetValue(util::make_unique<Attribute>())
+                                    .Build(),
+                                test::GetDiagnostics()));
 
   attr = test::GetValue<Attribute>(&table, "android:attr/foo");
   ASSERT_THAT(attr, NotNull());
@@ -130,23 +137,27 @@
   Attribute attr_two(android::ResTable_map::TYPE_STRING | android::ResTable_map::TYPE_REFERENCE);
   attr_two.SetWeak(true);
 
-  ASSERT_TRUE(table.AddResource(name, ConfigDescription{}, "",
-                                util::make_unique<Attribute>(attr_one), test::GetDiagnostics()));
-  ASSERT_TRUE(table.AddResource(name, ConfigDescription{}, "",
-                                util::make_unique<Attribute>(attr_two), test::GetDiagnostics()));
+  ASSERT_TRUE(table.AddResource(
+      NewResourceBuilder(name).SetValue(util::make_unique<Attribute>(attr_one)).Build(),
+      test::GetDiagnostics()));
+  ASSERT_TRUE(table.AddResource(
+      NewResourceBuilder(name).SetValue(util::make_unique<Attribute>(attr_two)).Build(),
+      test::GetDiagnostics()));
 }
 
 TEST(ResourceTableTest, ProductVaryingValues) {
   ResourceTable table;
+  ASSERT_TRUE(table.AddResource(
+      NewResourceBuilder(test::ParseNameOrDie("android:string/foo"))
+          .SetValue(util::make_unique<Id>(), test::ParseConfigOrDie("land"), "tablet")
+          .Build(),
+      test::GetDiagnostics()));
 
-  EXPECT_TRUE(table.AddResource(test::ParseNameOrDie("android:string/foo"),
-                                test::ParseConfigOrDie("land"), "tablet",
-                                util::make_unique<Id>(),
-                                test::GetDiagnostics()));
-  EXPECT_TRUE(table.AddResource(test::ParseNameOrDie("android:string/foo"),
-                                test::ParseConfigOrDie("land"), "phone",
-                                util::make_unique<Id>(),
-                                test::GetDiagnostics()));
+  ASSERT_TRUE(table.AddResource(
+      NewResourceBuilder(test::ParseNameOrDie("android:string/foo"))
+          .SetValue(util::make_unique<Id>(), test::ParseConfigOrDie("land"), "phone")
+          .Build(),
+      test::GetDiagnostics()));
 
   EXPECT_THAT(test::GetValueForConfigAndProduct<Id>(&table, "android:string/foo",test::ParseConfigOrDie("land"), "tablet"), NotNull());
   EXPECT_THAT(test::GetValueForConfigAndProduct<Id>(&table, "android:string/foo",test::ParseConfigOrDie("land"), "phone"), NotNull());
@@ -203,22 +214,26 @@
   Visibility visibility;
   visibility.level = Visibility::Level::kPrivate;
   visibility.comment = "private";
-  ASSERT_TRUE(table.SetVisibility(name, visibility, test::GetDiagnostics()));
+  ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetVisibility(visibility).Build(),
+                                test::GetDiagnostics()));
   ASSERT_TRUE(VisibilityOfResource(table, name, Level::kPrivate, "private"));
 
   visibility.level = Visibility::Level::kUndefined;
   visibility.comment = "undefined";
-  ASSERT_TRUE(table.SetVisibility(name, visibility, test::GetDiagnostics()));
+  ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetVisibility(visibility).Build(),
+                                test::GetDiagnostics()));
   ASSERT_TRUE(VisibilityOfResource(table, name, Level::kPrivate, "private"));
 
   visibility.level = Visibility::Level::kPublic;
   visibility.comment = "public";
-  ASSERT_TRUE(table.SetVisibility(name, visibility, test::GetDiagnostics()));
+  ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetVisibility(visibility).Build(),
+                                test::GetDiagnostics()));
   ASSERT_TRUE(VisibilityOfResource(table, name, Level::kPublic, "public"));
 
   visibility.level = Visibility::Level::kPrivate;
   visibility.comment = "private";
-  ASSERT_TRUE(table.SetVisibility(name, visibility, test::GetDiagnostics()));
+  ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetVisibility(visibility).Build(),
+                                test::GetDiagnostics()));
   ASSERT_TRUE(VisibilityOfResource(table, name, Level::kPublic, "public"));
 }
 
@@ -230,14 +245,16 @@
   Maybe<ResourceTable::SearchResult> result;
 
   allow_new.comment = "first";
-  ASSERT_TRUE(table.SetAllowNew(name, allow_new, test::GetDiagnostics()));
+  ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetAllowNew(allow_new).Build(),
+                                test::GetDiagnostics()));
   result = table.FindResource(name);
   ASSERT_TRUE(result);
   ASSERT_TRUE(result.value().entry->allow_new);
   ASSERT_THAT(result.value().entry->allow_new.value().comment, StrEq("first"));
 
   allow_new.comment = "second";
-  ASSERT_TRUE(table.SetAllowNew(name, allow_new, test::GetDiagnostics()));
+  ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetAllowNew(allow_new).Build(),
+                                test::GetDiagnostics()));
   result = table.FindResource(name);
   ASSERT_TRUE(result);
   ASSERT_TRUE(result.value().entry->allow_new);
@@ -255,7 +272,8 @@
   overlayable_item.source = Source("res/values/overlayable.xml", 42);
 
   const ResourceName name = test::ParseNameOrDie("android:string/foo");
-  ASSERT_TRUE(table.SetOverlayable(name, overlayable_item, test::GetDiagnostics()));
+  ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetOverlayable(overlayable_item).Build(),
+                                test::GetDiagnostics()));
   Maybe<ResourceTable::SearchResult> search_result = table.FindResource(name);
 
   ASSERT_TRUE(search_result);
@@ -280,17 +298,20 @@
   auto group = std::make_shared<Overlayable>("Name", "overlay://theme");
   OverlayableItem overlayable(group);
   overlayable.policies = PolicyFlags::PRODUCT_PARTITION;
-  ASSERT_TRUE(table.SetOverlayable(foo, overlayable, test::GetDiagnostics()));
+  ASSERT_TRUE(table.AddResource(NewResourceBuilder(foo).SetOverlayable(overlayable).Build(),
+                                test::GetDiagnostics()));
 
   const ResourceName bar = test::ParseNameOrDie("android:string/bar");
   OverlayableItem overlayable2(group);
   overlayable2.policies = PolicyFlags::PRODUCT_PARTITION;
-  ASSERT_TRUE(table.SetOverlayable(bar, overlayable2, test::GetDiagnostics()));
+  ASSERT_TRUE(table.AddResource(NewResourceBuilder(bar).SetOverlayable(overlayable2).Build(),
+                                test::GetDiagnostics()));
 
   const ResourceName baz = test::ParseNameOrDie("android:string/baz");
   OverlayableItem overlayable3(group);
   overlayable3.policies = PolicyFlags::VENDOR_PARTITION;
-  ASSERT_TRUE(table.SetOverlayable(baz, overlayable3, test::GetDiagnostics()));
+  ASSERT_TRUE(table.AddResource(NewResourceBuilder(baz).SetOverlayable(overlayable3).Build(),
+                                test::GetDiagnostics()));
 }
 
 TEST(ResourceTableTest, SetOverlayableDifferentResourcesDifferentName) {
@@ -299,12 +320,14 @@
   const ResourceName foo = test::ParseNameOrDie("android:string/foo");
   OverlayableItem overlayable_item(std::make_shared<Overlayable>("Name", "overlay://theme"));
   overlayable_item.policies = PolicyFlags::PRODUCT_PARTITION;
-  ASSERT_TRUE(table.SetOverlayable(foo, overlayable_item, test::GetDiagnostics()));
+  ASSERT_TRUE(table.AddResource(NewResourceBuilder(foo).SetOverlayable(overlayable_item).Build(),
+                                test::GetDiagnostics()));
 
   const ResourceName bar = test::ParseNameOrDie("android:string/bar");
   OverlayableItem overlayable_item2(std::make_shared<Overlayable>("Name2",  "overlay://theme"));
   overlayable_item2.policies = PolicyFlags::PRODUCT_PARTITION;
-  ASSERT_TRUE(table.SetOverlayable(bar, overlayable_item2, test::GetDiagnostics()));
+  ASSERT_TRUE(table.AddResource(NewResourceBuilder(bar).SetOverlayable(overlayable_item2).Build(),
+                                test::GetDiagnostics()));
 }
 
 TEST(ResourceTableTest, SetOverlayableSameResourcesFail) {
@@ -313,10 +336,12 @@
 
   auto overlayable = std::make_shared<Overlayable>("Name", "overlay://theme");
   OverlayableItem overlayable_item(overlayable);
-  ASSERT_TRUE(table.SetOverlayable(name, overlayable_item, test::GetDiagnostics()));
+  ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetOverlayable(overlayable_item).Build(),
+                                test::GetDiagnostics()));
 
   OverlayableItem overlayable_item2(overlayable);
-  ASSERT_FALSE(table.SetOverlayable(name, overlayable_item2, test::GetDiagnostics()));
+  ASSERT_FALSE(table.AddResource(NewResourceBuilder(name).SetOverlayable(overlayable_item2).Build(),
+                                 test::GetDiagnostics()));
 }
 
 TEST(ResourceTableTest,  SetOverlayableSameResourcesDifferentNameFail) {
@@ -325,51 +350,38 @@
 
   auto overlayable = std::make_shared<Overlayable>("Name", "overlay://theme");
   OverlayableItem overlayable_item(overlayable);
-  ASSERT_TRUE(table.SetOverlayable(name, overlayable_item, test::GetDiagnostics()));
+  ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetOverlayable(overlayable_item).Build(),
+                                test::GetDiagnostics()));
 
   auto overlayable2 = std::make_shared<Overlayable>("Other", "overlay://theme");
   OverlayableItem overlayable_item2(overlayable2);
-  ASSERT_FALSE(table.SetOverlayable(name, overlayable_item2, test::GetDiagnostics()));
+  ASSERT_FALSE(table.AddResource(NewResourceBuilder(name).SetOverlayable(overlayable_item2).Build(),
+                                 test::GetDiagnostics()));
 }
 
-TEST(ResourceTableTest, AllowDuplictaeResourcesNames) {
-  ResourceTable table(/* validate_resources */ false);
+TEST(ResourceTableTest, ConflictingIds) {
+  ResourceTable table;
+  const ResourceName name = test::ParseNameOrDie("android:string/foo");
+  ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetId(0x01010000).Build(),
+                                test::GetDiagnostics()));
+  ASSERT_FALSE(table.AddResource(NewResourceBuilder(name).SetId(0x01010001).Build(),
+                                 test::GetDiagnostics()));
+}
 
-  const ResourceName foo_name = test::ParseNameOrDie("android:bool/foo");
-  ASSERT_TRUE(table.AddResourceWithId(foo_name, ResourceId(0x7f0100ff), ConfigDescription{} , "",
-                                      test::BuildPrimitive(android::Res_value::TYPE_INT_BOOLEAN, 0),
-                                      test::GetDiagnostics()));
-  ASSERT_TRUE(table.AddResourceWithId(foo_name, ResourceId(0x7f010100), ConfigDescription{} , "",
-                                      test::BuildPrimitive(android::Res_value::TYPE_INT_BOOLEAN, 1),
-                                      test::GetDiagnostics()));
+TEST(ResourceTableTest, ConflictingIdsCreateEntry) {
+  ResourceTable table;
+  const ResourceName name = test::ParseNameOrDie("android:string/foo");
+  ASSERT_TRUE(table.AddResource(
+      NewResourceBuilder(name).SetId(0x01010000, OnIdConflict::CREATE_ENTRY).Build(),
+      test::GetDiagnostics()));
+  ASSERT_TRUE(table.AddResource(
+      NewResourceBuilder(name).SetId(0x01010001, OnIdConflict::CREATE_ENTRY).Build(),
+      test::GetDiagnostics()));
 
-  ASSERT_TRUE(table.SetVisibilityWithId(foo_name, Visibility{Visibility::Level::kPublic},
-                                        ResourceId(0x7f0100ff), test::GetDiagnostics()));
-  ASSERT_TRUE(table.SetVisibilityWithId(foo_name, Visibility{Visibility::Level::kPrivate},
-                                        ResourceId(0x7f010100), test::GetDiagnostics()));
-
-  auto package = table.FindPackageById(0x7f);
-  ASSERT_THAT(package, NotNull());
-  auto type = package->FindType(ResourceType::kBool);
-  ASSERT_THAT(type, NotNull());
-
-  auto entry1 = type->FindEntry("foo", 0x00ff);
-  ASSERT_THAT(entry1, NotNull());
-  ASSERT_THAT(entry1->id, Eq(0x00ff));
-  ASSERT_THAT(entry1->values[0], NotNull());
-  ASSERT_THAT(entry1->values[0]->value, NotNull());
-  ASSERT_THAT(ValueCast<BinaryPrimitive>(entry1->values[0]->value.get()), NotNull());
-  ASSERT_THAT(ValueCast<BinaryPrimitive>(entry1->values[0]->value.get())->value.data, Eq(0u));
-  ASSERT_THAT(entry1->visibility.level, Visibility::Level::kPublic);
-
-  auto entry2 = type->FindEntry("foo", 0x0100);
-  ASSERT_THAT(entry2, NotNull());
-  ASSERT_THAT(entry2->id, Eq(0x0100));
-  ASSERT_THAT(entry2->values[0], NotNull());
-  ASSERT_THAT(entry1->values[0]->value, NotNull());
-  ASSERT_THAT(ValueCast<BinaryPrimitive>(entry2->values[0]->value.get()), NotNull());
-  ASSERT_THAT(ValueCast<BinaryPrimitive>(entry2->values[0]->value.get())->value.data, Eq(1u));
-  ASSERT_THAT(entry2->visibility.level, Visibility::Level::kPrivate);
+  // Non-ambiguous query
+  ASSERT_TRUE(table.AddResource(
+      NewResourceBuilder(name).SetId(0x01010001).SetValue(std::make_unique<Id>()).Build(),
+      test::GetDiagnostics()));
 }
 
 }  // namespace aapt
diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp
index ff54fcc..cd5015e 100644
--- a/tools/aapt2/cmd/Compile.cpp
+++ b/tools/aapt2/cmd/Compile.cpp
@@ -190,17 +190,6 @@
     }
   }
 
-  // Ensure we have the compilation package at least.
-  table.CreatePackage(context->GetCompilationPackage());
-
-  // Assign an ID to any package that has resources.
-  for (auto& pkg : table.packages) {
-    if (!pkg->id) {
-      // If no package ID was set while parsing (public identifiers), auto assign an ID.
-      pkg->id = context->GetPackageId();
-    }
-  }
-
   // Create the file/zip entry.
   if (!writer->StartEntry(output_path, 0)) {
     context->GetDiagnostics()->Error(DiagMessage(output_path) << "failed to open");
diff --git a/tools/aapt2/cmd/Compile_test.cpp b/tools/aapt2/cmd/Compile_test.cpp
index 8cbd998..8975713 100644
--- a/tools/aapt2/cmd/Compile_test.cpp
+++ b/tools/aapt2/cmd/Compile_test.cpp
@@ -217,6 +217,7 @@
   }, compiled_files_dir, &diag));
 
   std::unique_ptr<LoadedApk> apk = LoadedApk::LoadApkFromPath(out_apk, &diag);
+  ASSERT_NE(apk, nullptr);
 
   ResourceTable* table = apk->GetResourceTable();
   ASSERT_NE(table, nullptr);
diff --git a/tools/aapt2/cmd/Diff.cpp b/tools/aapt2/cmd/Diff.cpp
index d56994e..0bb044e 100644
--- a/tools/aapt2/cmd/Diff.cpp
+++ b/tools/aapt2/cmd/Diff.cpp
@@ -95,17 +95,17 @@
   return false;
 }
 
-static bool EmitResourceConfigValueDiff(IAaptContext* context, LoadedApk* apk_a,
-                                        ResourceTablePackage* pkg_a, ResourceTableType* type_a,
-                                        ResourceEntry* entry_a, ResourceConfigValue* config_value_a,
-                                        LoadedApk* apk_b, ResourceTablePackage* pkg_b,
-                                        ResourceTableType* type_b, ResourceEntry* entry_b,
-                                        ResourceConfigValue* config_value_b) {
+static bool EmitResourceConfigValueDiff(
+    IAaptContext* context, LoadedApk* apk_a, const ResourceTablePackageView& pkg_a,
+    const ResourceTableTypeView& type_a, const ResourceEntry* entry_a,
+    const ResourceConfigValue* config_value_a, LoadedApk* apk_b,
+    const ResourceTablePackageView& pkg_b, const ResourceTableTypeView& type_b,
+    const ResourceEntry* entry_b, const ResourceConfigValue* config_value_b) {
   Value* value_a = config_value_a->value.get();
   Value* value_b = config_value_b->value.get();
   if (!value_a->Equals(value_b)) {
     std::stringstream str_stream;
-    str_stream << "value " << pkg_a->name << ":" << type_a->type << "/" << entry_a->name
+    str_stream << "value " << pkg_a.name << ":" << type_a.type << "/" << entry_a->name
                << " config=" << config_value_a->config << " does not match:\n";
     value_a->Print(&str_stream);
     str_stream << "\n vs \n";
@@ -117,16 +117,17 @@
 }
 
 static bool EmitResourceEntryDiff(IAaptContext* context, LoadedApk* apk_a,
-                                  ResourceTablePackage* pkg_a, ResourceTableType* type_a,
-                                  ResourceEntry* entry_a, LoadedApk* apk_b,
-                                  ResourceTablePackage* pkg_b, ResourceTableType* type_b,
-                                  ResourceEntry* entry_b) {
+                                  const ResourceTablePackageView& pkg_a,
+                                  const ResourceTableTypeView& type_a, const ResourceEntry* entry_a,
+                                  LoadedApk* apk_b, const ResourceTablePackageView& pkg_b,
+                                  const ResourceTableTypeView& type_b,
+                                  const ResourceEntry* entry_b) {
   bool diff = false;
-  for (std::unique_ptr<ResourceConfigValue>& config_value_a : entry_a->values) {
-    ResourceConfigValue* config_value_b = entry_b->FindValue(config_value_a->config);
+  for (const std::unique_ptr<ResourceConfigValue>& config_value_a : entry_a->values) {
+    auto config_value_b = entry_b->FindValue(config_value_a->config);
     if (!config_value_b) {
       std::stringstream str_stream;
-      str_stream << "missing " << pkg_a->name << ":" << type_a->type << "/" << entry_a->name
+      str_stream << "missing " << pkg_a.name << ":" << type_a.type << "/" << entry_a->name
                  << " config=" << config_value_a->config;
       EmitDiffLine(apk_b->GetSource(), str_stream.str());
       diff = true;
@@ -138,35 +139,47 @@
   }
 
   // Check for any newly added config values.
-  for (std::unique_ptr<ResourceConfigValue>& config_value_b : entry_b->values) {
-    ResourceConfigValue* config_value_a = entry_a->FindValue(config_value_b->config);
+  for (const std::unique_ptr<ResourceConfigValue>& config_value_b : entry_b->values) {
+    auto config_value_a = entry_a->FindValue(config_value_b->config);
     if (!config_value_a) {
       std::stringstream str_stream;
-      str_stream << "new config " << pkg_b->name << ":" << type_b->type << "/" << entry_b->name
+      str_stream << "new config " << pkg_b.name << ":" << type_b.type << "/" << entry_b->name
                  << " config=" << config_value_b->config;
       EmitDiffLine(apk_b->GetSource(), str_stream.str());
       diff = true;
     }
   }
-  return false;
+  return diff;
 }
 
 static bool EmitResourceTypeDiff(IAaptContext* context, LoadedApk* apk_a,
-                                 ResourceTablePackage* pkg_a, ResourceTableType* type_a,
-                                 LoadedApk* apk_b, ResourceTablePackage* pkg_b,
-                                 ResourceTableType* type_b) {
+                                 const ResourceTablePackageView& pkg_a,
+                                 const ResourceTableTypeView& type_a, LoadedApk* apk_b,
+                                 const ResourceTablePackageView& pkg_b,
+                                 const ResourceTableTypeView& type_b) {
   bool diff = false;
-  for (std::unique_ptr<ResourceEntry>& entry_a : type_a->entries) {
-    ResourceEntry* entry_b = type_b->FindEntry(entry_a->name);
-    if (!entry_b) {
+  auto entry_a_iter = type_a.entries.begin();
+  auto entry_b_iter = type_b.entries.begin();
+  while (entry_a_iter != type_a.entries.end() || entry_b_iter != type_b.entries.end()) {
+    if (entry_b_iter == type_b.entries.end()) {
+      // Type A contains a type that type B does not have.
       std::stringstream str_stream;
-      str_stream << "missing " << pkg_a->name << ":" << type_a->type << "/" << entry_a->name;
+      str_stream << "missing " << pkg_a.name << ":" << type_a.type << "/" << (*entry_a_iter)->name;
+      EmitDiffLine(apk_a->GetSource(), str_stream.str());
+      diff = true;
+    } else if (entry_a_iter == type_a.entries.end()) {
+      // Type B contains a type that type A does not have.
+      std::stringstream str_stream;
+      str_stream << "new entry " << pkg_b.name << ":" << type_b.type << "/"
+                 << (*entry_b_iter)->name;
       EmitDiffLine(apk_b->GetSource(), str_stream.str());
       diff = true;
     } else {
+      const auto& entry_a = *entry_a_iter;
+      const auto& entry_b = *entry_a_iter;
       if (IsSymbolVisibilityDifferent(entry_a->visibility, entry_b->visibility)) {
         std::stringstream str_stream;
-        str_stream << pkg_a->name << ":" << type_a->type << "/" << entry_a->name
+        str_stream << pkg_a.name << ":" << type_a.type << "/" << entry_a->name
                    << " has different visibility (";
         if (entry_b->visibility.level == Visibility::Level::kPublic) {
           str_stream << "PUBLIC";
@@ -185,7 +198,7 @@
       } else if (IsIdDiff(entry_a->visibility.level, entry_a->id, entry_b->visibility.level,
                           entry_b->id)) {
         std::stringstream str_stream;
-        str_stream << pkg_a->name << ":" << type_a->type << "/" << entry_a->name
+        str_stream << pkg_a.name << ":" << type_a.type << "/" << entry_a->name
                    << " has different public ID (";
         if (entry_b->id) {
           str_stream << "0x" << std::hex << entry_b->id.value();
@@ -202,46 +215,43 @@
         EmitDiffLine(apk_b->GetSource(), str_stream.str());
         diff = true;
       }
-      diff |= EmitResourceEntryDiff(context, apk_a, pkg_a, type_a, entry_a.get(), apk_b, pkg_b,
-                                    type_b, entry_b);
-    }
-  }
-
-  // Check for any newly added entries.
-  for (std::unique_ptr<ResourceEntry>& entry_b : type_b->entries) {
-    ResourceEntry* entry_a = type_a->FindEntry(entry_b->name);
-    if (!entry_a) {
-      std::stringstream str_stream;
-      str_stream << "new entry " << pkg_b->name << ":" << type_b->type << "/" << entry_b->name;
-      EmitDiffLine(apk_b->GetSource(), str_stream.str());
-      diff = true;
+      diff |= EmitResourceEntryDiff(context, apk_a, pkg_a, type_a, entry_a, apk_b, pkg_b, type_b,
+                                    entry_b);
     }
   }
   return diff;
 }
 
 static bool EmitResourcePackageDiff(IAaptContext* context, LoadedApk* apk_a,
-                                    ResourceTablePackage* pkg_a, LoadedApk* apk_b,
-                                    ResourceTablePackage* pkg_b) {
+                                    const ResourceTablePackageView& pkg_a, LoadedApk* apk_b,
+                                    const ResourceTablePackageView& pkg_b) {
   bool diff = false;
-  for (std::unique_ptr<ResourceTableType>& type_a : pkg_a->types) {
-    ResourceTableType* type_b = pkg_b->FindType(type_a->type);
-    if (!type_b) {
+  auto type_a_iter = pkg_a.types.begin();
+  auto type_b_iter = pkg_b.types.begin();
+  while (type_a_iter != pkg_a.types.end() || type_b_iter != pkg_b.types.end()) {
+    if (type_b_iter == pkg_b.types.end()) {
+      // Type A contains a type that type B does not have.
       std::stringstream str_stream;
-      str_stream << "missing " << pkg_a->name << ":" << type_a->type;
+      str_stream << "missing " << pkg_a.name << ":" << type_a_iter->type;
       EmitDiffLine(apk_a->GetSource(), str_stream.str());
       diff = true;
+    } else if (type_a_iter == pkg_a.types.end()) {
+      // Type B contains a type that type A does not have.
+      std::stringstream str_stream;
+      str_stream << "new type " << pkg_b.name << ":" << type_b_iter->type;
+      EmitDiffLine(apk_b->GetSource(), str_stream.str());
+      diff = true;
     } else {
-      if (type_a->visibility_level != type_b->visibility_level) {
+      if (type_a_iter->visibility_level != type_b_iter->visibility_level) {
         std::stringstream str_stream;
-        str_stream << pkg_a->name << ":" << type_a->type << " has different visibility (";
-        if (type_b->visibility_level == Visibility::Level::kPublic) {
+        str_stream << pkg_a.name << ":" << type_a_iter->type << " has different visibility (";
+        if (type_b_iter->visibility_level == Visibility::Level::kPublic) {
           str_stream << "PUBLIC";
         } else {
           str_stream << "PRIVATE";
         }
         str_stream << " vs ";
-        if (type_a->visibility_level == Visibility::Level::kPublic) {
+        if (type_a_iter->visibility_level == Visibility::Level::kPublic) {
           str_stream << "PUBLIC";
         } else {
           str_stream << "PRIVATE";
@@ -249,18 +259,18 @@
         str_stream << ")";
         EmitDiffLine(apk_b->GetSource(), str_stream.str());
         diff = true;
-      } else if (IsIdDiff(type_a->visibility_level, type_a->id, type_b->visibility_level,
-                          type_b->id)) {
+      } else if (IsIdDiff(type_a_iter->visibility_level, type_a_iter->id,
+                          type_b_iter->visibility_level, type_b_iter->id)) {
         std::stringstream str_stream;
-        str_stream << pkg_a->name << ":" << type_a->type << " has different public ID (";
-        if (type_b->id) {
-          str_stream << "0x" << std::hex << type_b->id.value();
+        str_stream << pkg_a.name << ":" << type_a_iter->type << " has different public ID (";
+        if (type_b_iter->id) {
+          str_stream << "0x" << std::hex << type_b_iter->id.value();
         } else {
           str_stream << "none";
         }
         str_stream << " vs ";
-        if (type_a->id) {
-          str_stream << "0x " << std::hex << type_a->id.value();
+        if (type_a_iter->id) {
+          str_stream << "0x " << std::hex << type_a_iter->id.value();
         } else {
           str_stream << "none";
         }
@@ -268,47 +278,44 @@
         EmitDiffLine(apk_b->GetSource(), str_stream.str());
         diff = true;
       }
-      diff |= EmitResourceTypeDiff(context, apk_a, pkg_a, type_a.get(), apk_b, pkg_b, type_b);
-    }
-  }
-
-  // Check for any newly added types.
-  for (std::unique_ptr<ResourceTableType>& type_b : pkg_b->types) {
-    ResourceTableType* type_a = pkg_a->FindType(type_b->type);
-    if (!type_a) {
-      std::stringstream str_stream;
-      str_stream << "new type " << pkg_b->name << ":" << type_b->type;
-      EmitDiffLine(apk_b->GetSource(), str_stream.str());
-      diff = true;
+      diff |= EmitResourceTypeDiff(context, apk_a, pkg_a, *type_a_iter, apk_b, pkg_b, *type_b_iter);
     }
   }
   return diff;
 }
 
 static bool EmitResourceTableDiff(IAaptContext* context, LoadedApk* apk_a, LoadedApk* apk_b) {
-  ResourceTable* table_a = apk_a->GetResourceTable();
-  ResourceTable* table_b = apk_b->GetResourceTable();
+  const auto table_a = apk_a->GetResourceTable()->GetPartitionedView();
+  const auto table_b = apk_b->GetResourceTable()->GetPartitionedView();
 
   bool diff = false;
-  for (std::unique_ptr<ResourceTablePackage>& pkg_a : table_a->packages) {
-    ResourceTablePackage* pkg_b = table_b->FindPackage(pkg_a->name);
-    if (!pkg_b) {
+  auto package_a_iter = table_a.packages.begin();
+  auto package_b_iter = table_b.packages.begin();
+  while (package_a_iter != table_a.packages.end() || package_b_iter != table_b.packages.end()) {
+    if (package_b_iter == table_b.packages.end()) {
+      // Table A contains a package that table B does not have.
       std::stringstream str_stream;
-      str_stream << "missing package " << pkg_a->name;
+      str_stream << "missing package " << package_a_iter->name;
+      EmitDiffLine(apk_a->GetSource(), str_stream.str());
+      diff = true;
+    } else if (package_a_iter == table_a.packages.end()) {
+      // Table B contains a package that table A does not have.
+      std::stringstream str_stream;
+      str_stream << "new package " << package_b_iter->name;
       EmitDiffLine(apk_b->GetSource(), str_stream.str());
       diff = true;
     } else {
-      if (pkg_a->id != pkg_b->id) {
+      if (package_a_iter->id != package_b_iter->id) {
         std::stringstream str_stream;
-        str_stream << "package '" << pkg_a->name << "' has different id (";
-        if (pkg_b->id) {
-          str_stream << "0x" << std::hex << pkg_b->id.value();
+        str_stream << "package '" << package_a_iter->name << "' has different id (";
+        if (package_b_iter->id) {
+          str_stream << "0x" << std::hex << package_b_iter->id.value();
         } else {
           str_stream << "none";
         }
         str_stream << " vs ";
-        if (pkg_a->id) {
-          str_stream << "0x" << std::hex << pkg_a->id.value();
+        if (package_a_iter->id) {
+          str_stream << "0x" << std::hex << package_b_iter->id.value();
         } else {
           str_stream << "none";
         }
@@ -316,20 +323,10 @@
         EmitDiffLine(apk_b->GetSource(), str_stream.str());
         diff = true;
       }
-      diff |= EmitResourcePackageDiff(context, apk_a, pkg_a.get(), apk_b, pkg_b);
+      diff |= EmitResourcePackageDiff(context, apk_a, *package_a_iter, apk_b, *package_b_iter);
     }
   }
 
-  // Check for any newly added packages.
-  for (std::unique_ptr<ResourceTablePackage>& pkg_b : table_b->packages) {
-    ResourceTablePackage* pkg_a = table_a->FindPackage(pkg_b->name);
-    if (!pkg_a) {
-      std::stringstream str_stream;
-      str_stream << "new package " << pkg_b->name;
-      EmitDiffLine(apk_b->GetSource(), str_stream.str());
-      diff = true;
-    }
-  }
   return diff;
 }
 
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index 13e090d..ee6a764 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -25,6 +25,7 @@
 #include <vector>
 
 #include "android-base/errors.h"
+#include "android-base/expected.h"
 #include "android-base/file.h"
 #include "android-base/stringprintf.h"
 #include "androidfw/Locale.h"
@@ -74,10 +75,25 @@
 using ::aapt::io::FileInputStream;
 using ::android::ConfigDescription;
 using ::android::StringPiece;
+using ::android::base::expected;
 using ::android::base::StringPrintf;
+using ::android::base::unexpected;
 
 namespace aapt {
 
+namespace {
+
+expected<ResourceTablePackage*, const char*> GetStaticLibraryPackage(ResourceTable* table) {
+  // Resource tables built by aapt2 always contain one package. This is a post condition of
+  // VerifyNoExternalPackages.
+  if (table->packages.size() != 1u) {
+    return unexpected("static library contains more than one package");
+  }
+  return table->packages.back().get();
+}
+
+}  // namespace
+
 constexpr uint8_t kAndroidPackageId = 0x01;
 
 class LinkContext : public IAaptContext {
@@ -633,13 +649,18 @@
               const ResourceFile& file = doc->file;
               dst_path = ResourceUtils::BuildResourceFileName(file, context_->GetNameMangler());
 
-              std::unique_ptr<FileReference> file_ref =
+              auto file_ref =
                   util::make_unique<FileReference>(table->string_pool.MakeRef(dst_path));
               file_ref->SetSource(doc->file.source);
+
               // Update the output format of this XML file.
               file_ref->type = XmlFileTypeForOutputFormat(options_.output_format);
-              if (!table->AddResourceMangled(file.name, file.config, {}, std::move(file_ref),
-                                             context_->GetDiagnostics())) {
+              bool result = table->AddResource(NewResourceBuilder(file.name)
+                                                   .SetValue(std::move(file_ref), file.config)
+                                                   .SetAllowMangled(true)
+                                                   .Build(),
+                                               context_->GetDiagnostics());
+              if (!result) {
                 return false;
               }
             }
@@ -842,18 +863,15 @@
         ResourceTable* table = static_apk->GetResourceTable();
 
         // If we are using --no-static-lib-packages, we need to rename the package of this table to
-        // our compilation package.
-        if (options_.no_static_lib_packages) {
-          // Since package names can differ, and multiple packages can exist in a ResourceTable,
-          // we place the requirement that all static libraries are built with the package
-          // ID 0x7f. So if one is not found, this is an error.
-          if (ResourceTablePackage* pkg = table->FindPackageById(kAppPackageId)) {
-            pkg->name = context_->GetCompilationPackage();
-          } else {
-            context_->GetDiagnostics()->Error(DiagMessage(path)
-                                              << "no package with ID 0x7f found in static library");
+        // our compilation package so the symbol package name does not get mangled into the entry
+        // name.
+        if (options_.no_static_lib_packages && !table->packages.empty()) {
+          auto lib_package_result = GetStaticLibraryPackage(table);
+          if (!lib_package_result.has_value()) {
+            context_->GetDiagnostics()->Error(DiagMessage(path) << lib_package_result.error());
             return false;
           }
+          lib_package_result.value()->name = context_->GetCompilationPackage();
         }
 
         context_->GetExternalSymbols()->AppendSource(
@@ -982,8 +1000,7 @@
   // stripped, or there is an error and false is returned.
   bool VerifyNoExternalPackages() {
     auto is_ext_package_func = [&](const std::unique_ptr<ResourceTablePackage>& pkg) -> bool {
-      return context_->GetCompilationPackage() != pkg->name || !pkg->id ||
-             pkg->id.value() != context_->GetPackageId();
+      return context_->GetCompilationPackage() != pkg->name;
     };
 
     bool error = false;
@@ -1027,19 +1044,11 @@
   bool VerifyNoIdsSet() {
     for (const auto& package : final_table_.packages) {
       for (const auto& type : package->types) {
-        if (type->id) {
-          context_->GetDiagnostics()->Error(DiagMessage() << "type " << type->type << " has ID "
-                                                          << StringPrintf("%02x", type->id.value())
-                                                          << " assigned");
-          return false;
-        }
-
         for (const auto& entry : type->entries) {
           if (entry->id) {
             ResourceNameRef res_name(package->name, type->type, entry->name);
-            context_->GetDiagnostics()->Error(
-                DiagMessage() << "entry " << res_name << " has ID "
-                              << StringPrintf("%02x", entry->id.value()) << " assigned");
+            context_->GetDiagnostics()->Error(DiagMessage() << "resource " << res_name << " has ID "
+                                                            << entry->id.value() << " assigned");
             return false;
           }
         }
@@ -1313,12 +1322,17 @@
     }
 
     ResourceTable* table = apk->GetResourceTable();
-    ResourceTablePackage* pkg = table->FindPackageById(kAppPackageId);
-    if (!pkg) {
-      context_->GetDiagnostics()->Error(DiagMessage(input) << "static library has no package");
+    if (table->packages.empty()) {
+      return true;
+    }
+
+    auto lib_package_result = GetStaticLibraryPackage(table);
+    if (!lib_package_result.has_value()) {
+      context_->GetDiagnostics()->Error(DiagMessage(input) << lib_package_result.error());
       return false;
     }
 
+    ResourceTablePackage* pkg = lib_package_result.value();
     bool result;
     if (options_.no_static_lib_packages) {
       // Merge all resources as if they were in the compilation package. This is the old behavior
@@ -1365,11 +1379,11 @@
         res_name = mangled_name.value();
       }
 
-      std::unique_ptr<Id> id = util::make_unique<Id>();
+      auto id = util::make_unique<Id>();
       id->SetSource(source.WithLine(exported_symbol.line));
-      bool result =
-          final_table_.AddResourceMangled(res_name, ConfigDescription::DefaultConfig(),
-                                          std::string(), std::move(id), context_->GetDiagnostics());
+      bool result = final_table_.AddResource(
+          NewResourceBuilder(res_name).SetValue(std::move(id)).SetAllowMangled(true).Build(),
+          context_->GetDiagnostics());
       if (!result) {
         return false;
       }
@@ -1750,7 +1764,7 @@
     // anything else being generated, which includes the Java classes.
     // If required, the package name is modifed before flattening, and then modified back
     // to its original name.
-    ResourceTablePackage* package_to_rewrite = nullptr;
+    std::optional<ResourceTablePackageView> package_to_rewrite;
     // Pre-O, the platform treats negative resource IDs [those with a package ID of 0x80
     // or higher] as invalid. In order to work around this limitation, we allow the use
     // of traditionally reserved resource IDs [those between 0x02 and 0x7E]. Allow the
@@ -1764,10 +1778,11 @@
       // The base APK is included, and this is a feature split. If the base package is
       // the same as this package, then we are building an old style Android Instant Apps feature
       // split and must apply this workaround to avoid requiring namespaces support.
-      package_to_rewrite = table->FindPackage(context_->GetCompilationPackage());
-      if (package_to_rewrite != nullptr) {
+      auto table_view = table->GetPartitionedView();
+      if (!table_view.packages.empty() &&
+          table_view.packages.back().name == context_->GetCompilationPackage()) {
+        package_to_rewrite = std::move(table_view.packages.back());
         CHECK_EQ(1u, table->packages.size()) << "can't change name of package when > 1 package";
-
         std::string new_package_name =
             StringPrintf("%s.%s", package_to_rewrite->name.c_str(),
                          app_info_.split_name.value_or_default("feature").c_str());
@@ -1783,7 +1798,7 @@
 
     bool success = FlattenTable(table, options_.output_format, writer);
 
-    if (package_to_rewrite != nullptr) {
+    if (package_to_rewrite.has_value()) {
       // Change the name back.
       package_to_rewrite->name = context_->GetCompilationPackage();
       if (package_to_rewrite->id) {
@@ -1925,8 +1940,7 @@
             for (auto& entry : type->entries) {
               ResourceName name(package->name, type->type, entry->name);
               // The IDs are guaranteed to exist.
-              options_.stable_id_map[std::move(name)] =
-                  ResourceId(package->id.value(), type->id.value(), entry->id.value());
+              options_.stable_id_map[std::move(name)] = entry->id.value();
             }
           }
         }
diff --git a/tools/aapt2/cmd/Link_test.cpp b/tools/aapt2/cmd/Link_test.cpp
index 73072a9..27cbe88 100644
--- a/tools/aapt2/cmd/Link_test.cpp
+++ b/tools/aapt2/cmd/Link_test.cpp
@@ -47,6 +47,8 @@
   // Load the binary xml tree
   android::ResXMLTree tree;
   std::unique_ptr<LoadedApk> apk = LoadedApk::LoadApkFromPath(out_apk, &diag);
+  ASSERT_THAT(apk, Ne(nullptr));
+
   std::unique_ptr<io::IData> data = OpenFileAsData(apk.get(), "res/xml/test.xml");
   ASSERT_THAT(data, Ne(nullptr));
   AssertLoadXml(apk.get(), data.get(), &tree);
@@ -73,6 +75,8 @@
   // Load the binary xml tree
   android::ResXMLTree tree;
   std::unique_ptr<LoadedApk> apk = LoadedApk::LoadApkFromPath(out_apk, &diag);
+  ASSERT_THAT(apk, Ne(nullptr));
+
   std::unique_ptr<io::IData> data = OpenFileAsData(apk.get(), "res/xml/test.xml");
   ASSERT_THAT(data, Ne(nullptr));
   AssertLoadXml(apk.get(), data.get(), &tree);
@@ -208,6 +212,8 @@
   ASSERT_TRUE(Link(link_args, compiled_files_dir, &diag));
 
   std::unique_ptr<LoadedApk> apk = LoadedApk::LoadApkFromPath(out_apk, &diag);
+  ASSERT_THAT(apk, Ne(nullptr));
+
   const Style* actual_style = test::GetValue<Style>(
       apk->GetResourceTable(), std::string(kDefaultPackageName) + ":style/MyStyle");
   ASSERT_NE(actual_style, nullptr);
@@ -250,6 +256,8 @@
   ASSERT_TRUE(Link(link_args, compiled_files_dir, &diag));
 
   std::unique_ptr<LoadedApk> apk = LoadedApk::LoadApkFromPath(out_apk, &diag);
+  ASSERT_THAT(apk, Ne(nullptr));
+
   const Style* actual_style = test::GetValue<Style>(
       apk->GetResourceTable(), std::string(kDefaultPackageName) + ":style/MyStyle");
   ASSERT_NE(actual_style, nullptr);
diff --git a/tools/aapt2/compile/IdAssigner.cpp b/tools/aapt2/compile/IdAssigner.cpp
index 17c22c5..07db73d 100644
--- a/tools/aapt2/compile/IdAssigner.cpp
+++ b/tools/aapt2/compile/IdAssigner.cpp
@@ -17,76 +17,109 @@
 #include "compile/IdAssigner.h"
 
 #include <map>
+#include <unordered_map>
 
+#include "android-base/expected.h"
 #include "android-base/logging.h"
 
 #include "ResourceTable.h"
 #include "process/IResourceTableConsumer.h"
 #include "util/Util.h"
 
+using android::base::expected;
+using android::base::unexpected;
+
 namespace aapt {
 
-/**
- * Assigns the intended ID to the ResourceTablePackage, ResourceTableType, and
- * ResourceEntry,
- * as long as there is no existing ID or the ID is the same.
- */
-static bool AssignId(IDiagnostics* diag, const ResourceId& id,
-                     const ResourceName& name, ResourceTablePackage* pkg,
-                     ResourceTableType* type, ResourceEntry* entry) {
-  if (pkg->id.value() == id.package_id()) {
-    if (!type->id || type->id.value() == id.type_id()) {
-      type->id = id.type_id();
+namespace {
+template <typename T>
+using Result = expected<T, std::string>;
 
-      if (!entry->id || entry->id.value() == id.entry_id()) {
-        entry->id = id.entry_id();
-        return true;
-      }
-    }
+template <typename Id, typename Key>
+struct NextIdFinder {
+  explicit NextIdFinder(Id start_id = 0u) : next_id_(start_id){};
+
+  // Attempts to reserve an identifier for the specified key.
+  // If the identifier is already reserved by a different key, an error message is returned.
+  // Reserving identifiers must be completed before `NextId` is called for the first time.
+  Result<Id> ReserveId(Key key, Id id);
+
+  // Retrieves the next available identifier that has not been reserved.
+  std::optional<Id> NextId();
+
+ private:
+  // Attempts to set `next_id_` to the next available identifier that has not been reserved.
+  // Returns whether there were any available identifiers.
+  std::optional<Id> SkipToNextAvailableId();
+
+  Id next_id_;
+  bool next_id_called_ = false;
+  bool exhausted_ = false;
+  std::map<Id, Key> pre_assigned_ids_;
+  typename std::map<Id, Key>::iterator next_preassigned_id_;
+};
+
+struct TypeGroup {
+  explicit TypeGroup(uint8_t package_id, uint8_t type_id)
+      : package_id_(package_id), type_id_(type_id){};
+
+  // Attempts to reserve the resource id for the specified resource name.
+  // If the id is already reserved by a different name, an error message is returned.
+  // Reserving identifiers must be completed before `NextId` is called for the first time.
+  Result<std::monostate> ReserveId(const ResourceName& name, ResourceId id);
+
+  // Retrieves the next available resource id that has not been reserved.
+  Result<ResourceId> NextId();
+
+ private:
+  uint8_t package_id_;
+  uint8_t type_id_;
+  NextIdFinder<uint16_t, ResourceName> next_entry_id_;
+};
+
+struct IdAssignerContext {
+  IdAssignerContext(std::string package_name, uint8_t package_id)
+      : package_name_(std::move(package_name)), package_id_(package_id) {
   }
 
-  const ResourceId existing_id(pkg->id.value(), type->id ? type->id.value() : 0,
-                               entry->id ? entry->id.value() : 0);
-  diag->Error(DiagMessage() << "can't assign ID " << id << " to resource "
-                            << name << " with conflicting ID " << existing_id);
-  return false;
-}
+  // Attempts to reserve the resource id for the specified resource name.
+  // Returns whether the id was reserved successfully.
+  // Reserving identifiers must be completed before `NextId` is called for the first time.
+  bool ReserveId(const ResourceName& name, ResourceId id, IDiagnostics* diag);
+
+  // Retrieves the next available resource id that has not been reserved.
+  std::optional<ResourceId> NextId(const ResourceName& name, IDiagnostics* diag);
+
+ private:
+  std::string package_name_;
+  uint8_t package_id_;
+  std::map<ResourceType, TypeGroup> types_;
+  NextIdFinder<uint8_t, ResourceType> type_id_finder_ = NextIdFinder<uint8_t, ResourceType>(1);
+};
+
+}  // namespace
 
 bool IdAssigner::Consume(IAaptContext* context, ResourceTable* table) {
-  std::map<ResourceId, ResourceName> assigned_ids;
-
+  IdAssignerContext assigned_ids(context->GetCompilationPackage(), context->GetPackageId());
   for (auto& package : table->packages) {
-    CHECK(bool(package->id)) << "packages must have manually assigned IDs";
-
     for (auto& type : package->types) {
       for (auto& entry : type->entries) {
         const ResourceName name(package->name, type->type, entry->name);
+        if (entry->id) {
+          if (!assigned_ids.ReserveId(name, entry->id.value(), context->GetDiagnostics())) {
+            return false;
+          }
+        }
 
         if (assigned_id_map_) {
           // Assign the pre-assigned stable ID meant for this resource.
           const auto iter = assigned_id_map_->find(name);
           if (iter != assigned_id_map_->end()) {
             const ResourceId assigned_id = iter->second;
-            const bool result =
-                AssignId(context->GetDiagnostics(), assigned_id, name,
-                         package.get(), type.get(), entry.get());
-            if (!result) {
+            if (!assigned_ids.ReserveId(name, assigned_id, context->GetDiagnostics())) {
               return false;
             }
-          }
-        }
-
-        if (package->id && type->id && entry->id) {
-          // If the ID is set for this resource, then reserve it.
-          ResourceId resource_id(package->id.value(), type->id.value(),
-                                 entry->id.value());
-          auto result = assigned_ids.insert({resource_id, name});
-          const ResourceName& existing_name = result.first->second;
-          if (!result.second) {
-            context->GetDiagnostics()->Error(
-                DiagMessage() << "resource " << name << " has same ID "
-                              << resource_id << " as " << existing_name);
-            return false;
+            entry->id = assigned_id;
           }
         }
       }
@@ -94,125 +127,162 @@
   }
 
   if (assigned_id_map_) {
-    // Reserve all the IDs mentioned in the stable ID map. That way we won't
-    // assign
-    // IDs that were listed in the map if they don't exist in the table.
+    // Reserve all the IDs mentioned in the stable ID map. That way we won't assig IDs that were
+    // listed in the map if they don't exist in the table.
     for (const auto& stable_id_entry : *assigned_id_map_) {
       const ResourceName& pre_assigned_name = stable_id_entry.first;
       const ResourceId& pre_assigned_id = stable_id_entry.second;
-      auto result = assigned_ids.insert({pre_assigned_id, pre_assigned_name});
-      const ResourceName& existing_name = result.first->second;
-      if (!result.second && existing_name != pre_assigned_name) {
-        context->GetDiagnostics()->Error(
-            DiagMessage() << "stable ID " << pre_assigned_id << " for resource "
-                          << pre_assigned_name
-                          << " is already taken by resource " << existing_name);
+      if (!assigned_ids.ReserveId(pre_assigned_name, pre_assigned_id, context->GetDiagnostics())) {
         return false;
       }
     }
   }
 
-  // Assign any resources without IDs the next available ID. Gaps will be filled
-  // if possible,
+  // Assign any resources without IDs the next available ID. Gaps will be filled if possible,
   // unless those IDs have been reserved.
-
-  const auto assigned_ids_iter_end = assigned_ids.end();
   for (auto& package : table->packages) {
-    CHECK(bool(package->id)) << "packages must have manually assigned IDs";
-
-    // Build a half filled ResourceId object, which will be used to find the
-    // closest matching
-    // reserved ID in the assignedId map. From that point the next available
-    // type ID can be
-    // found.
-    ResourceId resource_id(package->id.value(), 0, 0);
-    uint8_t next_expected_type_id = 1;
-
-    // Find the closest matching ResourceId that is <= the one with only the
-    // package set.
-    auto next_type_iter = assigned_ids.lower_bound(resource_id);
     for (auto& type : package->types) {
-      if (!type->id) {
-        // We need to assign a type ID. Iterate over the reserved IDs until we
-        // find
-        // some type ID that is a distance of 2 greater than the last one we've
-        // seen.
-        // That means there is an available type ID between these reserved IDs.
-        while (next_type_iter != assigned_ids_iter_end) {
-          if (next_type_iter->first.package_id() != package->id.value()) {
-            break;
-          }
-
-          const uint8_t type_id = next_type_iter->first.type_id();
-          if (type_id > next_expected_type_id) {
-            // There is a gap in the type IDs, so use the missing one.
-            type->id = next_expected_type_id++;
-            break;
-          }
-
-          // Set our expectation to be the next type ID after the reserved one
-          // we
-          // just saw.
-          next_expected_type_id = type_id + 1;
-
-          // Move to the next reserved ID.
-          ++next_type_iter;
-        }
-
-        if (!type->id) {
-          // We must have hit the end of the reserved IDs and not found a gap.
-          // That means the next ID is available.
-          type->id = next_expected_type_id++;
-        }
-      }
-
-      resource_id = ResourceId(package->id.value(), type->id.value(), 0);
-      uint16_t next_expected_entry_id = 0;
-
-      // Find the closest matching ResourceId that is <= the one with only the
-      // package
-      // and type set.
-      auto next_entry_iter = assigned_ids.lower_bound(resource_id);
       for (auto& entry : type->entries) {
-        if (!entry->id) {
-          // We need to assign an entry ID. Iterate over the reserved IDs until
-          // we find
-          // some entry ID that is a distance of 2 greater than the last one
-          // we've seen.
-          // That means there is an available entry ID between these reserved
-          // IDs.
-          while (next_entry_iter != assigned_ids_iter_end) {
-            if (next_entry_iter->first.package_id() != package->id.value() ||
-                next_entry_iter->first.type_id() != type->id.value()) {
-              break;
-            }
-
-            const uint16_t entry_id = next_entry_iter->first.entry_id();
-            if (entry_id > next_expected_entry_id) {
-              // There is a gap in the entry IDs, so use the missing one.
-              entry->id = next_expected_entry_id++;
-              break;
-            }
-
-            // Set our expectation to be the next type ID after the reserved one
-            // we
-            // just saw.
-            next_expected_entry_id = entry_id + 1;
-
-            // Move to the next reserved entry ID.
-            ++next_entry_iter;
-          }
-
-          if (!entry->id) {
-            // We must have hit the end of the reserved IDs and not found a gap.
-            // That means the next ID is available.
-            entry->id = next_expected_entry_id++;
-          }
+        const ResourceName name(package->name, type->type, entry->name);
+        if (entry->id) {
+          continue;
         }
+        auto id = assigned_ids.NextId(name, context->GetDiagnostics());
+        if (!id.has_value()) {
+          return false;
+        }
+        entry->id = id.value();
       }
     }
   }
   return true;
 }
 
+namespace {
+template <typename Id, typename Key>
+Result<Id> NextIdFinder<Id, Key>::ReserveId(Key key, Id id) {
+  CHECK(!next_id_called_) << "ReserveId cannot be called after NextId";
+  auto assign_result = pre_assigned_ids_.emplace(id, key);
+  if (!assign_result.second && assign_result.first->second != key) {
+    std::stringstream error;
+    error << "ID " << id << " is already assigned to " << assign_result.first->second;
+    return unexpected(error.str());
+  }
+  return id;
+}
+
+template <typename Id, typename Key>
+std::optional<Id> NextIdFinder<Id, Key>::NextId() {
+  if (!next_id_called_) {
+    next_id_called_ = true;
+    next_preassigned_id_ = pre_assigned_ids_.begin();
+  }
+  return SkipToNextAvailableId();
+}
+
+template <typename Id, typename Key>
+std::optional<Id> NextIdFinder<Id, Key>::SkipToNextAvailableId() {
+  if (exhausted_) {
+    return {};
+  }
+  while (next_preassigned_id_ != pre_assigned_ids_.end()) {
+    if (next_preassigned_id_->first == next_id_) {
+      if (next_id_ == std::numeric_limits<Id>::max()) {
+        // The last identifier was reserved so there are no more available identifiers.
+        exhausted_ = true;
+        return {};
+      }
+      ++next_id_;
+      ++next_preassigned_id_;
+      continue;
+    }
+    CHECK(next_preassigned_id_->first > next_id_) << "Preassigned IDs are not in sorted order";
+    break;
+  }
+  if (next_id_ == std::numeric_limits<Id>::max()) {
+    // There are no more identifiers after this one, but this one is still available so return it.
+    exhausted_ = true;
+  }
+  return next_id_++;
+}
+
+Result<std::monostate> TypeGroup::ReserveId(const ResourceName& name, ResourceId id) {
+  if (type_id_ != id.type_id()) {
+    // Currently there cannot be multiple type ids for a single type.
+    std::stringstream error;
+    error << "type '" << name.type << "' already has ID " << id.type_id();
+    return unexpected(error.str());
+  }
+
+  auto assign_result = next_entry_id_.ReserveId(name, id.entry_id());
+  if (!assign_result.has_value()) {
+    std::stringstream error;
+    error << "entry " << assign_result.error();
+    return unexpected(error.str());
+  }
+  return {};
+}
+
+Result<ResourceId> TypeGroup::NextId() {
+  auto entry_id = next_entry_id_.NextId();
+  if (!entry_id.has_value()) {
+    std::stringstream error;
+    error << "resource type ID has exceeded the maximum number of resource entries ("
+          << (std::numeric_limits<uint16_t>::max() + 1u) << ")";
+    return unexpected(error.str());
+  }
+  return ResourceId(package_id_, type_id_, entry_id.value());
+}
+
+bool IdAssignerContext::ReserveId(const ResourceName& name, ResourceId id, IDiagnostics* diag) {
+  if (package_id_ != id.package_id()) {
+    diag->Error(DiagMessage() << "can't assign ID " << id << " to resource " << name
+                              << " because package already has ID " << id.package_id());
+    return false;
+  }
+
+  auto type = types_.find(name.type);
+  if (type == types_.end()) {
+    // The type has not been assigned an id yet. Ensure that the specified id is not being used by
+    // another type.
+    auto assign_result = type_id_finder_.ReserveId(name.type, id.type_id());
+    if (!assign_result.has_value()) {
+      diag->Error(DiagMessage() << "can't assign ID " << id << " to resource " << name
+                                << " because type " << assign_result.error());
+      return false;
+    }
+    type = types_.emplace(name.type, TypeGroup(package_id_, id.type_id())).first;
+  }
+
+  auto assign_result = type->second.ReserveId(name, id);
+  if (!assign_result.has_value()) {
+    diag->Error(DiagMessage() << "can't assign ID " << id << " to resource " << name << " because "
+                              << assign_result.error());
+    return false;
+  }
+
+  return true;
+}
+
+std::optional<ResourceId> IdAssignerContext::NextId(const ResourceName& name, IDiagnostics* diag) {
+  // The package name is not known during the compile stage.
+  // Resources without a package name are considered a part of the app being linked.
+  CHECK(name.package.empty() || name.package == package_name_);
+  auto type = types_.find(name.type);
+  if (type == types_.end()) {
+    auto next_type_id = type_id_finder_.NextId();
+    CHECK(next_type_id.has_value()) << "resource type IDs allocated have exceeded maximum (256)";
+    type = types_.emplace(name.type, TypeGroup(package_id_, next_type_id.value())).first;
+  }
+
+  auto assign_result = type->second.NextId();
+  if (!assign_result.has_value()) {
+    diag->Error(DiagMessage() << "can't assign resource ID to resource " << name << " because "
+                              << assign_result.error());
+    return {};
+  }
+  return assign_result.value();
+}
+}  // namespace
+
 }  // namespace aapt
diff --git a/tools/aapt2/compile/IdAssigner_test.cpp b/tools/aapt2/compile/IdAssigner_test.cpp
index 5cff004..0065a22 100644
--- a/tools/aapt2/compile/IdAssigner_test.cpp
+++ b/tools/aapt2/compile/IdAssigner_test.cpp
@@ -20,42 +20,40 @@
 
 namespace aapt {
 
+struct IdAssignerTests : public ::testing::Test {
+  void SetUp() override {
+    context = test::ContextBuilder().SetCompilationPackage("android").SetPackageId(0x01).Build();
+  }
+  std::unique_ptr<IAaptContext> context;
+};
+
 ::testing::AssertionResult VerifyIds(ResourceTable* table);
 
-TEST(IdAssignerTest, AssignIds) {
-  std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-                                             .AddSimple("android:attr/foo")
-                                             .AddSimple("android:attr/bar")
-                                             .AddSimple("android:id/foo")
-                                             .SetPackageId("android", 0x01)
-                                             .Build();
-
-  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
+TEST_F(IdAssignerTests, AssignIds) {
+  auto table = test::ResourceTableBuilder()
+                   .AddSimple("android:attr/foo")
+                   .AddSimple("android:attr/bar")
+                   .AddSimple("android:id/foo")
+                   .Build();
   IdAssigner assigner;
 
   ASSERT_TRUE(assigner.Consume(context.get(), table.get()));
   ASSERT_TRUE(VerifyIds(table.get()));
 }
 
-TEST(IdAssignerTest, AssignIdsWithReservedIds) {
-  std::unique_ptr<ResourceTable> table =
-      test::ResourceTableBuilder()
-          .AddSimple("android:id/foo", ResourceId(0x01010000))
-          .AddSimple("android:dimen/two")
-          .AddSimple("android:integer/three")
-          .AddSimple("android:string/five")
-          .AddSimple("android:attr/fun", ResourceId(0x01040000))
-          .AddSimple("android:attr/foo", ResourceId(0x01040006))
-          .AddSimple("android:attr/bar")
-          .AddSimple("android:attr/baz")
-          .AddSimple("app:id/biz")
-          .SetPackageId("android", 0x01)
-          .SetPackageId("app", 0x7f)
-          .Build();
+TEST_F(IdAssignerTests, AssignIdsWithReservedIds) {
+  auto table = test::ResourceTableBuilder()
+                   .AddSimple("android:id/foo", ResourceId(0x01010000))
+                   .AddSimple("android:dimen/two")
+                   .AddSimple("android:integer/three")
+                   .AddSimple("android:string/five")
+                   .AddSimple("android:attr/fun", ResourceId(0x01040000))
+                   .AddSimple("android:attr/foo", ResourceId(0x01040006))
+                   .AddSimple("android:attr/bar")
+                   .AddSimple("android:attr/baz")
+                   .Build();
 
-  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
   IdAssigner assigner;
-
   ASSERT_TRUE(assigner.Consume(context.get(), table.get()));
   ASSERT_TRUE(VerifyIds(table.get()));
 
@@ -65,12 +63,12 @@
 
   maybe_result = table->FindResource(test::ParseNameOrDie("android:dimen/two"));
   ASSERT_TRUE(maybe_result);
-  EXPECT_EQ(make_value<uint8_t>(2), maybe_result.value().type->id);
+  EXPECT_EQ(make_value<ResourceId>(0x01020000), maybe_result.value().entry->id);
 
   maybe_result =
       table->FindResource(test::ParseNameOrDie("android:integer/three"));
   ASSERT_TRUE(maybe_result);
-  EXPECT_EQ(make_value<uint8_t>(3), maybe_result.value().type->id);
+  EXPECT_EQ(make_value<ResourceId>(0x01030000), maybe_result.value().entry->id);
 
   // Expect to bypass the reserved 0x0104XXXX IDs and use the next 0x0105XXXX
   // IDs.
@@ -78,103 +76,126 @@
   maybe_result =
       table->FindResource(test::ParseNameOrDie("android:string/five"));
   ASSERT_TRUE(maybe_result);
-  EXPECT_EQ(make_value<uint8_t>(5), maybe_result.value().type->id);
+  EXPECT_EQ(make_value<ResourceId>(0x01050000), maybe_result.value().entry->id);
 
   // Expect to fill in the gaps between 0x01040000 and 0x01040006.
 
   maybe_result = table->FindResource(test::ParseNameOrDie("android:attr/bar"));
   ASSERT_TRUE(maybe_result);
-  EXPECT_EQ(make_value<uint16_t>(1), maybe_result.value().entry->id);
+  EXPECT_EQ(make_value<ResourceId>(0x01040001), maybe_result.value().entry->id);
 
   maybe_result = table->FindResource(test::ParseNameOrDie("android:attr/baz"));
   ASSERT_TRUE(maybe_result);
-  EXPECT_EQ(make_value<uint16_t>(2), maybe_result.value().entry->id);
+  EXPECT_EQ(make_value<ResourceId>(0x01040002), maybe_result.value().entry->id);
 }
 
-TEST(IdAssignerTest, FailWhenNonUniqueIdsAssigned) {
-  std::unique_ptr<ResourceTable> table =
-      test::ResourceTableBuilder()
-          .AddSimple("android:attr/foo", ResourceId(0x01040006))
-          .AddSimple("android:attr/bar", ResourceId(0x01040006))
-          .SetPackageId("android", 0x01)
-          .SetPackageId("app", 0x7f)
-          .Build();
-
-  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
+TEST_F(IdAssignerTests, FailWhenNonUniqueIdsAssigned) {
+  auto table = test::ResourceTableBuilder()
+                   .AddSimple("android:attr/foo", ResourceId(0x01040006))
+                   .AddSimple("android:attr/bar", ResourceId(0x01040006))
+                   .Build();
   IdAssigner assigner;
-
   ASSERT_FALSE(assigner.Consume(context.get(), table.get()));
 }
 
-TEST(IdAssignerTest, AssignIdsWithIdMap) {
-  std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-                                             .AddSimple("android:attr/foo")
-                                             .AddSimple("android:attr/bar")
-                                             .SetPackageId("android", 0x01)
-                                             .Build();
-
-  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
+TEST_F(IdAssignerTests, AssignIdsWithIdMap) {
+  auto table = test::ResourceTableBuilder()
+                   .AddSimple("android:attr/foo")
+                   .AddSimple("android:attr/bar")
+                   .Build();
   std::unordered_map<ResourceName, ResourceId> id_map = {
       {test::ParseNameOrDie("android:attr/foo"), ResourceId(0x01010002)}};
   IdAssigner assigner(&id_map);
   ASSERT_TRUE(assigner.Consume(context.get(), table.get()));
   ASSERT_TRUE(VerifyIds(table.get()));
-  Maybe<ResourceTable::SearchResult> result =
-      table->FindResource(test::ParseNameOrDie("android:attr/foo"));
+  auto result = table->FindResource(test::ParseNameOrDie("android:attr/foo"));
   ASSERT_TRUE(result);
 
   const ResourceTable::SearchResult& search_result = result.value();
-  EXPECT_EQ(make_value<uint8_t>(0x01), search_result.package->id);
-  EXPECT_EQ(make_value<uint8_t>(0x01), search_result.type->id);
-  EXPECT_EQ(make_value<uint16_t>(0x0002), search_result.entry->id);
+  EXPECT_EQ(make_value<ResourceId>(0x01010002), search_result.entry->id);
+}
+
+TEST_F(IdAssignerTests, UseAllEntryIds) {
+  ResourceTable table;
+  const size_t max_entry_id = std::numeric_limits<uint16_t>::max();
+  for (size_t i = 0; i <= max_entry_id; i++) {
+    ASSERT_TRUE(
+        table.AddResource(NewResourceBuilder("android:attr/res" + std::to_string(i)).Build(),
+                          context->GetDiagnostics()));
+  }
+  IdAssigner assigner;
+  ASSERT_TRUE(assigner.Consume(context.get(), &table));
+}
+
+TEST_F(IdAssignerTests, ExaustEntryIds) {
+  ResourceTable table;
+  const size_t max_entry_id = std::numeric_limits<uint16_t>::max() + 1u;
+  for (size_t i = 0; i <= max_entry_id; i++) {
+    ASSERT_TRUE(
+        table.AddResource(NewResourceBuilder("android:attr/res" + std::to_string(i)).Build(),
+                          context->GetDiagnostics()));
+  }
+  IdAssigner assigner;
+  ASSERT_FALSE(assigner.Consume(context.get(), &table));
+}
+
+TEST_F(IdAssignerTests, ExaustEntryIdsLastIdIsPublic) {
+  ResourceTable table;
+  ASSERT_TRUE(table.AddResource(NewResourceBuilder("android:attr/res").SetId(0x0101ffff).Build(),
+                                context->GetDiagnostics()));
+  const size_t max_entry_id = std::numeric_limits<uint16_t>::max();
+  for (size_t i = 0; i <= max_entry_id; i++) {
+    ASSERT_TRUE(
+        table.AddResource(NewResourceBuilder("android:attr/res" + std::to_string(i)).Build(),
+                          context->GetDiagnostics()));
+  }
+  IdAssigner assigner;
+  ASSERT_FALSE(assigner.Consume(context.get(), &table));
 }
 
 ::testing::AssertionResult VerifyIds(ResourceTable* table) {
   std::set<uint8_t> package_ids;
-  for (auto& package : table->packages) {
-    if (!package->id) {
-      return ::testing::AssertionFailure() << "package " << package->name
-                                           << " has no ID";
+  auto table_view = table->GetPartitionedView();
+  for (auto& package : table_view.packages) {
+    if (!package.id) {
+      return ::testing::AssertionFailure() << "package " << package.name << " has no ID";
     }
 
-    if (!package_ids.insert(package->id.value()).second) {
-      return ::testing::AssertionFailure()
-             << "package " << package->name << " has non-unique ID " << std::hex
-             << (int)package->id.value() << std::dec;
+    if (!package_ids.insert(package.id.value()).second) {
+      return ::testing::AssertionFailure() << "package " << package.name << " has non-unique ID "
+                                           << std::hex << (int)package.id.value() << std::dec;
     }
   }
 
-  for (auto& package : table->packages) {
+  for (auto& package : table_view.packages) {
     std::set<uint8_t> type_ids;
-    for (auto& type : package->types) {
-      if (!type->id) {
-        return ::testing::AssertionFailure() << "type " << type->type
-                                             << " of package " << package->name
-                                             << " has no ID";
+    for (auto& type : package.types) {
+      if (!type.id) {
+        return ::testing::AssertionFailure()
+               << "type " << type.type << " of package " << package.name << " has no ID";
       }
 
-      if (!type_ids.insert(type->id.value()).second) {
+      if (!type_ids.insert(type.id.value()).second) {
         return ::testing::AssertionFailure()
-               << "type " << type->type << " of package " << package->name
-               << " has non-unique ID " << std::hex << (int)type->id.value()
-               << std::dec;
+               << "type " << type.type << " of package " << package.name << " has non-unique ID "
+               << std::hex << (int)type.id.value() << std::dec;
       }
     }
 
-    for (auto& type : package->types) {
-      std::set<uint16_t> entry_ids;
-      for (auto& entry : type->entries) {
+    for (auto& type : package.types) {
+      std::set<ResourceId> entry_ids;
+      for (auto& entry : type.entries) {
         if (!entry->id) {
           return ::testing::AssertionFailure()
-                 << "entry " << entry->name << " of type " << type->type
-                 << " of package " << package->name << " has no ID";
+                 << "entry " << entry->name << " of type " << type.type << " of package "
+                 << package.name << " has no ID";
         }
 
         if (!entry_ids.insert(entry->id.value()).second) {
           return ::testing::AssertionFailure()
-                 << "entry " << entry->name << " of type " << type->type
-                 << " of package " << package->name << " has non-unique ID "
-                 << std::hex << (int)entry->id.value() << std::dec;
+                 << "entry " << entry->name << " of type " << type.type << " of package "
+                 << package.name << " has non-unique ID " << std::hex << entry->id.value()
+                 << std::dec;
         }
       }
     }
diff --git a/tools/aapt2/compile/PseudolocaleGenerator_test.cpp b/tools/aapt2/compile/PseudolocaleGenerator_test.cpp
index e816c86..432d7bf 100644
--- a/tools/aapt2/compile/PseudolocaleGenerator_test.cpp
+++ b/tools/aapt2/compile/PseudolocaleGenerator_test.cpp
@@ -236,13 +236,14 @@
 
 TEST(PseudolocaleGeneratorTest, PluralsArePseudolocalized) {
   std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
-  std::unique_ptr<ResourceTable> table =
-      test::ResourceTableBuilder().SetPackageId("com.pkg", 0x7F).Build();
+  std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder().Build();
   std::unique_ptr<Plural> plural = util::make_unique<Plural>();
   plural->values = {util::make_unique<String>(table->string_pool.MakeRef("zero")),
                     util::make_unique<String>(table->string_pool.MakeRef("one"))};
-  ASSERT_TRUE(table->AddResource(test::ParseNameOrDie("com.pkg:plurals/foo"), ConfigDescription{},
-                                 {}, std::move(plural), context->GetDiagnostics()));
+  ASSERT_TRUE(table->AddResource(NewResourceBuilder(test::ParseNameOrDie("com.pkg:plurals/foo"))
+                                     .SetValue(std::move(plural))
+                                     .Build(),
+                                 context->GetDiagnostics()));
   std::unique_ptr<Plural> expected = util::make_unique<Plural>();
   expected->values = {util::make_unique<String>(table->string_pool.MakeRef("[žéŕö one]")),
                       util::make_unique<String>(table->string_pool.MakeRef("[öñé one]"))};
@@ -252,6 +253,7 @@
 
   const auto* actual = test::GetValueForConfig<Plural>(table.get(), "com.pkg:plurals/foo",
                                                        test::ParseConfigOrDie("en-rXA"));
+  ASSERT_NE(nullptr, actual);
   EXPECT_TRUE(actual->Equals(expected.get()));
 }
 
@@ -273,11 +275,14 @@
     auto string = util::make_unique<String>(table->string_pool.MakeRef(original_style.str));
     string->untranslatable_sections.push_back(UntranslatableSection{6u, 11u});
 
-    ASSERT_TRUE(table->AddResource(test::ParseNameOrDie("android:string/foo"), ConfigDescription{},
-                                   {} /* product */, std::move(styled_string),
+    ASSERT_TRUE(table->AddResource(NewResourceBuilder(test::ParseNameOrDie("android:string/foo"))
+                                       .SetValue(std::move(styled_string))
+                                       .Build(),
                                    context->GetDiagnostics()));
-    ASSERT_TRUE(table->AddResource(test::ParseNameOrDie("android:string/bar"), ConfigDescription{},
-                                   {} /* product */, std::move(string), context->GetDiagnostics()));
+    ASSERT_TRUE(table->AddResource(NewResourceBuilder(test::ParseNameOrDie("android:string/bar"))
+                                       .SetValue(std::move(string))
+                                       .Build(),
+                                   context->GetDiagnostics()));
   }
 
   PseudolocaleGenerator generator;
diff --git a/tools/aapt2/dump/DumpManifest.cpp b/tools/aapt2/dump/DumpManifest.cpp
index cc1cf7f..f29c918 100644
--- a/tools/aapt2/dump/DumpManifest.cpp
+++ b/tools/aapt2/dump/DumpManifest.cpp
@@ -191,18 +191,14 @@
                          const ConfigDescription& config = DefaultConfig()) {
       if (table) {
         for (auto& package : table->packages) {
-          if (package->id && package->id.value() == res_id.package_id()) {
             for (auto& type : package->types) {
-              if (type->id && type->id.value() == res_id.type_id()) {
-                for (auto& entry : type->entries) {
-                  if (entry->id && entry->id.value() == res_id.entry_id()) {
-                    if (auto value = BestConfigValue(entry.get(), config)) {
-                      return value;
-                    }
+              for (auto& entry : type->entries) {
+                if (entry->id && entry->id.value() == res_id.id) {
+                  if (auto value = BestConfigValue(entry.get(), config)) {
+                    return value;
                   }
                 }
               }
-            }
           }
         }
       }
diff --git a/tools/aapt2/format/binary/BinaryResourceParser.cpp b/tools/aapt2/format/binary/BinaryResourceParser.cpp
index cccd9fa..bfb8d58 100644
--- a/tools/aapt2/format/binary/BinaryResourceParser.cpp
+++ b/tools/aapt2/format/binary/BinaryResourceParser.cpp
@@ -192,8 +192,7 @@
   std::u16string package_name = strcpy16_dtoh((const char16_t*)package_header->name,
                                               arraysize(package_header->name));
 
-  ResourceTablePackage* package =
-      table_->CreatePackage(util::Utf16ToUtf8(package_name), static_cast<uint8_t>(package_id));
+  ResourceTablePackage* package = table_->FindOrCreatePackage(util::Utf16ToUtf8(package_name));
   if (!package) {
     diag_->Error(DiagMessage(source_)
                  << "incompatible package '" << package_name << "' with ID " << package_id);
@@ -232,13 +231,13 @@
         break;
 
       case android::RES_TABLE_TYPE_SPEC_TYPE:
-        if (!ParseTypeSpec(package, parser.chunk())) {
+        if (!ParseTypeSpec(package, parser.chunk(), package_id)) {
           return false;
         }
         break;
 
       case android::RES_TABLE_TYPE_TYPE:
-        if (!ParseType(package, parser.chunk())) {
+        if (!ParseType(package, parser.chunk(), package_id)) {
           return false;
         }
         break;
@@ -276,7 +275,7 @@
 }
 
 bool BinaryResourceParser::ParseTypeSpec(const ResourceTablePackage* package,
-                                         const ResChunk_header* chunk) {
+                                         const ResChunk_header* chunk, uint8_t package_id) {
   if (type_pool_.getError() != NO_ERROR) {
     diag_->Error(DiagMessage(source_) << "missing type string pool");
     return false;
@@ -317,14 +316,14 @@
   const uint32_t* type_spec_flags = reinterpret_cast<const uint32_t*>(
       reinterpret_cast<uintptr_t>(type_spec) + util::DeviceToHost16(type_spec->header.headerSize));
   for (size_t i = 0; i < entry_count; i++) {
-    ResourceId id(package->id.value_or_default(0x0), type_spec->id, static_cast<size_t>(i));
+    ResourceId id(package_id, type_spec->id, static_cast<size_t>(i));
     entry_type_spec_flags_[id] = util::DeviceToHost32(type_spec_flags[i]);
   }
   return true;
 }
 
 bool BinaryResourceParser::ParseType(const ResourceTablePackage* package,
-                                     const ResChunk_header* chunk) {
+                                     const ResChunk_header* chunk, uint8_t package_id) {
   if (type_pool_.getError() != NO_ERROR) {
     diag_->Error(DiagMessage(source_) << "missing type string pool");
     return false;
@@ -354,13 +353,9 @@
   const std::string type_str = util::GetString(type_pool_, type->id - 1);
   const ResourceType* parsed_type = ParseResourceType(type_str);
   if (!parsed_type) {
-    // Be lenient on the name of the type if the table is lenient on resource validation.
-    bool log_error = table_->GetValidateResources();
-    if (log_error) {
-      diag_->Error(DiagMessage(source_) << "invalid type name '" << type_str
-                                        << "' for type with ID " << type->id);
-    }
-    return !log_error;
+    diag_->Warn(DiagMessage(source_)
+                << "invalid type name '" << type_str << "' for type with ID " << type->id);
+    return true;
   }
 
   TypeVariant tv(type);
@@ -372,7 +367,7 @@
 
     const ResourceName name(package->name, *parsed_type,
                             util::GetString(key_pool_, util::DeviceToHost32(entry->key.index)));
-    const ResourceId res_id(package->id.value(), type->id, static_cast<uint16_t>(it.index()));
+    const ResourceId res_id(package_id, type->id, static_cast<uint16_t>(it.index()));
 
     std::unique_ptr<Value> resource_value;
     if (entry->flags & ResTable_entry::FLAG_COMPLEX) {
@@ -392,17 +387,13 @@
       return false;
     }
 
-    if (!table_->AddResourceWithIdMangled(name, res_id, config, {}, std::move(resource_value),
-                                          diag_)) {
-      return false;
-    }
+    NewResourceBuilder res_builder(name);
+    res_builder.SetValue(std::move(resource_value), config)
+        .SetId(res_id, OnIdConflict::CREATE_ENTRY)
+        .SetAllowMangled(true);
 
     if (entry->flags & ResTable_entry::FLAG_PUBLIC) {
-      Visibility visibility;
-      visibility.level = Visibility::Level::kPublic;
-      if (!table_->SetVisibilityWithIdMangled(name, visibility, res_id, diag_)) {
-        return false;
-      }
+      res_builder.SetVisibility(Visibility{Visibility::Level::kPublic});
 
       // Erase the ID from the map once processed, so that we don't mark the same symbol more than
       // once.
@@ -415,6 +406,10 @@
     if (cache_iter == id_index_.end()) {
       id_index_.insert({res_id, name});
     }
+
+    if (!table_->AddResource(res_builder.Build(), diag_)) {
+      return false;
+    }
   }
   return true;
 }
@@ -472,7 +467,12 @@
 
         OverlayableItem overlayable_item(overlayable);
         overlayable_item.policies = policy_header->policy_flags;
-        if (!table_->SetOverlayable(iter->second, overlayable_item, diag_)) {
+        if (!table_->AddResource(NewResourceBuilder(iter->second)
+                                     .SetId(res_id, OnIdConflict::CREATE_ENTRY)
+                                     .SetOverlayable(std::move(overlayable_item))
+                                     .SetAllowMangled(true)
+                                     .Build(),
+                                 diag_)) {
           return false;
         }
       }
diff --git a/tools/aapt2/format/binary/BinaryResourceParser.h b/tools/aapt2/format/binary/BinaryResourceParser.h
index a2eee50..13dd982 100644
--- a/tools/aapt2/format/binary/BinaryResourceParser.h
+++ b/tools/aapt2/format/binary/BinaryResourceParser.h
@@ -51,8 +51,10 @@
 
   bool ParseTable(const android::ResChunk_header* chunk);
   bool ParsePackage(const android::ResChunk_header* chunk);
-  bool ParseTypeSpec(const ResourceTablePackage* package, const android::ResChunk_header* chunk);
-  bool ParseType(const ResourceTablePackage* package, const android::ResChunk_header* chunk);
+  bool ParseTypeSpec(const ResourceTablePackage* package, const android::ResChunk_header* chunk,
+                     uint8_t package_id);
+  bool ParseType(const ResourceTablePackage* package, const android::ResChunk_header* chunk,
+                 uint8_t package_id);
   bool ParseLibrary(const android::ResChunk_header* chunk);
   bool ParseOverlayable(const android::ResChunk_header* chunk);
 
diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp
index 4b90b4f..5fea897 100644
--- a/tools/aapt2/format/binary/TableFlattener.cpp
+++ b/tools/aapt2/format/binary/TableFlattener.cpp
@@ -59,35 +59,35 @@
   dst[i] = 0;
 }
 
-static bool cmp_style_entries(const Style::Entry& a, const Style::Entry& b) {
-  if (a.key.id) {
-    if (b.key.id) {
-      return cmp_ids_dynamic_after_framework(a.key.id.value(), b.key.id.value());
+static bool cmp_style_entries(const Style::Entry* a, const Style::Entry* b) {
+  if (a->key.id) {
+    if (b->key.id) {
+      return cmp_ids_dynamic_after_framework(a->key.id.value(), b->key.id.value());
     }
     return true;
-  } else if (!b.key.id) {
-    return a.key.name.value() < b.key.name.value();
+  } else if (!b->key.id) {
+    return a->key.name.value() < b->key.name.value();
   }
   return false;
 }
 
 struct FlatEntry {
-  ResourceEntry* entry;
-  Value* value;
+  const ResourceEntry* entry;
+  const Value* value;
 
   // The entry string pool index to the entry's name.
   uint32_t entry_key;
 };
 
-class MapFlattenVisitor : public ValueVisitor {
+class MapFlattenVisitor : public ConstValueVisitor {
  public:
-  using ValueVisitor::Visit;
+  using ConstValueVisitor::Visit;
 
   MapFlattenVisitor(ResTable_entry_ext* out_entry, BigBuffer* buffer)
       : out_entry_(out_entry), buffer_(buffer) {
   }
 
-  void Visit(Attribute* attr) override {
+  void Visit(const Attribute* attr) override {
     {
       Reference key = Reference(ResourceId(ResTable_map::ATTR_TYPE));
       BinaryPrimitive val(Res_value::TYPE_INT_DEC, attr->type_mask);
@@ -106,13 +106,13 @@
       FlattenEntry(&key, &val);
     }
 
-    for (Attribute::Symbol& s : attr->symbols) {
+    for (const Attribute::Symbol& s : attr->symbols) {
       BinaryPrimitive val(s.type, s.value);
       FlattenEntry(&s.symbol, &val);
     }
   }
 
-  void Visit(Style* style) override {
+  void Visit(const Style* style) override {
     if (style->parent) {
       const Reference& parent_ref = style->parent.value();
       CHECK(bool(parent_ref.id)) << "parent has no ID";
@@ -120,21 +120,26 @@
     }
 
     // Sort the style.
-    std::sort(style->entries.begin(), style->entries.end(), cmp_style_entries);
+    std::vector<const Style::Entry*> sorted_entries;
+    for (const auto& entry : style->entries) {
+      sorted_entries.emplace_back(&entry);
+    }
 
-    for (Style::Entry& entry : style->entries) {
-      FlattenEntry(&entry.key, entry.value.get());
+    std::sort(sorted_entries.begin(), sorted_entries.end(), cmp_style_entries);
+
+    for (const Style::Entry* entry : sorted_entries) {
+      FlattenEntry(&entry->key, entry->value.get());
     }
   }
 
-  void Visit(Styleable* styleable) override {
+  void Visit(const Styleable* styleable) override {
     for (auto& attr_ref : styleable->entries) {
       BinaryPrimitive val(Res_value{});
       FlattenEntry(&attr_ref, &val);
     }
   }
 
-  void Visit(Array* array) override {
+  void Visit(const Array* array) override {
     const size_t count = array->elements.size();
     for (size_t i = 0; i < count; i++) {
       Reference key(android::ResTable_map::ATTR_MIN + i);
@@ -142,7 +147,7 @@
     }
   }
 
-  void Visit(Plural* plural) override {
+  void Visit(const Plural* plural) override {
     const size_t count = plural->values.size();
     for (size_t i = 0; i < count; i++) {
       if (!plural->values[i]) {
@@ -196,16 +201,16 @@
  private:
   DISALLOW_COPY_AND_ASSIGN(MapFlattenVisitor);
 
-  void FlattenKey(Reference* key, ResTable_map* out_entry) {
+  void FlattenKey(const Reference* key, ResTable_map* out_entry) {
     CHECK(bool(key->id)) << "key has no ID";
     out_entry->name.ident = util::HostToDevice32(key->id.value().id);
   }
 
-  void FlattenValue(Item* value, ResTable_map* out_entry) {
+  void FlattenValue(const Item* value, ResTable_map* out_entry) {
     CHECK(value->Flatten(&out_entry->value)) << "flatten failed";
   }
 
-  void FlattenEntry(Reference* key, Item* value) {
+  void FlattenEntry(const Reference* key, Item* value) {
     ResTable_map* out_entry = buffer_->NextBlock<ResTable_map>();
     FlattenKey(key, out_entry);
     FlattenValue(value, out_entry);
@@ -226,7 +231,7 @@
 
 class PackageFlattener {
  public:
-  PackageFlattener(IAaptContext* context, ResourceTablePackage* package,
+  PackageFlattener(IAaptContext* context, const ResourceTablePackageView& package,
                    const std::map<size_t, std::string>* shared_libs, bool use_sparse_entries,
                    bool collapse_key_stringpool,
                    const std::set<ResourceName>& name_collapse_exemptions)
@@ -243,20 +248,20 @@
     TRACE_CALL();
     ChunkWriter pkg_writer(buffer);
     ResTable_package* pkg_header = pkg_writer.StartChunk<ResTable_package>(RES_TABLE_PACKAGE_TYPE);
-    pkg_header->id = util::HostToDevice32(package_->id.value());
+    pkg_header->id = util::HostToDevice32(package_.id.value());
 
     // AAPT truncated the package name, so do the same.
     // Shared libraries require full package names, so don't truncate theirs.
     if (context_->GetPackageType() != PackageType::kApp &&
-        package_->name.size() >= arraysize(pkg_header->name)) {
-      diag_->Error(DiagMessage() << "package name '" << package_->name
+        package_.name.size() >= arraysize(pkg_header->name)) {
+      diag_->Error(DiagMessage() << "package name '" << package_.name
                                  << "' is too long. "
                                     "Shared libraries cannot have truncated package names");
       return false;
     }
 
     // Copy the package name in device endianness.
-    strcpy16_htod(pkg_header->name, arraysize(pkg_header->name), util::Utf8ToUtf16(package_->name));
+    strcpy16_htod(pkg_header->name, arraysize(pkg_header->name), util::Utf8ToUtf16(package_.name));
 
     // Serialize the types. We do this now so that our type and key strings
     // are populated. We write those first.
@@ -273,7 +278,7 @@
     buffer->AppendBuffer(std::move(type_buffer));
 
     // If there are libraries (or if the package ID is 0x00), encode a library chunk.
-    if (package_->id.value() == 0x00 || !shared_libs_->empty()) {
+    if (package_.id.value() == 0x00 || !shared_libs_->empty()) {
       FlattenLibrarySpec(buffer);
     }
 
@@ -315,7 +320,7 @@
   }
 
   bool FlattenValue(FlatEntry* entry, BigBuffer* buffer) {
-    if (Item* item = ValueCast<Item>(entry->value)) {
+    if (const Item* item = ValueCast<Item>(entry->value)) {
       WriteEntry<ResTable_entry, true>(entry, buffer);
       Res_value* outValue = buffer->NextBlock<Res_value>();
       CHECK(item->Flatten(outValue)) << "flatten failed";
@@ -329,7 +334,7 @@
     return true;
   }
 
-  bool FlattenConfig(const ResourceTableType* type, const ConfigDescription& config,
+  bool FlattenConfig(const ResourceTableTypeView& type, const ConfigDescription& config,
                      const size_t num_total_entries, std::vector<FlatEntry>* entries,
                      BigBuffer* buffer) {
     CHECK(num_total_entries != 0);
@@ -337,7 +342,7 @@
 
     ChunkWriter type_writer(buffer);
     ResTable_type* type_header = type_writer.StartChunk<ResTable_type>(RES_TABLE_TYPE_TYPE);
-    type_header->id = type->id.value();
+    type_header->id = type.id.value();
     type_header->config = config;
     type_header->config.swapHtoD();
 
@@ -346,12 +351,12 @@
 
     BigBuffer values_buffer(512);
     for (FlatEntry& flat_entry : *entries) {
-      CHECK(static_cast<size_t>(flat_entry.entry->id.value()) < num_total_entries);
-      offsets[flat_entry.entry->id.value()] = values_buffer.size();
+      CHECK(static_cast<size_t>(flat_entry.entry->id.value().entry_id()) < num_total_entries);
+      offsets[flat_entry.entry->id.value().entry_id()] = values_buffer.size();
       if (!FlattenValue(&flat_entry, &values_buffer)) {
         diag_->Error(DiagMessage()
                      << "failed to flatten resource '"
-                     << ResourceNameRef(package_->name, type->type, flat_entry.entry->name)
+                     << ResourceNameRef(package_.name, type.type, flat_entry.entry->name)
                      << "' for configuration '" << config << "'");
         return false;
       }
@@ -399,55 +404,27 @@
     return true;
   }
 
-  std::vector<ResourceTableType*> CollectAndSortTypes() {
-    std::vector<ResourceTableType*> sorted_types;
-    for (auto& type : package_->types) {
-      if (type->type == ResourceType::kStyleable) {
-        // Styleables aren't real Resource Types, they are represented in the
-        // R.java file.
-        continue;
-      }
-
-      CHECK(bool(type->id)) << "type must have an ID set";
-
-      sorted_types.push_back(type.get());
-    }
-    std::sort(sorted_types.begin(), sorted_types.end(), cmp_ids<ResourceTableType>);
-    return sorted_types;
-  }
-
-  std::vector<ResourceEntry*> CollectAndSortEntries(ResourceTableType* type) {
-    // Sort the entries by entry ID.
-    std::vector<ResourceEntry*> sorted_entries;
-    for (auto& entry : type->entries) {
-      CHECK(bool(entry->id)) << "entry must have an ID set";
-      sorted_entries.push_back(entry.get());
-    }
-    std::sort(sorted_entries.begin(), sorted_entries.end(), cmp_ids<ResourceEntry>);
-    return sorted_entries;
-  }
-
   bool FlattenOverlayable(BigBuffer* buffer) {
     std::set<ResourceId> seen_ids;
     std::map<std::string, OverlayableChunk> overlayable_chunks;
 
-    CHECK(bool(package_->id)) << "package must have an ID set when flattening <overlayable>";
-    for (auto& type : package_->types) {
-      CHECK(bool(type->id)) << "type must have an ID set when flattening <overlayable>";
-      for (auto& entry : type->entries) {
-        CHECK(bool(type->id)) << "entry must have an ID set when flattening <overlayable>";
+    CHECK(bool(package_.id)) << "package must have an ID set when flattening <overlayable>";
+    for (auto& type : package_.types) {
+      CHECK(bool(type.id)) << "type must have an ID set when flattening <overlayable>";
+      for (auto& entry : type.entries) {
+        CHECK(bool(type.id)) << "entry must have an ID set when flattening <overlayable>";
         if (!entry->overlayable_item) {
           continue;
         }
 
-        OverlayableItem& item = entry->overlayable_item.value();
+        const OverlayableItem& item = entry->overlayable_item.value();
 
         // Resource ids should only appear once in the resource table
-        ResourceId id = android::make_resid(package_->id.value(), type->id.value(),
-                                            entry->id.value());
+        ResourceId id =
+            android::make_resid(package_.id.value(), type.id.value(), entry->id.value().entry_id());
         CHECK(seen_ids.find(id) == seen_ids.end())
             << "multiple overlayable definitions found for resource "
-            << ResourceName(package_->name, type->type, entry->name).to_string();
+            << ResourceName(package_.name, type.type, entry->name).to_string();
         seen_ids.insert(id);
 
         // Find the overlayable chunk with the specified name
@@ -542,14 +519,14 @@
     return true;
   }
 
-  bool FlattenTypeSpec(ResourceTableType* type, std::vector<ResourceEntry*>* sorted_entries,
-                       BigBuffer* buffer) {
+  bool FlattenTypeSpec(const ResourceTableTypeView& type,
+                       const std::vector<const ResourceEntry*>& sorted_entries, BigBuffer* buffer) {
     ChunkWriter type_spec_writer(buffer);
     ResTable_typeSpec* spec_header =
         type_spec_writer.StartChunk<ResTable_typeSpec>(RES_TABLE_TYPE_SPEC_TYPE);
-    spec_header->id = type->id.value();
+    spec_header->id = type.id.value();
 
-    if (sorted_entries->empty()) {
+    if (sorted_entries.empty()) {
       type_spec_writer.Finish();
       return true;
     }
@@ -557,7 +534,7 @@
     // We can't just take the size of the vector. There may be holes in the
     // entry ID space.
     // Since the entries are sorted by ID, the last one will be the biggest.
-    const size_t num_entries = sorted_entries->back()->id.value() + 1;
+    const size_t num_entries = sorted_entries.back()->id.value().entry_id() + 1;
 
     spec_header->entryCount = util::HostToDevice32(num_entries);
 
@@ -565,21 +542,19 @@
     // show for which configuration axis the resource changes.
     uint32_t* config_masks = type_spec_writer.NextBlock<uint32_t>(num_entries);
 
-    const size_t actual_num_entries = sorted_entries->size();
-    for (size_t entryIndex = 0; entryIndex < actual_num_entries; entryIndex++) {
-      ResourceEntry* entry = sorted_entries->at(entryIndex);
+    for (const ResourceEntry* entry : sorted_entries) {
+      const uint16_t entry_id = entry->id.value().entry_id();
 
       // Populate the config masks for this entry.
       if (entry->visibility.level == Visibility::Level::kPublic) {
-        config_masks[entry->id.value()] |= util::HostToDevice32(ResTable_typeSpec::SPEC_PUBLIC);
+        config_masks[entry_id] |= util::HostToDevice32(ResTable_typeSpec::SPEC_PUBLIC);
       }
 
       const size_t config_count = entry->values.size();
       for (size_t i = 0; i < config_count; i++) {
         const ConfigDescription& config = entry->values[i]->config;
         for (size_t j = i + 1; j < config_count; j++) {
-          config_masks[entry->id.value()] |=
-              util::HostToDevice32(config.diff(entry->values[j]->config));
+          config_masks[entry_id] |= util::HostToDevice32(config.diff(entry->values[j]->config));
         }
       }
     }
@@ -590,32 +565,31 @@
   bool FlattenTypes(BigBuffer* buffer) {
     // Sort the types by their IDs. They will be inserted into the StringPool in
     // this order.
-    std::vector<ResourceTableType*> sorted_types = CollectAndSortTypes();
 
     size_t expected_type_id = 1;
-    for (ResourceTableType* type : sorted_types) {
+    for (const ResourceTableTypeView& type : package_.types) {
+      if (type.type == ResourceType::kStyleable) {
+        // Styleables aren't real Resource Types, they are represented in the R.java file.
+        continue;
+      }
+
       // If there is a gap in the type IDs, fill in the StringPool
       // with empty values until we reach the ID we expect.
-      while (type->id.value() > expected_type_id) {
+      while (type.id.value() > expected_type_id) {
         std::stringstream type_name;
         type_name << "?" << expected_type_id;
         type_pool_.MakeRef(type_name.str());
         expected_type_id++;
       }
       expected_type_id++;
-      type_pool_.MakeRef(to_string(type->type));
+      type_pool_.MakeRef(to_string(type.type));
 
-      std::vector<ResourceEntry*> sorted_entries = CollectAndSortEntries(type);
-      if (sorted_entries.empty()) {
-        continue;
-      }
-
-      if (!FlattenTypeSpec(type, &sorted_entries, buffer)) {
+      if (!FlattenTypeSpec(type, type.entries, buffer)) {
         return false;
       }
 
       // Since the entries are sorted by ID, the last ID will be the largest.
-      const size_t num_entries = sorted_entries.back()->id.value() + 1;
+      const size_t num_entries = type.entries.back()->id.value().entry_id() + 1;
 
       // The binary resource table lists resource entries for each
       // configuration.
@@ -628,9 +602,9 @@
       // hardcoded string uses characters which make it an invalid resource name
       const std::string obfuscated_resource_name = "0_resource_name_obfuscated";
 
-      for (ResourceEntry* entry : sorted_entries) {
+      for (const ResourceEntry* entry : type.entries) {
         uint32_t local_key_index;
-        ResourceName resource_name({}, type->type, entry->name);
+        ResourceName resource_name({}, type.type, entry->name);
         if (!collapse_key_stringpool_ ||
             name_collapse_exemptions_.find(resource_name) != name_collapse_exemptions_.end()) {
           local_key_index = (uint32_t)key_pool_.MakeRef(entry->name).index();
@@ -660,17 +634,17 @@
     ResTable_lib_header* lib_header =
         lib_writer.StartChunk<ResTable_lib_header>(RES_TABLE_LIBRARY_TYPE);
 
-    const size_t num_entries = (package_->id.value() == 0x00 ? 1 : 0) + shared_libs_->size();
+    const size_t num_entries = (package_.id.value() == 0x00 ? 1 : 0) + shared_libs_->size();
     CHECK(num_entries > 0);
 
     lib_header->count = util::HostToDevice32(num_entries);
 
     ResTable_lib_entry* lib_entry = buffer->NextBlock<ResTable_lib_entry>(num_entries);
-    if (package_->id.value() == 0x00) {
+    if (package_.id.value() == 0x00) {
       // Add this package
       lib_entry->packageId = util::HostToDevice32(0x00);
       strcpy16_htod(lib_entry->packageName, arraysize(lib_entry->packageName),
-                    util::Utf8ToUtf16(package_->name));
+                    util::Utf8ToUtf16(package_.name));
       ++lib_entry;
     }
 
@@ -685,7 +659,7 @@
 
   IAaptContext* context_;
   IDiagnostics* diag_;
-  ResourceTablePackage* package_;
+  const ResourceTablePackageView package_;
   const std::map<size_t, std::string>* shared_libs_;
   bool use_sparse_entries_;
   StringPool type_pool_;
@@ -709,9 +683,10 @@
   });
 
   // Write the ResTable header.
+  const auto& table_view = table->GetPartitionedView();
   ChunkWriter table_writer(buffer_);
   ResTable_header* table_header = table_writer.StartChunk<ResTable_header>(RES_TABLE_TYPE);
-  table_header->packageCount = util::HostToDevice32(table->packages.size());
+  table_header->packageCount = util::HostToDevice32(table_view.packages.size());
 
   // Flatten the values string pool.
   StringPool::FlattenUtf8(table_writer.buffer(), table->string_pool,
@@ -720,24 +695,25 @@
   BigBuffer package_buffer(1024);
 
   // Flatten each package.
-  for (auto& package : table->packages) {
+  for (auto& package : table_view.packages) {
     if (context->GetPackageType() == PackageType::kApp) {
       // Write a self mapping entry for this package if the ID is non-standard (0x7f).
-      const uint8_t package_id = package->id.value();
+      CHECK((bool)package.id) << "Resource ids have not been assigned before flattening the table";
+      const uint8_t package_id = package.id.value();
       if (package_id != kFrameworkPackageId && package_id != kAppPackageId) {
-        auto result = table->included_packages_.insert({package_id, package->name});
-        if (!result.second && result.first->second != package->name) {
+        auto result = table->included_packages_.insert({package_id, package.name});
+        if (!result.second && result.first->second != package.name) {
           // A mapping for this package ID already exists, and is a different package. Error!
           context->GetDiagnostics()->Error(
               DiagMessage() << android::base::StringPrintf(
                   "can't map package ID %02x to '%s'. Already mapped to '%s'", package_id,
-                  package->name.c_str(), result.first->second.c_str()));
+                  package.name.c_str(), result.first->second.c_str()));
           return false;
         }
       }
     }
 
-    PackageFlattener flattener(context, package.get(), &table->included_packages_,
+    PackageFlattener flattener(context, package, &table->included_packages_,
                                options_.use_sparse_entries, options_.collapse_key_stringpool,
                                options_.name_collapse_exemptions);
     if (!flattener.FlattenPackage(&package_buffer)) {
diff --git a/tools/aapt2/format/binary/TableFlattener_test.cpp b/tools/aapt2/format/binary/TableFlattener_test.cpp
index f8b8a1c..f5fe5e3 100644
--- a/tools/aapt2/format/binary/TableFlattener_test.cpp
+++ b/tools/aapt2/format/binary/TableFlattener_test.cpp
@@ -155,7 +155,6 @@
 TEST_F(TableFlattenerTest, FlattenFullyLinkedTable) {
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.test", 0x7f)
           .AddSimple("com.app.test:id/one", ResourceId(0x7f020000))
           .AddSimple("com.app.test:id/two", ResourceId(0x7f020001))
           .AddValue("com.app.test:id/three", ResourceId(0x7f020002),
@@ -204,7 +203,6 @@
 TEST_F(TableFlattenerTest, FlattenEntriesWithGapsInIds) {
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.test", 0x7f)
           .AddSimple("com.app.test:id/one", ResourceId(0x7f020001))
           .AddSimple("com.app.test:id/three", ResourceId(0x7f020003))
           .Build();
@@ -225,7 +223,6 @@
   attr.max_int = 23;
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("android", 0x01)
           .AddValue("android:attr/foo", ResourceId(0x01010000), util::make_unique<Attribute>(attr))
           .Build();
 
@@ -248,7 +245,6 @@
                                                                2u));
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("android", 0x01)
           .AddValue("android:array/foo", ResourceId(0x01010000), std::move(array))
           .Build();
 
@@ -300,7 +296,6 @@
     IAaptContext* context, const ConfigDescription& sparse_config, float load) {
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId(context->GetCompilationPackage(), context->GetPackageId())
           .Build();
 
   // Add regular entries.
@@ -311,15 +306,20 @@
     const ResourceId resid(context->GetPackageId(), 0x02, static_cast<uint16_t>(i));
     const auto value =
         util::make_unique<BinaryPrimitive>(Res_value::TYPE_INT_DEC, static_cast<uint32_t>(i));
-    CHECK(table->AddResourceWithId(name, resid, ConfigDescription::DefaultConfig(), "",
-                                   std::unique_ptr<Value>(value->Clone(nullptr)),
-                                   context->GetDiagnostics()));
+    CHECK(table->AddResource(NewResourceBuilder(name)
+                                 .SetId(resid)
+                                 .SetValue(std::unique_ptr<Value>(value->Clone(nullptr)))
+                                 .Build(),
+                             context->GetDiagnostics()));
 
     // Every few entries, write out a sparse_config value. This will give us the desired load.
     if (i % stride == 0) {
-      CHECK(table->AddResourceWithId(name, resid, sparse_config, "",
-                                     std::unique_ptr<Value>(value->Clone(nullptr)),
-                                     context->GetDiagnostics()));
+      CHECK(table->AddResource(
+          NewResourceBuilder(name)
+              .SetId(resid)
+              .SetValue(std::unique_ptr<Value>(value->Clone(nullptr)), sparse_config)
+              .Build(),
+          context->GetDiagnostics()));
     }
   }
   return table;
@@ -417,7 +417,6 @@
       test::ContextBuilder().SetCompilationPackage("lib").SetPackageId(0x00).Build();
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("lib", 0x00)
           .AddValue("lib:id/foo", ResourceId(0x00010000), util::make_unique<Id>())
           .Build();
   ResourceTable result;
@@ -426,7 +425,7 @@
   Maybe<ResourceTable::SearchResult> search_result =
       result.FindResource(test::ParseNameOrDie("lib:id/foo"));
   ASSERT_TRUE(search_result);
-  EXPECT_EQ(0x00u, search_result.value().package->id.value());
+  EXPECT_EQ(0x00u, search_result.value().entry->id.value().package_id());
 
   auto iter = result.included_packages_.find(0x00);
   ASSERT_NE(result.included_packages_.end(), iter);
@@ -438,7 +437,6 @@
       test::ContextBuilder().SetCompilationPackage("lib").SetPackageId(0x00).Build();
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("lib", 0x00)
           .AddValue("lib:style/Theme",
                     ResourceId(0x00030001),
                     test::StyleBuilder()
@@ -458,9 +456,7 @@
   Maybe<ResourceTable::SearchResult> search_result =
       result.FindResource(test::ParseNameOrDie("lib:style/Theme"));
   ASSERT_TRUE(search_result);
-  EXPECT_EQ(0x00u, search_result.value().package->id.value());
-  EXPECT_EQ(0x03u, search_result.value().type->id.value());
-  EXPECT_EQ(0x01u, search_result.value().entry->id.value());
+  EXPECT_EQ(0x00030001u, search_result.value().entry->id.value());
   ASSERT_EQ(1u, search_result.value().entry->values.size());
   Value* value = search_result.value().entry->values[0]->value.get();
   Style* style = ValueCast<Style>(value);
@@ -479,7 +475,6 @@
       test::ContextBuilder().SetCompilationPackage("app").SetPackageId(0x7f).Build();
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("app", 0x7f)
           .AddValue("app:id/foo", ResourceId(0x7f010000),
                     test::BuildReference("lib_one:id/foo", ResourceId(0x02010000)))
           .AddValue("app:id/bar", ResourceId(0x7f010001),
@@ -509,7 +504,6 @@
   std::unique_ptr<IAaptContext> context =
       test::ContextBuilder().SetCompilationPackage("app").SetPackageId(0x80).Build();
   std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-                                             .SetPackageId("app", 0x80)
                                              .AddSimple("app:id/foo", ResourceId(0x80010000))
                                              .Build();
 
@@ -532,7 +526,6 @@
       test::ContextBuilder().SetCompilationPackage(kPackageName).SetPackageId(0x7f).Build();
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId(kPackageName, 0x7f)
           .AddSimple(kPackageName + ":id/foo", ResourceId(0x7f010000))
           .Build();
 
@@ -553,7 +546,6 @@
                                               .Build();
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId(kPackageName, 0x7f)
           .AddSimple(kPackageName + ":id/foo", ResourceId(0x7f010000))
           .Build();
 
@@ -564,7 +556,6 @@
 TEST_F(TableFlattenerTest, ObfuscatingResourceNamesNoNameCollapseExemptionsSucceeds) {
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.test", 0x7f)
           .AddSimple("com.app.test:id/one", ResourceId(0x7f020000))
           .AddSimple("com.app.test:id/two", ResourceId(0x7f020001))
           .AddValue("com.app.test:id/three", ResourceId(0x7f020002),
@@ -618,7 +609,6 @@
 TEST_F(TableFlattenerTest, ObfuscatingResourceNamesWithNameCollapseExemptionsSucceeds) {
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.test", 0x7f)
           .AddSimple("com.app.test:id/one", ResourceId(0x7f020000))
           .AddSimple("com.app.test:id/two", ResourceId(0x7f020001))
           .AddValue("com.app.test:id/three", ResourceId(0x7f020002),
@@ -680,7 +670,6 @@
   std::string name = "com.app.test:integer/overlayable";
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.test", 0x7f)
           .AddSimple(name, ResourceId(0x7f020000))
           .SetOverlayable(name, overlayable_item)
           .Build();
@@ -717,7 +706,6 @@
 
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.test", 0x7f)
           .AddSimple(name_zero, ResourceId(0x7f020000))
           .SetOverlayable(name_zero, overlayable_item_zero)
           .AddSimple(name_one, ResourceId(0x7f020001))
@@ -780,7 +768,6 @@
 
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.test", 0x7f)
           .AddSimple(name_zero, ResourceId(0x7f020000))
           .SetOverlayable(name_zero, overlayable_item_zero)
           .AddSimple(name_one, ResourceId(0x7f020001))
@@ -842,7 +829,6 @@
 
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.test", 0x7f)
           .AddSimple(name_zero, ResourceId(0x7f020000))
           .SetOverlayable(name_zero, overlayable_item_zero)
           .Build();
diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp
index 06ac9e5..bfb92da 100644
--- a/tools/aapt2/format/proto/ProtoDeserialize.cpp
+++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp
@@ -425,15 +425,9 @@
                                      io::IFileCollection* files,
                                      const std::vector<std::shared_ptr<Overlayable>>& overlayables,
                                      ResourceTable* out_table, std::string* out_error) {
-  Maybe<uint8_t> id;
-  if (pb_package.has_package_id()) {
-    id = static_cast<uint8_t>(pb_package.package_id().id());
-  }
-
   std::map<ResourceId, ResourceNameRef> id_index;
 
-  ResourceTablePackage* pkg =
-      out_table->CreatePackageAllowingDuplicateNames(pb_package.package_name(), id);
+  ResourceTablePackage* pkg = out_table->FindOrCreatePackage(pb_package.package_name());
   for (const pb::Type& pb_type : pb_package.type()) {
     const ResourceType* res_type = ParseResourceType(pb_type.name());
     if (res_type == nullptr) {
@@ -444,17 +438,15 @@
     }
 
     ResourceTableType* type = pkg->FindOrCreateType(*res_type);
-    if (pb_type.has_type_id()) {
-      type->id = static_cast<uint8_t>(pb_type.type_id().id());
-    }
 
     for (const pb::Entry& pb_entry : pb_type.entry()) {
-      ResourceEntry* entry;
-      if (pb_entry.has_entry_id()) {
-        auto entry_id = static_cast<uint16_t>(pb_entry.entry_id().id());
-        entry = type->FindOrCreateEntry(pb_entry.name(), entry_id);
-      } else {
-        entry = type->FindOrCreateEntry(pb_entry.name());
+      ResourceEntry* entry = type->CreateEntry(pb_entry.name());
+      const ResourceId resource_id(
+          pb_package.has_package_id() ? static_cast<uint8_t>(pb_package.package_id().id()) : 0u,
+          pb_type.has_type_id() ? static_cast<uint8_t>(pb_type.type_id().id()) : 0u,
+          pb_entry.has_entry_id() ? static_cast<uint16_t>(pb_entry.entry_id().id()) : 0u);
+      if (resource_id.id != 0u) {
+        entry->id = resource_id;
       }
 
       // Deserialize the symbol status (public/private with source and comments).
diff --git a/tools/aapt2/format/proto/ProtoSerialize.cpp b/tools/aapt2/format/proto/ProtoSerialize.cpp
index 98c5175..9842e25 100644
--- a/tools/aapt2/format/proto/ProtoSerialize.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize.cpp
@@ -345,28 +345,29 @@
   pb_fingerprint->set_version(util::GetToolFingerprint());
 
   std::vector<Overlayable*> overlayables;
-  for (const std::unique_ptr<ResourceTablePackage>& package : table.packages) {
+  auto table_view = table.GetPartitionedView();
+  for (const auto& package : table_view.packages) {
     pb::Package* pb_package = out_table->add_package();
-    if (package->id) {
-      pb_package->mutable_package_id()->set_id(package->id.value());
+    if (package.id) {
+      pb_package->mutable_package_id()->set_id(package.id.value());
     }
-    pb_package->set_package_name(package->name);
+    pb_package->set_package_name(package.name);
 
-    for (const std::unique_ptr<ResourceTableType>& type : package->types) {
+    for (const auto& type : package.types) {
       pb::Type* pb_type = pb_package->add_type();
-      if (type->id) {
-        pb_type->mutable_type_id()->set_id(type->id.value());
+      if (type.id) {
+        pb_type->mutable_type_id()->set_id(type.id.value());
       }
-      pb_type->set_name(to_string(type->type).to_string());
+      pb_type->set_name(to_string(type.type).to_string());
 
       // hardcoded string uses characters which make it an invalid resource name
       static const char* obfuscated_resource_name = "0_resource_name_obfuscated";
-      for (const std::unique_ptr<ResourceEntry>& entry : type->entries) {
+      for (const auto& entry : type.entries) {
         pb::Entry* pb_entry = pb_type->add_entry();
         if (entry->id) {
-          pb_entry->mutable_entry_id()->set_id(entry->id.value());
+          pb_entry->mutable_entry_id()->set_id(entry->id.value().entry_id());
         }
-        ResourceName resource_name({}, type->type, entry->name);
+        ResourceName resource_name({}, type.type, entry->name);
         if (options.collapse_key_stringpool &&
             options.name_collapse_exemptions.find(resource_name) ==
             options.name_collapse_exemptions.end()) {
diff --git a/tools/aapt2/format/proto/ProtoSerialize_test.cpp b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
index fe4c8aa..ad5ed4d 100644
--- a/tools/aapt2/format/proto/ProtoSerialize_test.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
@@ -40,18 +40,20 @@
   MOCK_METHOD0(GetDirSeparator, char());
 };
 
-ResourceEntry* GetEntry(ResourceTable* table, const ResourceNameRef& res_name,
-                   uint32_t id) {
-  ResourceTablePackage* package = table->FindPackage(res_name.package);
-  ResourceTableType* type = package->FindType(res_name.type);
-  return  type->FindEntry(res_name.entry, id);
+ResourceEntry* GetEntry(ResourceTable* table, const ResourceNameRef& res_name) {
+  auto result = table->FindResource(res_name);
+  return (result) ? result.value().entry : nullptr;
+}
+
+ResourceEntry* GetEntry(ResourceTable* table, const ResourceNameRef& res_name, ResourceId id) {
+  auto result = table->FindResource(res_name, id);
+  return (result) ? result.value().entry : nullptr;
 }
 
 TEST(ProtoSerializeTest, SerializeSinglePackage) {
   std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.a", 0x7f)
           .AddFileReference("com.app.a:layout/main", ResourceId(0x7f020000), "res/layout/main.xml")
           .AddReference("com.app.a:layout/other", ResourceId(0x7f020001), "com.app.a:layout/main")
           .AddString("com.app.a:string/text", {}, "hi")
@@ -60,11 +62,11 @@
                           true /*allow_new*/)
           .Build();
 
-  Visibility public_symbol;
-  public_symbol.level = Visibility::Level::kPublic;
-  ASSERT_TRUE(table->SetVisibilityWithId(test::ParseNameOrDie("com.app.a:layout/main"),
-                                         public_symbol, ResourceId(0x7f020000),
-                                         context->GetDiagnostics()));
+  ASSERT_TRUE(table->AddResource(NewResourceBuilder(test::ParseNameOrDie("com.app.a:layout/main"))
+                                     .SetId(0x7f020000)
+                                     .SetVisibility({Visibility::Level::kPublic})
+                                     .Build(),
+                                 context->GetDiagnostics()));
 
   Id* id = test::GetValue<Id>(table.get(), "com.app.a:id/foo");
   ASSERT_THAT(id, NotNull());
@@ -72,25 +74,35 @@
   // Make a plural.
   std::unique_ptr<Plural> plural = util::make_unique<Plural>();
   plural->values[Plural::One] = util::make_unique<String>(table->string_pool.MakeRef("one"));
-  ASSERT_TRUE(table->AddResource(test::ParseNameOrDie("com.app.a:plurals/hey"), ConfigDescription{},
-                                 {}, std::move(plural), context->GetDiagnostics()));
+  ASSERT_TRUE(table->AddResource(NewResourceBuilder(test::ParseNameOrDie("com.app.a:plurals/hey"))
+                                     .SetValue(std::move(plural))
+                                     .Build(),
+                                 context->GetDiagnostics()));
 
   // Make a styled string.
   StyleString style_string;
   style_string.str = "hello";
   style_string.spans.push_back(Span{"b", 0u, 4u});
-  ASSERT_TRUE(
-      table->AddResource(test::ParseNameOrDie("com.app.a:string/styled"), ConfigDescription{}, {},
-                         util::make_unique<StyledString>(table->string_pool.MakeRef(style_string)),
-                         context->GetDiagnostics()));
+  ASSERT_TRUE(table->AddResource(
+      NewResourceBuilder(test::ParseNameOrDie("com.app.a:string/styled"))
+          .SetValue(util::make_unique<StyledString>(table->string_pool.MakeRef(style_string)))
+          .Build(),
+      context->GetDiagnostics()));
 
   // Make a resource with different products.
-  ASSERT_TRUE(table->AddResource(
-      test::ParseNameOrDie("com.app.a:integer/one"), test::ParseConfigOrDie("land"), {},
-      test::BuildPrimitive(android::Res_value::TYPE_INT_DEC, 123u), context->GetDiagnostics()));
-  ASSERT_TRUE(table->AddResource(
-      test::ParseNameOrDie("com.app.a:integer/one"), test::ParseConfigOrDie("land"), "tablet",
-      test::BuildPrimitive(android::Res_value::TYPE_INT_HEX, 321u), context->GetDiagnostics()));
+  ASSERT_TRUE(
+      table->AddResource(NewResourceBuilder(test::ParseNameOrDie("com.app.a:integer/one"))
+                             .SetValue(test::BuildPrimitive(android::Res_value::TYPE_INT_DEC, 123u),
+                                       test::ParseConfigOrDie("land"))
+                             .Build(),
+                         context->GetDiagnostics()));
+
+  ASSERT_TRUE(
+      table->AddResource(NewResourceBuilder(test::ParseNameOrDie("com.app.a:integer/one"))
+                             .SetValue(test::BuildPrimitive(android::Res_value::TYPE_INT_HEX, 321u),
+                                       test::ParseConfigOrDie("land"), "tablet")
+                             .Build(),
+                         context->GetDiagnostics()));
 
   // Make a reference with both resource name and resource ID.
   // The reference should point to a resource outside of this table to test that both name and id
@@ -98,16 +110,20 @@
   Reference expected_ref;
   expected_ref.name = test::ParseNameOrDie("android:layout/main");
   expected_ref.id = ResourceId(0x01020000);
-  ASSERT_TRUE(table->AddResource(
-      test::ParseNameOrDie("com.app.a:layout/abc"), ConfigDescription::DefaultConfig(), {},
-      util::make_unique<Reference>(expected_ref), context->GetDiagnostics()));
+  ASSERT_TRUE(table->AddResource(NewResourceBuilder(test::ParseNameOrDie("com.app.a:layout/abc"))
+                                     .SetValue(util::make_unique<Reference>(expected_ref))
+                                     .Build(),
+                                 context->GetDiagnostics()));
 
   // Make an overlayable resource.
   OverlayableItem overlayable_item(std::make_shared<Overlayable>(
       "OverlayableName", "overlay://theme", Source("res/values/overlayable.xml", 40)));
   overlayable_item.source = Source("res/values/overlayable.xml", 42);
-  ASSERT_TRUE(table->SetOverlayable(test::ParseNameOrDie("com.app.a:integer/overlayable"),
-                                    overlayable_item, test::GetDiagnostics()));
+  ASSERT_TRUE(
+      table->AddResource(NewResourceBuilder(test::ParseNameOrDie("com.app.a:integer/overlayable"))
+                             .SetOverlayable(overlayable_item)
+                             .Build(),
+                         context->GetDiagnostics()));
 
   pb::ResourceTable pb_table;
   SerializeTableToPb(*table, &pb_table, context->GetDiagnostics());
@@ -680,7 +696,6 @@
   std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.test", 0x7f)
           .AddSimple("com.app.test:id/one", ResourceId(id_one_id))
           .AddSimple("com.app.test:id/two", ResourceId(id_two_id))
           .AddValue("com.app.test:id/three", ResourceId(id_three_id),
@@ -714,7 +729,7 @@
 
   ResourceName real_id_resource(
       "com.app.test", ResourceType::kId, "one");
-  EXPECT_THAT(GetEntry(&new_table, real_id_resource, id_one_id), IsNull());
+  EXPECT_THAT(GetEntry(&new_table, real_id_resource), IsNull());
 
   ResourceName obfuscated_id_resource(
       "com.app.test", ResourceType::kId, "0_resource_name_obfuscated");
@@ -767,7 +782,6 @@
   std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.test", 0x7f)
           .AddSimple("com.app.test:id/one", ResourceId(id_one_id))
           .AddSimple("com.app.test:id/two", ResourceId(id_two_id))
           .AddValue("com.app.test:id/three", ResourceId(id_three_id),
diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp
index 59dd481..039448e 100644
--- a/tools/aapt2/java/JavaClassGenerator.cpp
+++ b/tools/aapt2/java/JavaClassGenerator.cpp
@@ -542,8 +542,8 @@
 
     // Create an ID if there is one (static libraries don't need one).
     ResourceId id;
-    if (package.id && type.id && entry->id) {
-      id = ResourceId(package.id.value(), type.id.value(), entry->id.value());
+    if (entry->id) {
+      id = entry->id.value();
     }
 
     // We need to make sure we hide the fact that we are generating kAttrPrivate attributes.
diff --git a/tools/aapt2/java/JavaClassGenerator_test.cpp b/tools/aapt2/java/JavaClassGenerator_test.cpp
index ec5b415..8bb3ee9 100644
--- a/tools/aapt2/java/JavaClassGenerator_test.cpp
+++ b/tools/aapt2/java/JavaClassGenerator_test.cpp
@@ -34,7 +34,6 @@
 TEST(JavaClassGeneratorTest, FailWhenEntryIsJavaKeyword) {
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("android", 0x01)
           .AddSimple("android:id/class", ResourceId(0x01020000))
           .Build();
 
@@ -54,7 +53,6 @@
 TEST(JavaClassGeneratorTest, TransformInvalidJavaIdentifierCharacter) {
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("android", 0x01)
           .AddSimple("android:id/hey-man", ResourceId(0x01020000))
           .AddValue("android:attr/cool.attr", ResourceId(0x01010000),
                     test::AttributeBuilder().Build())
@@ -84,7 +82,6 @@
 TEST(JavaClassGeneratorTest, CorrectPackageNameIsUsed) {
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("android", 0x01)
           .AddSimple("android:id/one", ResourceId(0x01020000))
           .AddSimple("android:id/com.foo$two", ResourceId(0x01020001))
           .Build();
@@ -110,8 +107,6 @@
 TEST(JavaClassGeneratorTest, StyleableAttributesWithDifferentPackageName) {
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("android", 0x01)
-          .SetPackageId("app", 0x7f)
           .AddValue("app:attr/foo", ResourceId(0x7f010000),
                     test::AttributeBuilder().Build())
           .AddValue("app:attr/bar", ResourceId(0x7f010001),
@@ -159,7 +154,6 @@
 TEST(JavaClassGeneratorTest, AttrPrivateIsWrittenAsAttr) {
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("android", 0x01)
           .AddSimple("android:attr/two", ResourceId(0x01010001))
           .AddSimple("android:^attr-private/one", ResourceId(0x01010000))
           .Build();
@@ -184,7 +178,6 @@
   StdErrDiagnostics diag;
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("android", 0x01)
           .AddSimple("android:id/one", ResourceId(0x01020000))
           .AddSimple("android:id/two", ResourceId(0x01020001))
           .AddSimple("android:id/three", ResourceId(0x01020002))
@@ -276,8 +269,6 @@
 TEST(JavaClassGeneratorTest, EmitOtherPackagesAttributesInStyleable) {
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("android", 0x01)
-          .SetPackageId("com.lib", 0x02)
           .AddValue("android:attr/bar", ResourceId(0x01010000), test::AttributeBuilder().Build())
           .AddValue("com.lib:attr/bar", ResourceId(0x02010000), test::AttributeBuilder().Build())
           .AddValue("android:styleable/foo", ResourceId(0x01030000),
@@ -306,7 +297,6 @@
 TEST(JavaClassGeneratorTest, CommentsForSimpleResourcesArePresent) {
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("android", 0x01)
           .AddSimple("android:id/foo", ResourceId(0x01010000))
           .Build();
   test::GetValue<Id>(table.get(), "android:id/foo")
@@ -346,7 +336,6 @@
 
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("android", 0x01)
           .AddValue("android:attr/one", util::make_unique<Attribute>(attr))
           .AddValue("android:styleable/Container",
                     std::unique_ptr<Styleable>(styleable.Clone(nullptr)))
@@ -384,7 +373,6 @@
 
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("android", 0x01)
           .AddValue("android:attr/one", util::make_unique<Attribute>(attr))
           .AddValue("android:styleable/Container",
                     std::unique_ptr<Styleable>(styleable.Clone(nullptr)))
@@ -415,7 +403,6 @@
 TEST(JavaClassGeneratorTest, StyleableAndIndicesAreColocated) {
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("android", 0x01)
           .AddValue("android:attr/layout_gravity", util::make_unique<Attribute>())
           .AddValue("android:attr/background", util::make_unique<Attribute>())
           .AddValue("android:styleable/ActionBar",
@@ -467,7 +454,6 @@
 
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("android", 0x01)
           .AddValue("android:attr/one", util::make_unique<Attribute>(attr))
           .Build();
 
@@ -499,7 +485,6 @@
 TEST(JavaClassGeneratorTest, GenerateOnResourcesLoadedCallbackForSharedLibrary) {
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("android", 0x00)
           .AddValue("android:attr/foo", ResourceId(0x00010000), util::make_unique<Attribute>())
           .AddValue("android:id/foo", ResourceId(0x00020000), util::make_unique<Id>())
           .AddValue(
@@ -536,7 +521,6 @@
 TEST(JavaClassGeneratorTest, OnlyGenerateRText) {
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("android", 0x01)
           .AddValue("android:attr/foo", ResourceId(0x01010000), util::make_unique<Attribute>())
           .AddValue("android:styleable/hey.dude", ResourceId(0x01020000),
                     test::StyleableBuilder()
@@ -554,8 +538,6 @@
 TEST(JavaClassGeneratorTest, SortsDynamicAttributesAfterFrameworkAttributes) {
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("android", 0x01)
-          .SetPackageId("lib", 0x00)
           .AddValue("android:attr/framework_attr", ResourceId(0x01010000),
                     test::AttributeBuilder().Build())
           .AddValue("lib:attr/dynamic_attr", ResourceId(0x00010000),
diff --git a/tools/aapt2/java/ProguardRules_test.cpp b/tools/aapt2/java/ProguardRules_test.cpp
index c7ae0b6..b7dfec3 100644
--- a/tools/aapt2/java/ProguardRules_test.cpp
+++ b/tools/aapt2/java/ProguardRules_test.cpp
@@ -247,8 +247,10 @@
 
   ResourceTable table;
   StdErrDiagnostics errDiagnostics;
-  table.AddResource(bar_layout->file.name, ConfigDescription::DefaultConfig(), "",
-                    util::make_unique<FileReference>(), &errDiagnostics);
+  table.AddResource(NewResourceBuilder(bar_layout->file.name)
+                        .SetValue(util::make_unique<FileReference>())
+                        .Build(),
+                    &errDiagnostics);
 
   std::unique_ptr<IAaptContext> context =
       test::ContextBuilder()
diff --git a/tools/aapt2/link/AutoVersioner_test.cpp b/tools/aapt2/link/AutoVersioner_test.cpp
index 1117472..02fd00b 100644
--- a/tools/aapt2/link/AutoVersioner_test.cpp
+++ b/tools/aapt2/link/AutoVersioner_test.cpp
@@ -54,7 +54,6 @@
 TEST(AutoVersionerTest, VersionStylesForTable) {
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("app", 0x7f)
           .AddValue(
               "app:style/Foo", test::ParseConfigOrDie("v4"),
               ResourceId(0x7f020000),
diff --git a/tools/aapt2/link/NoDefaultResourceRemover_test.cpp b/tools/aapt2/link/NoDefaultResourceRemover_test.cpp
index d129c9a..3179fef 100644
--- a/tools/aapt2/link/NoDefaultResourceRemover_test.cpp
+++ b/tools/aapt2/link/NoDefaultResourceRemover_test.cpp
@@ -21,10 +21,9 @@
 namespace aapt {
 
 TEST(NoDefaultResourceRemoverTest, RemoveEntryWithNoDefaultAndOnlyLocales) {
-  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
+  std::unique_ptr<IAaptContext> context = test::ContextBuilder().SetPackageId(0x01).Build();
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("android", 0x01)
           .AddSimple("android:string/foo")
           .AddSimple("android:string/foo", test::ParseConfigOrDie("en-rGB"))
           .AddSimple("android:string/foo", test::ParseConfigOrDie("fr-rFR"))
@@ -47,10 +46,10 @@
 }
 
 TEST(NoDefaultResourceRemoverTest, KeepEntryWithLocalesAndDensities) {
-  std::unique_ptr<IAaptContext> context = test::ContextBuilder().SetMinSdkVersion(26).Build();
+  std::unique_ptr<IAaptContext> context =
+      test::ContextBuilder().SetPackageId(0x01).SetMinSdkVersion(26).Build();
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("android", 0x01)
           .AddSimple("android:drawable/keep1", test::ParseConfigOrDie("mdpi")) // v4
           .AddSimple("android:drawable/keep1", test::ParseConfigOrDie("en-rGB"))
           .AddSimple("android:drawable/keep1", test::ParseConfigOrDie("fr-rFR"))
@@ -71,10 +70,10 @@
 }
 
 TEST(NoDefaultResourceRemoverTest, RemoveEntryWithLocalesAndDensitiesLowVersion) {
-  std::unique_ptr<IAaptContext> context = test::ContextBuilder().SetMinSdkVersion(3).Build();
+  std::unique_ptr<IAaptContext> context =
+      test::ContextBuilder().SetPackageId(0x01).SetMinSdkVersion(3).Build();
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("android", 0x01)
           .AddSimple("android:drawable/remove1", test::ParseConfigOrDie("mdpi")) // v4
           .AddSimple("android:drawable/remove1", test::ParseConfigOrDie("en-rGB"))
           .AddSimple("android:drawable/remove1", test::ParseConfigOrDie("fr-rFR"))
@@ -87,10 +86,10 @@
 }
 
 TEST(NoDefaultResourceRemoverTest, KeepEntryWithVersion) {
-  std::unique_ptr<IAaptContext> context = test::ContextBuilder().SetMinSdkVersion(8).Build();
+  std::unique_ptr<IAaptContext> context =
+      test::ContextBuilder().SetPackageId(0x01).SetMinSdkVersion(8).Build();
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("android", 0x01)
           .AddSimple("android:drawable/keep1", test::ParseConfigOrDie("v8"))
           .AddSimple("android:drawable/keep1", test::ParseConfigOrDie("en-rGB"))
           .AddSimple("android:drawable/keep1", test::ParseConfigOrDie("fr-rFR"))
diff --git a/tools/aapt2/link/ProductFilter_test.cpp b/tools/aapt2/link/ProductFilter_test.cpp
index dd47674..4f78bbc 100644
--- a/tools/aapt2/link/ProductFilter_test.cpp
+++ b/tools/aapt2/link/ProductFilter_test.cpp
@@ -30,21 +30,29 @@
 
   ResourceTable table;
   ASSERT_TRUE(table.AddResource(
-      test::ParseNameOrDie("android:string/one"), land, "",
-      test::ValueBuilder<Id>().SetSource(Source("land/default.xml")).Build(),
-      context->GetDiagnostics()));
-  ASSERT_TRUE(table.AddResource(
-      test::ParseNameOrDie("android:string/one"), land, "tablet",
-      test::ValueBuilder<Id>().SetSource(Source("land/tablet.xml")).Build(),
+      NewResourceBuilder(test::ParseNameOrDie("android:string/one"))
+          .SetValue(test::ValueBuilder<Id>().SetSource(Source("land/default.xml")).Build(), land)
+          .Build(),
       context->GetDiagnostics()));
 
   ASSERT_TRUE(table.AddResource(
-      test::ParseNameOrDie("android:string/one"), port, "",
-      test::ValueBuilder<Id>().SetSource(Source("port/default.xml")).Build(),
+      NewResourceBuilder(test::ParseNameOrDie("android:string/one"))
+          .SetValue(test::ValueBuilder<Id>().SetSource(Source("land/tablet.xml")).Build(), land,
+                    "tablet")
+          .Build(),
       context->GetDiagnostics()));
+
   ASSERT_TRUE(table.AddResource(
-      test::ParseNameOrDie("android:string/one"), port, "tablet",
-      test::ValueBuilder<Id>().SetSource(Source("port/tablet.xml")).Build(),
+      NewResourceBuilder(test::ParseNameOrDie("android:string/one"))
+          .SetValue(test::ValueBuilder<Id>().SetSource(Source("port/default.xml")).Build(), port)
+          .Build(),
+      context->GetDiagnostics()));
+
+  ASSERT_TRUE(table.AddResource(
+      NewResourceBuilder(test::ParseNameOrDie("android:string/one"))
+          .SetValue(test::ValueBuilder<Id>().SetSource(Source("port/tablet.xml")).Build(), port,
+                    "tablet")
+          .Build(),
       context->GetDiagnostics()));
 
   ProductFilter filter({"tablet"});
@@ -65,15 +73,17 @@
 
   ResourceTable table;
   ASSERT_TRUE(table.AddResource(
-      test::ParseNameOrDie("android:string/one"),
-      ConfigDescription::DefaultConfig(), "",
-      test::ValueBuilder<Id>().SetSource(Source("default.xml")).Build(),
+      NewResourceBuilder(test::ParseNameOrDie("android:string/one"))
+          .SetValue(test::ValueBuilder<Id>().SetSource(Source("default.xml")).Build())
+          .Build(),
       context->GetDiagnostics()));
+
   ASSERT_TRUE(table.AddResource(
-      test::ParseNameOrDie("android:string/one"),
-      ConfigDescription::DefaultConfig(), "tablet",
-      test::ValueBuilder<Id>().SetSource(Source("tablet.xml")).Build(),
+      NewResourceBuilder(test::ParseNameOrDie("android:string/one"))
+          .SetValue(test::ValueBuilder<Id>().SetSource(Source("tablet.xml")).Build(), {}, "tablet")
+          .Build(),
       context->GetDiagnostics()));
+  ;
 
   ProductFilter filter(std::unordered_set<std::string>{});
   ASSERT_TRUE(filter.Consume(context.get(), &table));
@@ -91,19 +101,22 @@
 
   ResourceTable table;
   ASSERT_TRUE(table.AddResource(
-      test::ParseNameOrDie("android:string/one"),
-      ConfigDescription::DefaultConfig(), "",
-      test::ValueBuilder<Id>().SetSource(Source("default.xml")).Build(),
+      NewResourceBuilder(test::ParseNameOrDie("android:string/one"))
+          .SetValue(test::ValueBuilder<Id>().SetSource(Source("default.xml")).Build())
+          .Build(),
       context->GetDiagnostics()));
+
   ASSERT_TRUE(table.AddResource(
-      test::ParseNameOrDie("android:string/one"),
-      ConfigDescription::DefaultConfig(), "tablet",
-      test::ValueBuilder<Id>().SetSource(Source("tablet.xml")).Build(),
+      NewResourceBuilder(test::ParseNameOrDie("android:string/one"))
+          .SetValue(test::ValueBuilder<Id>().SetSource(Source("tablet.xml")).Build(), {}, "tablet")
+          .Build(),
       context->GetDiagnostics()));
+
   ASSERT_TRUE(table.AddResource(
-      test::ParseNameOrDie("android:string/one"),
-      ConfigDescription::DefaultConfig(), "no-sdcard",
-      test::ValueBuilder<Id>().SetSource(Source("no-sdcard.xml")).Build(),
+      NewResourceBuilder(test::ParseNameOrDie("android:string/one"))
+          .SetValue(test::ValueBuilder<Id>().SetSource(Source("no-sdcard.xml")).Build(), {},
+                    "no-sdcard")
+          .Build(),
       context->GetDiagnostics()));
 
   ProductFilter filter({"tablet", "no-sdcard"});
@@ -114,15 +127,17 @@
   std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
 
   ResourceTable table;
+  ASSERT_TRUE(
+      table.AddResource(NewResourceBuilder(test::ParseNameOrDie("android:string/one"))
+                            .SetValue(test::ValueBuilder<Id>().SetSource(Source(".xml")).Build())
+                            .Build(),
+                        context->GetDiagnostics()));
+
   ASSERT_TRUE(table.AddResource(
-      test::ParseNameOrDie("android:string/one"),
-      ConfigDescription::DefaultConfig(), "",
-      test::ValueBuilder<Id>().SetSource(Source(".xml")).Build(),
-      context->GetDiagnostics()));
-  ASSERT_TRUE(table.AddResource(
-      test::ParseNameOrDie("android:string/one"),
-      ConfigDescription::DefaultConfig(), "default",
-      test::ValueBuilder<Id>().SetSource(Source("default.xml")).Build(),
+      NewResourceBuilder(test::ParseNameOrDie("android:string/one"))
+          .SetValue(test::ValueBuilder<Id>().SetSource(Source("default.xml")).Build(), {},
+                    "default")
+          .Build(),
       context->GetDiagnostics()));
 
   ProductFilter filter(std::unordered_set<std::string>{});
diff --git a/tools/aapt2/link/ReferenceLinker_test.cpp b/tools/aapt2/link/ReferenceLinker_test.cpp
index a31ce94..228c5bd74 100644
--- a/tools/aapt2/link/ReferenceLinker_test.cpp
+++ b/tools/aapt2/link/ReferenceLinker_test.cpp
@@ -28,7 +28,6 @@
 TEST(ReferenceLinkerTest, LinkSimpleReferences) {
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.test", 0x7f)
           .AddReference("com.app.test:string/foo", ResourceId(0x7f020000),
                         "com.app.test:string/bar")
 
@@ -75,7 +74,6 @@
 TEST(ReferenceLinkerTest, LinkStyleAttributes) {
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.test", 0x7f)
           .AddValue("com.app.test:style/Theme",
                     test::StyleBuilder()
                         .SetParent("android:style/Theme.Material")
@@ -155,7 +153,6 @@
 
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.test", 0x7f)
           .AddValue("com.app.test:style/Theme", ResourceId(0x7f020000),
                     test::StyleBuilder()
                         .AddItem("com.android.support:attr/foo",
@@ -176,7 +173,6 @@
 TEST(ReferenceLinkerTest, FailToLinkPrivateSymbols) {
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.test", 0x7f)
           .AddReference("com.app.test:string/foo", ResourceId(0x7f020000),
                         "android:string/hidden")
           .Build();
@@ -201,7 +197,6 @@
 TEST(ReferenceLinkerTest, FailToLinkPrivateMangledSymbols) {
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.test", 0x7f)
           .AddReference("com.app.test:string/foo", ResourceId(0x7f020000),
                         "com.app.lib:string/hidden")
           .Build();
@@ -229,7 +224,6 @@
 TEST(ReferenceLinkerTest, FailToLinkPrivateStyleAttributes) {
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.test", 0x7f)
           .AddValue("com.app.test:style/Theme",
                     test::StyleBuilder()
                         .AddItem("android:attr/hidden",
diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp
index ad56092..4ef2882 100644
--- a/tools/aapt2/link/TableMerger.cpp
+++ b/tools/aapt2/link/TableMerger.cpp
@@ -33,8 +33,7 @@
                          const TableMergerOptions& options)
     : context_(context), main_table_(out_table), options_(options) {
   // Create the desired package that all tables will be merged into.
-  main_package_ =
-      main_table_->CreatePackage(context_->GetCompilationPackage(), context_->GetPackageId());
+  main_package_ = main_table_->FindOrCreatePackage(context_->GetCompilationPackage());
   CHECK(main_package_ != nullptr) << "package name or ID already taken";
 }
 
@@ -85,20 +84,9 @@
 
 static bool MergeType(IAaptContext* context, const Source& src, ResourceTableType* dst_type,
                       ResourceTableType* src_type) {
-  if (src_type->visibility_level > dst_type->visibility_level) {
+  if (src_type->visibility_level >= dst_type->visibility_level) {
     // The incoming type's visibility is stronger, so we should override the visibility.
-    if (src_type->visibility_level == Visibility::Level::kPublic) {
-      // Only copy the ID if the source is public, or else the ID is meaningless.
-      dst_type->id = src_type->id;
-    }
     dst_type->visibility_level = src_type->visibility_level;
-  } else if (dst_type->visibility_level == Visibility::Level::kPublic &&
-             src_type->visibility_level == Visibility::Level::kPublic && dst_type->id &&
-             src_type->id && dst_type->id.value() != src_type->id.value()) {
-    // Both types are public and have different IDs.
-    context->GetDiagnostics()->Error(DiagMessage(src) << "cannot merge type '" << src_type->type
-                                                      << "': conflicting public IDs");
-    return false;
   }
   return true;
 }
@@ -347,7 +335,7 @@
   file_ref->type = file_desc.type;
   file_ref->file = file;
 
-  ResourceTablePackage* pkg = table.CreatePackage(file_desc.name.package, 0x0);
+  ResourceTablePackage* pkg = table.FindOrCreatePackage(file_desc.name.package);
   pkg->FindOrCreateType(file_desc.name.type)
       ->FindOrCreateEntry(file_desc.name.entry)
       ->FindOrCreateValue(file_desc.config, {})
diff --git a/tools/aapt2/link/TableMerger_test.cpp b/tools/aapt2/link/TableMerger_test.cpp
index 69cf5ee..4358fb5 100644
--- a/tools/aapt2/link/TableMerger_test.cpp
+++ b/tools/aapt2/link/TableMerger_test.cpp
@@ -55,16 +55,13 @@
 TEST_F(TableMergerTest, SimpleMerge) {
   std::unique_ptr<ResourceTable> table_a =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.a", 0x7f)
           .AddReference("com.app.a:id/foo", "com.app.a:id/bar")
           .AddReference("com.app.a:id/bar", "com.app.b:id/foo")
-          .AddValue(
-              "com.app.a:styleable/view",
-              test::StyleableBuilder().AddItem("com.app.b:id/foo").Build())
+          .AddValue("com.app.a:styleable/view",
+                    test::StyleableBuilder().AddItem("com.app.b:id/foo").Build())
           .Build();
 
   std::unique_ptr<ResourceTable> table_b = test::ResourceTableBuilder()
-                                               .SetPackageId("com.app.b", 0x7f)
                                                .AddSimple("com.app.b:id/foo")
                                                .Build();
 
@@ -129,12 +126,10 @@
 
   std::unique_ptr<ResourceTable> table_a =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.a", 0x7f)
           .AddFileReference("com.app.a:xml/file", "res/xml/file.xml", &file_a)
           .Build();
   std::unique_ptr<ResourceTable> table_b =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.b", 0x7f)
           .AddFileReference("com.app.b:xml/file", "res/xml/file.xml", &file_b)
           .Build();
 
@@ -158,12 +153,10 @@
 TEST_F(TableMergerTest, OverrideResourceWithOverlay) {
   std::unique_ptr<ResourceTable> base =
       test::ResourceTableBuilder()
-          .SetPackageId("", 0x00)
           .AddValue("bool/foo", ResourceUtils::TryParseBool("true"))
           .Build();
   std::unique_ptr<ResourceTable> overlay =
       test::ResourceTableBuilder()
-          .SetPackageId("", 0x00)
           .AddValue("bool/foo", ResourceUtils::TryParseBool("false"))
           .Build();
 
@@ -194,14 +187,12 @@
 
   std::unique_ptr<ResourceTable> base =
       test::ResourceTableBuilder()
-          .SetPackageId("", 0x00)
           .AddValue("bool/foo", std::move(foo_original))
           .AddValue("bool/bar", std::move(bar_original))
           .Build();
 
   std::unique_ptr<ResourceTable> overlay =
       test::ResourceTableBuilder()
-          .SetPackageId("", 0x00)
           .AddValue("bool/foo", std::move(foo_overlay))
           .AddValue("bool/bar", std::move(bar_overlay))
           .AddValue("bool/baz", std::move(baz_overlay))
@@ -226,12 +217,10 @@
 TEST_F(TableMergerTest, OverrideSameResourceIdsWithOverlay) {
   std::unique_ptr<ResourceTable> base =
       test::ResourceTableBuilder()
-          .SetPackageId("", 0x7f)
           .SetSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), Visibility::Level::kPublic)
           .Build();
   std::unique_ptr<ResourceTable> overlay =
       test::ResourceTableBuilder()
-          .SetPackageId("", 0x7f)
           .SetSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), Visibility::Level::kPublic)
           .Build();
 
@@ -247,12 +236,10 @@
 TEST_F(TableMergerTest, FailToOverrideConflictingTypeIdsWithOverlay) {
   std::unique_ptr<ResourceTable> base =
       test::ResourceTableBuilder()
-          .SetPackageId("", 0x7f)
           .SetSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), Visibility::Level::kPublic)
           .Build();
   std::unique_ptr<ResourceTable> overlay =
       test::ResourceTableBuilder()
-          .SetPackageId("", 0x7f)
           .SetSymbolState("bool/foo", ResourceId(0x7f, 0x02, 0x0001), Visibility::Level::kPublic)
           .Build();
 
@@ -268,12 +255,10 @@
 TEST_F(TableMergerTest, FailToOverrideConflictingEntryIdsWithOverlay) {
   std::unique_ptr<ResourceTable> base =
       test::ResourceTableBuilder()
-          .SetPackageId("", 0x7f)
           .SetSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), Visibility::Level::kPublic)
           .Build();
   std::unique_ptr<ResourceTable> overlay =
       test::ResourceTableBuilder()
-          .SetPackageId("", 0x7f)
           .SetSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0002), Visibility::Level::kPublic)
           .Build();
 
@@ -289,12 +274,10 @@
 TEST_F(TableMergerTest, FailConflictingVisibility) {
   std::unique_ptr<ResourceTable> base =
       test::ResourceTableBuilder()
-          .SetPackageId("", 0x7f)
           .SetSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), Visibility::Level::kPublic)
           .Build();
   std::unique_ptr<ResourceTable> overlay =
       test::ResourceTableBuilder()
-          .SetPackageId("", 0x7f)
           .SetSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), Visibility::Level::kPrivate)
           .Build();
 
@@ -318,11 +301,9 @@
 }
 
 TEST_F(TableMergerTest, MergeAddResourceFromOverlay) {
-  std::unique_ptr<ResourceTable> table_a =
-      test::ResourceTableBuilder().SetPackageId("", 0x7f).Build();
+  std::unique_ptr<ResourceTable> table_a = test::ResourceTableBuilder().Build();
   std::unique_ptr<ResourceTable> table_b =
       test::ResourceTableBuilder()
-          .SetPackageId("", 0x7f)
           .SetSymbolState("bool/foo", {}, Visibility::Level::kUndefined, true /*allow new overlay*/)
           .AddValue("bool/foo", ResourceUtils::TryParseBool("true"))
           .Build();
@@ -337,11 +318,9 @@
 }
 
 TEST_F(TableMergerTest, MergeAddResourceFromOverlayWithAutoAddOverlay) {
-  std::unique_ptr<ResourceTable> table_a =
-      test::ResourceTableBuilder().SetPackageId("", 0x7f).Build();
+  std::unique_ptr<ResourceTable> table_a = test::ResourceTableBuilder().Build();
   std::unique_ptr<ResourceTable> table_b =
       test::ResourceTableBuilder()
-          .SetPackageId("", 0x7f)
           .AddValue("bool/foo", ResourceUtils::TryParseBool("true"))
           .Build();
 
@@ -355,11 +334,9 @@
 }
 
 TEST_F(TableMergerTest, FailToMergeNewResourceWithoutAutoAddOverlay) {
-  std::unique_ptr<ResourceTable> table_a =
-      test::ResourceTableBuilder().SetPackageId("", 0x7f).Build();
+  std::unique_ptr<ResourceTable> table_a = test::ResourceTableBuilder().Build();
   std::unique_ptr<ResourceTable> table_b =
       test::ResourceTableBuilder()
-          .SetPackageId("", 0x7f)
           .AddValue("bool/foo", ResourceUtils::TryParseBool("true"))
           .Build();
 
@@ -375,7 +352,6 @@
 TEST_F(TableMergerTest, OverlaidStyleablesAndStylesShouldBeMerged) {
   std::unique_ptr<ResourceTable> table_a =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.a", 0x7f)
           .AddValue("com.app.a:styleable/Foo",
                     test::StyleableBuilder()
                         .AddItem("com.app.a:attr/bar")
@@ -391,7 +367,6 @@
 
   std::unique_ptr<ResourceTable> table_b =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.a", 0x7f)
           .AddValue("com.app.a:styleable/Foo", test::StyleableBuilder()
                                                    .AddItem("com.app.a:attr/bat")
                                                    .AddItem("com.app.a:attr/foo")
@@ -441,7 +416,6 @@
 TEST_F(TableMergerTest, OverrideStyleInsteadOfOverlaying) {
   std::unique_ptr<ResourceTable> table_a =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.a", 0x7f)
           .AddValue(
               "com.app.a:styleable/MyWidget",
               test::StyleableBuilder().AddItem("com.app.a:attr/foo", ResourceId(0x1234)).Build())
@@ -452,7 +426,6 @@
           .Build();
   std::unique_ptr<ResourceTable> table_b =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.a", 0x7f)
           .AddValue(
               "com.app.a:styleable/MyWidget",
               test::StyleableBuilder().AddItem("com.app.a:attr/bar", ResourceId(0x5678)).Build())
@@ -494,13 +467,11 @@
 
   std::unique_ptr<ResourceTable> table_a =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.a", 0x7f)
           .SetOverlayable("bool/foo", overlayable_item)
           .Build();
 
   std::unique_ptr<ResourceTable> table_b =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.a", 0x7f)
           .AddSimple("bool/foo")
           .Build();
 
@@ -527,7 +498,6 @@
                                                   "overlay://customization");
   std::unique_ptr<ResourceTable> table_a =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.a", 0x7f)
           .AddSimple("bool/foo")
           .Build();
 
@@ -536,7 +506,6 @@
   overlayable_item.policies |= PolicyFlags::SYSTEM_PARTITION;
   std::unique_ptr<ResourceTable> table_b =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.a", 0x7f)
           .SetOverlayable("bool/foo", overlayable_item)
           .Build();
 
@@ -565,7 +534,6 @@
   overlayable_item_first.policies |= PolicyFlags::PRODUCT_PARTITION;
   std::unique_ptr<ResourceTable> table_a =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.a", 0x7f)
           .SetOverlayable("bool/foo", overlayable_item_first)
           .Build();
 
@@ -575,7 +543,6 @@
   overlayable_item_second.policies |= PolicyFlags::PRODUCT_PARTITION;
   std::unique_ptr<ResourceTable> table_b =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.a", 0x7f)
           .SetOverlayable("bool/foo", overlayable_item_second)
           .Build();
 
@@ -594,7 +561,6 @@
   overlayable_item_first.policies |= PolicyFlags::PRODUCT_PARTITION;
   std::unique_ptr<ResourceTable> table_a =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.a", 0x7f)
           .SetOverlayable("bool/foo", overlayable_item_first)
           .Build();
 
@@ -604,7 +570,6 @@
   overlayable_item_second.policies |= PolicyFlags::PRODUCT_PARTITION;
   std::unique_ptr<ResourceTable> table_b =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.a", 0x7f)
           .SetOverlayable("bool/foo", overlayable_item_second)
           .Build();
 
@@ -623,7 +588,6 @@
   overlayable_item_first.policies |= PolicyFlags::PRODUCT_PARTITION;
   std::unique_ptr<ResourceTable> table_a =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.a", 0x7f)
           .SetOverlayable("bool/foo", overlayable_item_first)
           .Build();
 
@@ -633,7 +597,6 @@
   overlayable_item_second.policies |= PolicyFlags::SIGNATURE;
   std::unique_ptr<ResourceTable> table_b =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.a", 0x7f)
           .SetOverlayable("bool/foo", overlayable_item_second)
           .Build();
 
@@ -653,7 +616,6 @@
   overlayable_item_first.policies |= PolicyFlags::PRODUCT_PARTITION;
   std::unique_ptr<ResourceTable> table_a =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.a", 0x7f)
           .SetOverlayable("bool/foo", overlayable_item_first)
           .Build();
 
@@ -661,7 +623,6 @@
   overlayable_item_second.policies |= PolicyFlags::PRODUCT_PARTITION;
   std::unique_ptr<ResourceTable> table_b =
       test::ResourceTableBuilder()
-          .SetPackageId("com.app.a", 0x7f)
           .SetOverlayable("bool/foo", overlayable_item_second)
           .Build();
 
diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp
index 98ee63d..de72334 100644
--- a/tools/aapt2/process/SymbolTable.cpp
+++ b/tools/aapt2/process/SymbolTable.cpp
@@ -197,9 +197,9 @@
   std::unique_ptr<SymbolTable::Symbol> symbol = util::make_unique<SymbolTable::Symbol>();
   symbol->is_public = (sr.entry->visibility.level == Visibility::Level::kPublic);
 
-  if (sr.package->id && sr.type->id && sr.entry->id) {
-    symbol->id = ResourceId(sr.package->id.value(), sr.type->id.value(), sr.entry->id.value());
-    symbol->is_dynamic = (sr.package->id.value() == 0);
+  if (sr.entry->id) {
+    symbol->id = sr.entry->id.value();
+    symbol->is_dynamic = (sr.entry->id.value().package_id() == 0);
   }
 
   if (name.type == ResourceType::kAttr || name.type == ResourceType::kAttrPrivate) {
diff --git a/tools/aapt2/split/TableSplitter.cpp b/tools/aapt2/split/TableSplitter.cpp
index 6a67271..2f319b1 100644
--- a/tools/aapt2/split/TableSplitter.cpp
+++ b/tools/aapt2/split/TableSplitter.cpp
@@ -185,7 +185,7 @@
     // Initialize all packages for splits.
     for (size_t idx = 0; idx < split_count; idx++) {
       ResourceTable* split_table = splits_[idx].get();
-      split_table->CreatePackage(pkg->name, pkg->id);
+      split_table->FindOrCreatePackage(pkg->name);
     }
 
     for (auto& type : pkg->types) {
@@ -241,10 +241,7 @@
             // not have actual values for each type/entry.
             ResourceTablePackage* split_pkg = split_table->FindPackage(pkg->name);
             ResourceTableType* split_type = split_pkg->FindOrCreateType(type->type);
-            if (!split_type->id) {
-              split_type->id = type->id;
-              split_type->visibility_level = type->visibility_level;
-            }
+            split_type->visibility_level = type->visibility_level;
 
             ResourceEntry* split_entry = split_type->FindOrCreateEntry(entry->name);
             if (!split_entry->id) {
diff --git a/tools/aapt2/split/TableSplitter_test.cpp b/tools/aapt2/split/TableSplitter_test.cpp
index cdf0738..c6a2ff3 100644
--- a/tools/aapt2/split/TableSplitter_test.cpp
+++ b/tools/aapt2/split/TableSplitter_test.cpp
@@ -193,15 +193,23 @@
   ResourceTable table;
 
   const ResourceName foo = test::ParseNameOrDie("android:string/foo");
-  ASSERT_TRUE(table.AddResource(foo, test::ParseConfigOrDie("land-hdpi"), {},
-                                util::make_unique<Id>(),
-                                test::GetDiagnostics()));
-  ASSERT_TRUE(table.AddResource(foo, test::ParseConfigOrDie("land-xhdpi"), {},
-                                util::make_unique<Id>(),
-                                test::GetDiagnostics()));
-  ASSERT_TRUE(table.AddResource(foo, test::ParseConfigOrDie("land-xxhdpi"), {},
-                                util::make_unique<Id>(),
-                                test::GetDiagnostics()));
+  ASSERT_TRUE(
+      table.AddResource(NewResourceBuilder(foo)
+                            .SetValue(util::make_unique<Id>(), test::ParseConfigOrDie("land-hdpi"))
+                            .Build(),
+                        test::GetDiagnostics()));
+
+  ASSERT_TRUE(
+      table.AddResource(NewResourceBuilder(foo)
+                            .SetValue(util::make_unique<Id>(), test::ParseConfigOrDie("land-xhdpi"))
+                            .Build(),
+                        test::GetDiagnostics()));
+
+  ASSERT_TRUE(table.AddResource(
+      NewResourceBuilder(foo)
+          .SetValue(util::make_unique<Id>(), test::ParseConfigOrDie("land-xxhdpi"))
+          .Build(),
+      test::GetDiagnostics()));
 
   std::vector<SplitConstraints> constraints;
   constraints.push_back(
diff --git a/tools/aapt2/test/Builders.cpp b/tools/aapt2/test/Builders.cpp
index 9a93f2a..4816596 100644
--- a/tools/aapt2/test/Builders.cpp
+++ b/tools/aapt2/test/Builders.cpp
@@ -34,13 +34,6 @@
 namespace aapt {
 namespace test {
 
-ResourceTableBuilder& ResourceTableBuilder::SetPackageId(const StringPiece& package_name,
-                                                         uint8_t id) {
-  ResourceTablePackage* package = table_->CreatePackage(package_name, id);
-  CHECK(package != nullptr);
-  return *this;
-}
-
 ResourceTableBuilder& ResourceTableBuilder::AddSimple(const StringPiece& name,
                                                       const ResourceId& id) {
   return AddValue(name, id, util::make_unique<Id>());
@@ -118,8 +111,13 @@
                                                      const ResourceId& id,
                                                      std::unique_ptr<Value> value) {
   ResourceName res_name = ParseNameOrDie(name);
-  CHECK(table_->AddResourceWithIdMangled(res_name, id, config, {}, std::move(value),
-                                         GetDiagnostics()));
+  NewResourceBuilder builder(res_name);
+  builder.SetValue(std::move(value), config).SetAllowMangled(true);
+  if (id.id != 0U) {
+    builder.SetId(id);
+  }
+
+  CHECK(table_->AddResource(builder.Build(), GetDiagnostics()));
   return *this;
 }
 
@@ -128,10 +126,13 @@
                                                            Visibility::Level level,
                                                            bool allow_new) {
   ResourceName res_name = ParseNameOrDie(name);
-  Visibility visibility;
-  visibility.level = level;
-  CHECK(table_->SetVisibilityWithIdMangled(res_name, visibility, id, GetDiagnostics()));
-  CHECK(table_->SetAllowNewMangled(res_name, AllowNew{}, GetDiagnostics()));
+  NewResourceBuilder builder(res_name);
+  builder.SetVisibility({level}).SetAllowNew({}).SetAllowMangled(true);
+  if (id.id != 0U) {
+    builder.SetId(id);
+  }
+
+  CHECK(table_->AddResource(builder.Build(), GetDiagnostics()));
   return *this;
 }
 
@@ -139,7 +140,14 @@
                                                            const OverlayableItem& overlayable) {
 
   ResourceName res_name = ParseNameOrDie(name);
-  CHECK(table_->SetOverlayable(res_name, overlayable, GetDiagnostics()));
+  CHECK(table_->AddResource(
+      NewResourceBuilder(res_name).SetOverlayable(overlayable).SetAllowMangled(true).Build(),
+      GetDiagnostics()));
+  return *this;
+}
+
+ResourceTableBuilder& ResourceTableBuilder::Add(NewResource&& res) {
+  CHECK(table_->AddResource(std::move(res), GetDiagnostics()));
   return *this;
 }
 
diff --git a/tools/aapt2/test/Builders.h b/tools/aapt2/test/Builders.h
index c971a1b..3ff955d 100644
--- a/tools/aapt2/test/Builders.h
+++ b/tools/aapt2/test/Builders.h
@@ -39,7 +39,6 @@
  public:
   ResourceTableBuilder() = default;
 
-  ResourceTableBuilder& SetPackageId(const android::StringPiece& package_name, uint8_t id);
   ResourceTableBuilder& AddSimple(const android::StringPiece& name, const ResourceId& id = {});
   ResourceTableBuilder& AddSimple(const android::StringPiece& name,
                                   const android::ConfigDescription& config,
@@ -75,6 +74,7 @@
                                        Visibility::Level level, bool allow_new = false);
   ResourceTableBuilder& SetOverlayable(const android::StringPiece& name,
                                        const OverlayableItem& overlayable);
+  ResourceTableBuilder& Add(NewResource&& res);
 
   StringPool* string_pool();
   std::unique_ptr<ResourceTable> Build();