Merge "Reset to LiftReveal when going to sleep due to timing out, after a biometric auth." into sc-dev
diff --git a/apex/appsearch/framework/Android.bp b/apex/appsearch/framework/Android.bp
index cd9be9b..8964668 100644
--- a/apex/appsearch/framework/Android.bp
+++ b/apex/appsearch/framework/Android.bp
@@ -57,12 +57,8 @@
         // This list must be kept in sync with jarjar.txt
         "modules-utils-preconditions",
     ],
-    libs: ["unsupportedappusage"], // TODO(b/181887768) should be removed
     defaults: ["framework-module-defaults"],
     permitted_packages: ["android.app.appsearch"],
-    aidl: {
-        include_dirs: ["frameworks/base/core/java"], // TODO(b/146218515) should be removed
-    },
     jarjar_rules: "jarjar-rules.txt",
     apex_available: ["com.android.appsearch"],
     impl_library_visibility: [
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
index b5e3662..82b6d62 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
@@ -25,7 +25,6 @@
 import android.app.appsearch.aidl.IAppSearchResultCallback;
 import android.app.appsearch.exceptions.AppSearchException;
 import android.app.appsearch.util.SchemaMigrationUtil;
-import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.SystemClock;
@@ -309,19 +308,6 @@
     }
 
     /**
-     * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
-     * @hide
-     */
-    @Deprecated
-    @UnsupportedAppUsage
-    public void getByUri(
-            @NonNull GetByUriRequest request,
-            @NonNull @CallbackExecutor Executor executor,
-            @NonNull BatchResultCallback<String, GenericDocument> callback) {
-        getByDocumentId(request.toGetByDocumentIdRequest(), executor, callback);
-    }
-
-    /**
      * Gets {@link GenericDocument} objects by document IDs in a namespace from the {@link
      * AppSearchSession} database.
      *
@@ -521,19 +507,6 @@
     }
 
     /**
-     * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
-     * @hide
-     */
-    @Deprecated
-    @UnsupportedAppUsage
-    public void remove(
-            @NonNull RemoveByUriRequest request,
-            @NonNull @CallbackExecutor Executor executor,
-            @NonNull BatchResultCallback<String, Void> callback) {
-        remove(request.toRemoveByDocumentIdRequest(), executor, callback);
-    }
-
-    /**
      * Removes {@link GenericDocument} objects by document IDs in a namespace from the {@link
      * AppSearchSession} database.
      *
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchSchema.java b/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchSchema.java
index 0ee5e65..2e04d71 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchSchema.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchSchema.java
@@ -22,7 +22,6 @@
 import android.app.appsearch.exceptions.IllegalSchemaException;
 import android.app.appsearch.util.BundleUtil;
 import android.app.appsearch.util.IndentingStringBuilder;
-import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.util.ArraySet;
 
@@ -643,60 +642,8 @@
         }
     }
 
-    /**
-     * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
-     * @hide
-     */
-    @Deprecated
-    public static class Int64PropertyConfig extends PropertyConfig {
-        @UnsupportedAppUsage
-        Int64PropertyConfig(@NonNull Bundle bundle) {
-            super(bundle);
-        }
-
-        /** Builder for {@link Int64PropertyConfig}. */
-        public static final class Builder {
-            private final String mPropertyName;
-            private @Cardinality int mCardinality = CARDINALITY_OPTIONAL;
-
-            /** Creates a new {@link Int64PropertyConfig.Builder}. */
-            @UnsupportedAppUsage
-            public Builder(@NonNull String propertyName) {
-                mPropertyName = Objects.requireNonNull(propertyName);
-            }
-
-            /**
-             * The cardinality of the property (whether it is optional, required or repeated).
-             *
-             * <p>If this method is not called, the default cardinality is {@link
-             * PropertyConfig#CARDINALITY_OPTIONAL}.
-             */
-            @SuppressWarnings("MissingGetterMatchingBuilder") // getter defined in superclass
-            @NonNull
-            @UnsupportedAppUsage
-            public Int64PropertyConfig.Builder setCardinality(@Cardinality int cardinality) {
-                Preconditions.checkArgumentInRange(
-                        cardinality, CARDINALITY_REPEATED, CARDINALITY_REQUIRED, "cardinality");
-                mCardinality = cardinality;
-                return this;
-            }
-
-            /** Constructs a new {@link Int64PropertyConfig} from the contents of this builder. */
-            @NonNull
-            @UnsupportedAppUsage
-            public Int64PropertyConfig build() {
-                Bundle bundle = new Bundle();
-                bundle.putString(NAME_FIELD, mPropertyName);
-                bundle.putInt(DATA_TYPE_FIELD, DATA_TYPE_LONG);
-                bundle.putInt(CARDINALITY_FIELD, mCardinality);
-                return new Int64PropertyConfig(bundle);
-            }
-        }
-    }
-
     /** Configuration for a property containing a 64-bit integer. */
-    // TODO(b/181887768): This should extend directly from PropertyConfig
-    public static final class LongPropertyConfig extends Int64PropertyConfig {
+    public static final class LongPropertyConfig extends PropertyConfig {
         LongPropertyConfig(@NonNull Bundle bundle) {
             super(bundle);
         }
@@ -896,8 +843,7 @@
         /** Builder for {@link DocumentPropertyConfig}. */
         public static final class Builder {
             private final String mPropertyName;
-            // TODO(b/181887768): This should be final
-            private String mSchemaType;
+            private final String mSchemaType;
             private @Cardinality int mCardinality = CARDINALITY_OPTIONAL;
             private boolean mShouldIndexNestedProperties = false;
 
@@ -916,29 +862,6 @@
             }
 
             /**
-             * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
-             * @hide
-             */
-            @Deprecated
-            @UnsupportedAppUsage
-            public Builder(@NonNull String propertyName) {
-                mPropertyName = Objects.requireNonNull(propertyName);
-                mSchemaType = null;
-            }
-
-            /**
-             * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
-             * @hide
-             */
-            @Deprecated
-            @UnsupportedAppUsage
-            @NonNull
-            public Builder setSchemaType(@NonNull String schemaType) {
-                mSchemaType = Objects.requireNonNull(schemaType);
-                return this;
-            }
-
-            /**
              * The cardinality of the property (whether it is optional, required or repeated).
              *
              * <p>If this method is not called, the default cardinality is {@link
@@ -967,18 +890,6 @@
                 return this;
             }
 
-            /**
-             * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
-             * @hide
-             */
-            @Deprecated
-            @UnsupportedAppUsage
-            @NonNull
-            public DocumentPropertyConfig.Builder setIndexNestedProperties(
-                    boolean indexNestedProperties) {
-                return setShouldIndexNestedProperties(indexNestedProperties);
-            }
-
             /** Constructs a new {@link PropertyConfig} from the contents of this builder. */
             @NonNull
             public DocumentPropertyConfig build() {
@@ -987,9 +898,7 @@
                 bundle.putInt(DATA_TYPE_FIELD, DATA_TYPE_DOCUMENT);
                 bundle.putInt(CARDINALITY_FIELD, mCardinality);
                 bundle.putBoolean(INDEX_NESTED_PROPERTIES_FIELD, mShouldIndexNestedProperties);
-                // TODO(b/181887768): Remove checkNotNull after the deprecated constructor (which
-                //  is the only way to get null here) is removed
-                bundle.putString(SCHEMA_TYPE_FIELD, Objects.requireNonNull(mSchemaType));
+                bundle.putString(SCHEMA_TYPE_FIELD, mSchemaType);
                 return new DocumentPropertyConfig(bundle);
             }
         }
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/GenericDocument.java b/apex/appsearch/framework/java/external/android/app/appsearch/GenericDocument.java
index c905f95..4d27519 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/GenericDocument.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/GenericDocument.java
@@ -23,7 +23,6 @@
 import android.annotation.SuppressLint;
 import android.app.appsearch.util.BundleUtil;
 import android.app.appsearch.util.IndentingStringBuilder;
-import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.os.Parcelable;
 import android.util.Log;
@@ -51,9 +50,6 @@
 public class GenericDocument {
     private static final String TAG = "AppSearchGenericDocumen";
 
-    /** The maximum {@link String#length} of a {@link String} field. */
-    private static final int MAX_STRING_LENGTH = 20_000;
-
     /** The maximum number of indexed properties a document can have. */
     private static final int MAX_INDEXED_PROPERTIES = 16;
 
@@ -134,17 +130,6 @@
         return mBundle;
     }
 
-    /**
-     * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
-     * @hide
-     */
-    @Deprecated
-    @UnsupportedAppUsage
-    @NonNull
-    public String getUri() {
-        return getId();
-    }
-
     /** Returns the unique identifier of the {@link GenericDocument}. */
     @NonNull
     public String getId() {
@@ -1286,15 +1271,6 @@
             for (int i = 0; i < values.length; i++) {
                 if (values[i] == null) {
                     throw new IllegalArgumentException("The String at " + i + " is null.");
-                } else if (values[i].length() > MAX_STRING_LENGTH) {
-                    throw new IllegalArgumentException(
-                            "The String at "
-                                    + i
-                                    + " length is: "
-                                    + values[i].length()
-                                    + ", which exceeds length limit: "
-                                    + MAX_STRING_LENGTH
-                                    + ".");
                 }
             }
             mProperties.putStringArray(name, values);
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/GetByUriRequest.java b/apex/appsearch/framework/java/external/android/app/appsearch/GetByUriRequest.java
deleted file mode 100644
index 7b05eac..0000000
--- a/apex/appsearch/framework/java/external/android/app/appsearch/GetByUriRequest.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app.appsearch;
-
-import android.annotation.NonNull;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-
-import com.android.internal.util.Preconditions;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
- * @hide
- */
-@Deprecated
-public final class GetByUriRequest {
-    /**
-     * Schema type to be used in {@link GetByUriRequest.Builder#addProjection} to apply property
-     * paths to all results, excepting any types that have had their own, specific property paths
-     * set.
-     */
-    public static final String PROJECTION_SCHEMA_TYPE_WILDCARD = "*";
-
-    private final String mNamespace;
-    private final Set<String> mIds;
-    private final Map<String, List<String>> mTypePropertyPathsMap;
-
-    GetByUriRequest(
-            @NonNull String namespace,
-            @NonNull Set<String> ids,
-            @NonNull Map<String, List<String>> typePropertyPathsMap) {
-        mNamespace = Objects.requireNonNull(namespace);
-        mIds = Objects.requireNonNull(ids);
-        mTypePropertyPathsMap = Objects.requireNonNull(typePropertyPathsMap);
-    }
-
-    /** Returns the namespace attached to the request. */
-    @NonNull
-    public String getNamespace() {
-        return mNamespace;
-    }
-
-    /** Returns the set of document IDs attached to the request. */
-    @NonNull
-    public Set<String> getUris() {
-        return Collections.unmodifiableSet(mIds);
-    }
-
-    /**
-     * Returns a map from schema type to property paths to be used for projection.
-     *
-     * <p>If the map is empty, then all properties will be retrieved for all results.
-     *
-     * <p>Calling this function repeatedly is inefficient. Prefer to retain the Map returned by this
-     * function, rather than calling it multiple times.
-     */
-    @NonNull
-    public Map<String, List<String>> getProjections() {
-        Map<String, List<String>> copy = new ArrayMap<>();
-        for (Map.Entry<String, List<String>> entry : mTypePropertyPathsMap.entrySet()) {
-            copy.put(entry.getKey(), new ArrayList<>(entry.getValue()));
-        }
-        return copy;
-    }
-
-    /**
-     * Returns a map from schema type to property paths to be used for projection.
-     *
-     * <p>If the map is empty, then all properties will be retrieved for all results.
-     *
-     * <p>A more efficient version of {@link #getProjections}, but it returns a modifiable map. This
-     * is not meant to be unhidden and should only be used by internal classes.
-     *
-     * @hide
-     */
-    @NonNull
-    public Map<String, List<String>> getProjectionsInternal() {
-        return mTypePropertyPathsMap;
-    }
-
-    /**
-     * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
-     * @hide
-     */
-    @Deprecated
-    @NonNull
-    public GetByDocumentIdRequest toGetByDocumentIdRequest() {
-        GetByDocumentIdRequest.Builder builder =
-                new GetByDocumentIdRequest.Builder(mNamespace).addIds(mIds);
-        for (Map.Entry<String, List<String>> projection : mTypePropertyPathsMap.entrySet()) {
-            builder.addProjection(projection.getKey(), projection.getValue());
-        }
-        return builder.build();
-    }
-
-    /**
-     * Builder for {@link GetByUriRequest} objects.
-     *
-     * <p>Once {@link #build} is called, the instance can no longer be used.
-     */
-    public static final class Builder {
-        private final String mNamespace;
-        private final Set<String> mIds = new ArraySet<>();
-        private final Map<String, List<String>> mProjectionTypePropertyPaths = new ArrayMap<>();
-        private boolean mBuilt = false;
-
-        /**
-         * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
-         * @hide
-         */
-        @Deprecated
-        @UnsupportedAppUsage
-        public Builder(@NonNull String namespace) {
-            mNamespace = Objects.requireNonNull(namespace);
-        }
-
-        /**
-         * Adds one or more document IDs to the request.
-         *
-         * @throws IllegalStateException if the builder has already been used.
-         */
-        @NonNull
-        public Builder addUris(@NonNull String... ids) {
-            Objects.requireNonNull(ids);
-            return addUris(Arrays.asList(ids));
-        }
-
-        /**
-         * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
-         * @hide
-         */
-        @Deprecated
-        @UnsupportedAppUsage
-        @NonNull
-        public Builder addUris(@NonNull Collection<String> ids) {
-            Preconditions.checkState(!mBuilt, "Builder has already been used");
-            Objects.requireNonNull(ids);
-            mIds.addAll(ids);
-            return this;
-        }
-
-        /**
-         * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
-         * @hide
-         */
-        @Deprecated
-        @UnsupportedAppUsage
-        @NonNull
-        public Builder addProjection(
-                @NonNull String schemaType, @NonNull Collection<String> propertyPaths) {
-            Preconditions.checkState(!mBuilt, "Builder has already been used");
-            Objects.requireNonNull(schemaType);
-            Objects.requireNonNull(propertyPaths);
-            List<String> propertyPathsList = new ArrayList<>(propertyPaths.size());
-            for (String propertyPath : propertyPaths) {
-                Objects.requireNonNull(propertyPath);
-                propertyPathsList.add(propertyPath);
-            }
-            mProjectionTypePropertyPaths.put(schemaType, propertyPathsList);
-            return this;
-        }
-
-        /**
-         * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
-         * @hide
-         */
-        @Deprecated
-        @UnsupportedAppUsage
-        @NonNull
-        public GetByUriRequest build() {
-            Preconditions.checkState(!mBuilt, "Builder has already been used");
-            mBuilt = true;
-            return new GetByUriRequest(mNamespace, mIds, mProjectionTypePropertyPaths);
-        }
-    }
-}
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/RemoveByUriRequest.java b/apex/appsearch/framework/java/external/android/app/appsearch/RemoveByUriRequest.java
deleted file mode 100644
index 9c74966..0000000
--- a/apex/appsearch/framework/java/external/android/app/appsearch/RemoveByUriRequest.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app.appsearch;
-
-import android.annotation.NonNull;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.util.ArraySet;
-
-import com.android.internal.util.Preconditions;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
- * @hide
- */
-@Deprecated
-public final class RemoveByUriRequest {
-    private final String mNamespace;
-    private final Set<String> mIds;
-
-    RemoveByUriRequest(String namespace, Set<String> ids) {
-        mNamespace = namespace;
-        mIds = ids;
-    }
-
-    /** Returns the namespace to remove documents from. */
-    @NonNull
-    public String getNamespace() {
-        return mNamespace;
-    }
-
-    /** Returns the set of document IDs attached to the request. */
-    @NonNull
-    public Set<String> getUris() {
-        return Collections.unmodifiableSet(mIds);
-    }
-
-    /**
-     * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
-     * @hide
-     */
-    @Deprecated
-    @NonNull
-    public RemoveByDocumentIdRequest toRemoveByDocumentIdRequest() {
-        return new RemoveByDocumentIdRequest.Builder(mNamespace).addIds(mIds).build();
-    }
-
-    /**
-     * Builder for {@link RemoveByUriRequest} objects.
-     *
-     * <p>Once {@link #build} is called, the instance can no longer be used.
-     */
-    public static final class Builder {
-        private final String mNamespace;
-        private final Set<String> mIds = new ArraySet<>();
-        private boolean mBuilt = false;
-
-        /**
-         * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
-         * @hide
-         */
-        @Deprecated
-        @UnsupportedAppUsage
-        public Builder(@NonNull String namespace) {
-            mNamespace = Objects.requireNonNull(namespace);
-        }
-
-        /**
-         * Adds one or more document IDs to the request.
-         *
-         * @throws IllegalStateException if the builder has already been used.
-         */
-        @NonNull
-        public Builder addUris(@NonNull String... ids) {
-            Objects.requireNonNull(ids);
-            return addUris(Arrays.asList(ids));
-        }
-
-        /**
-         * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
-         * @hide
-         */
-        @Deprecated
-        @UnsupportedAppUsage
-        @NonNull
-        public Builder addUris(@NonNull Collection<String> ids) {
-            Preconditions.checkState(!mBuilt, "Builder has already been used");
-            Objects.requireNonNull(ids);
-            mIds.addAll(ids);
-            return this;
-        }
-
-        /**
-         * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
-         * @hide
-         */
-        @Deprecated
-        @UnsupportedAppUsage
-        @NonNull
-        public RemoveByUriRequest build() {
-            Preconditions.checkState(!mBuilt, "Builder has already been used");
-            mBuilt = true;
-            return new RemoveByUriRequest(mNamespace, mIds);
-        }
-    }
-}
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/ReportUsageRequest.java b/apex/appsearch/framework/java/external/android/app/appsearch/ReportUsageRequest.java
index c388bde..e807803 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/ReportUsageRequest.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/ReportUsageRequest.java
@@ -18,7 +18,6 @@
 
 import android.annotation.CurrentTimeMillisLong;
 import android.annotation.NonNull;
-import android.compat.annotation.UnsupportedAppUsage;
 
 import java.util.Objects;
 
@@ -67,8 +66,7 @@
     /** Builder for {@link ReportUsageRequest} objects. */
     public static final class Builder {
         private final String mNamespace;
-        // TODO(b/181887768): Make this final
-        private String mDocumentId;
+        private final String mDocumentId;
         private Long mUsageTimestampMillis;
 
         /**
@@ -85,40 +83,6 @@
         }
 
         /**
-         * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
-         * @hide
-         */
-        @Deprecated
-        @UnsupportedAppUsage
-        public Builder(@NonNull String namespace) {
-            mNamespace = Objects.requireNonNull(namespace);
-        }
-
-        /**
-         * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
-         * @hide
-         */
-        @Deprecated
-        @UnsupportedAppUsage
-        @NonNull
-        public Builder setUri(@NonNull String uri) {
-            mDocumentId = uri;
-            return this;
-        }
-
-        /**
-         * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
-         * @hide
-         */
-        @Deprecated
-        @UnsupportedAppUsage
-        @NonNull
-        public ReportUsageRequest.Builder setUsageTimeMillis(
-                @CurrentTimeMillisLong long usageTimestampMillis) {
-            return setUsageTimestampMillis(usageTimestampMillis);
-        }
-
-        /**
          * Sets the timestamp in milliseconds of the usage report (the time at which the document
          * was used).
          *
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/SearchResult.java b/apex/appsearch/framework/java/external/android/app/appsearch/SearchResult.java
index 4beb667..f6a597c 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/SearchResult.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/SearchResult.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 
 import com.android.internal.util.Preconditions;
@@ -84,17 +83,6 @@
     }
 
     /**
-     * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
-     * @hide
-     */
-    @Deprecated
-    @UnsupportedAppUsage
-    @NonNull
-    public List<MatchInfo> getMatches() {
-        return getMatchInfos();
-    }
-
-    /**
      * Returns a list of {@link MatchInfo}s providing information about how the document in {@link
      * #getGenericDocument} matched the query.
      *
@@ -196,17 +184,6 @@
             return this;
         }
 
-        /**
-         * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
-         * @hide
-         */
-        @Deprecated
-        @UnsupportedAppUsage
-        @NonNull
-        public Builder addMatch(@NonNull MatchInfo matchInfo) {
-            return addMatchInfo(matchInfo);
-        }
-
         /** Adds another match to this SearchResult. */
         @NonNull
         public Builder addMatchInfo(@NonNull MatchInfo matchInfo) {
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaResponse.java b/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaResponse.java
index 3e5a2ca..a3a4a23 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaResponse.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaResponse.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.util.ArraySet;
 
@@ -342,17 +341,6 @@
             return mBundle.getString(NAMESPACE_FIELD, /*defaultValue=*/ "");
         }
 
-        /**
-         * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
-         * @hide
-         */
-        @Deprecated
-        @UnsupportedAppUsage
-        @NonNull
-        public String getUri() {
-            return getDocumentId();
-        }
-
         /** Returns the id of the {@link GenericDocument} that failed to be migrated. */
         @NonNull
         public String getDocumentId() {
diff --git a/apex/appsearch/service/Android.bp b/apex/appsearch/service/Android.bp
index b101895..b6521ff 100644
--- a/apex/appsearch/service/Android.bp
+++ b/apex/appsearch/service/Android.bp
@@ -52,7 +52,6 @@
     libs: [
         "framework-appsearch.impl",
         "framework-statsd.stubs.module_lib",
-        "unsupportedappusage", // TODO(b/181887768) should be removed
     ],
     defaults: ["framework-system-server-module-defaults"],
     permitted_packages: [
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchConfig.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchConfig.java
index c44fd40..29048b2 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchConfig.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchConfig.java
@@ -81,6 +81,14 @@
             "sampling_interval_for_batch_call_stats";
     public static final String KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS =
             "sampling_interval_for_put_document_stats";
+    public static final String KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS =
+            "sampling_interval_for_initialize_stats";
+    public static final String KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS =
+            "sampling_interval_for_search_stats";
+    public static final String KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS =
+            "sampling_interval_for_global_search_stats";
+    public static final String KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS =
+            "sampling_interval_for_optimize_stats";
     public static final String KEY_LIMIT_CONFIG_MAX_DOCUMENT_SIZE_BYTES =
             "limit_config_max_document_size_bytes";
     public static final String KEY_LIMIT_CONFIG_MAX_DOCUMENT_COUNT =
@@ -95,6 +103,10 @@
             KEY_SAMPLING_INTERVAL_DEFAULT,
             KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS,
             KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS,
+            KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS,
+            KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS,
+            KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS,
+            KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS,
             KEY_LIMIT_CONFIG_MAX_DOCUMENT_SIZE_BYTES,
             KEY_LIMIT_CONFIG_MAX_DOCUMENT_COUNT,
             KEY_BYTES_OPTIMIZE_THRESHOLD,
@@ -245,6 +257,58 @@
         }
     }
 
+    /**
+     * Returns cached value for sampling interval for initialize.
+     *
+     * <p>For example, sampling_interval=10 means that one out of every 10 stats was logged.
+     */
+    public int getCachedSamplingIntervalForInitializeStats() {
+        synchronized (mLock) {
+            throwIfClosedLocked();
+            return mBundleLocked.getInt(KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS,
+                    getCachedSamplingIntervalDefault());
+        }
+    }
+
+    /**
+     * Returns cached value for sampling interval for search.
+     *
+     * <p>For example, sampling_interval=10 means that one out of every 10 stats was logged.
+     */
+    public int getCachedSamplingIntervalForSearchStats() {
+        synchronized (mLock) {
+            throwIfClosedLocked();
+            return mBundleLocked.getInt(KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS,
+                    getCachedSamplingIntervalDefault());
+        }
+    }
+
+    /**
+     * Returns cached value for sampling interval for globalSearch.
+     *
+     * <p>For example, sampling_interval=10 means that one out of every 10 stats was logged.
+     */
+    public int getCachedSamplingIntervalForGlobalSearchStats() {
+        synchronized (mLock) {
+            throwIfClosedLocked();
+            return mBundleLocked.getInt(KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS,
+                    getCachedSamplingIntervalDefault());
+        }
+    }
+
+    /**
+     * Returns cached value for sampling interval for optimize.
+     *
+     * <p>For example, sampling_interval=10 means that one out of every 10 stats was logged.
+     */
+    public int getCachedSamplingIntervalForOptimizeStats() {
+        synchronized (mLock) {
+            throwIfClosedLocked();
+            return mBundleLocked.getInt(KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS,
+                    getCachedSamplingIntervalDefault());
+        }
+    }
+
     /** Returns the maximum serialized size an indexed document can be, in bytes. */
     public int getCachedLimitConfigMaxDocumentSizeBytes() {
         synchronized (mLock) {
@@ -343,6 +407,10 @@
             case KEY_SAMPLING_INTERVAL_DEFAULT:
             case KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS:
             case KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS:
+            case KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS:
+            case KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS:
+            case KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS:
+            case KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS:
                 synchronized (mLock) {
                     mBundleLocked.putInt(key, properties.getInt(key, DEFAULT_SAMPLING_INTERVAL));
                 }
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 666d497..db23a6d 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -18,7 +18,6 @@
 import static android.app.appsearch.AppSearchResult.throwableToFailedResult;
 import static android.os.Process.INVALID_UID;
 
-import android.Manifest;
 import android.annotation.ElapsedRealtimeLong;
 import android.annotation.NonNull;
 import android.app.appsearch.AppSearchBatchResult;
@@ -60,6 +59,7 @@
 import com.android.server.LocalManagerRegistry;
 import com.android.server.SystemService;
 import com.android.server.appsearch.external.localstorage.stats.CallStats;
+import com.android.server.appsearch.external.localstorage.stats.OptimizeStats;
 import com.android.server.appsearch.external.localstorage.visibilitystore.VisibilityStore;
 import com.android.server.appsearch.stats.StatsCollector;
 import com.android.server.appsearch.util.PackageUtil;
@@ -1354,43 +1354,26 @@
     /**
      * Helper for dealing with incoming user arguments to system service calls.
      *
-     * <p>Takes care of checking permissions and converting USER_CURRENT to the actual current user.
-     *
      * @param requestedUser The user which the caller is requesting to execute as.
      * @param callingUid The actual uid of the caller as determined by Binder.
      * @return the user handle that the call should run as. Will always be a concrete user.
      */
     @NonNull
     private UserHandle handleIncomingUser(@NonNull UserHandle requestedUser, int callingUid) {
-        int callingPid = Binder.getCallingPid();
         UserHandle callingUser = UserHandle.getUserHandleForUid(callingUid);
         if (callingUser.equals(requestedUser)) {
             return requestedUser;
         }
+
         // Duplicates UserController#ensureNotSpecialUser
         if (requestedUser.getIdentifier() < 0) {
             throw new IllegalArgumentException(
                     "Call does not support special user " + requestedUser);
         }
-        boolean canInteractAcrossUsers = mContext.checkPermission(
-                Manifest.permission.INTERACT_ACROSS_USERS,
-                callingPid,
-                callingUid) == PackageManager.PERMISSION_GRANTED;
-        if (!canInteractAcrossUsers) {
-            canInteractAcrossUsers = mContext.checkPermission(
-                    Manifest.permission.INTERACT_ACROSS_USERS_FULL,
-                    callingPid,
-                    callingUid) == PackageManager.PERMISSION_GRANTED;
-        }
-        if (canInteractAcrossUsers) {
-            return requestedUser;
-        }
+
         throw new SecurityException(
-                "Permission denied while calling from uid " + callingUid
-                        + " with " + requestedUser + "; Need to run as either the calling user ("
-                        + callingUser + "), or with one of the following permissions: "
-                        + Manifest.permission.INTERACT_ACROSS_USERS + " or "
-                        + Manifest.permission.INTERACT_ACROSS_USERS_FULL);
+                "Requested user, " + requestedUser + ", is not the same as the calling user, "
+                        + callingUser + ".");
     }
 
     /**
@@ -1497,20 +1480,42 @@
 
     private void checkForOptimize(AppSearchUserInstance instance, int mutateBatchSize) {
         EXECUTOR.execute(() -> {
+            long totalLatencyStartMillis = SystemClock.elapsedRealtime();
+            OptimizeStats.Builder builder = new OptimizeStats.Builder();
             try {
-                instance.getAppSearchImpl().checkForOptimize(mutateBatchSize);
+                instance.getAppSearchImpl().checkForOptimize(mutateBatchSize, builder);
             } catch (AppSearchException e) {
                 Log.w(TAG, "Error occurred when check for optimize", e);
+            } finally {
+                OptimizeStats oStats = builder
+                        .setTotalLatencyMillis(
+                                (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
+                        .build();
+                if (oStats.getOriginalDocumentCount() > 0) {
+                    // see if optimize has been run by checking originalDocumentCount
+                    instance.getLogger().logStats(oStats);
+                }
             }
         });
     }
 
     private void checkForOptimize(AppSearchUserInstance instance) {
         EXECUTOR.execute(() -> {
+            long totalLatencyStartMillis = SystemClock.elapsedRealtime();
+            OptimizeStats.Builder builder = new OptimizeStats.Builder();
             try {
-                instance.getAppSearchImpl().checkForOptimize();
+                instance.getAppSearchImpl().checkForOptimize(builder);
             } catch (AppSearchException e) {
                 Log.w(TAG, "Error occurred when check for optimize", e);
+            } finally {
+                OptimizeStats oStats = builder
+                        .setTotalLatencyMillis(
+                                (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
+                        .build();
+                if (oStats.getOriginalDocumentCount() > 0) {
+                    // see if optimize has been run by checking originalDocumentCount
+                    instance.getLogger().logStats(oStats);
+                }
             }
         });
     }
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
index 830e76c..15916cc 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
@@ -55,6 +55,7 @@
 import com.android.server.appsearch.external.localstorage.converter.SetSchemaResponseToProtoConverter;
 import com.android.server.appsearch.external.localstorage.converter.TypePropertyPathToProtoConverter;
 import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
+import com.android.server.appsearch.external.localstorage.stats.OptimizeStats;
 import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats;
 import com.android.server.appsearch.external.localstorage.stats.RemoveStats;
 import com.android.server.appsearch.external.localstorage.stats.SearchStats;
@@ -145,6 +146,9 @@
 public final class AppSearchImpl implements Closeable {
     private static final String TAG = "AppSearchImpl";
 
+    /** A value 0 means that there're no more pages in the search results. */
+    private static final long EMPTY_PAGE_TOKEN = 0;
+
     @VisibleForTesting static final int CHECK_OPTIMIZE_INTERVAL = 100;
 
     private final ReadWriteLock mReadWriteLock = new ReentrantReadWriteLock();
@@ -284,6 +288,9 @@
 
                 // Log the time it took to read the data that goes into the cache maps
                 if (initStatsBuilder != null) {
+                    // In case there is some error for getAllNamespaces, we can still
+                    // set the latency for preparation.
+                    // If there is no error, the value will be overridden by the actual one later.
                     initStatsBuilder
                             .setStatusCode(
                                     statusProtoToResultCode(
@@ -1135,6 +1142,16 @@
                     searchResultProto.getResultsCount(),
                     searchResultProto);
             checkSuccess(searchResultProto.getStatus());
+            if (nextPageToken != EMPTY_PAGE_TOKEN
+                    && searchResultProto.getNextPageToken() == EMPTY_PAGE_TOKEN) {
+                // At this point, we're guaranteed that this nextPageToken exists for this package,
+                // otherwise checkNextPageToken would've thrown an exception.
+                // Since the new token is 0, this is the last page. We should remove the old token
+                // from our cache since it no longer refers to this query.
+                synchronized (mNextPageTokensLocked) {
+                    mNextPageTokensLocked.get(packageName).remove(nextPageToken);
+                }
+            }
             return rewriteSearchResultProto(searchResultProto, mSchemaMapLocked);
         } finally {
             mReadWriteLock.readLock().unlock();
@@ -1326,8 +1343,7 @@
                     deleteResultProto.getStatus(), StatusProto.Code.OK, StatusProto.Code.NOT_FOUND);
 
             // Update derived maps
-            int numDocumentsDeleted =
-                    deleteResultProto.getDeleteStats().getNumDocumentsDeleted();
+            int numDocumentsDeleted = deleteResultProto.getDeleteStats().getNumDocumentsDeleted();
             updateDocumentCountAfterRemovalLocked(packageName, numDocumentsDeleted);
         } finally {
             mReadWriteLock.writeLock().unlock();
@@ -2056,6 +2072,10 @@
     }
 
     private void addNextPageToken(String packageName, long nextPageToken) {
+        if (nextPageToken == EMPTY_PAGE_TOKEN) {
+            // There is no more pages. No need to add it.
+            return;
+        }
         synchronized (mNextPageTokensLocked) {
             Set<Long> tokens = mNextPageTokensLocked.get(packageName);
             if (tokens == null) {
@@ -2068,6 +2088,11 @@
 
     private void checkNextPageToken(String packageName, long nextPageToken)
             throws AppSearchException {
+        if (nextPageToken == EMPTY_PAGE_TOKEN) {
+            // Swallow the check for empty page token, token = 0 means there is no more page and it
+            // won't return anything from Icing.
+            return;
+        }
         synchronized (mNextPageTokensLocked) {
             Set<Long> nextPageTokens = mNextPageTokensLocked.get(packageName);
             if (nextPageTokens == null || !nextPageTokens.contains(nextPageToken)) {
@@ -2162,12 +2187,13 @@
      *     #CHECK_OPTIMIZE_INTERVAL}, {@link IcingSearchEngine#getOptimizeInfo()} will be triggered
      *     and the counter will be reset.
      */
-    public void checkForOptimize(int mutationSize) throws AppSearchException {
+    public void checkForOptimize(int mutationSize, @Nullable OptimizeStats.Builder builder)
+            throws AppSearchException {
         mReadWriteLock.writeLock().lock();
         try {
             mOptimizeIntervalCountLocked += mutationSize;
             if (mOptimizeIntervalCountLocked >= CHECK_OPTIMIZE_INTERVAL) {
-                checkForOptimize();
+                checkForOptimize(builder);
             }
         } finally {
             mReadWriteLock.writeLock().unlock();
@@ -2183,14 +2209,15 @@
      * <p>{@link IcingSearchEngine#optimize()} should be called only if {@link
      * OptimizeStrategy#shouldOptimize(GetOptimizeInfoResultProto)} return true.
      */
-    public void checkForOptimize() throws AppSearchException {
+    public void checkForOptimize(@Nullable OptimizeStats.Builder builder)
+            throws AppSearchException {
         mReadWriteLock.writeLock().lock();
         try {
             GetOptimizeInfoResultProto optimizeInfo = getOptimizeInfoResultLocked();
             checkSuccess(optimizeInfo.getStatus());
             mOptimizeIntervalCountLocked = 0;
             if (mOptimizeStrategy.shouldOptimize(optimizeInfo)) {
-                optimize();
+                optimize(builder);
             }
         } finally {
             mReadWriteLock.writeLock().unlock();
@@ -2201,13 +2228,18 @@
     }
 
     /** Triggers {@link IcingSearchEngine#optimize()} directly. */
-    public void optimize() throws AppSearchException {
+    public void optimize(@Nullable OptimizeStats.Builder builder) throws AppSearchException {
         mReadWriteLock.writeLock().lock();
         try {
             mLogUtil.piiTrace("optimize, request");
             OptimizeResultProto optimizeResultProto = mIcingSearchEngineLocked.optimize();
             mLogUtil.piiTrace(
                     "optimize, response", optimizeResultProto.getStatus(), optimizeResultProto);
+            if (builder != null) {
+                builder.setStatusCode(statusProtoToResultCode(optimizeResultProto.getStatus()));
+                AppSearchLoggerHelper.copyNativeStats(
+                        optimizeResultProto.getOptimizeStats(), builder);
+            }
             checkSuccess(optimizeResultProto.getStatus());
         } finally {
             mReadWriteLock.writeLock().unlock();
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLogger.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLogger.java
index d92f4f0..98cedc7 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLogger.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLogger.java
@@ -17,10 +17,10 @@
 package com.android.server.appsearch.external.localstorage;
 
 import android.annotation.NonNull;
-import android.app.appsearch.exceptions.AppSearchException;
 
 import com.android.server.appsearch.external.localstorage.stats.CallStats;
 import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
+import com.android.server.appsearch.external.localstorage.stats.OptimizeStats;
 import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats;
 import com.android.server.appsearch.external.localstorage.stats.RemoveStats;
 import com.android.server.appsearch.external.localstorage.stats.SearchStats;
@@ -37,19 +37,22 @@
  */
 public interface AppSearchLogger {
     /** Logs {@link CallStats} */
-    void logStats(@NonNull CallStats stats) throws AppSearchException;
+    void logStats(@NonNull CallStats stats);
 
     /** Logs {@link PutDocumentStats} */
-    void logStats(@NonNull PutDocumentStats stats) throws AppSearchException;
+    void logStats(@NonNull PutDocumentStats stats);
 
     /** Logs {@link InitializeStats} */
-    void logStats(@NonNull InitializeStats stats) throws AppSearchException;
+    void logStats(@NonNull InitializeStats stats);
 
     /** Logs {@link SearchStats} */
-    void logStats(@NonNull SearchStats stats) throws AppSearchException;
+    void logStats(@NonNull SearchStats stats);
 
     /** Logs {@link RemoveStats} */
-    void logStats(@NonNull RemoveStats stats) throws AppSearchException;
+    void logStats(@NonNull RemoveStats stats);
+
+    /** Logs {@link OptimizeStats} */
+    void logStats(@NonNull OptimizeStats stats);
 
     // TODO(b/173532925) Add remaining logStats once we add all the stats.
 }
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLoggerHelper.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLoggerHelper.java
index aa9200a..cd653e5 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLoggerHelper.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLoggerHelper.java
@@ -19,12 +19,14 @@
 import android.annotation.NonNull;
 
 import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
+import com.android.server.appsearch.external.localstorage.stats.OptimizeStats;
 import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats;
 import com.android.server.appsearch.external.localstorage.stats.RemoveStats;
 import com.android.server.appsearch.external.localstorage.stats.SearchStats;
 
 import com.google.android.icing.proto.DeleteStatsProto;
 import com.google.android.icing.proto.InitializeStatsProto;
+import com.google.android.icing.proto.OptimizeStatsProto;
 import com.google.android.icing.proto.PutDocumentStatsProto;
 import com.google.android.icing.proto.QueryStatsProto;
 
@@ -92,8 +94,8 @@
                 .setSchemaTypeCount(fromNativeStats.getNumSchemaTypes());
     }
 
-    /*
-     * Copy native Query stats to buiilder.
+    /**
+     * Copies native Query stats to builder.
      *
      * @param fromNativeStats Stats copied from.
      * @param toStatsBuilder Stats copied to.
@@ -122,8 +124,8 @@
                         fromNativeStats.getDocumentRetrievalLatencyMs());
     }
 
-    /*
-     * Copy native Query stats to buiilder.
+    /**
+     * Copies native Delete stats to builder.
      *
      * @param fromNativeStats Stats copied from.
      * @param toStatsBuilder Stats copied to.
@@ -138,4 +140,28 @@
                 .setDeleteType(fromNativeStats.getDeleteType().getNumber())
                 .setDeletedDocumentCount(fromNativeStats.getNumDocumentsDeleted());
     }
+
+    /**
+     * Copies native {@link OptimizeStatsProto} to builder.
+     *
+     * @param fromNativeStats Stats copied from.
+     * @param toStatsBuilder Stats copied to.
+     */
+    static void copyNativeStats(
+            @NonNull OptimizeStatsProto fromNativeStats,
+            @NonNull OptimizeStats.Builder toStatsBuilder) {
+        Objects.requireNonNull(fromNativeStats);
+        Objects.requireNonNull(toStatsBuilder);
+        toStatsBuilder
+                .setNativeLatencyMillis(fromNativeStats.getLatencyMs())
+                .setDocumentStoreOptimizeLatencyMillis(
+                        fromNativeStats.getDocumentStoreOptimizeLatencyMs())
+                .setIndexRestorationLatencyMillis(fromNativeStats.getIndexRestorationLatencyMs())
+                .setOriginalDocumentCount(fromNativeStats.getNumOriginalDocuments())
+                .setDeletedDocumentCount(fromNativeStats.getNumDeletedDocuments())
+                .setExpiredDocumentCount(fromNativeStats.getNumExpiredDocuments())
+                .setStorageSizeBeforeBytes(fromNativeStats.getStorageSizeBefore())
+                .setStorageSizeAfterBytes(fromNativeStats.getStorageSizeAfter())
+                .setTimeSinceLastOptimizeMillis(fromNativeStats.getTimeSinceLastOptimizeMs());
+    }
 }
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/OptimizeStats.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/OptimizeStats.java
new file mode 100644
index 0000000..83bd50f
--- /dev/null
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/OptimizeStats.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright 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.appsearch.external.localstorage.stats;
+
+import android.annotation.NonNull;
+import android.app.appsearch.AppSearchResult;
+
+import java.util.Objects;
+
+/**
+ * Class holds detailed stats for Optimize.
+ *
+ * @hide
+ */
+public final class OptimizeStats {
+    /**
+     * The status code returned by {@link AppSearchResult#getResultCode()} for the call or internal
+     * state.
+     */
+    @AppSearchResult.ResultCode private final int mStatusCode;
+
+    private final int mTotalLatencyMillis;
+    private final int mNativeLatencyMillis;
+
+    // Time used to optimize the document store in millis.
+    private final int mNativeDocumentStoreOptimizeLatencyMillis;
+
+    // Time used to restore the index in millis.
+    private final int mNativeIndexRestorationLatencyMillis;
+
+    // Number of documents before the optimization.
+    private final int mNativeOriginalDocumentCount;
+
+    // Number of documents deleted during the optimization.
+    private final int mNativeDeletedDocumentCount;
+
+    // Number of documents expired during the optimization.
+    private final int mNativeExpiredDocumentCount;
+
+    // Size of storage in bytes before the optimization.
+    private final long mNativeStorageSizeBeforeBytes;
+
+    // Size of storage in bytes after the optimization.
+    private final long mNativeStorageSizeAfterBytes;
+
+    // The amount of time in millis since the last optimization ran calculated using wall clock time
+    private final long mNativeTimeSinceLastOptimizeMillis;
+
+    OptimizeStats(@NonNull Builder builder) {
+        Objects.requireNonNull(builder);
+        mStatusCode = builder.mStatusCode;
+        mTotalLatencyMillis = builder.mTotalLatencyMillis;
+        mNativeLatencyMillis = builder.mNativeLatencyMillis;
+        mNativeDocumentStoreOptimizeLatencyMillis =
+                builder.mNativeDocumentStoreOptimizeLatencyMillis;
+        mNativeIndexRestorationLatencyMillis = builder.mNativeIndexRestorationLatencyMillis;
+        mNativeOriginalDocumentCount = builder.mNativeOriginalDocumentCount;
+        mNativeDeletedDocumentCount = builder.mNativeDeletedDocumentCount;
+        mNativeExpiredDocumentCount = builder.mNativeExpiredDocumentCount;
+        mNativeStorageSizeBeforeBytes = builder.mNativeStorageSizeBeforeBytes;
+        mNativeStorageSizeAfterBytes = builder.mNativeStorageSizeAfterBytes;
+        mNativeTimeSinceLastOptimizeMillis = builder.mNativeTimeSinceLastOptimizeMillis;
+    }
+
+    /** Returns status code for this optimization. */
+    @AppSearchResult.ResultCode
+    public int getStatusCode() {
+        return mStatusCode;
+    }
+
+    /** Returns total latency of this optimization in millis. */
+    public int getTotalLatencyMillis() {
+        return mTotalLatencyMillis;
+    }
+
+    /** Returns how much time in millis spent in the native code. */
+    public int getNativeLatencyMillis() {
+        return mNativeLatencyMillis;
+    }
+
+    /** Returns time used to optimize the document store in millis. */
+    public int getDocumentStoreOptimizeLatencyMillis() {
+        return mNativeDocumentStoreOptimizeLatencyMillis;
+    }
+
+    /** Returns time used to restore the index in millis. */
+    public int getIndexRestorationLatencyMillis() {
+        return mNativeIndexRestorationLatencyMillis;
+    }
+
+    /** Returns number of documents before the optimization. */
+    public int getOriginalDocumentCount() {
+        return mNativeOriginalDocumentCount;
+    }
+
+    /** Returns number of documents deleted during the optimization. */
+    public int getDeletedDocumentCount() {
+        return mNativeDeletedDocumentCount;
+    }
+
+    /** Returns number of documents expired during the optimization. */
+    public int getExpiredDocumentCount() {
+        return mNativeExpiredDocumentCount;
+    }
+
+    /** Returns size of storage in bytes before the optimization. */
+    public long getStorageSizeBeforeBytes() {
+        return mNativeStorageSizeBeforeBytes;
+    }
+
+    /** Returns size of storage in bytes after the optimization. */
+    public long getStorageSizeAfterBytes() {
+        return mNativeStorageSizeAfterBytes;
+    }
+
+    /**
+     * Returns the amount of time in millis since the last optimization ran calculated using wall
+     * clock time.
+     */
+    public long getTimeSinceLastOptimizeMillis() {
+        return mNativeTimeSinceLastOptimizeMillis;
+    }
+
+    /** Builder for {@link RemoveStats}. */
+    public static class Builder {
+        /**
+         * The status code returned by {@link AppSearchResult#getResultCode()} for the call or
+         * internal state.
+         */
+        @AppSearchResult.ResultCode int mStatusCode;
+
+        int mTotalLatencyMillis;
+        int mNativeLatencyMillis;
+        int mNativeDocumentStoreOptimizeLatencyMillis;
+        int mNativeIndexRestorationLatencyMillis;
+        int mNativeOriginalDocumentCount;
+        int mNativeDeletedDocumentCount;
+        int mNativeExpiredDocumentCount;
+        long mNativeStorageSizeBeforeBytes;
+        long mNativeStorageSizeAfterBytes;
+        long mNativeTimeSinceLastOptimizeMillis;
+
+        /** Sets the status code. */
+        @NonNull
+        public Builder setStatusCode(@AppSearchResult.ResultCode int statusCode) {
+            mStatusCode = statusCode;
+            return this;
+        }
+
+        /** Sets total latency in millis. */
+        @NonNull
+        public Builder setTotalLatencyMillis(int totalLatencyMillis) {
+            mTotalLatencyMillis = totalLatencyMillis;
+            return this;
+        }
+
+        /** Sets native latency in millis. */
+        @NonNull
+        public Builder setNativeLatencyMillis(int nativeLatencyMillis) {
+            mNativeLatencyMillis = nativeLatencyMillis;
+            return this;
+        }
+
+        /** Sets time used to optimize the document store. */
+        @NonNull
+        public Builder setDocumentStoreOptimizeLatencyMillis(
+                int documentStoreOptimizeLatencyMillis) {
+            mNativeDocumentStoreOptimizeLatencyMillis = documentStoreOptimizeLatencyMillis;
+            return this;
+        }
+
+        /** Sets time used to restore the index. */
+        @NonNull
+        public Builder setIndexRestorationLatencyMillis(int indexRestorationLatencyMillis) {
+            mNativeIndexRestorationLatencyMillis = indexRestorationLatencyMillis;
+            return this;
+        }
+
+        /** Sets number of documents before the optimization. */
+        @NonNull
+        public Builder setOriginalDocumentCount(int originalDocumentCount) {
+            mNativeOriginalDocumentCount = originalDocumentCount;
+            return this;
+        }
+
+        /** Sets number of documents deleted during the optimization. */
+        @NonNull
+        public Builder setDeletedDocumentCount(int deletedDocumentCount) {
+            mNativeDeletedDocumentCount = deletedDocumentCount;
+            return this;
+        }
+
+        /** Sets number of documents expired during the optimization. */
+        @NonNull
+        public Builder setExpiredDocumentCount(int expiredDocumentCount) {
+            mNativeExpiredDocumentCount = expiredDocumentCount;
+            return this;
+        }
+
+        /** Sets Storage size in bytes before optimization. */
+        @NonNull
+        public Builder setStorageSizeBeforeBytes(long storageSizeBeforeBytes) {
+            mNativeStorageSizeBeforeBytes = storageSizeBeforeBytes;
+            return this;
+        }
+
+        /** Sets storage size in bytes after optimization. */
+        @NonNull
+        public Builder setStorageSizeAfterBytes(long storageSizeAfterBytes) {
+            mNativeStorageSizeAfterBytes = storageSizeAfterBytes;
+            return this;
+        }
+
+        /**
+         * Sets the amount the time since the last optimize ran calculated using wall clock time.
+         */
+        @NonNull
+        public Builder setTimeSinceLastOptimizeMillis(long timeSinceLastOptimizeMillis) {
+            mNativeTimeSinceLastOptimizeMillis = timeSinceLastOptimizeMillis;
+            return this;
+        }
+
+        /** Creates a {@link OptimizeStats}. */
+        @NonNull
+        public OptimizeStats build() {
+            return new OptimizeStats(/* builder= */ this);
+        }
+    }
+}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java b/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java
index 2cbce10..fdf6a00 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java
@@ -32,6 +32,7 @@
 import com.android.server.appsearch.external.localstorage.AppSearchLogger;
 import com.android.server.appsearch.external.localstorage.stats.CallStats;
 import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
+import com.android.server.appsearch.external.localstorage.stats.OptimizeStats;
 import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats;
 import com.android.server.appsearch.external.localstorage.stats.RemoveStats;
 import com.android.server.appsearch.external.localstorage.stats.SearchStats;
@@ -145,7 +146,7 @@
     }
 
     @Override
-    public void logStats(@NonNull InitializeStats stats) throws AppSearchException {
+    public void logStats(@NonNull InitializeStats stats) {
         Objects.requireNonNull(stats);
         synchronized (mLock) {
             if (shouldLogForTypeLocked(CallStats.CALL_TYPE_INITIALIZE)) {
@@ -155,7 +156,7 @@
     }
 
     @Override
-    public void logStats(@NonNull SearchStats stats) throws AppSearchException {
+    public void logStats(@NonNull SearchStats stats) {
         Objects.requireNonNull(stats);
         synchronized (mLock) {
             if (shouldLogForTypeLocked(CallStats.CALL_TYPE_SEARCH)) {
@@ -165,10 +166,20 @@
     }
 
     @Override
-    public void logStats(@NonNull RemoveStats stats) throws AppSearchException {
+    public void logStats(@NonNull RemoveStats stats) {
         // TODO(b/173532925): Log stats
     }
 
+    @Override
+    public void logStats(@NonNull OptimizeStats stats) {
+        Objects.requireNonNull(stats);
+        synchronized (mLock) {
+            if (shouldLogForTypeLocked(CallStats.CALL_TYPE_OPTIMIZE)) {
+                logStatsImplLocked(stats);
+            }
+        }
+    }
+
     /**
      * Removes cached UID for package.
      *
@@ -326,6 +337,27 @@
                 stats.getResetStatusCode());
     }
 
+    @GuardedBy("mLock")
+    private void logStatsImplLocked(@NonNull OptimizeStats stats) {
+        mLastPushTimeMillisLocked = SystemClock.elapsedRealtime();
+        ExtraStats extraStats = createExtraStatsLocked(/*packageName=*/ null,
+                CallStats.CALL_TYPE_OPTIMIZE);
+        AppSearchStatsLog.write(AppSearchStatsLog.APP_SEARCH_OPTIMIZE_STATS_REPORTED,
+                extraStats.mSamplingInterval,
+                extraStats.mSkippedSampleCount,
+                stats.getStatusCode(),
+                stats.getTotalLatencyMillis(),
+                stats.getNativeLatencyMillis(),
+                stats.getDocumentStoreOptimizeLatencyMillis(),
+                stats.getIndexRestorationLatencyMillis(),
+                stats.getOriginalDocumentCount(),
+                stats.getDeletedDocumentCount(),
+                stats.getExpiredDocumentCount(),
+                stats.getStorageSizeBeforeBytes(),
+                stats.getStorageSizeAfterBytes(),
+                stats.getTimeSinceLastOptimizeMillis());
+    }
+
     /**
      * Calculate the hash code as an integer by returning the last four bytes of its MD5.
      *
@@ -464,15 +496,19 @@
                 return mConfig.getCachedSamplingIntervalForBatchCallStats();
             case CallStats.CALL_TYPE_PUT_DOCUMENT:
                 return mConfig.getCachedSamplingIntervalForPutDocumentStats();
-            case CallStats.CALL_TYPE_UNKNOWN:
             case CallStats.CALL_TYPE_INITIALIZE:
+                return mConfig.getCachedSamplingIntervalForInitializeStats();
+            case CallStats.CALL_TYPE_SEARCH:
+                return mConfig.getCachedSamplingIntervalForSearchStats();
+            case CallStats.CALL_TYPE_GLOBAL_SEARCH:
+                return mConfig.getCachedSamplingIntervalForGlobalSearchStats();
+            case CallStats.CALL_TYPE_OPTIMIZE:
+                return mConfig.getCachedSamplingIntervalForOptimizeStats();
+            case CallStats.CALL_TYPE_UNKNOWN:
             case CallStats.CALL_TYPE_SET_SCHEMA:
             case CallStats.CALL_TYPE_GET_DOCUMENT:
             case CallStats.CALL_TYPE_REMOVE_DOCUMENT_BY_ID:
-            case CallStats.CALL_TYPE_SEARCH:
-            case CallStats.CALL_TYPE_OPTIMIZE:
             case CallStats.CALL_TYPE_FLUSH:
-            case CallStats.CALL_TYPE_GLOBAL_SEARCH:
             case CallStats.CALL_TYPE_REMOVE_DOCUMENT_BY_SEARCH:
                 // TODO(b/173532925) Some of them above will have dedicated sampling ratio config
             default:
diff --git a/apex/appsearch/synced_jetpack_changeid.txt b/apex/appsearch/synced_jetpack_changeid.txt
index 6555107..a81d7d80 100644
--- a/apex/appsearch/synced_jetpack_changeid.txt
+++ b/apex/appsearch/synced_jetpack_changeid.txt
@@ -1 +1 @@
-c7387d9b58726a23a0608a9365fb3a1b57b7b8a1
+Ie04f1ecc033faae8085afcb51eb9e40a298998d5
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
index 9f52954..86fa06c 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -2052,10 +2052,11 @@
                     + " -- package not allowed to start");
             return;
         }
+        final int callerProcState = mActivityManagerInternal.getUidProcessState(callingUid);
         removeLocked(operation, directReceiver, REMOVE_REASON_UNDEFINED);
         incrementAlarmCount(a.uid);
         setImplLocked(a);
-        MetricsHelper.pushAlarmScheduled(a);
+        MetricsHelper.pushAlarmScheduled(a, callerProcState);
     }
 
     /**
@@ -4635,7 +4636,6 @@
                 Slog.d(TAG, "Package " + packageName + " for user " + userId + " now in bucket " +
                         bucket);
             }
-            mHandler.removeMessages(AlarmHandler.APP_STANDBY_BUCKET_CHANGED);
             mHandler.obtainMessage(AlarmHandler.APP_STANDBY_BUCKET_CHANGED, userId, -1, packageName)
                     .sendToTarget();
         }
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/MetricsHelper.java b/apex/jobscheduler/service/java/com/android/server/alarm/MetricsHelper.java
index 4e7311f..4c2f8d1 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/MetricsHelper.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/MetricsHelper.java
@@ -22,6 +22,7 @@
 import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__PERMISSION;
 import static com.android.server.alarm.AlarmManagerService.INDEFINITE_DELAY;
 
+import android.app.ActivityManager;
 import android.app.AlarmManager;
 import android.app.StatsManager;
 import android.content.Context;
@@ -93,7 +94,7 @@
         }
     }
 
-    static void pushAlarmScheduled(Alarm a) {
+    static void pushAlarmScheduled(Alarm a, int callerProcState) {
         FrameworkStatsLog.write(
                 FrameworkStatsLog.ALARM_SCHEDULED,
                 a.uid,
@@ -103,7 +104,8 @@
                 a.alarmClock != null,
                 a.repeatInterval != 0,
                 reasonToStatsReason(a.mExactAllowReason),
-                AlarmManagerService.isRtc(a.type));
+                AlarmManagerService.isRtc(a.type),
+                ActivityManager.processStateAmToProto(callerProcState));
     }
 
     static void pushAlarmBatchDelivered(int numAlarms, int wakeups) {
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 3fa1c12..90baa8e 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -116,6 +116,16 @@
     @VisibleForTesting
     int mVerb;
     private boolean mCancelled;
+    /**
+     * True if the previous job on this context successfully finished (ie. called jobFinished or
+     * dequeueWork with no work left).
+     */
+    private boolean mPreviousJobHadSuccessfulFinish;
+    /**
+     * The last time a job on this context didn't finish successfully, in the elapsed realtime
+     * timebase.
+     */
+    private long mLastUnsuccessfulFinishElapsed;
 
     /**
      * All the information maintained about the job currently being executed.
@@ -439,7 +449,9 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             synchronized (mLock) {
-                assertCallerLocked(cb);
+                if (!assertCallerLocked(cb)) {
+                    return null;
+                }
                 if (mVerb == VERB_STOPPING || mVerb == VERB_FINISHED) {
                     // This job is either all done, or on its way out.  Either way, it
                     // should not dispatch any more work.  We will pick up any remaining
@@ -465,7 +477,11 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             synchronized (mLock) {
-                assertCallerLocked(cb);
+                if (!assertCallerLocked(cb)) {
+                    // Return true instead of false here so we don't just kick the
+                    // Exception-throwing-can down the road to JobParameters.completeWork >:(
+                    return true;
+                }
                 return mRunningJob.completeWorkLocked(workId);
             }
         } finally {
@@ -554,18 +570,34 @@
         return true;
     }
 
-    private void assertCallerLocked(JobCallback cb) {
+    /**
+     * Will throw a {@link SecurityException} if the callback is not for the currently running job,
+     * but may decide not to throw an exception if the call from the previous job appears to be an
+     * accident.
+     *
+     * @return true if the callback is for the current job, false otherwise
+     */
+    private boolean assertCallerLocked(JobCallback cb) {
         if (!verifyCallerLocked(cb)) {
+            final long nowElapsed = sElapsedRealtimeClock.millis();
+            if (!mPreviousJobHadSuccessfulFinish
+                    && (nowElapsed - mLastUnsuccessfulFinishElapsed) < 15_000L) {
+                // Don't punish apps for race conditions
+                return false;
+            }
+            // It's been long enough that the app should really not be calling into JS for the
+            // stopped job.
             StringBuilder sb = new StringBuilder(128);
             sb.append("Caller no longer running");
             if (cb.mStoppedReason != null) {
                 sb.append(", last stopped ");
-                TimeUtils.formatDuration(sElapsedRealtimeClock.millis() - cb.mStoppedTime, sb);
+                TimeUtils.formatDuration(nowElapsed - cb.mStoppedTime, sb);
                 sb.append(" because: ");
                 sb.append(cb.mStoppedReason);
             }
             throw new SecurityException(sb.toString());
         }
+        return true;
     }
 
     /**
@@ -911,6 +943,11 @@
         applyStoppedReasonLocked(reason);
         completedJob = mRunningJob;
         final int internalStopReason = mParams.getInternalStopReasonCode();
+        mPreviousJobHadSuccessfulFinish =
+                (internalStopReason == JobParameters.INTERNAL_STOP_REASON_SUCCESSFUL_FINISH);
+        if (!mPreviousJobHadSuccessfulFinish) {
+            mLastUnsuccessfulFinishElapsed = sElapsedRealtimeClock.millis();
+        }
         mJobPackageTracker.noteInactive(completedJob, internalStopReason, reason);
         FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SCHEDULED_JOB_STATE_CHANGED,
                 completedJob.getSourceUid(), null, completedJob.getBatteryName(),
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 6c001f3..26c83ee 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -112,6 +112,8 @@
     srcs: [
         "android/os/Temperature.aidl",
         "android/os/CoolingDevice.aidl",
+        "android/os/IHintManager.aidl",
+        "android/os/IHintSession.aidl",
         "android/os/IThermalEventListener.aidl",
         "android/os/IThermalStatusListener.aidl",
         "android/os/IThermalService.aidl",
diff --git a/core/java/android/app/AppOpsManagerInternal.java b/core/java/android/app/AppOpsManagerInternal.java
index 363b5a7..4d6e4ae 100644
--- a/core/java/android/app/AppOpsManagerInternal.java
+++ b/core/java/android/app/AppOpsManagerInternal.java
@@ -21,6 +21,7 @@
 import android.app.AppOpsManager.AttributionFlags;
 import android.content.AttributionSource;
 import android.os.IBinder;
+import android.os.UserHandle;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 
@@ -215,4 +216,11 @@
      * Sets a global restriction on an op code.
      */
     public abstract void setGlobalRestriction(int code, boolean restricted, IBinder token);
+
+    /**
+     * Gets the number of tokens restricting the given appop for a user, package, and
+     * attributionTag.
+     */
+    public abstract int getOpRestrictionCount(int code, UserHandle user, String pkg,
+            String attributionTag);
 }
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index f52fdc5..4db1f71 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -26,6 +26,7 @@
 import android.annotation.Nullable;
 import android.annotation.UiContext;
 import android.compat.annotation.UnsupportedAppUsage;
+import android.content.AttributionSource;
 import android.content.AutofillOptions;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -60,7 +61,6 @@
 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;
@@ -3120,6 +3120,7 @@
             mForceDisplayOverrideInResources = container.mForceDisplayOverrideInResources;
             mIsConfigurationBasedContext = container.mIsConfigurationBasedContext;
             mContextType = container.mContextType;
+            mContentCaptureOptions = container.mContentCaptureOptions;
         } else {
             mBasePackageName = packageInfo.mPackageName;
             ApplicationInfo ainfo = packageInfo.getApplicationInfo();
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 871d48b..32ea41b 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -158,7 +158,6 @@
 import android.os.IBinder;
 import android.os.IDumpstate;
 import android.os.IHardwarePropertiesManager;
-import android.os.IHintManager;
 import android.os.IPowerManager;
 import android.os.IRecoverySystem;
 import android.os.ISystemUpdateManager;
@@ -600,10 +599,7 @@
             @Override
             public PerformanceHintManager createService(ContextImpl ctx)
                     throws ServiceNotFoundException {
-                IBinder hintBinder = ServiceManager.getServiceOrThrow(
-                        Context.PERFORMANCE_HINT_SERVICE);
-                IHintManager hintService = IHintManager.Stub.asInterface(hintBinder);
-                return new PerformanceHintManager(hintService);
+                return PerformanceHintManager.create();
             }});
 
         registerService(Context.RECOVERY_SERVICE, RecoverySystem.class,
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 6bc331d..549ab6e 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -10151,8 +10151,8 @@
      * An example of a supported preferential network service is the Enterprise
      * slice on 5G networks.
      *
-     * By default, preferential network service is enabled on the work profile on supported
-     * carriers and devices. Admins can explicitly disable it with this API.
+     * By default, preferential network service is disabled on the work profile on supported
+     * carriers and devices. Admins can explicitly enable it with this API.
      * On fully-managed devices this method is unsupported because all traffic is considered
      * work traffic.
      *
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index f5ab2ab..8398be1 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -3518,22 +3518,22 @@
     }
 
     /**
-     * Determines whether a String Bluetooth address, such as "00:43:A8:23:10:F0"
+     * Determines whether a String Bluetooth address, such as "F0:43:A8:23:10:00"
      * is a RANDOM STATIC address.
      *
-     * RANDOM STATIC: (addr & 0b11) == 0b11
-     * RANDOM RESOLVABLE: (addr & 0b11) == 0b10
-     * RANDOM non-RESOLVABLE: (addr & 0b11) == 0b00
+     * RANDOM STATIC: (addr & 0xC0) == 0xC0
+     * RANDOM RESOLVABLE: (addr &  0xC0) == 0x40
+     * RANDOM non-RESOLVABLE: (addr &  0xC0) == 0x00
      *
      * @param address Bluetooth address as string
-     * @return true if the 2 Least Significant Bits of the address equals 0b11.
+     * @return true if the 2 Most Significant Bits of the address equals 0xC0.
      *
      * @hide
      */
     public static boolean isAddressRandomStatic(@NonNull String address) {
         requireNonNull(address);
         return checkBluetoothAddress(address)
-                && (Integer.parseInt(address.split(":")[5], 16) & 0b11) == 0b11;
+                && (Integer.parseInt(address.split(":")[0], 16) & 0xC0) == 0xC0;
     }
 
     /** {@hide} */
diff --git a/core/java/android/hardware/ISensorPrivacyManager.aidl b/core/java/android/hardware/ISensorPrivacyManager.aidl
index debc074..d69a9e1 100644
--- a/core/java/android/hardware/ISensorPrivacyManager.aidl
+++ b/core/java/android/hardware/ISensorPrivacyManager.aidl
@@ -48,4 +48,8 @@
 
     void suppressIndividualSensorPrivacyReminders(int userId, int sensor, IBinder token,
             boolean suppress);
+
+    void addUserGlobalIndividualSensorPrivacyListener(int sensor, in ISensorPrivacyListener listener);
+
+    void removeUserGlobalIndividualSensorPrivacyListener(int sensor, in ISensorPrivacyListener listener);
 }
\ No newline at end of file
diff --git a/core/java/android/hardware/SensorPrivacyManager.java b/core/java/android/hardware/SensorPrivacyManager.java
index b7d95e7..4526ab77 100644
--- a/core/java/android/hardware/SensorPrivacyManager.java
+++ b/core/java/android/hardware/SensorPrivacyManager.java
@@ -24,6 +24,7 @@
 import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.annotation.UserIdInt;
+import android.app.ActivityManager;
 import android.content.Context;
 import android.os.Binder;
 import android.os.IBinder;
@@ -247,8 +248,7 @@
     @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
     public void addSensorPrivacyListener(@Sensors.Sensor int sensor,
             @NonNull OnSensorPrivacyChangedListener listener) {
-        addSensorPrivacyListener(sensor, mContext.getUserId(), mContext.getMainExecutor(),
-                listener);
+        addSensorPrivacyListener(sensor, mContext.getMainExecutor(), listener);
     }
 
     /**
@@ -283,7 +283,25 @@
     @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
     public void addSensorPrivacyListener(@Sensors.Sensor int sensor, @NonNull Executor executor,
             @NonNull OnSensorPrivacyChangedListener listener) {
-        addSensorPrivacyListener(sensor, mContext.getUserId(), executor, listener);
+        Pair<OnSensorPrivacyChangedListener, Integer> key = new Pair<>(listener, sensor);
+        synchronized (mIndividualListeners) {
+            ISensorPrivacyListener iListener = mIndividualListeners.get(key);
+            if (iListener == null) {
+                iListener = new ISensorPrivacyListener.Stub() {
+                    @Override
+                    public void onSensorPrivacyChanged(boolean enabled) {
+                        executor.execute(() -> listener.onSensorPrivacyChanged(sensor, enabled));
+                    }
+                };
+                mIndividualListeners.put(key, iListener);
+            }
+
+            try {
+                mService.addUserGlobalIndividualSensorPrivacyListener(sensor, iListener);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
     }
 
     /**
@@ -361,7 +379,7 @@
     @SystemApi
     @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
     public boolean isSensorPrivacyEnabled(@Sensors.Sensor int sensor) {
-        return isSensorPrivacyEnabled(sensor, mContext.getUserId());
+        return isSensorPrivacyEnabled(sensor, getCurrentUserId());
     }
 
     /**
@@ -392,7 +410,7 @@
     @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
     public void setSensorPrivacy(@Sources.Source int source, @Sensors.Sensor int sensor,
             boolean enable) {
-        setSensorPrivacy(source, sensor, enable, mContext.getUserId());
+        setSensorPrivacy(source, sensor, enable, getCurrentUserId());
     }
 
     /**
@@ -428,7 +446,7 @@
     @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
     public void setSensorPrivacyForProfileGroup(@Sources.Source int source,
             @Sensors.Sensor int sensor, boolean enable) {
-        setSensorPrivacyForProfileGroup(source , sensor, enable, mContext.getUserId());
+        setSensorPrivacyForProfileGroup(source , sensor, enable, getCurrentUserId());
     }
 
     /**
@@ -463,7 +481,7 @@
     @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
     public void suppressSensorPrivacyReminders(int sensor,
             boolean suppress) {
-        suppressSensorPrivacyReminders(sensor, suppress, mContext.getUserId());
+        suppressSensorPrivacyReminders(sensor, suppress, getCurrentUserId());
     }
 
     /**
@@ -590,4 +608,13 @@
             throw e.rethrowFromSystemServer();
         }
     }
+
+    private int getCurrentUserId() {
+        try {
+            return ActivityManager.getService().getCurrentUserId();
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+        return 0;
+    }
 }
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 9501994..d9fa56e 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -991,13 +991,27 @@
      * camera's crop region is set to maximum size, the FOV of the physical streams for the
      * ultrawide lens will be the same as the logical stream, by making the crop region
      * smaller than its active array size to compensate for the smaller focal length.</p>
-     * <p>Even if the underlying physical cameras have different RAW characteristics (such as
-     * size or CFA pattern), a logical camera can still advertise RAW capability. In this
-     * case, when the application configures a RAW stream, the camera device will make sure
-     * the active physical camera will remain active to ensure consistent RAW output
-     * behavior, and not switch to other physical cameras.</p>
+     * <p>There are two ways for the application to capture RAW images from a logical camera
+     * with RAW capability:</p>
+     * <ul>
+     * <li>Because the underlying physical cameras may have different RAW capabilities (such
+     * as resolution or CFA pattern), to maintain backward compatibility, when a RAW stream
+     * is configured, the camera device makes sure the default active physical camera remains
+     * active and does not switch to other physical cameras. (One exception is that, if the
+     * logical camera consists of identical image sensors and advertises multiple focalLength
+     * due to different lenses, the camera device may generate RAW images from different
+     * physical cameras based on the focalLength being set by the application.) This
+     * backward-compatible approach usually results in loss of optical zoom, to telephoto
+     * lens or to ultrawide lens.</li>
+     * <li>Alternatively, to take advantage of the full zoomRatio range of the logical camera,
+     * the application should use {@link android.hardware.camera2.MultiResolutionImageReader }
+     * to capture RAW images from the currently active physical camera. Because different
+     * physical camera may have different RAW characteristics, the application needs to use
+     * the characteristics and result metadata of the active physical camera for the
+     * relevant RAW metadata.</li>
+     * </ul>
      * <p>The capture request and result metadata tags required for backward compatible camera
-     * functionalities will be solely based on the logical camera capabiltity. On the other
+     * functionalities will be solely based on the logical camera capability. On the other
      * hand, the use of manual capture controls (sensor or post-processing) with a
      * logical camera may result in unexpected behavior when the HAL decides to switch
      * between physical cameras with different characteristics under the hood. For example,
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index 12557f9..c2a2c4c 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -74,7 +74,7 @@
 
     private final IFaceService mService;
     private final Context mContext;
-    private IBinder mToken = new Binder();
+    private final IBinder mToken = new Binder();
     @Nullable private AuthenticationCallback mAuthenticationCallback;
     @Nullable private FaceDetectionCallback mFaceDetectionCallback;
     @Nullable private EnrollmentCallback mEnrollmentCallback;
@@ -86,7 +86,7 @@
     private Face mRemovalFace;
     private Handler mHandler;
 
-    private IFaceServiceReceiver mServiceReceiver = new IFaceServiceReceiver.Stub() {
+    private final IFaceServiceReceiver mServiceReceiver = new IFaceServiceReceiver.Stub() {
 
         @Override // binder call
         public void onEnrollResult(Face face, int remaining) {
@@ -293,7 +293,7 @@
 
     /**
      * Defaults to {@link FaceManager#enroll(int, byte[], CancellationSignal, EnrollmentCallback,
-     * int[], Surface)} with {@code surface} set to null.
+     * int[], Surface)} with {@code previewSurface} set to null.
      *
      * @see FaceManager#enroll(int, byte[], CancellationSignal, EnrollmentCallback, int[], Surface)
      * @hide
@@ -301,8 +301,8 @@
     @RequiresPermission(MANAGE_BIOMETRIC)
     public void enroll(int userId, byte[] hardwareAuthToken, CancellationSignal cancel,
             EnrollmentCallback callback, int[] disabledFeatures) {
-        enroll(userId, hardwareAuthToken, cancel, callback, disabledFeatures, null /* surface */,
-                false /* debugConsent */);
+        enroll(userId, hardwareAuthToken, cancel, callback, disabledFeatures,
+                null /* previewSurface */, false /* debugConsent */);
     }
 
     /**
@@ -319,14 +319,14 @@
      * @param cancel            an object that can be used to cancel enrollment
      * @param userId            the user to whom this face will belong to
      * @param callback          an object to receive enrollment events
-     * @param surface           optional camera preview surface for a single-camera device.
+     * @param previewSurface    optional camera preview surface for a single-camera device.
      *                          Must be null if not used.
      * @param debugConsent      a feature flag that the user has consented to debug.
      * @hide
      */
     @RequiresPermission(MANAGE_BIOMETRIC)
     public void enroll(int userId, byte[] hardwareAuthToken, CancellationSignal cancel,
-            EnrollmentCallback callback, int[] disabledFeatures, @Nullable Surface surface,
+            EnrollmentCallback callback, int[] disabledFeatures, @Nullable Surface previewSurface,
             boolean debugConsent) {
         if (callback == null) {
             throw new IllegalArgumentException("Must supply an enrollment callback");
@@ -346,7 +346,8 @@
                 mEnrollmentCallback = callback;
                 Trace.beginSection("FaceManager#enroll");
                 mService.enroll(userId, mToken, hardwareAuthToken, mServiceReceiver,
-                        mContext.getOpPackageName(), disabledFeatures, surface, debugConsent);
+                        mContext.getOpPackageName(), disabledFeatures, previewSurface,
+                        debugConsent);
             } catch (RemoteException e) {
                 Slog.w(TAG, "Remote exception in enroll: ", e);
                 // Though this may not be a hardware issue, it will cause apps to give up or
@@ -853,10 +854,10 @@
      * @hide
      */
     public static class AuthenticationResult {
-        private Face mFace;
-        private CryptoObject mCryptoObject;
-        private int mUserId;
-        private boolean mIsStrongBiometric;
+        private final Face mFace;
+        private final CryptoObject mCryptoObject;
+        private final int mUserId;
+        private final boolean mIsStrongBiometric;
 
         /**
          * Authentication result
@@ -1127,7 +1128,7 @@
     }
 
     private class OnAuthenticationCancelListener implements OnCancelListener {
-        private CryptoObject mCrypto;
+        private final CryptoObject mCrypto;
 
         OnAuthenticationCancelListener(CryptoObject crypto) {
             mCrypto = crypto;
diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl
index 270d662..b9a49c6 100644
--- a/core/java/android/hardware/face/IFaceService.aidl
+++ b/core/java/android/hardware/face/IFaceService.aidl
@@ -75,7 +75,7 @@
 
     // Start face enrollment
     void enroll(int userId, IBinder token, in byte [] hardwareAuthToken, IFaceServiceReceiver receiver,
-            String opPackageName, in int [] disabledFeatures, in Surface surface, boolean debugConsent);
+            String opPackageName, in int [] disabledFeatures, in Surface previewSurface, boolean debugConsent);
 
     // Start remote face enrollment
     void enrollRemotely(int userId, IBinder token, in byte [] hardwareAuthToken, IFaceServiceReceiver receiver,
diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java
index 5a25cfc..ae8d010 100644
--- a/core/java/android/net/nsd/NsdManager.java
+++ b/core/java/android/net/nsd/NsdManager.java
@@ -23,6 +23,9 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemService;
+import android.app.compat.CompatChanges;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
 import android.content.Context;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -126,6 +129,24 @@
     private static final boolean DBG = false;
 
     /**
+     * When enabled, apps targeting < Android 12 are considered legacy for
+     * the NSD native daemon.
+     * The platform will only keep the daemon running as long as there are
+     * any legacy apps connected.
+     *
+     * After Android 12, directly communicate with native daemon might not
+     * work since the native damon won't always stay alive.
+     * Use the NSD APIs from NsdManager as the replacement is recommended.
+     * An another alternative could be bundling your own mdns solutions instead of
+     * depending on the system mdns native daemon.
+     *
+     * @hide
+     */
+    @ChangeId
+    @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S)
+    public static final long RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS = 191844585L;
+
+    /**
      * Broadcast intent action to indicate whether network service discovery is
      * enabled or disabled. An extra {@link #EXTRA_NSD_STATE} provides the state
      * information as int.
@@ -203,6 +224,9 @@
     public static final int DAEMON_CLEANUP                          = BASE + 21;
 
     /** @hide */
+    public static final int DAEMON_STARTUP                          = BASE + 22;
+
+    /** @hide */
     public static final int ENABLE                                  = BASE + 24;
     /** @hide */
     public static final int DISABLE                                 = BASE + 25;
@@ -232,6 +256,8 @@
         EVENT_NAMES.put(RESOLVE_SERVICE, "RESOLVE_SERVICE");
         EVENT_NAMES.put(RESOLVE_SERVICE_FAILED, "RESOLVE_SERVICE_FAILED");
         EVENT_NAMES.put(RESOLVE_SERVICE_SUCCEEDED, "RESOLVE_SERVICE_SUCCEEDED");
+        EVENT_NAMES.put(DAEMON_CLEANUP, "DAEMON_CLEANUP");
+        EVENT_NAMES.put(DAEMON_STARTUP, "DAEMON_STARTUP");
         EVENT_NAMES.put(ENABLE, "ENABLE");
         EVENT_NAMES.put(DISABLE, "DISABLE");
         EVENT_NAMES.put(NATIVE_DAEMON_EVENT, "NATIVE_DAEMON_EVENT");
@@ -494,6 +520,12 @@
         } catch (InterruptedException e) {
             fatal("Interrupted wait at init");
         }
+        if (CompatChanges.isChangeEnabled(RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)) {
+            return;
+        }
+        // Only proactively start the daemon if the target SDK < S, otherwise the internal service
+        // would automatically start/stop the native daemon as needed.
+        mAsyncChannel.sendMessage(DAEMON_STARTUP);
     }
 
     private static void fatal(String msg) {
diff --git a/core/java/android/os/DropBoxManager.java b/core/java/android/os/DropBoxManager.java
index 575fc4c..f38271a 100644
--- a/core/java/android/os/DropBoxManager.java
+++ b/core/java/android/os/DropBoxManager.java
@@ -72,7 +72,7 @@
     /** Flag value: Content is human-readable UTF-8 text (can be combined with IS_GZIPPED). */
     public static final int IS_TEXT = 2;
 
-    /** Flag value: Content can be decompressed with {@link java.util.zip.GZIPOutputStream}. */
+    /** Flag value: Content can be decompressed with java.util.zip.GZIPOutputStream. */
     public static final int IS_GZIPPED = 4;
 
     /** Flag value for serialization only: Value is a byte array, not a file descriptor */
diff --git a/core/java/android/os/PerformanceHintManager.java b/core/java/android/os/PerformanceHintManager.java
index 6791844..a75b5ef 100644
--- a/core/java/android/os/PerformanceHintManager.java
+++ b/core/java/android/os/PerformanceHintManager.java
@@ -24,24 +24,23 @@
 import com.android.internal.util.Preconditions;
 
 import java.io.Closeable;
-import java.util.ArrayList;
 
 /** The PerformanceHintManager allows apps to send performance hint to system. */
 @SystemService(Context.PERFORMANCE_HINT_SERVICE)
 public final class PerformanceHintManager {
-    private static final String TAG = "PerformanceHintManager";
-    private final IHintManager mService;
-    // HAL preferred update rate
-    private final long mPreferredRate;
+    private final long mNativeManagerPtr;
 
     /** @hide */
-    public PerformanceHintManager(IHintManager service) {
-        mService = service;
-        try {
-            mPreferredRate = mService.getHintSessionPreferredRate();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
+    public static PerformanceHintManager create() throws ServiceManager.ServiceNotFoundException {
+        long nativeManagerPtr = nativeAcquireManager();
+        if (nativeManagerPtr == 0) {
+            throw new ServiceManager.ServiceNotFoundException(Context.PERFORMANCE_HINT_SERVICE);
         }
+        return new PerformanceHintManager(nativeManagerPtr);
+    }
+
+    private PerformanceHintManager(long nativeManagerPtr) {
+        mNativeManagerPtr = nativeManagerPtr;
     }
 
     /**
@@ -57,16 +56,13 @@
      */
     @Nullable
     public Session createHintSession(@NonNull int[] tids, long initialTargetWorkDurationNanos) {
-        try {
-            IBinder token = new Binder();
-            IHintSession session = mService.createHintSession(token, tids,
-                    initialTargetWorkDurationNanos);
-            if (session == null) return null;
-            return new Session(session, sNanoClock, mPreferredRate,
-                    initialTargetWorkDurationNanos);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        Preconditions.checkNotNull(tids, "tids cannot be null");
+        Preconditions.checkArgumentPositive(initialTargetWorkDurationNanos,
+                "the hint target duration should be positive.");
+        long nativeSessionPtr = nativeCreateSession(mNativeManagerPtr, tids,
+                initialTargetWorkDurationNanos);
+        if (nativeSessionPtr == 0) return null;
+        return new Session(nativeSessionPtr);
     }
 
     /**
@@ -75,7 +71,7 @@
      * @return the preferred update rate supported by device software.
      */
     public long getPreferredUpdateRateNanos() {
-        return mPreferredRate;
+        return nativeGetPreferredUpdateRateNanos(mNativeManagerPtr);
     }
 
     /**
@@ -101,28 +97,21 @@
      * <p>All timings should be in {@link SystemClock#elapsedRealtimeNanos()}.</p>
      */
     public static class Session implements Closeable {
-        private final IHintSession mSession;
-        private final NanoClock mElapsedRealtimeClock;
-        // Target duration for choosing update rate
-        private long mTargetDurationInNanos;
-        // HAL preferred update rate
-        private long mPreferredRate;
-        // Last update timestamp
-        private long mLastUpdateTimeStamp = -1L;
-        // Cached samples
-        private final ArrayList<Long> mActualDurationNanos;
-        private final ArrayList<Long> mTimeStampNanos;
+        private long mNativeSessionPtr;
 
         /** @hide */
-        public Session(IHintSession session, NanoClock elapsedRealtimeClock, long preferredRate,
-                long durationNanos) {
-            mSession = session;
-            mElapsedRealtimeClock = elapsedRealtimeClock;
-            mTargetDurationInNanos = durationNanos;
-            mPreferredRate = preferredRate;
-            mActualDurationNanos = new ArrayList<Long>();
-            mTimeStampNanos = new ArrayList<Long>();
-            mLastUpdateTimeStamp = mElapsedRealtimeClock.nanos();
+        public Session(long nativeSessionPtr) {
+            mNativeSessionPtr = nativeSessionPtr;
+        }
+
+        /** @hide */
+        @Override
+        protected void finalize() throws Throwable {
+            try {
+                close();
+            } finally {
+                super.finalize();
+            }
         }
 
         /**
@@ -133,19 +122,7 @@
         public void updateTargetWorkDuration(long targetDurationNanos) {
             Preconditions.checkArgumentPositive(targetDurationNanos, "the hint target duration"
                     + " should be positive.");
-            try {
-                mSession.updateTargetWorkDuration(targetDurationNanos);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-            mTargetDurationInNanos = targetDurationNanos;
-            /**
-             * Most of the workload is target_duration dependent, so now clear the cached samples
-             * as they are most likely obsolete.
-             */
-            mActualDurationNanos.clear();
-            mTimeStampNanos.clear();
-            mLastUpdateTimeStamp = mElapsedRealtimeClock.nanos();
+            nativeUpdateTargetWorkDuration(mNativeSessionPtr, targetDurationNanos);
         }
 
         /**
@@ -161,38 +138,7 @@
         public void reportActualWorkDuration(long actualDurationNanos) {
             Preconditions.checkArgumentPositive(actualDurationNanos, "the actual duration should"
                     + " be positive.");
-            final long now = mElapsedRealtimeClock.nanos();
-            mActualDurationNanos.add(actualDurationNanos);
-            mTimeStampNanos.add(now);
-
-            /**
-             * Use current sample to determine the rate limit. We can pick a shorter rate limit
-             * if any sample underperformed, however, it could be the lower level system is slow
-             * to react. So here we explicitly choose the rate limit with the latest sample.
-             */
-            long rateLimit =
-                    actualDurationNanos > mTargetDurationInNanos ? mPreferredRate
-                            : 10 * mPreferredRate;
-
-            if (now - mLastUpdateTimeStamp <= rateLimit) {
-                return;
-            }
-            Preconditions.checkState(mActualDurationNanos.size() == mTimeStampNanos.size());
-            final int size = mActualDurationNanos.size();
-            long[] actualDurationArray = new long[size];
-            long[] timeStampArray = new long[size];
-            for (int i = 0; i < size; i++) {
-                actualDurationArray[i] = mActualDurationNanos.get(i);
-                timeStampArray[i] = mTimeStampNanos.get(i);
-            }
-            try {
-                mSession.reportActualWorkDuration(actualDurationArray, timeStampArray);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-            mActualDurationNanos.clear();
-            mTimeStampNanos.clear();
-            mLastUpdateTimeStamp = now;
+            nativeReportActualWorkDuration(mNativeSessionPtr, actualDurationNanos);
         }
 
         /**
@@ -201,26 +147,20 @@
          * <p>Once called, you should not call anything else on this object.</p>
          */
         public void close() {
-            try {
-                mSession.close();
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
+            if (mNativeSessionPtr != 0) {
+                nativeCloseSession(mNativeSessionPtr);
+                mNativeSessionPtr = 0;
             }
         }
     }
 
-    /**
-     * The interface is to make the FakeClock for testing.
-     * @hide
-     */
-    public interface NanoClock {
-        /** Gets the current nanosecond instant of the clock. */
-        long nanos();
-    }
-
-    private static final NanoClock sNanoClock = new NanoClock() {
-        public long nanos() {
-            return SystemClock.elapsedRealtimeNanos();
-        }
-    };
+    private static native long nativeAcquireManager();
+    private static native long nativeGetPreferredUpdateRateNanos(long nativeManagerPtr);
+    private static native long nativeCreateSession(long nativeManagerPtr,
+            int[] tids, long initialTargetWorkDurationNanos);
+    private static native void nativeUpdateTargetWorkDuration(long nativeSessionPtr,
+            long targetDurationNanos);
+    private static native void nativeReportActualWorkDuration(long nativeSessionPtr,
+            long actualDurationNanos);
+    private static native void nativeCloseSession(long nativeSessionPtr);
 }
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index c8cbc51..ddb6533 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -102,8 +102,6 @@
     /** @hide */
     public static final long TRACE_TAG_RRO = 1L << 26;
     /** @hide */
-    public static final long TRACE_TAG_SYSPROP = 1L << 27;
-    /** @hide */
     public static final long TRACE_TAG_APEX_MANAGER = 1L << 18;
 
     private static final long TRACE_TAG_NOT_READY = 1L << 63;
diff --git a/core/java/android/service/voice/HotwordDetectionService.java b/core/java/android/service/voice/HotwordDetectionService.java
index a435239..e3bb589 100644
--- a/core/java/android/service/voice/HotwordDetectionService.java
+++ b/core/java/android/service/voice/HotwordDetectionService.java
@@ -72,8 +72,7 @@
 @SystemApi
 public abstract class HotwordDetectionService extends Service {
     private static final String TAG = "HotwordDetectionService";
-    // TODO (b/177502877): Set the Debug flag to false before shipping.
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
 
     private static final long UPDATE_TIMEOUT_MILLIS = 5000;
 
@@ -151,9 +150,7 @@
         @Override
         public void updateState(PersistableBundle options, SharedMemory sharedMemory,
                 IRemoteCallback callback) throws RemoteException {
-            if (DBG) {
-                Log.d(TAG, "#updateState");
-            }
+            Log.v(TAG, "#updateState" + (callback != null ? " with callback" : ""));
             HotwordDetectionService.this.onUpdateStateInternal(
                     options,
                     sharedMemory,
diff --git a/core/java/android/service/voice/SoftwareHotwordDetector.java b/core/java/android/service/voice/SoftwareHotwordDetector.java
index fb540b1..02294e5 100644
--- a/core/java/android/service/voice/SoftwareHotwordDetector.java
+++ b/core/java/android/service/voice/SoftwareHotwordDetector.java
@@ -47,7 +47,7 @@
  **/
 class SoftwareHotwordDetector extends AbstractHotwordDetector {
     private static final String TAG = SoftwareHotwordDetector.class.getSimpleName();
-    private static final boolean DEBUG = true;
+    private static final boolean DEBUG = false;
 
     private final IVoiceInteractionManagerService mManagerService;
     private final HotwordDetector.Callback mCallback;
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index fe1fcfc..7a61511 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -1033,6 +1033,9 @@
                                     .build();
                             updateSurfaceDimming();
                         }
+                        // Propagate transform hint from WM so we can use the right hint for the
+                        // first frame.
+                        mBbqSurfaceControl.setTransformHint(mSurfaceControl.getTransformHint());
                         Surface blastSurface = getOrCreateBLASTSurface(mSurfaceSize.x,
                                 mSurfaceSize.y, mFormat);
                         // If blastSurface == null that means it hasn't changed since the last
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index 4b18c5a..bedad73 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -111,7 +111,12 @@
         IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() {
             @Override
             public void onSubscriptionsChanged () {
-                executor.execute(() -> listener.onSubscriptionsChanged());
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    executor.execute(() -> listener.onSubscriptionsChanged());
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
             }
         };
         mSubscriptionChangedListenerMap.put(listener, callback);
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 4e2f37f..8143cf9 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -148,6 +148,8 @@
             float width, float height, float vecX, float vecY,
             float maxStretchAmountX, float maxStretchAmountY, float childRelativeLeft,
             float childRelativeTop, float childRelativeRight, float childRelativeBottom);
+    private static native void nativeSetTrustedOverlay(long transactionObj, long nativeObject,
+            boolean isTrustedOverlay);
 
     private static native boolean nativeClearContentFrameStats(long nativeObject);
     private static native boolean nativeGetContentFrameStats(long nativeObject, WindowContentFrameStats outStats);
@@ -3413,6 +3415,17 @@
             return this;
         }
 
+        /**
+         * Sets the trusted overlay state on this SurfaceControl and it is inherited to all the
+         * children. The caller must hold the ACCESS_SURFACE_FLINGER permission.
+         * @hide
+         */
+        public Transaction setTrustedOverlay(SurfaceControl sc, boolean isTrustedOverlay) {
+            checkPreconditions(sc);
+            nativeSetTrustedOverlay(mNativeObject, sc.mNativeObject, isTrustedOverlay);
+            return this;
+        }
+
          /**
          * Merge the other transaction into this transaction, clearing the
          * other transaction as if it had been applied.
diff --git a/core/java/android/window/StartingWindowInfo.java b/core/java/android/window/StartingWindowInfo.java
index 566f154..8c64474 100644
--- a/core/java/android/window/StartingWindowInfo.java
+++ b/core/java/android/window/StartingWindowInfo.java
@@ -22,6 +22,7 @@
 import android.annotation.TestApi;
 import android.app.ActivityManager;
 import android.app.TaskInfo;
+import android.content.pm.ActivityInfo;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.view.InsetsState;
@@ -78,6 +79,14 @@
     public ActivityManager.RunningTaskInfo taskInfo;
 
     /**
+     * The {@link ActivityInfo} of the target activity which to create the starting window.
+     * It can be null if the info is the same as the top in task info.
+     * @hide
+     */
+    @Nullable
+    public ActivityInfo targetActivityInfo;
+
+    /**
      * InsetsState of TopFullscreenOpaqueWindow
      * @hide
      */
@@ -174,6 +183,7 @@
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeTypedObject(taskInfo, flags);
+        dest.writeTypedObject(targetActivityInfo, flags);
         dest.writeInt(startingWindowTypeParameter);
         dest.writeTypedObject(topOpaqueWindowInsetsState, flags);
         dest.writeTypedObject(topOpaqueWindowLayoutParams, flags);
@@ -185,6 +195,7 @@
 
     void readFromParcel(@NonNull Parcel source) {
         taskInfo = source.readTypedObject(ActivityManager.RunningTaskInfo.CREATOR);
+        targetActivityInfo = source.readTypedObject(ActivityInfo.CREATOR);
         startingWindowTypeParameter = source.readInt();
         topOpaqueWindowInsetsState = source.readTypedObject(InsetsState.CREATOR);
         topOpaqueWindowLayoutParams = source.readTypedObject(
@@ -198,6 +209,7 @@
     @Override
     public String toString() {
         return "StartingWindowInfo{taskId=" + taskInfo.taskId
+                + " targetActivityInfo=" + targetActivityInfo
                 + " displayId=" + taskInfo.displayId
                 + " topActivityType=" + taskInfo.topActivityType
                 + " preferredStartingWindowType="
diff --git a/core/java/com/android/internal/app/AbstractResolverComparator.java b/core/java/com/android/internal/app/AbstractResolverComparator.java
index 40ada0b..c00d16c 100644
--- a/core/java/com/android/internal/app/AbstractResolverComparator.java
+++ b/core/java/com/android/internal/app/AbstractResolverComparator.java
@@ -22,6 +22,7 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.os.BadParcelableException;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -109,17 +110,22 @@
 
     // get annotations of content from intent.
     private void getContentAnnotations(Intent intent) {
-        ArrayList<String> annotations = intent.getStringArrayListExtra(
-                Intent.EXTRA_CONTENT_ANNOTATIONS);
-        if (annotations != null) {
-            int size = annotations.size();
-            if (size > NUM_OF_TOP_ANNOTATIONS_TO_USE) {
-                size = NUM_OF_TOP_ANNOTATIONS_TO_USE;
+        try {
+            ArrayList<String> annotations = intent.getStringArrayListExtra(
+                    Intent.EXTRA_CONTENT_ANNOTATIONS);
+            if (annotations != null) {
+                int size = annotations.size();
+                if (size > NUM_OF_TOP_ANNOTATIONS_TO_USE) {
+                    size = NUM_OF_TOP_ANNOTATIONS_TO_USE;
+                }
+                mAnnotations = new String[size];
+                for (int i = 0; i < size; i++) {
+                    mAnnotations[i] = annotations.get(i);
+                }
             }
-            mAnnotations = new String[size];
-            for (int i = 0; i < size; i++) {
-                mAnnotations[i] = annotations.get(i);
-            }
+        } catch (BadParcelableException e) {
+            Log.i(TAG, "Couldn't unparcel intent annotations. Ignoring.");
+            mAnnotations = new String[0];
         }
     }
 
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index eeceafa..786af5f 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -1269,7 +1269,8 @@
                             SELECTION_TYPE_NEARBY,
                             "",
                             -1);
-                    safelyStartActivity(ti);
+                    // Action bar is user-independent, always start as primary
+                    safelyStartActivityAsUser(ti, getPersonalProfileUserHandle());
                     finish();
                 }
         );
@@ -1290,7 +1291,8 @@
                             SELECTION_TYPE_EDIT,
                             "",
                             -1);
-                    safelyStartActivity(ti);
+                    // Action bar is user-independent, always start as primary
+                    safelyStartActivityAsUser(ti, getPersonalProfileUserHandle());
                     finish();
                 }
         );
@@ -3452,8 +3454,6 @@
 
         private View createProfileView(ViewGroup parent) {
             View profileRow = mLayoutInflater.inflate(R.layout.chooser_profile_row, parent, false);
-            profileRow.setBackground(
-                    getResources().getDrawable(R.drawable.chooser_row_layer_list, null));
             mProfileView = profileRow.findViewById(R.id.profile_button);
             mProfileView.setOnClickListener(ChooserActivity.this::onProfileClick);
             updateProfileViewButton();
@@ -3599,10 +3599,6 @@
             final ViewGroup viewGroup = (ViewGroup) holder.itemView;
             int start = getListPosition(position);
             int startType = getRowType(start);
-            if (viewGroup.getForeground() == null && position > 0) {
-                viewGroup.setForeground(
-                        getResources().getDrawable(R.drawable.chooser_row_layer_list, null));
-            }
 
             int columnCount = holder.getColumnCount();
             int end = start + columnCount - 1;
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 6f9da6f..d08f21c 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -1257,13 +1257,32 @@
         // don't kill ourselves.
         StrictMode.disableDeathOnFileUriExposure();
         try {
-            safelyStartActivityInternal(cti);
+            UserHandle currentUserHandle = mMultiProfilePagerAdapter.getCurrentUserHandle();
+            safelyStartActivityInternal(cti, currentUserHandle);
         } finally {
             StrictMode.enableDeathOnFileUriExposure();
         }
     }
 
-    private void safelyStartActivityInternal(TargetInfo cti) {
+    /**
+     * Start activity as a fixed user handle.
+     * @param cti TargetInfo to be launched.
+     * @param user User to launch this activity as.
+     */
+    @VisibleForTesting
+    public void safelyStartActivityAsUser(TargetInfo cti, UserHandle user) {
+        // We're dispatching intents that might be coming from legacy apps, so
+        // don't kill ourselves.
+        StrictMode.disableDeathOnFileUriExposure();
+        try {
+            safelyStartActivityInternal(cti, user);
+        } finally {
+            StrictMode.enableDeathOnFileUriExposure();
+        }
+    }
+
+
+    private void safelyStartActivityInternal(TargetInfo cti, UserHandle user) {
         // If the target is suspended, the activity will not be successfully launched.
         // Do not unregister from package manager updates in this case
         if (!cti.isSuspended() && mRegistered) {
@@ -1280,18 +1299,17 @@
         if (mProfileSwitchMessageId != -1) {
             Toast.makeText(this, getString(mProfileSwitchMessageId), Toast.LENGTH_LONG).show();
         }
-        UserHandle currentUserHandle = mMultiProfilePagerAdapter.getCurrentUserHandle();
         if (!mSafeForwardingMode) {
-            if (cti.startAsUser(this, null, currentUserHandle)) {
+            if (cti.startAsUser(this, null, user)) {
                 onActivityStarted(cti);
-                maybeLogCrossProfileTargetLaunch(cti, currentUserHandle);
+                maybeLogCrossProfileTargetLaunch(cti, user);
             }
             return;
         }
         try {
-            if (cti.startAsCaller(this, null, currentUserHandle.getIdentifier())) {
+            if (cti.startAsCaller(this, null, user.getIdentifier())) {
                 onActivityStarted(cti);
-                maybeLogCrossProfileTargetLaunch(cti, currentUserHandle);
+                maybeLogCrossProfileTargetLaunch(cti, user);
             }
         } catch (RuntimeException e) {
             Slog.wtf(TAG, "Unable to launch as uid " + mLaunchedFromUid
diff --git a/core/java/com/android/internal/display/BrightnessSynchronizer.java b/core/java/com/android/internal/display/BrightnessSynchronizer.java
index c9a9e51..55a2052 100644
--- a/core/java/com/android/internal/display/BrightnessSynchronizer.java
+++ b/core/java/com/android/internal/display/BrightnessSynchronizer.java
@@ -16,9 +16,11 @@
 
 package com.android.internal.display;
 
+import android.annotation.NonNull;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.database.ContentObserver;
+import android.hardware.display.BrightnessInfo;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManager.DisplayListener;
 import android.net.Uri;
@@ -61,10 +63,10 @@
                     updateBrightnessFloatFromInt(msg.arg1);
                     break;
                 case MSG_UPDATE_INT:
-                    updateBrightnessIntFromFloat(Float.intBitsToFloat(msg.arg1));
+                    updateBrightnessIntFromFloat((BrightnessInfo) msg.obj);
                     break;
                 case MSG_UPDATE_BOTH:
-                    updateBoth(Float.intBitsToFloat(msg.arg1));
+                    updateBoth((BrightnessInfo) msg.obj, Float.intBitsToFloat(msg.arg1));
                     break;
                 default:
                     super.handleMessage(msg);
@@ -95,11 +97,11 @@
         brightnessSyncObserver = new BrightnessSyncObserver();
         brightnessSyncObserver.startObserving();
 
-        final float currentFloatBrightness = getScreenBrightnessFloat();
+        final BrightnessInfo brightnessInfo = getBrightnessInfo();
         final int currentIntBrightness = getScreenBrightnessInt(mContext);
 
-        if (!Float.isNaN(currentFloatBrightness)) {
-            updateBrightnessIntFromFloat(currentFloatBrightness);
+        if (brightnessInfo != null && !Float.isNaN(brightnessInfo.brightness)) {
+            updateBrightnessIntFromFloat(brightnessInfo);
         } else if (currentIntBrightness != -1) {
             updateBrightnessFloatFromInt(currentIntBrightness);
         } else {
@@ -112,15 +114,23 @@
 
     /**
      * Converts between the int brightness system and the float brightness system.
+     *
+     * @param brightnessInt The int brightness value to convert.
      */
     public static float brightnessIntToFloat(int brightnessInt) {
+        return brightnessIntToFloat(brightnessInt, null);
+    }
+
+    private static float brightnessIntToFloat(int brightnessInt, BrightnessInfo info) {
         if (brightnessInt == PowerManager.BRIGHTNESS_OFF) {
             return PowerManager.BRIGHTNESS_OFF_FLOAT;
         } else if (brightnessInt == PowerManager.BRIGHTNESS_INVALID) {
             return PowerManager.BRIGHTNESS_INVALID_FLOAT;
         } else {
-            final float minFloat = PowerManager.BRIGHTNESS_MIN;
-            final float maxFloat = PowerManager.BRIGHTNESS_MAX;
+            final float minFloat = info != null
+                    ? info.brightnessMinimum : PowerManager.BRIGHTNESS_MIN;
+            final float maxFloat = info != null
+                    ? info.brightnessMaximum : PowerManager.BRIGHTNESS_MAX;
             final float minInt = PowerManager.BRIGHTNESS_OFF + 1;
             final float maxInt = PowerManager.BRIGHTNESS_ON;
             return MathUtils.constrainedMap(minFloat, maxFloat, minInt, maxInt, brightnessInt);
@@ -128,29 +138,28 @@
     }
 
     /**
-     * Converts between the float brightness system and the int brightness system.
-     */
-    public static int brightnessFloatToInt(float brightnessFloat) {
-        return Math.round(brightnessFloatToIntRange(brightnessFloat));
-    }
-
-    /**
      * Translates specified value from the float brightness system to the int brightness system,
      * given the min/max of each range. Accounts for special values such as OFF and invalid values.
      * Value returned as a float primitive (to preserve precision), but is a value within the
      * int-system range.
+     *
+     * @param brightnessFloat The float brightness value to convert.
+     * @param info Brightness information to use in the conversion.
      */
-    public static float brightnessFloatToIntRange(float brightnessFloat) {
+    public static int brightnessFloatToInt(float brightnessFloat, BrightnessInfo info) {
         if (floatEquals(brightnessFloat, PowerManager.BRIGHTNESS_OFF_FLOAT)) {
             return PowerManager.BRIGHTNESS_OFF;
         } else if (Float.isNaN(brightnessFloat)) {
             return PowerManager.BRIGHTNESS_INVALID;
         } else {
-            final float minFloat = PowerManager.BRIGHTNESS_MIN;
-            final float maxFloat = PowerManager.BRIGHTNESS_MAX;
+            final float minFloat = info != null
+                    ? info.brightnessMinimum : PowerManager.BRIGHTNESS_MIN;
+            final float maxFloat = info != null
+                    ? info.brightnessMaximum : PowerManager.BRIGHTNESS_MAX;
             final float minInt = PowerManager.BRIGHTNESS_OFF + 1;
             final float maxInt = PowerManager.BRIGHTNESS_ON;
-            return MathUtils.constrainedMap(minInt, maxInt, minFloat, maxFloat, brightnessFloat);
+            return Math.round(MathUtils.constrainedMap(minInt, maxInt, minFloat, maxFloat,
+                    brightnessFloat));
         }
     }
 
@@ -185,35 +194,37 @@
      * @param value Brightness value as int to store in the float setting.
      */
     private void updateBrightnessFloatFromInt(int value) {
-        if (brightnessFloatToInt(mPreferredSettingValue) == value) {
+        final BrightnessInfo info = getBrightnessInfo();
+        if (brightnessFloatToInt(mPreferredSettingValue, info) == value) {
             return;
         }
 
-        mPreferredSettingValue = brightnessIntToFloat(value);
+        mPreferredSettingValue = brightnessIntToFloat(value, info);
         final int newBrightnessAsIntBits = Float.floatToIntBits(mPreferredSettingValue);
         mHandler.removeMessages(MSG_UPDATE_BOTH);
         mHandler.obtainMessage(MSG_UPDATE_BOTH, newBrightnessAsIntBits, 0).sendToTarget();
     }
 
     /**
-     * Updates the settings based on a passed in float value. This is called whenever the float
-     * setting changes. mPreferredSettingValue holds the most recently updated brightness value
-     * as a float that we would like the display to be set to.
+     * Updates the settings from the specified {@link BrightnessInfo}. This is called whenever the
+     * float brightness changed from DisplayManager. mPreferredSettingValue holds the most recently
+     * updated brightness value as a float that we would like the display to be set to.
      *
      * We then schedule an update to both the int and float settings, but, remove all the other
      * messages to update all, to prevent us getting stuck in a loop.
      *
-     * @param value Brightness setting as float to store in int setting.
+     * @param brightnessInfo Current brightness information
      */
-    private void updateBrightnessIntFromFloat(float value) {
+    private void updateBrightnessIntFromFloat(@NonNull BrightnessInfo brightnessInfo) {
+        final float value = brightnessInfo.brightness;
         if (floatEquals(mPreferredSettingValue, value)) {
             return;
         }
 
         mPreferredSettingValue = value;
-        final int newBrightnessAsIntBits = Float.floatToIntBits(mPreferredSettingValue);
         mHandler.removeMessages(MSG_UPDATE_BOTH);
-        mHandler.obtainMessage(MSG_UPDATE_BOTH, newBrightnessAsIntBits, 0).sendToTarget();
+        mHandler.obtainMessage(MSG_UPDATE_BOTH, Float.floatToIntBits(value), 0, brightnessInfo)
+                .sendToTarget();
     }
 
 
@@ -222,16 +233,24 @@
      * mDisplayManager.setBrightness automatically checks for changes
      * Settings.System.putIntForUser needs to be checked, to prevent an extra callback to this class
      *
+     * @param brightnessInfo Brightness information, takes precedent over newBrightnessFloat
      * @param newBrightnessFloat Brightness setting as float to store in both settings
      */
-    private void updateBoth(float newBrightnessFloat) {
-        int newBrightnessInt = brightnessFloatToInt(newBrightnessFloat);
+    private void updateBoth(BrightnessInfo brightnessInfo, float newBrightnessFloat) {
+        int newBrightnessInt = brightnessFloatToInt(newBrightnessFloat, brightnessInfo);
         mDisplayManager.setBrightness(Display.DEFAULT_DISPLAY, newBrightnessFloat);
         if (getScreenBrightnessInt(mContext) != newBrightnessInt) {
             Settings.System.putIntForUser(mContext.getContentResolver(),
                     Settings.System.SCREEN_BRIGHTNESS, newBrightnessInt, UserHandle.USER_CURRENT);
         }
+    }
 
+    private BrightnessInfo getBrightnessInfo() {
+        final Display display = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
+        if (display != null) {
+            return display.getBrightnessInfo();
+        }
+        return null;
     }
 
     /**
@@ -263,10 +282,15 @@
 
             @Override
             public void onDisplayChanged(int displayId) {
-                float currentFloat = getScreenBrightnessFloat();
-                int toSend = Float.floatToIntBits(currentFloat);
-                mHandler.removeMessages(MSG_UPDATE_INT);
-                mHandler.obtainMessage(MSG_UPDATE_INT, toSend, 0).sendToTarget();
+                if (displayId != Display.DEFAULT_DISPLAY) {
+                    return;
+                }
+
+                final BrightnessInfo info = getBrightnessInfo();
+                if (info != null) {
+                    mHandler.removeMessages(MSG_UPDATE_INT);
+                    mHandler.obtainMessage(MSG_UPDATE_INT, info).sendToTarget();
+                }
             }
         };
 
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index 6ce7cea..be91aac 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -220,8 +220,9 @@
     public CallSession callStarted(Binder binder, int code, int workSourceUid) {
         noteNativeThreadId();
 
+        boolean collectCpu = canCollect();
         // We always want to collect data for latency if it's enabled, regardless of device state.
-        if (!mCollectLatencyData && !canCollect()) {
+        if (!mCollectLatencyData && !collectCpu) {
             return null;
         }
 
@@ -233,7 +234,7 @@
         s.timeStarted = -1;
         s.recordedCall = shouldRecordDetailedData();
 
-        if (mRecordingAllTransactionsForUid || s.recordedCall) {
+        if (collectCpu && (mRecordingAllTransactionsForUid || s.recordedCall)) {
             s.cpuTimeStarted = getThreadTimeMicro();
             s.timeStarted = getElapsedRealtimeMicro();
         } else if (mCollectLatencyData) {
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index a8dcbaf..6cbace4 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -241,7 +241,11 @@
 
     private final ArraySet<String> mRollbackWhitelistedPackages = new ArraySet<>();
     private final ArraySet<String> mWhitelistedStagedInstallers = new ArraySet<>();
-    private final ArraySet<String> mAllowedVendorApexes = new ArraySet<>();
+    // A map from package name of vendor APEXes that can be updated to an installer package name
+    // allowed to install updates for it.
+    private final ArrayMap<String, String> mAllowedVendorApexes = new ArrayMap<>();
+
+    private String mModulesInstallerPackageName;
 
     /**
      * Map of system pre-defined, uniquely named actors; keys are namespace,
@@ -412,10 +416,14 @@
         return mWhitelistedStagedInstallers;
     }
 
-    public Set<String> getAllowedVendorApexes() {
+    public Map<String, String> getAllowedVendorApexes() {
         return mAllowedVendorApexes;
     }
 
+    public String getModulesInstallerPackageName() {
+        return mModulesInstallerPackageName;
+    }
+
     public ArraySet<String> getAppDataIsolationWhitelistedApps() {
         return mAppDataIsolationWhitelistedApps;
     }
@@ -1210,12 +1218,21 @@
                     case "whitelisted-staged-installer": {
                         if (allowAppConfigs) {
                             String pkgname = parser.getAttributeValue(null, "package");
+                            boolean isModulesInstaller = XmlUtils.readBooleanAttribute(
+                                    parser, "isModulesInstaller", false);
                             if (pkgname == null) {
                                 Slog.w(TAG, "<" + name + "> without package in " + permFile
                                         + " at " + parser.getPositionDescription());
                             } else {
                                 mWhitelistedStagedInstallers.add(pkgname);
                             }
+                            if (isModulesInstaller) {
+                                if (mModulesInstallerPackageName != null) {
+                                    throw new IllegalStateException(
+                                            "Multiple modules installers");
+                                }
+                                mModulesInstallerPackageName = pkgname;
+                            }
                         } else {
                             logNotAllowedInPartition(name, permFile, parser);
                         }
@@ -1224,11 +1241,18 @@
                     case "allowed-vendor-apex": {
                         if (allowVendorApex) {
                             String pkgName = parser.getAttributeValue(null, "package");
+                            String installerPkgName = parser.getAttributeValue(
+                                    null, "installerPackage");
                             if (pkgName == null) {
                                 Slog.w(TAG, "<" + name + "> without package in " + permFile
                                         + " at " + parser.getPositionDescription());
-                            } else {
-                                mAllowedVendorApexes.add(pkgName);
+                            }
+                            if (installerPkgName == null) {
+                                Slog.w(TAG, "<" + name + "> without installerPackage in " + permFile
+                                        + " at " + parser.getPositionDescription());
+                            }
+                            if (pkgName != null && installerPkgName != null) {
+                                mAllowedVendorApexes.put(pkgName, installerPkgName);
                             }
                         } else {
                             logNotAllowedInPartition(name, permFile, parser);
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 91a19e0..6b9d375 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -146,6 +146,7 @@
                 "android_os_MemoryFile.cpp",
                 "android_os_MessageQueue.cpp",
                 "android_os_Parcel.cpp",
+                "android_os_PerformanceHintManager.cpp",
                 "android_os_SELinux.cpp",
                 "android_os_ServiceManager.cpp",
                 "android_os_SharedMemory.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 406ccde..2fd1e54 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -143,6 +143,7 @@
 extern int register_android_os_ServiceManager(JNIEnv *env);
 extern int register_android_os_MessageQueue(JNIEnv* env);
 extern int register_android_os_Parcel(JNIEnv* env);
+extern int register_android_os_PerformanceHintManager(JNIEnv* env);
 extern int register_android_os_SELinux(JNIEnv* env);
 extern int register_android_os_VintfObject(JNIEnv *env);
 extern int register_android_os_VintfRuntimeInfo(JNIEnv *env);
@@ -1518,6 +1519,7 @@
         REG_JNI(register_android_os_SystemProperties),
         REG_JNI(register_android_os_Binder),
         REG_JNI(register_android_os_Parcel),
+        REG_JNI(register_android_os_PerformanceHintManager),
         REG_JNI(register_android_os_HidlMemory),
         REG_JNI(register_android_os_HidlSupport),
         REG_JNI(register_android_os_HwBinder),
diff --git a/core/jni/android_os_PerformanceHintManager.cpp b/core/jni/android_os_PerformanceHintManager.cpp
new file mode 100644
index 0000000..d05a24f
--- /dev/null
+++ b/core/jni/android_os_PerformanceHintManager.cpp
@@ -0,0 +1,155 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "PerfHint-jni"
+
+#include "jni.h"
+
+#include <dlfcn.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedPrimitiveArray.h>
+#include <utils/Log.h>
+#include <vector>
+
+#include "core_jni_helpers.h"
+
+namespace android {
+
+namespace {
+
+struct APerformanceHintManager;
+struct APerformanceHintSession;
+
+typedef APerformanceHintManager* (*APH_getManager)();
+typedef APerformanceHintSession* (*APH_createSession)(APerformanceHintManager*, const int32_t*,
+                                                      size_t, int64_t);
+typedef int64_t (*APH_getPreferredUpdateRateNanos)(APerformanceHintManager* manager);
+typedef void (*APH_updateTargetWorkDuration)(APerformanceHintSession*, int64_t);
+typedef void (*APH_reportActualWorkDuration)(APerformanceHintSession*, int64_t);
+typedef void (*APH_closeSession)(APerformanceHintSession* session);
+
+bool gAPerformanceHintBindingInitialized = false;
+APH_getManager gAPH_getManagerFn = nullptr;
+APH_createSession gAPH_createSessionFn = nullptr;
+APH_getPreferredUpdateRateNanos gAPH_getPreferredUpdateRateNanosFn = nullptr;
+APH_updateTargetWorkDuration gAPH_updateTargetWorkDurationFn = nullptr;
+APH_reportActualWorkDuration gAPH_reportActualWorkDurationFn = nullptr;
+APH_closeSession gAPH_closeSessionFn = nullptr;
+
+void ensureAPerformanceHintBindingInitialized() {
+    if (gAPerformanceHintBindingInitialized) return;
+
+    void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE);
+    LOG_ALWAYS_FATAL_IF(handle_ == nullptr, "Failed to dlopen libandroid.so!");
+
+    gAPH_getManagerFn = (APH_getManager)dlsym(handle_, "APerformanceHint_getManager");
+    LOG_ALWAYS_FATAL_IF(gAPH_getManagerFn == nullptr,
+                        "Failed to find required symbol APerformanceHint_getManager!");
+
+    gAPH_createSessionFn = (APH_createSession)dlsym(handle_, "APerformanceHint_createSession");
+    LOG_ALWAYS_FATAL_IF(gAPH_createSessionFn == nullptr,
+                        "Failed to find required symbol APerformanceHint_createSession!");
+
+    gAPH_getPreferredUpdateRateNanosFn =
+            (APH_getPreferredUpdateRateNanos)dlsym(handle_,
+                                                   "APerformanceHint_getPreferredUpdateRateNanos");
+    LOG_ALWAYS_FATAL_IF(gAPH_getPreferredUpdateRateNanosFn == nullptr,
+                        "Failed to find required symbol "
+                        "APerformanceHint_getPreferredUpdateRateNanos!");
+
+    gAPH_updateTargetWorkDurationFn =
+            (APH_updateTargetWorkDuration)dlsym(handle_,
+                                                "APerformanceHint_updateTargetWorkDuration");
+    LOG_ALWAYS_FATAL_IF(gAPH_updateTargetWorkDurationFn == nullptr,
+                        "Failed to find required symbol "
+                        "APerformanceHint_updateTargetWorkDuration!");
+
+    gAPH_reportActualWorkDurationFn =
+            (APH_reportActualWorkDuration)dlsym(handle_,
+                                                "APerformanceHint_reportActualWorkDuration");
+    LOG_ALWAYS_FATAL_IF(gAPH_reportActualWorkDurationFn == nullptr,
+                        "Failed to find required symbol "
+                        "APerformanceHint_reportActualWorkDuration!");
+
+    gAPH_closeSessionFn = (APH_closeSession)dlsym(handle_, "APerformanceHint_closeSession");
+    LOG_ALWAYS_FATAL_IF(gAPH_closeSessionFn == nullptr,
+                        "Failed to find required symbol APerformanceHint_closeSession!");
+
+    gAPerformanceHintBindingInitialized = true;
+}
+
+} // namespace
+
+static jlong nativeAcquireManager(JNIEnv* env, jclass clazz) {
+    ensureAPerformanceHintBindingInitialized();
+    return reinterpret_cast<jlong>(gAPH_getManagerFn());
+}
+
+static jlong nativeGetPreferredUpdateRateNanos(JNIEnv* env, jclass clazz, jlong nativeManagerPtr) {
+    ensureAPerformanceHintBindingInitialized();
+    return gAPH_getPreferredUpdateRateNanosFn(
+            reinterpret_cast<APerformanceHintManager*>(nativeManagerPtr));
+}
+
+static jlong nativeCreateSession(JNIEnv* env, jclass clazz, jlong nativeManagerPtr, jintArray tids,
+                                 jlong initialTargetWorkDurationNanos) {
+    ensureAPerformanceHintBindingInitialized();
+    if (tids == nullptr) return 0;
+    std::vector<int32_t> tidsVector;
+    ScopedIntArrayRO tidsArray(env, tids);
+    for (size_t i = 0; i < tidsArray.size(); ++i) {
+        tidsVector.push_back(static_cast<int32_t>(tidsArray[i]));
+    }
+    return reinterpret_cast<jlong>(
+            gAPH_createSessionFn(reinterpret_cast<APerformanceHintManager*>(nativeManagerPtr),
+                                 tidsVector.data(), tidsVector.size(),
+                                 initialTargetWorkDurationNanos));
+}
+
+static void nativeUpdateTargetWorkDuration(JNIEnv* env, jclass clazz, jlong nativeSessionPtr,
+                                           jlong targetDurationNanos) {
+    ensureAPerformanceHintBindingInitialized();
+    gAPH_updateTargetWorkDurationFn(reinterpret_cast<APerformanceHintSession*>(nativeSessionPtr),
+                                    targetDurationNanos);
+}
+
+static void nativeReportActualWorkDuration(JNIEnv* env, jclass clazz, jlong nativeSessionPtr,
+                                           jlong actualDurationNanos) {
+    ensureAPerformanceHintBindingInitialized();
+    gAPH_reportActualWorkDurationFn(reinterpret_cast<APerformanceHintSession*>(nativeSessionPtr),
+                                    actualDurationNanos);
+}
+
+static void nativeCloseSession(JNIEnv* env, jclass clazz, jlong nativeSessionPtr) {
+    ensureAPerformanceHintBindingInitialized();
+    gAPH_closeSessionFn(reinterpret_cast<APerformanceHintSession*>(nativeSessionPtr));
+}
+
+static const JNINativeMethod gPerformanceHintMethods[] = {
+        {"nativeAcquireManager", "()J", (void*)nativeAcquireManager},
+        {"nativeGetPreferredUpdateRateNanos", "(J)J", (void*)nativeGetPreferredUpdateRateNanos},
+        {"nativeCreateSession", "(J[IJ)J", (void*)nativeCreateSession},
+        {"nativeUpdateTargetWorkDuration", "(JJ)V", (void*)nativeUpdateTargetWorkDuration},
+        {"nativeReportActualWorkDuration", "(JJ)V", (void*)nativeReportActualWorkDuration},
+        {"nativeCloseSession", "(J)V", (void*)nativeCloseSession},
+};
+
+int register_android_os_PerformanceHintManager(JNIEnv* env) {
+    return RegisterMethodsOrDie(env, "android/os/PerformanceHintManager", gPerformanceHintMethods,
+                                NELEM(gPerformanceHintMethods));
+}
+
+} // namespace android
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 1695e1a..8d12df22 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -823,6 +823,14 @@
     transaction->setShadowRadius(ctrl, shadowRadius);
 }
 
+static void nativeSetTrustedOverlay(JNIEnv* env, jclass clazz, jlong transactionObj,
+                                    jlong nativeObject, jboolean isTrustedOverlay) {
+    auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+
+    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+    transaction->setTrustedOverlay(ctrl, isTrustedOverlay);
+}
+
 static void nativeSetFrameRate(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject,
                                jfloat frameRate, jint compatibility, jint changeFrameRateStrategy) {
     auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
@@ -1984,6 +1992,8 @@
             (void*)nativeSetTransformHint },
     {"nativeGetTransformHint", "(J)I",
             (void*)nativeGetTransformHint },
+    {"nativeSetTrustedOverlay", "(JJZ)V",
+            (void*)nativeSetTrustedOverlay },
         // clang-format on
 };
 
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index d49d215..bed0aae 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -887,7 +887,7 @@
 
     for (int fd : fds_to_close) {
       ALOGV("Switching descriptor %d to /dev/null", fd);
-      if (dup3(devnull_fd, fd, O_CLOEXEC) == -1) {
+      if (TEMP_FAILURE_RETRY(dup3(devnull_fd, fd, O_CLOEXEC)) == -1) {
         fail_fn(StringPrintf("Failed dup3() on descriptor %d: %s", fd, strerror(errno)));
       }
     }
diff --git a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
index 5fe96ed..248db76 100644
--- a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
+++ b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
@@ -426,7 +426,7 @@
       tmp_pid >>= 8;
     }
     pid_buf[4] = 0;  // Process is not wrapped.
-    int res = write(session_socket, pid_buf, 5);
+    int res = TEMP_FAILURE_RETRY(write(session_socket, pid_buf, 5));
     if (res != 5) {
       if (res == -1) {
         (first_time ? fail_fn_1 : fail_fn_n)
@@ -451,18 +451,18 @@
       }
       // We've now seen either a disconnect or connect request.
       close(session_socket);
-      int new_fd = accept(zygote_socket_fd, nullptr, nullptr);
+      int new_fd = TEMP_FAILURE_RETRY(accept(zygote_socket_fd, nullptr, nullptr));
       if (new_fd == -1) {
         fail_fn_z(CREATE_ERROR("Accept(%d) failed: %s", zygote_socket_fd, strerror(errno)));
       }
       if (new_fd != session_socket) {
           // Move new_fd back to the old value, so that we don't have to change Java-level data
           // structures to reflect a change. This implicitly closes the old one.
-          if (dup2(new_fd, session_socket) != session_socket) {
+          if (TEMP_FAILURE_RETRY(dup2(new_fd, session_socket)) != session_socket) {
             fail_fn_z(CREATE_ERROR("Failed to move fd %d to %d: %s",
                                    new_fd, session_socket, strerror(errno)));
           }
-          close(new_fd);
+          close(new_fd);  //  On Linux, fd is closed even if EINTR is returned.
       }
       // If we ever return, we effectively reuse the old Java ZygoteConnection.
       // None of its state needs to change.
diff --git a/core/res/res/drawable/chooser_row_layer_list.xml b/core/res/res/drawable/chooser_row_layer_list.xml
index 0800815..f5ba1e9 100644
--- a/core/res/res/drawable/chooser_row_layer_list.xml
+++ b/core/res/res/drawable/chooser_row_layer_list.xml
@@ -17,9 +17,11 @@
 */
 -->
 <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:bottom="-5dp" android:left="-5dp" android:right="-5dp">
+    <item>
         <shape android:shape="rectangle">
-            <stroke android:width="1dp" android:color="@color/chooser_row_divider"/>
+            <solid android:color="?android:attr/colorAccentSecondary"/>
+            <size android:width="128dp" android:height="2dp"/>
+            <corners android:radius="2dp" />
         </shape>
     </item>
 </layer-list>
diff --git a/core/res/res/layout/chooser_az_label_row.xml b/core/res/res/layout/chooser_az_label_row.xml
index 1b733fc..baf07ce 100644
--- a/core/res/res/layout/chooser_az_label_row.xml
+++ b/core/res/res/layout/chooser_az_label_row.xml
@@ -15,17 +15,12 @@
   ~ limitations under the License
   -->
 
-<!-- Separator applied as background -->
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
-          android:text="@string/chooser_all_apps_button_label"
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
           android:contentDescription="@string/chooser_all_apps_button_label"
-          android:background="@drawable/chooser_row_layer_list"
-          android:textAppearance="?attr/textAppearanceSmall"
-          android:textColor="?attr/textColorSecondary"
-          android:textSize="14sp"
-          android:singleLine="true"
+          android:src="@drawable/chooser_row_layer_list"
           android:paddingTop="16dp"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
+          android:scaleType="center"
           android:gravity="center"/>
 
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 0970fc5..2d94ffe 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1248,9 +1248,9 @@
     <string name="whichImageCaptureApplication" msgid="2737413019463215284">"Зрабіць здымак з дапамогай"</string>
     <string name="whichImageCaptureApplicationNamed" msgid="8820702441847612202">"Зрабіць здымак з дапамогай %1$s"</string>
     <string name="whichImageCaptureApplicationLabel" msgid="6505433734824988277">"Зрабіць здымак"</string>
-    <string name="alwaysUse" msgid="3153558199076112903">"Выкарыстоўваць па змаўчанні для гэтага дзеяння."</string>
+    <string name="alwaysUse" msgid="3153558199076112903">"Выкарыстоўваць стандартна для гэтага дзеяння."</string>
     <string name="use_a_different_app" msgid="4987790276170972776">"Выкарыстоўваць іншую праграму"</string>
-    <string name="clearDefaultHintMsg" msgid="1325866337702524936">"Ачысціць па змаўчанні ў раздзеле \"Налады сістэмы &gt; Прыкладанні &gt; Спампаваныя\"."</string>
+    <string name="clearDefaultHintMsg" msgid="1325866337702524936">"Ачысціць стандартныя налады ў раздзеле \"Налады сістэмы &gt; Праграмы &gt; Спампаваныя\"."</string>
     <string name="chooseActivity" msgid="8563390197659779956">"Выберыце дзеянне"</string>
     <string name="chooseUsbActivity" msgid="2096269989990986612">"Выберыце прыкладанне для USB-прылады"</string>
     <string name="noApplications" msgid="1186909265235544019">"Няма прыкладанняў, якія могуць выконваць гэты працэс."</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 141cf4e..8cf968d 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -700,8 +700,8 @@
     <string name="permdesc_bindConditionProviderService" msgid="6106018791256120258">"Allows the holder to bind to the top-level interface of a condition provider service. Should never be needed for normal apps."</string>
     <string name="permlab_bindDreamService" msgid="4776175992848982706">"bind to a dream service"</string>
     <string name="permdesc_bindDreamService" msgid="9129615743300572973">"Allows the holder to bind to the top-level interface of a dream service. Should never be needed for normal apps."</string>
-    <string name="permlab_invokeCarrierSetup" msgid="5098810760209818140">"invoke the carrier-provided configuration app"</string>
-    <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"Allows the holder to invoke the carrier-provided configuration app. Should never be needed for normal apps."</string>
+    <string name="permlab_invokeCarrierSetup" msgid="5098810760209818140">"invoke the operator-provided configuration app"</string>
+    <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"Allows the holder to invoke the operator-provided configuration app. Should never be needed for normal apps."</string>
     <string name="permlab_accessNetworkConditions" msgid="1270732533356286514">"listen for observations on network conditions"</string>
     <string name="permdesc_accessNetworkConditions" msgid="2959269186741956109">"Allows an application to listen for observations on network conditions. Should never be needed for normal apps."</string>
     <string name="permlab_setInputCalibration" msgid="932069700285223434">"change input device calibration"</string>
@@ -712,8 +712,8 @@
     <string name="permdesc_handoverStatus" msgid="3842269451732571070">"Allows this application to receive information about current Android Beam transfers"</string>
     <string name="permlab_removeDrmCertificates" msgid="710576248717404416">"remove DRM certificates"</string>
     <string name="permdesc_removeDrmCertificates" msgid="4068445390318355716">"Allows an application to remove DRM certficates. Should never be needed for normal apps."</string>
-    <string name="permlab_bindCarrierMessagingService" msgid="3363450860593096967">"bind to a carrier messaging service"</string>
-    <string name="permdesc_bindCarrierMessagingService" msgid="6316457028173478345">"Allows the holder to bind to the top-level interface of a carrier messaging service. Should never be needed for normal apps."</string>
+    <string name="permlab_bindCarrierMessagingService" msgid="3363450860593096967">"bind to an operator messaging service"</string>
+    <string name="permdesc_bindCarrierMessagingService" msgid="6316457028173478345">"Allows the holder to bind to the top-level interface of an operator messaging service. Should never be needed for normal apps."</string>
     <string name="permlab_bindCarrierServices" msgid="2395596978626237474">"bind to operator services"</string>
     <string name="permdesc_bindCarrierServices" msgid="9185614481967262900">"Allows the holder to bind to operator services. Should never be needed for normal apps."</string>
     <string name="permlab_access_notification_policy" msgid="5524112842876975537">"access Do Not Disturb"</string>
@@ -1655,7 +1655,7 @@
     <string name="kg_sim_pin_instructions" msgid="6479401489471690359">"Enter SIM PIN"</string>
     <string name="kg_pin_instructions" msgid="7355933174673539021">"Enter PIN"</string>
     <string name="kg_password_instructions" msgid="7179782578809398050">"Enter Password"</string>
-    <string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"SIM is now disabled. Enter PUK code to continue. Contact carrier for details."</string>
+    <string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"SIM is now disabled. Enter PUK code to continue. Contact operator for details."</string>
     <string name="kg_puk_enter_pin_hint" msgid="8190982314659429770">"Enter desired PIN code"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="6372557107414074580">"Confirm desired PIN code"</string>
     <string name="kg_sim_unlock_progress_dialog_message" msgid="8871937892678885545">"Unlocking SIM card…"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 2b1d3e0..b772335 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -700,8 +700,8 @@
     <string name="permdesc_bindConditionProviderService" msgid="6106018791256120258">"Allows the holder to bind to the top-level interface of a condition provider service. Should never be needed for normal apps."</string>
     <string name="permlab_bindDreamService" msgid="4776175992848982706">"bind to a dream service"</string>
     <string name="permdesc_bindDreamService" msgid="9129615743300572973">"Allows the holder to bind to the top-level interface of a dream service. Should never be needed for normal apps."</string>
-    <string name="permlab_invokeCarrierSetup" msgid="5098810760209818140">"invoke the carrier-provided configuration app"</string>
-    <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"Allows the holder to invoke the carrier-provided configuration app. Should never be needed for normal apps."</string>
+    <string name="permlab_invokeCarrierSetup" msgid="5098810760209818140">"invoke the operator-provided configuration app"</string>
+    <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"Allows the holder to invoke the operator-provided configuration app. Should never be needed for normal apps."</string>
     <string name="permlab_accessNetworkConditions" msgid="1270732533356286514">"listen for observations on network conditions"</string>
     <string name="permdesc_accessNetworkConditions" msgid="2959269186741956109">"Allows an application to listen for observations on network conditions. Should never be needed for normal apps."</string>
     <string name="permlab_setInputCalibration" msgid="932069700285223434">"change input device calibration"</string>
@@ -712,8 +712,8 @@
     <string name="permdesc_handoverStatus" msgid="3842269451732571070">"Allows this application to receive information about current Android Beam transfers"</string>
     <string name="permlab_removeDrmCertificates" msgid="710576248717404416">"remove DRM certificates"</string>
     <string name="permdesc_removeDrmCertificates" msgid="4068445390318355716">"Allows an application to remove DRM certficates. Should never be needed for normal apps."</string>
-    <string name="permlab_bindCarrierMessagingService" msgid="3363450860593096967">"bind to a carrier messaging service"</string>
-    <string name="permdesc_bindCarrierMessagingService" msgid="6316457028173478345">"Allows the holder to bind to the top-level interface of a carrier messaging service. Should never be needed for normal apps."</string>
+    <string name="permlab_bindCarrierMessagingService" msgid="3363450860593096967">"bind to an operator messaging service"</string>
+    <string name="permdesc_bindCarrierMessagingService" msgid="6316457028173478345">"Allows the holder to bind to the top-level interface of an operator messaging service. Should never be needed for normal apps."</string>
     <string name="permlab_bindCarrierServices" msgid="2395596978626237474">"bind to operator services"</string>
     <string name="permdesc_bindCarrierServices" msgid="9185614481967262900">"Allows the holder to bind to operator services. Should never be needed for normal apps."</string>
     <string name="permlab_access_notification_policy" msgid="5524112842876975537">"access Do Not Disturb"</string>
@@ -1655,7 +1655,7 @@
     <string name="kg_sim_pin_instructions" msgid="6479401489471690359">"Enter SIM PIN"</string>
     <string name="kg_pin_instructions" msgid="7355933174673539021">"Enter PIN"</string>
     <string name="kg_password_instructions" msgid="7179782578809398050">"Enter Password"</string>
-    <string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"SIM is now disabled. Enter PUK code to continue. Contact carrier for details."</string>
+    <string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"SIM is now disabled. Enter PUK code to continue. Contact operator for details."</string>
     <string name="kg_puk_enter_pin_hint" msgid="8190982314659429770">"Enter desired PIN code"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="6372557107414074580">"Confirm desired PIN code"</string>
     <string name="kg_sim_unlock_progress_dialog_message" msgid="8871937892678885545">"Unlocking SIM card…"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 01d8b39..e1e8187 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -700,8 +700,8 @@
     <string name="permdesc_bindConditionProviderService" msgid="6106018791256120258">"Allows the holder to bind to the top-level interface of a condition provider service. Should never be needed for normal apps."</string>
     <string name="permlab_bindDreamService" msgid="4776175992848982706">"bind to a dream service"</string>
     <string name="permdesc_bindDreamService" msgid="9129615743300572973">"Allows the holder to bind to the top-level interface of a dream service. Should never be needed for normal apps."</string>
-    <string name="permlab_invokeCarrierSetup" msgid="5098810760209818140">"invoke the carrier-provided configuration app"</string>
-    <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"Allows the holder to invoke the carrier-provided configuration app. Should never be needed for normal apps."</string>
+    <string name="permlab_invokeCarrierSetup" msgid="5098810760209818140">"invoke the operator-provided configuration app"</string>
+    <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"Allows the holder to invoke the operator-provided configuration app. Should never be needed for normal apps."</string>
     <string name="permlab_accessNetworkConditions" msgid="1270732533356286514">"listen for observations on network conditions"</string>
     <string name="permdesc_accessNetworkConditions" msgid="2959269186741956109">"Allows an application to listen for observations on network conditions. Should never be needed for normal apps."</string>
     <string name="permlab_setInputCalibration" msgid="932069700285223434">"change input device calibration"</string>
@@ -712,8 +712,8 @@
     <string name="permdesc_handoverStatus" msgid="3842269451732571070">"Allows this application to receive information about current Android Beam transfers"</string>
     <string name="permlab_removeDrmCertificates" msgid="710576248717404416">"remove DRM certificates"</string>
     <string name="permdesc_removeDrmCertificates" msgid="4068445390318355716">"Allows an application to remove DRM certficates. Should never be needed for normal apps."</string>
-    <string name="permlab_bindCarrierMessagingService" msgid="3363450860593096967">"bind to a carrier messaging service"</string>
-    <string name="permdesc_bindCarrierMessagingService" msgid="6316457028173478345">"Allows the holder to bind to the top-level interface of a carrier messaging service. Should never be needed for normal apps."</string>
+    <string name="permlab_bindCarrierMessagingService" msgid="3363450860593096967">"bind to an operator messaging service"</string>
+    <string name="permdesc_bindCarrierMessagingService" msgid="6316457028173478345">"Allows the holder to bind to the top-level interface of an operator messaging service. Should never be needed for normal apps."</string>
     <string name="permlab_bindCarrierServices" msgid="2395596978626237474">"bind to operator services"</string>
     <string name="permdesc_bindCarrierServices" msgid="9185614481967262900">"Allows the holder to bind to operator services. Should never be needed for normal apps."</string>
     <string name="permlab_access_notification_policy" msgid="5524112842876975537">"access Do Not Disturb"</string>
@@ -1655,7 +1655,7 @@
     <string name="kg_sim_pin_instructions" msgid="6479401489471690359">"Enter SIM PIN"</string>
     <string name="kg_pin_instructions" msgid="7355933174673539021">"Enter PIN"</string>
     <string name="kg_password_instructions" msgid="7179782578809398050">"Enter Password"</string>
-    <string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"SIM is now disabled. Enter PUK code to continue. Contact carrier for details."</string>
+    <string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"SIM is now disabled. Enter PUK code to continue. Contact operator for details."</string>
     <string name="kg_puk_enter_pin_hint" msgid="8190982314659429770">"Enter desired PIN code"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="6372557107414074580">"Confirm desired PIN code"</string>
     <string name="kg_sim_unlock_progress_dialog_message" msgid="8871937892678885545">"Unlocking SIM card…"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 3ed0279..892041c 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -700,8 +700,8 @@
     <string name="permdesc_bindConditionProviderService" msgid="6106018791256120258">"Allows the holder to bind to the top-level interface of a condition provider service. Should never be needed for normal apps."</string>
     <string name="permlab_bindDreamService" msgid="4776175992848982706">"bind to a dream service"</string>
     <string name="permdesc_bindDreamService" msgid="9129615743300572973">"Allows the holder to bind to the top-level interface of a dream service. Should never be needed for normal apps."</string>
-    <string name="permlab_invokeCarrierSetup" msgid="5098810760209818140">"invoke the carrier-provided configuration app"</string>
-    <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"Allows the holder to invoke the carrier-provided configuration app. Should never be needed for normal apps."</string>
+    <string name="permlab_invokeCarrierSetup" msgid="5098810760209818140">"invoke the operator-provided configuration app"</string>
+    <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"Allows the holder to invoke the operator-provided configuration app. Should never be needed for normal apps."</string>
     <string name="permlab_accessNetworkConditions" msgid="1270732533356286514">"listen for observations on network conditions"</string>
     <string name="permdesc_accessNetworkConditions" msgid="2959269186741956109">"Allows an application to listen for observations on network conditions. Should never be needed for normal apps."</string>
     <string name="permlab_setInputCalibration" msgid="932069700285223434">"change input device calibration"</string>
@@ -712,8 +712,8 @@
     <string name="permdesc_handoverStatus" msgid="3842269451732571070">"Allows this application to receive information about current Android Beam transfers"</string>
     <string name="permlab_removeDrmCertificates" msgid="710576248717404416">"remove DRM certificates"</string>
     <string name="permdesc_removeDrmCertificates" msgid="4068445390318355716">"Allows an application to remove DRM certficates. Should never be needed for normal apps."</string>
-    <string name="permlab_bindCarrierMessagingService" msgid="3363450860593096967">"bind to a carrier messaging service"</string>
-    <string name="permdesc_bindCarrierMessagingService" msgid="6316457028173478345">"Allows the holder to bind to the top-level interface of a carrier messaging service. Should never be needed for normal apps."</string>
+    <string name="permlab_bindCarrierMessagingService" msgid="3363450860593096967">"bind to an operator messaging service"</string>
+    <string name="permdesc_bindCarrierMessagingService" msgid="6316457028173478345">"Allows the holder to bind to the top-level interface of an operator messaging service. Should never be needed for normal apps."</string>
     <string name="permlab_bindCarrierServices" msgid="2395596978626237474">"bind to operator services"</string>
     <string name="permdesc_bindCarrierServices" msgid="9185614481967262900">"Allows the holder to bind to operator services. Should never be needed for normal apps."</string>
     <string name="permlab_access_notification_policy" msgid="5524112842876975537">"access Do Not Disturb"</string>
@@ -1655,7 +1655,7 @@
     <string name="kg_sim_pin_instructions" msgid="6479401489471690359">"Enter SIM PIN"</string>
     <string name="kg_pin_instructions" msgid="7355933174673539021">"Enter PIN"</string>
     <string name="kg_password_instructions" msgid="7179782578809398050">"Enter Password"</string>
-    <string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"SIM is now disabled. Enter PUK code to continue. Contact carrier for details."</string>
+    <string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"SIM is now disabled. Enter PUK code to continue. Contact operator for details."</string>
     <string name="kg_puk_enter_pin_hint" msgid="8190982314659429770">"Enter desired PIN code"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="6372557107414074580">"Confirm desired PIN code"</string>
     <string name="kg_sim_unlock_progress_dialog_message" msgid="8871937892678885545">"Unlocking SIM card…"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 8c465f1..9a07025 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -244,7 +244,7 @@
     <string name="global_actions" product="default" msgid="6410072189971495460">"Opciones del teléfono"</string>
     <string name="global_action_lock" msgid="6949357274257655383">"Bloqueo de pantalla"</string>
     <string name="global_action_power_off" msgid="4404936470711393203">"Apagar"</string>
-    <string name="global_action_power_options" msgid="1185286119330160073">"Encender o apagar"</string>
+    <string name="global_action_power_options" msgid="1185286119330160073">"Apagar o reiniciar"</string>
     <string name="global_action_restart" msgid="4678451019561687074">"Reiniciar"</string>
     <string name="global_action_emergency" msgid="1387617624177105088">"Emergencia"</string>
     <string name="global_action_bug_report" msgid="5127867163044170003">"Informe de errores"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index f51a9a5..e473ab6 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -34,7 +34,7 @@
     <string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
     <string name="mmiError" msgid="2862759606579822246">"કનેક્શન સમસ્યા અથવા અમાન્ય MMI કોડ."</string>
     <string name="mmiFdnError" msgid="3975490266767565852">"ઑપરેશન ફક્ત સ્થિર ડાયલિંગ નંબર્સ પર પ્રતિબંધિત છે."</string>
-    <string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"તમે રોમિંગમાં હોવ તે વખતે તમારા ફોન પરથી કૉલ ફોરવર્ડિગ સેટિંગ્સ બદલી શકતાં નથી."</string>
+    <string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"તમે રોમિંગમાં હો તે વખતે તમારા ફોન પરથી કૉલ ફૉરવર્ડિગ સેટિંગ બદલી શકતાં નથી."</string>
     <string name="serviceEnabled" msgid="7549025003394765639">"સેવા સક્ષમ હતી."</string>
     <string name="serviceEnabledFor" msgid="1463104778656711613">"સેવા આ માટે સક્ષમ હતી:"</string>
     <string name="serviceDisabled" msgid="641878791205871379">"સેવા અક્ષમ કરવામાં આવી છે."</string>
@@ -124,7 +124,7 @@
     <string name="roamingTextSearching" msgid="5323235489657753486">"સેવા શોધી રહ્યું છે"</string>
     <string name="wfcRegErrorTitle" msgid="3193072971584858020">"વાઇ-ફાઇ કૉલિંગ સેટ કરી શકાયું નથી"</string>
   <string-array name="wfcOperatorErrorAlertMessages">
-    <item msgid="468830943567116703">"વાઇ-ફાઇ પરથી કૉલ કરવા અને સંદેશા મોકલવા માટે પહેલાં તમારા કૅરિઅરને આ સેવા સેટ કરવા માટે કહો. પછી સેટિંગ્સમાંથી વાઇ-ફાઇ કૉલિંગ ફરીથી ચાલુ કરો. (ભૂલ કોડ: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
+    <item msgid="468830943567116703">"વાઇ-ફાઇ પરથી કૉલ કરવા અને સંદેશા મોકલવા માટે પહેલાં તમારા કૅરિઅરને આ સેવા સેટ કરવા માટે કહો. પછી સેટિંગમાંથી વાઇ-ફાઇ કૉલિંગ ફરીથી ચાલુ કરો. (ભૂલ કોડ: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
   </string-array>
   <string-array name="wfcOperatorErrorNotificationMessages">
     <item msgid="4795145070505729156">"તમારા કૅરિઅરમાં વાઇ-ફાઇ કૉલિંગ રજિસ્ટર કરવામાં સમસ્યા આવી: <xliff:g id="CODE">%1$s</xliff:g>"</item>
@@ -401,7 +401,7 @@
     <string name="permlab_getPackageSize" msgid="375391550792886641">"ઍપ્લિકેશન સંગ્રહ સ્થાન માપો"</string>
     <string name="permdesc_getPackageSize" msgid="742743530909966782">"એપ્લિકેશનને તેનો કોડ, ડેટા અને કેશ કદ પુનઃપ્રાપ્ત કરવાની મંજૂરી આપે છે."</string>
     <string name="permlab_writeSettings" msgid="8057285063719277394">"સિસ્ટમ સેટિંગમાં ફેરફાર કરો"</string>
-    <string name="permdesc_writeSettings" msgid="8293047411196067188">"એપ્લિકેશનને તમારા સિસ્ટમના સેટિંગ્સ ડેટાને સંશોધિત કરવાની મંજૂરી આપે છે. દુર્ભાવનાપૂર્ણ ઍપ્લિકેશનો તમારા સિસ્ટમની ગોઠવણીને દૂષિત કરી શકે છે."</string>
+    <string name="permdesc_writeSettings" msgid="8293047411196067188">"ઍપને તમારા સિસ્ટમના સેટિંગ ડેટાને સંશોધિત કરવાની મંજૂરી આપે છે. દુર્ભાવનાપૂર્ણ ઍપ તમારા સિસ્ટમની ગોઠવણીને દૂષિત કરી શકે છે."</string>
     <string name="permlab_receiveBootCompleted" msgid="6643339400247325379">"સ્ટાર્ટઅપ પર શરૂ કરો"</string>
     <string name="permdesc_receiveBootCompleted" product="tablet" msgid="5565659082718177484">"એપ્લિકેશનને સિસ્ટમ બૂટ થવાનું સમાપ્ત કરી લે કે તરત જ પોતાની જાતે પ્રારંભ થવાની મંજૂરી આપે છે. આનાથી ટેબ્લેટને પ્રારંભ થવામાં વધુ લાંબો સમય લાગી શકે છે અને એપ્લિકેશનને હંમેશા ચાલુ રહીને ટેબ્લેટને એકંદર ધીમું કરવાની મંજૂરી આપી શકે છે."</string>
     <string name="permdesc_receiveBootCompleted" product="tv" msgid="4900842256047614307">"ઍપને સિસ્ટમ બૂટ થવાનું સમાપ્ત કરી લે કે તરત જ પોતાની જાતે પ્રારંભ થવાની મંજૂરી આપે છે. આનાથી તમારા Android TV ડિવાઇસને શરૂ થવામાં વધુ સમય લાગી શકે છે અને ઍપને હંમેશાં ચાલુ રહીને ડિવાઇસને એકંદર ધીમું કરવાની મંજૂરી આપે છે."</string>
@@ -442,8 +442,8 @@
     <string name="permdesc_accessCoarseLocation" msgid="778521847873199160">"ઍપ ઉપયોગમાં હોય તે વખતે સ્થાન સેવાઓમાંથી આ ઍપ તમારું અંદાજિત સ્થાન મેળવી શકે છે. ઍપ સ્થાન મેળવી શકે તે માટે તમારા ડિવાઇસમાં સ્થાન સેવાઓ ચાલુ કરેલી હોવી જરૂરી છે."</string>
     <string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"બૅકગ્રાઉન્ડમાં સ્થાન ઍક્સેસ કરો"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="8264885066095638105">"આ ઍપ કોઈપણ સમયે સ્થાનને ઍક્સેસ કરી શકે છે, પછી ભલેને આ ઍપ ઉપયોગમાં ન હોય."</string>
-    <string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"તમારી ઑડિઓ સેટિંગ્સ બદલો"</string>
-    <string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"એપ્લિકેશનને વૈશ્વિક ઑડિઓ સેટિંગ્સને સંશોધિત કરવાની મંજૂરી આપે છે, જેમ કે વૉલ્યૂમ અને આઉટપુટ માટે કયા સ્પીકરનો ઉપયોગ કરવો."</string>
+    <string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"તમારા ઑડિયો સેટિંગ બદલો"</string>
+    <string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"ઍપને વૈશ્વિક ઑડિયો સેટિંગમાં ફેરફાર કરવાની મંજૂરી આપે છે, જેમ કે વૉલ્યૂમ અને આઉટપુટ માટે કયા સ્પીકરનો ઉપયોગ કરવો."</string>
     <string name="permlab_recordAudio" msgid="1208457423054219147">"ઑડિઓ રેકોર્ડ કરવાની"</string>
     <string name="permdesc_recordAudio" msgid="5857246765327514062">"આ ઍપ ઉપયોગમાં હોય ત્યારે તે માઇક્રોફોનનો ઉપયોગ કરીને ઑડિયો રેકોર્ડ કરી શકે છે."</string>
     <string name="permlab_recordBackgroundAudio" msgid="5891032812308878254">"બૅકગ્રાઉન્ડમાં ઑડિયો રેકોર્ડ કરો"</string>
@@ -519,7 +519,7 @@
     <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="191079868596433554">"એપ્લિકેશનને ફક્ત તમારા ટેબ્લેટ પર નહીં, પણ મલ્ટિકાસ્ટ સરનામાંનો ઉપયોગ કરીને વાઇ-ફાઇ નેટવર્ક પરના તમામ ઉપકરણોને મોકલાયેલ પૅકેટ્સ પ્રાપ્ત કરવાની મંજૂરી આપે છે. તે બિન-મલ્ટિકાસ્ટ મોડ કરતાં વધુ પાવર વાપરે છે."</string>
     <string name="permdesc_changeWifiMulticastState" product="tv" msgid="1336952358450652595">"ઍપને ફક્ત તમારા Android TV ડિવાઇસ પર નહીં, પણ મલ્ટિકાસ્ટ ઍડ્રેસનો ઉપયોગ કરીને વાઇ-ફાઇ નેટવર્ક પરના તમામ ડિવાઇસને મોકલાયેલા પૅકેટ પ્રાપ્ત કરવાની મંજૂરી આપે છે. તે બિન-મલ્ટિકાસ્ટ મોડ કરતાં વધુ પાવર વાપરે છે."</string>
     <string name="permdesc_changeWifiMulticastState" product="default" msgid="8296627590220222740">"એપ્લિકેશનને ફક્ત તમારા ફોન પર નહીં, પણ મલ્ટિકાસ્ટ સરનામાંનો ઉપયોગ કરીને વાઇ-ફાઇ નેટવર્ક પર તમામ ઉપકરણોને મોકલાયેલ પૅકેટ્સ પ્રાપ્ત કરવાની મંજૂરી આપે છે. તે બિન-મલ્ટિકાસ્ટ મોડ કરતાં વધુ પાવર વાપરે છે."</string>
-    <string name="permlab_bluetoothAdmin" msgid="6490373569441946064">"બ્લૂટૂથ સેટિંગ્સ ઍક્સેસ કરો"</string>
+    <string name="permlab_bluetoothAdmin" msgid="6490373569441946064">"બ્લૂટૂથ સેટિંગ ઍક્સેસ કરો"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="5370837055438574863">"એપ્લિકેશનને સ્થાનિક બ્લૂટૂથ ટેબ્લેટ ગોઠવવાની અને રિમોટ ઉપકરણો શોધવા અને તેમની સાથે જોડી કરવાની મંજૂરી આપે છે."</string>
     <string name="permdesc_bluetoothAdmin" product="tv" msgid="1623992984547014588">"ઍપને તમારા Android TV ડિવાઇસ પર બ્લૂટૂથને ગોઠવવાની અને રિમોટ ડિવાઇસ શોધવા અને તેમની સાથે જોડાણ કરવાની મંજૂરી આપે છે."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="7381341743021234863">"એપ્લિકેશનને સ્થાનિક બ્લૂટૂથ ફોન ગોઠવવાની અને રિમોટ ઉપકરણો શોધવા અને તેમની સાથે જોડી કરવાની મંજૂરી આપે છે."</string>
@@ -662,10 +662,10 @@
   <string-array name="face_error_vendor">
   </string-array>
     <string name="face_icon_content_description" msgid="465030547475916280">"ચહેરા આઇકન"</string>
-    <string name="permlab_readSyncSettings" msgid="6250532864893156277">"સમન્વયન સેટિંગ્સ વાંચો"</string>
-    <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ઍપ્લિકેશનને એકાઉન્ટ માટે સમન્વયન સેટિંગ્સને વાંચવાની મંજૂરી આપે છે. ઉદાહરણ તરીકે, આ એકાઉન્ટ સાથે લોકો ઍપ્લિકેશન સમન્વયિત થઈ છે કે કેમ તે નિર્ધારિત કરી શકે છે."</string>
+    <string name="permlab_readSyncSettings" msgid="6250532864893156277">"સિંક સેટિંગ વાંચો"</string>
+    <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ઍપને એકાઉન્ટ માટે સિંક સેટિંગને વાંચવાની મંજૂરી આપે છે. ઉદાહરણ તરીકે, આ એકાઉન્ટ સાથે લોકો ઍપ સિંક થઈ છે કે કેમ તે નિર્ધારિત કરી શકે છે."</string>
     <string name="permlab_writeSyncSettings" msgid="6583154300780427399">"સમન્વયન ચાલુ અને બંધ ટોગલ કરો"</string>
-    <string name="permdesc_writeSyncSettings" msgid="6029151549667182687">"એપ્લિકેશનને એકાઉન્ટ માટે સમન્વયન સેટિંગ્સ સંશોધિત કરવાની મંજૂરી આપે છે. ઉદાહરણ તરીકે, આનો ઉપયોગ એકાઉન્ટ સાથે લોકો એપ્લિકેશનના સમન્વયનને સક્ષમ કરવા માટે થઈ શકે છે."</string>
+    <string name="permdesc_writeSyncSettings" msgid="6029151549667182687">"ઍપને એકાઉન્ટ માટે સિંક સેટિંગમાં ફેરફાર કરવાની મંજૂરી આપે છે. ઉદાહરણ તરીકે, આનો ઉપયોગ એકાઉન્ટ સાથે લોકો ઍપના સિંકને ચાલુ કરવા માટે થઈ શકે છે."</string>
     <string name="permlab_readSyncStats" msgid="3747407238320105332">"સમન્વયન આંકડા વાંચો"</string>
     <string name="permdesc_readSyncStats" msgid="3867809926567379434">"એપ્લિકેશનને સમન્વયન ઇવેન્ટ્સનો ઇતિહાસ અને કેટલો ડેટા સમન્વયિત થયો છે તે સહિત કોઈ એકાઉન્ટ માટેનાં સમન્વયન આંકડા વાંચવાની મંજૂરી આપે છે."</string>
     <string name="permlab_sdcardRead" msgid="5791467020950064920">"તમારા શેર કરેલા સ્ટોરેજના કન્ટેન્ટને વાંચો"</string>
@@ -815,7 +815,7 @@
     <string name="phoneTypeTtyTdd" msgid="532038552105328779">"TTY TDD"</string>
     <string name="phoneTypeWorkMobile" msgid="7522314392003565121">"કાર્યાલય મોબાઇલ"</string>
     <string name="phoneTypeWorkPager" msgid="3748332310638505234">"કાર્ય પેજર"</string>
-    <string name="phoneTypeAssistant" msgid="757550783842231039">"Assistant"</string>
+    <string name="phoneTypeAssistant" msgid="757550783842231039">"આસિસ્ટંટ"</string>
     <string name="phoneTypeMms" msgid="1799747455131365989">"MMS"</string>
     <string name="eventTypeCustom" msgid="3257367158986466481">"કસ્ટમ"</string>
     <string name="eventTypeBirthday" msgid="7770026752793912283">"જન્મદિવસ"</string>
@@ -1210,7 +1210,7 @@
     <string name="whichImageCaptureApplicationLabel" msgid="6505433734824988277">"છબી કૅપ્ચર કરો"</string>
     <string name="alwaysUse" msgid="3153558199076112903">"આ ક્રિયા માટે ડિફોલ્ટ તરીકે ઉપયોગમાં લો."</string>
     <string name="use_a_different_app" msgid="4987790276170972776">"અલગ એપ્લિકેશનનો ઉપયોગ કરો"</string>
-    <string name="clearDefaultHintMsg" msgid="1325866337702524936">"સિસ્ટમ સેટિંગ્સ &gt; ઍપ્લિકેશનો &gt; ડાઉનલોડ કરેલમાં ડિફોલ્ટ સાફ કરો."</string>
+    <string name="clearDefaultHintMsg" msgid="1325866337702524936">"સિસ્ટમ સેટિંગ &gt; ઍપ &gt; ડાઉનલોડ કરેલામાં ડિફૉલ્ટ સાફ કરો."</string>
     <string name="chooseActivity" msgid="8563390197659779956">"એક ક્રિયા પસંદ કરો"</string>
     <string name="chooseUsbActivity" msgid="2096269989990986612">"USB ઉપકરણ માટે ઍપ્લિકેશન પસંદ કરો"</string>
     <string name="noApplications" msgid="1186909265235544019">"કોઈ ઍપ્લિકેશન આ ક્રિયા કરી શકતી નથી."</string>
@@ -1238,8 +1238,8 @@
     <string name="launch_warning_original" msgid="3332206576800169626">"<xliff:g id="APP_NAME">%1$s</xliff:g> મૂળરૂપે લોંચ થઈ હતી."</string>
     <string name="screen_compat_mode_scale" msgid="8627359598437527726">"સ્કેલ"</string>
     <string name="screen_compat_mode_show" msgid="5080361367584709857">"હંમેશા બતાવો"</string>
-    <string name="screen_compat_mode_hint" msgid="4032272159093750908">"આને સિસ્ટમ સેટિંગ્સ &gt; ઍપ્લિકેશનો &gt; ડાઉનલોડ કરેલમાં ફરીથી સક્ષમ કરો."</string>
-    <string name="unsupported_display_size_message" msgid="7265211375269394699">"<xliff:g id="APP_NAME">%1$s</xliff:g> વર્તમાન પ્રદર્શન કદની સેટિંગનું સમર્થન કરતું નથી અને અનપેક્ષિત રીતે વર્તી શકે છે."</string>
+    <string name="screen_compat_mode_hint" msgid="4032272159093750908">"આને સિસ્ટમ સેટિંગ &gt; ઍપ &gt; ડાઉનલોડ કરેલામાં ફરીથી ચાલુ કરો."</string>
+    <string name="unsupported_display_size_message" msgid="7265211375269394699">"<xliff:g id="APP_NAME">%1$s</xliff:g> વર્તમાન ડિસ્પ્લે કદની સેટિંગને સપોર્ટ કરતું નથી અને અનપેક્ષિત રીતે વર્તી શકે છે."</string>
     <string name="unsupported_display_size_show" msgid="980129850974919375">"હંમેશાં બતાવો"</string>
     <string name="unsupported_compile_sdk_message" msgid="7326293500707890537">"<xliff:g id="APP_NAME">%1$s</xliff:g>ને Android OSના અસંગત વર્ઝન માટે બનાવવામાં આવ્યું હતું અને તે અનપેક્ષિત રીતે કાર્ય કરી શકે છે. ઍપનું અપડેટ કરેલ વર્ઝન ઉપલબ્ધ હોઈ શકે છે."</string>
     <string name="unsupported_compile_sdk_show" msgid="1601210057960312248">"હંમેશાં બતાવો"</string>
@@ -1335,7 +1335,7 @@
     <string name="sms_short_code_confirm_allow" msgid="920477594325526691">"મોકલો"</string>
     <string name="sms_short_code_confirm_deny" msgid="1356917469323768230">"રદ કરો"</string>
     <string name="sms_short_code_remember_choice" msgid="1374526438647744862">"મારી પસંદગી યાદ રાખો"</string>
-    <string name="sms_short_code_remember_undo_instruction" msgid="2620984439143080410">"તમે પછીથી આને સેટિંગ્સ &gt; એપ્લિકેશન્સમાં બદલી શકો છો"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="2620984439143080410">"તમે પછીથી આને સેટિંગ &gt; ઍપમાં બદલી શકો છો"</string>
     <string name="sms_short_code_confirm_always_allow" msgid="2223014893129755950">"હંમેશા મંજૂરી આપો"</string>
     <string name="sms_short_code_confirm_never_allow" msgid="2688828813521652079">"ક્યારેય મંજૂરી આપશો નહીં"</string>
     <string name="sim_removed_title" msgid="5387212933992546283">"સિમ કાર્ડ કાઢી નાખ્યો"</string>
@@ -1502,7 +1502,7 @@
     <string name="vpn_lockdown_connected" msgid="2853127976590658469">"હંમેશા-ચાલુ VPN કનેક્ટ થયું"</string>
     <string name="vpn_lockdown_disconnected" msgid="5573611651300764955">"હંમેશાં-ચાલુ VPN થી ડિસ્કનેક્ટ થયું"</string>
     <string name="vpn_lockdown_error" msgid="4453048646854247947">"હંમેશાં-ચાલુ VPN સાથે કનેક્ટ કરી શકાયું નથી"</string>
-    <string name="vpn_lockdown_config" msgid="8331697329868252169">"નેટવર્ક અથવા VPN સેટિંગ્સ બદલો"</string>
+    <string name="vpn_lockdown_config" msgid="8331697329868252169">"નેટવર્ક અથવા VPN સેટિંગ બદલો"</string>
     <string name="upload_file" msgid="8651942222301634271">"ફાઇલ પસંદ કરો"</string>
     <string name="no_file_chosen" msgid="4146295695162318057">"કોઈ ફાઇલ પસંદ કરેલી નથી"</string>
     <string name="reset" msgid="3865826612628171429">"ફરીથી સેટ કરો"</string>
@@ -1616,7 +1616,7 @@
     <string name="SetupCallDefault" msgid="5581740063237175247">"કૉલ સ્વીકારીએ?"</string>
     <string name="activity_resolver_use_always" msgid="5575222334666843269">"હંમેશાં"</string>
     <string name="activity_resolver_use_once" msgid="948462794469672658">"ફક્ત એક વાર"</string>
-    <string name="activity_resolver_work_profiles_support" msgid="4071345609235361269">"%1$s કાર્ય પ્રોફાઇલનું સમર્થન કરતું નથી"</string>
+    <string name="activity_resolver_work_profiles_support" msgid="4071345609235361269">"%1$s ઑફિસની પ્રોફાઇલને સપોર્ટ કરતું નથી"</string>
     <string name="default_audio_route_name" product="tablet" msgid="367936735632195517">"ટેબ્લેટ"</string>
     <string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
     <string name="default_audio_route_name" product="default" msgid="9213546147739983977">"ફોન"</string>
@@ -2067,7 +2067,7 @@
     <string name="popup_window_default_title" msgid="6907717596694826919">"પૉપઅપ વિંડો"</string>
     <string name="slice_more_content" msgid="3377367737876888459">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
     <string name="shortcut_restored_on_lower_version" msgid="9206301954024286063">"આ ઍપનું વર્ઝન ડાઉનગ્રેડ કરવામાં આવ્યું છે અથવા આ શૉર્ટકટ સાથે સુસંગત નથી"</string>
-    <string name="shortcut_restore_not_supported" msgid="4763198938588468400">"શૉર્ટકટ ફરી મેળવી શકાયો નથી કારણ કે ઍપ બૅકઅપ અને ફરી મેળવવાનું સમર્થન કરતી નથી"</string>
+    <string name="shortcut_restore_not_supported" msgid="4763198938588468400">"શૉર્ટકટ ફરી મેળવી શકાયો નથી કારણ કે ઍપ બૅકઅપ અને ફરી મેળવવાને સપોર્ટ કરતી નથી"</string>
     <string name="shortcut_restore_signature_mismatch" msgid="579345304221605479">"શૉર્ટકટ ફરી મેળવી શકાયો નથી કારણ કે ઍપમાં છે તે સહી મેળ ખાતી નથી"</string>
     <string name="shortcut_restore_unknown_issue" msgid="2478146134395982154">"શૉર્ટકટ પાછો મેળવી શકાયો નથી"</string>
     <string name="shortcut_disabled_reason_unknown" msgid="753074793553599166">"શૉર્ટકટને બંધ કરવામાં આવ્યો છે"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 1b224c3..44172ea 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -815,7 +815,7 @@
     <string name="phoneTypeTtyTdd" msgid="532038552105328779">"TTY TDD"</string>
     <string name="phoneTypeWorkMobile" msgid="7522314392003565121">"ഓഫീസ് മൊബൈല്‍"</string>
     <string name="phoneTypeWorkPager" msgid="3748332310638505234">"ഔദ്യോഗിക പേജര്‍‌"</string>
-    <string name="phoneTypeAssistant" msgid="757550783842231039">"Assistant"</string>
+    <string name="phoneTypeAssistant" msgid="757550783842231039">"അസിസ്റ്റന്‍റ്"</string>
     <string name="phoneTypeMms" msgid="1799747455131365989">"MMS"</string>
     <string name="eventTypeCustom" msgid="3257367158986466481">"ഇഷ്‌ടാനുസൃതം"</string>
     <string name="eventTypeBirthday" msgid="7770026752793912283">"ജന്മദിനം"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 86a9c3f..2648296 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -306,7 +306,7 @@
     <string name="permgroupdesc_contacts" msgid="9163927941244182567">"ਆਪਣੇ ਸੰਪਰਕਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ"</string>
     <string name="permgrouplab_location" msgid="1858277002233964394">"ਟਿਕਾਣਾ"</string>
     <string name="permgroupdesc_location" msgid="1995955142118450685">"ਇਸ ਡੀਵਾਈਸ ਦੇ ਨਿਰਧਾਰਤ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚੋ"</string>
-    <string name="permgrouplab_calendar" msgid="6426860926123033230">"ਕੈਲੰਡਰ"</string>
+    <string name="permgrouplab_calendar" msgid="6426860926123033230">"Calendar"</string>
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"ਤੁਹਾਡੇ ਕੈਲੰਡਰ ਤੱਕ ਪਹੁੰਚ ਕਰਨ"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS ਸੁਨੇਹੇ ਭੇਜੋ ਅਤੇ ਦੇਖੋ"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 93f2d742..d632e0c 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -434,7 +434,7 @@
     <string name="permdesc_bodySensors" product="default" msgid="2365357960407973997">"Aplikaciji omogoča dostop do podatkov tipal, ki nadzirajo vaše fizično stanje, med drugim vaš srčni utrip."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Branje dogodkov v koledarjih in podrobnosti koledarjev"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Ta aplikacija lahko prebere vse dogodke v koledarju, ki so shranjeni v tabličnem računalniku, ter shrani podatke koledarja ali jih deli z drugimi."</string>
-    <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Ta aplikacija lahko prebere vse dogodke v koledarju, ki so shranjeni v napravi Android TV, ter shrani podatke koledarja ali jih da v skupno rabo z drugimi."</string>
+    <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Ta aplikacija lahko prebere vse dogodke v koledarju, ki so shranjeni v napravi Android TV, ter shrani podatke koledarja ali jih deli z drugimi."</string>
     <string name="permdesc_readCalendar" product="default" msgid="9118823807655829957">"Ta aplikacija lahko prebere vse dogodke v koledarju, ki so shranjeni v telefonu, ter shrani podatke koledarja ali jih deli z drugimi."</string>
     <string name="permlab_writeCalendar" msgid="6422137308329578076">"dodajanje ali spreminjanje dogodkov v koledarju in pošiljanje e-pošte gostom brez vedenja lastnikov"</string>
     <string name="permdesc_writeCalendar" product="tablet" msgid="8722230940717092850">"Ta aplikacija lahko dodaja, odstranjuje in spreminja dogodke v koledarju, ki so shranjeni v tabličnem računalniku. Ta aplikacija lahko pošilja sporočila, ki bodo morda videti, kot da prihajajo od lastnikov koledarjev, ali spreminja dogodke brez vednosti lastnikov."</string>
@@ -932,7 +932,7 @@
     <string name="lockscreen_forgot_pattern_button_text" msgid="8362442730606839031">"Ali ste pozabili vzorec?"</string>
     <string name="lockscreen_glogin_forgot_pattern" msgid="9218940117797602518">"Odklepanje računa"</string>
     <string name="lockscreen_glogin_too_many_attempts" msgid="3775904917743034195">"Preveč poskusov vzorca"</string>
-    <string name="lockscreen_glogin_instructions" msgid="4695162942525531700">"Če želite odkleniti telefon, se prijavite z Google Računom."</string>
+    <string name="lockscreen_glogin_instructions" msgid="4695162942525531700">"Če želite odkleniti telefon, se prijavite z računom Google."</string>
     <string name="lockscreen_glogin_username_hint" msgid="6916101478673157045">"Uporabniško ime (e-pošta)"</string>
     <string name="lockscreen_glogin_password_hint" msgid="3031027901286812848">"Geslo"</string>
     <string name="lockscreen_glogin_submit_button" msgid="3590556636347843733">"Prijava"</string>
@@ -1237,8 +1237,8 @@
     <string name="whichEditApplicationNamed" msgid="8096494987978521514">"Urejanje z aplikacijo %1$s"</string>
     <string name="whichEditApplicationLabel" msgid="1463288652070140285">"Urejanje"</string>
     <string name="whichSendApplication" msgid="4143847974460792029">"Deljenje z drugimi"</string>
-    <string name="whichSendApplicationNamed" msgid="4470386782693183461">"Skupna raba z aplikacijo %1$s"</string>
-    <string name="whichSendApplicationLabel" msgid="7467813004769188515">"Skupna raba"</string>
+    <string name="whichSendApplicationNamed" msgid="4470386782693183461">"Deljenje z aplikacijo %1$s"</string>
+    <string name="whichSendApplicationLabel" msgid="7467813004769188515">"Deljenje"</string>
     <string name="whichSendToApplication" msgid="77101541959464018">"Pošiljanje z aplikacijo"</string>
     <string name="whichSendToApplicationNamed" msgid="3385686512014670003">"Pošiljanje z aplikacijo %1$s"</string>
     <string name="whichSendToApplicationLabel" msgid="3543240188816513303">"Pošiljanje"</string>
@@ -1400,14 +1400,14 @@
     <string name="perm_costs_money" msgid="749054595022779685">"to je lahko plačljivo"</string>
     <string name="dlg_ok" msgid="5103447663504839312">"V redu"</string>
     <string name="usb_charging_notification_title" msgid="1674124518282666955">"Polnjenje naprave prek USB-ja"</string>
-    <string name="usb_supplying_notification_title" msgid="5378546632408101811">"Polnjenje akumulatorja v povezani napravi prek USB-ja"</string>
+    <string name="usb_supplying_notification_title" msgid="5378546632408101811">"Polnjenje baterije v povezani napravi prek USB-ja"</string>
     <string name="usb_mtp_notification_title" msgid="1065989144124499810">"Vklopljen je prenos datotek prek USB-ja"</string>
     <string name="usb_ptp_notification_title" msgid="5043437571863443281">"Vklopljen je način PTP prek USB-ja"</string>
     <string name="usb_tether_notification_title" msgid="8828527870612663771">"Vklopljen je internet prek USB-ja"</string>
     <string name="usb_midi_notification_title" msgid="7404506788950595557">"Vklopljen je način MIDI prek USB-ja"</string>
     <string name="usb_accessory_notification_title" msgid="1385394660861956980">"Dodatek USB je priključen"</string>
     <string name="usb_notification_message" msgid="4715163067192110676">"Dotaknite se za več možnosti."</string>
-    <string name="usb_power_notification_message" msgid="7284765627437897702">"Polnjenje akumulatorja v povezani napravi. Dotaknite se za več možnosti."</string>
+    <string name="usb_power_notification_message" msgid="7284765627437897702">"Polnjenje baterije v povezani napravi. Dotaknite se za več možnosti."</string>
     <string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Zaznana je analogna dodatna zvočna oprema"</string>
     <string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"Priključena naprava ni združljiva s tem telefonom. Dotaknite se za več informacij."</string>
     <string name="adb_active_notification_title" msgid="408390247354560331">"Iskanje napak prek USB-ja je povezano"</string>
@@ -1427,8 +1427,8 @@
     <string name="taking_remote_bugreport_notification_title" msgid="1582531382166919850">"Zajemanje poročila o napakah …"</string>
     <string name="share_remote_bugreport_notification_title" msgid="6708897723753334999">"Želite poslati poročilo o napakah?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="3077385149217638550">"Pošiljanje poročila o napakah …"</string>
-    <string name="share_remote_bugreport_notification_message_finished" msgid="7325635795739260135">"Skrbnik je zahteval poročilo o napakah za pomoč pri odpravljanju napak v tej napravi. Aplikacije in podatki bodo morda dani v skupno rabo."</string>
-    <string name="share_remote_bugreport_action" msgid="7630880678785123682">"SKUPNA RABA"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="7325635795739260135">"Skrbnik je zahteval poročilo o napakah za pomoč pri odpravljanju napak v tej napravi. Aplikacije in podatki bodo morda deljeni."</string>
+    <string name="share_remote_bugreport_action" msgid="7630880678785123682">"DELJENJE"</string>
     <string name="decline_remote_bugreport_action" msgid="4040894777519784346">"NE SPREJMEM"</string>
     <string name="select_input_method" msgid="3971267998568587025">"Izberite način vnosa"</string>
     <string name="show_ime" msgid="6406112007347443383">"Ohrani na zaslonu, dokler je aktivna fizična tipkovnica"</string>
@@ -1616,7 +1616,7 @@
     <string name="action_menu_overflow_description" msgid="4579536843510088170">"Več možnosti"</string>
     <string name="action_bar_home_description_format" msgid="5087107531331621803">"%1$s, %2$s"</string>
     <string name="action_bar_home_subtitle_description_format" msgid="4346835454749569826">"%1$s, %2$s, %3$s"</string>
-    <string name="storage_internal" msgid="8490227947584914460">"Notranja shramba v skupni rabi"</string>
+    <string name="storage_internal" msgid="8490227947584914460">"Notranja deljena shramba"</string>
     <string name="storage_sd_card" msgid="3404740277075331881">"Kartica SD"</string>
     <string name="storage_sd_card_label" msgid="7526153141147470509">"Kartica SD <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb_drive" msgid="448030813201444573">"Pogon USB"</string>
@@ -1709,7 +1709,7 @@
     <string name="kg_invalid_puk" msgid="4809502818518963344">"Vnovič vnesite pravilno kodo PUK. Večkratni poskusi bodo trajno onemogočili kartico SIM."</string>
     <string name="kg_invalid_confirm_pin_hint" product="default" msgid="4705368340409816254">"Kodi PIN se ne ujemata"</string>
     <string name="kg_login_too_many_attempts" msgid="699292728290654121">"Preveč poskusov vzorca"</string>
-    <string name="kg_login_instructions" msgid="3619844310339066827">"Če želite odkleniti napravo, se prijavite z Google Računom."</string>
+    <string name="kg_login_instructions" msgid="3619844310339066827">"Če želite odkleniti napravo, se prijavite z računom Google."</string>
     <string name="kg_login_username_hint" msgid="1765453775467133251">"Uporabniško ime (e-pošta)"</string>
     <string name="kg_login_password_hint" msgid="3330530727273164402">"Geslo"</string>
     <string name="kg_login_submit_button" msgid="893611277617096870">"Prijava"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 25e2820..239c9f8 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -1197,7 +1197,7 @@
     <string name="whichEditApplicationNamed" msgid="8096494987978521514">"Redakto me %1$s"</string>
     <string name="whichEditApplicationLabel" msgid="1463288652070140285">"Redakto"</string>
     <string name="whichSendApplication" msgid="4143847974460792029">"Ndaj"</string>
-    <string name="whichSendApplicationNamed" msgid="4470386782693183461">"Shpërnda publikisht me %1$s"</string>
+    <string name="whichSendApplicationNamed" msgid="4470386782693183461">"Shpërndaj me %1$s"</string>
     <string name="whichSendApplicationLabel" msgid="7467813004769188515">"Ndaj"</string>
     <string name="whichSendToApplication" msgid="77101541959464018">"Dërgo me"</string>
     <string name="whichSendToApplicationNamed" msgid="3385686512014670003">"Dërgo me %1$s"</string>
@@ -1565,8 +1565,8 @@
     <string name="keyboardview_keycode_enter" msgid="168054869339091055">"Enter"</string>
     <string name="activitychooserview_choose_application" msgid="3500574466367891463">"Zgjidh një aplikacion"</string>
     <string name="activitychooserview_choose_application_error" msgid="6937782107559241734">"Nuk mundi ta hapte <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
-    <string name="shareactionprovider_share_with" msgid="2753089758467748982">"Shpërnda publikisht me"</string>
-    <string name="shareactionprovider_share_with_application" msgid="4902832247173666973">"Shpërnda me <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+    <string name="shareactionprovider_share_with" msgid="2753089758467748982">"Shpërndaj me"</string>
+    <string name="shareactionprovider_share_with_application" msgid="4902832247173666973">"Shpërndaj me <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="982510275422590757">"Dorezë me rrëshqitje. Preke dhe mbaje të shtypur."</string>
     <string name="description_target_unlock_tablet" msgid="7431571180065859551">"Rrëshqit për të shkyçur."</string>
     <string name="action_bar_home_description" msgid="1501655419158631974">"Orientohu për në shtëpi"</string>
@@ -1610,7 +1610,7 @@
     <string name="sha1_fingerprint" msgid="2339915142825390774">"Gjurma e gishtit SHA-1:"</string>
     <string name="activity_chooser_view_see_all" msgid="3917045206812726099">"Shikoji të gjitha"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="8880731437191978314">"Zgjidh aktivitetin"</string>
-    <string name="share_action_provider_share_with" msgid="1904096863622941880">"Shpërnda publikisht me"</string>
+    <string name="share_action_provider_share_with" msgid="1904096863622941880">"Shpërndaj me"</string>
     <string name="sending" msgid="206925243621664438">"Po dërgon…"</string>
     <string name="launchBrowserDefault" msgid="6328349989932924119">"Të hapet shfletuesi?"</string>
     <string name="SetupCallDefault" msgid="5581740063237175247">"Dëshiron ta pranosh telefonatën?"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index cb0b420..940ee56 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -572,7 +572,7 @@
     <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Autentiseringen avbröts"</string>
     <string name="biometric_not_recognized" msgid="5106687642694635888">"Identifierades inte"</string>
     <string name="biometric_error_canceled" msgid="8266582404844179778">"Autentiseringen avbröts"</string>
-    <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Pinkod, grafiskt lösenord eller lösenord har inte angetts"</string>
+    <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Pinkod, mönster eller lösenord har inte angetts"</string>
     <string name="biometric_error_generic" msgid="6784371929985434439">"Ett fel uppstod vid autentiseringen"</string>
     <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Använd skärmlåset"</string>
     <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Fortsätt med hjälp av ditt skärmlås"</string>
@@ -881,7 +881,7 @@
     <string name="lockscreen_screen_locked" msgid="7364905540516041817">"Skärmen har låsts."</string>
     <string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Tryck på Menu för att låsa upp eller ringa nödsamtal."</string>
     <string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Tryck på Menu för att låsa upp."</string>
-    <string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Rita grafiskt lösenord för att låsa upp"</string>
+    <string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Rita mönster för att låsa upp"</string>
     <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Nödsamtal"</string>
     <string name="lockscreen_return_to_call" msgid="3156883574692006382">"Tillbaka till samtal"</string>
     <string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Korrekt!"</string>
@@ -925,7 +925,7 @@
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6807200118164539589">"Försök igen om <xliff:g id="NUMBER">%d</xliff:g> sekunder."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="8362442730606839031">"Glömt ditt grafiska lösenord?"</string>
     <string name="lockscreen_glogin_forgot_pattern" msgid="9218940117797602518">"Lås upp konto"</string>
-    <string name="lockscreen_glogin_too_many_attempts" msgid="3775904917743034195">"För många försök med grafiskt lösenord"</string>
+    <string name="lockscreen_glogin_too_many_attempts" msgid="3775904917743034195">"För många försök med mönster"</string>
     <string name="lockscreen_glogin_instructions" msgid="4695162942525531700">"Logga in med ditt Google-konto om du vill låsa upp."</string>
     <string name="lockscreen_glogin_username_hint" msgid="6916101478673157045">"Användarnamn (e-post)"</string>
     <string name="lockscreen_glogin_password_hint" msgid="3031027901286812848">"Lösenord"</string>
@@ -936,12 +936,12 @@
     <string name="lockscreen_unlock_label" msgid="4648257878373307582">"Lås upp"</string>
     <string name="lockscreen_sound_on_label" msgid="1660281470535492430">"Ljud på"</string>
     <string name="lockscreen_sound_off_label" msgid="2331496559245450053">"Ljud av"</string>
-    <string name="lockscreen_access_pattern_start" msgid="3778502525702613399">"Skriver grafiskt lösenord"</string>
-    <string name="lockscreen_access_pattern_cleared" msgid="7493849102641167049">"Grafiskt lösenord har tagits bort"</string>
+    <string name="lockscreen_access_pattern_start" msgid="3778502525702613399">"Ritar mönster"</string>
+    <string name="lockscreen_access_pattern_cleared" msgid="7493849102641167049">"Mönster har tagits bort"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6746676335293144163">"En cell har lagts till"</string>
     <string name="lockscreen_access_pattern_cell_added_verbose" msgid="2931364927622563465">"Cell <xliff:g id="CELL_INDEX">%1$s</xliff:g> har lagts till"</string>
-    <string name="lockscreen_access_pattern_detected" msgid="3931150554035194012">"Grafiskt lösenord har slutförts"</string>
-    <string name="lockscreen_access_pattern_area" msgid="1288780416685002841">"Fält för grafiskt lösenord."</string>
+    <string name="lockscreen_access_pattern_detected" msgid="3931150554035194012">"Mönster har slutförts"</string>
+    <string name="lockscreen_access_pattern_area" msgid="1288780416685002841">"Fält för mönster."</string>
     <string name="keyguard_accessibility_widget_changed" msgid="7298011259508200234">"%1$s. Widget %2$d av %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8245795023551343672">"Lägg till en widget."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="544239307077644480">"Tom"</string>
@@ -957,13 +957,13 @@
     <string name="keyguard_accessibility_widget_deleted" msgid="1509738950119878705">"Widgeten <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> har tagits bort."</string>
     <string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"Expandera upplåsningsytan."</string>
     <string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"Lås upp genom att dra."</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Lås upp med grafiskt lösenord."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Lås upp med mönster."</string>
     <string name="keyguard_accessibility_face_unlock" msgid="4533832120787386728">"Ansiktslås."</string>
     <string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"Lås upp med PIN-kod."</string>
     <string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"Lås upp med SIM-kortets pinkod."</string>
     <string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"Lås upp med SIM-kortets PUK-kod."</string>
     <string name="keyguard_accessibility_password_unlock" msgid="6130186108581153265">"Lås upp med lösenord."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="1419570880512350689">"Fält för grafiskt lösenord."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="1419570880512350689">"Fält för mönster."</string>
     <string name="keyguard_accessibility_slide_area" msgid="4331399051142520176">"Fält med dragreglage."</string>
     <string name="password_keyboard_label_symbol_key" msgid="2716255580853511949">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="5294837425652726684">"ABC"</string>
@@ -1644,7 +1644,7 @@
     <string name="display_manager_overlay_display_title" msgid="1480158037150469170">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
     <string name="display_manager_overlay_display_secure_suffix" msgid="2810034719482834679">", säker"</string>
     <string name="kg_forgot_pattern_button_text" msgid="406145459223122537">"Har du glömt ditt grafiska lösenord?"</string>
-    <string name="kg_wrong_pattern" msgid="1342812634464179931">"Fel grafiskt lösenord"</string>
+    <string name="kg_wrong_pattern" msgid="1342812634464179931">"Fel mönster"</string>
     <string name="kg_wrong_password" msgid="2384677900494439426">"Fel lösenord"</string>
     <string name="kg_wrong_pin" msgid="3680925703673166482">"Fel PIN-kod"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="236717428673283568">
@@ -1664,7 +1664,7 @@
     <string name="kg_invalid_sim_puk_hint" msgid="2539364558870734339">"PUK-koden ska vara åtta siffror."</string>
     <string name="kg_invalid_puk" msgid="4809502818518963344">"Ange rätt PUK-kod igen. Om försöken upprepas inaktiveras SIM-kortet permanent."</string>
     <string name="kg_invalid_confirm_pin_hint" product="default" msgid="4705368340409816254">"PIN-koderna stämmer inte överens"</string>
-    <string name="kg_login_too_many_attempts" msgid="699292728290654121">"För många försök med grafiskt lösenord"</string>
+    <string name="kg_login_too_many_attempts" msgid="699292728290654121">"För många försök med mönster"</string>
     <string name="kg_login_instructions" msgid="3619844310339066827">"Logga in med ditt Google-konto om du vill låsa upp."</string>
     <string name="kg_login_username_hint" msgid="1765453775467133251">"Användarnamn (e-post)"</string>
     <string name="kg_login_password_hint" msgid="3330530727273164402">"Lösenord"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index d68c088..89a7749 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -815,7 +815,7 @@
     <string name="phoneTypeTtyTdd" msgid="532038552105328779">"TTY TDD"</string>
     <string name="phoneTypeWorkMobile" msgid="7522314392003565121">"కార్యాలయ మొబైల్"</string>
     <string name="phoneTypeWorkPager" msgid="3748332310638505234">"కార్యాలయ పేజర్"</string>
-    <string name="phoneTypeAssistant" msgid="757550783842231039">"Assistant"</string>
+    <string name="phoneTypeAssistant" msgid="757550783842231039">"అసిస్టెంట్"</string>
     <string name="phoneTypeMms" msgid="1799747455131365989">"MMS"</string>
     <string name="eventTypeCustom" msgid="3257367158986466481">"అనుకూలం"</string>
     <string name="eventTypeBirthday" msgid="7770026752793912283">"పుట్టినరోజు"</string>
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index 6f17ea9..fb820cb 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -286,6 +286,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 194242735)
     public void testHandleActivityConfigurationChanged_EnsureUpdatesProcessedInOrder()
             throws Exception {
         final TestActivity activity = mActivityTestRule.launchActivity(new Intent());
diff --git a/core/tests/coretests/src/android/app/appsearch/AppSearchSessionUnitTest.java b/core/tests/coretests/src/android/app/appsearch/AppSearchSessionUnitTest.java
index d51004c..07e4333 100644
--- a/core/tests/coretests/src/android/app/appsearch/AppSearchSessionUnitTest.java
+++ b/core/tests/coretests/src/android/app/appsearch/AppSearchSessionUnitTest.java
@@ -16,6 +16,8 @@
 
 package android.app.appsearch;
 
+import static android.app.appsearch.SearchSpec.TERM_MATCH_PREFIX;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.testng.Assert.expectThrows;
@@ -30,6 +32,8 @@
 import org.junit.Before;
 import org.junit.Test;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Objects;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
@@ -100,4 +104,127 @@
                 .isEqualTo(AppSearchResult.RESULT_INTERNAL_ERROR);
         assertThat(appSearchException.getMessage()).startsWith("NullPointerException");
     }
+
+    @Test
+    public void testGetEmptyNextPage() throws Exception {
+        // Set the schema.
+        CompletableFuture<AppSearchResult<SetSchemaResponse>> schemaFuture =
+                new CompletableFuture<>();
+        mSearchSession.setSchema(
+                new SetSchemaRequest.Builder()
+                        .addSchemas(new AppSearchSchema.Builder("schema1").build())
+                        .setForceOverride(true).build(),
+                mExecutor, mExecutor, schemaFuture::complete);
+        schemaFuture.get().getResultValue();
+
+        // Create a document and index it.
+        GenericDocument document1 = new GenericDocument.Builder<>("namespace", "id1",
+                "schema1").build();
+        CompletableFuture<AppSearchBatchResult<String, Void>> putDocumentsFuture =
+                new CompletableFuture<>();
+        mSearchSession.put(
+                new PutDocumentsRequest.Builder().addGenericDocuments(document1).build(),
+                mExecutor, new BatchResultCallback<String, Void>() {
+                    @Override
+                    public void onResult(AppSearchBatchResult<String, Void> result) {
+                        putDocumentsFuture.complete(result);
+                    }
+
+                    @Override
+                    public void onSystemError(Throwable throwable) {
+                        putDocumentsFuture.completeExceptionally(throwable);
+                    }
+                });
+        putDocumentsFuture.get();
+
+        // Search and get the first page.
+        SearchSpec searchSpec = new SearchSpec.Builder()
+                .setTermMatch(TERM_MATCH_PREFIX)
+                .setResultCountPerPage(1)
+                .build();
+        SearchResults searchResults = mSearchSession.search("", searchSpec);
+
+        CompletableFuture<AppSearchResult<List<SearchResult>>> getNextPageFuture =
+                new CompletableFuture<>();
+        searchResults.getNextPage(mExecutor, getNextPageFuture::complete);
+        List<SearchResult> results = getNextPageFuture.get().getResultValue();
+        assertThat(results).hasSize(1);
+        assertThat(results.get(0).getGenericDocument()).isEqualTo(document1);
+
+        // We get all documents, and it shouldn't fail if we keep calling getNextPage().
+        getNextPageFuture = new CompletableFuture<>();
+        searchResults.getNextPage(mExecutor, getNextPageFuture::complete);
+        results = getNextPageFuture.get().getResultValue();
+        assertThat(results).isEmpty();
+    }
+
+    @Test
+    public void testGetEmptyNextPage_multiPages() throws Exception {
+        // Set the schema.
+        CompletableFuture<AppSearchResult<SetSchemaResponse>> schemaFuture =
+                new CompletableFuture<>();
+        mSearchSession.setSchema(
+                new SetSchemaRequest.Builder()
+                        .addSchemas(new AppSearchSchema.Builder("schema1").build())
+                        .setForceOverride(true).build(),
+                mExecutor, mExecutor, schemaFuture::complete);
+        schemaFuture.get().getResultValue();
+
+        // Create a document and insert 3 package1 documents
+        GenericDocument document1 = new GenericDocument.Builder<>("namespace", "id1",
+                "schema1").build();
+        GenericDocument document2 = new GenericDocument.Builder<>("namespace", "id2",
+                "schema1").build();
+        GenericDocument document3 = new GenericDocument.Builder<>("namespace", "id3",
+                "schema1").build();
+        CompletableFuture<AppSearchBatchResult<String, Void>> putDocumentsFuture =
+                new CompletableFuture<>();
+        mSearchSession.put(
+                new PutDocumentsRequest.Builder()
+                        .addGenericDocuments(document1, document2, document3).build(),
+                mExecutor, new BatchResultCallback<String, Void>() {
+                    @Override
+                    public void onResult(AppSearchBatchResult<String, Void> result) {
+                        putDocumentsFuture.complete(result);
+                    }
+
+                    @Override
+                    public void onSystemError(Throwable throwable) {
+                        putDocumentsFuture.completeExceptionally(throwable);
+                    }
+                });
+        putDocumentsFuture.get();
+
+        // Search for only 2 result per page
+        SearchSpec searchSpec = new SearchSpec.Builder()
+                .setTermMatch(TERM_MATCH_PREFIX)
+                .setResultCountPerPage(2)
+                .build();
+        SearchResults searchResults = mSearchSession.search("", searchSpec);
+
+        // Get the first page, it contains 2 results.
+        List<GenericDocument> outDocs = new ArrayList<>();
+        CompletableFuture<AppSearchResult<List<SearchResult>>> getNextPageFuture =
+                new CompletableFuture<>();
+        searchResults.getNextPage(mExecutor, getNextPageFuture::complete);
+        List<SearchResult> results = getNextPageFuture.get().getResultValue();
+        assertThat(results).hasSize(2);
+        outDocs.add(results.get(0).getGenericDocument());
+        outDocs.add(results.get(1).getGenericDocument());
+
+        // Get the second page, it contains only 1 result.
+        getNextPageFuture = new CompletableFuture<>();
+        searchResults.getNextPage(mExecutor, getNextPageFuture::complete);
+        results = getNextPageFuture.get().getResultValue();
+        assertThat(results).hasSize(1);
+        outDocs.add(results.get(0).getGenericDocument());
+
+        assertThat(outDocs).containsExactly(document1, document2, document3);
+
+        // We get all documents, and it shouldn't fail if we keep calling getNextPage().
+        getNextPageFuture = new CompletableFuture<>();
+        searchResults.getNextPage(mExecutor, getNextPageFuture::complete);
+        results = getNextPageFuture.get().getResultValue();
+        assertThat(results).isEmpty();
+    }
 }
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/GenericDocumentTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/GenericDocumentTest.java
index 6884f13d..3d820ac 100644
--- a/core/tests/coretests/src/android/app/appsearch/external/app/GenericDocumentTest.java
+++ b/core/tests/coretests/src/android/app/appsearch/external/app/GenericDocumentTest.java
@@ -62,4 +62,18 @@
         assertThat(outDoc.getPropertyDocument("propDocument").getPropertyBytesArray("propBytes"))
                 .isEqualTo(new byte[][] {{3, 4}});
     }
+
+    @Test
+    public void testPutLargeDocument_exceedLimit() throws Exception {
+        // Create a String property that has a very large property.
+        char[] chars = new char[10_000_000];
+        String property = new StringBuilder().append(chars).append("the end.").toString();
+
+        GenericDocument doc =
+                new GenericDocument.Builder<>("namespace", "id1", "schema1")
+                        .setPropertyString("propString", property)
+                        .build();
+
+        assertThat(doc.getPropertyString("propString")).isEqualTo(property);
+    }
 }
diff --git a/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java b/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java
index 7dea82d..69eb13f 100644
--- a/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java
+++ b/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java
@@ -22,12 +22,6 @@
 import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeNotNull;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
 
 import android.os.PerformanceHintManager.Session;
 
@@ -120,92 +114,9 @@
     }
 
     @Test
-    public void testRateLimitWithDurationFastEnough() throws Exception {
-        FakeClock fakeClock = new FakeClock();
-        Session s = new Session(mIHintSessionMock, fakeClock, RATE_1000, TARGET_166);
-
-        reset(mIHintSessionMock);
-        fakeClock.setNow(0);
-        s.updateTargetWorkDuration(TARGET_166);
-
-        s.reportActualWorkDuration(TARGET_166 - 1);
-        s.reportActualWorkDuration(TARGET_166);
-        // we should not see update as the rate should be 10X for over-perform case.
-        verify(mIHintSessionMock, never()).reportActualWorkDuration(any(), any());
-        fakeClock.incrementClock(10 * RATE_1000);
-        s.reportActualWorkDuration(TARGET_166);
-        verify(mIHintSessionMock, never()).reportActualWorkDuration(any(), any());
-        fakeClock.incrementClock(1);
-        s.reportActualWorkDuration(TARGET_166);
-        // we should see update after rate limit
-        verify(mIHintSessionMock, times(1)).reportActualWorkDuration(
-                eq(new long[] {TARGET_166 - 1, TARGET_166, TARGET_166, TARGET_166}),
-                eq(new long[] {0, 0, 10 * RATE_1000, 10 * RATE_1000 + 1}));
-
-        reset(mIHintSessionMock);
-        s.reportActualWorkDuration(TARGET_166);
-        s.reportActualWorkDuration(TARGET_166 - 1);
-        s.reportActualWorkDuration(TARGET_166 - 2);
-        // we should not see update as the rate should be 10X for over-perform case.
-        verify(mIHintSessionMock, never()).reportActualWorkDuration(any(), any());
-        fakeClock.incrementClock(10 * RATE_1000 + 1);
-        s.reportActualWorkDuration(TARGET_166);
-        s.reportActualWorkDuration(TARGET_166 - 1);
-        // we should see update now
-        verify(mIHintSessionMock, times(1)).reportActualWorkDuration(
-                eq(new long[] {TARGET_166, TARGET_166 - 1, TARGET_166 - 2, TARGET_166}),
-                eq(new long[] {10 * RATE_1000 + 1, 10 * RATE_1000 + 1, 10 * RATE_1000 + 1,
-                    (10 * RATE_1000 + 1) * 2}));
-    }
-
-    @Test
-    public void testRateLimitWithDurationTooSlow() throws Exception {
-        FakeClock fakeClock = new FakeClock();
-        Session s = new Session(mIHintSessionMock, fakeClock, RATE_1000, TARGET_166);
-
-        reset(mIHintSessionMock);
-        fakeClock.setNow(0);
-        s.updateTargetWorkDuration(TARGET_166);
-
-        verify(mIHintSessionMock, times(1)).updateTargetWorkDuration(eq(TARGET_166));
-        // shouldn't update before rate limit
-        s.reportActualWorkDuration(TARGET_166 + 1);
-        verify(mIHintSessionMock, never()).reportActualWorkDuration(any(), any());
-
-        // shouldn't update when the time is exactly at rate limit
-        fakeClock.incrementClock(RATE_1000);
-        s.reportActualWorkDuration(TARGET_166 + 1);
-        verify(mIHintSessionMock, never()).reportActualWorkDuration(any(), any());
-
-        // should be ready for sending hint
-        fakeClock.incrementClock(1);
-        s.reportActualWorkDuration(TARGET_166 + 1);
-        verify(mIHintSessionMock, times(1)).reportActualWorkDuration(
-                eq(new long[] {TARGET_166 + 1, TARGET_166 + 1, TARGET_166 + 1}),
-                eq(new long[] {0 , RATE_1000, RATE_1000 + 1}));
-    }
-
-    @Test
     public void testCloseHintSession() {
         Session s = createSession();
         assumeNotNull(s);
         s.close();
     }
-
-    private static class FakeClock implements PerformanceHintManager.NanoClock {
-        private long mCurrentTime = 0L;
-
-        @Override
-        public long nanos() {
-            return mCurrentTime;
-        }
-
-        public void setNow(long nanos) {
-            mCurrentTime = nanos;
-        }
-
-        public void incrementClock(long nanos) {
-            mCurrentTime += nanos;
-        }
-    }
 }
diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java
index fe04f0d..c3b1cd74 100644
--- a/graphics/java/android/graphics/HardwareRenderer.java
+++ b/graphics/java/android/graphics/HardwareRenderer.java
@@ -28,7 +28,6 @@
 import android.hardware.display.DisplayManager;
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
-import android.os.PerformanceHintManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.util.Log;
@@ -856,36 +855,6 @@
         callback.onPictureCaptured(picture);
     }
 
-    /** called by native */
-    static PerformanceHintManager.Session createHintSession(int[] tids) {
-        PerformanceHintManager performanceHintManager =
-                ProcessInitializer.sInstance.getHintManager();
-        if (performanceHintManager == null) {
-            return null;
-        }
-        // Native code will always set a target duration before reporting actual durations.
-        // So this is just a placeholder value that's never used.
-        long targetDurationNanos = 16666667;
-        return performanceHintManager.createHintSession(tids, targetDurationNanos);
-    }
-
-    /** called by native */
-    static void updateTargetWorkDuration(PerformanceHintManager.Session session,
-            long targetDurationNanos) {
-        session.updateTargetWorkDuration(targetDurationNanos);
-    }
-
-    /** called by native */
-    static void reportActualWorkDuration(PerformanceHintManager.Session session,
-            long actualDurationNanos) {
-        session.reportActualWorkDuration(actualDurationNanos);
-    }
-
-    /** called by native */
-    static void closeHintSession(PerformanceHintManager.Session session) {
-        session.close();
-    }
-
    /**
      * Interface used to receive callbacks when Webview requests a surface control.
      *
@@ -1152,7 +1121,6 @@
         private boolean mIsolated = false;
         private Context mContext;
         private String mPackageName;
-        private PerformanceHintManager mPerformanceHintManager;
         private IGraphicsStats mGraphicsStatsService;
         private IGraphicsStatsCallback mGraphicsStatsCallback = new IGraphicsStatsCallback.Stub() {
             @Override
@@ -1164,10 +1132,6 @@
         private ProcessInitializer() {
         }
 
-        synchronized PerformanceHintManager getHintManager() {
-            return mPerformanceHintManager;
-        }
-
         synchronized void setPackageName(String name) {
             if (mInitialized) return;
             mPackageName = name;
@@ -1218,10 +1182,6 @@
 
             initDisplayInfo();
 
-            // HintManager and HintSession are designed to be accessible from isoalted processes
-            // so not checking for isolated process here.
-            initHintSession();
-
             nSetIsHighEndGfx(ActivityManager.isHighEndGfx());
             // Defensively clear out the context in case we were passed a context that can leak
             // if we live longer than it, e.g. an activity context.
@@ -1265,11 +1225,6 @@
             mDisplayInitialized = true;
         }
 
-        private void initHintSession() {
-            if (mContext == null) return;
-            mPerformanceHintManager = mContext.getSystemService(PerformanceHintManager.class);
-        }
-
         private void rotateBuffer() {
             nRotateProcessStatsBuffer();
             requestBuffer();
diff --git a/libs/WindowManager/Shell/res/color/one_handed_tutorial_background_color.xml b/libs/WindowManager/Shell/res/color/one_handed_tutorial_background_color.xml
new file mode 100644
index 0000000..4f56e0f
--- /dev/null
+++ b/libs/WindowManager/Shell/res/color/one_handed_tutorial_background_color.xml
@@ -0,0 +1,21 @@
+<?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.
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+          xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+    <item android:color="?androidprv:attr/colorSurfaceVariant"/>
+</selector>
diff --git a/libs/WindowManager/Shell/res/drawable-hdpi/one_handed_tutorial.png b/libs/WindowManager/Shell/res/drawable-hdpi/one_handed_tutorial.png
deleted file mode 100644
index 6c1f1cf..0000000
--- a/libs/WindowManager/Shell/res/drawable-hdpi/one_handed_tutorial.png
+++ /dev/null
Binary files differ
diff --git a/libs/WindowManager/Shell/res/drawable/one_handed_tutorial_icon.xml b/libs/WindowManager/Shell/res/drawable/one_handed_tutorial_icon.xml
new file mode 100644
index 0000000..b32f34e
--- /dev/null
+++ b/libs/WindowManager/Shell/res/drawable/one_handed_tutorial_icon.xml
@@ -0,0 +1,14 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="60dp"
+    android:viewportWidth="32"
+    android:viewportHeight="60">
+  <path
+      android:pathData="M1.9703,30.5041C1.9703,28.295 3.7612,26.5042 5.9703,26.5042H25.5551C27.7642,26.5042 29.5551,28.295 29.5551,30.5042V54.0296C29.5551,56.2387 27.7642,58.0296 25.5551,58.0296H5.9703C3.7612,58.0296 1.9703,56.2387 1.9703,54.0296V30.5041Z"
+      android:fillColor="#000000"
+      android:fillAlpha="0.16"/>
+  <path
+      android:pathData="M25.5254,2H6C3.7909,2 2,3.7909 2,6V54C2,56.2091 3.7909,58 6,58H25.5254C27.7346,58 29.5254,56.2091 29.5254,54V6C29.5254,3.7909 27.7346,2 25.5254,2ZM6,0C2.6863,0 0,2.6863 0,6V54C0,57.3137 2.6863,60 6,60H25.5254C28.8391,60 31.5254,57.3137 31.5254,54V6C31.5254,2.6863 28.8391,0 25.5254,0H6ZM12.2034,47.2336L12.8307,47.861L15.3178,45.3783V52.1277H16.2076V45.3783L18.6903,47.8654L19.322,47.2336L15.7627,43.6743L12.2034,47.2336ZM19.7034,55.0742H11.822V56.552H19.7034V55.0742Z"
+      android:fillColor="#000000"
+      android:fillType="evenOdd"/>
+</vector>
diff --git a/libs/WindowManager/Shell/res/layout/one_handed_tutorial.xml b/libs/WindowManager/Shell/res/layout/one_handed_tutorial.xml
index 0190aad..d29ed8b 100644
--- a/libs/WindowManager/Shell/res/layout/one_handed_tutorial.xml
+++ b/libs/WindowManager/Shell/res/layout/one_handed_tutorial.xml
@@ -31,7 +31,7 @@
         android:layout_marginTop="6dp"
         android:layout_marginBottom="0dp"
         android:gravity="center_horizontal"
-        android:src="@drawable/one_handed_tutorial"
+        android:src="@drawable/one_handed_tutorial_icon"
         android:scaleType="centerInside" />
 
     <TextView
@@ -45,7 +45,6 @@
         android:fontFamily="google-sans-medium"
         android:text="@string/one_handed_tutorial_title"
         android:textSize="16sp"
-        android:textStyle="bold"
         android:textColor="@android:color/white"/>
 
     <TextView
@@ -54,8 +53,8 @@
         android:layout_height="wrap_content"
         android:layout_marginTop="6dp"
         android:layout_marginBottom="0dp"
-        android:layout_marginStart="46dp"
-        android:layout_marginEnd="46dp"
+        android:layout_marginStart="60dp"
+        android:layout_marginEnd="60dp"
         android:gravity="center_horizontal"
         android:fontFamily="roboto-regular"
         android:text="@string/one_handed_tutorial_description"
diff --git a/libs/WindowManager/Shell/res/values-ky/strings.xml b/libs/WindowManager/Shell/res/values-ky/strings.xml
index c16041d..8056d15 100644
--- a/libs/WindowManager/Shell/res/values-ky/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ky/strings.xml
@@ -46,7 +46,7 @@
     <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Үстүнкү экранды 30%"</string>
     <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Ылдыйкы экранды толук экран режимине өткөрүү"</string>
     <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Бир кол режимин колдонуу"</string>
-    <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Чыгуу үчүн экранды ылдый жагынан өйдө көздөй сүрүңүз же колдонмонун өйдө жагын басыңыз"</string>
+    <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Чыгуу үчүн экранды ылдый жагынан өйдө сүрүңүз же колдонмонун өйдө жагын басыңыз"</string>
     <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Бир кол режимин баштоо"</string>
     <string name="accessibility_action_stop_one_handed" msgid="1369940261782179442">"Бир кол режиминен чыгуу"</string>
     <string name="bubbles_settings_button_description" msgid="1301286017420516912">"<xliff:g id="APP_NAME">%1$s</xliff:g> калкып чыкма билдирмелер жөндөөлөрү"</string>
diff --git a/libs/WindowManager/Shell/res/values/config.xml b/libs/WindowManager/Shell/res/values/config.xml
index 8cea869..d0e4f7a 100644
--- a/libs/WindowManager/Shell/res/values/config.xml
+++ b/libs/WindowManager/Shell/res/values/config.xml
@@ -36,6 +36,9 @@
     <!-- Allow PIP to resize via dragging the corner of PiP. -->
     <bool name="config_pipEnableDragCornerResize">false</bool>
 
+    <!-- PiP minimum size, which is a % based off the shorter side of display width and height -->
+    <fraction name="config_pipShortestEdgePercent">40%</fraction>
+
     <!-- Animation duration when using long press on recents to dock -->
     <integer name="long_press_dock_anim_duration">250</integer>
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index 92e455c..c0df06f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -45,6 +45,7 @@
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.SurfaceControl;
+import android.view.SurfaceHolder;
 import android.view.SurfaceView;
 import android.view.View;
 import android.view.ViewGroup;
@@ -205,6 +206,7 @@
      * between bubble activities without needing both to be alive at the same time.
      */
     private SurfaceView mAnimatingOutSurfaceView;
+    private boolean mAnimatingOutSurfaceReady;
 
     /** Container for the animating-out SurfaceView. */
     private FrameLayout mAnimatingOutSurfaceContainer;
@@ -811,6 +813,20 @@
         mAnimatingOutSurfaceView.setZOrderOnTop(true);
         mAnimatingOutSurfaceView.setCornerRadius(mCornerRadius);
         mAnimatingOutSurfaceView.setLayoutParams(new ViewGroup.LayoutParams(0, 0));
+        mAnimatingOutSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
+            @Override
+            public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {}
+
+            @Override
+            public void surfaceCreated(SurfaceHolder surfaceHolder) {
+                mAnimatingOutSurfaceReady = true;
+            }
+
+            @Override
+            public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
+                mAnimatingOutSurfaceReady = false;
+            }
+        });
         mAnimatingOutSurfaceContainer.addView(mAnimatingOutSurfaceView);
 
         mAnimatingOutSurfaceContainer.setPadding(
@@ -2653,7 +2669,7 @@
                 return;
             }
 
-            if (!mIsExpanded) {
+            if (!mIsExpanded || !mAnimatingOutSurfaceReady) {
                 onComplete.accept(false);
                 return;
             }
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 481b948..3ccb9e7 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
@@ -20,7 +20,6 @@
 import android.graphics.Color;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
-import android.util.Log;
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 import android.window.DisplayAreaAppearedInfo;
@@ -30,7 +29,6 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
-import androidx.core.content.ContextCompat;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.wm.shell.R;
@@ -48,14 +46,17 @@
 public class OneHandedBackgroundPanelOrganizer extends DisplayAreaOrganizer
         implements OneHandedTransitionCallback {
     private static final String TAG = "OneHandedBackgroundPanelOrganizer";
+    private static final int THEME_COLOR_OFFSET = 10;
 
+    private final Context mContext;
     private final Object mLock = new Object();
     private final SurfaceSession mSurfaceSession = new SurfaceSession();
-    private final float[] mDefaultColor;
     private final Executor mMainExecutor;
     private final OneHandedSurfaceTransactionHelper.SurfaceControlTransactionFactory
             mSurfaceControlTransactionFactory;
 
+    private float[] mDefaultColor;
+
     /**
      * The background to distinguish the boundary of translated windows and empty region when
      * one handed mode triggered.
@@ -88,15 +89,14 @@
     public OneHandedBackgroundPanelOrganizer(Context context, DisplayLayout displayLayout,
             Executor executor) {
         super(executor);
+        mContext = context;
         // 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());
         }
-        final int defaultColor = ContextCompat.getColor(context, R.color.GM2_grey_800);
-        mDefaultColor = new float[]{Color.red(defaultColor) / 255.0f,
-                Color.green(defaultColor) / 255.0f, Color.blue(defaultColor) / 255.0f};
+        updateThemeColors();
         mMainExecutor = executor;
         mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new;
     }
@@ -170,7 +170,6 @@
             }
 
             if (getBackgroundSurface() == null) {
-                Log.w(TAG, "mBackgroundSurface is null !");
                 return;
             }
 
@@ -201,6 +200,30 @@
         }
     }
 
+    /**
+     * onConfigurationChanged events for updating tutorial text.
+     */
+    public void onConfigurationChanged() {
+        synchronized (mLock) {
+            if (mBackgroundSurface == null) {
+                getBackgroundSurface();
+            } else {
+                removeBackgroundPanelLayer();
+            }
+            updateThemeColors();
+            showBackgroundPanelLayer();
+        }
+    }
+
+    private void updateThemeColors() {
+        synchronized (mLock) {
+            final int themeColor = mContext.getColor(R.color.one_handed_tutorial_background_color);
+            mDefaultColor = new float[]{(Color.red(themeColor) - THEME_COLOR_OFFSET) / 255.0f,
+                    (Color.green(themeColor) - THEME_COLOR_OFFSET) / 255.0f,
+                    (Color.blue(themeColor) - THEME_COLOR_OFFSET) / 255.0f};
+        }
+    }
+
     void dump(@NonNull PrintWriter pw) {
         final String innerPrefix = "  ";
         pw.println(TAG);
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 2038cff..09cde38 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
@@ -658,12 +658,13 @@
     }
 
     private void onConfigChanged(Configuration newConfig) {
-        if (mTutorialHandler == null) {
+        if (mTutorialHandler == null || mBackgroundPanelOrganizer == null) {
             return;
         }
         if (!mIsOneHandedEnabled || newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
             return;
         }
+        mBackgroundPanelOrganizer.onConfigurationChanged();
         mTutorialHandler.onConfigurationChanged();
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java
index d0206a4..97e04b5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java
@@ -25,8 +25,11 @@
 import static com.android.wm.shell.onehanded.OneHandedState.STATE_EXITING;
 import static com.android.wm.shell.onehanded.OneHandedState.STATE_NONE;
 
+import android.animation.ValueAnimator;
 import android.annotation.Nullable;
 import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.TypedArray;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.os.SystemProperties;
@@ -35,9 +38,13 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
+import android.view.animation.LinearInterpolator;
 import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
 
 import androidx.annotation.NonNull;
+import androidx.appcompat.view.ContextThemeWrapper;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.wm.shell.R;
@@ -53,11 +60,14 @@
 public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
         OneHandedState.OnStateChangedListener {
     private static final String TAG = "OneHandedTutorialHandler";
-    private static final String ONE_HANDED_MODE_OFFSET_PERCENTAGE =
-            "persist.debug.one_handed_offset_percentage";
+    private static final String OFFSET_PERCENTAGE = "persist.debug.one_handed_offset_percentage";
+    private static final String TRANSLATE_ANIMATION_DURATION =
+            "persist.debug.one_handed_translate_animation_duration";
+    private static final float START_TRANSITION_FRACTION = 0.7f;
 
     private final float mTutorialHeightRatio;
     private final WindowManager mWindowManager;
+    private final OneHandedAnimationCallback mAnimationCallback;
 
     private @OneHandedState.State int mCurrentState;
     private int mTutorialAreaHeight;
@@ -67,7 +77,9 @@
     private @Nullable View mTutorialView;
     private @Nullable ViewGroup mTargetViewContainer;
 
-    private final OneHandedAnimationCallback mAnimationCallback;
+    private float mAlphaTransitionStart;
+    private ValueAnimator mAlphaAnimator;
+    private int mAlphaAnimationDurationMs;
 
     public OneHandedTutorialHandler(Context context, WindowManager windowManager) {
         mContext = context;
@@ -75,15 +87,35 @@
         final float offsetPercentageConfig = context.getResources().getFraction(
                 R.fraction.config_one_handed_offset, 1, 1);
         final int sysPropPercentageConfig = SystemProperties.getInt(
-                ONE_HANDED_MODE_OFFSET_PERCENTAGE, Math.round(offsetPercentageConfig * 100.0f));
+                OFFSET_PERCENTAGE, Math.round(offsetPercentageConfig * 100.0f));
         mTutorialHeightRatio = sysPropPercentageConfig / 100.0f;
+        final int animationDuration = context.getResources().getInteger(
+                R.integer.config_one_handed_translate_animation_duration);
+        mAlphaAnimationDurationMs = SystemProperties.getInt(TRANSLATE_ANIMATION_DURATION,
+                animationDuration);
         mAnimationCallback = new OneHandedAnimationCallback() {
             @Override
+            public void onOneHandedAnimationCancel(
+                    OneHandedAnimationController.OneHandedTransitionAnimator animator) {
+                if (mAlphaAnimator != null) {
+                    mAlphaAnimator.cancel();
+                }
+            }
+
+            @Override
             public void onAnimationUpdate(float xPos, float yPos) {
                 if (!isAttached()) {
                     return;
                 }
-                mTargetViewContainer.setTranslationY(yPos - mTutorialAreaHeight);
+                if (yPos < mAlphaTransitionStart) {
+                    checkTransitionEnd();
+                    return;
+                }
+                if (mAlphaAnimator == null || mAlphaAnimator.isStarted()
+                        || mAlphaAnimator.isRunning()) {
+                    return;
+                }
+                mAlphaAnimator.start();
             }
         };
     }
@@ -94,12 +126,16 @@
         switch (newState) {
             case STATE_ENTERING:
                 createViewAndAttachToWindow(mContext);
+                updateThemeColor();
+                setupAlphaTransition(true /* isEntering */);
                 break;
             case STATE_ACTIVE:
-            case STATE_EXITING:
-                // no - op
+                checkTransitionEnd();
+                setupAlphaTransition(false /* isEntering */);
                 break;
+            case STATE_EXITING:
             case STATE_NONE:
+                checkTransitionEnd();
                 removeTutorialFromWindowManager();
                 break;
             default:
@@ -119,6 +155,7 @@
             mDisplayBounds = new Rect(0, 0, displayLayout.height(), displayLayout.width());
         }
         mTutorialAreaHeight = Math.round(mDisplayBounds.height() * mTutorialHeightRatio);
+        mAlphaTransitionStart = mTutorialAreaHeight * START_TRANSITION_FRACTION;
     }
 
     @VisibleForTesting
@@ -129,6 +166,7 @@
         mTutorialView = LayoutInflater.from(context).inflate(R.layout.one_handed_tutorial, null);
         mTargetViewContainer = new FrameLayout(context);
         mTargetViewContainer.setClipChildren(false);
+        mTargetViewContainer.setAlpha(mCurrentState == STATE_ACTIVE ? 1.0f : 0.0f);
         mTargetViewContainer.addView(mTutorialView);
         mTargetViewContainer.setLayerType(LAYER_TYPE_HARDWARE, null);
 
@@ -192,6 +230,52 @@
         removeTutorialFromWindowManager();
         if (mCurrentState == STATE_ENTERING || mCurrentState == STATE_ACTIVE) {
             createViewAndAttachToWindow(mContext);
+            updateThemeColor();
+            checkTransitionEnd();
+        }
+    }
+
+    private void updateThemeColor() {
+        if (mTutorialView == null) {
+            return;
+        }
+
+        final Context themedContext = new ContextThemeWrapper(mTutorialView.getContext(),
+                com.android.internal.R.style.Theme_DeviceDefault_DayNight);
+        final int textColorPrimary;
+        final int themedTextColorSecondary;
+        TypedArray ta = themedContext.obtainStyledAttributes(new int[]{
+                com.android.internal.R.attr.textColorPrimary,
+                com.android.internal.R.attr.textColorSecondary});
+        textColorPrimary = ta.getColor(0, 0);
+        themedTextColorSecondary = ta.getColor(1, 0);
+        ta.recycle();
+
+        final ImageView iconView = mTutorialView.findViewById(R.id.one_handed_tutorial_image);
+        iconView.setImageTintList(ColorStateList.valueOf(textColorPrimary));
+
+        final TextView tutorialTitle = mTutorialView.findViewById(R.id.one_handed_tutorial_title);
+        final TextView tutorialDesc = mTutorialView.findViewById(
+                R.id.one_handed_tutorial_description);
+        tutorialTitle.setTextColor(textColorPrimary);
+        tutorialDesc.setTextColor(themedTextColorSecondary);
+    }
+
+    private void setupAlphaTransition(boolean isEntering) {
+        final float start = isEntering ? 0.0f : 1.0f;
+        final float end = isEntering ? 1.0f : 0.0f;
+        mAlphaAnimator = ValueAnimator.ofFloat(start, end);
+        mAlphaAnimator.setInterpolator(new LinearInterpolator());
+        mAlphaAnimator.setDuration(mAlphaAnimationDurationMs);
+        mAlphaAnimator.addUpdateListener(
+                animator -> mTargetViewContainer.setAlpha((float) animator.getAnimatedValue()));
+    }
+
+    private void checkTransitionEnd() {
+        if (mAlphaAnimator != null && mAlphaAnimator.isRunning()) {
+            mAlphaAnimator.end();
+            mAlphaAnimator.removeAllUpdateListeners();
+            mAlphaAnimator = null;
         }
     }
 
@@ -206,5 +290,9 @@
         pw.println(mDisplayBounds);
         pw.print(innerPrefix + "mTutorialAreaHeight=");
         pw.println(mTutorialAreaHeight);
+        pw.print(innerPrefix + "mAlphaTransitionStart=");
+        pw.println(mAlphaTransitionStart);
+        pw.print(innerPrefix + "mAlphaAnimationDurationMs=");
+        pw.println(mAlphaAnimationDurationMs);
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
index c46b559..200af74 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
@@ -26,10 +26,14 @@
 import android.animation.ValueAnimator;
 import android.annotation.IntDef;
 import android.app.TaskInfo;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Color;
 import android.graphics.Rect;
 import android.view.Choreographer;
 import android.view.Surface;
 import android.view.SurfaceControl;
+import android.view.SurfaceSession;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
@@ -253,6 +257,7 @@
                 mSurfaceControlTransactionFactory;
         private PipSurfaceTransactionHelper mSurfaceTransactionHelper;
         private @TransitionDirection int mTransitionDirection;
+        protected SurfaceControl mContentOverlay;
 
         private PipTransitionAnimator(TaskInfo taskInfo, SurfaceControl leash,
                 @AnimationType int animationType, Rect destinationBounds, T baseValue, T startValue,
@@ -331,6 +336,53 @@
             return false;
         }
 
+        SurfaceControl getContentOverlay() {
+            return mContentOverlay;
+        }
+
+        PipTransitionAnimator<T> setUseContentOverlay(Context context) {
+            final SurfaceControl.Transaction tx = newSurfaceControlTransaction();
+            if (mContentOverlay != null) {
+                // remove existing content overlay if there is any.
+                tx.remove(mContentOverlay);
+                tx.apply();
+            }
+            mContentOverlay = new SurfaceControl.Builder(new SurfaceSession())
+                    .setCallsite("PipAnimation")
+                    .setName("PipContentOverlay")
+                    .setColorLayer()
+                    .build();
+            tx.show(mContentOverlay);
+            tx.setLayer(mContentOverlay, Integer.MAX_VALUE);
+            tx.setColor(mContentOverlay, getContentOverlayColor(context));
+            tx.setAlpha(mContentOverlay, 0f);
+            tx.reparent(mContentOverlay, mLeash);
+            tx.apply();
+            return this;
+        }
+
+        private float[] getContentOverlayColor(Context context) {
+            final TypedArray ta = context.obtainStyledAttributes(new int[] {
+                    android.R.attr.colorBackground });
+            try {
+                int colorAccent = ta.getColor(0, 0);
+                return new float[] {
+                        Color.red(colorAccent) / 255f,
+                        Color.green(colorAccent) / 255f,
+                        Color.blue(colorAccent) / 255f };
+            } finally {
+                ta.recycle();
+            }
+        }
+
+        /**
+         * Clears the {@link #mContentOverlay}, this should be done after the content overlay is
+         * faded out, such as in {@link PipTaskOrganizer#fadeOutAndRemoveOverlay}
+         */
+        void clearContentOverlay() {
+            mContentOverlay = null;
+        }
+
         @VisibleForTesting
         @TransitionDirection public int getTransitionDirection() {
             return mTransitionDirection;
@@ -517,6 +569,9 @@
                     final Rect base = getBaseValue();
                     final Rect start = getStartValue();
                     final Rect end = getEndValue();
+                    if (mContentOverlay != null) {
+                        tx.setAlpha(mContentOverlay, fraction < 0.5f ? 0 : (fraction - 0.5f) * 2);
+                    }
                     if (rotatedEndRect != null) {
                         // Animate the bounds in a different orientation. It only happens when
                         // switching between PiP and fullscreen.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index f367cd6..f2bad6c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -107,6 +107,13 @@
      */
     private static final int ONE_SHOT_ALPHA_ANIMATION_TIMEOUT_MS = 1000;
 
+    /**
+     * The fixed start delay in ms when fading out the content overlay from bounds animation.
+     * This is to overcome the flicker caused by configuration change when rotating from landscape
+     * to portrait PiP in button navigation mode.
+     */
+    private static final int CONTENT_OVERLAY_FADE_OUT_DELAY_MS = 500;
+
     // Not a complete set of states but serves what we want right now.
     private enum State {
         UNDEFINED(0),
@@ -176,6 +183,10 @@
             final int direction = animator.getTransitionDirection();
             final int animationType = animator.getAnimationType();
             final Rect destinationBounds = animator.getDestinationBounds();
+            if (isInPipDirection(direction) && animator.getContentOverlay() != null) {
+                fadeOutAndRemoveOverlay(animator.getContentOverlay(),
+                        animator::clearContentOverlay, true /* withStartDelay*/);
+            }
             if (mWaitForFixedRotation && animationType == ANIM_TYPE_BOUNDS
                     && direction == TRANSITION_DIRECTION_TO_PIP) {
                 // Notify the display to continue the deferred orientation change.
@@ -199,17 +210,17 @@
                 finishResize(tx, destinationBounds, direction, animationType);
                 sendOnPipTransitionFinished(direction);
             }
-            if (direction == TRANSITION_DIRECTION_TO_PIP) {
-                // TODO (b//169221267): Add jank listener for transactions without buffer updates.
-                //InteractionJankMonitor.getInstance().end(
-                //        InteractionJankMonitor.CUJ_LAUNCHER_APP_CLOSE_TO_PIP);
-            }
         }
 
         @Override
         public void onPipAnimationCancel(TaskInfo taskInfo,
                 PipAnimationController.PipTransitionAnimator animator) {
-            sendOnPipTransitionCancelled(animator.getTransitionDirection());
+            final int direction = animator.getTransitionDirection();
+            if (isInPipDirection(direction) && animator.getContentOverlay() != null) {
+                fadeOutAndRemoveOverlay(animator.getContentOverlay(),
+                        animator::clearContentOverlay, true /* withStartDelay */);
+            }
+            sendOnPipTransitionCancelled(direction);
         }
     };
 
@@ -640,7 +651,8 @@
 
             // Remove the swipe to home overlay
             if (swipeToHomeOverlay != null) {
-                fadeOutAndRemoveOverlay(swipeToHomeOverlay);
+                fadeOutAndRemoveOverlay(swipeToHomeOverlay,
+                        null /* callback */, false /* withStartDelay */);
             }
         }, tx);
         mInSwipePipToHomeTransition = false;
@@ -723,9 +735,12 @@
             mOnDisplayIdChangeCallback.accept(Display.DEFAULT_DISPLAY);
         }
 
-        final PipAnimationController.PipTransitionAnimator animator =
+        final PipAnimationController.PipTransitionAnimator<?> animator =
                 mPipAnimationController.getCurrentAnimator();
         if (animator != null) {
+            if (animator.getContentOverlay() != null) {
+                removeContentOverlay(animator.getContentOverlay(), animator::clearContentOverlay);
+            }
             animator.removeAllUpdateListeners();
             animator.removeAllListeners();
             animator.cancel();
@@ -1196,7 +1211,8 @@
                             snapshotDest);
 
                     // Start animation to fade out the snapshot.
-                    fadeOutAndRemoveOverlay(snapshotSurface);
+                    fadeOutAndRemoveOverlay(snapshotSurface,
+                            null /* callback */, false /* withStartDelay */);
                 });
             } else {
                 applyFinishBoundsResize(wct, direction);
@@ -1287,15 +1303,20 @@
         animator.setTransitionDirection(direction)
                 .setPipAnimationCallback(mPipAnimationCallback)
                 .setPipTransactionHandler(mPipTransactionHandler)
-                .setDuration(durationMs)
-                .start();
-        if (rotationDelta != Surface.ROTATION_0 && direction == TRANSITION_DIRECTION_TO_PIP) {
+                .setDuration(durationMs);
+        if (isInPipDirection(direction)) {
+            // Similar to auto-enter-pip transition, we use content overlay when there is no
+            // source rect hint to enter PiP use bounds animation.
+            if (sourceHintRect == null) animator.setUseContentOverlay(mContext);
             // The destination bounds are used for the end rect of animation and the final bounds
             // after animation finishes. So after the animation is started, the destination bounds
             // can be updated to new rotation (computeRotatedBounds has changed the DisplayLayout
             // without affecting the animation.
-            animator.setDestinationBounds(mPipBoundsAlgorithm.getEntryDestinationBounds());
+            if (rotationDelta != Surface.ROTATION_0) {
+                animator.setDestinationBounds(mPipBoundsAlgorithm.getEntryDestinationBounds());
+            }
         }
+        animator.start();
         return animator;
     }
 
@@ -1308,6 +1329,14 @@
             outDestinationBounds.set(mPipBoundsAlgorithm.getEntryDestinationBounds());
             // Transform the destination bounds to current display coordinates.
             rotateBounds(outDestinationBounds, displayBounds, mNextRotation, mCurrentRotation);
+            // When entering PiP (from button navigation mode), adjust the source rect hint by
+            // display cutout if applicable.
+            if (sourceHintRect != null && mTaskInfo.displayCutoutInsets != null) {
+                if (rotationDelta == Surface.ROTATION_270) {
+                    sourceHintRect.offset(mTaskInfo.displayCutoutInsets.left,
+                            mTaskInfo.displayCutoutInsets.top);
+                }
+            }
         } else if (direction == TRANSITION_DIRECTION_LEAVE_PIP) {
             final Rect rotatedDestinationBounds = new Rect(outDestinationBounds);
             rotateBounds(rotatedDestinationBounds, mPipBoundsState.getDisplayBounds(),
@@ -1346,7 +1375,8 @@
     /**
      * Fades out and removes an overlay surface.
      */
-    private void fadeOutAndRemoveOverlay(SurfaceControl surface) {
+    private void fadeOutAndRemoveOverlay(SurfaceControl surface, Runnable callback,
+            boolean withStartDelay) {
         if (surface == null) {
             return;
         }
@@ -1354,24 +1384,43 @@
         final ValueAnimator animator = ValueAnimator.ofFloat(1.0f, 0.0f);
         animator.setDuration(mCrossFadeAnimationDuration);
         animator.addUpdateListener(animation -> {
-            final float alpha = (float) animation.getAnimatedValue();
-            final SurfaceControl.Transaction transaction =
-                    mSurfaceControlTransactionFactory.getTransaction();
-            transaction.setAlpha(surface, alpha);
-            transaction.apply();
+            if (mState == State.UNDEFINED) {
+                // Could happen if onTaskVanished happens during the animation since we may have
+                // set a start delay on this animation.
+                Log.d(TAG, "Task vanished, skip fadeOutAndRemoveOverlay");
+                animation.removeAllListeners();
+                animation.removeAllUpdateListeners();
+                animation.cancel();
+            } else {
+                final float alpha = (float) animation.getAnimatedValue();
+                final SurfaceControl.Transaction transaction =
+                        mSurfaceControlTransactionFactory.getTransaction();
+                transaction.setAlpha(surface, alpha);
+                transaction.apply();
+            }
         });
         animator.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
-                final SurfaceControl.Transaction tx =
-                        mSurfaceControlTransactionFactory.getTransaction();
-                tx.remove(surface);
-                tx.apply();
+                removeContentOverlay(surface, callback);
             }
         });
+        animator.setStartDelay(withStartDelay ? CONTENT_OVERLAY_FADE_OUT_DELAY_MS : 0);
         animator.start();
     }
 
+    private void removeContentOverlay(SurfaceControl surface, Runnable callback) {
+        if (mState == State.UNDEFINED) {
+            // Avoid double removal, which is fatal.
+            return;
+        }
+        final SurfaceControl.Transaction tx =
+                mSurfaceControlTransactionFactory.getTransaction();
+        tx.remove(surface);
+        tx.apply();
+        if (callback != null) callback.run();
+    }
+
     /**
      * Dumps internal states.
      */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
index 0bcd1a3..7867f93 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
@@ -63,7 +63,6 @@
  * the PIP.
  */
 public class PipTouchHandler {
-    @VisibleForTesting static final float MINIMUM_SIZE_PERCENT = 0.4f;
 
     private static final String TAG = "PipTouchHandler";
     private static final float DEFAULT_STASH_VELOCITY_THRESHOLD = 18000.f;
@@ -115,6 +114,7 @@
     private float mSavedSnapFraction = -1f;
     private boolean mSendingHoverAccessibilityEvents;
     private boolean mMovementWithinDismiss;
+    private float mMinimumSizePercent;
 
     // Touch state
     private final PipTouchState mTouchState;
@@ -252,6 +252,7 @@
         mExpandedShortestEdgeSize = res.getDimensionPixelSize(
                 R.dimen.pip_expanded_shortest_edge_size);
         mImeOffset = res.getDimensionPixelSize(R.dimen.pip_ime_offset);
+        mMinimumSizePercent = res.getFraction(R.fraction.config_pipShortestEdgePercent, 1, 1);
         mPipDismissTargetHandler.updateMagneticTargetSize();
     }
 
@@ -481,12 +482,12 @@
                 + (mPipBoundsState.getDisplayBounds().height() - insetBounds.bottom);
         final int minWidth, minHeight, maxWidth, maxHeight;
         if (aspectRatio > 1f) {
-            minWidth = (int) Math.min(normalBounds.width(), shorterLength * MINIMUM_SIZE_PERCENT);
+            minWidth = (int) Math.min(normalBounds.width(), shorterLength * mMinimumSizePercent);
             minHeight = (int) (minWidth / aspectRatio);
             maxWidth = (int) Math.max(normalBounds.width(), shorterLength - totalHorizontalPadding);
             maxHeight = (int) (maxWidth / aspectRatio);
         } else {
-            minHeight = (int) Math.min(normalBounds.height(), shorterLength * MINIMUM_SIZE_PERCENT);
+            minHeight = (int) Math.min(normalBounds.height(), shorterLength * mMinimumSizePercent);
             minWidth = (int) (minHeight * aspectRatio);
             maxHeight = (int) Math.max(normalBounds.height(), shorterLength - totalVerticalPadding);
             maxWidth = (int) (maxHeight * aspectRatio);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
index 107a3f8..dff5577 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
@@ -23,6 +23,7 @@
 import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
 
 import android.annotation.ColorInt;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.app.ActivityThread;
 import android.content.BroadcastReceiver;
@@ -37,6 +38,7 @@
 import android.graphics.Color;
 import android.graphics.Rect;
 import android.graphics.drawable.AdaptiveIconDrawable;
+import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.LayerDrawable;
@@ -57,11 +59,13 @@
 import com.android.internal.graphics.palette.Palette;
 import com.android.internal.graphics.palette.Quantizer;
 import com.android.internal.graphics.palette.VariationalKMeansQuantizer;
+import com.android.launcher3.icons.BaseIconFactory;
 import com.android.launcher3.icons.IconProvider;
 import com.android.wm.shell.common.TransactionPool;
 
 import java.util.List;
 import java.util.function.Consumer;
+import java.util.function.IntPredicate;
 import java.util.function.IntSupplier;
 import java.util.function.Supplier;
 import java.util.function.UnaryOperator;
@@ -130,7 +134,6 @@
      * @param splashScreenViewConsumer Receiving the SplashScreenView object, which will also be
      *                                 executed on splash screen thread. Note that the view can be
      *                                 null if failed.
-     * @param bgColorConsumer Receiving the background color once it's estimated complete.
      */
     void createContentView(Context context, @StartingWindowType int suggestType, ActivityInfo info,
             int taskId, Consumer<SplashScreenView> splashScreenViewConsumer) {
@@ -207,9 +210,9 @@
     }
 
     private static int estimateWindowBGColor(Drawable themeBGDrawable) {
-        final DrawableColorTester themeBGTester =
-                new DrawableColorTester(themeBGDrawable, true /* filterTransparent */);
-        if (themeBGTester.nonTransparentRatio() == 0) {
+        final DrawableColorTester themeBGTester = new DrawableColorTester(
+                themeBGDrawable, DrawableColorTester.TRANSPARENT_FILTER /* filterType */);
+        if (themeBGTester.passFilterRatio() == 0) {
             // the window background is transparent, unable to draw
             Slog.w(TAG, "Window background is transparent, fill background with black color");
             return getSystemBGColor();
@@ -368,8 +371,14 @@
                     if (DEBUG) {
                         Slog.d(TAG, "The icon is not an AdaptiveIconDrawable");
                     }
-                    // TODO process legacy icon(bitmap)
-                    createIconDrawable(iconDrawable, true);
+                    Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "legacy_icon_factory");
+                    final ShapeIconFactory factory = new ShapeIconFactory(
+                            SplashscreenContentDrawer.this.mContext,
+                            scaledIconDpi, mFinalIconSize);
+                    final Bitmap bitmap = factory.createScaledBitmapWithoutShadow(
+                            iconDrawable, true /* shrinkNonAdaptiveIcons */);
+                    Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+                    createIconDrawable(new BitmapDrawable(bitmap), true);
                 }
                 animationDuration = 0;
             }
@@ -377,11 +386,15 @@
             return fillViewWithIcon(mFinalIconSize, mFinalIconDrawable, animationDuration);
         }
 
+        private class ShapeIconFactory extends BaseIconFactory {
+            protected ShapeIconFactory(Context context, int fillResIconDpi, int iconBitmapSize) {
+                super(context, fillResIconDpi, iconBitmapSize, true /* shapeDetection */);
+            }
+        }
+
         private void createIconDrawable(Drawable iconDrawable, boolean legacy) {
             if (legacy) {
                 mFinalIconDrawable = SplashscreenIconDrawableFactory.makeLegacyIconDrawable(
-                        mTmpAttrs.mIconBgColor != Color.TRANSPARENT
-                                ? mTmpAttrs.mIconBgColor : Color.WHITE,
                         iconDrawable, mDefaultIconSize, mFinalIconSize, mSplashscreenWorkerHandler);
             } else {
                 mFinalIconDrawable = SplashscreenIconDrawableFactory.makeIconDrawable(
@@ -402,7 +415,8 @@
             final ColorCache.IconColor iconColor = mColorCache.getIconColor(
                     mActivityInfo.packageName, mActivityInfo.getIconResource(),
                     mLastPackageContextConfigHash,
-                    () -> new DrawableColorTester(iconForeground, true /* filterTransparent */),
+                    () -> new DrawableColorTester(iconForeground,
+                            DrawableColorTester.TRANSLUCENT_FILTER /* filterType */),
                     () -> new DrawableColorTester(adaptiveIconDrawable.getBackground()));
 
             if (DEBUG) {
@@ -431,7 +445,7 @@
                 // Reference AdaptiveIcon description, outer is 108 and inner is 72, so we
                 // scale by 192/160 if we only draw adaptiveIcon's foreground.
                 final float noBgScale =
-                        iconColor.mFgNonTransparentRatio < ENLARGE_FOREGROUND_ICON_THRESHOLD
+                        iconColor.mFgNonTranslucentRatio < ENLARGE_FOREGROUND_ICON_THRESHOLD
                                 ? NO_BACKGROUND_SCALE : 1f;
                 // Using AdaptiveIconDrawable here can help keep the shape consistent with the
                 // current settings.
@@ -533,13 +547,26 @@
     }
 
     private static class DrawableColorTester {
+        private static final int NO_ALPHA_FILTER = 0;
+        // filter out completely invisible pixels
+        private static final int TRANSPARENT_FILTER = 1;
+        // filter out translucent and invisible pixels
+        private static final int TRANSLUCENT_FILTER = 2;
+
+        @IntDef(flag = true, value = {
+                NO_ALPHA_FILTER,
+                TRANSPARENT_FILTER,
+                TRANSLUCENT_FILTER
+        })
+        private @interface QuantizerFilterType {}
+
         private final ColorTester mColorChecker;
 
         DrawableColorTester(Drawable drawable) {
-            this(drawable, false /* filterTransparent */);
+            this(drawable, NO_ALPHA_FILTER /* filterType */);
         }
 
-        DrawableColorTester(Drawable drawable, boolean filterTransparent) {
+        DrawableColorTester(Drawable drawable, @QuantizerFilterType int filterType) {
             // Some applications use LayerDrawable for their windowBackground. To ensure that we
             // only get the real background, so that the color is not affected by the alpha of the
             // upper layer, try to get the lower layer here. This can also speed up the calculation.
@@ -558,12 +585,12 @@
             } else {
                 mColorChecker = drawable instanceof ColorDrawable
                         ? new SingleColorTester((ColorDrawable) drawable)
-                        : new ComplexDrawableTester(drawable, filterTransparent);
+                        : new ComplexDrawableTester(drawable, filterType);
             }
         }
 
-        public float nonTransparentRatio() {
-            return mColorChecker.nonTransparentRatio();
+        public float passFilterRatio() {
+            return mColorChecker.passFilterRatio();
         }
 
         public boolean isComplexColor() {
@@ -582,7 +609,7 @@
          * A help class to check the color information from a Drawable.
          */
         private interface ColorTester {
-            float nonTransparentRatio();
+            float passFilterRatio();
 
             boolean isComplexColor();
 
@@ -610,7 +637,7 @@
             }
 
             @Override
-            public float nonTransparentRatio() {
+            public float passFilterRatio() {
                 final int alpha = mColorDrawable.getAlpha();
                 return (float) (alpha / 255);
             }
@@ -639,15 +666,21 @@
             private static final int MAX_BITMAP_SIZE = 40;
             private final Palette mPalette;
             private final boolean mFilterTransparent;
-            private static final TransparentFilterQuantizer TRANSPARENT_FILTER_QUANTIZER =
-                    new TransparentFilterQuantizer();
+            private static final AlphaFilterQuantizer ALPHA_FILTER_QUANTIZER =
+                    new AlphaFilterQuantizer();
 
-            ComplexDrawableTester(Drawable drawable, boolean filterTransparent) {
+            /**
+             * @param drawable The test target.
+             * @param filterType Targeting to filter out transparent or translucent pixels,
+             *                   this would be needed if want to check
+             *                   {@link #passFilterRatio()}, also affecting the estimated result
+             *                   of the dominant color.
+             */
+            ComplexDrawableTester(Drawable drawable, @QuantizerFilterType int filterType) {
                 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "ComplexDrawableTester");
                 final Rect initialBounds = drawable.copyBounds();
                 int width = drawable.getIntrinsicWidth();
                 int height = drawable.getIntrinsicHeight();
-
                 // Some drawables do not have intrinsic dimensions
                 if (width <= 0 || height <= 0) {
                     width = MAX_BITMAP_SIZE;
@@ -668,9 +701,10 @@
                 // The Palette API will ignore Alpha, so it cannot handle transparent pixels, but
                 // sometimes we will need this information to know if this Drawable object is
                 // transparent.
-                mFilterTransparent = filterTransparent;
+                mFilterTransparent = filterType != NO_ALPHA_FILTER;
                 if (mFilterTransparent) {
-                    builder = new Palette.Builder(bitmap, TRANSPARENT_FILTER_QUANTIZER)
+                    ALPHA_FILTER_QUANTIZER.setFilter(filterType);
+                    builder = new Palette.Builder(bitmap, ALPHA_FILTER_QUANTIZER)
                             .maximumColorCount(5);
                 } else {
                     builder = new Palette.Builder(bitmap, null)
@@ -682,8 +716,8 @@
             }
 
             @Override
-            public float nonTransparentRatio() {
-                return mFilterTransparent ? TRANSPARENT_FILTER_QUANTIZER.mNonTransparentRatio : 1;
+            public float passFilterRatio() {
+                return mFilterTransparent ? ALPHA_FILTER_QUANTIZER.mPassFilterRatio : 1;
             }
 
             @Override
@@ -714,17 +748,34 @@
                 return true;
             }
 
-            private static class TransparentFilterQuantizer implements Quantizer {
+            private static class AlphaFilterQuantizer implements Quantizer {
                 private static final int NON_TRANSPARENT = 0xFF000000;
                 private final Quantizer mInnerQuantizer = new VariationalKMeansQuantizer();
-                private float mNonTransparentRatio;
+                private final IntPredicate mTransparentFilter = i -> (i & NON_TRANSPARENT) != 0;
+                private final IntPredicate mTranslucentFilter = i ->
+                        (i & NON_TRANSPARENT) == NON_TRANSPARENT;
+
+                private IntPredicate mFilter = mTransparentFilter;
+                private float mPassFilterRatio;
+
+                void setFilter(@QuantizerFilterType int filterType) {
+                    switch (filterType) {
+                        case TRANSLUCENT_FILTER:
+                            mFilter = mTranslucentFilter;
+                            break;
+                        case TRANSPARENT_FILTER:
+                        default:
+                            mFilter = mTransparentFilter;
+                            break;
+                    }
+                }
 
                 @Override
                 public void quantize(final int[] pixels, final int maxColors) {
-                    mNonTransparentRatio = 0;
+                    mPassFilterRatio = 0;
                     int realSize = 0;
                     for (int i = pixels.length - 1; i > 0; i--) {
-                        if ((pixels[i] & NON_TRANSPARENT) != 0) {
+                        if (mFilter.test(pixels[i])) {
                             realSize++;
                         }
                     }
@@ -735,11 +786,11 @@
                         mInnerQuantizer.quantize(pixels, maxColors);
                         return;
                     }
-                    mNonTransparentRatio = (float) realSize / pixels.length;
+                    mPassFilterRatio = (float) realSize / pixels.length;
                     final int[] samplePixels = new int[realSize];
                     int rowIndex = 0;
                     for (int i = pixels.length - 1; i > 0; i--) {
-                        if ((pixels[i] & NON_TRANSPARENT) == NON_TRANSPARENT) {
+                        if (mFilter.test(pixels[i])) {
                             samplePixels[rowIndex] = pixels[i];
                             rowIndex++;
                         }
@@ -798,16 +849,16 @@
             final int mBgColor;
             final boolean mIsBgComplex;
             final boolean mIsBgGrayscale;
-            final float mFgNonTransparentRatio;
+            final float mFgNonTranslucentRatio;
 
             IconColor(int hash, int fgColor, int bgColor, boolean isBgComplex,
-                    boolean isBgGrayscale, float fgNonTransparentRatio) {
+                    boolean isBgGrayscale, float fgNonTranslucnetRatio) {
                 super(hash);
                 mFgColor = fgColor;
                 mBgColor = bgColor;
                 mIsBgComplex = isBgComplex;
                 mIsBgGrayscale = isBgGrayscale;
-                mFgNonTransparentRatio = fgNonTransparentRatio;
+                mFgNonTranslucentRatio = fgNonTranslucnetRatio;
             }
         }
 
@@ -893,7 +944,7 @@
             final DrawableColorTester bgTester = bgColorTesterSupplier.get();
             final IconColor iconColor = new IconColor(hash, fgTester.getDominateColor(),
                     bgTester.getDominateColor(), bgTester.isComplexColor(), bgTester.isGrayscale(),
-                    fgTester.nonTransparentRatio());
+                    fgTester.passFilterRatio());
             colors.mIconColors[leastUsedIndex[0]] = iconColor;
             return iconColor;
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java
index 211941f..ba9123d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java
@@ -64,11 +64,10 @@
         }
     }
 
-    static Drawable makeLegacyIconDrawable(@ColorInt int backgroundColor,
-            @NonNull Drawable foregroundDrawable, int srcIconSize, int iconSize,
-            Handler splashscreenWorkerHandler) {
-        return new ImmobileIconDrawable(new LegacyIconDrawable(backgroundColor,
-                foregroundDrawable), srcIconSize, iconSize, splashscreenWorkerHandler);
+    static Drawable makeLegacyIconDrawable(@NonNull Drawable iconDrawable, int srcIconSize,
+            int iconSize, Handler splashscreenWorkerHandler) {
+        return new ImmobileIconDrawable(iconDrawable, srcIconSize, iconSize,
+                splashscreenWorkerHandler);
     }
 
     private static class ImmobileIconDrawable extends Drawable {
@@ -179,65 +178,6 @@
         }
     }
 
-    private static class LegacyIconDrawable extends MaskBackgroundDrawable {
-        // reference FixedScaleDrawable
-        // iconBounds = 0.7 * X * outerBounds, X is the scale of diagonal
-        private static final float LEGACY_ICON_SCALE = .7f * .8f;
-        private final Drawable mForegroundDrawable;
-        private float mScaleX, mScaleY, mTransX, mTransY;
-
-        LegacyIconDrawable(@ColorInt int backgroundColor, Drawable foregroundDrawable) {
-            super(backgroundColor);
-            mForegroundDrawable = foregroundDrawable;
-            mScaleX = LEGACY_ICON_SCALE;
-            mScaleY = LEGACY_ICON_SCALE;
-        }
-
-        @Override
-        protected void updateLayerBounds(Rect bounds) {
-            super.updateLayerBounds(bounds);
-
-            if (mForegroundDrawable == null) {
-                return;
-            }
-            float outerBoundsWidth = bounds.width();
-            float outerBoundsHeight = bounds.height();
-            float h = mForegroundDrawable.getIntrinsicHeight();
-            float w = mForegroundDrawable.getIntrinsicWidth();
-            mScaleX = LEGACY_ICON_SCALE;
-            mScaleY = LEGACY_ICON_SCALE;
-            if (h > w && w > 0) {
-                mScaleX *= w / h;
-            } else if (w > h && h > 0) {
-                mScaleY *= h / w;
-            }
-            int innerBoundsWidth = (int) (0.5 + outerBoundsWidth * mScaleX);
-            int innerBoundsHeight = (int) (0.5 + outerBoundsHeight * mScaleY);
-            final Rect rect = new Rect(0, 0, innerBoundsWidth, innerBoundsHeight);
-            mForegroundDrawable.setBounds(rect);
-            mTransX = (outerBoundsWidth - innerBoundsWidth) / 2;
-            mTransY = (outerBoundsHeight - innerBoundsHeight) / 2;
-            invalidateSelf();
-        }
-
-        @Override
-        public void draw(Canvas canvas) {
-            super.draw(canvas);
-            int saveCount = canvas.save();
-            canvas.translate(mTransX, mTransY);
-            if (mForegroundDrawable != null) {
-                mForegroundDrawable.draw(canvas);
-            }
-            canvas.restoreToCount(saveCount);
-        }
-
-        @Override
-        public void setColorFilter(ColorFilter colorFilter) {
-            if (mForegroundDrawable != null) {
-                mForegroundDrawable.setColorFilter(colorFilter);
-            }
-        }
-    }
     /**
      * A lightweight AdaptiveIconDrawable which support foreground to be Animatable, and keep this
      * drawable masked by config_icon_mask.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
index 243751fe..fc7c86d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
@@ -168,16 +168,14 @@
     void addSplashScreenStartingWindow(StartingWindowInfo windowInfo, IBinder appToken,
             @StartingWindowType int suggestType) {
         final RunningTaskInfo taskInfo = windowInfo.taskInfo;
-        final ActivityInfo activityInfo = taskInfo.topActivityInfo;
-        if (activityInfo == null) {
+        final ActivityInfo activityInfo = windowInfo.targetActivityInfo != null
+                ? windowInfo.targetActivityInfo
+                : taskInfo.topActivityInfo;
+        if (activityInfo == null || activityInfo.packageName == null) {
             return;
         }
 
         final int displayId = taskInfo.displayId;
-        if (activityInfo.packageName == null) {
-            return;
-        }
-
         final int taskId = taskInfo.taskId;
         Context context = mContext;
         // replace with the default theme if the application didn't set
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
index 284f384..d536adb 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
@@ -214,6 +214,7 @@
         final ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo();
         taskInfo.topActivityInfo = info;
         taskInfo.taskId = taskId;
+        windowInfo.targetActivityInfo = info;
         windowInfo.taskInfo = taskInfo;
         return windowInfo;
     }
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index c4cdb7d..54367b8 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -44,8 +44,6 @@
 #include <utils/StrongPointer.h>
 #include <utils/Timers.h>
 
-#include <pthread.h>
-
 #include <algorithm>
 #include <atomic>
 #include <vector>
@@ -60,10 +58,6 @@
 struct {
     jclass clazz;
     jmethodID invokePictureCapturedCallback;
-    jmethodID createHintSession;
-    jmethodID updateTargetWorkDuration;
-    jmethodID reportActualWorkDuration;
-    jmethodID closeHintSession;
 } gHardwareRenderer;
 
 struct {
@@ -90,14 +84,6 @@
     return env;
 }
 
-static bool hasExceptionAndClear(JNIEnv* env) {
-    if (GraphicsJNI::hasException(env)) {
-        env->ExceptionClear();
-        return true;
-    }
-    return false;
-}
-
 typedef ANativeWindow* (*ANW_fromSurface)(JNIEnv* env, jobject surface);
 ANW_fromSurface fromSurface;
 
@@ -147,67 +133,6 @@
     }
 };
 
-class HintSessionWrapper : public LightRefBase<HintSessionWrapper> {
-public:
-    static sp<HintSessionWrapper> create(JNIEnv* env, RenderProxy* proxy) {
-        if (!Properties::useHintManager) return nullptr;
-
-        // Include UI thread (self), render thread, and thread pool.
-        std::vector<int> tids = CommonPool::getThreadIds();
-        tids.push_back(proxy->getRenderThreadTid());
-        tids.push_back(pthread_gettid_np(pthread_self()));
-
-        jintArray tidsArray = env->NewIntArray(tids.size());
-        if (hasExceptionAndClear(env)) return nullptr;
-        env->SetIntArrayRegion(tidsArray, 0, tids.size(), reinterpret_cast<jint*>(tids.data()));
-        if (hasExceptionAndClear(env)) return nullptr;
-        jobject session = env->CallStaticObjectMethod(
-                gHardwareRenderer.clazz, gHardwareRenderer.createHintSession, tidsArray);
-        if (hasExceptionAndClear(env) || !session) return nullptr;
-        return new HintSessionWrapper(env, session);
-    }
-
-    ~HintSessionWrapper() {
-        if (!mSession) return;
-        JNIEnv* env = getenv(mVm);
-        env->CallStaticVoidMethod(gHardwareRenderer.clazz, gHardwareRenderer.closeHintSession,
-                                  mSession);
-        hasExceptionAndClear(env);
-        env->DeleteGlobalRef(mSession);
-        mSession = nullptr;
-    }
-
-    void updateTargetWorkDuration(long targetDurationNanos) {
-        if (!mSession) return;
-        JNIEnv* env = getenv(mVm);
-        env->CallStaticVoidMethod(gHardwareRenderer.clazz,
-                                  gHardwareRenderer.updateTargetWorkDuration, mSession,
-                                  static_cast<jlong>(targetDurationNanos));
-        hasExceptionAndClear(env);
-    }
-
-    void reportActualWorkDuration(long actualDurationNanos) {
-        if (!mSession) return;
-        JNIEnv* env = getenv(mVm);
-        env->CallStaticVoidMethod(gHardwareRenderer.clazz,
-                                  gHardwareRenderer.reportActualWorkDuration, mSession,
-                                  static_cast<jlong>(actualDurationNanos));
-        hasExceptionAndClear(env);
-    }
-
-private:
-    HintSessionWrapper(JNIEnv* env, jobject jobject) {
-        env->GetJavaVM(&mVm);
-        if (jobject) {
-            mSession = env->NewGlobalRef(jobject);
-            LOG_ALWAYS_FATAL_IF(!mSession, "Failed to make global ref");
-        }
-    }
-
-    JavaVM* mVm = nullptr;
-    jobject mSession = nullptr;
-};
-
 static void android_view_ThreadedRenderer_rotateProcessStatsBuffer(JNIEnv* env, jobject clazz) {
     RenderProxy::rotateProcessStatsBuffer();
 }
@@ -235,12 +160,6 @@
     RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr);
     ContextFactoryImpl factory(rootRenderNode);
     RenderProxy* proxy = new RenderProxy(translucent, rootRenderNode, &factory);
-    sp<HintSessionWrapper> wrapper = HintSessionWrapper::create(env, proxy);
-    if (wrapper) {
-        proxy->setHintSessionCallbacks(
-                [wrapper](int64_t nanos) { wrapper->updateTargetWorkDuration(nanos); },
-                [wrapper](int64_t nanos) { wrapper->reportActualWorkDuration(nanos); });
-    }
     return (jlong) proxy;
 }
 
@@ -1059,18 +978,6 @@
     gHardwareRenderer.invokePictureCapturedCallback = GetStaticMethodIDOrDie(env, hardwareRenderer,
             "invokePictureCapturedCallback",
             "(JLandroid/graphics/HardwareRenderer$PictureCapturedCallback;)V");
-    gHardwareRenderer.createHintSession =
-            GetStaticMethodIDOrDie(env, hardwareRenderer, "createHintSession",
-                                   "([I)Landroid/os/PerformanceHintManager$Session;");
-    gHardwareRenderer.updateTargetWorkDuration =
-            GetStaticMethodIDOrDie(env, hardwareRenderer, "updateTargetWorkDuration",
-                                   "(Landroid/os/PerformanceHintManager$Session;J)V");
-    gHardwareRenderer.reportActualWorkDuration =
-            GetStaticMethodIDOrDie(env, hardwareRenderer, "reportActualWorkDuration",
-                                   "(Landroid/os/PerformanceHintManager$Session;J)V");
-    gHardwareRenderer.closeHintSession =
-            GetStaticMethodIDOrDie(env, hardwareRenderer, "closeHintSession",
-                                   "(Landroid/os/PerformanceHintManager$Session;)V");
 
     jclass aSurfaceTransactionCallbackClass =
             FindClassOrDie(env, "android/graphics/HardwareRenderer$ASurfaceTransactionCallback");
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index db29e34..e7081df 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -16,6 +16,7 @@
 
 #include "DrawFrameTask.h"
 
+#include <dlfcn.h>
 #include <gui/TraceUtils.h>
 #include <utils/Log.h>
 #include <algorithm>
@@ -26,11 +27,63 @@
 #include "../RenderNode.h"
 #include "CanvasContext.h"
 #include "RenderThread.h"
+#include "thread/CommonPool.h"
 
 namespace android {
 namespace uirenderer {
 namespace renderthread {
 
+namespace {
+
+typedef APerformanceHintManager* (*APH_getManager)();
+typedef APerformanceHintSession* (*APH_createSession)(APerformanceHintManager*, const int32_t*,
+                                                      size_t, int64_t);
+typedef void (*APH_updateTargetWorkDuration)(APerformanceHintSession*, int64_t);
+typedef void (*APH_reportActualWorkDuration)(APerformanceHintSession*, int64_t);
+typedef void (*APH_closeSession)(APerformanceHintSession* session);
+
+bool gAPerformanceHintBindingInitialized = false;
+APH_getManager gAPH_getManagerFn = nullptr;
+APH_createSession gAPH_createSessionFn = nullptr;
+APH_updateTargetWorkDuration gAPH_updateTargetWorkDurationFn = nullptr;
+APH_reportActualWorkDuration gAPH_reportActualWorkDurationFn = nullptr;
+APH_closeSession gAPH_closeSessionFn = nullptr;
+
+void ensureAPerformanceHintBindingInitialized() {
+    if (gAPerformanceHintBindingInitialized) return;
+
+    void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE);
+    LOG_ALWAYS_FATAL_IF(handle_ == nullptr, "Failed to dlopen libandroid.so!");
+
+    gAPH_getManagerFn = (APH_getManager)dlsym(handle_, "APerformanceHint_getManager");
+    LOG_ALWAYS_FATAL_IF(gAPH_getManagerFn == nullptr,
+                        "Failed to find required symbol APerformanceHint_getManager!");
+
+    gAPH_createSessionFn = (APH_createSession)dlsym(handle_, "APerformanceHint_createSession");
+    LOG_ALWAYS_FATAL_IF(gAPH_createSessionFn == nullptr,
+                        "Failed to find required symbol APerformanceHint_createSession!");
+
+    gAPH_updateTargetWorkDurationFn = (APH_updateTargetWorkDuration)dlsym(
+            handle_, "APerformanceHint_updateTargetWorkDuration");
+    LOG_ALWAYS_FATAL_IF(
+            gAPH_updateTargetWorkDurationFn == nullptr,
+            "Failed to find required symbol APerformanceHint_updateTargetWorkDuration!");
+
+    gAPH_reportActualWorkDurationFn = (APH_reportActualWorkDuration)dlsym(
+            handle_, "APerformanceHint_reportActualWorkDuration");
+    LOG_ALWAYS_FATAL_IF(
+            gAPH_reportActualWorkDurationFn == nullptr,
+            "Failed to find required symbol APerformanceHint_reportActualWorkDuration!");
+
+    gAPH_closeSessionFn = (APH_closeSession)dlsym(handle_, "APerformanceHint_closeSession");
+    LOG_ALWAYS_FATAL_IF(gAPH_closeSessionFn == nullptr,
+                        "Failed to find required symbol APerformanceHint_closeSession!");
+
+    gAPerformanceHintBindingInitialized = true;
+}
+
+}  // namespace
+
 DrawFrameTask::DrawFrameTask()
         : mRenderThread(nullptr)
         , mContext(nullptr)
@@ -39,17 +92,13 @@
 
 DrawFrameTask::~DrawFrameTask() {}
 
-void DrawFrameTask::setContext(RenderThread* thread, CanvasContext* context,
-                               RenderNode* targetNode) {
+void DrawFrameTask::setContext(RenderThread* thread, CanvasContext* context, RenderNode* targetNode,
+                               int32_t uiThreadId, int32_t renderThreadId) {
     mRenderThread = thread;
     mContext = context;
     mTargetNode = targetNode;
-}
-
-void DrawFrameTask::setHintSessionCallbacks(std::function<void(int64_t)> updateTargetWorkDuration,
-                                            std::function<void(int64_t)> reportActualWorkDuration) {
-    mUpdateTargetWorkDuration = std::move(updateTargetWorkDuration);
-    mReportActualWorkDuration = std::move(reportActualWorkDuration);
+    mUiThreadId = uiThreadId;
+    mRenderThreadId = renderThreadId;
 }
 
 void DrawFrameTask::pushLayerUpdate(DeferredLayerUpdater* layer) {
@@ -144,27 +193,25 @@
         unblockUiThread();
     }
 
-    // These member callbacks are effectively const as they are set once during init, so it's safe
-    // to use these directly instead of making local copies.
-    if (mUpdateTargetWorkDuration && mReportActualWorkDuration) {
-        constexpr int64_t kSanityCheckLowerBound = 100000;       // 0.1ms
-        constexpr int64_t kSanityCheckUpperBound = 10000000000;  // 10s
-        int64_t targetWorkDuration = frameDeadline - intendedVsync;
-        targetWorkDuration = targetWorkDuration * Properties::targetCpuTimePercentage / 100;
-        if (targetWorkDuration > kSanityCheckLowerBound &&
-            targetWorkDuration < kSanityCheckUpperBound &&
-            targetWorkDuration != mLastTargetWorkDuration) {
-            mLastTargetWorkDuration = targetWorkDuration;
-            mUpdateTargetWorkDuration(targetWorkDuration);
-        }
-        int64_t frameDuration = systemTime(SYSTEM_TIME_MONOTONIC) - frameStartTime;
-        int64_t actualDuration = frameDuration -
-                                 (std::min(syncDelayDuration, mLastDequeueBufferDuration)) -
-                                 dequeueBufferDuration;
-        if (actualDuration > kSanityCheckLowerBound && actualDuration < kSanityCheckUpperBound) {
-            mReportActualWorkDuration(actualDuration);
-        }
+    if (!mHintSessionWrapper) mHintSessionWrapper.emplace(mUiThreadId, mRenderThreadId);
+    constexpr int64_t kSanityCheckLowerBound = 100000;       // 0.1ms
+    constexpr int64_t kSanityCheckUpperBound = 10000000000;  // 10s
+    int64_t targetWorkDuration = frameDeadline - intendedVsync;
+    targetWorkDuration = targetWorkDuration * Properties::targetCpuTimePercentage / 100;
+    if (targetWorkDuration > kSanityCheckLowerBound &&
+        targetWorkDuration < kSanityCheckUpperBound &&
+        targetWorkDuration != mLastTargetWorkDuration) {
+        mLastTargetWorkDuration = targetWorkDuration;
+        mHintSessionWrapper->updateTargetWorkDuration(targetWorkDuration);
     }
+    int64_t frameDuration = systemTime(SYSTEM_TIME_MONOTONIC) - frameStartTime;
+    int64_t actualDuration = frameDuration -
+                             (std::min(syncDelayDuration, mLastDequeueBufferDuration)) -
+                             dequeueBufferDuration;
+    if (actualDuration > kSanityCheckLowerBound && actualDuration < kSanityCheckUpperBound) {
+        mHintSessionWrapper->reportActualWorkDuration(actualDuration);
+    }
+
     mLastDequeueBufferDuration = dequeueBufferDuration;
 }
 
@@ -216,6 +263,44 @@
     mSignal.signal();
 }
 
+DrawFrameTask::HintSessionWrapper::HintSessionWrapper(int32_t uiThreadId, int32_t renderThreadId) {
+    if (!Properties::useHintManager) return;
+    if (uiThreadId < 0 || renderThreadId < 0) return;
+
+    ensureAPerformanceHintBindingInitialized();
+
+    APerformanceHintManager* manager = gAPH_getManagerFn();
+    if (!manager) return;
+
+    std::vector<int32_t> tids = CommonPool::getThreadIds();
+    tids.push_back(uiThreadId);
+    tids.push_back(renderThreadId);
+
+    // DrawFrameTask code will always set a target duration before reporting actual durations.
+    // So this is just a placeholder value that's never used.
+    int64_t dummyTargetDurationNanos = 16666667;
+    mHintSession =
+            gAPH_createSessionFn(manager, tids.data(), tids.size(), dummyTargetDurationNanos);
+}
+
+DrawFrameTask::HintSessionWrapper::~HintSessionWrapper() {
+    if (mHintSession) {
+        gAPH_closeSessionFn(mHintSession);
+    }
+}
+
+void DrawFrameTask::HintSessionWrapper::updateTargetWorkDuration(long targetDurationNanos) {
+    if (mHintSession) {
+        gAPH_updateTargetWorkDurationFn(mHintSession, targetDurationNanos);
+    }
+}
+
+void DrawFrameTask::HintSessionWrapper::reportActualWorkDuration(long actualDurationNanos) {
+    if (mHintSession) {
+        gAPH_reportActualWorkDurationFn(mHintSession, actualDurationNanos);
+    }
+}
+
 } /* namespace renderthread */
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index 2455ea8..6a61a2b 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -16,8 +16,10 @@
 #ifndef DRAWFRAMETASK_H
 #define DRAWFRAMETASK_H
 
+#include <optional>
 #include <vector>
 
+#include <performance_hint_private.h>
 #include <utils/Condition.h>
 #include <utils/Mutex.h>
 #include <utils/StrongPointer.h>
@@ -60,9 +62,8 @@
     DrawFrameTask();
     virtual ~DrawFrameTask();
 
-    void setContext(RenderThread* thread, CanvasContext* context, RenderNode* targetNode);
-    void setHintSessionCallbacks(std::function<void(int64_t)> updateTargetWorkDuration,
-                                 std::function<void(int64_t)> reportActualWorkDuration);
+    void setContext(RenderThread* thread, CanvasContext* context, RenderNode* targetNode,
+                    int32_t uiThreadId, int32_t renderThreadId);
     void setContentDrawBounds(int left, int top, int right, int bottom) {
         mContentDrawBounds.set(left, top, right, bottom);
     }
@@ -85,6 +86,18 @@
     }
 
 private:
+    class HintSessionWrapper {
+    public:
+        HintSessionWrapper(int32_t uiThreadId, int32_t renderThreadId);
+        ~HintSessionWrapper();
+
+        void updateTargetWorkDuration(long targetDurationNanos);
+        void reportActualWorkDuration(long actualDurationNanos);
+
+    private:
+        APerformanceHintSession* mHintSession = nullptr;
+    };
+
     void postAndWait();
     bool syncFrameState(TreeInfo& info);
     void unblockUiThread();
@@ -95,6 +108,8 @@
     RenderThread* mRenderThread;
     CanvasContext* mContext;
     RenderNode* mTargetNode = nullptr;
+    int32_t mUiThreadId = -1;
+    int32_t mRenderThreadId = -1;
     Rect mContentDrawBounds;
 
     /*********************************************
@@ -112,8 +127,7 @@
 
     nsecs_t mLastDequeueBufferDuration = 0;
     nsecs_t mLastTargetWorkDuration = 0;
-    std::function<void(int64_t)> mUpdateTargetWorkDuration;
-    std::function<void(int64_t)> mReportActualWorkDuration;
+    std::optional<HintSessionWrapper> mHintSessionWrapper;
 };
 
 } /* namespace renderthread */
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index a77b5b5..c485ce2 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -29,6 +29,8 @@
 #include "utils/Macros.h"
 #include "utils/TimeUtils.h"
 
+#include <pthread.h>
+
 namespace android {
 namespace uirenderer {
 namespace renderthread {
@@ -39,7 +41,8 @@
     mContext = mRenderThread.queue().runSync([&]() -> CanvasContext* {
         return CanvasContext::create(mRenderThread, translucent, rootRenderNode, contextFactory);
     });
-    mDrawFrameTask.setContext(&mRenderThread, mContext, rootRenderNode);
+    mDrawFrameTask.setContext(&mRenderThread, mContext, rootRenderNode,
+                              pthread_gettid_np(pthread_self()), getRenderThreadTid());
 }
 
 RenderProxy::~RenderProxy() {
@@ -48,7 +51,7 @@
 
 void RenderProxy::destroyContext() {
     if (mContext) {
-        mDrawFrameTask.setContext(nullptr, nullptr, nullptr);
+        mDrawFrameTask.setContext(nullptr, nullptr, nullptr, -1, -1);
         // This is also a fence as we need to be certain that there are no
         // outstanding mDrawFrame tasks posted before it is destroyed
         mRenderThread.queue().runSync([this]() { delete mContext; });
@@ -76,12 +79,6 @@
     mRenderThread.queue().runSync([this, name]() { mContext->setName(std::string(name)); });
 }
 
-void RenderProxy::setHintSessionCallbacks(std::function<void(int64_t)> updateTargetWorkDuration,
-                                          std::function<void(int64_t)> reportActualWorkDuration) {
-    mDrawFrameTask.setHintSessionCallbacks(std::move(updateTargetWorkDuration),
-                                           std::move(reportActualWorkDuration));
-}
-
 void RenderProxy::setSurface(ANativeWindow* window, bool enableTimeout) {
     if (window) { ANativeWindow_acquire(window); }
     mRenderThread.queue().post([this, win = window, enableTimeout]() mutable {
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 1b0f22e..2b5405c 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -71,8 +71,6 @@
     void setSwapBehavior(SwapBehavior swapBehavior);
     bool loadSystemProperties();
     void setName(const char* name);
-    void setHintSessionCallbacks(std::function<void(int64_t)> updateTargetWorkDuration,
-                                 std::function<void(int64_t)> reportActualWorkDuration);
 
     void setSurface(ANativeWindow* window, bool enableTimeout = true);
     void setSurfaceControl(ASurfaceControl* surfaceControl);
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index cc05ecd..8b91536 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -72,6 +72,37 @@
  Finally, you request (or receive) a filled output buffer, consume its contents and release it
  back to the codec.
 
+ <h3 id=qualityFloor><a name="qualityFloor">Minimum Quality Floor for Video Encoding</h3>
+ <p>
+ Beginning with {@link android.os.Build.VERSION_CODES#S}, Android's Video MediaCodecs enforce a
+ minimum quality floor. The intent is to eliminate poor quality video encodings. This quality
+ floor is applied when the codec is in Variable Bitrate (VBR) mode; it is not applied when
+ the codec is in Constant Bitrate (CBR) mode. The quality floor enforcement is also restricted
+ to a particular size range; this size range is currently for video resolutions
+ larger than 320x240 up through 1920x1080.
+
+ <p>
+ When this quality floor is in effect, the codec and supporting framework code will work to
+ ensure that the generated video is of at least a "fair" or "good" quality. The metric
+ used to choose these targets is the VMAF (Video Multi-method Assessment Function) with a
+ target score of 70 for selected test sequences.
+
+ <p>
+ The typical effect is that
+ some videos will generate a higher bitrate than originally configured. This will be most
+ notable for videos which were configured with very low bitrates; the codec will use a bitrate
+ that is determined to be more likely to generate an "fair" or "good" quality video. Another
+ situation is where a video includes very complicated content (lots of motion and detail);
+ in such configurations, the codec will use extra bitrate as needed to avoid losing all of
+ the content's finer detail.
+
+ <p>
+ This quality floor will not impact content captured at high bitrates (a high bitrate should
+ already provide the codec with sufficient capacity to encode all of the detail).
+ The quality floor does not operate on CBR encodings.
+ The quality floor currently does not operate on resolutions of 320x240 or lower, nor on
+ videos with resolution above 1920x1080.
+
  <h3>Data Types</h3>
  <p>
  Codecs operate on three kinds of data: compressed data, raw audio data and raw video data.
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 341bb8d..7d80e93 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -1096,6 +1096,13 @@
      * clipped internally to ensure the video recording can proceed smoothly based on
      * the capabilities of the platform.
      *
+     * <p>
+     * NB: the actual bitrate and other encoding characteristics may be affected by
+     * the minimum quality floor behavior introduced in
+     * {@link android.os.Build.VERSION_CODES#S}. More detail on how and where this
+     * impacts video encoding can be found in the
+     * {@link MediaCodec} page and looking for "quality floor" (near the top of the page).
+     *
      * @param bitRate the video encoding bit rate in bits per second.
      */
     public void setVideoEncodingBitRate(int bitRate) {
diff --git a/media/java/android/media/metrics/PlaybackErrorEvent.java b/media/java/android/media/metrics/PlaybackErrorEvent.java
index 184b359..4e3b426 100644
--- a/media/java/android/media/metrics/PlaybackErrorEvent.java
+++ b/media/java/android/media/metrics/PlaybackErrorEvent.java
@@ -317,7 +317,7 @@
      */
     public static final class Builder {
         private @Nullable Exception mException;
-        private int mErrorCode;
+        private int mErrorCode = ERROR_UNKNOWN;
         private int mSubErrorCode;
         private long mTimeSinceCreatedMillis = -1;
         private Bundle mMetricsBundle = new Bundle();
diff --git a/media/java/android/media/metrics/PlaybackMetrics.java b/media/java/android/media/metrics/PlaybackMetrics.java
index bbcc484..e71ee20 100644
--- a/media/java/android/media/metrics/PlaybackMetrics.java
+++ b/media/java/android/media/metrics/PlaybackMetrics.java
@@ -502,9 +502,9 @@
         private long mMediaDurationMillis = -1;
         private int mStreamSource = STREAM_SOURCE_UNKNOWN;
         private int mStreamType = STREAM_TYPE_UNKNOWN;
-        private int mPlaybackType = PLAYBACK_TYPE_OTHER;
+        private int mPlaybackType = PLAYBACK_TYPE_UNKNOWN;
         private int mDrmType = DRM_TYPE_NONE;
-        private int mContentType = CONTENT_TYPE_OTHER;
+        private int mContentType = CONTENT_TYPE_UNKNOWN;
         private @Nullable String mPlayerName;
         private @Nullable String mPlayerVersion;
         private @NonNull List<Long> mExperimentIds = new ArrayList<>();
diff --git a/media/jni/android_mtp_MtpDevice.cpp b/media/jni/android_mtp_MtpDevice.cpp
index ac89fecd..8436ba4 100644
--- a/media/jni/android_mtp_MtpDevice.cpp
+++ b/media/jni/android_mtp_MtpDevice.cpp
@@ -416,20 +416,14 @@
         return -1;
     }
 
-    MtpProperty* property = new MtpProperty(MTP_DEVICE_PROPERTY_SESSION_INITIATOR_VERSION_INFO,
-                                            MTP_TYPE_STR, true);
-    if (!property) {
-        env->ThrowNew(clazz_io_exception, "Failed to obtain property.");
-        return -1;
-    }
-
-    if (property->getDataType() != MTP_TYPE_STR) {
+    MtpProperty property(MTP_DEVICE_PROPERTY_SESSION_INITIATOR_VERSION_INFO, MTP_TYPE_STR, true);
+    if (property.getDataType() != MTP_TYPE_STR) {
         env->ThrowNew(clazz_io_exception, "Unexpected property data type.");
         return -1;
     }
 
-    property->setCurrentValue(propertyStr);
-    if (!device->setDevicePropValueStr(property)) {
+    property.setCurrentValue(propertyStr);
+    if (!device->setDevicePropValueStr(&property)) {
         env->ThrowNew(clazz_io_exception, "Failed to obtain property value.");
         return -1;
     }
diff --git a/native/android/Android.bp b/native/android/Android.bp
index 3ee2c18..32b7a07 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -57,6 +57,7 @@
         "net.c",
         "obb.cpp",
         "permission_manager.cpp",
+        "performance_hint.cpp",
         "sensor.cpp",
         "sharedmem.cpp",
         "storage_manager.cpp",
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index de6db1a..f33e118 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -312,6 +312,13 @@
 
 LIBANDROID_PLATFORM {
   global:
+    APerformanceHint_getManager;
+    APerformanceHint_createSession;
+    APerformanceHint_getPreferredUpdateRateNanos;
+    APerformanceHint_updateTargetWorkDuration;
+    APerformanceHint_reportActualWorkDuration;
+    APerformanceHint_closeSession;
+    APerformanceHint_setIHintManagerForTesting;
     extern "C++" {
         ASurfaceControl_registerSurfaceStatsListener*;
         ASurfaceControl_unregisterSurfaceStatsListener*;
diff --git a/native/android/performance_hint.cpp b/native/android/performance_hint.cpp
new file mode 100644
index 0000000..95a2da9
--- /dev/null
+++ b/native/android/performance_hint.cpp
@@ -0,0 +1,241 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "perf_hint"
+
+#include <utility>
+#include <vector>
+
+#include <android/os/IHintManager.h>
+#include <android/os/IHintSession.h>
+#include <binder/Binder.h>
+#include <binder/IBinder.h>
+#include <binder/IServiceManager.h>
+#include <performance_hint_private.h>
+#include <utils/SystemClock.h>
+
+using namespace android;
+using namespace android::os;
+
+struct APerformanceHintSession;
+
+struct APerformanceHintManager {
+public:
+    static APerformanceHintManager* getInstance();
+    APerformanceHintManager(sp<IHintManager> service, int64_t preferredRateNanos);
+    APerformanceHintManager() = delete;
+    ~APerformanceHintManager() = default;
+
+    APerformanceHintSession* createSession(const int32_t* threadIds, size_t size,
+                                           int64_t initialTargetWorkDurationNanos);
+    int64_t getPreferredRateNanos() const;
+
+private:
+    static APerformanceHintManager* create(sp<IHintManager> iHintManager);
+
+    sp<IHintManager> mHintManager;
+    const int64_t mPreferredRateNanos;
+};
+
+struct APerformanceHintSession {
+public:
+    APerformanceHintSession(sp<IHintSession> session, int64_t preferredRateNanos,
+                            int64_t targetDurationNanos);
+    APerformanceHintSession() = delete;
+    ~APerformanceHintSession();
+
+    int updateTargetWorkDuration(int64_t targetDurationNanos);
+    int reportActualWorkDuration(int64_t actualDurationNanos);
+
+private:
+    friend struct APerformanceHintManager;
+
+    sp<IHintSession> mHintSession;
+    // HAL preferred update rate
+    const int64_t mPreferredRateNanos;
+    // Target duration for choosing update rate
+    int64_t mTargetDurationNanos;
+    // Last update timestamp
+    int64_t mLastUpdateTimestamp;
+    // Cached samples
+    std::vector<int64_t> mActualDurationsNanos;
+    std::vector<int64_t> mTimestampsNanos;
+};
+
+static IHintManager* gIHintManagerForTesting = nullptr;
+static APerformanceHintManager* gHintManagerForTesting = nullptr;
+
+// ===================================== APerformanceHintManager implementation
+APerformanceHintManager::APerformanceHintManager(sp<IHintManager> manager,
+                                                 int64_t preferredRateNanos)
+      : mHintManager(std::move(manager)), mPreferredRateNanos(preferredRateNanos) {}
+
+APerformanceHintManager* APerformanceHintManager::getInstance() {
+    if (gHintManagerForTesting) return gHintManagerForTesting;
+    if (gIHintManagerForTesting) {
+        APerformanceHintManager* manager = create(gIHintManagerForTesting);
+        gIHintManagerForTesting = nullptr;
+        return manager;
+    }
+    static APerformanceHintManager* instance = create(nullptr);
+    return instance;
+}
+
+APerformanceHintManager* APerformanceHintManager::create(sp<IHintManager> manager) {
+    if (!manager) {
+        manager = interface_cast<IHintManager>(
+                defaultServiceManager()->checkService(String16("performance_hint")));
+    }
+    if (manager == nullptr) {
+        ALOGE("%s: PerformanceHint service is not ready ", __FUNCTION__);
+        return nullptr;
+    }
+    int64_t preferredRateNanos = -1L;
+    binder::Status ret = manager->getHintSessionPreferredRate(&preferredRateNanos);
+    if (!ret.isOk()) {
+        ALOGE("%s: PerformanceHint cannot get preferred rate. %s", __FUNCTION__,
+              ret.exceptionMessage().c_str());
+        return nullptr;
+    }
+    if (preferredRateNanos <= 0) {
+        ALOGE("%s: PerformanceHint invalid preferred rate.", __FUNCTION__);
+        return nullptr;
+    }
+    return new APerformanceHintManager(std::move(manager), preferredRateNanos);
+}
+
+APerformanceHintSession* APerformanceHintManager::createSession(
+        const int32_t* threadIds, size_t size, int64_t initialTargetWorkDurationNanos) {
+    sp<IBinder> token = sp<BBinder>::make();
+    std::vector<int32_t> tids(threadIds, threadIds + size);
+    sp<IHintSession> session;
+    binder::Status ret =
+            mHintManager->createHintSession(token, tids, initialTargetWorkDurationNanos, &session);
+    if (!ret.isOk() || !session) {
+        return nullptr;
+    }
+    return new APerformanceHintSession(std::move(session), mPreferredRateNanos,
+                                       initialTargetWorkDurationNanos);
+}
+
+int64_t APerformanceHintManager::getPreferredRateNanos() const {
+    return mPreferredRateNanos;
+}
+
+// ===================================== APerformanceHintSession implementation
+
+APerformanceHintSession::APerformanceHintSession(sp<IHintSession> session,
+                                                 int64_t preferredRateNanos,
+                                                 int64_t targetDurationNanos)
+      : mHintSession(std::move(session)),
+        mPreferredRateNanos(preferredRateNanos),
+        mTargetDurationNanos(targetDurationNanos),
+        mLastUpdateTimestamp(elapsedRealtimeNano()) {}
+
+APerformanceHintSession::~APerformanceHintSession() {
+    binder::Status ret = mHintSession->close();
+    if (!ret.isOk()) {
+        ALOGE("%s: HintSession close failed: %s", __FUNCTION__, ret.exceptionMessage().c_str());
+    }
+}
+
+int APerformanceHintSession::updateTargetWorkDuration(int64_t targetDurationNanos) {
+    if (targetDurationNanos <= 0) {
+        ALOGE("%s: targetDurationNanos must be positive", __FUNCTION__);
+        return EINVAL;
+    }
+    binder::Status ret = mHintSession->updateTargetWorkDuration(targetDurationNanos);
+    if (!ret.isOk()) {
+        ALOGE("%s: HintSessionn updateTargetWorkDuration failed: %s", __FUNCTION__,
+              ret.exceptionMessage().c_str());
+        return EPIPE;
+    }
+    mTargetDurationNanos = targetDurationNanos;
+    /**
+     * Most of the workload is target_duration dependent, so now clear the cached samples
+     * as they are most likely obsolete.
+     */
+    mActualDurationsNanos.clear();
+    mTimestampsNanos.clear();
+    mLastUpdateTimestamp = elapsedRealtimeNano();
+    return 0;
+}
+
+int APerformanceHintSession::reportActualWorkDuration(int64_t actualDurationNanos) {
+    if (actualDurationNanos <= 0) {
+        ALOGE("%s: actualDurationNanos must be positive", __FUNCTION__);
+        return EINVAL;
+    }
+    int64_t now = elapsedRealtimeNano();
+    mActualDurationsNanos.push_back(actualDurationNanos);
+    mTimestampsNanos.push_back(now);
+
+    /**
+     * Use current sample to determine the rate limit. We can pick a shorter rate limit
+     * if any sample underperformed, however, it could be the lower level system is slow
+     * to react. So here we explicitly choose the rate limit with the latest sample.
+     */
+    int64_t rateLimit = actualDurationNanos > mTargetDurationNanos ? mPreferredRateNanos
+                                                                   : 10 * mPreferredRateNanos;
+    if (now - mLastUpdateTimestamp <= rateLimit) return 0;
+
+    binder::Status ret =
+            mHintSession->reportActualWorkDuration(mActualDurationsNanos, mTimestampsNanos);
+    mActualDurationsNanos.clear();
+    mTimestampsNanos.clear();
+    if (!ret.isOk()) {
+        ALOGE("%s: HintSession reportActualWorkDuration failed: %s", __FUNCTION__,
+              ret.exceptionMessage().c_str());
+        return EPIPE;
+    }
+    mLastUpdateTimestamp = now;
+    return 0;
+}
+
+// ===================================== C API
+APerformanceHintManager* APerformanceHint_getManager() {
+    return APerformanceHintManager::getInstance();
+}
+
+APerformanceHintSession* APerformanceHint_createSession(APerformanceHintManager* manager,
+                                                        const int32_t* threadIds, size_t size,
+                                                        int64_t initialTargetWorkDurationNanos) {
+    return manager->createSession(threadIds, size, initialTargetWorkDurationNanos);
+}
+
+int64_t APerformanceHint_getPreferredUpdateRateNanos(APerformanceHintManager* manager) {
+    return manager->getPreferredRateNanos();
+}
+
+int APerformanceHint_updateTargetWorkDuration(APerformanceHintSession* session,
+                                              int64_t targetDurationNanos) {
+    return session->updateTargetWorkDuration(targetDurationNanos);
+}
+
+int APerformanceHint_reportActualWorkDuration(APerformanceHintSession* session,
+                                              int64_t actualDurationNanos) {
+    return session->reportActualWorkDuration(actualDurationNanos);
+}
+
+void APerformanceHint_closeSession(APerformanceHintSession* session) {
+    delete session;
+}
+
+void APerformanceHint_setIHintManagerForTesting(void* iManager) {
+    delete gHintManagerForTesting;
+    gHintManagerForTesting = nullptr;
+    gIHintManagerForTesting = static_cast<IHintManager*>(iManager);
+}
diff --git a/native/android/tests/performance_hint/Android.bp b/native/android/tests/performance_hint/Android.bp
new file mode 100644
index 0000000..fdc1bc6
--- /dev/null
+++ b/native/android/tests/performance_hint/Android.bp
@@ -0,0 +1,65 @@
+// 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 {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+cc_test {
+    name: "PerformanceHintNativeTestCases",
+
+    multilib: {
+        lib32: {
+            suffix: "32",
+        },
+        lib64: {
+            suffix: "64",
+        },
+    },
+
+    srcs: ["PerformanceHintNativeTest.cpp"],
+
+    shared_libs: [
+        "libandroid",
+        "liblog",
+        "libbinder",
+        "libpowermanager",
+        "libutils",
+    ],
+
+    static_libs: [
+        "libbase",
+        "libgmock",
+        "libgtest",
+    ],
+    stl: "c++_shared",
+
+    test_suites: [
+        "device-tests",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    header_libs: [
+        "libandroid_headers_private",
+    ],
+}
diff --git a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
new file mode 100644
index 0000000..284e9ee
--- /dev/null
+++ b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "PerformanceHintNativeTest"
+
+#include <android/os/IHintManager.h>
+#include <android/os/IHintSession.h>
+#include <binder/IBinder.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <performance_hint_private.h>
+#include <memory>
+#include <vector>
+
+using android::binder::Status;
+using android::os::IHintManager;
+using android::os::IHintSession;
+
+using namespace android;
+using namespace testing;
+
+class MockIHintManager : public IHintManager {
+public:
+    MOCK_METHOD(Status, createHintSession,
+                (const ::android::sp<::android::IBinder>& token, const ::std::vector<int32_t>& tids,
+                 int64_t durationNanos, ::android::sp<::android::os::IHintSession>* _aidl_return),
+                (override));
+    MOCK_METHOD(Status, getHintSessionPreferredRate, (int64_t * _aidl_return), (override));
+    MOCK_METHOD(IBinder*, onAsBinder, (), (override));
+};
+
+class MockIHintSession : public IHintSession {
+public:
+    MOCK_METHOD(Status, updateTargetWorkDuration, (int64_t targetDurationNanos), (override));
+    MOCK_METHOD(Status, reportActualWorkDuration,
+                (const ::std::vector<int64_t>& actualDurationNanos,
+                 const ::std::vector<int64_t>& timeStampNanos),
+                (override));
+    MOCK_METHOD(Status, close, (), (override));
+    MOCK_METHOD(IBinder*, onAsBinder, (), (override));
+};
+
+class PerformanceHintTest : public Test {
+public:
+    void SetUp() override {
+        mMockIHintManager = new StrictMock<MockIHintManager>();
+        APerformanceHint_setIHintManagerForTesting(mMockIHintManager);
+    }
+
+    void TearDown() override {
+        mMockIHintManager = nullptr;
+        // Destroys MockIHintManager.
+        APerformanceHint_setIHintManagerForTesting(nullptr);
+    }
+
+    APerformanceHintManager* createManager() {
+        EXPECT_CALL(*mMockIHintManager, getHintSessionPreferredRate(_))
+                .Times(Exactly(1))
+                .WillRepeatedly(DoAll(SetArgPointee<0>(123L), Return(Status())));
+        return APerformanceHint_getManager();
+    }
+
+    StrictMock<MockIHintManager>* mMockIHintManager = nullptr;
+};
+
+TEST_F(PerformanceHintTest, TestGetPreferredUpdateRateNanos) {
+    APerformanceHintManager* manager = createManager();
+    int64_t preferredUpdateRateNanos = APerformanceHint_getPreferredUpdateRateNanos(manager);
+    EXPECT_EQ(123L, preferredUpdateRateNanos);
+}
+
+TEST_F(PerformanceHintTest, TestSession) {
+    APerformanceHintManager* manager = createManager();
+
+    std::vector<int32_t> tids;
+    tids.push_back(1);
+    tids.push_back(2);
+    int64_t targetDuration = 56789L;
+
+    StrictMock<MockIHintSession>* iSession = new StrictMock<MockIHintSession>();
+    sp<IHintSession> session_sp(iSession);
+
+    EXPECT_CALL(*mMockIHintManager, createHintSession(_, Eq(tids), Eq(targetDuration), _))
+            .Times(Exactly(1))
+            .WillRepeatedly(DoAll(SetArgPointee<3>(std::move(session_sp)), Return(Status())));
+
+    APerformanceHintSession* session =
+            APerformanceHint_createSession(manager, tids.data(), tids.size(), targetDuration);
+    ASSERT_TRUE(session);
+
+    int64_t targetDurationNanos = 10;
+    EXPECT_CALL(*iSession, updateTargetWorkDuration(Eq(targetDurationNanos))).Times(Exactly(1));
+    int result = APerformanceHint_updateTargetWorkDuration(session, targetDurationNanos);
+    EXPECT_EQ(0, result);
+
+    usleep(2); // Sleep for longer than preferredUpdateRateNanos.
+    int64_t actualDurationNanos = 20;
+    std::vector<int64_t> actualDurations;
+    actualDurations.push_back(20);
+    EXPECT_CALL(*iSession, reportActualWorkDuration(Eq(actualDurations), _)).Times(Exactly(1));
+    result = APerformanceHint_reportActualWorkDuration(session, actualDurationNanos);
+    EXPECT_EQ(0, result);
+
+    result = APerformanceHint_updateTargetWorkDuration(session, -1L);
+    EXPECT_EQ(EINVAL, result);
+    result = APerformanceHint_reportActualWorkDuration(session, -1L);
+    EXPECT_EQ(EINVAL, result);
+
+    EXPECT_CALL(*iSession, close()).Times(Exactly(1));
+    APerformanceHint_closeSession(session);
+}
diff --git a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
index f04b0e3..266fc78 100644
--- a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
+++ b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
@@ -267,26 +267,22 @@
 
     private static void startLottieAnimationWith(LottieAnimationView illustrationView,
             Uri imageUri) {
-        try {
-            final InputStream inputStream =
-                    getInputStreamFromUri(illustrationView.getContext(), imageUri);
-            illustrationView.setAnimation(inputStream, /* cacheKey= */ null);
-            illustrationView.setRepeatCount(LottieDrawable.INFINITE);
-            illustrationView.playAnimation();
-        } catch (IllegalStateException e) {
-            Log.w(TAG, "Invalid illustration image uri: " + imageUri, e);
-        }
+        final InputStream inputStream =
+                getInputStreamFromUri(illustrationView.getContext(), imageUri);
+        illustrationView.setFailureListener(
+                result -> Log.w(TAG, "Invalid illustration image uri: " + imageUri, result));
+        illustrationView.setAnimation(inputStream, /* cacheKey= */ null);
+        illustrationView.setRepeatCount(LottieDrawable.INFINITE);
+        illustrationView.playAnimation();
     }
 
     private static void startLottieAnimationWith(LottieAnimationView illustrationView,
             @RawRes int rawRes) {
-        try {
-            illustrationView.setAnimation(rawRes);
-            illustrationView.setRepeatCount(LottieDrawable.INFINITE);
-            illustrationView.playAnimation();
-        } catch (IllegalStateException e) {
-            Log.w(TAG, "Invalid illustration resource id: " + rawRes, e);
-        }
+        illustrationView.setFailureListener(
+                result -> Log.w(TAG, "Invalid illustration resource id: " + rawRes, result));
+        illustrationView.setAnimation(rawRes);
+        illustrationView.setRepeatCount(LottieDrawable.INFINITE);
+        illustrationView.playAnimation();
     }
 
     private static void resetAnimations(LottieAnimationView illustrationView) {
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 710ca32..08ca17f 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -172,7 +172,7 @@
     <string name="tts_engine_security_warning" msgid="3372432853837988146">"Гэты модуль сінтэзу гаворкі можа збіраць увесь тэкст, які будзе прамоўлены, у тым ліку асабістыя дадзеныя, напрыклад паролі і нумары крэдытных карт. Ён адносіцца да модуля <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Уключыць гэты модуль сінтэзу гаворкі?"</string>
     <string name="tts_engine_network_required" msgid="8722087649733906851">"Гэта мова патрабуе актыўнага падключэння да сеткі, каб выконваць функцыю прамаўлення тэксту."</string>
     <string name="tts_default_sample_string" msgid="6388016028292967973">"Гэта прыклад сінтэзу гаворкі"</string>
-    <string name="tts_status_title" msgid="8190784181389278640">"Статус мовы па змаўчанні"</string>
+    <string name="tts_status_title" msgid="8190784181389278640">"Статус стандартнай мовы"</string>
     <string name="tts_status_ok" msgid="8583076006537547379">"<xliff:g id="LOCALE">%1$s</xliff:g> цалкам падтрымліваецца"</string>
     <string name="tts_status_requires_network" msgid="8327617638884678896">"Для <xliff:g id="LOCALE">%1$s</xliff:g> патрабуецца падлучэнне да сеткі"</string>
     <string name="tts_status_not_supported" msgid="2702997696245523743">"<xliff:g id="LOCALE">%1$s</xliff:g> не падтрымліваецца"</string>
@@ -388,7 +388,7 @@
     <string name="local_backup_password_toast_validation_failure" msgid="714669442363647122">"Збой пры ўсталёўцы паролю для рэзервовага капіявання"</string>
     <string name="loading_injected_setting_summary" msgid="8394446285689070348">"Ідзе загрузка…"</string>
   <string-array name="color_mode_names">
-    <item msgid="3836559907767149216">"Сочны (па змаўчанні)"</item>
+    <item msgid="3836559907767149216">"Насычаны (стандартна)"</item>
     <item msgid="9112200311983078311">"Натуральныя"</item>
     <item msgid="6564241960833766170">"Стандартны"</item>
   </string-array>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 8052e2a..ac078fd 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -85,7 +85,7 @@
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"મીડિયા ઑડિયો"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ફોન કૉલ"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ફાઇલ સ્થાનાંતરણ"</string>
-    <string name="bluetooth_profile_hid" msgid="2969922922664315866">"ઇનપુટ ઉપકરણ"</string>
+    <string name="bluetooth_profile_hid" msgid="2969922922664315866">"ઇનપુટ ડિવાઇસ"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"ઇન્ટરનેટ ઍક્સેસ"</string>
     <string name="bluetooth_profile_pbap" msgid="7064307749579335765">"સંપર્ક શેરિંગ"</string>
     <string name="bluetooth_profile_pbap_summary" msgid="2955819694801952056">"સંપર્ક શેરિંગ માટે ઉપયોગ કરો"</string>
@@ -102,7 +102,7 @@
     <string name="bluetooth_map_profile_summary_connected" msgid="4141725591784669181">"નકશા સાથે કનેક્ટ થયું"</string>
     <string name="bluetooth_sap_profile_summary_connected" msgid="1280297388033001037">"SAP થી કનેક્ટ કરેલ"</string>
     <string name="bluetooth_opp_profile_summary_not_connected" msgid="3959741824627764954">"ફાઇલ સ્થાનાંતરણ સેવાથી કનેક્ટ થયેલ નથી"</string>
-    <string name="bluetooth_hid_profile_summary_connected" msgid="3923653977051684833">"ઇનપુટ ઉપકરણ સાથે કનેક્ટ થયાં"</string>
+    <string name="bluetooth_hid_profile_summary_connected" msgid="3923653977051684833">"ઇનપુટ ડિવાઇસ સાથે કનેક્ટ થયાં"</string>
     <string name="bluetooth_pan_user_profile_summary_connected" msgid="380469653827505727">"ઇન્ટરનેટ ઍક્સેસ માટે ઉપકરણથી કનેક્ટેડ છીએ"</string>
     <string name="bluetooth_pan_nap_profile_summary_connected" msgid="3744773111299503493">"ઉપકરણ સાથે સ્થાનિક ઇન્ટરનેટ કનેક્શન શેર કરી રહ્યાં છીએ"</string>
     <string name="bluetooth_pan_profile_summary_use_for" msgid="7422039765025340313">"ઇન્ટરનેટ ઍક્સેસ માટે ઉપયોગ કરો"</string>
@@ -155,7 +155,7 @@
     <string name="running_process_item_user_label" msgid="3988506293099805796">"વપરાશકર્તા: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
     <string name="launch_defaults_some" msgid="3631650616557252926">"કેટલાંક ડિફોલ્ટ્સ સેટ કરેલ છે"</string>
     <string name="launch_defaults_none" msgid="8049374306261262709">"કોઈ ડિફૉલ્ટ સેટ કરેલા નથી"</string>
-    <string name="tts_settings" msgid="8130616705989351312">"ટેક્સ્ટ-ટુ-સ્પીચ સેટિંગ્સ"</string>
+    <string name="tts_settings" msgid="8130616705989351312">"ટેક્સ્ટ ટૂ સ્પીચ સેટિંગ"</string>
     <string name="tts_settings_title" msgid="7602210956640483039">"ટેક્સ્ટ ટુ સ્પીચ આઉટપુટ"</string>
     <string name="tts_default_rate_title" msgid="3964187817364304022">"વાણી દર"</string>
     <string name="tts_default_rate_summary" msgid="3781937042151716987">"ટેક્સ્ટ બોલાયેલ છે તે ઝડપ"</string>
@@ -177,8 +177,8 @@
     <string name="tts_status_requires_network" msgid="8327617638884678896">"<xliff:g id="LOCALE">%1$s</xliff:g> નેટવર્ક કનેક્શનની આવશ્યકતા છે"</string>
     <string name="tts_status_not_supported" msgid="2702997696245523743">"<xliff:g id="LOCALE">%1$s</xliff:g> સમર્થિત નથી"</string>
     <string name="tts_status_checking" msgid="8026559918948285013">"તપાસી રહ્યું છે..."</string>
-    <string name="tts_engine_settings_title" msgid="7849477533103566291">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> માટેની સેટિંગ્સ"</string>
-    <string name="tts_engine_settings_button" msgid="477155276199968948">"એન્જિન સેટિંગ્સ લોંચ કરો"</string>
+    <string name="tts_engine_settings_title" msgid="7849477533103566291">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> માટેના સેટિંગ"</string>
+    <string name="tts_engine_settings_button" msgid="477155276199968948">"એન્જિન સેટિંગ લૉન્ચ કરો"</string>
     <string name="tts_engine_preference_section_title" msgid="3861562305498624904">"મનપસંદ એન્જિન"</string>
     <string name="tts_general_section_title" msgid="8919671529502364567">"સામાન્ય"</string>
     <string name="tts_reset_speech_pitch_title" msgid="7149398585468413246">"સ્પીચની પિચ ફરીથી સેટ કરો"</string>
@@ -201,9 +201,9 @@
     <string name="development_settings_enable" msgid="4285094651288242183">"વિકાસકર્તાનાં વિકલ્પો સક્ષમ કરો"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"ઍપ્લિકેશન વિકાસ માટે વિકલ્પો સેટ કરો"</string>
     <string name="development_settings_not_available" msgid="355070198089140951">"આ વપરાશકર્તા માટે વિકાસકર્તા વિકલ્પો ઉપલબ્ધ નથી"</string>
-    <string name="vpn_settings_not_available" msgid="2894137119965668920">"આ વપરાશકર્તા માટે VPN સેટિંગ્સ ઉપલબ્ધ નથી"</string>
-    <string name="tethering_settings_not_available" msgid="266821736434699780">"આ વપરાશકર્તા માટે ટિથરિંગ સેટિંગ્સ ઉપલબ્ધ નથી"</string>
-    <string name="apn_settings_not_available" msgid="1147111671403342300">"અ‍ૅક્સેસ પોઇન્ટનું નામ સેટિંગ્સ આ વપરાશકર્તા માટે ઉપલબ્ધ નથી"</string>
+    <string name="vpn_settings_not_available" msgid="2894137119965668920">"આ વપરાશકર્તા માટે VPN સેટિંગ ઉપલબ્ધ નથી"</string>
+    <string name="tethering_settings_not_available" msgid="266821736434699780">"આ વપરાશકર્તા માટે ટિથરિંગ સેટિંગ ઉપલબ્ધ નથી"</string>
+    <string name="apn_settings_not_available" msgid="1147111671403342300">"અ‍ૅક્સેસ પૉઇન્ટનું નામ સેટિંગ આ વપરાશકર્તા માટે ઉપલબ્ધ નથી"</string>
     <string name="enable_adb" msgid="8072776357237289039">"USB ડિબગીંગ"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"જ્યારે USB કનેક્ટ કરેલું હોય ત્યારે ડિબગ મોડ"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"USB ડીબગિંગ પ્રમાણીકરણોને રદબાતલ કરો"</string>
@@ -259,7 +259,7 @@
     <string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"ચોક્કસ વૉલ્યૂમને બંધ કરો"</string>
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche ચાલુ કરો"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"બ્લૂટૂથ AVRCP વર્ઝન"</string>
-    <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"બ્લૂટૂથ AVRCP સંસ્કરણ પસંદ કરો"</string>
+    <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"બ્લૂટૂથ AVRCP વર્ઝન પસંદ કરો"</string>
     <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"બ્લૂટૂથ MAP વર્ઝન"</string>
     <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"બ્લૂટૂથ MAP વર્ઝન પસંદ કરો"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"બ્લૂટૂથ ઑડિયો કોડેક"</string>
@@ -301,12 +301,12 @@
     <string name="mobile_data_always_on_summary" msgid="1112156365594371019">"વાઇ-ફાઇ  સક્રિય હોય ત્યારે પણ, હંમેશા મોબાઇલ ડેટાને સક્રિય રાખો (ઝડપી નેટવર્ક સ્વિચિંગ માટે)."</string>
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"જો ટિથરિંગ માટે હાર્ડવેર ગતિવૃદ્ધિ ઉપલબ્ધ હોય તો તેનો ઉપયોગ કરો"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"USB ડિબગિંગને મંજૂરી આપીએ?"</string>
-    <string name="adb_warning_message" msgid="8145270656419669221">"USB ડિબગીંગ ફક્ત વિકાસ હેતુઓ માટે જ બનાવાયેલ છે. તેનો ઉપયોગ તમારા કમ્પ્યુટર અને તમારા ઉપકરણ વચ્ચે ડેટાને કૉપિ કરવા, નોટિફિકેશન વગર તમારા ઉપકરણ પર ઍપ્લિકેશનો ઇન્સ્ટોલ કરવા અને લૉગ ડેટા વાંચવા માટે કરો."</string>
+    <string name="adb_warning_message" msgid="8145270656419669221">"USB ડિબગીંગ ફક્ત વિકાસ હેતુઓ માટે જ બનાવાયેલ છે. તેનો ઉપયોગ તમારા કમ્પ્યુટર અને તમારા ડિવાઇસ વચ્ચે ડેટાને કૉપિ કરવા, નોટિફિકેશન વગર તમારા ડિવાઇસ પર ઍપ ઇન્સ્ટોલ કરવા અને લૉગ ડેટા વાંચવા માટે કરો."</string>
     <string name="adbwifi_warning_title" msgid="727104571653031865">"વાયરલેસ ડિબગીંગને મંજૂરી આપીએ?"</string>
     <string name="adbwifi_warning_message" msgid="8005936574322702388">"વાયરલેસ ડિબગીંગ ફક્ત ડેવલપમેન્ટના હેતુઓ માટે જ બનાવાયું છે. તેનો ઉપયોગ તમારા કમ્પ્યુટર અને તમારા ડિવાઇસ વચ્ચે ડેટાને કૉપિ કરવા, નોટિફિકેશન વગર તમારા ડિવાઇસ પર ઍપને ઇન્સ્ટૉલ કરવા અને લૉગ ડેટા વાંચવા માટે કરો."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"તમે અગાઉ અધિકૃત કરેલા તમામ કમ્પ્યુટર્સમાંથી USB ડિબગિંગ પરની અ‍ૅક્સેસ રદબાતલ કરીએ?"</string>
-    <string name="dev_settings_warning_title" msgid="8251234890169074553">"વિકાસ સેટિંગ્સને મંજૂરી આપીએ?"</string>
-    <string name="dev_settings_warning_message" msgid="37741686486073668">"આ સેટિંગ્સ ફક્ત વિકાસનાં ઉપયોગ માટે જ હેતુબદ્ધ છે. તે તમારા ઉપકરણ અને તેના પરની એપ્લિકેશન્સનાં ભંગ થવા અથવા ખરાબ વર્તનનું કારણ બની શકે છે."</string>
+    <string name="dev_settings_warning_title" msgid="8251234890169074553">"ડેવલપમેન્ટ સેટિંગને મંજૂરી આપીએ?"</string>
+    <string name="dev_settings_warning_message" msgid="37741686486073668">"આ સેટિંગ ફક્ત વિકાસનાં ઉપયોગ માટે જ હેતુબદ્ધ છે. તે તમારા ડિવાઇસ અને તેના પરની ઍપના ભંગ થવા અથવા ખરાબ વર્તનનું કારણ બની શકે છે."</string>
     <string name="verify_apps_over_usb_title" msgid="6031809675604442636">"USB પર ઍપ ચકાસો"</string>
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"હાનિકારક વર્તણૂંક માટે ADB/ADT મારફતે ઇન્સ્ટોલ કરવામાં આવેલી ઍપ તપાસો."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"નામ વગરના (ફક્ત MAC ઍડ્રેસવાળા) બ્લૂટૂથ ડિવાઇસ બતાવવામાં આવશે"</string>
@@ -468,7 +468,7 @@
     <string name="external_source_trusted" msgid="1146522036773132905">"મંજૂરી છે"</string>
     <string name="external_source_untrusted" msgid="5037891688911672227">"મંજૂરી નથી"</string>
     <string name="install_other_apps" msgid="3232595082023199454">"અજાણી ઍપ ઇન્સ્ટૉલ કરો"</string>
-    <string name="home" msgid="973834627243661438">"સેટિંગ્સ હોમ"</string>
+    <string name="home" msgid="973834627243661438">"સેટિંગ હોમ"</string>
   <string-array name="battery_labels">
     <item msgid="7878690469765357158">"0%"</item>
     <item msgid="8894873528875953317">"50%"</item>
@@ -488,7 +488,7 @@
     <string name="retail_demo_reset_title" msgid="1866911701095959800">"પાસવર્ડ આવશ્યક છે"</string>
     <string name="active_input_method_subtypes" msgid="4232680535471633046">"ઇનપુટ પદ્ધતિઓ સક્રિય કરો"</string>
     <string name="use_system_language_to_select_input_method_subtypes" msgid="4865195835541387040">"સિસ્ટમ ભાષાઓનો ઉપયોગ કરો"</string>
-    <string name="failed_to_open_app_settings_toast" msgid="764897252657692092">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> માટેની સેટિંગ્સ ખોલવામાં નિષ્ફળ"</string>
+    <string name="failed_to_open_app_settings_toast" msgid="764897252657692092">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> માટેના સેટિંગ ખોલવામાં નિષ્ફળ"</string>
     <string name="ime_security_warning" msgid="6547562217880551450">"આ ઇનપુટ પદ્ધતિ પાસવર્ડ્સ અને ક્રેડિટ કાર્ડ નંબર જેવી વ્યક્તિગત માહિતી સહિત તમે લખો છો તે તમામ ટેક્સ્ટ એકત્રિત કરવા માટે સક્ષમ હોઈ શકે છે. તે ઍપ્લિકેશન <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> માંથી આવે છે. આ ઇનપુટ પદ્ધતિ વાપરીએ?"</string>
     <string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"નોંધ: રીબૂટ કર્યાં પછી, જ્યાં સુધી તમે તમારો ફોન અનલૉક કરશો નહીં ત્યાં સુધી આ ઍપ્લિકેશન શરૂ થઈ શકશે નહીં"</string>
     <string name="ims_reg_title" msgid="8197592958123671062">"IMS રજિસ્ટ્રેશનની સ્થિતિ"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 5ac22ff..2576993 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -155,8 +155,8 @@
     <string name="running_process_item_user_label" msgid="3988506293099805796">"Хэрэглэгч: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
     <string name="launch_defaults_some" msgid="3631650616557252926">"Зарим үндсэн тохиргоонуудыг суулгасан"</string>
     <string name="launch_defaults_none" msgid="8049374306261262709">"Ямар ч үндсэн тохиргоог суулгаагүй байна"</string>
-    <string name="tts_settings" msgid="8130616705989351312">"Текст-ярианы тохиргоо"</string>
-    <string name="tts_settings_title" msgid="7602210956640483039">"Текстийг яриа болгон гаргах"</string>
+    <string name="tts_settings" msgid="8130616705989351312">"Бичвэрийг ярианд хувиргах тохиргоо"</string>
+    <string name="tts_settings_title" msgid="7602210956640483039">"Бичвэрийг ярианд хувиргах"</string>
     <string name="tts_default_rate_title" msgid="3964187817364304022">"Ярианы түвшин"</string>
     <string name="tts_default_rate_summary" msgid="3781937042151716987">"Текстийг унших хурд"</string>
     <string name="tts_default_pitch_title" msgid="6988592215554485479">"Авиа тон"</string>
@@ -170,7 +170,7 @@
     <string name="tts_install_data_title" msgid="1829942496472751703">"Хоолойн өгөгдлийг суулгах"</string>
     <string name="tts_install_data_summary" msgid="3608874324992243851">"Яриа үүсгэхэд шаардлагатай дууны өгөгдлийг суулгах"</string>
     <string name="tts_engine_security_warning" msgid="3372432853837988146">"Энэ яриа үүсгүүр нь нууц үг, зээлийн картын дугаар гэх мэт таны хувийн мэдээллийг оруулан унших бүх текстийг цуглуулах боломжтой. Үүнийг <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> үүсгүүрээс нийлүүлдэг. Энэ яриа үүсгүүрийн ашиглалтыг идэвхжүүлэх үү?"</string>
-    <string name="tts_engine_network_required" msgid="8722087649733906851">"Энэ хэл нь текстээс дуунд хөрвүүлэхэд ажлын сүлжээний холболтыг шаарддаг."</string>
+    <string name="tts_engine_network_required" msgid="8722087649733906851">"Энэ хэл нь бичвэрийг ярианд хувиргахад ажлын сүлжээний холболт шаардана."</string>
     <string name="tts_default_sample_string" msgid="6388016028292967973">"Энэ бол яриа үүсгэх жишээ юм."</string>
     <string name="tts_status_title" msgid="8190784181389278640">"Үндсэн хэлний статус"</string>
     <string name="tts_status_ok" msgid="8583076006537547379">"<xliff:g id="LOCALE">%1$s</xliff:g> бүрэн дэмжигдсэн"</string>
diff --git a/packages/SettingsLib/res/values-pl/arrays.xml b/packages/SettingsLib/res/values-pl/arrays.xml
index db621be..22b0539 100644
--- a/packages/SettingsLib/res/values-pl/arrays.xml
+++ b/packages/SettingsLib/res/values-pl/arrays.xml
@@ -247,7 +247,7 @@
     <item msgid="5023908510820531131">"W: <xliff:g id="AS_TYPED_COMMAND">adb shell dumpsys gfxinfo</xliff:g>"</item>
   </string-array>
   <string-array name="debug_hw_overdraw_entries">
-    <item msgid="1968128556747588800">"Wył."</item>
+    <item msgid="1968128556747588800">"Wyłączone"</item>
     <item msgid="3033215374382962216">"Pokaż przerysowywane obszary"</item>
     <item msgid="3474333938380896988">"Pokaż obszary dostosowane do deuteranomalii"</item>
   </string-array>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 490d3aa..055760d 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -88,8 +88,8 @@
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Vnosna naprava"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internetni dostop"</string>
     <string name="bluetooth_profile_pbap" msgid="7064307749579335765">"Deljenje stikov"</string>
-    <string name="bluetooth_profile_pbap_summary" msgid="2955819694801952056">"Uporabi za dajanje stikov v skupno rabo"</string>
-    <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Skupna raba internetne povezave"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="2955819694801952056">"Uporabi za deljenje stikov"</string>
+    <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Deljenje internetne povezave"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Sporočila SMS"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Dostop do kartice SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"Zvok visoke kakovosti: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
@@ -104,7 +104,7 @@
     <string name="bluetooth_opp_profile_summary_not_connected" msgid="3959741824627764954">"Povezava s strežnikom za prenos datotek ni vzpostavljena"</string>
     <string name="bluetooth_hid_profile_summary_connected" msgid="3923653977051684833">"Povezava z vnosno napravo je vzpostavljena"</string>
     <string name="bluetooth_pan_user_profile_summary_connected" msgid="380469653827505727">"Povezava z napravo za internetni dostop"</string>
-    <string name="bluetooth_pan_nap_profile_summary_connected" msgid="3744773111299503493">"Skupna raba lok. internetne povezave z napravo"</string>
+    <string name="bluetooth_pan_nap_profile_summary_connected" msgid="3744773111299503493">"Deljenje lok. internetne povezave z napravo"</string>
     <string name="bluetooth_pan_profile_summary_use_for" msgid="7422039765025340313">"Uporabi za dostop do interneta"</string>
     <string name="bluetooth_map_profile_summary_use_for" msgid="4453622103977592583">"Uporabi za zemljevid"</string>
     <string name="bluetooth_sap_profile_summary_use_for" msgid="6204902866176714046">"Uporablja se za dostop do kartice SIM"</string>
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java
index ea9be04..9e3312a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java
@@ -18,6 +18,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
@@ -130,4 +132,27 @@
 
         verify(drawable).start();
     }
+
+    @Test
+    public void playLottieAnimationWithUri_verifyFailureListener() {
+        doReturn(null).when(mAnimationView).getDrawable();
+
+        mPreference.setImageUri(mImageUri);
+        mPreference.onBindViewHolder(mViewHolder);
+
+        verify(mAnimationView).setFailureListener(any());
+    }
+
+    @Test
+    public void playLottieAnimationWithResource_verifyFailureListener() {
+        // fake the valid lottie image
+        final int fakeValidResId = 111;
+        doNothing().when(mAnimationView).setImageResource(fakeValidResId);
+        doReturn(null).when(mAnimationView).getDrawable();
+
+        mPreference.setLottieAnimationResId(fakeValidResId);
+        mPreference.onBindViewHolder(mViewHolder);
+
+        verify(mAnimationView).setFailureListener(any());
+    }
 }
diff --git a/packages/SettingsProvider/res/values-gu/strings.xml b/packages/SettingsProvider/res/values-gu/strings.xml
index 1f91f71..dded10e 100644
--- a/packages/SettingsProvider/res/values-gu/strings.xml
+++ b/packages/SettingsProvider/res/values-gu/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4567566098528588863">"સેટિંગ્સ સંગ્રહ"</string>
+    <string name="app_label" msgid="4567566098528588863">"સેટિંગ સ્ટોરેજ"</string>
     <string name="wifi_softap_config_change" msgid="5688373762357941645">"હૉટસ્પૉટ સેટિંગ બદલાઈ ગઈ છે"</string>
     <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"વિગતો જોવા માટે ટૅપ કરો"</string>
 </resources>
diff --git a/packages/Shell/res/values-mr/strings.xml b/packages/Shell/res/values-mr/strings.xml
index 3842733..8297488 100644
--- a/packages/Shell/res/values-mr/strings.xml
+++ b/packages/Shell/res/values-mr/strings.xml
@@ -31,7 +31,7 @@
     <string name="bugreport_confirm" msgid="5917407234515812495">"बग रीपोर्टांमध्ये तुम्ही संवेदनशील (अ‍ॅप-वापर आणि स्थान डेटा यासारखा) डेटा म्हणून विचार करता त्या डेटाच्या समावेशासह सिस्टीमच्या विविध लॉग फायलींमधील डेटा असतो. ज्या लोकांवर आणि अ‍ॅपवर तुमचा विश्वास आहे केवळ त्यांच्यासह हा बग रीपोर्ट शेअर करा."</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"पुन्हा दर्शवू नका"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"बग रीपोर्ट"</string>
-    <string name="bugreport_unreadable_text" msgid="586517851044535486">"बग रिपोर्ट फाइल वाचणे शक्य झाले नाही"</string>
+    <string name="bugreport_unreadable_text" msgid="586517851044535486">"बग अहवाल फाइल वाचणे शक्य झाले नाही"</string>
     <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"झिप फाइल मध्ये बग रिपोर्ट तपशील जोडणे शक्य झाले नाही"</string>
     <string name="bugreport_unnamed" msgid="2800582406842092709">"अनामित"</string>
     <string name="bugreport_info_action" msgid="2158204228510576227">"तपशील"</string>
diff --git a/packages/Shell/res/values-sl/strings.xml b/packages/Shell/res/values-sl/strings.xml
index 1fc27ca..76702d6 100644
--- a/packages/Shell/res/values-sl/strings.xml
+++ b/packages/Shell/res/values-sl/strings.xml
@@ -24,7 +24,7 @@
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Počakajte ..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"Poročilo o napakah bo kmalu prikazano v telefonu"</string>
     <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"Izberite za pošiljanje poročila o napakah"</string>
-    <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Dotaknite se, če želite poročilo o napaki dati v skupno rabo"</string>
+    <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Dotaknite se, če želite deliti poročilo o napaki"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Izberite za pošiljanje poročila o napakah brez posnetka zaslona ali počakajte, da se ta dokonča"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Dotaknite se za pošiljanje poročila o napakah brez posnetka zaslona ali počakajte, da se ta dokonča"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Dotaknite se za pošiljanje poročila o napakah brez posnetka zaslona ali počakajte, da se ta dokonča"</string>
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
index bd2209b..0424382 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
@@ -52,13 +52,6 @@
     void setListening(boolean listening);
     boolean isShowingDetail();
     void closeDetail();
-
-    /**
-     * Set that we're currently pulse expanding
-     *
-     * @param pulseExpanding if we're currently expanding during pulsing
-     */
-    default void setPulseExpanding(boolean pulseExpanding) {}
     void animateHeaderSlidingOut();
     void setQsExpansion(float qsExpansionFraction, float headerTranslation);
     void setHeaderListening(boolean listening);
diff --git a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
index 1abd393..009b7cb 100644
--- a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
@@ -74,7 +74,7 @@
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Disable eSIM to use device without mobile service."</string>
     <string name="kg_pin_instructions" msgid="822353548385014361">"Enter PIN"</string>
     <string name="kg_password_instructions" msgid="324455062831719903">"Enter Password"</string>
-    <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM is now disabled. Enter PUK code to continue. Contact carrier for details."</string>
+    <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM is now disabled. Enter PUK code to continue. Contact operator for details."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" is now disabled. Enter PUK code to continue. Contact operator for details."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Enter desired PIN code"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="4261064020391799132">"Confirm desired PIN code"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
index c3e8e61..21f32cf 100644
--- a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
@@ -74,7 +74,7 @@
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Disable eSIM to use device without mobile service."</string>
     <string name="kg_pin_instructions" msgid="822353548385014361">"Enter PIN"</string>
     <string name="kg_password_instructions" msgid="324455062831719903">"Enter Password"</string>
-    <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM is now disabled. Enter PUK code to continue. Contact carrier for details."</string>
+    <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM is now disabled. Enter PUK code to continue. Contact operator for details."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" is now disabled. Enter PUK code to continue. Contact operator for details."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Enter desired PIN code"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="4261064020391799132">"Confirm desired PIN code"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
index 1abd393..009b7cb 100644
--- a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
@@ -74,7 +74,7 @@
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Disable eSIM to use device without mobile service."</string>
     <string name="kg_pin_instructions" msgid="822353548385014361">"Enter PIN"</string>
     <string name="kg_password_instructions" msgid="324455062831719903">"Enter Password"</string>
-    <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM is now disabled. Enter PUK code to continue. Contact carrier for details."</string>
+    <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM is now disabled. Enter PUK code to continue. Contact operator for details."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" is now disabled. Enter PUK code to continue. Contact operator for details."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Enter desired PIN code"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="4261064020391799132">"Confirm desired PIN code"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
index 1abd393..009b7cb 100644
--- a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
@@ -74,7 +74,7 @@
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Disable eSIM to use device without mobile service."</string>
     <string name="kg_pin_instructions" msgid="822353548385014361">"Enter PIN"</string>
     <string name="kg_password_instructions" msgid="324455062831719903">"Enter Password"</string>
-    <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM is now disabled. Enter PUK code to continue. Contact carrier for details."</string>
+    <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM is now disabled. Enter PUK code to continue. Contact operator for details."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" is now disabled. Enter PUK code to continue. Contact operator for details."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Enter desired PIN code"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="4261064020391799132">"Confirm desired PIN code"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sv/strings.xml b/packages/SystemUI/res-keyguard/values-sv/strings.xml
index 0b1efa8..fb2571e 100644
--- a/packages/SystemUI/res-keyguard/values-sv/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sv/strings.xml
@@ -61,7 +61,7 @@
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Det gick inte att inaktivera eSIM-kortet på grund av ett fel."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Retur"</string>
     <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Har du glömt ditt grafiska lösenord?"</string>
-    <string name="kg_wrong_pattern" msgid="5907301342430102842">"Fel grafiskt lösenord"</string>
+    <string name="kg_wrong_pattern" msgid="5907301342430102842">"Fel mönster"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Fel lösenord"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Fel pinkod"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="991400408675793914">
@@ -82,7 +82,7 @@
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Ange en pinkod med fyra till åtta siffror."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK-koden ska vara minst åtta siffror."</string>
     <string name="kg_invalid_puk" msgid="1774337070084931186">"Ange rätt PUK-kod. Om försöken upprepas inaktiveras SIM-kortet permanent."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"För många försök med grafiskt lösenord"</string>
+    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"För många försök med mönster"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Du har angett fel pinkod <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. \n\nFörsök igen om <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunder."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Du har angett fel lösenord <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. \n\nFörsök igen om <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunder."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Du har ritat ditt grafiska lösenord fel <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. \n\nFörsök igen om <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunder."</string>
@@ -102,13 +102,13 @@
     <string name="keyguard_carrier_default" msgid="6359808469637388586">"Ingen tjänst."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Byt inmatningsmetod"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Flygplansläge"</string>
-    <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Du måste ange grafiskt lösenord när du har startat om enheten"</string>
+    <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Du måste rita mönster när du har startat om enheten"</string>
     <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Du måste ange pinkod när du har startat om enheten"</string>
     <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Du måste ange lösenord när du har startat om enheten"</string>
-    <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Du måste ange grafiskt lösenord för ytterligare säkerhet"</string>
+    <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Du måste rita mönster för ytterligare säkerhet"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Du måste ange pinkod för ytterligare säkerhet"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Du måste ange lösenord för ytterligare säkerhet"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Du måste ange grafiskt lösenord när du byter profil"</string>
+    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Du måste rita mönster när du byter profil"</string>
     <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Du måste ange pinkod när du byter profil"</string>
     <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Du måste ange lösenord när du byter profil"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Administratören har låst enheten"</string>
diff --git a/packages/SystemUI/res/drawable/controls_icon.xml b/packages/SystemUI/res/drawable/controls_icon.xml
new file mode 100644
index 0000000..f1814a2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/controls_icon.xml
@@ -0,0 +1,25 @@
+<?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
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M12,3L4,9v12h16L20,9l-8,-6zM18,19h-3v-6L9,13v6L6,19v-9l6,-4.5 6,4.5v9z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/wallet_lockscreen_bg.xml b/packages/SystemUI/res/drawable/keyguard_bottom_affordance_bg.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/wallet_lockscreen_bg.xml
rename to packages/SystemUI/res/drawable/keyguard_bottom_affordance_bg.xml
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index 9ce83a7..8dbd59d 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -82,18 +82,32 @@
 
     <ImageView
         android:id="@+id/wallet_button"
-        android:layout_height="@dimen/keyguard_affordance_wallet_height"
-        android:layout_width="@dimen/keyguard_affordance_wallet_width"
+        android:layout_height="@dimen/keyguard_affordance_fixed_height"
+        android:layout_width="@dimen/keyguard_affordance_fixed_width"
         android:layout_gravity="bottom|end"
         android:scaleType="center"
         android:tint="?android:attr/textColorPrimary"
         android:src="@drawable/ic_wallet_lockscreen"
-        android:background="@drawable/wallet_lockscreen_bg"
+        android:background="@drawable/keyguard_bottom_affordance_bg"
         android:layout_marginEnd="@dimen/keyguard_affordance_horizontal_offset"
         android:layout_marginBottom="@dimen/keyguard_affordance_vertical_offset"
         android:contentDescription="@string/accessibility_wallet_button"
         android:visibility="gone" />
 
+    <ImageView
+        android:id="@+id/controls_button"
+        android:layout_height="@dimen/keyguard_affordance_fixed_height"
+        android:layout_width="@dimen/keyguard_affordance_fixed_width"
+        android:layout_gravity="bottom|start"
+        android:scaleType="center"
+        android:tint="?android:attr/textColorPrimary"
+        android:src="@drawable/controls_icon"
+        android:background="@drawable/keyguard_bottom_affordance_bg"
+        android:layout_marginStart="@dimen/keyguard_affordance_horizontal_offset"
+        android:layout_marginBottom="@dimen/keyguard_affordance_vertical_offset"
+        android:contentDescription="@string/quick_controls_title"
+        android:visibility="gone" />
+
     <FrameLayout
         android:id="@+id/overlay_container"
         android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout/qs_carrier.xml b/packages/SystemUI/res/layout/qs_carrier.xml
index d4594d1..a854660 100644
--- a/packages/SystemUI/res/layout/qs_carrier.xml
+++ b/packages/SystemUI/res/layout/qs_carrier.xml
@@ -39,6 +39,13 @@
         android:singleLine="true"
         android:maxEms="7"/>
 
+    <View
+        android:id="@+id/spacer"
+        android:layout_width="@dimen/qs_carrier_margin_width"
+        android:layout_height="match_parent"
+        android:visibility="gone"
+    />
+
     <include
         layout="@layout/mobile_signal_group"
         android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index f9dcd39..f3b8b0b 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -55,7 +55,7 @@
         android:clipChildren="false"
         android:clipToPadding="false"
         android:focusable="true"
-        android:paddingBottom="10dp"
+        android:paddingBottom="24dp"
         android:importantForAccessibility="yes" />
     </RelativeLayout>
 
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 9598e87..3506057 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Dit deblokkeer toegang vir alle programme en dienste wat toegelaat word om jou kamera te gebruik."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Dit deblokkeer toegang vir alle programme en dienste wat toegelaat word om jou kamera of mikrofoon te gebruik."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Toestel"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Swiep op om programme te wissel"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Sleep regs om programme vinnig te wissel"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Wissel oorsig"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Gelaai"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Laai tans"</string>
diff --git a/packages/SystemUI/res/values-af/strings_tv.xml b/packages/SystemUI/res/values-af/strings_tv.xml
index 2e9400e..5420779 100644
--- a/packages/SystemUI/res/values-af/strings_tv.xml
+++ b/packages/SystemUI/res/values-af/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Kennisgewings"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Geen kennisgewings nie"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index d60d082..74009bf 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ይህ ካሜራዎን እንዲጠቀሙ ለተፈቀደላቸው ሁሉም መተግበሪያዎች እና አገልግሎቶች መዳረሻን እገዳ ያነሳል።"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ይህ የእርስዎን ካሜራ ወይም ማይክሮፎን እንዲጠቀሙ የተፈቀደላቸው የሁሉም መተግበሪያዎች እና አገልግሎቶች መዳረሻ እገዳን ያነሳል።"</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"መሣሪያ"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"መተግበሪያዎችን ለመቀየር ወደ ላይ ያንሸራትቱ"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"መተግበሪያዎችን በፍጥነት ለመቀየር ወደ ቀኝ ይጎትቱ"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"አጠቃላይ እይታን ቀያይር"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"ባትሪ ሞልቷል"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"ኃይል በመሙላት ላይ"</string>
diff --git a/packages/SystemUI/res/values-am/strings_tv.xml b/packages/SystemUI/res/values-am/strings_tv.xml
index 71d887d..ede0b78 100644
--- a/packages/SystemUI/res/values-am/strings_tv.xml
+++ b/packages/SystemUI/res/values-am/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"በ<xliff:g id="VPN_APP">%1$s</xliff:g> በኩል"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"ማሳወቂያዎች"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ምንም ማሳወቂያዎች የሉም"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 6195e5f..993ee39 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -441,8 +441,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"يؤدي هذا الخيار إلى إزالة حظر الوصول بالنسبة إلى كل التطبيقات والخدمات المسموح لها باستخدام الكاميرا."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"يؤدي هذا الخيار إلى إزالة حظر الوصول بالنسبة إلى كل التطبيقات والخدمات المسموح لها باستخدام الكاميرا أو الميكروفون."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"الجهاز"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"مرّر سريعًا لأعلى لتبديل التطبيقات"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"اسحب لليسار للتبديل السريع بين التطبيقات"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"تبديل \"النظرة العامة\""</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"تم الشحن"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"جارٍ الشحن"</string>
diff --git a/packages/SystemUI/res/values-ar/strings_tv.xml b/packages/SystemUI/res/values-ar/strings_tv.xml
index 769999f..f6c4aef 100644
--- a/packages/SystemUI/res/values-ar/strings_tv.xml
+++ b/packages/SystemUI/res/values-ar/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"عبر <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"الإشعارات"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ما من إشعارات"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index bc5a91a..20023c0 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"এইটোৱে আপোনাৰ কেমেৰা ব্যৱহাৰ কৰিবলৈ অনুমতি দিয়া আটাইবোৰ এপ্ আৰু সেৱাৰ বাবে এক্সেছ অৱৰোধৰ পৰা আঁতৰায়।"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"এইটোৱে আপোনাৰ কেমেৰা অথবা মাইক্ৰ\'ফ\'ন ব্যৱহাৰ কৰিবলৈ অনুমতি দিয়া আটাইবোৰ এপ্ আৰু সেৱাৰ বাবে এক্সেছ অৱৰোধৰ পৰা আঁতৰায়।"</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"ডিভাইচ"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"আনটো এপ্ ব্য়ৱহাৰ কৰিবলৈ ওপৰলৈ ছোৱাইপ কৰক"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"খৰতকীয়াকৈ আনটো এপ্ ব্য়ৱহাৰ কৰিবলৈ সোঁফালে টানক"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"অৱলোকন ট’গল কৰক"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"চ্চার্জ হ’ল"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"চ্চার্জ হৈ আছে"</string>
diff --git a/packages/SystemUI/res/values-as/strings_tv.xml b/packages/SystemUI/res/values-as/strings_tv.xml
index 859ea2c..6ceee80 100644
--- a/packages/SystemUI/res/values-as/strings_tv.xml
+++ b/packages/SystemUI/res/values-as/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>ৰ জৰিয়তে"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"জাননী"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"কোনো জাননী নাই"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 5479089..71f90fd5 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Kamera və mikrofon istifadə edən bütün tətbiq və xidmətlərə giriş verir."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Kamera və mikrofon istifadə edən bütün tətbiq və xidmətlərə giriş verir."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Cihaz"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Tətbiqi dəyişmək üçün yuxarı sürüşdürün"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Tətbiqləri cəld dəyişmək üçün sağa çəkin"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"İcmala Keçin"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Enerji yığılıb"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Enerji doldurulur"</string>
diff --git a/packages/SystemUI/res/values-az/strings_tv.xml b/packages/SystemUI/res/values-az/strings_tv.xml
index 1f1b649..d141ad6 100644
--- a/packages/SystemUI/res/values-az/strings_tv.xml
+++ b/packages/SystemUI/res/values-az/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> vasitəsilə"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Bildirişlər"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Bildiriş yoxdur"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index d48eebc..7402594 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -435,8 +435,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Ovim će se odblokirati pristup za sve aplikacije i usluge koje imaju dozvolu za korišćenje kamere."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Ovim će se odblokirati pristup za sve aplikacije i usluge koje imaju dozvolu za korišćenje kamere ili mikrofona."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Uređaj"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Prevucite nagore da biste menjali aplikacije"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Prevucite udesno da biste brzo promenili aplikacije"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Uključi/isključi pregled"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Napunjena je"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Puni se"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml b/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml
index 2eaa499..04a7e81 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Preko: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Obaveštenja"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nema obaveštenja"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 491cdcd..7688e06 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -437,8 +437,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Доступ адкрыецца для ўсіх праграм і сэрвісаў, якім дазволена выкарыстоўваць камеру."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Доступ адкрыецца для ўсіх праграм і сэрвісаў, якім дазволена выкарыстоўваць камеру ці мікрафон."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Прылада"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Правядзіце ўверх, каб пераключыць праграмы"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Каб хутка пераключыцца паміж праграмамі, перацягніце ўправа"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Уключыць/выключыць агляд"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Зараджаны"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Зарадка"</string>
diff --git a/packages/SystemUI/res/values-be/strings_tv.xml b/packages/SystemUI/res/values-be/strings_tv.xml
index 21a2e6e..5aa771f 100644
--- a/packages/SystemUI/res/values-be/strings_tv.xml
+++ b/packages/SystemUI/res/values-be/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Праз <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Апавяшчэнні"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Апавяшчэнняў няма"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index da45743..386fbd6 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Това действие отблокира достъпа за всички приложения и услуги, които имат разрешение да използват камерата ви."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Това действие отблокира достъпа за всички приложения и услуги, които имат разрешение да използват камерата или микрофона ви."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Устройство"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Прекарайте пръст нагоре, за да превключите между приложенията"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Плъзнете надясно за бързо превключване между приложенията"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Превключване на общия преглед"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Заредена"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Зарежда се"</string>
diff --git a/packages/SystemUI/res/values-bg/strings_tv.xml b/packages/SystemUI/res/values-bg/strings_tv.xml
index b7af7cb..49bf014 100644
--- a/packages/SystemUI/res/values-bg/strings_tv.xml
+++ b/packages/SystemUI/res/values-bg/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Чрез <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Известия"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Няма известия"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 46aea06..d269126 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"এটার জন্য ক্যামেরার অ্যাক্সেস সেই সব অ্যাপ এবং পরিষেবার জন্য আনব্লক হয়ে যাবে, যাতে আপনার ক্যামেরা ব্যবহারের অনুমতি দেওয়া হয়েছে।"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"এটার জন্য ক্যামেরা অথবা মাইক্রোফোনের অ্যাক্সেস সেই সব অ্যাপ এবং পরিষেবার জন্য আনব্লক হয়ে যাবে, যাতে আপনার ক্যামেরা অথবা মাইক্রোফোন ব্যবহারের অনুমতি দেওয়া হয়েছে।"</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"ডিভাইস"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"অন্য অ্যাপে যেতে উপরের দিকে সোয়াইপ করুন"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"একটি অ্যাপ ছেড়ে দ্রুত অন্য অ্যাপে যেতে ডান দিকে টেনে আনুন"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"\'এক নজরে\' বৈশিষ্ট্যটি চালু বা বন্ধ করুন"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"চার্জ হয়েছে"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"চার্জ হচ্ছে"</string>
diff --git a/packages/SystemUI/res/values-bn/strings_tv.xml b/packages/SystemUI/res/values-bn/strings_tv.xml
index 38c24ac..5a9b456 100644
--- a/packages/SystemUI/res/values-bn/strings_tv.xml
+++ b/packages/SystemUI/res/values-bn/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>-এর মাধ্যমে"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"বিজ্ঞপ্তি"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"কোনও বিজ্ঞপ্তি নেই"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 2dc7301..2857ecc 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -435,8 +435,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Ovim se deblokira pristup za sve aplikacije i usluge kojima je dozvoljeno da koriste vašu kameru."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Ovim se deblokira pristup za sve aplikacije i usluge kojima je dozvoljeno da koriste vašu kameru ili mikrofon."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Uređaj"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Prevucite prema gore za promjenu aplikacije"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Prevucite udesno za brzu promjenu aplikacija"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Pregled uključivanja/isključivanja"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Napunjeno"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Punjenje"</string>
diff --git a/packages/SystemUI/res/values-bs/strings_tv.xml b/packages/SystemUI/res/values-bs/strings_tv.xml
index 01916a1..92c5e2a 100644
--- a/packages/SystemUI/res/values-bs/strings_tv.xml
+++ b/packages/SystemUI/res/values-bs/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Putem: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Obavještenja"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nema obavještenja"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 37fdbc1..c25dca5 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Aquesta opció desbloqueja l\'accés de tots els serveis i aplicacions que tenen permís per utilitzar la càmera."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Aquesta opció desbloqueja l\'accés de tots els serveis i aplicacions que tenen permís per utilitzar la càmera o el micròfon."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositiu"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Llisca cap amunt per canviar d\'aplicació"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Arrossega el dit cap a la dreta per canviar ràpidament d\'aplicació"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Activa o desactiva Aplicacions recents"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Carregada"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"S\'està carregant"</string>
diff --git a/packages/SystemUI/res/values-ca/strings_tv.xml b/packages/SystemUI/res/values-ca/strings_tv.xml
index a060785..dac4a1a 100644
--- a/packages/SystemUI/res/values-ca/strings_tv.xml
+++ b/packages/SystemUI/res/values-ca/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Mitjançant <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificacions"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Cap notificació"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 25f796c..5fed1b3 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -437,8 +437,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Tímto odblokujete přístup všem aplikacím a službám, které mají povoleno používat váš fotoaparát."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Tímto odblokujete přístup všem aplikacím a službám, které mají povoleno používat váš fotoaparát či mikrofon."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Zařízení"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Přejetím nahoru přepnete aplikace"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Přetažením doprava rychle přepnete aplikace"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Přepnout přehled"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Nabito"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Nabíjení"</string>
diff --git a/packages/SystemUI/res/values-cs/strings_tv.xml b/packages/SystemUI/res/values-cs/strings_tv.xml
index eeab0d9..e9f4a10 100644
--- a/packages/SystemUI/res/values-cs/strings_tv.xml
+++ b/packages/SystemUI/res/values-cs/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Přes <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Oznámení"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Žádná oznámení"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index feb0dae..facedf0f 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Dette fjerner adgangsblokeringen for alle apps og tjenester, der har tilladelse til at bruge dit kamera."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Dette fjerner adgangsblokeringen for alle apps og tjenester, der har tilladelse til at bruge dit kamera eller din mikrofon."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Enhed"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Stryg opad for at skifte apps"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Træk til højre for hurtigt at skifte app"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Slå Oversigt til/fra"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Opladet"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Oplader"</string>
diff --git a/packages/SystemUI/res/values-da/strings_tv.xml b/packages/SystemUI/res/values-da/strings_tv.xml
index fb0bc2d..9534776 100644
--- a/packages/SystemUI/res/values-da/strings_tv.xml
+++ b/packages/SystemUI/res/values-da/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifikationer"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ingen notifikationer"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index a92dd6f..5d10eb4 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Dadurch wird die Blockierung des Zugriffs für alle Apps und Dienste aufgehoben, die deine Kamera verwenden dürfen."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Dadurch wird die Blockierung des Zugriffs für alle Apps und Dienste aufgehoben, die deine Kamera oder dein Mikrofon verwenden dürfen."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Gerät"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Nach oben wischen, um Apps zu wechseln"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Zum schnellen Wechseln der Apps nach rechts ziehen"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Übersicht ein-/ausblenden"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Aufgeladen"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Wird aufgeladen"</string>
diff --git a/packages/SystemUI/res/values-de/strings_tv.xml b/packages/SystemUI/res/values-de/strings_tv.xml
index 0345c80..ec162ef 100644
--- a/packages/SystemUI/res/values-de/strings_tv.xml
+++ b/packages/SystemUI/res/values-de/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Über <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Benachrichtigungen"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Keine Benachrichtigungen"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 99a90cc..cfda46f 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Με αυτόν τον τρόπο καταργείται ο αποκλεισμός της πρόσβασης για όλες τις εφαρμογές και υπηρεσίες που επιτρέπεται να χρησιμοποιούν την κάμερά σας."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Με αυτόν τον τρόπο καταργείται ο αποκλεισμός της πρόσβασης για όλες τις εφαρμογές και υπηρεσίες που επιτρέπεται να χρησιμοποιούν την κάμερα ή το μικρόφωνό σας."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Συσκευή"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Σύρετε προς τα επάνω για εναλλαγή των εφαρμογών"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Σύρετε προς τα δεξιά για γρήγορη εναλλαγή εφαρμογών"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Εναλλαγή επισκόπησης"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Φορτίστηκε"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Φόρτιση"</string>
diff --git a/packages/SystemUI/res/values-el/strings_tv.xml b/packages/SystemUI/res/values-el/strings_tv.xml
index cd92772..175c402 100644
--- a/packages/SystemUI/res/values-el/strings_tv.xml
+++ b/packages/SystemUI/res/values-el/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Μέσω <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Ειδοποιήσεις"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Δεν υπάρχουν ειδοποιήσεις."</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index fd54063..9af2d89 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"This unblocks access for all apps and services allowed to use your camera."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"This unblocks access for all apps and services allowed to use your camera or microphone."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Device"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Swipe up to switch apps"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Drag right to quickly switch apps"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Charged"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Charging"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings_tv.xml b/packages/SystemUI/res/values-en-rAU/strings_tv.xml
index 3b3e2d6..08fc8a6 100644
--- a/packages/SystemUI/res/values-en-rAU/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings_tv.xml
@@ -26,4 +26,10 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No notifications"</string>
+    <string name="mic_recording_announcement" msgid="7587123608060316575">"Microphone is recording"</string>
+    <string name="camera_recording_announcement" msgid="7240177719403759112">"Camera is recording"</string>
+    <string name="mic_and_camera_recording_announcement" msgid="8599231390508812667">"Camera and microphone are recording"</string>
+    <string name="mic_stopped_recording_announcement" msgid="7301537004900721242">"Microphone stopped recording"</string>
+    <string name="camera_stopped_recording_announcement" msgid="8540496432367032801">"Camera stopped recording"</string>
+    <string name="mic_camera_stopped_recording_announcement" msgid="8708524579599977412">"Camera and microphone stopped recording"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index dff3c30..398420a 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"This unblocks access for all apps and services allowed to use your camera."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"This unblocks access for all apps and services allowed to use your camera or microphone."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Device"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Swipe up to switch apps"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Drag right to quickly switch apps"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Charged"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Charging"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings_tv.xml b/packages/SystemUI/res/values-en-rCA/strings_tv.xml
index 3b3e2d6..08fc8a6 100644
--- a/packages/SystemUI/res/values-en-rCA/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings_tv.xml
@@ -26,4 +26,10 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No notifications"</string>
+    <string name="mic_recording_announcement" msgid="7587123608060316575">"Microphone is recording"</string>
+    <string name="camera_recording_announcement" msgid="7240177719403759112">"Camera is recording"</string>
+    <string name="mic_and_camera_recording_announcement" msgid="8599231390508812667">"Camera and microphone are recording"</string>
+    <string name="mic_stopped_recording_announcement" msgid="7301537004900721242">"Microphone stopped recording"</string>
+    <string name="camera_stopped_recording_announcement" msgid="8540496432367032801">"Camera stopped recording"</string>
+    <string name="mic_camera_stopped_recording_announcement" msgid="8708524579599977412">"Camera and microphone stopped recording"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index fd54063..9af2d89 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"This unblocks access for all apps and services allowed to use your camera."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"This unblocks access for all apps and services allowed to use your camera or microphone."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Device"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Swipe up to switch apps"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Drag right to quickly switch apps"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Charged"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Charging"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings_tv.xml b/packages/SystemUI/res/values-en-rGB/strings_tv.xml
index 3b3e2d6..08fc8a6 100644
--- a/packages/SystemUI/res/values-en-rGB/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings_tv.xml
@@ -26,4 +26,10 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No notifications"</string>
+    <string name="mic_recording_announcement" msgid="7587123608060316575">"Microphone is recording"</string>
+    <string name="camera_recording_announcement" msgid="7240177719403759112">"Camera is recording"</string>
+    <string name="mic_and_camera_recording_announcement" msgid="8599231390508812667">"Camera and microphone are recording"</string>
+    <string name="mic_stopped_recording_announcement" msgid="7301537004900721242">"Microphone stopped recording"</string>
+    <string name="camera_stopped_recording_announcement" msgid="8540496432367032801">"Camera stopped recording"</string>
+    <string name="mic_camera_stopped_recording_announcement" msgid="8708524579599977412">"Camera and microphone stopped recording"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index fd54063..9af2d89 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"This unblocks access for all apps and services allowed to use your camera."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"This unblocks access for all apps and services allowed to use your camera or microphone."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Device"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Swipe up to switch apps"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Drag right to quickly switch apps"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Charged"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Charging"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings_tv.xml b/packages/SystemUI/res/values-en-rIN/strings_tv.xml
index 3b3e2d6..08fc8a6 100644
--- a/packages/SystemUI/res/values-en-rIN/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings_tv.xml
@@ -26,4 +26,10 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No notifications"</string>
+    <string name="mic_recording_announcement" msgid="7587123608060316575">"Microphone is recording"</string>
+    <string name="camera_recording_announcement" msgid="7240177719403759112">"Camera is recording"</string>
+    <string name="mic_and_camera_recording_announcement" msgid="8599231390508812667">"Camera and microphone are recording"</string>
+    <string name="mic_stopped_recording_announcement" msgid="7301537004900721242">"Microphone stopped recording"</string>
+    <string name="camera_stopped_recording_announcement" msgid="8540496432367032801">"Camera stopped recording"</string>
+    <string name="mic_camera_stopped_recording_announcement" msgid="8708524579599977412">"Camera and microphone stopped recording"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 97976db..b211026 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‏‎‎‏‎‏‏‎‏‎‏‎‏‎‏‎‏‎‏‎‏‎‏‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‎This unblocks access for all apps and services allowed to use your camera.‎‏‎‎‏‎"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‎‎‏‏‎‎‏‎‏‎‏‏‎‏‏‏‏‎‎‏‏‏‎‏‎‎‎‏‏‏‏‎‏‏‎‎‏‎‏‎‎‎‏‏‎‎‎‏‏‎‏‏‏‎This unblocks access for all apps and services allowed to use your camera or microphone.‎‏‎‎‏‎"</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‎‏‏‏‎‏‎‎‏‏‏‏‎‎‏‏‎‎‎‎‎‎‎‎‎‎‏‎‎‏‎‏‏‎‏‏‏‏‎‎‎‎‎‎‎‏‎‎‏‎‎‏‎‎‎‎‎Device‎‏‎‎‏‎"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‏‎‎‎‏‏‏‎‎‏‏‎‎‎‏‏‏‎‎‎‎‏‏‎‎‏‏‏‎‎‎‏‎‎‎‏‏‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‎Swipe up to switch apps‎‏‎‎‏‎"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‏‎‏‎‎‎‎‏‎‎‏‎‎‏‎‏‎‎‏‏‎‎‎‎‎‎‏‎‎‎‎‏‏‎‏‎‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‎‎‎‎‎‎Drag right to quickly switch apps‎‏‎‎‏‎"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‎‏‎‎‎‏‏‏‏‎‎‎‎‎‏‏‎‎‏‏‎‏‏‎‏‎‏‎‎‏‎‏‏‏‎‎‏‏‎‎‏‏‏‎‎‏‎‎‎‏‏‎Toggle Overview‎‏‎‎‏‎"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎‏‎‏‎‎‏‎‏‏‏‏‎‎‏‏‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‏‎‎‏‏‏‏‎‎‎‎‏‎‏‎‎‎‏‏‎‎‎‎‎‎Charged‎‏‎‎‏‎"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‏‏‎‏‎‏‏‎‎‎‏‏‏‎‏‏‎‎‏‎‎‎‎‏‎‏‏‎‎‏‏‎‎‏‏‎‏‎‎‎‏‏‎‏‎Charging‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings_tv.xml b/packages/SystemUI/res/values-en-rXC/strings_tv.xml
index 34882b3..c030833 100644
--- a/packages/SystemUI/res/values-en-rXC/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings_tv.xml
@@ -26,4 +26,10 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‎‎‎‎‏‏‎‎‎‏‏‎‏‏‎‎‎‎‎‎‎‎‎‎‎‏‎‏‎‎‏‏‎‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‎Via ‎‏‎‎‏‏‎<xliff:g id="VPN_APP">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎‏‏‎‏‎‎‏‎‏‎‎‏‎‎‏‎‏‏‎‎‏‎‎‏‎‏‏‎‏‎‏‎‎‎‎‎‏‎‎‎‏‏‏‏‎‏‎‎‏‏‏‎‏‎‎Notifications‎‏‎‎‏‎"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‎‎‎‏‎‎‏‎‏‎‎‎‎‏‎‏‏‎‎No Notifications‎‏‎‎‏‎"</string>
+    <string name="mic_recording_announcement" msgid="7587123608060316575">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‎‏‎‏‎‏‏‏‎‎‎‎‎‏‎‏‏‏‎‎‏‎‎‏‎‎‏‎‏‎‏‏‎‏‎‏‎‎‏‎‎‏‎‏‏‏‎‎‏‏‏‏‏‎Microphone is recording‎‏‎‎‏‎"</string>
+    <string name="camera_recording_announcement" msgid="7240177719403759112">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‏‏‏‎‏‎‎‏‎‎‎‏‏‏‎‏‎‎‎‏‏‎‏‎‎‏‎‎‏‏‏‏‎‎‎‎‏‎‎‏‎‎‎‏‏‎‎‎‎‎‏‎‎‎‎Camera is recording‎‏‎‎‏‎"</string>
+    <string name="mic_and_camera_recording_announcement" msgid="8599231390508812667">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‏‏‎‏‎‎‏‏‎‏‏‎‏‏‎‎‎‏‏‏‎‎‏‎‏‎‎‏‎‏‎‏‎‏‎‏‎‎‎‏‎‎‏‎‏‏‏‏‎‏‏‎Camera and Microphone are recording‎‏‎‎‏‎"</string>
+    <string name="mic_stopped_recording_announcement" msgid="7301537004900721242">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‏‎‏‎‎‎‏‎‎‎‏‎‏‎‎‏‏‏‎‎‎‏‎‎‎‎‎‏‏‎‏‏‏‏‎‏‎‎‎‏‎‎‎‏‎‎‏‎‏‏‎‏‎‎Microphone stopped recording‎‏‎‎‏‎"</string>
+    <string name="camera_stopped_recording_announcement" msgid="8540496432367032801">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‏‎‏‏‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‎‏‏‏‏‎‎‎‏‎‏‏‏‎‏‎‎‏‎‏‏‎‎‏‏‏‏‎‎‎‎‏‎Camera stopped recording‎‏‎‎‏‎"</string>
+    <string name="mic_camera_stopped_recording_announcement" msgid="8708524579599977412">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‎‏‎‏‏‏‎‎‏‎‎‏‏‏‏‎‏‏‏‎‎‏‎‎‏‎‎‏‏‎‏‎‎‎‎‏‎‎‎‏‎‏‏‏‏‎‎‎‏‎‎‎Camera and Microphone stopped recording‎‏‎‎‏‎"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index a431258..4520ed3 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Esta acción desbloquea el acceso para todos los servicios y las apps que tengan permitido usar la cámara."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Esta acción permite que todas las aplicaciones y servicios que tengan permiso puedan usar la cámara o el micrófono."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Desliza el dedo hacia arriba para cambiar de app"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Arrastra a la derecha para cambiar aplicaciones rápidamente"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Ocultar o mostrar Recientes"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Cargada"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Cargando"</string>
@@ -536,7 +534,7 @@
     <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Este dispositivo pertenece a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> y está conectado a VPN"</string>
     <string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Tu organización puede controlar el tráfico de red en tu perfil de trabajo"</string>
     <string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"Es posible que <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> controle el tráfico de red en tu perfil de trabajo"</string>
-    <string name="quick_settings_disclosure_managed_profile_network_activity" msgid="2636594621387832827">"El administrador de IT puede ver la actividad de red de tu perfil de trabajo"</string>
+    <string name="quick_settings_disclosure_managed_profile_network_activity" msgid="2636594621387832827">"El administrador de TI puede ver la actividad de red de tu perfil de trabajo"</string>
     <string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Es posible que la red esté supervisada"</string>
     <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Este dispositivo está conectado a VPN"</string>
     <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Tu perfil de trabajo está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings_tv.xml b/packages/SystemUI/res/values-es-rUS/strings_tv.xml
index a0a355b..680e7cc 100644
--- a/packages/SystemUI/res/values-es-rUS/strings_tv.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"A través de <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificaciones"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No hay notificaciones"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 0fa33e7..c5096e9 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Si lo haces, todas las aplicaciones y servicios que tengan permiso podrán usar tu cámara."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Si lo haces, todas las aplicaciones y servicios que tengan permiso podrán usar tu cámara o tu micrófono."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Desliza el dedo hacia arriba para cambiar de aplicación"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Arrastra hacia la derecha para cambiar rápidamente de aplicación"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Mostrar u ocultar aplicaciones recientes"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Cargada"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Cargando"</string>
diff --git a/packages/SystemUI/res/values-es/strings_tv.xml b/packages/SystemUI/res/values-es/strings_tv.xml
index 4607ad5..16154a4 100644
--- a/packages/SystemUI/res/values-es/strings_tv.xml
+++ b/packages/SystemUI/res/values-es/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"A través de <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificaciones"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Sin notificaciones"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 5e52394..ee7c760 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Sellega tühistatakse juurdepääsu blokeerimine kõikide rakenduste ja teenuste puhul, millel on lubatud kaamerat kasutada."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Sellega tühistatakse juurdepääsu blokeerimine kõikide rakenduste ja teenuste puhul, millel on lubatud kaamerat või mikrofoni kasutada."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Seade"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Rakenduste vahetamiseks pühkige üles"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Lohistage paremale, et rakendusi kiiresti vahetada"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Lehe Ülevaade sisse- ja väljalülitamine"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Laetud"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Laadimine"</string>
diff --git a/packages/SystemUI/res/values-et/strings_tv.xml b/packages/SystemUI/res/values-et/strings_tv.xml
index 593298e..3732020 100644
--- a/packages/SystemUI/res/values-et/strings_tv.xml
+++ b/packages/SystemUI/res/values-et/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Teenuse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Märguanded"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Märguandeid pole"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 3e687d7..0972c26b 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Kamera atzitzeko baimena duten aplikazio eta zerbitzu guztiek erabili ahalko dute."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Kamera edo mikrofonoa atzitzeko baimena duten aplikazio eta zerbitzu guztiek erabili ahalko dituzte."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Gailua"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Egin gora aplikazioa aldatzeko"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Arrastatu eskuinera aplikazioa azkar aldatzeko"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Aldatu ikuspegi orokorra"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Kargatuta"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Kargatzen"</string>
diff --git a/packages/SystemUI/res/values-eu/strings_tv.xml b/packages/SystemUI/res/values-eu/strings_tv.xml
index e1c4fcc..524165e 100644
--- a/packages/SystemUI/res/values-eu/strings_tv.xml
+++ b/packages/SystemUI/res/values-eu/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> bidez"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Jakinarazpenak"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ez dago jakinarazpenik"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index b37a7be..2899e17 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"با این کار دسترسی برای همه برنامه‌ها و سرویس‌هایی که مجاز هستند از دوربینتان استفاده کنند لغو انسداد می‌شود."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"با این کار دسترسی برای همه برنامه‌ها و دستگاه‌هایی که مجاز هستند از دوربین یا میکروفونتان استفاده کنند لغو انسداد می‌شود."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"دستگاه"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"برای تغییر برنامه‌ها،‌ تند به‌بالا بکشید"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"برای جابه‌جایی سریع میان برنامه‌ها، به چپ بکشید"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"تغییر وضعیت نمای کلی"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"شارژ کامل شد"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"در حال شارژ شدن"</string>
diff --git a/packages/SystemUI/res/values-fa/strings_tv.xml b/packages/SystemUI/res/values-fa/strings_tv.xml
index 5ad12df..8038755 100644
--- a/packages/SystemUI/res/values-fa/strings_tv.xml
+++ b/packages/SystemUI/res/values-fa/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"ازطریق <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"اعلان‌ها"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"اعلانی ندارید"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index e963853..dc49957 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Tämä kumoaa kaikkien sellaisten sovellusten ja palveluiden eston, joilla on lupa käyttää kameraasi."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Tämä kumoaa eston kaikkien sellaisten sovellusten ja palveluiden osalta, joilla on lupa käyttää kameraasi tai mikrofoniasi."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Laite"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Vaihda sovellusta pyyhkäisemällä ylös"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Vaihda sovellusta nopeasti vetämällä oikealle"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Näytä/piilota viimeisimmät"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Ladattu"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Ladataan"</string>
diff --git a/packages/SystemUI/res/values-fi/strings_tv.xml b/packages/SystemUI/res/values-fi/strings_tv.xml
index 61cd5ab..17797d7 100644
--- a/packages/SystemUI/res/values-fi/strings_tv.xml
+++ b/packages/SystemUI/res/values-fi/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Palvelun <xliff:g id="VPN_APP">%1$s</xliff:g> kautta"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Ilmoitukset"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ei ilmoituksia"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 457ab8a..83c0ef4 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Cette action débloque l\'accès pour toutes les applications et pour tous les services autorisés à utiliser l\'appareil photo."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Cette action débloque l\'accès pour toutes les applications et tous les services autorisés à utiliser l\'appareil photo ou le microphone."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Appareil"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Balayez vers le haut pour changer d\'application"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Balayez l\'écran vers la droite pour changer rapidement d\'application"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Basculer l\'aperçu"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Chargée"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Charge en cours..."</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings_tv.xml b/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
index a667d76..7f45411 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Par <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Aucune notification"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 1c09d87..bb3183e 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Cette action débloque l\'accès à tous les services et applis autorisés à utiliser votre appareil photo."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Cette action débloque l\'accès pour tous les services et applis autorisés à utiliser votre appareil photo ou votre micro."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Appareil"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Balayer l\'écran vers le haut pour changer d\'application"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Déplacer vers la droite pour changer rapidement d\'application"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Activer/Désactiver l\'aperçu"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Chargé"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"En charge"</string>
diff --git a/packages/SystemUI/res/values-fr/strings_tv.xml b/packages/SystemUI/res/values-fr/strings_tv.xml
index 25fab4e..99bab80 100644
--- a/packages/SystemUI/res/values-fr/strings_tv.xml
+++ b/packages/SystemUI/res/values-fr/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Aucune notification"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index b5018d1..d8fe4b8 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Con esta acción desbloquearase o acceso á cámara para todas as aplicacións e servizos que teñan permiso para utilizala."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Con esta acción desbloquearase o acceso á cámara ou ao micrófono para todas as aplicacións e servizos que teñan permiso para utilizalos."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Pasar o dedo cara arriba para cambiar de aplicación"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Arrastra cara á dereita para cambiar de aplicacións rapidamente"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Activar/desactivar Visión xeral"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Cargado"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Cargando"</string>
diff --git a/packages/SystemUI/res/values-gl/strings_tv.xml b/packages/SystemUI/res/values-gl/strings_tv.xml
index cd12b94..0d35c4d 100644
--- a/packages/SystemUI/res/values-gl/strings_tv.xml
+++ b/packages/SystemUI/res/values-gl/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"A través de <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificacións"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Non hai notificacións"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index b29a528..553924a 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -230,7 +230,7 @@
     <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 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_settings_button" msgid="2197034218538913880">"સિસ્ટમ સેટિંગ."</string>
     <string name="accessibility_notifications_button" msgid="3960913924189228831">"નોટિફિકેશન."</string>
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"બધી સૂચના જુઓ"</string>
     <string name="accessibility_remove_notification" msgid="1641455251495815527">"સૂચના સાફ કરો."</string>
@@ -245,7 +245,7 @@
     <skip />
     <string name="accessibility_notification_dismissed" msgid="4411652015138892952">"સૂચના કાઢી નાખી."</string>
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"નોટિફિકેશન શેડ."</string>
-    <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ઝડપી સેટિંગ્સ."</string>
+    <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ઝડપી સેટિંગ."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"લૉક સ્ક્રીન."</string>
     <string name="accessibility_desc_settings" msgid="6728577365389151969">"સેટિંગ"</string>
     <string name="accessibility_desc_recent_apps" msgid="1748675199348914194">"ઝલક."</string>
@@ -315,7 +315,7 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> વધુ સૂચના અંદર છે.</item>
     </plurals>
     <string name="notification_summary_message_format" msgid="5158219088501909966">"<xliff:g id="CONTACT_NAME">%1$s</xliff:g>: <xliff:g id="MESSAGE_CONTENT">%2$s</xliff:g>"</string>
-    <string name="status_bar_notification_inspect_item_title" msgid="6818779631806163080">"સૂચનાઓની સેટિંગ્સ"</string>
+    <string name="status_bar_notification_inspect_item_title" msgid="6818779631806163080">"નોટિફિકેશન સેટિંગ"</string>
     <string name="status_bar_notification_app_settings_title" msgid="5050006438806013903">"<xliff:g id="APP_NAME">%s</xliff:g> સેટિંગ"</string>
     <string name="accessibility_rotation_lock_off" msgid="3880436123632448930">"સ્ક્રીન ઑટોમૅટિક રીતે ફરશે."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="936972553861524360">"સ્ક્રીન લેન્ડસ્કેપ ઓરિએન્ટેશનમાં લૉક કરેલ છે."</string>
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"આ તમારા કૅમેરાનો ઉપયોગ કરવાની મંજૂરી ધરાવતી તમામ ઍપ અને સેવાઓ માટે ઍક્સેસને અનબ્લૉક કરે છે."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"આ તમારા કૅમેરા અથવા માઇક્રોફોનનો ઉપયોગ કરવાની મંજૂરી ધરાવતી તમામ ઍપ અને સેવાઓ માટે ઍક્સેસને અનબ્લૉક કરે છે."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"ડિવાઇસ"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ઍપ સ્વિચ કરવા માટે ઉપરની તરફ સ્વાઇપ કરો"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ઍપને ઝડપથી સ્વિચ કરવા માટે જમણે ખેંચો"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ઝલકને ટૉગલ કરો"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"ચાર્જ થઈ ગયું"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"ચાર્જ થઈ રહ્યું છે"</string>
@@ -567,12 +565,12 @@
     <string name="monitoring_description_personal_profile_named_vpn" msgid="8179722332380953673">"તમારી વ્યક્તિગત પ્રોફાઇલ <xliff:g id="VPN_APP">%1$s</xliff:g> સાથે કનેક્ટ કરેલ છે, જે ઇમેઇલ, ઍપ્લિકેશનો અને વેબસાઇટો સહિતની તમારી નેટવર્ક પ્રવૃત્તિનું નિયમન કરી શકે છે."</string>
     <string name="monitoring_description_do_header_generic" msgid="6130190408164834986">"તમારું ડિવાઇસ <xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g> દ્વારા મેનેજ થાય છે."</string>
     <string name="monitoring_description_do_header_with_name" msgid="2696255132542779511">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>, તમારા ઉપકરણનું સંચાલન કરવા માટે <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> નો ઉપયોગ કરે છે."</string>
-    <string name="monitoring_description_do_body" msgid="7700878065625769970">"વ્યવસ્થાપક સેટિંગ્સ, કૉર્પોરેટ ઍક્સેસ, ઍપ્સ, તમારા ઉપકરણ સંબંદ્ધ ડેટા અને ઉપકરણની સ્થાન માહિતીનું નિરીક્ષણ અને સંચાલન કરી શકે છે."</string>
+    <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_vpn_settings_separator" msgid="8292589617720435430">" "</string>
-    <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"VPNની સેટિંગ્સ ખોલો"</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_network_logging" msgid="577305979174002252">"તમારા વ્યવસ્થાપકે નેટવર્ક લૉગિંગ ચાલુ કર્યુ છે, જે તમારા ઉપકરણ પર ટ્રાફિકનું નિરીક્ષણ કરે છે.\n\nવધુ માહિતી માટે, તમારા વ્યવસ્થાપકનો સંપર્ક કરો."</string>
@@ -619,7 +617,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>
@@ -657,7 +655,7 @@
     <string name="system_ui_tuner" msgid="1471348823289954729">"સિસ્ટમ UI ટ્યૂનર"</string>
     <string name="show_battery_percentage" msgid="6235377891802910455">"એમ્બેડ કરેલ બૅટરી ટકા બતાવો"</string>
     <string name="show_battery_percentage_summary" msgid="9053024758304102915">"જ્યારે ચાર્જ ન થઈ રહ્યું હોય ત્યારે સ્ટેટસ બાર આયકનની અંદર બૅટરી સ્તર ટકા બતાવો"</string>
-    <string name="quick_settings" msgid="6211774484997470203">"ઝડપી સેટિંગ્સ"</string>
+    <string name="quick_settings" msgid="6211774484997470203">"ઝડપી સેટિંગ"</string>
     <string name="status_bar" msgid="4357390266055077437">"સ્ટેટસ બાર"</string>
     <string name="overview" msgid="3522318590458536816">"ઝલક"</string>
     <string name="demo_mode" msgid="263484519766901593">"સિસ્ટમ UI ડેમો મોડ"</string>
@@ -682,21 +680,21 @@
     <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>
+    <string name="accessibility_quick_settings_detail" msgid="544463655956179791">"ઝડપી સેટિંગ, <xliff:g id="TITLE">%s</xliff:g>."</string>
     <string name="accessibility_status_bar_hotspot" msgid="2888479317489131669">"હૉટસ્પૉટ"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"ઑફિસની પ્રોફાઇલ"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"કેટલાક માટે મજા પરંતુ બધા માટે નહીં"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"સિસ્ટમ UI ટ્યૂનર તમને Android વપરાશકર્તા ઇન્ટરફેસને ટ્વીક અને કસ્ટમાઇઝ કરવાની વધારાની રીતો આપે છે. ભાવિ રીલિઝેસમાં આ પ્રાયોગિક સુવિધાઓ બદલાઈ, ભંગ અથવા અદૃશ્ય થઈ શકે છે. સાવધાની સાથે આગળ વધો."</string>
     <string name="tuner_persistent_warning" msgid="230466285569307806">"ભાવિ રીલિઝેસમાં આ પ્રાયોગિક સુવિધાઓ બદલાઈ, ભંગ અથવા અદૃશ્ય થઈ શકે છે. સાવધાની સાથે આગળ વધો."</string>
     <string name="got_it" msgid="477119182261892069">"સમજાઈ ગયું"</string>
-    <string name="tuner_toast" msgid="3812684836514766951">"અભિનંદન! સિસ્ટમ UI ટ્યૂનરને સેટિંગ્સમાં ઉમેરવામાં આવ્યું છે"</string>
-    <string name="remove_from_settings" msgid="633775561782209994">"સેટિંગ્સમાંથી દૂર કરો"</string>
-    <string name="remove_from_settings_prompt" msgid="551565437265615426">"સેટિંગ્સમાંથી સિસ્ટમ UI ટ્યૂનર દૂર કરી અને તેની તમામ સુવિધાઓનો ઉપયોગ કરવાનું બંધ કરીએ?"</string>
+    <string name="tuner_toast" msgid="3812684836514766951">"અભિનંદન! સિસ્ટમ UI ટ્યૂનરને સેટિંગમાં ઉમેરવામાં આવ્યું છે"</string>
+    <string name="remove_from_settings" msgid="633775561782209994">"સેટિંગમાંથી કાઢી નાખો"</string>
+    <string name="remove_from_settings_prompt" msgid="551565437265615426">"સેટિંગમાંથી સિસ્ટમ UI ટ્યૂનર કાઢી નાખી અને તેની તમામ સુવિધાઓનો ઉપયોગ કરવાનું બંધ કરીએ?"</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="qs_rearrange" msgid="484816665478662911">"ઝડપી સેટિંગ્સને ફરીથી ગોઠવો"</string>
-    <string name="show_brightness" msgid="6700267491672470007">"ઝડપી સેટિંગ્સમાં તેજ બતાવો"</string>
+    <string name="qs_rearrange" msgid="484816665478662911">"ઝડપી સેટિંગને ફરીથી ગોઠવો"</string>
+    <string name="show_brightness" msgid="6700267491672470007">"ઝડપી સેટિંગમાં બ્રાઇટનેસ બતાવો"</string>
     <string name="experimental" msgid="3549865454812314826">"પ્રાયોગિક"</string>
     <string name="enable_bluetooth_title" msgid="866883307336662596">"બ્લૂટૂથ ચાલુ કરવુ છે?"</string>
     <string name="enable_bluetooth_message" msgid="6740938333772779717">"તમારા ટેબ્લેટ સાથે કીબોર્ડ કનેક્ટ કરવા માટે, તમારે પહેલાં બ્લૂટૂથ ચાલુ કરવાની જરૂર પડશે."</string>
@@ -918,19 +916,19 @@
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"જગ્યા <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"ટાઇલ ઉમેરી"</string>
     <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"ટાઇલ કાઢી નાખી"</string>
-    <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ઝડપી સેટિંગ્સ સંપાદક."</string>
+    <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ઝડપી સેટિંગ એડિટર."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> નોટિફિકેશન: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
-    <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"સેટિંગ્સ ખોલો."</string>
-    <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"ઝડપી સેટિંગ્સ ખોલો."</string>
-    <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"ઝડપી સેટિંગ્સ બંધ કરો."</string>
+    <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"સેટિંગ ખોલો."</string>
+    <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_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>
-    <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g> સેટિંગ્સ ખોલો."</string>
-    <string name="accessibility_quick_settings_edit" msgid="1523745183383815910">"સેટિંગ્સનો ક્રમ સંપાદિત કરો."</string>
+    <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g> સેટિંગ ખોલો."</string>
+    <string name="accessibility_quick_settings_edit" msgid="1523745183383815910">"સેટિંગના ક્રમમાં ફેરફાર કરો."</string>
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"પાવર મેનૂ"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> માંથી <xliff:g id="ID_1">%1$d</xliff:g> પૃષ્ઠ"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"લૉક સ્ક્રીન"</string>
@@ -988,7 +986,7 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"મોબાઇલ ડેટા બંધ કરીએ?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"તમને <xliff:g id="CARRIER">%s</xliff:g> મારફતે ડેટા અથવા ઇન્ટરનેટનો ઍક્સેસ મળશે નહીં. ઇન્ટરનેટ માત્ર વાઇ-ફાઇ દ્વારા ઉપલબ્ધ થશે."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"તમારા કૅરિઅર"</string>
-    <string name="touch_filtered_warning" msgid="8119511393338714836">"એક ઍપ પરવાનગી વિનંતીને અસ્પષ્ટ કરતી હોવાને કારણે, સેટિંગ્સ તમારા પ્રતિસાદને ચકાસી શકતી નથી."</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_2" msgid="6758906940360746983">"- મારાથી <xliff:g id="APP">%1$s</xliff:g>ની અંદર ક્રિયાઓ કરી શકાતી નથી"</string>
diff --git a/packages/SystemUI/res/values-gu/strings_tv.xml b/packages/SystemUI/res/values-gu/strings_tv.xml
index a53e983..c2c8ad6 100644
--- a/packages/SystemUI/res/values-gu/strings_tv.xml
+++ b/packages/SystemUI/res/values-gu/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> મારફતે"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"નોટિફિકેશન"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"કોઈ નોટિફિકેશન નથી"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 1d56cd6..ac4a903 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ऐसा करने से, कैमरे का ऐक्सेस उन सभी ऐप्लिकेशन और सेवाओं के लिए अनब्लॉक हो जाएगा जिन्हें कैमरे का इस्तेमाल करने की अनुमति दी गई है."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ऐसा करने से, कैमरा या माइक्रोफ़ोन का ऐक्सेस उन सभी ऐप्लिकेशन और सेवाओं के लिए अनब्लॉक हो जाएगा जिन्हें ये इस्तेमाल करने की अनुमति है."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"डिवाइस"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ऐप्लिकेशन बदलने के लिए ऊपर स्वाइप करें"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ऐप्लिकेशन को झटपट स्विच करने के लिए उसे दाईं ओर खींचें और छोड़ें"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"खास जानकारी टॉगल करें"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"चार्ज हो गई है"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"चार्ज हो रही है"</string>
diff --git a/packages/SystemUI/res/values-hi/strings_tv.xml b/packages/SystemUI/res/values-hi/strings_tv.xml
index fedaae3..eb8f150 100644
--- a/packages/SystemUI/res/values-hi/strings_tv.xml
+++ b/packages/SystemUI/res/values-hi/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> के ज़रिए"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"सूचनाएं"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"कोई सूचना नहीं है"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 689a435..571ca24 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -435,8 +435,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Time se deblokira pristup za sve aplikacije i usluge kojima je dopuštena upotreba vašeg fotoaparata."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Time se deblokira pristup za sve aplikacije i usluge kojima je dopuštena upotreba vašeg fotoaparata ili mikrofona."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Uređaj"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Prijeđite prstom prema gore da biste promijenili aplikaciju"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Povucite udesno da biste brzo promijenili aplikaciju"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Uključivanje/isključivanje pregleda"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Napunjeno"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Punjenje"</string>
diff --git a/packages/SystemUI/res/values-hr/strings_tv.xml b/packages/SystemUI/res/values-hr/strings_tv.xml
index 3bfdf70..241195b 100644
--- a/packages/SystemUI/res/values-hr/strings_tv.xml
+++ b/packages/SystemUI/res/values-hr/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Putem mreže <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Obavijesti"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nema obavijesti"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index f7728d2..9a7ca9d6 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Ezzel feloldja a hozzáférés letiltását az összes olyan alkalmazás és szolgáltatás esetében, amelyek számára engedélyezte a kamera használatát."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Ezzel feloldja a hozzáférés letiltását az összes olyan alkalmazás és szolgáltatás esetében, amelyek számára engedélyezte a kamera vagy a mikrofon használatát."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Eszköz"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Váltás az alkalmazások között felfelé csúsztatással"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Húzza jobbra az ujját az alkalmazások közötti gyors váltáshoz"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Áttekintés be- és kikapcsolása"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Feltöltve"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Töltés"</string>
diff --git a/packages/SystemUI/res/values-hu/strings_tv.xml b/packages/SystemUI/res/values-hu/strings_tv.xml
index 91183af..e825584 100644
--- a/packages/SystemUI/res/values-hu/strings_tv.xml
+++ b/packages/SystemUI/res/values-hu/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Ezzel: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Értesítések"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nincs értesítés"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 4605a98..74ab34d 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Սա բացում է մուտքը բոլոր հավելվածների և ծառայությունների համար, որոնք ունեն ձեր տեսախցիկն օգտագործելու թույլտվություն։"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Սա բացում է մուտքը բոլոր հավելվածների և ծառայությունների համար, որոնք ունեն ձեր տեսախցիկը կամ խոսափողն օգտագործելու թույլտվություն։"</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Սարք"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Սահեցրեք վերև՝ մյուս հավելվածին անցնելու համար"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Քաշեք աջ՝ հավելվածների միջև անցնելու համար"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Միացնել/անջատել համատեսքը"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Լիցքավորված է"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Լիցքավորվում է"</string>
diff --git a/packages/SystemUI/res/values-hy/strings_tv.xml b/packages/SystemUI/res/values-hy/strings_tv.xml
index cf4eb90..0fab090 100644
--- a/packages/SystemUI/res/values-hy/strings_tv.xml
+++ b/packages/SystemUI/res/values-hy/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>-ի միջոցով"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Ծանուցումներ"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ծանուցումներ չկան"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index ef20347..204484c 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Ini akan berhenti memblokir akses untuk semua aplikasi dan layanan yang diizinkan menggunakan kamera."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Langkah ini akan berhenti memblokir akses untuk semua aplikasi dan layanan yang diizinkan menggunakan kamera atau mikrofon."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Perangkat"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Geser ke atas untuk beralih aplikasi"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Tarik ke kanan untuk beralih aplikasi dengan cepat"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Aktifkan Ringkasan"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Terisi penuh"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Mengisi daya"</string>
diff --git a/packages/SystemUI/res/values-in/strings_tv.xml b/packages/SystemUI/res/values-in/strings_tv.xml
index 3b446ad..c787ca2 100644
--- a/packages/SystemUI/res/values-in/strings_tv.xml
+++ b/packages/SystemUI/res/values-in/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Melalui <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifikasi"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Tidak Ada Notifikasi"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index b2e2198..5afc8bc 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Þetta veitir öllum forritum og þjónustum aðgang að myndavélinni þinni."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Þetta veitir öllum forritum og þjónustum aðgang að myndavélinni og hljóðnemanum þínum."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Tæki"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Strjúktu upp til að skipta á milli forrita"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Dragðu til hægri til að skipta hratt á milli forrita"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Kveikja/slökkva á yfirliti"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Fullhlaðin"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Í hleðslu"</string>
diff --git a/packages/SystemUI/res/values-is/strings_tv.xml b/packages/SystemUI/res/values-is/strings_tv.xml
index 7c23e62..6d7c91c 100644
--- a/packages/SystemUI/res/values-is/strings_tv.xml
+++ b/packages/SystemUI/res/values-is/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Í gegnum <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Tilkynningar"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Engar tilkynningar"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 42e5dea..9c28363 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Viene sbloccato l\'accesso per tutti i servizi e le app autorizzati a usare la fotocamera."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Viene sbloccato l\'accesso per tutti i servizi e le app autorizzati a usare la fotocamera o il microfono."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Scorri verso l\'alto per passare ad altre app"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Trascina verso destra per cambiare velocemente app"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Attiva/disattiva la panoramica"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Carica"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"In carica"</string>
diff --git a/packages/SystemUI/res/values-it/strings_tv.xml b/packages/SystemUI/res/values-it/strings_tv.xml
index 57931b0..c676029 100644
--- a/packages/SystemUI/res/values-it/strings_tv.xml
+++ b/packages/SystemUI/res/values-it/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Tramite <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifiche"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nessuna notifica"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 731d36c..b7153b1 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -437,8 +437,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"הפעולה הזו מבטלת את חסימת הגישה של כל האפליקציות והשירותים שמורשים להשתמש במצלמה."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"הפעולה הזו מבטלת את חסימת הגישה של כל האפליקציות והשירותים שמורשים להשתמש במצלמה או במיקרופון."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"מכשיר"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"יש להחליק מעלה כדי להחליף אפליקציות"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"יש לגרור ימינה כדי לעבור במהירות בין אפליקציות"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"החלפת מצב של מסכים אחרונים"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"הסוללה טעונה"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"בטעינה"</string>
diff --git a/packages/SystemUI/res/values-iw/strings_tv.xml b/packages/SystemUI/res/values-iw/strings_tv.xml
index f01321e..46e61d0 100644
--- a/packages/SystemUI/res/values-iw/strings_tv.xml
+++ b/packages/SystemUI/res/values-iw/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"דרך <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"התראות"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"אין התראות"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index d638ace..a8fb87d 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"カメラの使用が許可されているすべてのアプリとサービスでアクセスのブロックが解除されます。"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"カメラやマイクの使用が許可されているすべてのアプリとサービスでアクセスのブロックが解除されます。"</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"デバイス"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"アプリを切り替えるには上にスワイプ"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"右にドラッグするとアプリを素早く切り替えることができます"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"概要を切り替え"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"充電が完了しました"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"充電しています"</string>
diff --git a/packages/SystemUI/res/values-ja/strings_tv.xml b/packages/SystemUI/res/values-ja/strings_tv.xml
index 7f676b5..798caec 100644
--- a/packages/SystemUI/res/values-ja/strings_tv.xml
+++ b/packages/SystemUI/res/values-ja/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> 経由"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"通知"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"通知はありません"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index aff2521..da4f5bc 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ამ მოქმედების მეშვეობით განიბლოკება ყველა აპსა და მომსახურებაზე წვდომა, რომელთაც აქვთ თქვენი კამერის გამოყენების უფლება."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ამ მოქმედების მეშვეობით განიბლოკება ყველა აპსა და მომსახურებაზე წვდომა, რომელთაც აქვთ თქვენი კამერის ან მიკროფონის გამოყენების უფლება."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"მოწყობილობა"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"გადაფურცლეთ ზემოთ აპების გადასართავად"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"აპების სწრაფად გადასართავად ჩავლებით გადაიტანეთ მარჯვნივ"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"მიმოხილვის გადართვა"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"დატენილია"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"მიმდინარეობს დატენვა"</string>
diff --git a/packages/SystemUI/res/values-ka/strings_tv.xml b/packages/SystemUI/res/values-ka/strings_tv.xml
index 0819781..b158e5c 100644
--- a/packages/SystemUI/res/values-ka/strings_tv.xml
+++ b/packages/SystemUI/res/values-ka/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>-ის მიერ"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"შეტყობინებები"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"შეტყობინებები არ არის"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 674f6a0..c15c6be 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Камераңызды пайдалануға рұқсат берілген барлық қолданба мен қызметтің бөгеуі алынады."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Камераңызды немесе микрофоныңызды пайдалануға рұқсат берілген барлық қолданба мен қызметтің бөгеуі алынады."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Құрылғы"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Қолданбалар арасында ауысу үшін жоғары сырғытыңыз"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Қолданбаларды жылдам ауыстырып қосу үшін оңға қарай сүйреңіз"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Шолуды қосу/өшіру"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Зарядталды"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Зарядталуда"</string>
diff --git a/packages/SystemUI/res/values-kk/strings_tv.xml b/packages/SystemUI/res/values-kk/strings_tv.xml
index 768e3ac..36440c9 100644
--- a/packages/SystemUI/res/values-kk/strings_tv.xml
+++ b/packages/SystemUI/res/values-kk/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> арқылы жалғанған"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Хабарландырулар"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Хабарландырулар жоқ"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 1d4b515..31de2be 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ការធ្វើបែបនេះ​នឹងឈប់ទប់ស្កាត់​ការចូលប្រើ​សម្រាប់កម្មវិធី និងសេវាកម្ម​ទាំងអស់ ដែលត្រូវបាន​អនុញ្ញាតឱ្យប្រើ​កាមេរ៉ារបស់អ្នក​។"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ការធ្វើបែបនេះ​នឹងឈប់ទប់ស្កាត់​ការចូលប្រើ​សម្រាប់កម្មវិធី និងសេវាកម្ម​ទាំងអស់ ដែលត្រូវបាន​អនុញ្ញាតឱ្យប្រើ​កាមេរ៉ា ឬមីក្រូហ្វូនរបស់អ្នក​។"</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"ឧបករណ៍"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"អូស​ឡើង​លើ​ដើម្បី​ប្តូរ​កម្មវិធី"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"អូសទៅស្ដាំដើម្បីប្ដូរកម្មវិធីបានរហ័ស"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"បិទ/បើក​ទិដ្ឋភាពរួម"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"បាន​សាក​ថ្មពេញ"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"កំពុងសាក​ថ្ម"</string>
diff --git a/packages/SystemUI/res/values-km/strings_tv.xml b/packages/SystemUI/res/values-km/strings_tv.xml
index 0dec2d6..b04cc2b 100644
--- a/packages/SystemUI/res/values-km/strings_tv.xml
+++ b/packages/SystemUI/res/values-km/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"តាម​រយៈ <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"ការ​ជូនដំណឹង"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"គ្មាន​ការជូនដំណឹងទេ"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 264f248..9b9138c 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ಇದು ಎಲ್ಲಾ ಆ್ಯಪ್‌ಗಳಿಗೆ ಹಾಗೂ ಸೇವೆಗಳಿಗೆ ನಿಮ್ಮ ಕ್ಯಾಮರಾವನ್ನು ಬಳಸುವುದಕ್ಕಾಗಿ ಇರುವ ಪ್ರವೇಶದ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆದುಹಾಕುತ್ತದೆ."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ಇದು ಎಲ್ಲಾ ಆ್ಯಪ್‌ಗಳಿಗೆ ಹಾಗೂ ಸೇವೆಗಳಿಗೆ ನಿಮ್ಮ ಕ್ಯಾಮರಾ ಅಥವಾ ಮೈಕ್ರೋಫೋನ್ ಬಳಸುವುದಕ್ಕಾಗಿ ಇರುವ ಪ್ರವೇಶದ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆದುಹಾಕುತ್ತದೆ."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"ಸಾಧನ"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಬದಲಾಯಿಸಲು ಸ್ವೈಪ್ ಮಾಡಿ"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಬದಲಿಸಲು ತ್ವರಿತವಾಗಿ ಬಲಕ್ಕೆ ಡ್ರ್ಯಾಗ್ ಮಾಡಿ"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ಟಾಗಲ್ ನ ಅವಲೋಕನ"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"ಚಾರ್ಜ್ ಆಗಿದೆ"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string>
diff --git a/packages/SystemUI/res/values-kn/strings_tv.xml b/packages/SystemUI/res/values-kn/strings_tv.xml
index ef10e3a..e4b3314 100644
--- a/packages/SystemUI/res/values-kn/strings_tv.xml
+++ b/packages/SystemUI/res/values-kn/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> ಮೂಲಕ"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"ಅಧಿಸೂಚನೆಗಳು"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ಯಾವುದೇ ಅಧಿಸೂಚನೆಗಳಿಲ್ಲ"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index db96984..044086e 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"카메라를 사용할 수 있는 모든 앱 및 서비스에 대해 액세스가 차단 해제됩니다."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"카메라 또는 마이크를 사용할 수 있는 모든 앱 및 서비스에 대해 액세스가 차단 해제됩니다."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"기기"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"위로 스와이프하여 앱 전환"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"앱을 빠르게 전환하려면 오른쪽으로 드래그"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"최근 사용 버튼 전환"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"충전됨"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"충전 중"</string>
diff --git a/packages/SystemUI/res/values-ko/strings_tv.xml b/packages/SystemUI/res/values-ko/strings_tv.xml
index f9c723a..8849265 100644
--- a/packages/SystemUI/res/values-ko/strings_tv.xml
+++ b/packages/SystemUI/res/values-ko/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>에 연결됨"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"알림"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"알림 없음"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 42d684e..0a0bf4c 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Камераны колдонууга уруксат алган бардык колдонмолор менен кызматтар бөгөттөн чыгат."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Камераңызды же микрофонуңузду колдонууга уруксат алган бардык колдонмолор менен кызматтар бөгөттөн чыгат."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Түзмөк"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Башка колдонмого которулуу үчүн өйдө сүрүңүз"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Колдонмолорду тез которуштуруу үчүн, оңго сүйрөңүз"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Назар режимин өчүрүү/күйгүзүү"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Кубатталды"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Кубатталууда"</string>
@@ -1019,8 +1017,8 @@
     <string name="device_services" msgid="1549944177856658705">"Түзмөк кызматтары"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Аталышы жок"</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Жылдыруу"</string>
-    <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Тутум чабыттоосу жаңырды. Өзгөртүү үчүн, Жөндөөлөргө өтүңүз."</string>
-    <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Тутум чабыттоосун жаңыртуу үчүн Жөндөөлөргө өтүңүз"</string>
+    <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Тутум чабыттоосу жаңырды. Өзгөртүү үчүн, жөндөөлөргө өтүңүз."</string>
+    <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Тутум чабыттоосун жаңыртуу үчүн жөндөөлөргө өтүңүз"</string>
     <string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Көшүү режими"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"Чоңойтуу терезеси"</string>
     <string name="magnification_controls_title" msgid="8421106606708891519">"Чоңойтуу терезесин башкаруу каражаттары"</string>
diff --git a/packages/SystemUI/res/values-ky/strings_tv.xml b/packages/SystemUI/res/values-ky/strings_tv.xml
index 1dba865..128c7e0 100644
--- a/packages/SystemUI/res/values-ky/strings_tv.xml
+++ b/packages/SystemUI/res/values-ky/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> аркылуу"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Билдирмелер"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Билдирме жок"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index d6b8fa2..53a0ace 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ນີ້ຈະຍົກເລີກການບລັອກການເຂົ້າເຖິງແອັບ ແລະ ບໍລິການທັງໝົດທີ່ອະນຸຍາດໃຫ້ໃຊ້ກ້ອງຖ່າຍຮູບຂອງທ່ານ."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ນີ້ຈະປົດບລັອກການເຂົ້າເຖິງແອັບ ແລະ ບໍລິການທັງໝົດທີ່ອະນຸຍາດໃຫ້ໃຊ້ກ້ອງຖ່າຍຮູບ ຫຼື ໄມໂຄຣໂຟນຂອງທ່ານ."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"ອຸປະກອນ"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ປັດຂື້ນເພື່ອສະຫຼັບແອັບ"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ລາກໄປຂວາເພື່ອສະຫຼັບແອັບດ່ວນ"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ສະຫຼັບພາບຮວມ"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"ສາກເຕັມແລ້ວ."</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"ກຳລັງສາກໄຟ"</string>
diff --git a/packages/SystemUI/res/values-lo/strings_tv.xml b/packages/SystemUI/res/values-lo/strings_tv.xml
index a45fb45..b852456 100644
--- a/packages/SystemUI/res/values-lo/strings_tv.xml
+++ b/packages/SystemUI/res/values-lo/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"ຜ່ານ <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"ການແຈ້ງເຕືອນ"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ບໍ່ມີການແຈ້ງເຕືອນ"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 19e8fbf..56f187e 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -437,8 +437,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Tai atlikus visų programų ir paslaugų prieigos blokavimas panaikinamas ir joms leidžiama naudoti fotoaparatą."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Tai atlikus visų programų ir paslaugų prieigos blokavimas panaikinamas ir joms leidžiama naudoti fotoaparatą ar mikrofoną."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Įrenginys"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Perbraukite aukštyn, kad perjungtumėte programas"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Vilkite į dešinę, kad greitai perjungtumėte programas"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Perjungti apžvalgą"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Įkrautas"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Kraunamas"</string>
diff --git a/packages/SystemUI/res/values-lt/strings_tv.xml b/packages/SystemUI/res/values-lt/strings_tv.xml
index 8c329f9..7cd7507 100644
--- a/packages/SystemUI/res/values-lt/strings_tv.xml
+++ b/packages/SystemUI/res/values-lt/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Per „<xliff:g id="VPN_APP">%1$s</xliff:g>“"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Pranešimai"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nėra jokių pranešimų"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index f0d26c8..4522b98 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -435,8 +435,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Visas lietotnes un pakalpojumi, kuriem ir atļauts izmantot kameru, varēs tai piekļūt."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Visas lietotnes un pakalpojumi, kuriem ir atļauts izmantot kameru vai mikrofonu, varēs tiem piekļūt."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Ierīce"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Velciet augšup, lai pārslēgtu lietotnes"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Lai ātri pārslēgtu lietotnes, velciet pa labi"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Pārskata pārslēgšana"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Akumulators uzlādēts"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Notiek uzlāde"</string>
diff --git a/packages/SystemUI/res/values-lv/strings_tv.xml b/packages/SystemUI/res/values-lv/strings_tv.xml
index 758d28c..4c64843 100644
--- a/packages/SystemUI/res/values-lv/strings_tv.xml
+++ b/packages/SystemUI/res/values-lv/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Izmantojot: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Paziņojumi"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nav paziņojumu"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 719f519..5317bca 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Ова ќе го одблокира пристапот за сите апликации и услуги на кои им е дозволено користење на камерата."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Ова ќе го одблокира пристапот за сите апликации и услуги на кои им е дозволено користење на камерата или микрофонот."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Уред"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Повлечете нагоре за да се префрлите од една на друга апликација"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Повлечете надесно за брзо префрлање меѓу апликациите"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Вклучи/исклучи преглед"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Наполнета"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Се полни"</string>
diff --git a/packages/SystemUI/res/values-mk/strings_tv.xml b/packages/SystemUI/res/values-mk/strings_tv.xml
index 0dfbd79..55d9df7 100644
--- a/packages/SystemUI/res/values-mk/strings_tv.xml
+++ b/packages/SystemUI/res/values-mk/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Преку <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Известувања"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Нема известувања"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index cdb3a69..e798c7d 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"നിങ്ങളുടെ ക്യാമറ ഉപയോഗിക്കാൻ അനുവദിച്ചിരിക്കുന്ന എല്ലാ ആപ്പുകൾക്കും സേവനങ്ങൾക്കുമുള്ള ആക്‌സസ് ഇത് അൺബ്ലോക്ക് ചെയ്യുന്നു."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"നിങ്ങളുടെ ക്യാമറയോ മൈക്രോഫോണോ ഉപയോഗിക്കാൻ അനുവദിച്ചിരിക്കുന്ന എല്ലാ ആപ്പുകൾക്കും സേവനങ്ങൾക്കുമുള്ള ആക്‌സസ് ഇത് അൺബ്ലോക്ക് ചെയ്യുന്നു."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"ഉപകരണം"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ആപ്പുകൾ മാറാൻ മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യുക"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ആപ്പുകൾ പെട്ടെന്ന് മാറാൻ വലത്തോട്ട് വലിച്ചിടുക"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"അവലോകനം മാറ്റുക"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"ചാർജായി"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"ചാർജ് ചെയ്യുന്നു"</string>
diff --git a/packages/SystemUI/res/values-ml/strings_tv.xml b/packages/SystemUI/res/values-ml/strings_tv.xml
index 70cced8..6ae342cf 100644
--- a/packages/SystemUI/res/values-ml/strings_tv.xml
+++ b/packages/SystemUI/res/values-ml/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> വഴി"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"അറിയിപ്പുകൾ"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"അറിയിപ്പുകൾ ഒന്നുമില്ല"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index d16e479..0e4cac02 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Энэ нь таны камерыг ашиглах зөвшөөрөлтэй бүх апп болон үйлчилгээний хандалтыг блокоос гаргана."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Энэ нь таны камер эсвэл микрофоныг ашиглах зөвшөөрөлтэй бүх апп болон үйлчилгээний хандалтыг блокоос гаргана."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Төхөөрөмж"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Апп сэлгэхийн тулд дээш шударна уу"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Аппуудыг хурдан сэлгэхийн тулд баруун тийш чирнэ үү"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Тоймыг асаах/унтраах"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Цэнэглэгдсэн"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Цэнэглэж байна"</string>
diff --git a/packages/SystemUI/res/values-mn/strings_tv.xml b/packages/SystemUI/res/values-mn/strings_tv.xml
index 221d8ae..bbb302f 100644
--- a/packages/SystemUI/res/values-mn/strings_tv.xml
+++ b/packages/SystemUI/res/values-mn/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>-р"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Мэдэгдэл"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Мэдэгдэл байхгүй байна"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 9578370..45a9a1b 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"हे तुमचा कॅमेरा वापरण्याची परवानगी असलेल्या सर्व ॲप्स आणि सेवांसाठी अ‍ॅक्सेस अनब्लॉक करते."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"हे तुमचा कॅमेरा आणि मायक्रोफोन वापरण्याची परवानगी असलेल्या सर्व ॲप्स व सेवांसाठी अ‍ॅक्सेस अनब्लॉक करते."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"डिव्हाइस"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"अ‍ॅप्स स्विच करण्यासाठी वर स्वाइप करा"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"अ‍ॅप्स वर झटपट स्विच करण्यासाठी उजवीकडे ड्रॅग करा"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"अवलोकन टॉगल करा."</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"चार्ज झाली"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"चार्ज होत आहे"</string>
diff --git a/packages/SystemUI/res/values-mr/strings_tv.xml b/packages/SystemUI/res/values-mr/strings_tv.xml
index ac0cad1..d596d95 100644
--- a/packages/SystemUI/res/values-mr/strings_tv.xml
+++ b/packages/SystemUI/res/values-mr/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> द्वारे"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"सूचना"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"सूचना नाहीत"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 684d718..2349e28 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Tindakan ini menyahsekat akses bagi semua apl dan perkhidmatan yang dibenarkan untuk menggunakan kamera anda."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Tindakan ini menyahsekat akses bagi semua apl dan perkhidmatan yang dibenarkan untuk menggunakan kamera atau mikrofon anda."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Peranti"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Leret ke atas untuk menukar apl"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Seret ke kanan untuk beralih apl dengan pantas"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Togol Ikhtisar"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Sudah dicas"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Mengecas"</string>
diff --git a/packages/SystemUI/res/values-ms/strings_tv.xml b/packages/SystemUI/res/values-ms/strings_tv.xml
index 46e345e..e28d032 100644
--- a/packages/SystemUI/res/values-ms/strings_tv.xml
+++ b/packages/SystemUI/res/values-ms/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Melalui <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Pemberitahuan"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Tiada Pemberitahuan"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 4dddc71..23de47f 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"၎င်းက သင့်ကင်မရာသုံးရန် ခွင့်ပြုထားသော အက်ပ်နှင့် ဝန်ဆောင်မှုအားလုံးအတွက် သုံးခွင့်ကို ပြန်ဖွင့်ပေးသည်။"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"၎င်းက သင့်ကင်မရာ (သို့) မိုက်ခရိုဖုန်းသုံးရန် ခွင့်ပြုထားသော အက်ပ်နှင့် ဝန်ဆောင်မှုအားလုံးအတွက် သုံးခွင့်ကို ပြန်ဖွင့်ပေးသည်။"</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"စက်"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"အက်ပ်များကို ဖွင့်ရန် အပေါ်သို့ ပွတ်ဆွဲပါ"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"အက်ပ်များကို ပြောင်းရန် ညာဘက်သို့ ဖိဆွဲပါ"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ဖွင့်၊ ပိတ် အနှစ်ချုပ်"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"အားသွင်းပြီး"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"အားသွင်းနေ"</string>
diff --git a/packages/SystemUI/res/values-my/strings_tv.xml b/packages/SystemUI/res/values-my/strings_tv.xml
index 268c554..848c403 100644
--- a/packages/SystemUI/res/values-my/strings_tv.xml
+++ b/packages/SystemUI/res/values-my/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> မှတစ်ဆင့်"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"အကြောင်းကြားချက်များ"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"အကြောင်းကြားချက်များ မရှိပါ"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index a0db779..9c18b95 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Dette opphever blokkeringen av tilgang for alle apper og tjenester som har tillatelse til å bruke kameraet."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Dette opphever blokkeringen av tilgang for alle apper og tjenester som har tillatelse til å bruke kameraet eller mikrofonen."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Enhet"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Sveip opp for å bytte apper"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Dra til høyre for å bytte apper raskt"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Slå oversikten av eller på"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Oppladet"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Lader"</string>
diff --git a/packages/SystemUI/res/values-nb/strings_tv.xml b/packages/SystemUI/res/values-nb/strings_tv.xml
index c5767dd..11de50a 100644
--- a/packages/SystemUI/res/values-nb/strings_tv.xml
+++ b/packages/SystemUI/res/values-nb/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Varsler"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ingen varsler"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index d719123..9ae2d43e2 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"यसो गर्नुभयो भने क्यामेरा प्रयोग गर्ने अनुमति दिइएका सबै एप तथा सेवाहरूका लागि सो अनुमति अनब्लक गरिन्छ।"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"यसो गर्नुभयो भने क्यामेरा वा माइक्रोफोन प्रयोग गर्ने अनुमति दिइएका सबै एप तथा सेवाहरूका लागि सो अनुमति अनब्लक गरिन्छ।"</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"यन्त्र"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"एपहरू बदल्न माथितिर स्वाइप गर्नुहोस्"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"एपहरू बदल्न द्रुत गतिमा दायाँतिर ड्र्याग गर्नुहोस्"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"परिदृश्य टगल गर्नुहोस्"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"चार्ज भयो"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"चार्ज हुँदै छ"</string>
diff --git a/packages/SystemUI/res/values-ne/strings_tv.xml b/packages/SystemUI/res/values-ne/strings_tv.xml
index 925f7b76..0bcc1cc 100644
--- a/packages/SystemUI/res/values-ne/strings_tv.xml
+++ b/packages/SystemUI/res/values-ne/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> मार्फत"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"सूचनाहरू"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"कुनै पनि सूचना छैन"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index b74892a..155d1ad 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Hiermee hef je de toegangsblokkering op voor alle apps en services die rechten hebben om je camera te gebruiken."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Hiermee hef je de toegangsblokkering op voor alle apps en services die rechten hebben om je camera of microfoon te gebruiken."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Apparaat"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Swipe omhoog om te schakelen tussen apps"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Sleep naar rechts om snel tussen apps te schakelen"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Overzicht aan- of uitzetten"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Opgeladen"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Opladen"</string>
diff --git a/packages/SystemUI/res/values-nl/strings_tv.xml b/packages/SystemUI/res/values-nl/strings_tv.xml
index 22d3b88..02c00ec 100644
--- a/packages/SystemUI/res/values-nl/strings_tv.xml
+++ b/packages/SystemUI/res/values-nl/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Meldingen"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Geen meldingen"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index b8a104f..4d44690b 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ଆପଣଙ୍କ କ୍ୟାମେରାକୁ ବ୍ୟବହାର କରିବା ପାଇଁ ଅନୁମତି ଦିଆଯାଇଥିବା ସମସ୍ତ ଆପ୍ ଓ ସେବା ପାଇଁ ଏହା ଆକ୍ସେସକୁ ଅନବ୍ଲକ୍ କରେ।"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ଆପଣଙ୍କ କ୍ୟାମେରା କିମ୍ବା ମାଇକ୍ରୋଫୋନକୁ ବ୍ୟବହାର କରିବା ପାଇଁ ଅନୁମତି ଦିଆଯାଇଥିବା ସମସ୍ତ ଆପ୍ ଓ ସେବା ପାଇଁ ଏହା ଆକ୍ସେସକୁ ଅନବ୍ଲକ୍ କରେ।"</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"ଡିଭାଇସ୍"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ଆପ୍‌କୁ ବଦଳ କରିବା ପାଇଁ ସ୍ଵାଇପ୍ କରନ୍ତୁ"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ଆପ୍‌ଗୁଡ଼ିକ ମଧ୍ୟରେ ଶୀଘ୍ର ବଦଳ କରିବା ପାଇଁ ଡାହାଣକୁ ଡ୍ରାଗ୍ କରନ୍ତୁ"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ସଂକ୍ଷିପ୍ତ ବିବରଣୀକୁ ଟୋଗଲ୍ କରନ୍ତୁ"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"ଚାର୍ଜ ହୋଇଗଲା"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"ଚାର୍ଜ କରାଯାଉଛି"</string>
diff --git a/packages/SystemUI/res/values-or/strings_tv.xml b/packages/SystemUI/res/values-or/strings_tv.xml
index 707c49e..8289068 100644
--- a/packages/SystemUI/res/values-or/strings_tv.xml
+++ b/packages/SystemUI/res/values-or/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> ମାଧ୍ୟମରେ"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"କୌଣସି ବିଜ୍ଞପ୍ତି ନାହିଁ"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 45c4f0f..7bb60a0 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ਇਹ ਉਹਨਾਂ ਐਪਾਂ ਅਤੇ ਸੇਵਾਵਾਂ ਲਈ ਪਹੁੰਚ ਨੂੰ ਅਣਬਲਾਕ ਕਰਦਾ ਹੈ ਜਿਨ੍ਹਾਂ ਨੂੰ ਤੁਹਾਡਾ ਕੈਮਰਾ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੱਤੀ ਗਈ ਹੈ।"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ਇਹ ਉਹਨਾਂ ਐਪਾਂ ਅਤੇ ਸੇਵਾਵਾਂ ਲਈ ਪਹੁੰਚ ਨੂੰ ਅਣਬਲਾਕ ਕਰਦਾ ਹੈ ਜਿਨ੍ਹਾਂ ਨੂੰ ਤੁਹਾਡਾ ਕੈਮਰਾ ਜਾਂ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੱਤੀ ਗਈ ਹੈ।"</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"ਡੀਵਾਈਸ"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ਐਪਾਂ ਵਿਚਾਲੇ ਅਦਲਾ-ਬਦਲੀ ਕਰਨ ਲਈ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ਐਪਾਂ ਵਿਚਾਲੇ ਤੇਜ਼ੀ ਨਾਲ ਅਦਲਾ-ਬਦਲੀ ਕਰਨ ਲਈ ਸੱਜੇ ਪਾਸੇ ਵੱਲ ਘਸੀਟੋ"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ਰੂਪ-ਰੇਖਾ ਨੂੰ ਟੌਗਲ ਕਰੋ"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"ਚਾਰਜ ਹੋਇਆ"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"ਚਾਰਜ ਕਰ ਰਿਹਾ ਹੈ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings_tv.xml b/packages/SystemUI/res/values-pa/strings_tv.xml
index c076194..22fcce8 100644
--- a/packages/SystemUI/res/values-pa/strings_tv.xml
+++ b/packages/SystemUI/res/values-pa/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> ਰਾਹੀਂ"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"ਸੂਚਨਾਵਾਂ"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ਕੋਈ ਸੂਚਨਾ ਨਹੀਂ"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index b8da6bb..ea6f225 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -437,8 +437,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Spowoduje to odblokowanie dostępu dla wszystkich aplikacji i usług, które mają uprawnienia do korzystania z aparatu."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Spowoduje to odblokowanie dostępu dla wszystkich aplikacji i usług, które mają uprawnienia do korzystania z aparatu lub mikrofonu."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Urządzenie"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Przesuń w górę, by przełączyć aplikacje"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Szybko przeciągnij w prawo, by przełączyć aplikacje"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Przełącz Przegląd"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Naładowana"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Ładowanie"</string>
diff --git a/packages/SystemUI/res/values-pl/strings_tv.xml b/packages/SystemUI/res/values-pl/strings_tv.xml
index e63aade..2371b5e 100644
--- a/packages/SystemUI/res/values-pl/strings_tv.xml
+++ b/packages/SystemUI/res/values-pl/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Przez: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Powiadomienia"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Brak powiadomień"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 2755508..2f1501b 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Essa ação desbloqueia o acesso para todos os apps e serviços com autorização para usar sua câmera."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Essa ação desbloqueia o acesso para todos os apps e serviços com autorização para usar sua câmera ou seu microfone."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Deslize para cima para mudar de app"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Arraste para a direita para mudar rapidamente de app"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Alternar Visão geral"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Carregado"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Carregando"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings_tv.xml b/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
index 2ea8152..d29bc6a 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
@@ -26,4 +26,10 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificações"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nenhuma notificação"</string>
+    <string name="mic_recording_announcement" msgid="7587123608060316575">"O microfone está gravando"</string>
+    <string name="camera_recording_announcement" msgid="7240177719403759112">"A câmera está gravando"</string>
+    <string name="mic_and_camera_recording_announcement" msgid="8599231390508812667">"A câmera e o microfone estão gravando"</string>
+    <string name="mic_stopped_recording_announcement" msgid="7301537004900721242">"O microfone parou de gravar"</string>
+    <string name="camera_stopped_recording_announcement" msgid="8540496432367032801">"A câmera parou de gravar"</string>
+    <string name="mic_camera_stopped_recording_announcement" msgid="8708524579599977412">"A câmera e o microfone pararam de gravar"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 15c2874..563e99d 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Isto desbloqueia o acesso a todas as apps e serviços com autorização para utilizar a sua câmara."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Isto desbloqueia o acesso a todas as apps e serviços com autorização para utilizar a sua câmara ou microfone."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Deslizar rapidamente para cima para mudar de app"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Arraste para a direita para mudar rapidamente de app."</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Ativar/desativar Vista geral"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Carregada"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"A carregar"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings_tv.xml b/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
index 8ce3e30..883fa3a 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Através de <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificações"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Sem notificações"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 2755508..2f1501b 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Essa ação desbloqueia o acesso para todos os apps e serviços com autorização para usar sua câmera."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Essa ação desbloqueia o acesso para todos os apps e serviços com autorização para usar sua câmera ou seu microfone."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Deslize para cima para mudar de app"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Arraste para a direita para mudar rapidamente de app"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Alternar Visão geral"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Carregado"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Carregando"</string>
diff --git a/packages/SystemUI/res/values-pt/strings_tv.xml b/packages/SystemUI/res/values-pt/strings_tv.xml
index 2ea8152..d29bc6a 100644
--- a/packages/SystemUI/res/values-pt/strings_tv.xml
+++ b/packages/SystemUI/res/values-pt/strings_tv.xml
@@ -26,4 +26,10 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificações"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nenhuma notificação"</string>
+    <string name="mic_recording_announcement" msgid="7587123608060316575">"O microfone está gravando"</string>
+    <string name="camera_recording_announcement" msgid="7240177719403759112">"A câmera está gravando"</string>
+    <string name="mic_and_camera_recording_announcement" msgid="8599231390508812667">"A câmera e o microfone estão gravando"</string>
+    <string name="mic_stopped_recording_announcement" msgid="7301537004900721242">"O microfone parou de gravar"</string>
+    <string name="camera_stopped_recording_announcement" msgid="8540496432367032801">"A câmera parou de gravar"</string>
+    <string name="mic_camera_stopped_recording_announcement" msgid="8708524579599977412">"A câmera e o microfone pararam de gravar"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index cf957a4..2102600 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -435,8 +435,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Astfel, deblocați accesul pentru toate aplicațiile și serviciile care au permisiunea de a folosi camera."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Astfel, deblocați accesul pentru toate aplicațiile și serviciile care au permisiunea de a folosi camera sau microfonul."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispozitiv"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Glisați în sus pentru a comuta între aplicații"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Glisați la dreapta pentru a comuta rapid între aplicații"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Comutați secțiunea Recente"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Încărcată"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Se încarcă"</string>
diff --git a/packages/SystemUI/res/values-ro/strings_tv.xml b/packages/SystemUI/res/values-ro/strings_tv.xml
index c64a492..9f28693 100644
--- a/packages/SystemUI/res/values-ro/strings_tv.xml
+++ b/packages/SystemUI/res/values-ro/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Prin <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificări"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nicio notificare"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 9fd91f1..eeb1f3e 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -437,8 +437,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Будет снята блокировка доступа для всех приложений и сервисов с разрешением на использование камеры."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Будет снята блокировка доступа для всех приложений и сервисов с разрешением на использование камеры или микрофона."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Устройство"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Чтобы переключиться между приложениями, проведите по экрану вверх."</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Перетащите вправо, чтобы быстро переключиться между приложениями"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Переключить режим обзора"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Батарея заряжена"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Зарядка батареи"</string>
diff --git a/packages/SystemUI/res/values-ru/strings_tv.xml b/packages/SystemUI/res/values-ru/strings_tv.xml
index 8ce0dc2..e2162ea 100644
--- a/packages/SystemUI/res/values-ru/strings_tv.xml
+++ b/packages/SystemUI/res/values-ru/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Через приложение <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Уведомления"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Уведомлений нет."</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 4235d81..247b7a5 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"මෙය ඔබගේ කැමරාව භාවිතා කිරීමට ඉඩ දී ඇති සියලු යෙදුම් සහ සේවා සඳහා ප්‍රවේශය අවහිර කිරීම ඉවත් කරයි."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"මෙය ඔබගේ කැමරාව හෝ මයික්‍රෆෝනය භාවිත කිරීමට ඉඩ දී ඇති සියලු යෙදුම් සහ සේවා සඳහා ප්‍රවේශය අවහිර කිරීම ඉවත් කරයි."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"උපාංගය"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"යෙදුම් මාරු කිරීමට ස්වයිප් කරන්න"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ඉක්මනින් යෙදුම් මාරු කිරීමට දකුණට අදින්න"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"දළ විශ්ලේෂණය ටොගල කරන්න"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"අරෝපිතයි"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"ආරෝපණය වෙමින්"</string>
diff --git a/packages/SystemUI/res/values-si/strings_tv.xml b/packages/SystemUI/res/values-si/strings_tv.xml
index 3067be3..b750988 100644
--- a/packages/SystemUI/res/values-si/strings_tv.xml
+++ b/packages/SystemUI/res/values-si/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> හරහා"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"දැනුම්දීම්"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"දැනුම්දීම් නැත"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 14aa0a7..74b24bd 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -437,8 +437,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Táto akcia odblokuje prístup všetkým aplikáciám a službám, ktoré majú povolené používať fotoaparát."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Táto akcia odblokuje prístup všetkým aplikáciám a službám, ktoré majú povolené používať fotoaparát alebo mikrofón."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Zariadenie"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Potiahnutím nahor prepnete aplikácie"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Presunutím doprava rýchlo prepnete aplikácie"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Prepnúť prehľad"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Nabitá"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Nabíja sa"</string>
diff --git a/packages/SystemUI/res/values-sk/strings_tv.xml b/packages/SystemUI/res/values-sk/strings_tv.xml
index b37648d..2b74267 100644
--- a/packages/SystemUI/res/values-sk/strings_tv.xml
+++ b/packages/SystemUI/res/values-sk/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Cez: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Upozornenia"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Žiadne upozornenia"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index a553ff22..cfb89d4 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -437,8 +437,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"S tem boste odblokirali dostop za vse aplikacije in storitve, ki imajo dovoljenje za uporabo fotoaparata."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"S tem boste odblokirali dostop za vse aplikacije in storitve, ki imajo dovoljenje za uporabo fotoaparata ali mikrofona."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Naprava"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Za preklop aplikacij povlecite navzgor"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Povlecite v desno za hiter preklop med aplikacijami"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Vklop/izklop pregleda"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Baterija napolnjena"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Polnjenje"</string>
diff --git a/packages/SystemUI/res/values-sl/strings_tv.xml b/packages/SystemUI/res/values-sl/strings_tv.xml
index 1f66138..2ef9705 100644
--- a/packages/SystemUI/res/values-sl/strings_tv.xml
+++ b/packages/SystemUI/res/values-sl/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Prek storitve <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Obvestila"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ni obvestil"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 5ce3cd4..f7753c7 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Kjo zhbllokon qasjen për të gjitha aplikacionet dhe shërbimet që lejohen të përdorin kamerën tënde."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Kjo zhbllokon qasjen për të gjitha aplikacionet dhe shërbimet që lejohen të përdorin kamerën ose mikrofonin tënd."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Pajisja"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Rrëshqit shpejt lart për të ndërruar aplikacionet"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Zvarrit djathtas për të ndërruar aplikacionet me shpejtësi"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Kalo te përmbledhja"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"I karikuar"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Po karikohet"</string>
diff --git a/packages/SystemUI/res/values-sq/strings_tv.xml b/packages/SystemUI/res/values-sq/strings_tv.xml
index fb74e38..ece5982 100644
--- a/packages/SystemUI/res/values-sq/strings_tv.xml
+++ b/packages/SystemUI/res/values-sq/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Nëpërmjet <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Njoftimet"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Asnjë njoftim"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 282d18b..73ecc4c 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -435,8 +435,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Овим ће се одблокирати приступ за све апликације и услуге које имају дозволу за коришћење камере."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Овим ће се одблокирати приступ за све апликације и услуге које имају дозволу за коришћење камере или микрофона."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Уређај"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Превуците нагоре да бисте мењали апликације"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Превуците удесно да бисте брзо променили апликације"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Укључи/искључи преглед"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Напуњена је"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Пуни се"</string>
diff --git a/packages/SystemUI/res/values-sr/strings_tv.xml b/packages/SystemUI/res/values-sr/strings_tv.xml
index 59151da..38b106b 100644
--- a/packages/SystemUI/res/values-sr/strings_tv.xml
+++ b/packages/SystemUI/res/values-sr/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Преко: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Обавештења"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Нема обавештења"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 7e0dbd7..c27cd83 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -158,21 +158,21 @@
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Slutför genom att trycka på Bekräfta"</string>
     <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentiserad"</string>
     <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Använd pinkod"</string>
-    <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Använd grafiskt lösenord"</string>
+    <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Använd mönster"</string>
     <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Använd lösenord"</string>
     <string name="biometric_dialog_wrong_pin" msgid="1878539073972762803">"Fel pinkod"</string>
-    <string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Fel grafiskt lösenord"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Fel mönster"</string>
     <string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Fel lösenord"</string>
     <string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"För många felaktiga försök.\nFörsök igen om <xliff:g id="NUMBER">%d</xliff:g> sekunder."</string>
     <string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Försök igen. Försök <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> av <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
     <string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Din data raderas."</string>
-    <string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Enhetens data raderas om du anger fel grafiskt lösenord vid nästa försök."</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Enhetens data raderas om du ritar fel mönster vid nästa försök."</string>
     <string name="biometric_dialog_last_pin_attempt_before_wipe_device" msgid="9151756675698215723">"Enhetens data raderas om du anger fel pinkod vid nästa försök."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_device" msgid="2363778585575998317">"Enhetens data raderas om du anger fel lösenord vid nästa försök."</string>
-    <string name="biometric_dialog_last_pattern_attempt_before_wipe_user" msgid="8400180746043407270">"Användaren raderas om du anger fel grafiskt lösenord vid nästa försök."</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_user" msgid="8400180746043407270">"Användaren raderas om du ritar fel mönster vid nästa försök."</string>
     <string name="biometric_dialog_last_pin_attempt_before_wipe_user" msgid="4159878829962411168">"Användaren raderas om du anger fel pinkod vid nästa försök."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_user" msgid="4695682515465063885">"Den här användaren raderas om du anger fel lösenord vid nästa försök."</string>
-    <string name="biometric_dialog_last_pattern_attempt_before_wipe_profile" msgid="6045224069529284686">"Jobbprofilen och dess data raderas om du anger fel grafiskt lösenord vid nästa försök."</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_profile" msgid="6045224069529284686">"Jobbprofilen och dess data raderas om du ritar fel mönster vid nästa försök."</string>
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Jobbprofilen och dess data raderas om du anger fel pinkod vid nästa försök."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Din jobbprofil och dess data raderas om du anger fel lösenord vid nästa försök."</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_device" msgid="6585503524026243042">"För många felaktiga försök. Enhetens data raderas."</string>
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Detta återaktiverar åtkomsten för alla appar och tjänster som tillåts att använda kameran."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Detta återaktiverar åtkomsten för alla appar och tjänster som tillåts att använda kameran eller mikrofonen."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Enhet"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Byt appar genom att svepa uppåt"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Tryck och dra åt höger för att snabbt byta mellan appar"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Aktivera och inaktivera översikten"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Laddat"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Laddar"</string>
diff --git a/packages/SystemUI/res/values-sv/strings_tv.xml b/packages/SystemUI/res/values-sv/strings_tv.xml
index fd8fa4b..22f6baa 100644
--- a/packages/SystemUI/res/values-sv/strings_tv.xml
+++ b/packages/SystemUI/res/values-sv/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Aviseringar"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Inga aviseringar"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index e603fc9..7ac26be4 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Hatua hii huruhusu programu na huduma zote zenye idhini zitumie kamera yako."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Hatua hii huruhusu programu na huduma zote zenye idhini zitumie kamera au maikrofoni yako."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Kifaa"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Telezesha kidole juu ili ubadilishe programu"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Buruta kulia ili ubadilishe programu haraka"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Washa Muhtasari"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Betri imejaa"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Inachaji"</string>
diff --git a/packages/SystemUI/res/values-sw/strings_tv.xml b/packages/SystemUI/res/values-sw/strings_tv.xml
index 8f6880d..086a098 100644
--- a/packages/SystemUI/res/values-sw/strings_tv.xml
+++ b/packages/SystemUI/res/values-sw/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Kupitia <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Arifa"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Hakuna Arifa"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index d1d6d0d..426ddd4 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"உங்கள் கேமராவைப் பயன்படுத்த அனுமதிக்கப்பட்டுள்ள அனைத்து ஆப்ஸ் மற்றும் சேவைகளை அணுகுவதற்கான தடுப்பை இது நீக்கும்."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"உங்கள் கேமராவையோ மைக்ரோஃபோனையோ பயன்படுத்த அனுமதிக்கப்பட்டுள்ள அனைத்து ஆப்ஸ் மற்றும் சேவைகளை அணுகுவதற்கான தடுப்பை இது நீக்கும்."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"சாதனம்"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ஆப்ஸிற்கு இடையே மாற்றுவதற்கு, மேல்நோக்கி ஸ்வைப் செய்க"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ஆப்ஸை வேகமாக மாற்ற, வலப்புறம் இழுக்கவும்"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"மேலோட்டப் பார்வையை நிலைமாற்று"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"சார்ஜ் செய்யப்பட்டது"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"சார்ஜ் ஆகிறது"</string>
diff --git a/packages/SystemUI/res/values-ta/strings_tv.xml b/packages/SystemUI/res/values-ta/strings_tv.xml
index 9c62d8cf..398ffe9 100644
--- a/packages/SystemUI/res/values-ta/strings_tv.xml
+++ b/packages/SystemUI/res/values-ta/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> வழியாக"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"அறிவிப்புகள்"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"அறிவிப்புகள் எதுவுமில்லை"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 2bc2923..020d9b4 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"మీ కెమెరాను ఉపయోగించడానికి అనుమతి పొందిన అన్ని యాప్‌లు, సర్వీస్‌లకు యాక్సెస్‌ను ఇది అన్‌బ్లాక్ చేస్తుంది."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"మీ కెమెరాను లేదా మైక్రోఫోన్‌ను ఉపయోగించడానికి అనుమతి పొందిన అన్ని యాప్‌లు, సర్వీస్‌లకు యాక్సెస్‌ను ఇది అన్‌బ్లాక్ చేస్తుంది."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"పరికరం"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"యాప్‌లను మార్చడం కోసం ఎగువకు స్వైప్ చేయండి"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"యాప్‌లను శీఘ్రంగా స్విచ్ చేయడానికి కుడి వైపుకు లాగండి"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"స్థూలదృష్టిని టోగుల్ చేయి"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"ఛార్జ్ చేయబడింది"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"ఛార్జ్ అవుతోంది"</string>
diff --git a/packages/SystemUI/res/values-te/strings_tv.xml b/packages/SystemUI/res/values-te/strings_tv.xml
index 1879edd..33c9ec9 100644
--- a/packages/SystemUI/res/values-te/strings_tv.xml
+++ b/packages/SystemUI/res/values-te/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> ద్వారా"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"నోటిఫికేషన్‌లు"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"నోటిఫికేషన్‌లు లేవు"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 69b4999..ce469f7 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"การดำเนินการนี้จะเลิกบล็อกสิทธิ์เข้าถึงของแอปและบริการทั้งหมดที่ได้รับอนุญาตให้ใช้กล้องของคุณ"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"การดำเนินการนี้จะเลิกบล็อกสิทธิ์เข้าถึงของแอปและบริการทั้งหมดที่ได้รับอนุญาตให้ใช้กล้องหรือไมโครโฟนของคุณ"</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"อุปกรณ์"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"เลื่อนขึ้นเพื่อสลับแอป"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ลากไปทางขวาเพื่อสลับแอปอย่างรวดเร็ว"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"สลับภาพรวม"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"ชาร์จแล้ว"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"กำลังชาร์จ"</string>
diff --git a/packages/SystemUI/res/values-th/strings_tv.xml b/packages/SystemUI/res/values-th/strings_tv.xml
index 0724821..57cff1f 100644
--- a/packages/SystemUI/res/values-th/strings_tv.xml
+++ b/packages/SystemUI/res/values-th/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"ผ่าน <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"การแจ้งเตือน"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ไม่มีการแจ้งเตือน"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index d65f16d..8d0a847 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Ina-unblock nito ang access para sa lahat ng app at serbisyong pinapayagang gumamit ng iyong camera."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Ina-unblock nito ang access para sa lahat ng app at serbisyong pinapayagang gumamit ng iyong camera o mikropono."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Device"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Mag-swipe pataas upang lumipat ng app"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"I-drag pakanan para mabilisang magpalipat-lipat ng app"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"I-toggle ang Overview"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Tapos nang mag-charge"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Nagcha-charge"</string>
diff --git a/packages/SystemUI/res/values-tl/strings_tv.xml b/packages/SystemUI/res/values-tl/strings_tv.xml
index 8dcc22f..8be6a86 100644
--- a/packages/SystemUI/res/values-tl/strings_tv.xml
+++ b/packages/SystemUI/res/values-tl/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Sa pamamagitan ng <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Mga Notification"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Walang Notification"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index bbae9c9..6b55d1c 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Bu işlem, kameranızı kullanmasına izin verilen tüm uygulama ve hizmetlere erişimin engellemesini kaldırır."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Bu işlem, kamera veya mikrofonunuzu kullanmasına izin verilen tüm uygulama ve hizmetlere erişimin engellemesini kaldırır."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Cihaz"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Uygulamalar arasında geçiş yapmak için yukarı kaydırın"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Uygulamaları hızlıca değiştirmek için sağa kaydırın"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Genel bakışı aç/kapat"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Şarj oldu"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Şarj oluyor"</string>
diff --git a/packages/SystemUI/res/values-tr/strings_tv.xml b/packages/SystemUI/res/values-tr/strings_tv.xml
index 49e76af..28b2d77 100644
--- a/packages/SystemUI/res/values-tr/strings_tv.xml
+++ b/packages/SystemUI/res/values-tr/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> üzerinden"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Bildirimler"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Bildirim Yok"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index d4d1816..0a5992b 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -437,8 +437,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Усі додатки та сервіси, яким дозволено користуватися вашою камерою, отримають доступ."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Усі додатки та сервіси, яким дозволено користуватися вашою камерою чи мікрофоном, отримають доступ."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Пристрій"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Проводьте пальцем угору, щоб переходити між додатками"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Перетягуйте праворуч, щоб швидко переходити між додатками"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Увімкнути або вимкнути огляд"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Заряджено"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Заряджається"</string>
diff --git a/packages/SystemUI/res/values-uk/strings_tv.xml b/packages/SystemUI/res/values-uk/strings_tv.xml
index 170b068..c86cf31 100644
--- a/packages/SystemUI/res/values-uk/strings_tv.xml
+++ b/packages/SystemUI/res/values-uk/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Через <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Сповіщення"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Немає сповіщень"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index e8cb657..5a96fa8 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"اس سے آپ کا کیمرا استعمال کرنے کے لیے اجازت یافتہ سبھی ایپس اور سروسز کے لیے رسائی غیر مسدود ہو جاتی ہے۔"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"اس سے آپ کا کیمرا یا مائیکروفون استعمال کرنے کے لیے اجازت یافتہ سبھی ایپس اور سروسز کے لیے رسائی غیر مسدود ہو جاتی ہے۔"</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"آلہ"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ایپس سوئچ کرنے کیلئے اوپر سوائپ کریں"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"تیزی سے ایپس کو سوئچ کرنے کے لیے دائیں طرف گھسیٹیں"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"مجموعی جائزہ ٹوگل کریں"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"چارج ہوگئی"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"چارج ہو رہی ہے"</string>
diff --git a/packages/SystemUI/res/values-ur/strings_tv.xml b/packages/SystemUI/res/values-ur/strings_tv.xml
index fbaa3f6..5810482 100644
--- a/packages/SystemUI/res/values-ur/strings_tv.xml
+++ b/packages/SystemUI/res/values-ur/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"بذریعہ <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"اطلاعات"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"کوئی اطلاع نہیں ہے"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index b722acc..d96ea064 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Kamerangizdan foydalanishga ruxsat berilgan barcha ilovalar va xizmatlar uchun ruxsatni blokdan chiqaradi."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Kamera va mikrofoningizdan foydalanishga ruxsat berilgan barcha ilovalar va xizmatlar uchun ruxsatni blokdan chiqaradi."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Qurilma"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Ilovalarni almashtirish uchun ekranni tepaga suring"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Ilovalarni tezkor almashtirish uchun o‘ngga torting"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Umumiy nazar rejimini almashtirish"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Quvvat oldi"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Quvvat olmoqda"</string>
diff --git a/packages/SystemUI/res/values-uz/strings_tv.xml b/packages/SystemUI/res/values-uz/strings_tv.xml
index f4b4b08..afa82bc 100644
--- a/packages/SystemUI/res/values-uz/strings_tv.xml
+++ b/packages/SystemUI/res/values-uz/strings_tv.xml
@@ -26,4 +26,10 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> orqali"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Bildirishnomalar"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Bildirishnomalar yoʻq"</string>
+    <string name="mic_recording_announcement" msgid="7587123608060316575">"Mikrofon yozib olmoqda"</string>
+    <string name="camera_recording_announcement" msgid="7240177719403759112">"Kamera yozib olmoqda"</string>
+    <string name="mic_and_camera_recording_announcement" msgid="8599231390508812667">"Kamera va mikrofon yozib olmoqda"</string>
+    <string name="mic_stopped_recording_announcement" msgid="7301537004900721242">"Mikrofon yozib olishni toʻxtatdi"</string>
+    <string name="camera_stopped_recording_announcement" msgid="8540496432367032801">"Kamera yozib olishni toʻxtatdi"</string>
+    <string name="mic_camera_stopped_recording_announcement" msgid="8708524579599977412">"Kamera va mikrofon yozib olishni toʻxtatdi"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index de7fbcbe..54b4967 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Thao tác này sẽ bỏ chặn quyền truy cập cho mọi ứng dụng và dịch vụ được phép sử dụng máy ảnh của bạn."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Thao tác này sẽ bỏ chặn quyền truy cập cho mọi ứng dụng và dịch vụ được phép sử dụng máy ảnh hoặc micrô của bạn."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Thiết bị"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Vuốt lên để chuyển đổi ứng dụng"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Kéo sang phải để chuyển đổi nhanh giữa các ứng dụng"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Bật/tắt chế độ xem Tổng quan"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Đã sạc đầy"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Đang sạc"</string>
diff --git a/packages/SystemUI/res/values-vi/strings_tv.xml b/packages/SystemUI/res/values-vi/strings_tv.xml
index 3dfc8c1..21f5471 100644
--- a/packages/SystemUI/res/values-vi/strings_tv.xml
+++ b/packages/SystemUI/res/values-vi/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Thông qua <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Thông báo"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Không có thông báo"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index e432c62..3cbcf31 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"这将会为所有获准使用您摄像头的应用和服务启用这项权限。"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"这将会为所有获准使用您的摄像头或麦克风的应用和服务启用这项权限。"</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"设备"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"向上滑动可切换应用"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"向右拖动可快速切换应用"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"切换概览"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"已充满"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"正在充电"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings_tv.xml b/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
index 1e599ca..ca814a3 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"通过“<xliff:g id="VPN_APP">%1$s</xliff:g>”"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"通知"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"没有通知"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index ea9f1fc..726947f 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"解除封鎖後,凡有存取權的應用程式和服務都可使用您的相機。"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"解除封鎖後,凡有存取權的應用程式和服務都可使用您的相機或麥克風。"</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"裝置"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"向上滑動即可切換應用程式"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"向右拖曳即可快速切換應用程式"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"切換概覽"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"已完成充電"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"充電中"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings_tv.xml b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
index 92b1762..f992b62 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"透過 <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"通知"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"沒有通知"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 7e9d2fe..437bece 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"這麼做可允許所有應用程式和服務使用相機。"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"這麼做可允許所有應用程式和服務使用相機或麥克風。"</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"裝置"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"向上滑動即可切換應用程式"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"向右拖曳即可快速切換應用程式"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"切換總覽"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"已充飽"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"充電中"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings_tv.xml b/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
index db0781a..94135d2 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"透過「<xliff:g id="VPN_APP">%1$s</xliff:g>」"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"通知"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"沒有通知"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index eac6f74..6b7d577 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -433,8 +433,6 @@
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Lokhu kuvulela ukufinyelela kwawo wonke ama-app namasevisi avunyelwe ukusebenzisa ikhamera yakho."</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Lokhu kuvulela ukufinyelela kwawo wonke ama-app namasevisi avunyelwe ukusebenzisa ikhamera yakho noma imakrofoni."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Idivayisi"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Swayiphela phezulu ukuze ushintshe izinhlelo zokusebenza"</string>
-    <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Hudula ngqo ukuze ushintshe ngokushesha izinhlelo zokusebenza"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Guqula ukubuka konke"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Kushajiwe"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Iyashaja"</string>
diff --git a/packages/SystemUI/res/values-zu/strings_tv.xml b/packages/SystemUI/res/values-zu/strings_tv.xml
index a9b7597..79a6575 100644
--- a/packages/SystemUI/res/values-zu/strings_tv.xml
+++ b/packages/SystemUI/res/values-zu/strings_tv.xml
@@ -26,4 +26,16 @@
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Nge-<xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Izaziso"</string>
     <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Azikho Izaziso"</string>
+    <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+    <skip />
+    <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+    <skip />
+    <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+    <skip />
+    <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+    <skip />
+    <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+    <skip />
+    <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 7485ef8..34f8503 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -906,8 +906,8 @@
     <dimen name="keyguard_affordance_height">48dp</dimen>
     <dimen name="keyguard_affordance_width">48dp</dimen>
 
-    <dimen name="keyguard_affordance_wallet_height">48dp</dimen>
-    <dimen name="keyguard_affordance_wallet_width">48dp</dimen>
+    <dimen name="keyguard_affordance_fixed_height">48dp</dimen>
+    <dimen name="keyguard_affordance_fixed_width">48dp</dimen>
 
     <dimen name="keyguard_affordance_horizontal_offset">32dp</dimen>
     <dimen name="keyguard_affordance_vertical_offset">32dp</dimen>
@@ -921,6 +921,7 @@
     <dimen name="keyguard_lock_padding">20dp</dimen>
 
     <dimen name="keyguard_indication_margin_bottom">32dp</dimen>
+    <dimen name="lock_icon_margin_bottom">98dp</dimen>
 
     <!-- The text size for battery level -->
     <dimen name="battery_level_text_size">12sp</dimen>
@@ -1266,6 +1267,8 @@
     <!--  Three privacy items. This value must not be exceeded  -->
     <dimen name="ongoing_appops_chip_max_width">76dp</dimen>
     <dimen name="ongoing_appops_dot_diameter">6dp</dimen>
+    <!--  Total minimum padding to enforce to ensure that the dot can always show  -->
+    <dimen name="ongoing_appops_dot_min_padding">20dp</dimen>
 
     <dimen name="ongoing_appops_dialog_side_margins">@dimen/notification_shade_content_margin_horizontal</dimen>
 
@@ -1453,7 +1456,7 @@
     <dimen name="lockscreen_shade_notification_movement">24dp</dimen>
 
     <!-- Maximum overshoot for the pulse expansion -->
-    <dimen name="pulse_expansion_max_top_overshoot">16dp</dimen>
+    <dimen name="pulse_expansion_max_top_overshoot">32dp</dimen>
 
     <dimen name="people_space_widget_radius">28dp</dimen>
     <dimen name="people_space_image_radius">20dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 5aff817..04e5dd1 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1064,6 +1064,9 @@
     <!-- Message shown when lock screen is tapped or face authentication fails. [CHAR LIMIT=60] -->
     <string name="keyguard_unlock">Swipe up to open</string>
 
+    <!-- Message shown when lock screen is tapped or face authentication fails. Provides extra instructions for how the user can enter their device (unlock or proceed to home) [CHAR LIMIT=60] -->
+    <string name="keyguard_unlock_press">Press to open</string>
+
     <!-- Message shown when face authentication fails and the pin pad is visible. [CHAR LIMIT=60] -->
     <string name="keyguard_retry">Swipe up to try again</string>
 
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 70ed817..51eabf6 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -764,6 +764,8 @@
         <item name="android:windowBackground">@android:color/black</item>
         <item name="android:windowAnimationStyle">@null</item>
         <item name="android:statusBarColor">@android:color/black</item>
+        <!-- Setting a placeholder will avoid using the SystemUI icon on the splash screen -->
+        <item name="android:windowSplashScreenAnimatedIcon">@drawable/ic_blank</item>
         <item name="wallpaperTextColor">@*android:color/primary_text_material_dark</item>
     </style>
 
@@ -898,5 +900,7 @@
     <style name="Wallet.Theme" parent="@android:style/Theme.DeviceDefault">
       <item name="android:colorBackground">@android:color/system_neutral1_900</item>
       <item name="android:itemBackground">@android:color/system_neutral1_800</item>
+      <!-- Setting a placeholder will avoid using the SystemUI icon on the splash screen.  -->
+      <item name="android:windowSplashScreenAnimatedIcon">@drawable/ic_blank</item>
     </style>
 </resources>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginEnabler.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginEnabler.java
index 01b012d..1c5da82 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginEnabler.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginEnabler.java
@@ -24,9 +24,9 @@
 
     int ENABLED = 0;
     int DISABLED_MANUALLY = 1;
-    int DISABLED_INVALID_VERSION = 1;
-    int DISABLED_FROM_EXPLICIT_CRASH = 2;
-    int DISABLED_FROM_SYSTEM_CRASH = 3;
+    int DISABLED_INVALID_VERSION = 2;
+    int DISABLED_FROM_EXPLICIT_CRASH = 3;
+    int DISABLED_FROM_SYSTEM_CRASH = 4;
 
     @IntDef({ENABLED, DISABLED_MANUALLY, DISABLED_INVALID_VERSION, DISABLED_FROM_EXPLICIT_CRASH,
             DISABLED_FROM_SYSTEM_CRASH})
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java
index f5ed9da..2b4cdd6 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java
@@ -197,10 +197,12 @@
         filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
         filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
         filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+        filter.addDataScheme("package");
+        mContext.registerReceiver(this, filter);
         filter.addAction(PLUGIN_CHANGED);
         filter.addAction(DISABLE_PLUGIN);
         filter.addDataScheme("package");
-        mContext.registerReceiver(this, filter);
+        mContext.registerReceiver(this, filter, PluginInstanceManager.PLUGIN_PERMISSION, null);
         filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED);
         mContext.registerReceiver(this, filter);
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
index c89cda9..92f89d6 100644
--- a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
@@ -134,11 +134,15 @@
     };
 
     @Override
+    protected void onInit() {
+        mIsDozing = mStatusBarStateController.isDozing();
+    }
+
+    @Override
     protected void onViewAttached() {
         updateLocale();
         mBroadcastDispatcher.registerReceiver(mLocaleBroadcastReceiver,
                 new IntentFilter(Intent.ACTION_LOCALE_CHANGED));
-        mIsDozing = mStatusBarStateController.isDozing();
         mDozeAmount = mStatusBarStateController.getDozeAmount();
         mBatteryController.addCallback(mBatteryCallback);
         mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 8032839..459f3ca 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -123,10 +123,13 @@
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Set;
 import java.util.TimeZone;
 import java.util.concurrent.Executor;
 import java.util.function.Consumer;
@@ -469,16 +472,39 @@
         List<SubscriptionInfo> subscriptionInfos = getSubscriptionInfo(true /* forceReload */);
 
         // Hack level over 9000: Because the subscription id is not yet valid when we see the
-        // first update in handleSimStateChange, we need to force refresh all all SIM states
+        // first update in handleSimStateChange, we need to force refresh all SIM states
         // so the subscription id for them is consistent.
         ArrayList<SubscriptionInfo> changedSubscriptions = new ArrayList<>();
+        Set<Integer> activeSubIds = new HashSet<>();
         for (int i = 0; i < subscriptionInfos.size(); i++) {
             SubscriptionInfo info = subscriptionInfos.get(i);
+            activeSubIds.add(info.getSubscriptionId());
             boolean changed = refreshSimState(info.getSubscriptionId(), info.getSimSlotIndex());
             if (changed) {
                 changedSubscriptions.add(info);
             }
         }
+
+        // It is possible for active subscriptions to become invalid (-1), and these will not be
+        // present in the subscriptionInfo list
+        Iterator<Map.Entry<Integer, SimData>> iter = mSimDatas.entrySet().iterator();
+        while (iter.hasNext()) {
+            Map.Entry<Integer, SimData> simData = iter.next();
+            if (!activeSubIds.contains(simData.getKey())) {
+                Log.i(TAG, "Previously active sub id " + simData.getKey() + " is now invalid, "
+                        + "will remove");
+                iter.remove();
+
+                SimData data = simData.getValue();
+                for (int j = 0; j < mCallbacks.size(); j++) {
+                    KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get();
+                    if (cb != null) {
+                        cb.onSimStateChanged(data.subId, data.slotId, data.simState);
+                    }
+                }
+            }
+        }
+
         for (int i = 0; i < changedSubscriptions.size(); i++) {
             SimData data = mSimDatas.get(changedSubscriptions.get(i).getSubscriptionId());
             for (int j = 0; j < mCallbacks.size(); j++) {
@@ -2042,6 +2068,15 @@
     }
 
     /**
+     * @return if udfps is available on this device. will return true even if the user hasn't
+     * enrolled udfps.
+     */
+    public boolean isUdfpsAvailable() {
+        return mAuthController.getUdfpsProps() != null
+                && !mAuthController.getUdfpsProps().isEmpty();
+    }
+
+    /**
      * @return true if there's at least one face enrolled
      */
     public boolean isFaceEnrolled() {
@@ -3339,6 +3374,7 @@
             pw.println("    trustManaged=" + getUserTrustIsManaged(userId));
             pw.println("    udfpsEnrolled=" + isUdfpsEnrolled());
             pw.println("    mFingerprintLockedOut=" + mFingerprintLockedOut);
+            pw.println("    mFingerprintLockedOutPermanent=" + mFingerprintLockedOutPermanent);
             pw.println("    enabledByUser=" + mBiometricEnabledForUser.get(userId));
             if (isUdfpsEnrolled()) {
                 pw.println("        shouldListenForUdfps=" + shouldListenForFingerprint(true));
@@ -3360,8 +3396,11 @@
                     + getStrongAuthTracker().hasUserAuthenticatedSinceBoot());
             pw.println("    disabled(DPM)=" + isFaceDisabled(userId));
             pw.println("    possible=" + isUnlockWithFacePossible(userId));
+            pw.println("    listening: actual=" + mFaceRunningState
+                    + " expected=(" + (shouldListenForFace() ? 1 : 0));
             pw.println("    strongAuthFlags=" + Integer.toHexString(strongAuthFlags));
             pw.println("    trustManaged=" + getUserTrustIsManaged(userId));
+            pw.println("    mFaceLockedOutPermanent=" + mFaceLockedOutPermanent);
             pw.println("    enabledByUser=" + mBiometricEnabledForUser.get(userId));
             pw.println("    mSecureCameraLaunched=" + mSecureCameraLaunched);
         }
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index 8b974b4..9c8582fa 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -72,7 +72,10 @@
  */
 @StatusBarComponent.StatusBarScope
 public class LockIconViewController extends ViewController<LockIconView> implements Dumpable {
-
+    private static final float sDefaultDensity =
+            (float) DisplayMetrics.DENSITY_DEVICE_STABLE / (float) DisplayMetrics.DENSITY_DEFAULT;
+    private static final int sLockIconRadiusPx = (int) (sDefaultDensity * 36);
+    private static final float sDistAboveKgBottomAreaPx = sDefaultDensity * 12;
     private static final AudioAttributes VIBRATION_SONIFICATION_ATTRIBUTES =
             new AudioAttributes.Builder()
                 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
@@ -111,9 +114,7 @@
     private boolean mHasUdfps;
     private float mHeightPixels;
     private float mWidthPixels;
-    private float mDensity;
-    private int mAmbientIndicationHeight; // in pixels
-    private int mKgIndicationHeight; // in pixels
+    private int mBottomPadding; // in pixels
 
     private boolean mShowUnlockIcon;
     private boolean mShowLockIcon;
@@ -318,11 +319,8 @@
         final DisplayMetrics metrics = mView.getContext().getResources().getDisplayMetrics();
         mWidthPixels = metrics.widthPixels;
         mHeightPixels = metrics.heightPixels;
-        mDensity = metrics.density;
-        mKgIndicationHeight = mView.getContext().getResources().getDimensionPixelSize(
-                R.dimen.keyguard_indication_margin_bottom)
-            + mView.getContext().getResources().getDimensionPixelSize(
-                R.dimen.keyguard_indication_bottom_padding);
+        mBottomPadding = mView.getContext().getResources().getDimensionPixelSize(
+                R.dimen.lock_icon_margin_bottom);
         updateLockIconLocation();
     }
 
@@ -332,26 +330,15 @@
             mView.setCenterLocation(new PointF(props.sensorLocationX, props.sensorLocationY),
                     props.sensorRadius);
         } else {
-            final float distAboveKgBottomArea = 12 * mDensity;
-            final float radius = 36 * mDensity;
-            final int kgBottomAreaHeight = Math.max(mKgIndicationHeight, mAmbientIndicationHeight);
             mView.setCenterLocation(
                     new PointF(mWidthPixels / 2,
-                        mHeightPixels - kgBottomAreaHeight - distAboveKgBottomArea
-                            - radius / 2), (int) radius);
+                        mHeightPixels - mBottomPadding - sDistAboveKgBottomAreaPx
+                            - sLockIconRadiusPx), sLockIconRadiusPx);
         }
 
         mView.getHitRect(mSensorTouchLocation);
     }
 
-    /**
-     * Set the location of ambient indication if showing (ie: now playing)
-     */
-    public void setAmbientIndicationBottomPadding(int ambientIndicationBottomPadding) {
-        mAmbientIndicationHeight = ambientIndicationBottomPadding;
-        updateLockIconLocation();
-    }
-
     @Override
     public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
         pw.println("mUdfpsEnrolled: " + mUdfpsEnrolled);
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index c70281d..76f30a8 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -100,6 +100,7 @@
 import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper;
 import com.android.systemui.statusbar.phone.ShadeController;
 import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.phone.StatusBarWindowController;
 import com.android.systemui.statusbar.policy.AccessibilityController;
@@ -140,7 +141,6 @@
 
 import javax.inject.Inject;
 import javax.inject.Named;
-import javax.inject.Provider;
 
 import dagger.Lazy;
 
@@ -200,12 +200,6 @@
     public static final String ALLOW_NOTIFICATION_LONG_PRESS_NAME = "allow_notif_longpress";
 
     /**
-     * A provider of {@link EdgeBackGestureHandler}.
-     */
-    public static final String EDGE_BACK_GESTURE_HANDLER_PROVIDER_NAME =
-            "edge_back_gesture_handler_provider";
-
-    /**
      * Key for getting a background Looper for background work.
      */
     public static final DependencyKey<Looper> BG_LOOPER = new DependencyKey<>(BG_LOOPER_NAME);
@@ -240,12 +234,6 @@
      */
     public static final DependencyKey<String> LEAK_REPORT_EMAIL =
             new DependencyKey<>(LEAK_REPORT_EMAIL_NAME);
-    /**
-     * Key for retrieving an Provider<EdgeBackGestureHandler>.
-     */
-    public static final DependencyKey<Provider<EdgeBackGestureHandler>>
-            EDGE_BACK_GESTURE_HANDLER_PROVIDER =
-            new DependencyKey<>(EDGE_BACK_GESTURE_HANDLER_PROVIDER_NAME);
 
     private final ArrayMap<Object, Object> mDependencies = new ArrayMap<>();
     private final ArrayMap<Object, LazyDependencyCreator> mProviders = new ArrayMap<>();
@@ -372,9 +360,10 @@
     @Inject Lazy<TelephonyListenerManager> mTelephonyListenerManager;
     @Inject Lazy<SystemStatusAnimationScheduler> mSystemStatusAnimationSchedulerLazy;
     @Inject Lazy<PrivacyDotViewController> mPrivacyDotViewControllerLazy;
-    @Inject Provider<EdgeBackGestureHandler> mEdgeBackGestureHandlerProvider;
+    @Inject Lazy<EdgeBackGestureHandler.Factory> mEdgeBackGestureHandlerFactoryLazy;
     @Inject Lazy<UiEventLogger> mUiEventLogger;
     @Inject Lazy<FeatureFlags> mFeatureFlagsLazy;
+    @Inject Lazy<StatusBarContentInsetsProvider> mContentInsetsProviderLazy;
 
     @Inject
     public Dependency() {
@@ -587,9 +576,11 @@
         mProviders.put(SystemStatusAnimationScheduler.class,
                 mSystemStatusAnimationSchedulerLazy::get);
         mProviders.put(PrivacyDotViewController.class, mPrivacyDotViewControllerLazy::get);
-        mProviders.put(EDGE_BACK_GESTURE_HANDLER_PROVIDER, () -> mEdgeBackGestureHandlerProvider);
+        mProviders.put(EdgeBackGestureHandler.Factory.class,
+                mEdgeBackGestureHandlerFactoryLazy::get);
         mProviders.put(UiEventLogger.class, mUiEventLogger::get);
         mProviders.put(FeatureFlags.class, mFeatureFlagsLazy::get);
+        mProviders.put(StatusBarContentInsetsProvider.class, mContentInsetsProviderLazy::get);
 
         Dependency.setInstance(this);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 71e2bb6..0ce1846 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -37,6 +37,7 @@
 import android.hardware.biometrics.BiometricPrompt;
 import android.hardware.biometrics.IBiometricSysuiReceiver;
 import android.hardware.biometrics.PromptInfo;
+import android.hardware.display.DisplayManager;
 import android.hardware.face.FaceManager;
 import android.hardware.face.FaceSensorPropertiesInternal;
 import android.hardware.fingerprint.FingerprintManager;
@@ -57,6 +58,7 @@
 import com.android.systemui.SystemUI;
 import com.android.systemui.assist.ui.DisplayUtils;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.doze.DozeReceiver;
 import com.android.systemui.statusbar.CommandQueue;
 
@@ -423,7 +425,9 @@
             @Nullable FingerprintManager fingerprintManager,
             @Nullable FaceManager faceManager,
             Provider<UdfpsController> udfpsControllerFactory,
-            Provider<SidefpsController> sidefpsControllerFactory) {
+            Provider<SidefpsController> sidefpsControllerFactory,
+            @NonNull DisplayManager displayManager,
+            @Main Handler handler) {
         super(context);
         mCommandQueue = commandQueue;
         mActivityTaskManager = activityTaskManager;
@@ -432,10 +436,13 @@
         mUdfpsControllerFactory = udfpsControllerFactory;
         mSidefpsControllerFactory = sidefpsControllerFactory;
         mWindowManager = windowManager;
-        mOrientationListener = new BiometricOrientationEventListener(context, () -> {
-            onOrientationChanged();
-            return Unit.INSTANCE;
-        });
+        mOrientationListener = new BiometricOrientationEventListener(context,
+                () -> {
+                    onOrientationChanged();
+                    return Unit.INSTANCE;
+                },
+                displayManager,
+                handler);
 
         mFaceProps = mFaceManager != null ? mFaceManager.getSensorPropertiesInternal() : null;
 
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricOrientationEventListener.kt b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricOrientationEventListener.kt
index 08ea857..98a03a1 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricOrientationEventListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricOrientationEventListener.kt
@@ -17,7 +17,10 @@
 package com.android.systemui.biometrics
 
 import android.content.Context
+import android.hardware.display.DisplayManager
+import android.os.Handler
 import android.view.OrientationEventListener
+import android.view.Surface
 
 /**
  * An [OrientationEventListener] that invokes the [onOrientationChanged] callback whenever
@@ -26,20 +29,16 @@
  */
 class BiometricOrientationEventListener(
     private val context: Context,
-    private val onOrientationChanged: () -> Unit
-) : OrientationEventListener(context) {
+    private val onOrientationChanged: () -> Unit,
+    private val displayManager: DisplayManager,
+    private val handler: Handler
+) : DisplayManager.DisplayListener {
 
-    /** If actively listening (not available in base class). */
-    var enabled: Boolean = false
-        private set
+    private var lastRotation = context.display?.rotation ?: Surface.ROTATION_0
 
-    private var lastRotation = context.display?.rotation ?: ORIENTATION_UNKNOWN
-
-    override fun onOrientationChanged(orientation: Int) {
-        if (orientation == ORIENTATION_UNKNOWN) {
-            return
-        }
-
+    override fun onDisplayAdded(displayId: Int) {}
+    override fun onDisplayRemoved(displayId: Int) {}
+    override fun onDisplayChanged(displayId: Int) {
         val rotation = context.display?.rotation ?: return
         if (lastRotation != rotation) {
             lastRotation = rotation
@@ -48,13 +47,11 @@
         }
     }
 
-    override fun enable() {
-        enabled = true
-        super.enable()
+    fun enable() {
+        displayManager.registerDisplayListener(this, handler)
     }
 
-    override fun disable() {
-        enabled = false
-        super.disable()
+    fun disable() {
+        displayManager.unregisterDisplayListener(this)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java
index a51c2b8..8f6e249 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java
@@ -23,9 +23,11 @@
 import android.annotation.Nullable;
 import android.content.Context;
 import android.graphics.PixelFormat;
+import android.hardware.display.DisplayManager;
 import android.hardware.fingerprint.FingerprintManager;
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
 import android.hardware.fingerprint.ISidefpsController;
+import android.os.Handler;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.Gravity;
@@ -93,16 +95,22 @@
             @NonNull LayoutInflater inflater,
             @Nullable FingerprintManager fingerprintManager,
             @NonNull WindowManager windowManager,
-            @Main DelayableExecutor fgExecutor) {
+            @Main DelayableExecutor fgExecutor,
+            @NonNull DisplayManager displayManager,
+            @Main Handler handler) {
         mContext = context;
         mInflater = inflater;
         mFingerprintManager = checkNotNull(fingerprintManager);
         mWindowManager = windowManager;
         mFgExecutor = fgExecutor;
-        mOrientationListener = new BiometricOrientationEventListener(context, () -> {
-            onOrientationChanged();
-            return Unit.INSTANCE;
-        });
+        mOrientationListener = new BiometricOrientationEventListener(
+                context,
+                () -> {
+                    onOrientationChanged();
+                    return Unit.INSTANCE;
+                },
+                displayManager,
+                handler);
 
         mSensorProps = findFirstSidefps();
         checkArgument(mSensorProps != null);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 3c3dfec..950bd83 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -32,6 +32,7 @@
 import android.graphics.PixelFormat;
 import android.graphics.Point;
 import android.graphics.RectF;
+import android.hardware.display.DisplayManager;
 import android.hardware.fingerprint.FingerprintManager;
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
 import android.hardware.fingerprint.IUdfpsOverlayController;
@@ -519,7 +520,9 @@
             @NonNull UdfpsHapticsSimulator udfpsHapticsSimulator,
             @NonNull Optional<UdfpsHbmProvider> hbmProvider,
             @NonNull KeyguardStateController keyguardStateController,
-            @NonNull KeyguardBypassController keyguardBypassController) {
+            @NonNull KeyguardBypassController keyguardBypassController,
+            @NonNull DisplayManager displayManager,
+            @Main Handler mainHandler) {
         mContext = context;
         mExecution = execution;
         // TODO (b/185124905): inject main handler and vibrator once done prototyping
@@ -545,10 +548,14 @@
         mHbmProvider = hbmProvider.orElse(null);
         screenLifecycle.addObserver(mScreenObserver);
         mScreenOn = screenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_ON;
-        mOrientationListener = new BiometricOrientationEventListener(context, () -> {
-            onOrientationChanged();
-            return Unit.INSTANCE;
-        });
+        mOrientationListener = new BiometricOrientationEventListener(
+                context,
+                () -> {
+                    onOrientationChanged();
+                    return Unit.INSTANCE;
+                },
+                displayManager,
+                mainHandler);
         mKeyguardBypassController = keyguardBypassController;
 
         mSensorProps = findFirstUdfps();
@@ -662,7 +669,8 @@
         // Transform dimensions if the device is in landscape mode
         switch (mContext.getDisplay().getRotation()) {
             case Surface.ROTATION_90:
-                if (animation instanceof UdfpsKeyguardViewController) {
+                if (animation instanceof UdfpsKeyguardViewController
+                        && mKeyguardUpdateMonitor.isGoingToSleep()) {
                     break;
                 }
                 mCoreLayoutParams.x = mSensorProps.sensorLocationY - mSensorProps.sensorRadius
@@ -672,7 +680,8 @@
                 break;
 
             case Surface.ROTATION_270:
-                if (animation instanceof UdfpsKeyguardViewController) {
+                if (animation instanceof UdfpsKeyguardViewController
+                        && mKeyguardUpdateMonitor.isGoingToSleep()) {
                     break;
                 }
                 mCoreLayoutParams.x = p.x - mSensorProps.sensorLocationY - mSensorProps.sensorRadius
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
index 51124fb..6435bdd 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
@@ -377,6 +377,9 @@
 
                 @Override
                 public boolean onTouch(MotionEvent event) {
+                    if (mTransitionToFullShadeProgress != 0) {
+                        return false;
+                    }
                     return mUdfpsController.onTouch(event);
                 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
index c241c08..4104e31 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
@@ -64,16 +64,12 @@
         }
     }
 
-    override fun onStart() {
-        super.onStart()
+    override fun onResume() {
+        super.onResume()
 
         parent = requireViewById<ViewGroup>(R.id.global_actions_controls)
         parent.alpha = 0f
         uiController.show(parent, { finish() }, this)
-    }
-
-    override fun onResume() {
-        super.onResume()
 
         ControlsAnimations.enterAnimation(parent).start()
     }
@@ -82,8 +78,8 @@
         finish()
     }
 
-    override fun onStop() {
-        super.onStop()
+    override fun onPause() {
+        super.onPause()
 
         uiController.hide()
     }
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index c840c7a..61e8033 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -18,7 +18,6 @@
 
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
 
-import static com.android.systemui.Dependency.EDGE_BACK_GESTURE_HANDLER_PROVIDER;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
@@ -340,7 +339,8 @@
 
         mNavColorSampleMargin = getResources()
                         .getDimensionPixelSize(R.dimen.navigation_handle_sample_horizontal_margin);
-        mEdgeBackGestureHandler = Dependency.get(EDGE_BACK_GESTURE_HANDLER_PROVIDER).get();
+        mEdgeBackGestureHandler = Dependency.get(EdgeBackGestureHandler.Factory.class)
+                .create(mContext);
         mEdgeBackGestureHandler.setStateChangeCallback(this::updateStates);
         mRegionSamplingHelper = new RegionSamplingHelper(this,
                 new RegionSamplingHelper.SamplingCallback() {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index 3fc6a3a..aaa3bf0 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -292,8 +292,8 @@
         }
     };
 
-    @Inject
-    public EdgeBackGestureHandler(Context context, OverviewProxyService overviewProxyService,
+
+    EdgeBackGestureHandler(Context context, OverviewProxyService overviewProxyService,
             SysUiState sysUiState, PluginManager pluginManager, @Main Executor executor,
             BroadcastDispatcher broadcastDispatcher, ProtoTracer protoTracer,
             NavigationModeController navigationModeController, ViewConfiguration viewConfiguration,
@@ -942,6 +942,53 @@
         proto.edgeBackGestureHandler.allowGesture = mAllowGesture;
     }
 
+    /**
+     * Injectable instance to create a new EdgeBackGestureHandler.
+     *
+     * Necessary because we don't have good handling of per-display contexts at the moment. With
+     * this, you can pass in a specific context that knows what display it is in.
+     */
+    public static class Factory {
+        private final OverviewProxyService mOverviewProxyService;
+        private final SysUiState mSysUiState;
+        private final PluginManager mPluginManager;
+        private final Executor mExecutor;
+        private final BroadcastDispatcher mBroadcastDispatcher;
+        private final ProtoTracer mProtoTracer;
+        private final NavigationModeController mNavigationModeController;
+        private final ViewConfiguration mViewConfiguration;
+        private final WindowManager mWindowManager;
+        private final IWindowManager mWindowManagerService;
+        private final FalsingManager mFalsingManager;
+
+        @Inject
+        public Factory(OverviewProxyService overviewProxyService,
+                SysUiState sysUiState, PluginManager pluginManager, @Main Executor executor,
+                BroadcastDispatcher broadcastDispatcher, ProtoTracer protoTracer,
+                NavigationModeController navigationModeController,
+                ViewConfiguration viewConfiguration, WindowManager windowManager,
+                IWindowManager windowManagerService, FalsingManager falsingManager) {
+            mOverviewProxyService = overviewProxyService;
+            mSysUiState = sysUiState;
+            mPluginManager = pluginManager;
+            mExecutor = executor;
+            mBroadcastDispatcher = broadcastDispatcher;
+            mProtoTracer = protoTracer;
+            mNavigationModeController = navigationModeController;
+            mViewConfiguration = viewConfiguration;
+            mWindowManager = windowManager;
+            mWindowManagerService = windowManagerService;
+            mFalsingManager = falsingManager;
+        }
+
+        /** Construct a {@link EdgeBackGestureHandler}. */
+        public EdgeBackGestureHandler create(Context context) {
+            return new EdgeBackGestureHandler(context, mOverviewProxyService, mSysUiState,
+                    mPluginManager, mExecutor, mBroadcastDispatcher, mProtoTracer,
+                    mNavigationModeController, mViewConfiguration, mWindowManager,
+                    mWindowManagerService, mFalsingManager);
+        }
+    }
 
     private static class LogArray extends ArrayDeque<String> {
         private final int mLength;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index a318073..4fcd46c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -423,6 +423,9 @@
             if (mQsPanelController.shouldUseHorizontalLayout()
                     && mQsPanelController.mMediaHost.hostView != null) {
                 builder.addFloat(mQsPanelController.mMediaHost.hostView, "alpha", 0, 1);
+            } else {
+                // In portrait, media view should always be visible
+                mQsPanelController.mMediaHost.hostView.setAlpha(1.0f);
             }
             mAllPagesDelayedAnimator = builder.build();
             mAllViews.add(mSecurityFooter.getView());
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 0a1e9d0..04f692d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -48,6 +48,7 @@
 import com.android.systemui.statusbar.FeatureFlags;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
 import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
 import com.android.systemui.util.InjectionInflationController;
@@ -69,6 +70,7 @@
     private final Rect mQsBounds = new Rect();
     private final StatusBarStateController mStatusBarStateController;
     private final FalsingManager mFalsingManager;
+    private final KeyguardBypassController mBypassController;
     private boolean mQsExpanded;
     private boolean mHeaderAnimating;
     private boolean mStackScrollerOverscrolling;
@@ -135,6 +137,7 @@
             StatusBarStateController statusBarStateController, CommandQueue commandQueue,
             QSDetailDisplayer qsDetailDisplayer, @Named(QS_PANEL) MediaHost qsMediaHost,
             @Named(QUICK_QS_PANEL) MediaHost qqsMediaHost,
+            KeyguardBypassController keyguardBypassController,
             QSFragmentComponent.Factory qsComponentFactory, FeatureFlags featureFlags,
             FalsingManager falsingManager) {
         mRemoteInputQuickSettingsDisabler = remoteInputQsDisabler;
@@ -148,6 +151,7 @@
         mHost = qsTileHost;
         mFeatureFlags = featureFlags;
         mFalsingManager = falsingManager;
+        mBypassController = keyguardBypassController;
         mStatusBarStateController = statusBarStateController;
     }
 
@@ -380,16 +384,8 @@
         return mStatusBarStateController.getState() == StatusBarState.KEYGUARD;
     }
 
-    @Override
-    public void setPulseExpanding(boolean pulseExpanding) {
-        if (pulseExpanding != mPulseExpanding) {
-            mPulseExpanding = pulseExpanding;
-            updateShowCollapsedOnKeyguard();
-        }
-    }
-
     private void updateShowCollapsedOnKeyguard() {
-        boolean showCollapsed = mPulseExpanding || mTransitioningToFullShade;
+        boolean showCollapsed = mBypassController.getBypassEnabled() || mTransitioningToFullShade;
         if (showCollapsed != mShowCollapsedOnKeyguard) {
             mShowCollapsedOnKeyguard = showCollapsed;
             updateQsState();
@@ -719,5 +715,6 @@
     public void onStateChanged(int newState) {
         mState = newState;
         setKeyguardShowing(newState == StatusBarState.KEYGUARD);
+        updateShowCollapsedOnKeyguard();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 7c7f566..425bdc2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -56,6 +56,8 @@
     private static final String TAG = "QSPanel";
 
     protected final Context mContext;
+    private final int mMediaTopMargin;
+    private final int mMediaTotalBottomMargin;
 
     /**
      * The index where the content starts that needs to be moved between parents
@@ -99,13 +101,14 @@
     protected LinearLayout mHorizontalContentContainer;
 
     protected QSTileLayout mTileLayout;
-    private int mMediaTotalBottomMargin;
 
     public QSPanel(Context context, AttributeSet attrs) {
         super(context, attrs);
         mUsingMediaPlayer = useQsMediaPlayer(context);
         mMediaTotalBottomMargin = getResources().getDimensionPixelSize(
                 R.dimen.quick_settings_bottom_margin_media);
+        mMediaTopMargin = getResources().getDimensionPixelSize(
+                R.dimen.qs_tile_margin_vertical);
         mContext = context;
 
         setOrientation(VERTICAL);
@@ -328,7 +331,7 @@
     private void updateHorizontalLinearLayoutMargins() {
         if (mHorizontalLinearLayout != null && !displayMediaMarginsOnMedia()) {
             LayoutParams lp = (LayoutParams) mHorizontalLinearLayout.getLayoutParams();
-            lp.bottomMargin = mMediaTotalBottomMargin - getPaddingBottom();
+            lp.bottomMargin = Math.max(mMediaTotalBottomMargin - getPaddingBottom(), 0);
             mHorizontalLinearLayout.setLayoutParams(lp);
         }
     }
@@ -343,6 +346,13 @@
         return true;
     }
 
+    /**
+     * @return true if the media view needs margin on the top to separate it from the qs tiles
+     */
+    protected boolean mediaNeedsTopMargin() {
+        return false;
+    }
+
     private boolean needsDynamicRowsAndColumns() {
         return true;
     }
@@ -411,7 +421,9 @@
             // necessary if the view isn't horizontal, since otherwise the padding is
             // carried in the parent of this view (to ensure correct vertical alignment)
             layoutParams.bottomMargin = !horizontal || displayMediaMarginsOnMedia()
-                    ? mMediaTotalBottomMargin - getPaddingBottom() : 0;
+                    ? Math.max(mMediaTotalBottomMargin - getPaddingBottom(), 0) : 0;
+            layoutParams.topMargin = mediaNeedsTopMargin() && !horizontal
+                    ? mMediaTopMargin : 0;
         }
     }
 
@@ -674,6 +686,7 @@
                 mTileLayout.setMaxColumns(horizontal ? 2 : 4);
             }
             updateMargins(mediaHostView);
+            mHorizontalLinearLayout.setVisibility(horizontal ? View.VISIBLE : View.GONE);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index 4cd4048..985943b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -73,6 +73,11 @@
     }
 
     @Override
+    protected boolean mediaNeedsTopMargin() {
+        return true;
+    }
+
+    @Override
     protected void updatePadding() {
         // QS Panel is setting a top padding by default, which we don't need.
     }
@@ -180,7 +185,6 @@
                     LayoutParams.WRAP_CONTENT);
             setLayoutParams(lp);
             setMaxColumns(4);
-            mLastRowPadding = true;
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 03a2c84..cd9db61 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -32,6 +32,8 @@
 import android.widget.LinearLayout;
 import android.widget.Space;
 
+import androidx.annotation.NonNull;
+
 import com.android.settingslib.Utils;
 import com.android.systemui.BatteryMeterView;
 import com.android.systemui.R;
@@ -41,6 +43,8 @@
 import com.android.systemui.statusbar.phone.StatusIconContainer;
 import com.android.systemui.statusbar.policy.Clock;
 
+import java.util.List;
+
 /**
  * View that contains the top-most bits of the QS panel (primarily the status bar with date, time,
  * battery, carrier info and privacy icons) and also contains the {@link QuickQSPanel}.
@@ -86,18 +90,13 @@
     private float mKeyguardExpansionFraction;
     private int mTextColorPrimary = Color.TRANSPARENT;
     private int mTopViewMeasureHeight;
-    private boolean mProviderModel;
 
-    private final String mMobileSlotName;
-    private final String mNoCallingSlotName;
-    private final String mCallStrengthSlotName;
+    @NonNull
+    private List<String> mRssiIgnoredSlots;
+    private boolean mIsSingleCarrier;
 
     public QuickStatusBarHeader(Context context, AttributeSet attrs) {
         super(context, attrs);
-        mMobileSlotName = context.getString(com.android.internal.R.string.status_bar_mobile);
-        mNoCallingSlotName = context.getString(com.android.internal.R.string.status_bar_no_calling);
-        mCallStrengthSlotName =
-                context.getString(com.android.internal.R.string.status_bar_call_strength);
     }
 
     /**
@@ -148,9 +147,9 @@
 
     void onAttach(TintedIconManager iconManager,
             QSExpansionPathInterpolator qsExpansionPathInterpolator,
-            boolean providerModel) {
-        mProviderModel = providerModel;
+            List<String> rssiIgnoredSlots) {
         mTintedIconManager = iconManager;
+        mRssiIgnoredSlots = rssiIgnoredSlots;
         int fillColor = Utils.getColorAttrDefaultColor(getContext(),
                 android.R.attr.textColorPrimary);
 
@@ -161,6 +160,11 @@
         updateAnimators();
     }
 
+    void setIsSingleCarrier(boolean isSingleCarrier) {
+        mIsSingleCarrier = isSingleCarrier;
+        updateAlphaAnimator();
+    }
+
     public QuickQSPanel getHeaderQsPanel() {
         return mHeaderQsPanel;
     }
@@ -267,39 +271,26 @@
                 .setListener(new TouchAnimator.ListenerAdapter() {
                     @Override
                     public void onAnimationAtEnd() {
-                        // TODO(b/185580157): Remove the mProviderModel if the mobile slot can be
-                        // hidden in Provider model.
-                        if (mProviderModel) {
-                            mIconContainer.addIgnoredSlot(mNoCallingSlotName);
-                            mIconContainer.addIgnoredSlot(mCallStrengthSlotName);
-                        } else {
-                            mIconContainer.addIgnoredSlot(mMobileSlotName);
+                        super.onAnimationAtEnd();
+                        if (!mIsSingleCarrier) {
+                            mIconContainer.addIgnoredSlots(mRssiIgnoredSlots);
                         }
                     }
 
                     @Override
                     public void onAnimationStarted() {
-                        if (mProviderModel) {
-                            mIconContainer.addIgnoredSlot(mNoCallingSlotName);
-                            mIconContainer.addIgnoredSlot(mCallStrengthSlotName);
-                        } else {
-                            mIconContainer.addIgnoredSlot(mMobileSlotName);
-                        }
-
                         setSeparatorVisibility(false);
+                        if (!mIsSingleCarrier) {
+                            mIconContainer.addIgnoredSlots(mRssiIgnoredSlots);
+                        }
                     }
 
                     @Override
                     public void onAnimationAtStart() {
                         super.onAnimationAtStart();
-                        if (mProviderModel) {
-                            mIconContainer.removeIgnoredSlot(mNoCallingSlotName);
-                            mIconContainer.removeIgnoredSlot(mCallStrengthSlotName);
-                        } else {
-                            mIconContainer.removeIgnoredSlot(mMobileSlotName);
-                        }
-
                         setSeparatorVisibility(mShowClockIconsSeparator);
+                        // In QQS we never ignore RSSI.
+                        mIconContainer.removeIgnoredSlots(mRssiIgnoredSlots);
                     }
                 });
         mAlphaAnimator = builder.build();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
index fcf1302..b8b7f42 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
@@ -43,7 +43,6 @@
 import com.android.systemui.statusbar.policy.Clock;
 import com.android.systemui.util.ViewController;
 
-import java.util.ArrayList;
 import java.util.List;
 
 import javax.inject.Inject;
@@ -76,6 +75,9 @@
     private boolean mMicCameraIndicatorsEnabled;
     private boolean mLocationIndicatorsEnabled;
     private boolean mPrivacyChipLogged;
+    private final String mCameraSlot;
+    private final String mMicSlot;
+    private final String mLocationSlot;
 
     private SysuiColorExtractor mColorExtractor;
     private ColorExtractor.OnColorsChangedListener mOnColorsChangedListener;
@@ -104,8 +106,7 @@
         }
 
         private void update() {
-            StatusIconContainer iconContainer = mView.requireViewById(R.id.statusIcons);
-            iconContainer.setIgnoredSlots(getIgnoredIconSlots());
+            updatePrivacyIconSlots();
             setChipVisibility(!mPrivacyChip.getPrivacyList().isEmpty());
         }
     };
@@ -154,7 +155,7 @@
         mClockView = mView.findViewById(R.id.clock);
         mIconContainer = mView.findViewById(R.id.statusIcons);
 
-        mIconManager = new StatusBarIconController.TintedIconManager(mIconContainer, mFeatureFlags);
+        mIconManager = new StatusBarIconController.TintedIconManager(mIconContainer, featureFlags);
         mDemoModeReceiver = new ClockDemoModeReceiver(mClockView);
         mColorExtractor = colorExtractor;
         mOnColorsChangedListener = (extractor, which) -> {
@@ -162,6 +163,10 @@
             mClockView.onColorsChanged(lightTheme);
         };
         mColorExtractor.addOnColorsChangedListener(mOnColorsChangedListener);
+
+        mCameraSlot = getResources().getString(com.android.internal.R.string.status_bar_camera);
+        mMicSlot = getResources().getString(com.android.internal.R.string.status_bar_microphone);
+        mLocationSlot = getResources().getString(com.android.internal.R.string.status_bar_location);
     }
 
     @Override
@@ -172,14 +177,30 @@
         mLocationIndicatorsEnabled = mPrivacyItemController.getLocationAvailable();
 
         // Ignore privacy icons because they show in the space above QQS
-        mIconContainer.setIgnoredSlots(getIgnoredIconSlots());
+        updatePrivacyIconSlots();
         mIconContainer.setShouldRestrictIcons(false);
         mStatusBarIconController.addIconGroup(mIconManager);
 
         setChipVisibility(mPrivacyChip.getVisibility() == View.VISIBLE);
 
-        mView.onAttach(mIconManager, mQSExpansionPathInterpolator,
-                mFeatureFlags.isCombinedStatusBarSignalIconsEnabled());
+        mView.setIsSingleCarrier(mQSCarrierGroupController.isSingleCarrier());
+        mQSCarrierGroupController
+                .setOnSingleCarrierChangedListener(mView::setIsSingleCarrier);
+
+        List<String> rssiIgnoredSlots;
+
+        if (mFeatureFlags.isCombinedStatusBarSignalIconsEnabled()) {
+            rssiIgnoredSlots = List.of(
+                    getResources().getString(com.android.internal.R.string.status_bar_no_calling),
+                    getResources().getString(com.android.internal.R.string.status_bar_call_strength)
+            );
+        } else {
+            rssiIgnoredSlots = List.of(
+                    getResources().getString(com.android.internal.R.string.status_bar_mobile)
+            );
+        }
+
+        mView.onAttach(mIconManager, mQSExpansionPathInterpolator, rssiIgnoredSlots);
 
         mDemoModeController.addCallback(mDemoModeReceiver);
     }
@@ -189,6 +210,7 @@
         mColorExtractor.removeOnColorsChangedListener(mOnColorsChangedListener);
         mPrivacyChip.setOnClickListener(null);
         mStatusBarIconController.removeIconGroup(mIconManager);
+        mQSCarrierGroupController.setOnSingleCarrierChangedListener(null);
         mDemoModeController.removeCallback(mDemoModeReceiver);
         setListening(false);
     }
@@ -236,21 +258,25 @@
         mView.setChipVisibility(chipVisible);
     }
 
-    private List<String> getIgnoredIconSlots() {
-        ArrayList<String> ignored = new ArrayList<>();
+    private void updatePrivacyIconSlots() {
         if (getChipEnabled()) {
             if (mMicCameraIndicatorsEnabled) {
-                ignored.add(mView.getResources().getString(
-                        com.android.internal.R.string.status_bar_camera));
-                ignored.add(mView.getResources().getString(
-                        com.android.internal.R.string.status_bar_microphone));
+                mIconContainer.addIgnoredSlot(mCameraSlot);
+                mIconContainer.addIgnoredSlot(mMicSlot);
+            } else {
+                mIconContainer.removeIgnoredSlot(mCameraSlot);
+                mIconContainer.removeIgnoredSlot(mMicSlot);
             }
             if (mLocationIndicatorsEnabled) {
-                ignored.add(mView.getResources().getString(
-                        com.android.internal.R.string.status_bar_location));
+                mIconContainer.addIgnoredSlot(mLocationSlot);
+            } else {
+                mIconContainer.removeIgnoredSlot(mLocationSlot);
             }
+        } else {
+            mIconContainer.removeIgnoredSlot(mCameraSlot);
+            mIconContainer.removeIgnoredSlot(mMicSlot);
+            mIconContainer.removeIgnoredSlot(mLocationSlot);
         }
-        return ignored;
     }
 
     private boolean getChipEnabled() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index 2b96a34..1a890a7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -31,7 +31,6 @@
     protected int mCellMarginVertical;
     protected int mSidePadding;
     protected int mRows = 1;
-    protected boolean mLastRowPadding = false;
 
     protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
     protected boolean mListening;
@@ -168,9 +167,7 @@
         }
 
         int height = (mCellHeight + mCellMarginVertical) * mRows;
-        if (!mLastRowPadding) {
-            height -= mCellMarginVertical;
-        }
+        height -= mCellMarginVertical;
 
         if (height < 0) height = 0;
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java
index d6fa216..32ac733 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java
@@ -25,6 +25,8 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.settingslib.Utils;
 import com.android.settingslib.graph.SignalDrawable;
 import com.android.systemui.R;
@@ -37,8 +39,10 @@
     private TextView mCarrierText;
     private ImageView mMobileSignal;
     private ImageView mMobileRoaming;
+    private View mSpacer;
     private CellSignalState mLastSignalState;
     private boolean mProviderModelInitialized = false;
+    private boolean mIsSingleCarrier;
 
     public QSCarrier(Context context) {
         super(context);
@@ -63,18 +67,25 @@
         mMobileRoaming = findViewById(R.id.mobile_roaming);
         mMobileSignal = findViewById(R.id.mobile_signal);
         mCarrierText = findViewById(R.id.qs_carrier_text);
+        mSpacer = findViewById(R.id.spacer);
     }
 
     /**
      * Update the state of this view
      * @param state the current state of the signal for this view
+     * @param isSingleCarrier whether there is a single carrier being shown in the container
      * @return true if the state was actually changed
      */
-    public boolean updateState(CellSignalState state) {
-        if (Objects.equals(state, mLastSignalState)) return false;
+    public boolean updateState(CellSignalState state, boolean isSingleCarrier) {
+        if (Objects.equals(state, mLastSignalState) && isSingleCarrier == mIsSingleCarrier) {
+            return false;
+        }
         mLastSignalState = state;
-        mMobileGroup.setVisibility(state.visible ? View.VISIBLE : View.GONE);
-        if (state.visible) {
+        mIsSingleCarrier = isSingleCarrier;
+        final boolean visible = state.visible && !isSingleCarrier;
+        mMobileGroup.setVisibility(visible ? View.VISIBLE : View.GONE);
+        mSpacer.setVisibility(isSingleCarrier ? View.VISIBLE : View.GONE);
+        if (visible) {
             mMobileRoaming.setVisibility(state.roaming ? View.VISIBLE : View.GONE);
             ColorStateList colorStateList = Utils.getColorAttr(mContext,
                     android.R.attr.textColorPrimary);
@@ -125,6 +136,11 @@
                         com.android.settingslib.R.string.not_default_data_content_description));
     }
 
+    @VisibleForTesting
+    View getRSSIView() {
+        return mMobileGroup;
+    }
+
     public void setCarrierText(CharSequence text) {
         mCarrierText.setText(text);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java
index f23c058..67c4d33 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java
@@ -37,6 +37,7 @@
 import com.android.settingslib.AccessibilityContentDescriptions;
 import com.android.settingslib.mobile.TelephonyIcons;
 import com.android.systemui.R;
+import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.plugins.ActivityStarter;
@@ -62,7 +63,8 @@
     private final NetworkController mNetworkController;
     private final CarrierTextManager mCarrierTextManager;
     private final TextView mNoSimTextView;
-    private final H mMainHandler;
+    // Non final for testing
+    private H mMainHandler;
     private final Callback mCallback;
     private boolean mListening;
     private final CellSignalState[] mInfos =
@@ -74,6 +76,11 @@
     private final boolean mProviderModel;
     private final CarrierConfigTracker mCarrierConfigTracker;
 
+    private boolean mIsSingleCarrier;
+    private OnSingleCarrierChangedListener mOnSingleCarrierChangedListener;
+
+    private final SlotIndexResolver mSlotIndexResolver;
+
     private final NetworkController.SignalCallback mSignalCallback =
             new NetworkController.SignalCallback() {
                 @Override
@@ -207,7 +214,8 @@
             @Background Handler bgHandler, @Main Looper mainLooper,
             NetworkController networkController,
             CarrierTextManager.Builder carrierTextManagerBuilder, Context context,
-            CarrierConfigTracker carrierConfigTracker, FeatureFlags featureFlags) {
+            CarrierConfigTracker carrierConfigTracker, FeatureFlags featureFlags,
+            SlotIndexResolver slotIndexResolver) {
 
         if (featureFlags.isCombinedStatusBarSignalIconsEnabled()) {
             mProviderModel = true;
@@ -222,6 +230,7 @@
                 .setShowMissingSim(false)
                 .build();
         mCarrierConfigTracker = carrierConfigTracker;
+        mSlotIndexResolver = slotIndexResolver;
         View.OnClickListener onClickListener = v -> {
             if (!v.isVisibleToUser()) {
                 return;
@@ -256,6 +265,7 @@
                             .toString();
             mCarrierGroups[i].setOnClickListener(onClickListener);
         }
+        mIsSingleCarrier = computeIsSingleCarrier();
         view.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
 
         view.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
@@ -272,10 +282,24 @@
 
     @VisibleForTesting
     protected int getSlotIndex(int subscriptionId) {
-        return SubscriptionManager.getSlotIndex(subscriptionId);
+        return mSlotIndexResolver.getSlotIndex(subscriptionId);
     }
 
-    private boolean isSingleCarrier() {
+    /**
+     * Sets a {@link OnSingleCarrierChangedListener}.
+     *
+     * This will get notified when the number of carriers changes between 1 and "not one".
+     * @param listener
+     */
+    public void setOnSingleCarrierChangedListener(OnSingleCarrierChangedListener listener) {
+        mOnSingleCarrierChangedListener = listener;
+    }
+
+    public boolean isSingleCarrier() {
+        return mIsSingleCarrier;
+    }
+
+    private boolean computeIsSingleCarrier() {
         int carrierCount = 0;
         for (int i = 0; i < SIM_SLOTS; i++) {
 
@@ -315,7 +339,9 @@
             return;
         }
 
-        if (isSingleCarrier()) {
+        boolean singleCarrier = computeIsSingleCarrier();
+
+        if (singleCarrier) {
             for (int i = 0; i < SIM_SLOTS; i++) {
                 if (mInfos[i].visible
                         && mInfos[i].mobileSignalIconId == R.drawable.ic_qs_sim_card) {
@@ -326,7 +352,7 @@
         }
 
         for (int i = 0; i < SIM_SLOTS; i++) {
-            mCarrierGroups[i].updateState(mInfos[i]);
+            mCarrierGroups[i].updateState(mInfos[i], singleCarrier);
         }
 
         mCarrierDividers[0].setVisibility(
@@ -337,6 +363,12 @@
         mCarrierDividers[1].setVisibility(
                 (mInfos[1].visible && mInfos[2].visible)
                         || (mInfos[0].visible && mInfos[2].visible) ? View.VISIBLE : View.GONE);
+        if (mIsSingleCarrier != singleCarrier) {
+            mIsSingleCarrier = singleCarrier;
+            if (mOnSingleCarrierChangedListener != null) {
+                mOnSingleCarrierChangedListener.onSingleCarrierChanged(singleCarrier);
+            }
+        }
     }
 
     @MainThread
@@ -433,12 +465,14 @@
         private final Context mContext;
         private final CarrierConfigTracker mCarrierConfigTracker;
         private final FeatureFlags mFeatureFlags;
+        private final SlotIndexResolver mSlotIndexResolver;
 
         @Inject
         public Builder(ActivityStarter activityStarter, @Background Handler handler,
                 @Main Looper looper, NetworkController networkController,
                 CarrierTextManager.Builder carrierTextControllerBuilder, Context context,
-                CarrierConfigTracker carrierConfigTracker, FeatureFlags featureFlags) {
+                CarrierConfigTracker carrierConfigTracker, FeatureFlags featureFlags,
+                SlotIndexResolver slotIndexResolver) {
             mActivityStarter = activityStarter;
             mHandler = handler;
             mLooper = looper;
@@ -447,6 +481,7 @@
             mContext = context;
             mCarrierConfigTracker = carrierConfigTracker;
             mFeatureFlags = featureFlags;
+            mSlotIndexResolver = slotIndexResolver;
         }
 
         public Builder setQSCarrierGroup(QSCarrierGroup view) {
@@ -457,7 +492,43 @@
         public QSCarrierGroupController build() {
             return new QSCarrierGroupController(mView, mActivityStarter, mHandler, mLooper,
                     mNetworkController, mCarrierTextControllerBuilder, mContext,
-                    mCarrierConfigTracker, mFeatureFlags);
+                    mCarrierConfigTracker, mFeatureFlags, mSlotIndexResolver);
+        }
+    }
+
+    /**
+     * Notify when the state changes from 1 carrier to "not one" and viceversa
+     */
+    @FunctionalInterface
+    public interface OnSingleCarrierChangedListener {
+        void onSingleCarrierChanged(boolean isSingleCarrier);
+    }
+
+    /**
+     * Interface for resolving slot index from subscription ID.
+     */
+    @FunctionalInterface
+    public interface SlotIndexResolver {
+        /**
+         * Get slot index for given sub id.
+         */
+        int getSlotIndex(int subscriptionId);
+    }
+
+    /**
+     * Default implementation for {@link SlotIndexResolver}.
+     *
+     * It retrieves the slot index using {@link SubscriptionManager#getSlotIndex}.
+     */
+    @SysUISingleton
+    public static class SubscriptionManagerSlotIndexResolver implements SlotIndexResolver {
+
+        @Inject
+        public SubscriptionManagerSlotIndexResolver() {}
+
+        @Override
+        public int getSlotIndex(int subscriptionId) {
+            return SubscriptionManager.getSlotIndex(subscriptionId);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
index 34aac49..4d63349 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
@@ -33,6 +33,7 @@
 import com.android.systemui.qs.QSPanel;
 import com.android.systemui.qs.QuickQSPanel;
 import com.android.systemui.qs.QuickStatusBarHeader;
+import com.android.systemui.qs.carrier.QSCarrierGroupController;
 import com.android.systemui.qs.customize.QSCustomizer;
 import com.android.systemui.statusbar.phone.MultiUserSwitch;
 
@@ -146,4 +147,8 @@
         return useQsMediaPlayer(context);
     }
 
+    /** */
+    @Binds
+    QSCarrierGroupController.SlotIndexResolver provideSlotIndexResolver(
+            QSCarrierGroupController.SubscriptionManagerSlotIndexResolver impl);
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
index de3be78..6d1bbee 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
@@ -89,5 +89,4 @@
     /** */
     @Binds
     QSHost provideQsHost(QSTileHost controllerImpl);
-
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
index f66b722..bc21b2d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
@@ -69,7 +69,7 @@
 
     private var hasControlsApps = AtomicBoolean(false)
 
-    private val icon = ResourceIcon.get(R.drawable.ic_device_light)
+    private val icon = ResourceIcon.get(R.drawable.controls_icon)
 
     private val listingCallback = object : ControlsListingController.ControlsListingCallback {
         override fun onServicesUpdated(serviceInfos: List<ControlsServiceInfo>) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
index ab81ac1..82b6c0c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
@@ -153,25 +153,9 @@
         });
     }
 
-    @Nullable
-    private CharSequence getServiceLabelSafe() {
-        try {
-            return mController.getWalletClient().getServiceLabel();
-        } catch (RuntimeException e) {
-            Log.e(TAG, "Failed to get the service label safely, recreating wallet client", e);
-            mController.reCreateWalletClient();
-            try {
-                return mController.getWalletClient().getServiceLabel();
-            } catch (RuntimeException e2) {
-                Log.e(TAG, "The QAW service label is broken.", e2);
-                return null;
-            }
-        }
-    }
-
     @Override
     protected void handleUpdateState(State state, Object arg) {
-        CharSequence label = getServiceLabelSafe();
+        CharSequence label = mController.getWalletClient().getServiceLabel();
         state.label = label == null ? mLabel : label;
         state.contentDescription = state.label;
         Drawable tileIcon = mController.getWalletClient().getTileIcon();
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
index 1ad253e..39d6c4f 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
@@ -354,9 +354,10 @@
                 convertGammaToLinearFloat(value, minBacklight, maxBacklight),
                 maxBacklight);
         if (stopTracking) {
-            // TODO(brightnessfloat): change to use float value instead.
+            // Log brightness as a value between 0-1000 directly correlated to brightnesses 0-1.0
             MetricsLogger.action(mContext, metric,
-                    BrightnessSynchronizer.brightnessFloatToInt(valFloat));
+                    Math.round(MathUtils.constrainedMap(0, 1000, PowerManager.BRIGHTNESS_MIN,
+                        PowerManager.BRIGHTNESS_MAX, valFloat)));
 
         }
         setBrightness(valFloat);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 44399a1..92922b6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -77,6 +77,7 @@
 import com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -94,13 +95,13 @@
  * Controls the indications and error messages shown on the Keyguard
  */
 @SysUISingleton
-public class KeyguardIndicationController implements KeyguardStateController.Callback {
+public class KeyguardIndicationController {
 
     private static final String TAG = "KeyguardIndication";
     private static final boolean DEBUG_CHARGING_SPEED = false;
 
     private static final int MSG_HIDE_TRANSIENT = 1;
-    private static final int MSG_SWIPE_UP_TO_UNLOCK = 2;
+    private static final int MSG_SHOW_ACTION_TO_UNLOCK = 2;
     private static final long TRANSIENT_BIOMETRIC_ERROR_TIMEOUT = 1300;
     private static final float BOUNCE_ANIMATION_FINAL_Y = 0f;
 
@@ -121,6 +122,7 @@
     private final LockPatternUtils mLockPatternUtils;
     private final IActivityManager mIActivityManager;
     private final FalsingManager mFalsingManager;
+    private final KeyguardBypassController mKeyguardBypassController;
 
     protected KeyguardIndicationRotateTextViewController mRotateTextViewController;
     private BroadcastReceiver mBroadcastReceiver;
@@ -175,7 +177,8 @@
             @Main DelayableExecutor executor,
             FalsingManager falsingManager,
             LockPatternUtils lockPatternUtils,
-            IActivityManager iActivityManager) {
+            IActivityManager iActivityManager,
+            KeyguardBypassController keyguardBypassController) {
         mContext = context;
         mBroadcastDispatcher = broadcastDispatcher;
         mDevicePolicyManager = devicePolicyManager;
@@ -191,6 +194,7 @@
         mLockPatternUtils = lockPatternUtils;
         mIActivityManager = iActivityManager;
         mFalsingManager = falsingManager;
+        mKeyguardBypassController = keyguardBypassController;
 
     }
 
@@ -206,7 +210,7 @@
         mKeyguardUpdateMonitor.registerCallback(getKeyguardCallback());
         mKeyguardUpdateMonitor.registerCallback(mTickReceiver);
         mStatusBarStateController.addCallback(mStatusBarStateListener);
-        mKeyguardStateController.addCallback(this);
+        mKeyguardStateController.addCallback(mKeyguardStateCallback);
 
         mStatusBarStateListener.onDozingChanged(mStatusBarStateController.isDozing());
     }
@@ -593,7 +597,7 @@
         mTransientIndication = transientIndication;
         mHideTransientMessageOnScreenOff = hideOnScreenOff && transientIndication != null;
         mHandler.removeMessages(MSG_HIDE_TRANSIENT);
-        mHandler.removeMessages(MSG_SWIPE_UP_TO_UNLOCK);
+        mHandler.removeMessages(MSG_SHOW_ACTION_TO_UNLOCK);
         if (mDozing && !TextUtils.isEmpty(mTransientIndication)) {
             // Make sure this doesn't get stuck and burns in. Acquire wakelock until its cleared.
             mWakeLock.setAcquired(true);
@@ -785,27 +789,35 @@
         public void handleMessage(Message msg) {
             if (msg.what == MSG_HIDE_TRANSIENT) {
                 hideTransientIndication();
-            } else if (msg.what == MSG_SWIPE_UP_TO_UNLOCK) {
-                showSwipeUpToUnlock();
+            } else if (msg.what == MSG_SHOW_ACTION_TO_UNLOCK) {
+                showActionToUnlock();
             }
         }
     };
 
-    private void showSwipeUpToUnlock() {
+    /**
+     * Show message on the keyguard for how the user can unlock/enter their device.
+     */
+    public void showActionToUnlock() {
         if (mDozing) {
             return;
         }
 
         if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
             if (mStatusBarKeyguardViewManager.isShowingAlternateAuth()) {
-                return; // udfps affordance is highlighted, no need to surface face auth error
-            } else {
+                return; // udfps affordance is highlighted, no need to show action to unlock
+            } else if (mKeyguardUpdateMonitor.isFaceEnrolled()) {
                 String message = mContext.getString(R.string.keyguard_retry);
                 mStatusBarKeyguardViewManager.showBouncerMessage(message, mInitialTextColorState);
             }
         } else if (mKeyguardUpdateMonitor.isScreenOn()) {
-            showTransientIndication(mContext.getString(R.string.keyguard_unlock),
-                    false /* isError */, true /* hideOnScreenOff */);
+            if (mKeyguardUpdateMonitor.isUdfpsAvailable()) {
+                showTransientIndication(mContext.getString(R.string.keyguard_unlock_press),
+                        false /* isError */, true /* hideOnScreenOff */);
+            } else {
+                showTransientIndication(mContext.getString(R.string.keyguard_unlock),
+                        false /* isError */, true /* hideOnScreenOff */);
+            }
         }
     }
 
@@ -827,11 +839,6 @@
         mRotateTextViewController.dump(fd, pw, args);
     }
 
-    @Override
-    public void onUnlockedChanged() {
-        updateIndication(false);
-    }
-
     protected class BaseKeyguardCallback extends KeyguardUpdateMonitorCallback {
         public static final int HIDE_DELAY_MS = 5000;
 
@@ -899,7 +906,7 @@
                 showTransientIndication(helpString, false /* isError */, showSwipeToUnlock);
             }
             if (showSwipeToUnlock) {
-                mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SWIPE_UP_TO_UNLOCK),
+                mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SHOW_ACTION_TO_UNLOCK),
                         TRANSIENT_BIOMETRIC_ERROR_TIMEOUT);
             }
         }
@@ -933,7 +940,7 @@
                     );
                 } else {
                     // suggest swiping up to unlock (try face auth again or swipe up to bouncer)
-                    showSwipeUpToUnlock();
+                    showActionToUnlock();
                 }
             } else if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
                 mStatusBarKeyguardViewManager.showBouncerMessage(errString, mInitialTextColorState);
@@ -967,10 +974,8 @@
         }
 
         private boolean shouldSuppressFaceMsgAndShowTryFingerprintMsg() {
-            // For dual biometric, don't show face auth messages unless face auth was explicitly
-            // requested by the user.
+            // For dual biometric, don't show face auth messages
             return mKeyguardUpdateMonitor.isFingerprintDetectionRunning()
-                && !mKeyguardUpdateMonitor.isFaceAuthUserRequested()
                 && mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
                     true /* isStrongBiometric */);
         }
@@ -1017,6 +1022,11 @@
                 boolean isStrongBiometric) {
             super.onBiometricAuthenticated(userId, biometricSourceType, isStrongBiometric);
             mHandler.sendEmptyMessage(MSG_HIDE_TRANSIENT);
+
+            if (biometricSourceType == BiometricSourceType.FACE
+                    && !mKeyguardBypassController.canBypass()) {
+                mHandler.sendEmptyMessage(MSG_SHOW_ACTION_TO_UNLOCK);
+            }
         }
 
         @Override
@@ -1068,4 +1078,20 @@
             updateIndication(false);
         }
     };
+
+    private KeyguardStateController.Callback mKeyguardStateCallback =
+            new KeyguardStateController.Callback() {
+        @Override
+        public void onUnlockedChanged() {
+            updateIndication(false);
+        }
+
+        @Override
+        public void onKeyguardShowingChanged() {
+            if (!mKeyguardStateController.isShowing()) {
+                mTopIndicationView.clearMessages();
+                mLockScreenIndicationView.clearMessages();
+            }
+        }
+    };
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
index 6f4a73e..6fa06a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -65,6 +65,7 @@
     configurationController: ConfigurationController,
     falsingManager: FalsingManager
 ) {
+    private var pulseHeight: Float = 0f
     private var useSplitShade: Boolean = false
     private lateinit var nsslController: NotificationStackScrollLayoutController
     lateinit var notificationPanelController: NotificationPanelViewController
@@ -88,6 +89,12 @@
     internal var dragDownAnimator: ValueAnimator? = null
 
     /**
+     * The current pulse height animator if any
+     */
+    @VisibleForTesting
+    internal var pulseHeightAnimator: ValueAnimator? = null
+
+    /**
      * Distance that the full shade transition takes in order for scrim to fully transition to
      * the shade (in alpha)
      */
@@ -110,6 +117,12 @@
     private var nextHideKeyguardNeedsNoAnimation = false
 
     /**
+     * The distance until we're showing the notifications when pulsing
+     */
+    val distanceUntilShowingPulsingNotifications
+        get() = scrimTransitionDistance
+
+    /**
      * The udfpsKeyguardViewController if it exists.
      */
     var udfpsKeyguardViewController: UdfpsKeyguardViewController? = null
@@ -286,22 +299,26 @@
                     nsslController.setTransitionToFullShadeAmount(field)
                     notificationPanelController.setTransitionToFullShadeAmount(field,
                             false /* animate */, 0 /* delay */)
-                    val scrimProgress = MathUtils.saturate(field / scrimTransitionDistance)
-                    scrimController.setTransitionToFullShadeProgress(scrimProgress)
                     // TODO: appear qs also in split shade
                     val qsAmount = if (useSplitShade) 0f else field
                     qS.setTransitionToFullShadeAmount(qsAmount, false /* animate */)
                     // TODO: appear media also in split shade
                     val mediaAmount = if (useSplitShade) 0f else field
                     mediaHierarchyManager.setTransitionToFullShadeAmount(mediaAmount)
-                    // Fade out all content only visible on the lockscreen
-                    notificationPanelController.setKeyguardOnlyContentAlpha(1.0f - scrimProgress)
-                    depthController.transitionToFullShadeProgress = scrimProgress
-                    udfpsKeyguardViewController?.setTransitionToFullShadeProgress(scrimProgress)
+                    transitionToShadeAmountCommon(field)
                 }
             }
         }
 
+    private fun transitionToShadeAmountCommon(dragDownAmount: Float) {
+        val scrimProgress = MathUtils.saturate(dragDownAmount / scrimTransitionDistance)
+        scrimController.setTransitionToFullShadeProgress(scrimProgress)
+        // Fade out all content only visible on the lockscreen
+        notificationPanelController.setKeyguardOnlyContentAlpha(1.0f - scrimProgress)
+        depthController.transitionToFullShadeProgress = scrimProgress
+        udfpsKeyguardViewController?.setTransitionToFullShadeProgress(scrimProgress)
+    }
+
     private fun setDragDownAmountAnimated(
         target: Float,
         delay: Long = 0,
@@ -453,15 +470,19 @@
     /**
      * Notify this handler that the keyguard was just dismissed and that a animation to
      * the full shade should happen.
+     *
+     * @param delay the delay to do the animation with
+     * @param previousState which state were we in when we hid the keyguard?
      */
-    fun onHideKeyguard(delay: Long) {
+    fun onHideKeyguard(delay: Long, previousState: Int) {
         if (animationHandlerOnKeyguardDismiss != null) {
             animationHandlerOnKeyguardDismiss!!.invoke(delay)
             animationHandlerOnKeyguardDismiss = null
         } else {
             if (nextHideKeyguardNeedsNoAnimation) {
                 nextHideKeyguardNeedsNoAnimation = false
-            } else {
+            } else if (previousState != StatusBarState.SHADE_LOCKED) {
+                // No animation necessary if we already were in the shade locked!
                 performDefaultGoToFullShadeAnimation(delay)
             }
         }
@@ -479,6 +500,53 @@
         notificationPanelController.animateToFullShade(delay)
         animateAppear(delay)
     }
+
+    //
+    // PULSE EXPANSION
+    //
+
+    /**
+     * Set the height how tall notifications are pulsing. This is only set whenever we are expanding
+     * from a pulse and determines how much the notifications are expanded.
+     */
+    fun setPulseHeight(height: Float, animate: Boolean = false) {
+        if (animate) {
+            val pulseHeightAnimator = ValueAnimator.ofFloat(pulseHeight, height)
+            pulseHeightAnimator.interpolator = Interpolators.FAST_OUT_SLOW_IN
+            pulseHeightAnimator.duration = SPRING_BACK_ANIMATION_LENGTH_MS
+            pulseHeightAnimator.addUpdateListener { animation: ValueAnimator ->
+                setPulseHeight(animation.animatedValue as Float)
+            }
+            pulseHeightAnimator.start()
+            this.pulseHeightAnimator = pulseHeightAnimator
+        } else {
+            pulseHeight = height
+            val overflow = nsslController.setPulseHeight(height)
+            notificationPanelController.setOverStrechAmount(overflow)
+            val transitionHeight = if (keyguardBypassController.bypassEnabled) height else 0.0f
+            transitionToShadeAmountCommon(transitionHeight)
+        }
+    }
+
+    /**
+     * Finish the pulse animation when the touch interaction finishes
+     * @param cancelled was the interaction cancelled and this is a reset?
+     */
+    fun finishPulseAnimation(cancelled: Boolean) {
+        if (cancelled) {
+            setPulseHeight(0f, animate = true)
+        } else {
+            notificationPanelController.onPulseExpansionFinished()
+            setPulseHeight(0f, animate = false)
+        }
+    }
+
+    /**
+     * Notify this class that a pulse expansion is starting
+     */
+    fun onPulseExpansionStarted() {
+        pulseHeightAnimator?.cancel()
+    }
 }
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
index 28bdd5f..db553e4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
@@ -89,6 +89,9 @@
     private var prevShadeDirection = 0
     private var prevShadeVelocity = 0f
 
+    // Only for dumpsys
+    private var lastAppliedBlur = 0
+
     @VisibleForTesting
     var shadeSpring = DepthAnimation()
     var shadeAnimation = DepthAnimation()
@@ -201,6 +204,7 @@
         val opaque = scrimsVisible && !blursDisabledForAppLaunch
         Trace.traceCounter(Trace.TRACE_TAG_APP, "shade_blur_radius", blur)
         blurUtils.applyBlur(blurRoot?.viewRootImpl ?: root.viewRootImpl, blur, opaque)
+        lastAppliedBlur = blur
         try {
             if (root.isAttachedToWindow && root.windowToken != null) {
                 wallpaperManager.setWallpaperZoomOut(root.windowToken, zoomOut)
@@ -271,6 +275,11 @@
                 brightnessMirrorSpring.finishIfRunning()
             }
         }
+
+        override fun onDozeAmountChanged(linear: Float, eased: Float) {
+            wakeAndUnlockBlurRadius = blurUtils.blurRadiusOfRatio(eased)
+            scheduleUpdate()
+        }
     }
 
     init {
@@ -428,6 +437,9 @@
             it.println("brightnessMirrorRadius: ${brightnessMirrorSpring.radius}")
             it.println("wakeAndUnlockBlur: $wakeAndUnlockBlurRadius")
             it.println("blursDisabledForAppLaunch: $blursDisabledForAppLaunch")
+            it.println("qsPanelExpansion: $qsPanelExpansion")
+            it.println("transitionToFullShadeProgress: $transitionToFullShadeProgress")
+            it.println("lastAppliedBlur: $lastAppliedBlur")
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
index b34bfad..761a203 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
@@ -19,8 +19,8 @@
 import android.animation.Animator
 import android.animation.AnimatorListenerAdapter
 import android.animation.ObjectAnimator
-import android.animation.ValueAnimator
 import android.content.Context
+import android.content.res.Configuration
 import android.os.PowerManager
 import android.os.PowerManager.WAKE_REASON_GESTURE
 import android.os.SystemClock
@@ -42,6 +42,7 @@
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
 import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
 import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.policy.ConfigurationController
 import javax.inject.Inject
 import kotlin.math.max
 
@@ -56,18 +57,17 @@
     private val bypassController: KeyguardBypassController,
     private val headsUpManager: HeadsUpManagerPhone,
     private val roundnessManager: NotificationRoundnessManager,
+    private val configurationController: ConfigurationController,
     private val statusBarStateController: StatusBarStateController,
     private val falsingManager: FalsingManager,
     private val lockscreenShadeTransitionController: LockscreenShadeTransitionController,
     private val falsingCollector: FalsingCollector
 ) : Gefingerpoken {
     companion object {
-        private val RUBBERBAND_FACTOR_STATIC = 0.25f
         private val SPRING_BACK_ANIMATION_LENGTH_MS = 375
     }
     private val mPowerManager: PowerManager?
 
-    private val mMinDragDistance: Int
     private var mInitialTouchX: Float = 0.0f
     private var mInitialTouchY: Float = 0.0f
     var isExpanding: Boolean = false
@@ -81,6 +81,7 @@
                     topEntry?.let {
                         roundnessManager.setTrackingHeadsUp(it.row)
                     }
+                    lockscreenShadeTransitionController.onPulseExpansionStarted()
                 } else {
                     roundnessManager.setTrackingHeadsUp(null)
                     if (!leavingLockscreen) {
@@ -93,8 +94,8 @@
         }
     var leavingLockscreen: Boolean = false
         private set
-    private val mTouchSlop: Float
-    private lateinit var overStretchHandler: OverStretchHandler
+    private var touchSlop = 0f
+    private var minDragDistance = 0
     private lateinit var stackScrollerController: NotificationStackScrollLayoutController
     private val mTemp2 = IntArray(2)
     private var mDraggedFarEnough: Boolean = false
@@ -102,9 +103,7 @@
     private var mPulsing: Boolean = false
     var isWakingToShadeLocked: Boolean = false
         private set
-    private var overStretchAmount: Float = 0.0f
-    private var mWakeUpHeight: Float = 0.0f
-    private var mReachedWakeUpHeight: Boolean = false
+
     private var velocityTracker: VelocityTracker? = null
 
     private val isFalseTouch: Boolean
@@ -114,12 +113,21 @@
     var bouncerShowing: Boolean = false
 
     init {
-        mMinDragDistance = context.resources.getDimensionPixelSize(
-                R.dimen.keyguard_drag_down_min_distance)
-        mTouchSlop = ViewConfiguration.get(context).scaledTouchSlop.toFloat()
+        initResources(context)
+        configurationController.addCallback(object : ConfigurationController.ConfigurationListener {
+            override fun onConfigChanged(newConfig: Configuration?) {
+                initResources(context)
+            }
+        })
         mPowerManager = context.getSystemService(PowerManager::class.java)
     }
 
+    private fun initResources(context: Context) {
+        minDragDistance = context.resources.getDimensionPixelSize(
+            R.dimen.keyguard_drag_down_min_distance)
+        touchSlop = ViewConfiguration.get(context).scaledTouchSlop.toFloat()
+    }
+
     override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
         return canHandleMotionEvent() && startExpansion(event)
     }
@@ -148,14 +156,12 @@
 
             MotionEvent.ACTION_MOVE -> {
                 val h = y - mInitialTouchY
-                if (h > mTouchSlop && h > Math.abs(x - mInitialTouchX)) {
+                if (h > touchSlop && h > Math.abs(x - mInitialTouchX)) {
                     falsingCollector.onStartExpandingFromPulse()
                     isExpanding = true
                     captureStartingChild(mInitialTouchX, mInitialTouchY)
                     mInitialTouchY = y
                     mInitialTouchX = x
-                    mWakeUpHeight = wakeUpCoordinator.getWakeUpHeight()
-                    mReachedWakeUpHeight = false
                     return true
                 }
             }
@@ -216,7 +222,6 @@
     }
 
     private fun finishExpansion() {
-        resetClock()
         val startingChild = mStartingChild
         if (mStartingChild != null) {
             setUserLocked(mStartingChild!!, false)
@@ -230,6 +235,7 @@
         }
         lockscreenShadeTransitionController.goToLockedShade(startingChild,
                 needsQSAnimation = false)
+        lockscreenShadeTransitionController.finishPulseAnimation(cancelled = false)
         leavingLockscreen = true
         isExpanding = false
         if (mStartingChild is ExpandableNotificationRow) {
@@ -240,24 +246,19 @@
 
     private fun updateExpansionHeight(height: Float) {
         var expansionHeight = max(height, 0.0f)
-        if (!mReachedWakeUpHeight && height > mWakeUpHeight) {
-            mReachedWakeUpHeight = true
-        }
         if (mStartingChild != null) {
             val child = mStartingChild!!
             val newHeight = Math.min((child.collapsedHeight + expansionHeight).toInt(),
                     child.maxContentHeight)
             child.actualHeight = newHeight
-            expansionHeight = max(newHeight.toFloat(), expansionHeight)
         } else {
-            val target = if (mReachedWakeUpHeight) mWakeUpHeight else 0.0f
-            wakeUpCoordinator.setNotificationsVisibleForExpansion(height > target,
-                    true /* animate */,
-                    true /* increaseSpeed */)
-            expansionHeight = max(mWakeUpHeight, expansionHeight)
+            wakeUpCoordinator.setNotificationsVisibleForExpansion(
+                height
+                    > lockscreenShadeTransitionController.distanceUntilShowingPulsingNotifications,
+                true /* animate */,
+                true /* increaseSpeed */)
         }
-        val dragDownAmount = wakeUpCoordinator.setPulseHeight(expansionHeight)
-        setOverStretchAmount(dragDownAmount)
+        lockscreenShadeTransitionController.setPulseHeight(expansionHeight, animate = false)
     }
 
     private fun captureStartingChild(x: Float, y: Float) {
@@ -269,11 +270,6 @@
         }
     }
 
-    private fun setOverStretchAmount(amount: Float) {
-        overStretchAmount = amount
-        overStretchHandler.setOverStretchAmount(amount)
-    }
-
     private fun reset(child: ExpandableView) {
         if (child.actualHeight == child.collapsedHeight) {
             setUserLocked(child, false)
@@ -297,25 +293,14 @@
         }
     }
 
-    private fun resetClock() {
-        val anim = ValueAnimator.ofFloat(overStretchAmount, 0f)
-        anim.interpolator = Interpolators.FAST_OUT_SLOW_IN
-        anim.duration = SPRING_BACK_ANIMATION_LENGTH_MS.toLong()
-        anim.addUpdateListener {
-            animation -> setOverStretchAmount(animation.animatedValue as Float)
-        }
-        anim.start()
-    }
-
     private fun cancelExpansion() {
         isExpanding = false
         falsingCollector.onExpansionFromPulseStopped()
         if (mStartingChild != null) {
             reset(mStartingChild!!)
             mStartingChild = null
-        } else {
-            resetClock()
         }
+        lockscreenShadeTransitionController.finishPulseAnimation(cancelled = true)
         wakeUpCoordinator.setNotificationsVisibleForExpansion(false /* visible */,
                 true /* animate */,
                 false /* increaseSpeed */)
@@ -333,11 +318,7 @@
         } else null
     }
 
-    fun setUp(
-        stackScrollerController: NotificationStackScrollLayoutController,
-        overStrechHandler: OverStretchHandler
-    ) {
-        this.overStretchHandler = overStrechHandler
+    fun setUp(stackScrollerController: NotificationStackScrollLayoutController) {
         this.stackScrollerController = stackScrollerController
     }
 
@@ -348,12 +329,4 @@
     fun onStartedWakingUp() {
         isWakingToShadeLocked = false
     }
-
-    interface OverStretchHandler {
-
-        /**
-         * Set the overstretch amount in pixels This will be rubberbanded later
-         */
-        fun setOverStretchAmount(amount: Float)
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
index 5f10e55..29cfb07 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
@@ -18,6 +18,8 @@
 
 import android.animation.Animator
 import android.annotation.UiThread
+import android.graphics.Point
+import android.graphics.Rect
 import android.util.Log
 import android.view.Gravity
 import android.view.View
@@ -31,9 +33,16 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.statusbar.StatusBarState.SHADE
 import com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED
-import com.android.systemui.statusbar.phone.StatusBarLocationPublisher
-import com.android.systemui.statusbar.phone.StatusBarMarginUpdatedListener
+import com.android.systemui.statusbar.phone.StatusBarContentInsetsChangedListener
+import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
+import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.util.concurrency.DelayableExecutor
+import com.android.systemui.util.leak.RotationUtils
+import com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE
+import com.android.systemui.util.leak.RotationUtils.ROTATION_NONE
+import com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE
+import com.android.systemui.util.leak.RotationUtils.ROTATION_UPSIDE_DOWN
+import com.android.systemui.util.leak.RotationUtils.Rotation
 
 import java.lang.IllegalStateException
 import java.util.concurrent.Executor
@@ -58,7 +67,8 @@
 class PrivacyDotViewController @Inject constructor(
     @Main private val mainExecutor: Executor,
     private val stateController: StatusBarStateController,
-    private val locationPublisher: StatusBarLocationPublisher,
+    private val configurationController: ConfigurationController,
+    private val contentInsetsProvider: StatusBarContentInsetsProvider,
     private val animationScheduler: SystemStatusAnimationScheduler
 ) {
     private var sbHeightPortrait = 0
@@ -84,18 +94,27 @@
     // Privacy dots are created in ScreenDecoration's UiThread, which is not the main thread
     private var uiExecutor: DelayableExecutor? = null
 
-    private val marginListener: StatusBarMarginUpdatedListener =
-            object : StatusBarMarginUpdatedListener {
-        override fun onStatusBarMarginUpdated(marginLeft: Int, marginRight: Int) {
-            setStatusBarMargins(marginLeft, marginRight)
-        }
-    }
-
     private val views: Sequence<View>
         get() = if (!this::tl.isInitialized) sequenceOf() else sequenceOf(tl, tr, br, bl)
 
     init {
-        locationPublisher.addCallback(marginListener)
+        contentInsetsProvider.addCallback(object : StatusBarContentInsetsChangedListener {
+            override fun onStatusBarContentInsetsChanged() {
+                dlog("onStatusBarContentInsetsChanged: ")
+                setNewLayoutRects()
+            }
+        })
+        configurationController.addCallback(object : ConfigurationController.ConfigurationListener {
+            override fun onLayoutDirectionChanged(isRtl: Boolean) {
+                synchronized(this) {
+                    val corner = selectDesignatedCorner(nextViewState.rotation, isRtl)
+                    nextViewState = nextViewState.copy(
+                            layoutRtl = isRtl,
+                            designatedCorner = corner
+                    )
+                }
+            }
+        })
 
         stateController.addCallback(object : StatusBarStateController.StateListener {
             override fun onExpandedChanged(isExpanded: Boolean) {
@@ -123,16 +142,19 @@
     fun setNewRotation(rot: Int) {
         dlog("updateRotation: $rot")
 
+        val isRtl: Boolean
         synchronized(lock) {
             if (rot == nextViewState.rotation) {
                 return
             }
+
+            isRtl = nextViewState.layoutRtl
         }
 
         // If we rotated, hide all dotes until the next state resolves
         setCornerVisibilities(View.INVISIBLE)
 
-        val newCorner = selectDesignatedCorner(rot)
+        val newCorner = selectDesignatedCorner(rot, isRtl)
         val index = newCorner.cornerIndex()
 
         val h = when (rot) {
@@ -222,15 +244,77 @@
         }
     }
 
+    @UiThread
+    private fun setCornerSizes(state: ViewState) {
+        // StatusBarContentInsetsProvider can tell us the location of the privacy indicator dot
+        // in every rotation. The only thing we need to check is rtl
+        val rtl = state.layoutRtl
+        val size = Point()
+        tl.context.display.getRealSize(size)
+        val currentRotation = RotationUtils.getExactRotation(tl.context)
+
+        val displayWidth: Int
+        val displayHeight: Int
+        if (currentRotation == ROTATION_LANDSCAPE || currentRotation == ROTATION_SEASCAPE) {
+            displayWidth = size.y
+            displayHeight = size.x
+        } else {
+            displayWidth = size.x
+            displayHeight = size.y
+        }
+
+        var rot = activeRotationForCorner(tl, rtl)
+        var contentInsets = state.contentRectForRotation(rot)
+        (tl.layoutParams as FrameLayout.LayoutParams).apply {
+            height = contentInsets.height()
+            if (rtl) {
+                width = contentInsets.left
+            } else {
+                width = displayHeight - contentInsets.right
+            }
+        }
+
+        rot = activeRotationForCorner(tr, rtl)
+        contentInsets = state.contentRectForRotation(rot)
+        (tr.layoutParams as FrameLayout.LayoutParams).apply {
+            height = contentInsets.height()
+            if (rtl) {
+                width = contentInsets.left
+            } else {
+                width = displayWidth - contentInsets.right
+            }
+        }
+
+        rot = activeRotationForCorner(br, rtl)
+        contentInsets = state.contentRectForRotation(rot)
+        (br.layoutParams as FrameLayout.LayoutParams).apply {
+            height = contentInsets.height()
+            if (rtl) {
+                width = contentInsets.left
+            } else {
+                width = displayHeight - contentInsets.right
+            }
+        }
+
+        rot = activeRotationForCorner(bl, rtl)
+        contentInsets = state.contentRectForRotation(rot)
+        (bl.layoutParams as FrameLayout.LayoutParams).apply {
+            height = contentInsets.height()
+            if (rtl) {
+                width = contentInsets.left
+            } else {
+                width = displayWidth - contentInsets.right
+            }
+        }
+    }
+
     // Designated view will be the one at statusbar's view.END
     @UiThread
-    private fun selectDesignatedCorner(r: Int): View? {
+    private fun selectDesignatedCorner(r: Int, isRtl: Boolean): View? {
         if (!this::tl.isInitialized) {
             return null
         }
 
-        val isRtl = tl.isLayoutRtl
-
         return when (r) {
             0 -> if (isRtl) tl else tr
             1 -> if (isRtl) tr else br
@@ -282,6 +366,17 @@
         return modded
     }
 
+    @Rotation
+    private fun activeRotationForCorner(corner: View, rtl: Boolean): Int {
+        // Each corner will only be visible in a single rotation, based on rtl
+        return when (corner) {
+            tr -> if (rtl) ROTATION_LANDSCAPE else ROTATION_NONE
+            tl -> if (rtl) ROTATION_NONE else ROTATION_SEASCAPE
+            br -> if (rtl) ROTATION_UPSIDE_DOWN else ROTATION_LANDSCAPE
+            else /* bl */ -> if (rtl) ROTATION_SEASCAPE else ROTATION_UPSIDE_DOWN
+        }
+    }
+
     private fun widthForCorner(corner: Int, left: Int, right: Int): Int {
         return when (corner) {
             TOP_LEFT, BOTTOM_LEFT -> left
@@ -303,15 +398,32 @@
         bl = bottomLeft
         br = bottomRight
 
-        val dc = selectDesignatedCorner(0)
+        val rtl = configurationController.isLayoutRtl
+        val dc = selectDesignatedCorner(0, rtl)
+
         val index = dc.cornerIndex()
 
         mainExecutor.execute {
             animationScheduler.addCallback(systemStatusAnimationCallback)
         }
 
+        val left = contentInsetsProvider.getStatusBarContentInsetsForRotation(ROTATION_SEASCAPE)
+        val top = contentInsetsProvider.getStatusBarContentInsetsForRotation(ROTATION_NONE)
+        val right = contentInsetsProvider.getStatusBarContentInsetsForRotation(ROTATION_LANDSCAPE)
+        val bottom = contentInsetsProvider
+                .getStatusBarContentInsetsForRotation(ROTATION_UPSIDE_DOWN)
+
         synchronized(lock) {
-            nextViewState = nextViewState.copy(designatedCorner = dc, cornerIndex = index)
+            nextViewState = nextViewState.copy(
+                    viewInitialized = true,
+                    designatedCorner = dc,
+                    cornerIndex = index,
+                    seascapeRect = left,
+                    portraitRect = top,
+                    landscapeRect = right,
+                    upsideDownRect = bottom,
+                    layoutRtl = rtl
+            )
         }
     }
 
@@ -324,19 +436,6 @@
         sbHeightLandscape = landscape
     }
 
-    /**
-     * The dot view containers will fill the margin in order to position the dots correctly
-     *
-     * @param left the space between the status bar contents and the left side of the screen
-     * @param right space between the status bar contents and the right side of the screen
-     */
-    private fun setStatusBarMargins(left: Int, right: Int) {
-        dlog("setStatusBarMargins l=$left r=$right")
-        synchronized(lock) {
-            nextViewState = nextViewState.copy(marginLeft = left, marginRight = right)
-        }
-    }
-
     private fun updateStatusBarState() {
         synchronized(lock) {
             nextViewState = nextViewState.copy(shadeExpanded = isShadeInQs())
@@ -377,6 +476,11 @@
     @UiThread
     private fun resolveState(state: ViewState) {
         dlog("resolveState $state")
+        if (!state.viewInitialized) {
+            dlog("resolveState: view is not initialized. skipping.")
+            return
+        }
+
         if (state == currentViewState) {
             dlog("resolveState: skipping")
             return
@@ -387,23 +491,15 @@
             updateRotations(state.rotation)
         }
 
-        if (state.height != currentViewState.height) {
-            updateHeights(state.rotation)
-        }
-
-        if (state.marginLeft != currentViewState.marginLeft ||
-                state.marginRight != currentViewState.marginRight) {
-            updateCornerSizes(state.marginLeft, state.marginRight, state.rotation)
+        if (state.needsLayout(currentViewState)) {
+            setCornerSizes(state)
+            views.forEach { it.requestLayout() }
         }
 
         if (state.designatedCorner != currentViewState.designatedCorner) {
             updateDesignatedCorner(state.designatedCorner, state.shouldShowDot())
         }
 
-        if (state.needsLayout(currentViewState)) {
-            views.forEach { it.requestLayout() }
-        }
-
         val shouldShow = state.shouldShowDot()
         if (shouldShow != currentViewState.shouldShowDot()) {
             if (shouldShow && state.designatedCorner != null) {
@@ -441,6 +537,30 @@
         }
         return -1
     }
+
+    // Returns [left, top, right, bottom] aka [seascape, none, landscape, upside-down]
+    private fun getLayoutRects(): List<Rect> {
+        val left = contentInsetsProvider.getStatusBarContentInsetsForRotation(ROTATION_SEASCAPE)
+        val top = contentInsetsProvider.getStatusBarContentInsetsForRotation(ROTATION_NONE)
+        val right = contentInsetsProvider.getStatusBarContentInsetsForRotation(ROTATION_LANDSCAPE)
+        val bottom = contentInsetsProvider
+                .getStatusBarContentInsetsForRotation(ROTATION_UPSIDE_DOWN)
+
+        return listOf(left, top, right, bottom)
+    }
+
+    private fun setNewLayoutRects() {
+        val rects = getLayoutRects()
+
+        synchronized(lock) {
+            nextViewState = nextViewState.copy(
+                    seascapeRect = rects[0],
+                    portraitRect = rects[1],
+                    landscapeRect = rects[2],
+                    upsideDownRect = rects[3]
+            )
+        }
+    }
 }
 
 private fun dlog(s: String) {
@@ -461,7 +581,7 @@
 const val BOTTOM_LEFT = 3
 private const val DURATION = 160L
 private const val TAG = "PrivacyDotViewController"
-private const val DEBUG = true
+private const val DEBUG = false
 private const val DEBUG_VERBOSE = false
 
 private fun Int.toGravity(): Int {
@@ -485,14 +605,20 @@
 }
 
 private data class ViewState(
+    val viewInitialized: Boolean = false,
+
     val systemPrivacyEventIsActive: Boolean = false,
     val shadeExpanded: Boolean = false,
     val qsExpanded: Boolean = false,
 
+    val portraitRect: Rect? = null,
+    val landscapeRect: Rect? = null,
+    val upsideDownRect: Rect? = null,
+    val seascapeRect: Rect? = null,
+    val layoutRtl: Boolean = false,
+
     val rotation: Int = 0,
     val height: Int = 0,
-    val marginLeft: Int = 0,
-    val marginRight: Int = 0,
     val cornerIndex: Int = -1,
     val designatedCorner: View? = null
 ) {
@@ -502,7 +628,20 @@
 
     fun needsLayout(other: ViewState): Boolean {
         return rotation != other.rotation ||
-                marginRight != other.marginRight ||
-                height != other.height
+                layoutRtl != other.layoutRtl ||
+                portraitRect != other.portraitRect ||
+                landscapeRect != other.landscapeRect ||
+                upsideDownRect != other.upsideDownRect ||
+                seascapeRect != other.seascapeRect
+    }
+
+    fun contentRectForRotation(@Rotation rot: Int): Rect {
+        return when (rot) {
+            ROTATION_NONE -> portraitRect!!
+            ROTATION_LANDSCAPE -> landscapeRect!!
+            ROTATION_UPSIDE_DOWN -> upsideDownRect!!
+            ROTATION_SEASCAPE -> seascapeRect!!
+            else -> throw IllegalArgumentException("not a rotation ($rot)")
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
index b0a7767..a2c9ffc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
@@ -374,10 +374,6 @@
         }
     }
 
-    fun getWakeUpHeight(): Float {
-        return mStackScrollerController.wakeUpHeight
-    }
-
     private fun updateHideAmount() {
         val linearAmount = min(1.0f - mLinearVisibilityAmount, mLinearDozeAmount)
         val amount = min(1.0f - mVisibilityAmount, mDozeAmount)
@@ -395,16 +391,6 @@
         }
     }
 
-    /**
-     * Set the height how tall notifications are pulsing. This is only set whenever we are expanding
-     * from a pulse and determines how much the notifications are expanded.
-     */
-    fun setPulseHeight(height: Float): Float {
-        val overflow = mStackScrollerController.setPulseHeight(height)
-        //  no overflow for the bypass experience
-        return if (bypassController.bypassEnabled) 0.0f else overflow
-    }
-
     override fun onHeadsUpStateChanged(entry: NotificationEntry, isHeadsUp: Boolean) {
         var animate = shouldAnimateVisibility()
         if (!isHeadsUp) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 93166f3..73bb6cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -287,7 +287,7 @@
                 mGroupExpansionChanging = true;
                 final boolean wasExpanded = mGroupExpansionManager.isGroupExpanded(mEntry);
                 boolean nowExpanded = mGroupExpansionManager.toggleGroupExpansion(mEntry);
-                mOnExpandClickListener.onExpandClicked(mEntry, nowExpanded);
+                mOnExpandClickListener.onExpandClicked(mEntry, v, nowExpanded);
                 MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTIFICATION_GROUP_EXPANDER,
                         nowExpanded);
                 onExpansionChanged(true /* userAction */, wasExpanded);
@@ -310,7 +310,7 @@
                     setUserExpanded(nowExpanded);
                 }
                 notifyHeightChanged(true);
-                mOnExpandClickListener.onExpandClicked(mEntry, nowExpanded);
+                mOnExpandClickListener.onExpandClicked(mEntry, v, nowExpanded);
                 MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTIFICATION_EXPANDER,
                         nowExpanded);
             }
@@ -3064,7 +3064,7 @@
     }
 
     public interface OnExpandClickListener {
-        void onExpandClicked(NotificationEntry clickedEntry, boolean nowExpanded);
+        void onExpandClicked(NotificationEntry clickedEntry, View clickedView, boolean nowExpanded);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 4ad7202..289c32f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -5138,12 +5138,17 @@
      * @return the overflow how much the height is further than he lowest notification
      */
     public float setPulseHeight(float height) {
+        float overflow;
         mAmbientState.setPulseHeight(height);
         if (mKeyguardBypassEnabledProvider.getBypassEnabled()) {
             notifyAppearChangedListeners();
+            overflow = Math.max(0, height - getIntrinsicPadding());
+        } else {
+            overflow = Math.max(0, height
+                    - mAmbientState.getInnerHeight(true /* ignorePulseHeight */));
         }
         requestChildrenUpdate();
-        return Math.max(0, height - mAmbientState.getInnerHeight(true /* ignorePulseHeight */));
+        return overflow;
     }
 
     public float getPulseHeight() {
@@ -5203,12 +5208,9 @@
 
     public float calculateAppearFractionBypass() {
         float pulseHeight = getPulseHeight();
-        float wakeUpHeight = getWakeUpHeight();
-        float dragDownAmount = pulseHeight - wakeUpHeight;
-
         // The total distance required to fully reveal the header
         float totalDistance = getIntrinsicPadding();
-        return MathUtils.smoothStep(0, totalDistance, dragDownAmount);
+        return MathUtils.smoothStep(0, totalDistance, pulseHeight);
     }
 
     public void setController(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 09afedb..9e4adce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -885,10 +885,6 @@
         mView.setDozeAmount(amount);
     }
 
-    public float getWakeUpHeight() {
-        return mView.getWakeUpHeight();
-    }
-
     public int getSpeedBumpIndex() {
         return mView.getSpeedBumpIndex();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 23e3742..b36dc56 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -274,7 +274,9 @@
         // expanded. Consider updating these states in updateContentView instead so that we don't
         // have to recalculate in every frame.
         float currentY = -ambientState.getScrollY();
-        if (!ambientState.isOnKeyguard()) {
+        if (!ambientState.isOnKeyguard()
+                || (ambientState.isBypassEnabled() && ambientState.isPulseExpanding())) {
+            // add top padding at the start as long as we're not on the lock screen
             currentY += mNotificationScrimPadding;
         }
         state.firstViewInShelf = null;
@@ -324,7 +326,8 @@
      */
     private void updatePositionsForState(StackScrollAlgorithmState algorithmState,
             AmbientState ambientState) {
-        if (!ambientState.isOnKeyguard()) {
+        if (!ambientState.isOnKeyguard()
+                || (ambientState.isBypassEnabled() && ambientState.isPulseExpanding())) {
             algorithmState.mCurrentYPosition += mNotificationScrimPadding;
             algorithmState.mCurrentExpandedYPosition += mNotificationScrimPadding;
         }
@@ -355,7 +358,9 @@
                 && algorithmState.firstViewInShelf != null;
 
         final float shelfHeight = showingShelf ? ambientState.getShelf().getIntrinsicHeight() : 0f;
-        final float scrimPadding = ambientState.isOnKeyguard() ? 0 : mNotificationScrimPadding;
+        final float scrimPadding = ambientState.isOnKeyguard()
+                && (!ambientState.isBypassEnabled() || !ambientState.isPulseExpanding())
+                ? 0 : mNotificationScrimPadding;
 
         final float stackHeight = ambientState.getStackHeight()  - shelfHeight - scrimPadding;
         final float stackEndHeight = ambientState.getStackEndHeight() - shelfHeight - scrimPadding;
@@ -394,7 +399,8 @@
                     ambientState.getExpansionFraction(), true /* notification */);
         }
 
-        if (view.mustStayOnScreen() && viewState.yTranslation >= 0) {
+        if (ambientState.isShadeExpanded() && view.mustStayOnScreen()
+                && viewState.yTranslation >= 0) {
             // Even if we're not scrolled away we're in view and we're also not in the
             // shelf. We can relax the constraints and let us scroll off the top!
             float end = viewState.yTranslation + viewState.height + ambientState.getStackY();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
index 1361acb..6d12a1c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
@@ -37,7 +37,6 @@
 import android.view.ViewStub;
 import android.widget.LinearLayout;
 
-import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.animation.Interpolators;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -76,9 +75,9 @@
     public static final int FADE_IN_DURATION = 320;
     public static final int FADE_IN_DELAY = 50;
     private PhoneStatusBarView mStatusBar;
-    private StatusBarStateController mStatusBarStateController;
-    private KeyguardStateController mKeyguardStateController;
-    private NetworkController mNetworkController;
+    private final StatusBarStateController mStatusBarStateController;
+    private final KeyguardStateController mKeyguardStateController;
+    private final NetworkController mNetworkController;
     private LinearLayout mSystemIconArea;
     private View mClockView;
     private View mOngoingCallChip;
@@ -86,15 +85,16 @@
     private View mCenteredIconArea;
     private int mDisabled1;
     private int mDisabled2;
-    private StatusBar mStatusBarComponent;
+    private final StatusBar mStatusBarComponent;
     private DarkIconManager mDarkIconManager;
     private View mOperatorNameFrame;
-    private CommandQueue mCommandQueue;
-    private OngoingCallController mOngoingCallController;
+    private final CommandQueue mCommandQueue;
+    private final OngoingCallController mOngoingCallController;
     private final SystemStatusAnimationScheduler mAnimationScheduler;
     private final StatusBarLocationPublisher mLocationPublisher;
-    private NotificationIconAreaController mNotificationIconAreaController;
     private final FeatureFlags mFeatureFlags;
+    private final NotificationIconAreaController mNotificationIconAreaController;
+    private final StatusBarIconController mStatusBarIconController;
 
     private List<String> mBlockedIcons = new ArrayList<>();
 
@@ -118,23 +118,25 @@
             SystemStatusAnimationScheduler animationScheduler,
             StatusBarLocationPublisher locationPublisher,
             NotificationIconAreaController notificationIconAreaController,
-            FeatureFlags featureFlags
+            FeatureFlags featureFlags,
+            StatusBarIconController statusBarIconController,
+            KeyguardStateController keyguardStateController,
+            NetworkController networkController,
+            StatusBarStateController statusBarStateController,
+            StatusBar statusBarComponent,
+            CommandQueue commandQueue
     ) {
         mOngoingCallController = ongoingCallController;
         mAnimationScheduler = animationScheduler;
         mLocationPublisher = locationPublisher;
         mNotificationIconAreaController = notificationIconAreaController;
         mFeatureFlags = featureFlags;
-    }
-
-    @Override
-    public void onCreate(@Nullable Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        mKeyguardStateController = Dependency.get(KeyguardStateController.class);
-        mNetworkController = Dependency.get(NetworkController.class);
-        mStatusBarStateController = Dependency.get(StatusBarStateController.class);
-        mStatusBarComponent = Dependency.get(StatusBar.class);
-        mCommandQueue = Dependency.get(CommandQueue.class);
+        mStatusBarIconController = statusBarIconController;
+        mKeyguardStateController = keyguardStateController;
+        mNetworkController = networkController;
+        mStatusBarStateController = statusBarStateController;
+        mStatusBarComponent = statusBarComponent;
+        mCommandQueue = commandQueue;
     }
 
     @Override
@@ -160,7 +162,7 @@
         mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_alarm_clock));
         mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_call_strength));
         mDarkIconManager.setBlockList(mBlockedIcons);
-        Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager);
+        mStatusBarIconController.addIconGroup(mDarkIconManager);
         mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area);
         mClockView = mStatusBar.findViewById(R.id.clock);
         mOngoingCallChip = mStatusBar.findViewById(R.id.ongoing_call_chip);
@@ -199,7 +201,8 @@
     @Override
     public void onDestroyView() {
         super.onDestroyView();
-        Dependency.get(StatusBarIconController.class).removeIconGroup(mDarkIconManager);
+        mStatusBarIconController.removeIconGroup(mDarkIconManager);
+        mAnimationScheduler.removeCallback(this);
         if (mNetworkController.hasEmergencyCryptKeeperText()) {
             mNetworkController.removeCallback(mSignalCallback);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
index b148eeb..07618da 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
@@ -18,6 +18,7 @@
 import android.content.pm.ActivityInfo
 import android.content.res.Configuration
 import android.os.LocaleList
+import android.view.View.LAYOUT_DIRECTION_RTL
 import com.android.systemui.statusbar.policy.ConfigurationController
 
 import java.util.ArrayList
@@ -33,6 +34,7 @@
     private var uiMode: Int = 0
     private var localeList: LocaleList? = null
     private val context: Context
+    private var layoutDirection: Int
 
     init {
         val currentConfig = context.resources.configuration
@@ -44,6 +46,7 @@
                 Configuration.UI_MODE_TYPE_CAR
         uiMode = currentConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK
         localeList = currentConfig.locales
+        layoutDirection = currentConfig.layoutDirection
     }
 
     override fun notifyThemeChanged() {
@@ -101,6 +104,13 @@
             }
         }
 
+        if (layoutDirection != newConfig.layoutDirection) {
+            layoutDirection = newConfig.layoutDirection
+            listeners.filterForEach({ this.listeners.contains(it) }) {
+                it.onLayoutDirectionChanged(layoutDirection == LAYOUT_DIRECTION_RTL)
+            }
+        }
+
         if (lastConfig.updateFrom(newConfig) and ActivityInfo.CONFIG_ASSETS_PATHS != 0) {
             listeners.filterForEach({ this.listeners.contains(it) }) {
                 it.onOverlayChanged()
@@ -116,6 +126,10 @@
     override fun removeCallback(listener: ConfigurationController.ConfigurationListener) {
         listeners.remove(listener)
     }
+
+    override fun isLayoutRtl(): Boolean {
+        return layoutDirection == LAYOUT_DIRECTION_RTL
+    }
 }
 
 // This could be done with a Collection.filter and Collection.forEach, but Collection.filter
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 91d503b..0a4e59c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -19,6 +19,7 @@
 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
 import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 
+import static com.android.systemui.controls.dagger.ControlsComponent.Visibility.AVAILABLE;
 import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;
 import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_BUTTON;
 import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_UNLOCK;
@@ -40,6 +41,7 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.content.res.ColorStateList;
 import android.content.res.Configuration;
 import android.graphics.drawable.Drawable;
 import android.os.AsyncTask;
@@ -81,6 +83,11 @@
 import com.android.systemui.animation.Interpolators;
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.camera.CameraIntents;
+import com.android.systemui.controls.ControlsServiceInfo;
+import com.android.systemui.controls.dagger.ControlsComponent;
+import com.android.systemui.controls.management.ControlsListingController;
+import com.android.systemui.controls.ui.ControlsActivity;
+import com.android.systemui.controls.ui.ControlsUiController;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.IntentButtonProvider;
@@ -98,6 +105,8 @@
 import com.android.systemui.wallet.controller.QuickAccessWalletController;
 import com.android.systemui.wallet.ui.WalletActivity;
 
+import java.util.List;
+
 /**
  * Implementation for the bottom area of the Keyguard, including camera/phone affordance and status
  * text.
@@ -133,9 +142,12 @@
     private KeyguardAffordanceView mLeftAffordanceView;
 
     private ImageView mWalletButton;
+    private ImageView mControlsButton;
     private boolean mHasCard = false;
     private WalletCardRetriever mCardRetriever = new WalletCardRetriever();
     private QuickAccessWalletController mQuickAccessWalletController;
+    private ControlsComponent mControlsComponent;
+    private boolean mControlServicesAvailable = false;
 
     private ViewGroup mIndicationArea;
     private TextView mIndicationText;
@@ -188,6 +200,19 @@
     private ActivityIntentHelper mActivityIntentHelper;
     private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
 
+    private ControlsListingController.ControlsListingCallback mListingCallback =
+            new ControlsListingController.ControlsListingCallback() {
+                public void onServicesUpdated(List<ControlsServiceInfo> serviceInfos) {
+                    boolean available = !serviceInfos.isEmpty();
+
+                    if (available != mControlServicesAvailable) {
+                        mControlServicesAvailable = available;
+                        updateControlsVisibility();
+                        updateAffordanceColors();
+                    }
+                }
+            };
+
     public KeyguardBottomAreaView(Context context) {
         this(context, null);
     }
@@ -253,6 +278,7 @@
         mRightAffordanceView = findViewById(R.id.camera_button);
         mLeftAffordanceView = findViewById(R.id.left_button);
         mWalletButton = findViewById(R.id.wallet_button);
+        mControlsButton = findViewById(R.id.controls_button);
         mIndicationArea = findViewById(R.id.keyguard_indication_area);
         mIndicationText = findViewById(R.id.keyguard_indication_text);
         mIndicationTextBottom = findViewById(R.id.keyguard_indication_text_bottom);
@@ -276,6 +302,7 @@
         mIndicationPadding = getResources().getDimensionPixelSize(
                 R.dimen.keyguard_indication_area_padding);
         updateWalletVisibility();
+        updateControlsVisibility();
     }
 
     /**
@@ -328,6 +355,11 @@
             mQuickAccessWalletController.unregisterWalletChangeObservers(
                     WALLET_PREFERENCE_CHANGE, DEFAULT_PAYMENT_APP_CHANGE);
         }
+
+        if (mControlsComponent != null) {
+            mControlsComponent.getControlsListingController().ifPresent(
+                    c -> c.removeCallback(mListingCallback));
+        }
     }
 
     private void initAccessibility() {
@@ -369,13 +401,20 @@
         updateLeftAffordanceIcon();
 
         lp = mWalletButton.getLayoutParams();
-        lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_wallet_width);
-        lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_wallet_width);
+        lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_width);
+        lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_height);
         mWalletButton.setLayoutParams(lp);
 
+        lp = mControlsButton.getLayoutParams();
+        lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_width);
+        lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_height);
+        mControlsButton.setLayoutParams(lp);
+
         mIndicationPadding = getResources().getDimensionPixelSize(
                 R.dimen.keyguard_indication_area_padding);
+
         updateWalletVisibility();
+        updateAffordanceColors();
     }
 
     private void updateRightAffordanceIcon() {
@@ -454,22 +493,38 @@
                 || !mQuickAccessWalletController.isWalletEnabled()
                 || !mHasCard) {
             mWalletButton.setVisibility(GONE);
-            mIndicationArea.setPadding(0, 0, 0, 0);
-        } else {
-            Drawable tileIcon = mQuickAccessWalletController.getWalletClient().getTileIcon();
-            if (tileIcon != null) {
-                mWalletButton.setImageDrawable(tileIcon);
+
+            if (mControlsButton.getVisibility() == GONE) {
+                mIndicationArea.setPadding(0, 0, 0, 0);
             }
-            mWalletButton.getDrawable().setTint(
-                    Utils.getColorAttr(
-                            mContext,
-                            com.android.internal.R.attr.textColorPrimary).getDefaultColor());
+        } else {
             mWalletButton.setVisibility(VISIBLE);
             mWalletButton.setOnClickListener(this::onWalletClick);
             mIndicationArea.setPadding(mIndicationPadding, 0, mIndicationPadding, 0);
         }
     }
 
+    private void updateControlsVisibility() {
+        if (mControlsComponent == null) return;
+
+        boolean hasFavorites = mControlsComponent.getControlsController()
+                .map(c -> c.getFavorites().size() > 0)
+                .orElse(false);
+        if (mDozing
+                || !hasFavorites
+                || !mControlServicesAvailable
+                || mControlsComponent.getVisibility() != AVAILABLE) {
+            mControlsButton.setVisibility(GONE);
+            if (mWalletButton.getVisibility() == GONE) {
+                mIndicationArea.setPadding(0, 0, 0, 0);
+            }
+        } else {
+            mControlsButton.setVisibility(VISIBLE);
+            mControlsButton.setOnClickListener(this::onControlsClick);
+            mIndicationArea.setPadding(mIndicationPadding, 0, mIndicationPadding, 0);
+        }
+    }
+
     public boolean isLeftVoiceAssist() {
         return mLeftIsVoiceAssist;
     }
@@ -751,6 +806,9 @@
         if (mWalletButton.getVisibility() == View.VISIBLE) {
             startFinishDozeAnimationElement(mWalletButton, delay);
         }
+        if (mControlsButton.getVisibility() == View.VISIBLE) {
+            startFinishDozeAnimationElement(mControlsButton, delay);
+        }
         if (mLeftAffordanceView.getVisibility() == View.VISIBLE) {
             startFinishDozeAnimationElement(mLeftAffordanceView, delay);
             delay += DOZE_ANIMATION_STAGGER_DELAY;
@@ -824,6 +882,7 @@
         updateCameraVisibility();
         updateLeftAffordanceIcon();
         updateWalletVisibility();
+        updateControlsVisibility();
 
         if (dozing) {
             mOverlayContainer.setVisibility(INVISIBLE);
@@ -857,6 +916,7 @@
         mRightAffordanceView.setAlpha(alpha);
         mIndicationArea.setAlpha(alpha);
         mWalletButton.setAlpha(alpha);
+        mControlsButton.setAlpha(alpha);
     }
 
     private class DefaultLeftButton implements IntentButton {
@@ -950,6 +1010,32 @@
         mQuickAccessWalletController.queryWalletCards(mCardRetriever);
 
         updateWalletVisibility();
+        updateAffordanceColors();
+    }
+
+    private void updateAffordanceColors() {
+        int iconColor = Utils.getColorAttrDefaultColor(
+                mContext,
+                com.android.internal.R.attr.textColorPrimary);
+        mWalletButton.getDrawable().setTint(iconColor);
+        mControlsButton.getDrawable().setTint(iconColor);
+
+        ColorStateList bgColor = Utils.getColorAttr(
+                mContext,
+                com.android.internal.R.attr.colorSurface);
+        mWalletButton.setBackgroundTintList(bgColor);
+        mControlsButton.setBackgroundTintList(bgColor);
+    }
+
+    /**
+      * Initialize controls via the ControlsComponent
+      */
+    public void initControls(ControlsComponent controlsComponent) {
+        mControlsComponent = controlsComponent;
+        mControlsComponent.getControlsListingController().ifPresent(
+                c -> c.addCallback(mListingCallback));
+
+        updateAffordanceColors();
     }
 
     private void onWalletClick(View v) {
@@ -974,19 +1060,41 @@
         }
     }
 
+    private void onControlsClick(View v) {
+        if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+            return;
+        }
+
+        Intent intent = new Intent(mContext, ControlsActivity.class)
+                .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK)
+                .putExtra(ControlsUiController.EXTRA_ANIMATE, true);
+
+        if (mControlsComponent.getVisibility() == AVAILABLE) {
+            mContext.startActivity(intent);
+        } else {
+            mActivityStarter.postStartActivityDismissingKeyguard(intent, 0 /* delay */);
+        }
+    }
+
     private class WalletCardRetriever implements
             QuickAccessWalletClient.OnWalletCardsRetrievedCallback {
 
         @Override
         public void onWalletCardsRetrieved(@NonNull GetWalletCardsResponse response) {
             mHasCard = !response.getWalletCards().isEmpty();
+            Drawable tileIcon = mQuickAccessWalletController.getWalletClient().getTileIcon();
+            if (tileIcon != null) {
+                mWalletButton.setImageDrawable(tileIcon);
+            }
             updateWalletVisibility();
+            updateAffordanceColors();
         }
 
         @Override
         public void onWalletCardRetrievalError(@NonNull GetWalletCardsError error) {
             mHasCard = false;
             updateWalletVisibility();
+            updateAffordanceColors();
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index ad4213d..f77c052 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -211,7 +211,7 @@
 
     private int getStackScrollerPadding(int clockYPosition) {
         if (mBypassEnabled) {
-            return mUnlockedStackScrollerPadding;
+            return (int) (mUnlockedStackScrollerPadding + mOverStretchAmount);
         } else if (mIsSplitShade) {
             return clockYPosition;
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
index 1789743..f1cde8a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
@@ -62,6 +62,14 @@
     }
 
     /**
+     * Clears message queue.
+     */
+    public void clearMessages() {
+        mMessages.clear();
+        mKeyguardIndicationInfo.clear();
+    }
+
+    /**
      * Changes the text with an animation and makes sure a single indication is shown long enough.
      */
     public void switchIndication(int textResId) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index cfe95e0..6516abd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -165,14 +165,14 @@
      * Called by the Keyguard*ViewController whose view contains the aod icons.
      */
     public void setupAodIcons(@NonNull NotificationIconContainer aodIcons) {
-        boolean changed = mAodIcons != null;
+        boolean changed = mAodIcons != null && aodIcons != mAodIcons;
         if (changed) {
             mAodIcons.setAnimationsEnabled(false);
             mAodIcons.removeAllViews();
         }
         mAodIcons = aodIcons;
         mAodIcons.setOnLockScreen(true);
-        updateAodIconsVisibility(false /* animate */);
+        updateAodIconsVisibility(false /* animate */, changed);
         updateAnimations();
         if (changed) {
             updateAodNotificationIcons();
@@ -587,7 +587,7 @@
 
     @Override
     public void onStateChanged(int newState) {
-        updateAodIconsVisibility(false /* animate */);
+        updateAodIconsVisibility(false /* animate */, false /* force */);
         updateAnimations();
     }
 
@@ -663,18 +663,18 @@
             // since otherwise the unhide animation overlaps
             animate &= fullyHidden;
         }
-        updateAodIconsVisibility(animate);
+        updateAodIconsVisibility(animate, false /* force */);
         updateAodNotificationIcons();
     }
 
     @Override
     public void onPulseExpansionChanged(boolean expandingChanged) {
         if (expandingChanged) {
-            updateAodIconsVisibility(true /* animate */);
+            updateAodIconsVisibility(true /* animate */, false /* force */);
         }
     }
 
-    private void updateAodIconsVisibility(boolean animate) {
+    private void updateAodIconsVisibility(boolean animate, boolean forceUpdate) {
         if (mAodIcons == null) {
             return;
         }
@@ -688,10 +688,11 @@
                 && !mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()) {
             visible = false;
         }
-        if (visible && mWakeUpCoordinator.isPulseExpanding()) {
+        if (visible && mWakeUpCoordinator.isPulseExpanding()
+                && !mBypassController.getBypassEnabled()) {
             visible = false;
         }
-        if (mAodIconsVisible != visible) {
+        if (mAodIconsVisible != visible || forceUpdate) {
             mAodIconsVisible = visible;
             mAodIcons.animate().cancel();
             if (animate) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 3c1892d..12e85be 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -97,6 +97,7 @@
 import com.android.systemui.biometrics.AuthController;
 import com.android.systemui.classifier.Classifier;
 import com.android.systemui.classifier.FalsingCollector;
+import com.android.systemui.controls.dagger.ControlsComponent;
 import com.android.systemui.dagger.qualifiers.DisplayId;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.doze.DozeLog;
@@ -321,6 +322,7 @@
     private final ScrimController mScrimController;
     private final PrivacyDotViewController mPrivacyDotViewController;
     private final QuickAccessWalletController mQuickAccessWalletController;
+    private final ControlsComponent mControlsComponent;
     private final NotificationRemoteInputManager mRemoteInputManager;
 
     // Maximum # notifications to show on Keyguard; extras will be collapsed in an overflow card.
@@ -606,6 +608,11 @@
      * Is the current animator resetting the qs translation.
      */
     private boolean mIsQsTranslationResetAnimator;
+
+    /**
+     * Is the current animator resetting the pulse expansion after a drag down
+     */
+    private boolean mIsPulseExpansionResetAnimator;
     private final Rect mKeyguardStatusAreaClipBounds = new Rect();
     private final Region mQsInterceptRegion = new Region();
 
@@ -717,7 +724,8 @@
             @Main Executor uiExecutor,
             SecureSettings secureSettings,
             UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
-            NotificationRemoteInputManager remoteInputManager) {
+            NotificationRemoteInputManager remoteInputManager,
+            ControlsComponent controlsComponent) {
         super(view, falsingManager, dozeLog, keyguardStateController,
                 (SysuiStatusBarStateController) statusBarStateController, vibratorHelper,
                 statusBarKeyguardViewManager, latencyTracker, flingAnimationUtilsBuilder.get(),
@@ -727,6 +735,7 @@
         mKeyguardMediaController = keyguardMediaController;
         mPrivacyDotViewController = privacyDotViewController;
         mQuickAccessWalletController = quickAccessWalletController;
+        mControlsComponent = controlsComponent;
         mMetricsLogger = metricsLogger;
         mActivityManager = activityManager;
         mConfigurationController = configurationController;
@@ -880,14 +889,7 @@
 
         mWakeUpCoordinator.setStackScroller(mNotificationStackScrollLayoutController);
         mQsFrame = mView.findViewById(R.id.qs_frame);
-        mPulseExpansionHandler.setUp(mNotificationStackScrollLayoutController,
-                amount -> {
-                    float progress = amount / mView.getHeight();
-                    float overstretch = Interpolators.getOvershootInterpolation(progress,
-                            (float) mMaxOverscrollAmountForPulse / mView.getHeight(),
-                            0.2f);
-                    setOverStrechAmount(overstretch);
-                });
+        mPulseExpansionHandler.setUp(mNotificationStackScrollLayoutController);
         mWakeUpCoordinator.addListener(new NotificationWakeUpCoordinator.WakeUpListener() {
             @Override
             public void onFullyHiddenChanged(boolean isFullyHidden) {
@@ -899,7 +901,6 @@
                 if (mKeyguardBypassController.getBypassEnabled()) {
                     // Position the notifications while dragging down while pulsing
                     requestScrollerTopPaddingUpdate(false /* animate */);
-                    updateQSPulseExpansion();
                 }
             }
         });
@@ -937,8 +938,6 @@
                 R.dimen.notification_panel_min_side_margin);
         mIndicationBottomPadding = mResources.getDimensionPixelSize(
                 R.dimen.keyguard_indication_bottom_padding);
-        mQsNotificationTopPadding = mResources.getDimensionPixelSize(
-                R.dimen.qs_notification_padding);
         mShelfHeight = mResources.getDimensionPixelSize(R.dimen.notification_shelf_height);
         mDarkIconSize = mResources.getDimensionPixelSize(R.dimen.status_bar_icon_drawing_size_dark);
         int statusbarHeight = mResources.getDimensionPixelSize(
@@ -1177,6 +1176,7 @@
         mKeyguardBottomArea.setUserSetupComplete(mUserSetupComplete);
         mKeyguardBottomArea.setFalsingManager(mFalsingManager);
         mKeyguardBottomArea.initWallet(mQuickAccessWalletController);
+        mKeyguardBottomArea.initControls(mControlsComponent);
     }
 
     private void updateMaxDisplayedNotifications(boolean recompute) {
@@ -1336,8 +1336,7 @@
      * @return the padding of the stackscroller when unlocked
      */
     private int getUnlockedStackScrollerPadding() {
-        return (mQs != null ? mQs.getHeader().getHeight() : 0) + mQsPeekHeight
-                + mQsNotificationTopPadding;
+        return (mQs != null ? mQs.getHeader().getHeight() : 0) + mQsPeekHeight;
     }
 
     /**
@@ -2234,7 +2233,7 @@
         }
     }
 
-    protected void updateQsExpansion() {
+    private void updateQsExpansion() {
         if (mQs == null) return;
         float qsExpansionFraction = computeQsExpansionFraction();
         mQs.setQsExpansion(qsExpansionFraction, getHeaderTranslation());
@@ -2293,9 +2292,20 @@
                 top = mTransitionToFullShadeQSPosition;
             } else {
                 final float notificationTop = getQSEdgePosition();
-                top = (int) (isOnKeyguard() ? Math.min(qsPanelBottomY, notificationTop)
-                        : notificationTop);
+                if (isOnKeyguard()) {
+                    if (mKeyguardBypassController.getBypassEnabled()) {
+                        // When bypassing on the keyguard, let's use the panel bottom.
+                        // this should go away once we unify the stackY position and don't have
+                        // to do this min anymore below.
+                        top = qsPanelBottomY;
+                    } else {
+                        top = (int) Math.min(qsPanelBottomY, notificationTop);
+                    }
+                } else {
+                    top = (int) notificationTop;
+                }
             }
+            top += mOverStretchAmount;
             bottom = getView().getBottom();
             // notification bounds should take full screen width regardless of insets
             left = 0;
@@ -2348,6 +2358,7 @@
                 public void onAnimationEnd(Animator animation) {
                     mQsClippingAnimation = null;
                     mIsQsTranslationResetAnimator = false;
+                    mIsPulseExpansionResetAnimator = false;
                 }
             });
             mQsClippingAnimation.start();
@@ -2373,9 +2384,17 @@
         }
         if (mQs != null) {
             float qsTranslation = 0;
-            if (mTransitioningToFullShadeProgress > 0.0f || (mQsClippingAnimation != null
-                    && mIsQsTranslationResetAnimator)) {
-                qsTranslation = (top - mQs.getHeader().getHeight()) * QS_PARALLAX_AMOUNT;
+            boolean pulseExpanding = mPulseExpansionHandler.isExpanding();
+            if (mTransitioningToFullShadeProgress > 0.0f || pulseExpanding
+                    || (mQsClippingAnimation != null
+                        && (mIsQsTranslationResetAnimator || mIsPulseExpansionResetAnimator))) {
+                if (pulseExpanding || mIsPulseExpansionResetAnimator) {
+                    // qsTranslation should only be positive during pulse expansion because it's
+                    // already translating in from the top
+                    qsTranslation = Math.max(0, (top - mQs.getHeader().getHeight()) / 2.0f);
+                } else {
+                    qsTranslation = (top - mQs.getHeader().getHeight()) * QS_PARALLAX_AMOUNT;
+                }
             }
             mQsTranslationForFullShadeTransition = qsTranslation;
             updateQsFrameTranslation();
@@ -2442,7 +2461,7 @@
 
     private float calculateNotificationsTopPadding() {
         if (mShouldUseSplitNotificationShade && !mKeyguardShowing) {
-            return mSplitShadeNotificationsTopPadding + mQsNotificationTopPadding;
+            return mSplitShadeNotificationsTopPadding;
         }
         if (mKeyguardShowing && (mQsExpandImmediate
                 || mIsExpanding && mQsExpandedWhenExpandingStarted)) {
@@ -2453,7 +2472,7 @@
             // panel. We need to take the maximum and linearly interpolate with the panel expansion
             // for a nice motion.
             int maxNotificationPadding = getKeyguardNotificationStaticPadding();
-            int maxQsPadding = mQsMaxExpansionHeight + mQsNotificationTopPadding;
+            int maxQsPadding = mQsMaxExpansionHeight;
             int max = mBarState == KEYGUARD ? Math.max(
                     maxNotificationPadding, maxQsPadding) : maxQsPadding;
             return (int) MathUtils.lerp((float) mQsMinExpansionHeight, (float) max,
@@ -2466,10 +2485,10 @@
             // We can only do the smoother transition on Keyguard when we also are not collapsing
             // from a scrolled quick settings.
             return MathUtils.lerp((float) getKeyguardNotificationStaticPadding(),
-                    (float) (mQsMaxExpansionHeight + mQsNotificationTopPadding),
+                    (float) (mQsMaxExpansionHeight),
                     computeQsExpansionFraction());
         } else {
-            return mQsExpansionHeight + mQsNotificationTopPadding;
+            return mQsExpansionHeight;
         }
     }
 
@@ -2504,14 +2523,6 @@
         }
     }
 
-    private void updateQSPulseExpansion() {
-        if (mQs != null) {
-            mQs.setPulseExpanding(
-                    mKeyguardShowing && mKeyguardBypassController.getBypassEnabled()
-                            && mNotificationStackScrollLayoutController.isPulseExpanding());
-        }
-    }
-
     /**
      * Set the amount of pixels we have currently dragged down if we're transitioning to the full
      * shade. 0.0f means we're not transitioning yet.
@@ -2563,6 +2574,15 @@
     }
 
     /**
+     * Notify the panel that the pulse expansion has finished and that we're going to the full
+     * shade
+     */
+    public void onPulseExpansionFinished() {
+        animateNextNotificationBounds(StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE, 0);
+        mIsPulseExpansionResetAnimator = true;
+    }
+
+    /**
      * Set the alpha of the keyguard elements which only show on the lockscreen, but not in
      * shade locked / shade. This is used when dragging down to the full shade.
      */
@@ -2855,10 +2875,6 @@
         }
         int maxQsHeight = mQsMaxExpansionHeight;
 
-        if (mKeyguardShowing) {
-            maxQsHeight += mQsNotificationTopPadding;
-        }
-
         // If an animation is changing the size of the QS panel, take the animated value.
         if (mQsSizeChangeAnimator != null) {
             maxQsHeight = (int) mQsSizeChangeAnimator.getAnimatedValue();
@@ -2923,19 +2939,7 @@
             startHeight = -mQsExpansionHeight * QS_PARALLAX_AMOUNT;
         }
         if (mKeyguardBypassController.getBypassEnabled() && isOnKeyguard()) {
-            if (mNotificationStackScrollLayoutController.isPulseExpanding()) {
-                if (!mPulseExpansionHandler.isExpanding()
-                        && !mPulseExpansionHandler.getLeavingLockscreen()) {
-                    // If we aborted the expansion we need to make sure the header doesn't reappear
-                    // again after the header has animated away
-                    appearAmount = 0;
-                } else {
-                    appearAmount = mNotificationStackScrollLayoutController
-                            .calculateAppearFractionBypass();
-                }
-            } else {
-                appearAmount = 0.0f;
-            }
+            appearAmount = mNotificationStackScrollLayoutController.calculateAppearFractionBypass();
             startHeight = -mQs.getQsMinExpansionHeight();
         }
         float translation = MathUtils.lerp(startHeight, 0, Math.min(1.0f, appearAmount));
@@ -3538,7 +3542,6 @@
             mQs.setPanelView(mHeightListener);
             mQs.setExpandClickListener(mOnClickListener);
             mQs.setHeaderClickable(isQsExpansionEnabled());
-            updateQSPulseExpansion();
             mQs.setOverscrolling(mStackScrollerOverscrolling);
             mQs.setTranslateWhileExpanding(mShouldUseSplitNotificationShade);
 
@@ -3635,8 +3638,6 @@
     public void setAmbientIndicationBottomPadding(int ambientIndicationBottomPadding) {
         if (mAmbientIndicationBottomPadding != ambientIndicationBottomPadding) {
             mAmbientIndicationBottomPadding = ambientIndicationBottomPadding;
-            mLockIconViewController.setAmbientIndicationBottomPadding(
-                    mAmbientIndicationBottomPadding);
             updateMaxDisplayedNotifications(true);
         }
     }
@@ -4301,8 +4302,7 @@
             if (mAccessibilityManager.isEnabled()) {
                 mView.setAccessibilityPaneTitle(determineAccessibilityPaneTitle());
             }
-            mNotificationStackScrollLayoutController.setMaxTopPadding(
-                    mQsMaxExpansionHeight + mQsNotificationTopPadding);
+            mNotificationStackScrollLayoutController.setMaxTopPadding(mQsMaxExpansionHeight);
         }
     }
 
@@ -4420,7 +4420,6 @@
             updateMaxDisplayedNotifications(false);
             // The update needs to happen after the headerSlide in above, otherwise the translation
             // would reset
-            updateQSPulseExpansion();
             maybeAnimateBottomAreaAlpha();
             resetHorizontalPanelPosition();
             updateQsState();
@@ -4455,7 +4454,9 @@
      * Sets the overstretch amount in raw pixels when dragging down.
      */
     public void setOverStrechAmount(float amount) {
-        mOverStretchAmount = amount;
+        float progress = amount / mView.getHeight();
+        float overstretch = Interpolators.getOvershootInterpolation(progress);
+        mOverStretchAmount = overstretch * mMaxOverscrollAmountForPulse;
         positionClockAndNotifications(true /* forceUpdate */);
     }
 
@@ -4509,8 +4510,7 @@
             if (mQs != null) {
                 updateQSMinHeight();
                 mQsMaxExpansionHeight = mQs.getDesiredHeight();
-                mNotificationStackScrollLayoutController.setMaxTopPadding(
-                        mQsMaxExpansionHeight + mQsNotificationTopPadding);
+                mNotificationStackScrollLayoutController.setMaxTopPadding(mQsMaxExpansionHeight);
             }
             positionClockAndNotifications();
             if (mQsExpanded && mQsFullyExpanded) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 31a432e..c300b11 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -23,6 +23,7 @@
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.util.EventLog;
@@ -52,6 +53,7 @@
     private static final boolean DEBUG = StatusBar.DEBUG;
     private static final boolean DEBUG_GESTURES = false;
     private final CommandQueue mCommandQueue;
+    private final StatusBarContentInsetsProvider mContentInsetsProvider;
 
     StatusBar mBar;
 
@@ -85,11 +87,10 @@
     private int mCutoutSideNudge = 0;
     private boolean mHeadsUpVisible;
 
-    private int mRoundedCornerPadding = 0;
-
     public PhoneStatusBarView(Context context, AttributeSet attrs) {
         super(context, attrs);
         mCommandQueue = Dependency.get(CommandQueue.class);
+        mContentInsetsProvider = Dependency.get(StatusBarContentInsetsProvider.class);
     }
 
     public void setBar(StatusBar bar) {
@@ -305,8 +306,6 @@
     public void updateResources() {
         mCutoutSideNudge = getResources().getDimensionPixelSize(
                 R.dimen.display_cutout_margin_consumption);
-        mRoundedCornerPadding = getResources().getDimensionPixelSize(
-                R.dimen.rounded_corner_content_padding);
 
         updateStatusBarHeight();
     }
@@ -341,8 +340,7 @@
     private void updateLayoutForCutout() {
         updateStatusBarHeight();
         updateCutoutLocation(StatusBarWindowView.cornerCutoutMargins(mDisplayCutout, getDisplay()));
-        updateSafeInsets(StatusBarWindowView.statusBarCornerCutoutMargins(mDisplayCutout,
-                getDisplay(), mRotationOrientation, mStatusBarHeight));
+        updateSafeInsets();
     }
 
     private void updateCutoutLocation(Pair<Integer, Integer> cornerCutoutMargins) {
@@ -370,15 +368,18 @@
         lp.height = bounds.height();
     }
 
-    private void updateSafeInsets(Pair<Integer, Integer> cornerCutoutMargins) {
-        // Depending on our rotation, we may have to work around a cutout in the middle of the view,
-        // or letterboxing from the right or left sides.
+    private void updateSafeInsets() {
+        Rect contentRect = mContentInsetsProvider
+                .getStatusBarContentInsetsForRotation(RotationUtils.getExactRotation(getContext()));
 
-        Pair<Integer, Integer> padding =
-                StatusBarWindowView.paddingNeededForCutoutAndRoundedCorner(
-                        mDisplayCutout, cornerCutoutMargins, mRoundedCornerPadding);
+        Point size = new Point();
+        getDisplay().getRealSize(size);
 
-        setPadding(padding.first, getPaddingTop(), padding.second, getPaddingBottom());
+        setPadding(
+                contentRect.left,
+                getPaddingTop(),
+                size.x - contentRect.right,
+                getPaddingBottom());
     }
 
     public void setHeadsUpVisible(boolean headsUpVisible) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 686fbdc..394e4ad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -441,6 +441,7 @@
     private final OngoingCallController mOngoingCallController;
     private final SystemStatusAnimationScheduler mAnimationScheduler;
     private final StatusBarLocationPublisher mStatusBarLocationPublisher;
+    private final StatusBarIconController mStatusBarIconController;
 
     // expanded notifications
     // the sliding/resizing panel within the notification window
@@ -803,6 +804,7 @@
             OngoingCallController ongoingCallController,
             SystemStatusAnimationScheduler animationScheduler,
             StatusBarLocationPublisher locationPublisher,
+            StatusBarIconController statusBarIconController,
             LockscreenShadeTransitionController lockscreenShadeTransitionController,
             FeatureFlags featureFlags,
             KeyguardUnlockAnimationController keyguardUnlockAnimationController,
@@ -889,6 +891,7 @@
         mOngoingCallController = ongoingCallController;
         mAnimationScheduler = animationScheduler;
         mStatusBarLocationPublisher = locationPublisher;
+        mStatusBarIconController = statusBarIconController;
         mFeatureFlags = featureFlags;
         mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
         mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
@@ -1190,7 +1193,14 @@
                                 mAnimationScheduler,
                                 mStatusBarLocationPublisher,
                                 mNotificationIconAreaController,
-                                mFeatureFlags),
+                                mFeatureFlags,
+                                mStatusBarIconController,
+                                mKeyguardStateController,
+                                mNetworkController,
+                                mStatusBarStateController,
+                                this,
+                                mCommandQueue
+                        ),
                         CollapsedStatusBarFragment.TAG)
                 .commit();
 
@@ -2737,6 +2747,11 @@
             mScrimController.dump(fd, pw, args);
         }
 
+        if (mLightRevealScrim != null) {
+            pw.println(
+                    "mLightRevealScrim.getRevealAmount(): " + mLightRevealScrim.getRevealAmount());
+        }
+
         if (mStatusBarKeyguardViewManager != null) {
             mStatusBarKeyguardViewManager.dump(pw);
         }
@@ -3601,6 +3616,7 @@
         mIsKeyguard = false;
         Trace.beginSection("StatusBar#hideKeyguard");
         boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide();
+        int previousState = mStatusBarStateController.getState();
         if (!(mStatusBarStateController.setState(StatusBarState.SHADE, force))) {
             //TODO: StatusBarStateController should probably know about hiding the keyguard and
             // notify listeners.
@@ -3613,7 +3629,7 @@
                 mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
             }
             long delay = mKeyguardStateController.calculateGoingToFullShadeDelay();
-            mLockscreenShadeTransitionController.onHideKeyguard(delay);
+            mLockscreenShadeTransitionController.onHideKeyguard(delay, previousState);
 
             // Disable layout transitions in navbar for this transition because the load is just
             // too heavy for the CPU and GPU on any device.
@@ -3968,7 +3984,7 @@
 
     public void onUnlockHintStarted() {
         mFalsingCollector.onUnlockHintStarted();
-        mKeyguardIndicationController.showTransientIndication(R.string.keyguard_unlock);
+        mKeyguardIndicationController.showActionToUnlock();
     }
 
     public void onHintFinished() {
@@ -4182,7 +4198,7 @@
 
     private void vibrateForCameraGesture() {
         // Make sure to pass -1 for repeat so VibratorService doesn't stop us when going to sleep.
-        mVibrator.vibrate(mCameraLaunchGestureVibrationEffect);
+        mVibrator.vibrate(mCameraLaunchGestureVibrationEffect, VIBRATION_ATTRIBUTES);
     }
 
     private static VibrationEffect getCameraGestureVibrationEffect(Vibrator vibrator,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt
index edcf261..fe1f63a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt
@@ -19,6 +19,7 @@
 import android.content.Context
 import android.content.res.Resources
 import android.graphics.Rect
+import android.util.Log
 import android.util.Pair
 import android.view.DisplayCutout
 import android.view.View.LAYOUT_DIRECTION_RTL
@@ -155,13 +156,30 @@
         val dc = context.display.cutout
         val currentRotation = RotationUtils.getExactRotation(context)
 
+        val isRtl = rotatedResources.configuration.layoutDirection == LAYOUT_DIRECTION_RTL
+        val roundedCornerPadding = rotatedResources
+                .getDimensionPixelSize(R.dimen.rounded_corner_content_padding)
+        val minDotWidth = rotatedResources
+                .getDimensionPixelSize(R.dimen.ongoing_appops_dot_min_padding)
+
+        val minLeft: Int
+        val minRight: Int
+        if (isRtl) {
+            minLeft = max(minDotWidth, roundedCornerPadding)
+            minRight = roundedCornerPadding
+        } else {
+            minLeft = roundedCornerPadding
+            minRight = max(minDotWidth, roundedCornerPadding)
+        }
+
         return calculateInsetsForRotationWithRotatedResources(
                 currentRotation,
                 targetRotation,
                 dc,
                 windowManager.maximumWindowMetrics,
                 rotatedResources.getDimensionPixelSize(R.dimen.status_bar_height),
-                rotatedResources.getDimensionPixelSize(R.dimen.rounded_corner_content_padding))
+                minLeft,
+                minRight)
     }
 
     override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
@@ -212,9 +230,12 @@
  * Calculates the exact left and right positions for the status bar contents for the given
  * rotation
  *
- * @param rot rotation for which to query the margins
- * @param context systemui context
- * @param rotatedResources resources constructed with the proper orientation set
+ * @param currentRotation current device rotation
+ * @param targetRotation rotation for which to calculate the status bar content rect
+ * @param displayCutout [DisplayCutout] for the curren display. possibly null
+ * @param windowMetrics [WindowMetrics] for the current window
+ * @param statusBarHeight height of the status bar for the target rotation
+ * @param roundedCornerPadding from rounded_corner_content_padding
  *
  * @see [RotationUtils#getResourcesForRotation]
  */
@@ -224,7 +245,8 @@
     displayCutout: DisplayCutout?,
     windowMetrics: WindowMetrics,
     statusBarHeight: Int,
-    roundedCornerPadding: Int
+    minLeft: Int,
+    minRight: Int
 ): Rect {
     /*
     TODO: Check if this is ever used for devices with no rounded corners
@@ -242,7 +264,8 @@
             rotZeroBounds.bottom,
             currentBounds.width(),
             currentBounds.height(),
-            roundedCornerPadding,
+            minLeft,
+            minRight,
             targetRotation,
             currentRotation)
 
@@ -256,7 +279,10 @@
  * @param sbHeight appropriate status bar height for this rotation
  * @param width display width calculated for ROTATION_NONE
  * @param height display height calculated for ROTATION_NONE
- * @param roundedCornerPadding rounded_corner_content_padding dimension
+ * @param cWidth display width in our current rotation
+ * @param cHeight display height in our current rotation
+ * @param minLeft the minimum padding to enforce on the left
+ * @param minRight the minimum padding to enforce on the right
  * @param targetRotation the rotation for which to calculate margins
  * @param currentRotation the rotation from which the display cutout was generated
  *
@@ -270,7 +296,8 @@
     height: Int,
     cWidth: Int,
     cHeight: Int,
-    roundedCornerPadding: Int,
+    minLeft: Int,
+    minRight: Int,
     @Rotation targetRotation: Int,
     @Rotation currentRotation: Int
 ): Rect {
@@ -279,9 +306,9 @@
 
     val cutoutRects = dc?.boundingRects
     if (cutoutRects == null || cutoutRects.isEmpty()) {
-        return Rect(roundedCornerPadding,
+        return Rect(minLeft,
                 0,
-                logicalDisplayWidth - roundedCornerPadding,
+                logicalDisplayWidth - minRight,
                 sbHeight)
     }
 
@@ -294,8 +321,8 @@
     // Size of the status bar window for the given rotation relative to our exact rotation
     val sbRect = sbRect(relativeRotation, sbHeight, Pair(cWidth, cHeight))
 
-    var leftMargin = roundedCornerPadding
-    var rightMargin = roundedCornerPadding
+    var leftMargin = minLeft
+    var rightMargin = minRight
     for (cutoutRect in cutoutRects) {
         // There is at most one non-functional area per short edge of the device. So if the status
         // bar doesn't share a short edge with the cutout, we can ignore its insets because there
@@ -306,11 +333,11 @@
 
         if (cutoutRect.touchesLeftEdge(relativeRotation, cWidth, cHeight)) {
 
-            val l = max(roundedCornerPadding, cutoutRect.logicalWidth(relativeRotation))
+            val l = max(minLeft, cutoutRect.logicalWidth(relativeRotation))
             leftMargin = max(l, leftMargin)
         } else if (cutoutRect.touchesRightEdge(relativeRotation, cWidth, cHeight)) {
             val logicalWidth = cutoutRect.logicalWidth(relativeRotation)
-            rightMargin = max(roundedCornerPadding, logicalWidth)
+            rightMargin = max(minRight, logicalWidth)
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index aa58527..47deb1f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -24,12 +24,14 @@
 import android.content.Context;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.SystemClock;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
 import android.service.vr.IVrManager;
 import android.service.vr.IVrStateCallbacks;
 import android.util.Log;
 import android.util.Slog;
+import android.view.View;
 import android.view.accessibility.AccessibilityManager;
 import android.widget.TextView;
 
@@ -394,8 +396,10 @@
     }
 
     @Override
-    public void onExpandClicked(NotificationEntry clickedEntry, boolean nowExpanded) {
+    public void onExpandClicked(NotificationEntry clickedEntry, View clickedView,
+            boolean nowExpanded) {
         mHeadsUpManager.setExpanded(clickedEntry, nowExpanded);
+        mStatusBar.wakeUpIfDozing(SystemClock.uptimeMillis(), clickedView, "NOTIFICATION_CLICK");
         if (nowExpanded) {
             if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
                 mShadeTransitionController.goToLockedShade(clickedEntry.getRow());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
index 64a497d..3292934 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
@@ -245,8 +245,19 @@
      * @param slotName name of the icon slot to remove from the ignored list
      */
     public void removeIgnoredSlot(String slotName) {
-        if (mIgnoredSlots.contains(slotName)) {
-            mIgnoredSlots.remove(slotName);
+        mIgnoredSlots.remove(slotName);
+
+        requestLayout();
+    }
+
+    /**
+     * Remove a list of slots from the list of ignored icon slots.
+     * It will then be shown when set to visible by the {@link StatusBarIconController}.
+     * @param slots name of the icon slots to remove from the ignored list
+     */
+    public void removeIgnoredSlots(List<String> slots) {
+        for (String slot : slots) {
+            mIgnoredSlots.remove(slot);
         }
 
         requestLayout();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
index 4167287..a5b868b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
@@ -199,10 +199,9 @@
 
         // We currently draw both the light reveal scrim, and the AOD UI, in the shade. If it's
         // already expanded and showing notifications/QS, the animation looks really messy. For now,
-        // disable it if the notification panel is expanded.
+        // disable it if the notification panel is not fully collapsed.
         if (!this::statusBar.isInitialized ||
-                statusBar.notificationPanelViewController.isFullyExpanded ||
-                statusBar.notificationPanelViewController.isExpanding) {
+                !statusBar.notificationPanelViewController.isFullyCollapsed) {
             return false
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index 716d1db..b6e8bd8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -89,6 +89,7 @@
 import com.android.systemui.statusbar.phone.ScrimController;
 import com.android.systemui.statusbar.phone.ShadeController;
 import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.phone.StatusBarLocationPublisher;
 import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter;
@@ -216,6 +217,7 @@
             OngoingCallController ongoingCallController,
             SystemStatusAnimationScheduler animationScheduler,
             StatusBarLocationPublisher locationPublisher,
+            StatusBarIconController statusBarIconController,
             LockscreenShadeTransitionController transitionController,
             FeatureFlags featureFlags,
             KeyguardUnlockAnimationController keyguardUnlockAnimationController,
@@ -305,6 +307,7 @@
                 ongoingCallController,
                 animationScheduler,
                 locationPublisher,
+                statusBarIconController,
                 transitionController,
                 featureFlags,
                 keyguardUnlockAnimationController,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
index c2bd87c..3a05ec7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
@@ -30,6 +30,9 @@
     /** Alert controller of a change in between light and dark themes. */
     void notifyThemeChanged();
 
+    /** Query the current configuration's layout direction */
+    boolean isLayoutRtl();
+
     interface ConfigurationListener {
         default void onConfigChanged(Configuration newConfig) {}
         default void onDensityOrFontScaleChanged() {}
@@ -38,5 +41,6 @@
         default void onUiModeChanged() {}
         default void onThemeChanged() {}
         default void onLocaleListChanged() {}
+        default void onLayoutDirectionChanged(boolean isLayoutRtl) {}
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 4e921a0..f10f4fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -131,6 +131,7 @@
     public final DetailAdapter mUserDetailAdapter;
     private final Executor mUiBgExecutor;
     private final boolean mGuestUserAutoCreated;
+    private final AtomicBoolean mGuestIsResetting;
     private final AtomicBoolean mGuestCreationScheduled;
     private FalsingManager mFalsingManager;
 
@@ -160,6 +161,7 @@
         }
         mGuestUserAutoCreated = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_guestUserAutoCreated);
+        mGuestIsResetting = new AtomicBoolean();
         mGuestCreationScheduled = new AtomicBoolean();
         mKeyguardStateController = keyguardStateController;
         mHandler = handler;
@@ -301,7 +303,20 @@
                 boolean createIsRestricted = !addUsersWhenLocked;
 
                 if (guestRecord == null) {
-                    if (canCreateGuest) {
+                    if (mGuestUserAutoCreated) {
+                        // If mGuestIsResetting=true, the switch should be disabled since
+                        // we will just use it as an indicator for "Resetting guest...".
+                        // Otherwise, default to canSwitchUsers.
+                        boolean isSwitchToGuestEnabled =
+                                !mGuestIsResetting.get() && canSwitchUsers;
+                        guestRecord = new UserRecord(null /* info */, null /* picture */,
+                                true /* isGuest */, false /* isCurrent */,
+                                false /* isAddUser */, false /* isRestricted */,
+                                isSwitchToGuestEnabled);
+                        // Don't call checkIfAddUserDisallowedByAdminOnly if
+                        // config_guestUserAutoCreated=true.
+                        records.add(guestRecord);
+                    } else if (canCreateGuest) {
                         guestRecord = new UserRecord(null /* info */, null /* picture */,
                                 true /* isGuest */, false /* isCurrent */,
                                 false /* isAddUser */, createIsRestricted, canSwitchUsers);
@@ -539,6 +554,13 @@
                     mSecondaryUser = userInfo.id;
                 }
                 unpauseRefreshUsers = true;
+                if (mGuestUserAutoCreated) {
+                    // Guest user must be scheduled for creation AFTER switching to the target user.
+                    // This avoids lock contention which will produce UX bugs on the keyguard
+                    // (b/193933686).
+                    // TODO(b/191067027): Move guest user recreation to system_server
+                    guaranteeGuestPresent();
+                }
             } else if (Intent.ACTION_USER_INFO_CHANGED.equals(intent.getAction())) {
                 forcePictureLoadForId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
                         UserHandle.USER_NULL);
@@ -671,8 +693,7 @@
                 mUserManager.removeUser(currentUser.id);
             } else {
                 if (mGuestUserAutoCreated) {
-                    // TODO(b/191067027): Move guest recreation to system_server
-                    scheduleGuestCreation();
+                    mGuestIsResetting.set(true);
                 }
                 switchToUserId(targetUserId);
                 mUserManager.removeUser(currentUser.id);
@@ -690,10 +711,14 @@
 
         mUiBgExecutor.execute(() -> {
             int newGuestId = createGuest();
+            mGuestCreationScheduled.set(false);
+            mGuestIsResetting.set(false);
             if (newGuestId == UserHandle.USER_NULL) {
                 Log.w(TAG, "Could not create new guest while exiting existing guest");
+                // Refresh users so that we still display "Guest" if
+                // config_guestUserAutoCreated=true
+                refreshUsers(UserHandle.USER_NULL);
             }
-            mGuestCreationScheduled.set(false);
         });
 
     }
@@ -796,12 +821,25 @@
                             ? com.android.settingslib.R.string.guest_reset_guest
                             : com.android.settingslib.R.string.guest_exit_guest);
                 } else {
-                    // If config_guestUserAutoCreated, always show guest nickname instead of "Add
-                    // guest" to make it seem as though the device always has a guest ready for use
-                    return context.getString(
-                            item.info == null && !mController.mGuestUserAutoCreated
-                                    ? com.android.settingslib.R.string.guest_new_guest
-                                    : com.android.settingslib.R.string.guest_nickname);
+                    if (item.info != null) {
+                        return context.getString(com.android.settingslib.R.string.guest_nickname);
+                    } else {
+                        if (mController.mGuestUserAutoCreated) {
+                            // If mGuestIsResetting=true, we expect the guest user to be created
+                            // shortly, so display a "Resetting guest..." as an indicator that we
+                            // are busy. Otherwise, if mGuestIsResetting=false, we probably failed
+                            // to create a guest at some point. In this case, always show guest
+                            // nickname instead of "Add guest" to make it seem as though the device
+                            // always has a guest ready for use.
+                            return context.getString(
+                                    mController.mGuestIsResetting.get()
+                                            ? com.android.settingslib.R.string.guest_resetting
+                                            : com.android.settingslib.R.string.guest_nickname);
+                        } else {
+                            return context.getString(
+                                    com.android.settingslib.R.string.guest_new_guest);
+                        }
+                    }
                 }
             } else if (item.isAddUser) {
                 return context.getString(R.string.user_add_user);
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java
index 843630b..c3b4fbe 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java
@@ -197,8 +197,10 @@
                     .collect(Collectors.toList());
 
             OverlayManagerTransaction.Builder transaction = getTransactionBuilder();
+            HashSet<OverlayIdentifier> identifiersPending = new HashSet<>();
             if (pendingCreation != null) {
                 for (FabricatedOverlay overlay : pendingCreation) {
+                    identifiersPending.add(overlay.getIdentifier());
                     transaction.registerFabricatedOverlay(overlay);
                 }
             }
@@ -206,14 +208,14 @@
             for (Pair<String, String> packageToDisable : overlaysToDisable) {
                 OverlayIdentifier overlayInfo = new OverlayIdentifier(packageToDisable.second);
                 setEnabled(transaction, overlayInfo, packageToDisable.first, currentUser,
-                        managedProfiles, false);
+                        managedProfiles, false, identifiersPending.contains(overlayInfo));
             }
 
             for (String category : THEME_CATEGORIES) {
                 if (categoryToPackage.containsKey(category)) {
                     OverlayIdentifier overlayInfo = categoryToPackage.get(category);
                     setEnabled(transaction, overlayInfo, category, currentUser, managedProfiles,
-                            true);
+                            true, identifiersPending.contains(overlayInfo));
                 }
             }
 
@@ -233,7 +235,7 @@
     @AnyThread
     private void setEnabled(OverlayManagerTransaction.Builder transaction,
             OverlayIdentifier identifier, String category, int currentUser,
-            Set<UserHandle> managedProfiles, boolean enabled) {
+            Set<UserHandle> managedProfiles, boolean enabled, boolean pendingCreation) {
         if (DEBUG) {
             Log.d(TAG, "setEnabled: " + identifier.getPackageName() + " category: "
                     + category + ": " + enabled);
@@ -241,7 +243,7 @@
 
         OverlayInfo overlayInfo = mOverlayManager.getOverlayInfo(identifier,
                 UserHandle.of(currentUser));
-        if (overlayInfo == null) {
+        if (overlayInfo == null && !pendingCreation) {
             Log.i(TAG, "Won't enable " + identifier + ", it doesn't exist for user"
                     + currentUser);
             return;
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java b/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java
index 0ecc4e2..4a4f2e9 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java
@@ -31,8 +31,10 @@
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.util.settings.SecureSettings;
+import com.android.systemui.util.time.SystemClock;
 
 import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
 
 import javax.inject.Inject;
 
@@ -52,9 +54,11 @@
     }
 
     private static final String TAG = "QAWController";
+    private static final long RECREATION_TIME_WINDOW = TimeUnit.MINUTES.toMillis(10L);
     private final Context mContext;
     private final Executor mExecutor;
     private final SecureSettings mSecureSettings;
+    private final SystemClock mClock;
 
     private QuickAccessWalletClient mQuickAccessWalletClient;
     private ContentObserver mWalletPreferenceObserver;
@@ -62,17 +66,21 @@
     private int mWalletPreferenceChangeEvents = 0;
     private int mDefaultPaymentAppChangeEvents = 0;
     private boolean mWalletEnabled = false;
+    private long mQawClientCreatedTimeMillis;
 
     @Inject
     public QuickAccessWalletController(
             Context context,
             @Main Executor executor,
             SecureSettings secureSettings,
-            QuickAccessWalletClient quickAccessWalletClient) {
+            QuickAccessWalletClient quickAccessWalletClient,
+            SystemClock clock) {
         mContext = context;
         mExecutor = executor;
         mSecureSettings = secureSettings;
         mQuickAccessWalletClient = quickAccessWalletClient;
+        mClock = clock;
+        mQawClientCreatedTimeMillis = mClock.elapsedRealtime();
     }
 
     /**
@@ -143,6 +151,11 @@
      */
     public void queryWalletCards(
             QuickAccessWalletClient.OnWalletCardsRetrievedCallback cardsRetriever) {
+        if (mClock.elapsedRealtime() - mQawClientCreatedTimeMillis
+                > RECREATION_TIME_WINDOW) {
+            Log.i(TAG, "Re-creating the QAW client to avoid stale.");
+            reCreateWalletClient();
+        }
         if (!mQuickAccessWalletClient.isWalletFeatureAvailable()) {
             Log.d(TAG, "QuickAccessWallet feature is not available.");
             return;
@@ -162,6 +175,7 @@
      */
     public void reCreateWalletClient() {
         mQuickAccessWalletClient = QuickAccessWalletClient.create(mContext);
+        mQawClientCreatedTimeMillis = mClock.elapsedRealtime();
     }
 
     private void setupDefaultPaymentAppObserver(
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index fc0214a..e9061af 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -754,6 +754,28 @@
     }
 
     @Test
+    public void testActiveSubscriptionBecomesInactive() {
+        List<SubscriptionInfo> list = new ArrayList<>();
+        list.add(TEST_SUBSCRIPTION);
+        when(mSubscriptionManager.getCompleteActiveSubscriptionInfoList()).thenReturn(list);
+        mKeyguardUpdateMonitor.mPhoneStateListener.onActiveDataSubscriptionIdChanged(
+                TEST_SUBSCRIPTION.getSubscriptionId());
+        mTestableLooper.processAllMessages();
+        assertThat(mKeyguardUpdateMonitor.mSimDatas.get(TEST_SUBSCRIPTION.getSubscriptionId()))
+                .isNotNull();
+
+        when(mSubscriptionManager.getCompleteActiveSubscriptionInfoList()).thenReturn(null);
+        mKeyguardUpdateMonitor.mPhoneStateListener.onActiveDataSubscriptionIdChanged(
+                SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+        mTestableLooper.processAllMessages();
+
+        assertThat(mKeyguardUpdateMonitor.mSimDatas.get(TEST_SUBSCRIPTION.getSubscriptionId()))
+                .isNull();
+        assertThat(mKeyguardUpdateMonitor.mSimDatas.get(
+                SubscriptionManager.INVALID_SUBSCRIPTION_ID)).isNull();
+    }
+
+    @Test
     public void testIsUserUnlocked() {
         // mUserManager will report the user as unlocked on @Before
         assertThat(mKeyguardUpdateMonitor.isUserUnlocked(KeyguardUpdateMonitor.getCurrentUser()))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
index e94f836..39d5314 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -20,9 +20,7 @@
 import static android.hardware.biometrics.BiometricManager.BIOMETRIC_MULTI_SENSOR_FACE_THEN_FINGERPRINT;
 
 import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertNull;
-import static junit.framework.Assert.assertTrue;
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -50,12 +48,14 @@
 import android.hardware.biometrics.IBiometricSysuiReceiver;
 import android.hardware.biometrics.PromptInfo;
 import android.hardware.biometrics.SensorProperties;
+import android.hardware.display.DisplayManager;
 import android.hardware.face.FaceManager;
 import android.hardware.fingerprint.FingerprintManager;
 import android.hardware.fingerprint.FingerprintSensorProperties;
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
 import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
 import android.os.Bundle;
+import android.os.Handler;
 import android.os.RemoteException;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableContext;
@@ -110,6 +110,10 @@
     private UdfpsController mUdfpsController;
     @Mock
     private SidefpsController mSidefpsController;
+    @Mock
+    private DisplayManager mDisplayManager;
+    @Mock
+    private Handler mHandler;
     @Captor
     ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mAuthenticatorsRegisteredCaptor;
 
@@ -544,13 +548,12 @@
 
     @Test
     public void testSubscribesToOrientationChangesWhenShowingDialog() {
-        assertFalse(mAuthController.mOrientationListener.getEnabled());
-
         showDialog(new int[]{1} /* sensorIds */, false /* credentialAllowed */);
-        assertTrue(mAuthController.mOrientationListener.getEnabled());
+
+        verify(mDisplayManager).registerDisplayListener(any(), eq(mHandler));
 
         mAuthController.hideAuthenticationDialog();
-        assertFalse(mAuthController.mOrientationListener.getEnabled());
+        verify(mDisplayManager).unregisterDisplayListener(any());
     }
 
     // Helpers
@@ -603,7 +606,7 @@
                 Provider<SidefpsController> sidefpsControllerFactory) {
             super(context, commandQueue, activityTaskManager, windowManager,
                     fingerprintManager, faceManager, udfpsControllerFactory,
-                    sidefpsControllerFactory);
+                    sidefpsControllerFactory, mDisplayManager, mHandler);
         }
 
         @Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt
index 7019a4b..977b05c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt
@@ -17,11 +17,13 @@
 package com.android.systemui.biometrics
 
 import android.hardware.biometrics.SensorProperties
+import android.hardware.display.DisplayManager
 import android.hardware.display.DisplayManagerGlobal
 import android.hardware.fingerprint.FingerprintManager
 import android.hardware.fingerprint.FingerprintSensorProperties
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
 import android.hardware.fingerprint.ISidefpsController
+import android.os.Handler
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
 import android.view.Display
@@ -34,14 +36,15 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.time.FakeSystemClock
-import com.google.common.truth.Truth.assertThat
 import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers.eq
 import org.mockito.Mock
 import org.mockito.Mockito.`when`
+import org.mockito.Mockito.any
 import org.mockito.Mockito.verify
 import org.mockito.junit.MockitoJUnit
 
@@ -64,6 +67,10 @@
     lateinit var windowManager: WindowManager
     @Mock
     lateinit var sidefpsView: SidefpsView
+    @Mock
+    lateinit var displayManager: DisplayManager
+    @Mock
+    lateinit var handler: Handler
 
     private val executor = FakeExecutor(FakeSystemClock())
     private lateinit var overlayController: ISidefpsController
@@ -94,7 +101,8 @@
         )
 
         sideFpsController = SidefpsController(
-                mContext, layoutInflater, fingerprintManager, windowManager, executor
+                mContext, layoutInflater, fingerprintManager, windowManager, executor,
+                displayManager, handler
         )
 
         overlayController = ArgumentCaptor.forClass(ISidefpsController::class.java).apply {
@@ -104,14 +112,13 @@
 
     @Test
     fun testSubscribesToOrientationChangesWhenShowingOverlay() {
-        assertThat(sideFpsController.mOrientationListener.enabled).isFalse()
-
         overlayController.show()
         executor.runAllReady()
-        assertThat(sideFpsController.mOrientationListener.enabled).isTrue()
+
+        verify(displayManager).registerDisplayListener(any(), eq(handler))
 
         overlayController.hide()
         executor.runAllReady()
-        assertThat(sideFpsController.mOrientationListener.enabled).isFalse()
+        verify(displayManager).unregisterDisplayListener(any())
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index 36ca664..ca11451 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -17,8 +17,6 @@
 package com.android.systemui.biometrics;
 
 import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -33,11 +31,13 @@
 import android.content.res.TypedArray;
 import android.hardware.biometrics.ComponentInfoInternal;
 import android.hardware.biometrics.SensorProperties;
+import android.hardware.display.DisplayManager;
 import android.hardware.fingerprint.FingerprintManager;
 import android.hardware.fingerprint.FingerprintSensorProperties;
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
 import android.hardware.fingerprint.IUdfpsOverlayController;
 import android.hardware.fingerprint.IUdfpsOverlayControllerCallback;
+import android.os.Handler;
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.Vibrator;
@@ -139,6 +139,10 @@
     private KeyguardStateController mKeyguardStateController;
     @Mock
     private KeyguardBypassController mKeyguardBypassController;
+    @Mock
+    private DisplayManager mDisplayManager;
+    @Mock
+    private Handler mHandler;
 
     private FakeExecutor mFgExecutor;
 
@@ -208,7 +212,9 @@
                 mUdfpsHapticsSimulator,
                 Optional.of(mHbmProvider),
                 mKeyguardStateController,
-                mKeyguardBypassController);
+                mKeyguardBypassController,
+                mDisplayManager,
+                mHandler);
         verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture());
         mOverlayController = mOverlayCaptor.getValue();
         verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture());
@@ -324,18 +330,16 @@
 
     @Test
     public void testSubscribesToOrientationChangesWhenShowingOverlay() throws Exception {
-        assertFalse(mUdfpsController.mOrientationListener.getEnabled());
-
         mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
                 IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD, mUdfpsOverlayControllerCallback);
         mFgExecutor.runAllReady();
 
-        assertTrue(mUdfpsController.mOrientationListener.getEnabled());
+        verify(mDisplayManager).registerDisplayListener(any(), eq(mHandler));
 
         mOverlayController.hideUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
         mFgExecutor.runAllReady();
 
-        assertFalse(mUdfpsController.mOrientationListener.getEnabled());
+        verify(mDisplayManager).unregisterDisplayListener(any());
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarButtonTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarButtonTest.java
index d25b3e3..92652a7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarButtonTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarButtonTest.java
@@ -16,12 +16,12 @@
 
 package com.android.systemui.navigationbar;
 
-import static com.android.systemui.Dependency.EDGE_BACK_GESTURE_HANDLER_PROVIDER;
-
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
 
+import android.content.Context;
 import android.graphics.PixelFormat;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.VirtualDisplay;
@@ -38,7 +38,6 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.SysuiTestableContext;
 import com.android.systemui.assist.AssistManager;
-import com.android.systemui.navigationbar.NavigationBarView;
 import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
 import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -47,6 +46,8 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
 import java.util.function.Predicate;
 
@@ -56,6 +57,10 @@
 @SmallTest
 public class NavigationBarButtonTest extends SysuiTestCase {
 
+    @Mock
+    EdgeBackGestureHandler.Factory mEdgeBackGestureHandlerFactory;
+    @Mock
+    EdgeBackGestureHandler mEdgeBackGestureHandler;
     private static final String TAG = "NavigationBarButtonTest";
     private ImageReader mReader;
     private NavigationBarView mNavBar;
@@ -63,16 +68,20 @@
 
     @Before
     public void setup() {
+        MockitoAnnotations.initMocks(this);
         final Display display = createVirtualDisplay();
         final SysuiTestableContext context =
                 (SysuiTestableContext) mContext.createDisplayContext(display);
 
+        when(mEdgeBackGestureHandlerFactory.create(any(Context.class)))
+                .thenReturn(mEdgeBackGestureHandler);
+
         mDependency.injectMockDependency(AssistManager.class);
         mDependency.injectMockDependency(OverviewProxyService.class);
         mDependency.injectMockDependency(KeyguardStateController.class);
         mDependency.injectMockDependency(NavigationBarController.class);
-        mDependency.injectTestDependency(EDGE_BACK_GESTURE_HANDLER_PROVIDER,
-                () -> mock(EdgeBackGestureHandler.class));
+        mDependency.injectTestDependency(EdgeBackGestureHandler.Factory.class,
+                mEdgeBackGestureHandlerFactory);
         mNavBar = new NavigationBarView(context, null);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
index a76afd4..1968f7f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
@@ -24,7 +24,6 @@
 import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
 
 import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.HOME_BUTTON_LONG_PRESS_DURATION_MS;
-import static com.android.systemui.Dependency.EDGE_BACK_GESTURE_HANDLER_PROVIDER;
 import static com.android.systemui.navigationbar.NavigationBar.NavBarActionEvent.NAVBAR_ASSIST_LONGPRESS;
 
 import static org.junit.Assert.assertEquals;
@@ -119,6 +118,10 @@
     private BroadcastDispatcher mBroadcastDispatcher;
     @Mock
     private UiEventLogger mUiEventLogger;
+    @Mock
+    EdgeBackGestureHandler.Factory mEdgeBackGestureHandlerFactory;
+    @Mock
+    EdgeBackGestureHandler mEdgeBackGestureHandler;
 
     @Rule
     public final LeakCheckedTest.SysuiLeakCheck mLeakCheck = new LeakCheckedTest.SysuiLeakCheck();
@@ -129,6 +132,8 @@
     public void setup() throws Exception {
         MockitoAnnotations.initMocks(this);
 
+        when(mEdgeBackGestureHandlerFactory.create(any(Context.class)))
+                .thenReturn(mEdgeBackGestureHandler);
         mCommandQueue = new CommandQueue(mContext);
         setupSysuiDependency();
         mDependency.injectMockDependency(AssistManager.class);
@@ -136,8 +141,8 @@
         mDependency.injectMockDependency(StatusBarStateController.class);
         mDependency.injectMockDependency(NavigationBarController.class);
         mOverviewProxyService = mDependency.injectMockDependency(OverviewProxyService.class);
-        mDependency.injectTestDependency(EDGE_BACK_GESTURE_HANDLER_PROVIDER,
-                () -> mock(EdgeBackGestureHandler.class));
+        mDependency.injectTestDependency(EdgeBackGestureHandler.Factory.class,
+                mEdgeBackGestureHandlerFactory);
         TestableLooper.get(this).runWithLooper(() -> {
             mNavigationBar = createNavBar(mContext);
             mExternalDisplayNavigationBar = createNavBar(mSysuiTestableContextExternal);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java
index 62871dc..6a2a78b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java
@@ -16,16 +16,16 @@
 
 package com.android.systemui.navigationbar;
 
-import static com.android.systemui.Dependency.EDGE_BACK_GESTURE_HANDLER_PROVIDER;
-
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
+import android.content.Context;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper.RunWithLooper;
 import android.view.IWindowManager;
@@ -44,24 +44,34 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
 @SmallTest
 public class NavigationBarTransitionsTest extends SysuiTestCase {
 
+    @Mock
+    EdgeBackGestureHandler.Factory mEdgeBackGestureHandlerFactory;
+    @Mock
+    EdgeBackGestureHandler mEdgeBackGestureHandler;
     private NavigationBarTransitions mTransitions;
 
     @Before
     public void setup() {
+        MockitoAnnotations.initMocks(this);
+
+        when(mEdgeBackGestureHandlerFactory.create(any(Context.class)))
+                .thenReturn(mEdgeBackGestureHandler);
         mDependency.injectMockDependency(IWindowManager.class);
         mDependency.injectMockDependency(AssistManager.class);
         mDependency.injectMockDependency(OverviewProxyService.class);
         mDependency.injectMockDependency(StatusBarStateController.class);
         mDependency.injectMockDependency(KeyguardStateController.class);
         mDependency.injectMockDependency(NavigationBarController.class);
-        mDependency.injectTestDependency(EDGE_BACK_GESTURE_HANDLER_PROVIDER,
-                () -> mock(EdgeBackGestureHandler.class));
+        mDependency.injectTestDependency(EdgeBackGestureHandler.Factory.class,
+                mEdgeBackGestureHandlerFactory);
         doReturn(mContext)
                 .when(mDependency.injectMockDependency(NavigationModeController.class))
                 .getCurrentUserContext();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NavigationBarContextTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NavigationBarContextTest.java
index 671b1be..7eb7c8e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NavigationBarContextTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NavigationBarContextTest.java
@@ -16,19 +16,20 @@
 
 package com.android.systemui.navigationbar.buttons;
 
-import static com.android.systemui.Dependency.EDGE_BACK_GESTURE_HANDLER_PROVIDER;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
 
+import android.content.Context;
 import android.graphics.drawable.Drawable;
 import android.view.View;
 
@@ -37,15 +38,14 @@
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.assist.AssistManager;
-import com.android.systemui.navigationbar.buttons.ContextualButton;
-import com.android.systemui.navigationbar.buttons.ContextualButtonGroup;
-import com.android.systemui.navigationbar.buttons.KeyButtonDrawable;
 import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
 
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
 /** atest NavigationBarContextTest */
 @SmallTest
@@ -60,6 +60,11 @@
     private static final float DARK_INTENSITY_ERR = 0.0002f;
     private static final int ICON_RES_ID = 1;
 
+    @Mock
+    EdgeBackGestureHandler.Factory mEdgeBackGestureHandlerFactory;
+    @Mock
+    EdgeBackGestureHandler mEdgeBackGestureHandler;
+
     private ContextualButtonGroup mGroup;
     private ContextualButton mBtn0;
     private ContextualButton mBtn1;
@@ -67,9 +72,14 @@
 
     @Before
     public void setup() {
+        MockitoAnnotations.initMocks(this);
+
+        when(mEdgeBackGestureHandlerFactory.create(any(Context.class)))
+                .thenReturn(mEdgeBackGestureHandler);
+
         mDependency.injectMockDependency(AssistManager.class);
-        mDependency.injectTestDependency(EDGE_BACK_GESTURE_HANDLER_PROVIDER,
-                () -> mock(EdgeBackGestureHandler.class));
+        mDependency.injectTestDependency(EdgeBackGestureHandler.Factory.class,
+                mEdgeBackGestureHandlerFactory);
 
         mGroup = new ContextualButtonGroup(GROUP_ID);
         mBtn0 = new ContextualButton(BUTTON_0_ID, mContext, ICON_RES_ID);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NearestTouchFrameTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NearestTouchFrameTest.java
index 2ab2c94..038b42b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NearestTouchFrameTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NearestTouchFrameTest.java
@@ -16,18 +16,16 @@
 
 package com.android.systemui.navigationbar.buttons;
 
-import static com.android.systemui.Dependency.EDGE_BACK_GESTURE_HANDLER_PROVIDER;
-
 import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.testing.AndroidTestingRunner;
@@ -38,12 +36,13 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.navigationbar.buttons.NearestTouchFrame;
 import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
 import java.util.Map;
 
@@ -52,12 +51,21 @@
 @SmallTest
 public class NearestTouchFrameTest extends SysuiTestCase {
 
+    @Mock
+    EdgeBackGestureHandler.Factory mEdgeBackGestureHandlerFactory;
+    @Mock
+    EdgeBackGestureHandler mEdgeBackGestureHandler;
     private NearestTouchFrame mNearestTouchFrame;
 
     @Before
     public void setup() {
-        mDependency.injectTestDependency(EDGE_BACK_GESTURE_HANDLER_PROVIDER,
-                () -> mock(EdgeBackGestureHandler.class));
+        MockitoAnnotations.initMocks(this);
+
+        when(mEdgeBackGestureHandlerFactory.create(any(Context.class)))
+                .thenReturn(mEdgeBackGestureHandler);
+
+        mDependency.injectTestDependency(EdgeBackGestureHandler.Factory.class,
+                mEdgeBackGestureHandlerFactory);
         Configuration c = new Configuration(mContext.getResources().getConfiguration());
         c.smallestScreenWidthDp = 500;
         mNearestTouchFrame = new NearestTouchFrame(mContext, null, c);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index c40977b..c1a7bc5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -55,6 +55,7 @@
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.FeatureFlags;
 import com.android.systemui.statusbar.phone.AutoTileManager;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.policy.Clock;
@@ -92,6 +93,8 @@
     @Mock
     private MediaHost mQQSMediaHost;
     @Mock
+    private KeyguardBypassController mBypassController;
+    @Mock
     private FeatureFlags mFeatureFlags;
     @Mock
     private FalsingManager mFalsingManager;
@@ -184,6 +187,7 @@
                 new QSDetailDisplayer(),
                 mQSMediaHost,
                 mQQSMediaHost,
+                mBypassController,
                 mQsComponentFactory,
                 mFeatureFlags,
                 mFalsingManager);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
index f140eb8..35360bd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
@@ -48,6 +48,7 @@
 import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.Mock
 import org.mockito.Mockito.`when`
+import org.mockito.Mockito.reset
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
 
@@ -98,6 +99,10 @@
 
     private lateinit var controller: QuickStatusBarHeaderController
 
+    private lateinit var cameraSlotName: String
+    private lateinit var microphoneSlotName: String
+    private lateinit var locationSlotName: String
+
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
@@ -108,6 +113,13 @@
         `when`(view.isAttachedToWindow).thenReturn(true)
         `when`(view.context).thenReturn(context)
 
+        cameraSlotName = mContext.resources.getString(
+            com.android.internal.R.string.status_bar_camera)
+        microphoneSlotName = mContext.resources.getString(
+            com.android.internal.R.string.status_bar_microphone)
+        locationSlotName = mContext.resources.getString(
+            com.android.internal.R.string.status_bar_location)
+
         controller = QuickStatusBarHeaderController(
                 view,
                 privacyItemController,
@@ -141,10 +153,9 @@
 
         controller.init()
 
-        val captor = argumentCaptor<List<String>>()
-        verify(iconContainer).setIgnoredSlots(capture(captor))
-
-        assertThat(captor.value).isEmpty()
+        verify(iconContainer).removeIgnoredSlot(cameraSlotName)
+        verify(iconContainer).removeIgnoredSlot(microphoneSlotName)
+        verify(iconContainer).removeIgnoredSlot(locationSlotName)
     }
 
     @Test
@@ -153,15 +164,9 @@
 
         controller.init()
 
-        val captor = argumentCaptor<List<String>>()
-        verify(iconContainer).setIgnoredSlots(capture(captor))
-
-        val cameraString = mContext.resources.getString(
-                com.android.internal.R.string.status_bar_camera)
-        val micString = mContext.resources.getString(
-                com.android.internal.R.string.status_bar_microphone)
-
-        assertThat(captor.value).containsExactly(cameraString, micString)
+        verify(iconContainer).addIgnoredSlot(cameraSlotName)
+        verify(iconContainer).addIgnoredSlot(microphoneSlotName)
+        verify(iconContainer).removeIgnoredSlot(locationSlotName)
     }
 
     @Test
@@ -170,13 +175,9 @@
 
         controller.init()
 
-        val captor = argumentCaptor<List<String>>()
-        verify(iconContainer).setIgnoredSlots(capture(captor))
-
-        val locationString = mContext.resources.getString(
-                com.android.internal.R.string.status_bar_location)
-
-        assertThat(captor.value).containsExactly(locationString)
+        verify(iconContainer).removeIgnoredSlot(cameraSlotName)
+        verify(iconContainer).removeIgnoredSlot(microphoneSlotName)
+        verify(iconContainer).addIgnoredSlot(locationSlotName)
     }
 
     @Test
@@ -185,17 +186,9 @@
 
         controller.init()
 
-        val captor = argumentCaptor<List<String>>()
-        verify(iconContainer).setIgnoredSlots(capture(captor))
-
-        val cameraString = mContext.resources.getString(
-                com.android.internal.R.string.status_bar_camera)
-        val micString = mContext.resources.getString(
-                com.android.internal.R.string.status_bar_microphone)
-        val locationString = mContext.resources.getString(
-                com.android.internal.R.string.status_bar_location)
-
-        assertThat(captor.value).containsExactly(cameraString, micString, locationString)
+        verify(iconContainer).addIgnoredSlot(cameraSlotName)
+        verify(iconContainer).addIgnoredSlot(microphoneSlotName)
+        verify(iconContainer).addIgnoredSlot(locationSlotName)
     }
 
     @Test
@@ -210,6 +203,71 @@
         verify(privacyDialogController).showDialog(any(Context::class.java))
     }
 
+    @Test
+    fun testSingleCarrierListenerAttachedOnInit() {
+        controller.init()
+
+        verify(qsCarrierGroupController).setOnSingleCarrierChangedListener(any())
+    }
+
+    @Test
+    fun testSingleCarrierSetOnViewOnInit_false() {
+        `when`(qsCarrierGroupController.isSingleCarrier).thenReturn(false)
+        controller.init()
+
+        verify(view).setIsSingleCarrier(false)
+    }
+
+    @Test
+    fun testSingleCarrierSetOnViewOnInit_true() {
+        `when`(qsCarrierGroupController.isSingleCarrier).thenReturn(true)
+        controller.init()
+
+        verify(view).setIsSingleCarrier(true)
+    }
+
+    @Test
+    fun testRSSISlot_notCombined() {
+        `when`(featureFlags.isCombinedStatusBarSignalIconsEnabled).thenReturn(false)
+        controller.init()
+
+        val captor = argumentCaptor<List<String>>()
+        verify(view).onAttach(any(), any(), capture(captor))
+
+        assertThat(captor.value).containsExactly(
+            mContext.getString(com.android.internal.R.string.status_bar_mobile)
+        )
+    }
+
+    @Test
+    fun testRSSISlot_combined() {
+        `when`(featureFlags.isCombinedStatusBarSignalIconsEnabled).thenReturn(true)
+        controller.init()
+
+        val captor = argumentCaptor<List<String>>()
+        verify(view).onAttach(any(), any(), capture(captor))
+
+        assertThat(captor.value).containsExactly(
+            mContext.getString(com.android.internal.R.string.status_bar_no_calling),
+            mContext.getString(com.android.internal.R.string.status_bar_call_strength)
+        )
+    }
+
+    @Test
+    fun testSingleCarrierCallback() {
+        controller.init()
+        reset(view)
+
+        val captor = argumentCaptor<QSCarrierGroupController.OnSingleCarrierChangedListener>()
+        verify(qsCarrierGroupController).setOnSingleCarrierChangedListener(capture(captor))
+
+        captor.value.onSingleCarrierChanged(true)
+        verify(view).setIsSingleCarrier(true)
+
+        captor.value.onSingleCarrierChanged(false)
+        verify(view).setIsSingleCarrier(false)
+    }
+
     private fun stubViews() {
         `when`(view.findViewById<View>(anyInt())).thenReturn(mockView)
         `when`(view.findViewById<QSCarrierGroup>(R.id.carrier_group)).thenReturn(qsCarrierGroup)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java
index 9ae6069..72c7ddd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java
@@ -17,15 +17,18 @@
 package com.android.systemui.qs.carrier;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.os.Handler;
-import android.telephony.SubscriptionManager;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.view.View;
@@ -46,9 +49,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
-import org.mockito.stubbing.Answer;
 
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
@@ -70,8 +71,18 @@
     private CarrierTextManager mCarrierTextManager;
     @Mock
     private CarrierConfigTracker mCarrierConfigTracker;
+    @Mock
+    private QSCarrier mQSCarrier1;
+    @Mock
+    private QSCarrier mQSCarrier2;
+    @Mock
+    private QSCarrier mQSCarrier3;
     private TestableLooper mTestableLooper;
     @Mock private FeatureFlags mFeatureFlags;
+    @Mock
+    private QSCarrierGroupController.OnSingleCarrierChangedListener mOnSingleCarrierChangedListener;
+
+    private FakeSlotIndexResolver mSlotIndexResolver;
 
     @Before
     public void setup() throws Exception {
@@ -96,29 +107,31 @@
                 .setListening(any(CarrierTextManager.CarrierTextCallback.class));
 
         when(mQSCarrierGroup.getNoSimTextView()).thenReturn(new TextView(mContext));
-        when(mQSCarrierGroup.getCarrier1View()).thenReturn(mock(QSCarrier.class));
-        when(mQSCarrierGroup.getCarrier2View()).thenReturn(mock(QSCarrier.class));
-        when(mQSCarrierGroup.getCarrier3View()).thenReturn(mock(QSCarrier.class));
+        when(mQSCarrierGroup.getCarrier1View()).thenReturn(mQSCarrier1);
+        when(mQSCarrierGroup.getCarrier2View()).thenReturn(mQSCarrier2);
+        when(mQSCarrierGroup.getCarrier3View()).thenReturn(mQSCarrier3);
         when(mQSCarrierGroup.getCarrierDivider1()).thenReturn(new View(mContext));
         when(mQSCarrierGroup.getCarrierDivider2()).thenReturn(new View(mContext));
 
+        mSlotIndexResolver = new FakeSlotIndexResolver();
+
         mQSCarrierGroupController = new QSCarrierGroupController.Builder(
                 mActivityStarter, handler, TestableLooper.get(this).getLooper(),
                 mNetworkController, mCarrierTextControllerBuilder, mContext, mCarrierConfigTracker,
-                mFeatureFlags)
+                mFeatureFlags, mSlotIndexResolver)
                 .setQSCarrierGroup(mQSCarrierGroup)
                 .build();
 
         mQSCarrierGroupController.setListening(true);
     }
 
+    @Test
+    public void testInitiallyMultiCarrier() {
+        assertFalse(mQSCarrierGroupController.isSingleCarrier());
+    }
+
     @Test // throws no Exception
     public void testUpdateCarrierText_sameLengths() {
-        QSCarrierGroupController spiedCarrierGroupController =
-                Mockito.spy(mQSCarrierGroupController);
-        when(spiedCarrierGroupController.getSlotIndex(anyInt())).thenAnswer(
-                (Answer<Integer>) invocationOnMock -> invocationOnMock.getArgument(0));
-
         // listOfCarriers length 1, subscriptionIds length 1, anySims false
         CarrierTextManager.CarrierTextCallbackInfo
                 c1 = new CarrierTextManager.CarrierTextCallbackInfo(
@@ -160,11 +173,6 @@
 
     @Test // throws no Exception
     public void testUpdateCarrierText_differentLength() {
-        QSCarrierGroupController spiedCarrierGroupController =
-                Mockito.spy(mQSCarrierGroupController);
-        when(spiedCarrierGroupController.getSlotIndex(anyInt())).thenAnswer(
-                (Answer<Integer>) invocationOnMock -> invocationOnMock.getArgument(0));
-
         // listOfCarriers length 2, subscriptionIds length 1, anySims false
         CarrierTextManager.CarrierTextCallbackInfo
                 c1 = new CarrierTextManager.CarrierTextCallbackInfo(
@@ -205,10 +213,7 @@
 
     @Test // throws no Exception
     public void testUpdateCarrierText_invalidSim() {
-        QSCarrierGroupController spiedCarrierGroupController =
-                Mockito.spy(mQSCarrierGroupController);
-        when(spiedCarrierGroupController.getSlotIndex(anyInt())).thenReturn(
-                SubscriptionManager.INVALID_SIM_SLOT_INDEX);
+        mSlotIndexResolver.overrideInvalid = true;
 
         CarrierTextManager.CarrierTextCallbackInfo
                 c4 = new CarrierTextManager.CarrierTextCallbackInfo(
@@ -222,6 +227,8 @@
 
     @Test // throws no Exception
     public void testSetMobileDataIndicators_invalidSim() {
+        mSlotIndexResolver.overrideInvalid = true;
+
         MobileDataIndicators indicators = new MobileDataIndicators(
                 mock(NetworkController.IconState.class),
                 mock(NetworkController.IconState.class),
@@ -242,4 +249,137 @@
         mTestableLooper.processAllMessages();
         assertEquals(View.GONE, mQSCarrierGroup.getNoSimTextView().getVisibility());
     }
+
+    @Test
+    public void testListenerNotCalledOnRegistreation() {
+        mQSCarrierGroupController
+                .setOnSingleCarrierChangedListener(mOnSingleCarrierChangedListener);
+
+        verify(mOnSingleCarrierChangedListener, never()).onSingleCarrierChanged(anyBoolean());
+    }
+
+    @Test
+    public void testSingleCarrier() {
+        // Only one element in the info
+        CarrierTextManager.CarrierTextCallbackInfo
+                info = new CarrierTextManager.CarrierTextCallbackInfo(
+                "",
+                new CharSequence[]{""},
+                true,
+                new int[]{0},
+                false /* airplaneMode */);
+
+        mCallback.updateCarrierInfo(info);
+        mTestableLooper.processAllMessages();
+
+        verify(mQSCarrier1).updateState(any(), eq(true));
+        verify(mQSCarrier2).updateState(any(), eq(true));
+        verify(mQSCarrier3).updateState(any(), eq(true));
+    }
+
+    @Test
+    public void testMultiCarrier() {
+        // More than one element in the info
+        CarrierTextManager.CarrierTextCallbackInfo
+                info = new CarrierTextManager.CarrierTextCallbackInfo(
+                "",
+                new CharSequence[]{"", ""},
+                true,
+                new int[]{0, 1},
+                false /* airplaneMode */);
+
+        mCallback.updateCarrierInfo(info);
+        mTestableLooper.processAllMessages();
+
+        verify(mQSCarrier1).updateState(any(), eq(false));
+        verify(mQSCarrier2).updateState(any(), eq(false));
+        verify(mQSCarrier3).updateState(any(), eq(false));
+    }
+
+    @Test
+    public void testSingleMultiCarrierSwitch() {
+        CarrierTextManager.CarrierTextCallbackInfo
+                singleCarrierInfo = new CarrierTextManager.CarrierTextCallbackInfo(
+                "",
+                new CharSequence[]{""},
+                true,
+                new int[]{0},
+                false /* airplaneMode */);
+
+        CarrierTextManager.CarrierTextCallbackInfo
+                multiCarrierInfo = new CarrierTextManager.CarrierTextCallbackInfo(
+                "",
+                new CharSequence[]{"", ""},
+                true,
+                new int[]{0, 1},
+                false /* airplaneMode */);
+
+        mCallback.updateCarrierInfo(singleCarrierInfo);
+        mTestableLooper.processAllMessages();
+
+        mQSCarrierGroupController
+                .setOnSingleCarrierChangedListener(mOnSingleCarrierChangedListener);
+        reset(mOnSingleCarrierChangedListener);
+
+        mCallback.updateCarrierInfo(multiCarrierInfo);
+        mTestableLooper.processAllMessages();
+        verify(mOnSingleCarrierChangedListener).onSingleCarrierChanged(false);
+
+        mCallback.updateCarrierInfo(singleCarrierInfo);
+        mTestableLooper.processAllMessages();
+        verify(mOnSingleCarrierChangedListener).onSingleCarrierChanged(true);
+    }
+
+    @Test
+    public void testNoCallbackIfSingleCarrierDoesntChange() {
+        CarrierTextManager.CarrierTextCallbackInfo
+                singleCarrierInfo = new CarrierTextManager.CarrierTextCallbackInfo(
+                "",
+                new CharSequence[]{""},
+                true,
+                new int[]{0},
+                false /* airplaneMode */);
+
+        mCallback.updateCarrierInfo(singleCarrierInfo);
+        mTestableLooper.processAllMessages();
+
+        mQSCarrierGroupController
+                .setOnSingleCarrierChangedListener(mOnSingleCarrierChangedListener);
+
+        mCallback.updateCarrierInfo(singleCarrierInfo);
+        mTestableLooper.processAllMessages();
+
+        verify(mOnSingleCarrierChangedListener, never()).onSingleCarrierChanged(anyBoolean());
+    }
+
+    @Test
+    public void testNoCallbackIfMultiCarrierDoesntChange() {
+        CarrierTextManager.CarrierTextCallbackInfo
+                multiCarrierInfo = new CarrierTextManager.CarrierTextCallbackInfo(
+                "",
+                new CharSequence[]{"", ""},
+                true,
+                new int[]{0, 1},
+                false /* airplaneMode */);
+
+        mCallback.updateCarrierInfo(multiCarrierInfo);
+        mTestableLooper.processAllMessages();
+
+        mQSCarrierGroupController
+                .setOnSingleCarrierChangedListener(mOnSingleCarrierChangedListener);
+
+        mCallback.updateCarrierInfo(multiCarrierInfo);
+        mTestableLooper.processAllMessages();
+
+        verify(mOnSingleCarrierChangedListener, never()).onSingleCarrierChanged(anyBoolean());
+    }
+
+    private class FakeSlotIndexResolver implements QSCarrierGroupController.SlotIndexResolver {
+        public boolean overrideInvalid;
+
+        @Override
+        public int getSlotIndex(int subscriptionId) {
+            return overrideInvalid ? -1 : subscriptionId;
+        }
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierTest.java
index 9bee47d..93c75ad8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierTest.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.qs.carrier;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
@@ -23,6 +24,7 @@
 import android.testing.TestableLooper;
 import android.util.FeatureFlagUtils;
 import android.view.LayoutInflater;
+import android.view.View;
 
 import androidx.test.filters.SmallTest;
 
@@ -64,25 +66,64 @@
     public void testUpdateState_first() {
         CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false);
 
-        assertTrue(mQSCarrier.updateState(c));
+        assertTrue(mQSCarrier.updateState(c, false));
     }
 
     @Test
     public void testUpdateState_same() {
         CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false);
 
-        assertTrue(mQSCarrier.updateState(c));
-        assertFalse(mQSCarrier.updateState(c));
+        assertTrue(mQSCarrier.updateState(c, false));
+        assertFalse(mQSCarrier.updateState(c, false));
     }
 
     @Test
     public void testUpdateState_changed() {
         CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false);
 
-        assertTrue(mQSCarrier.updateState(c));
+        assertTrue(mQSCarrier.updateState(c, false));
 
         CellSignalState other = c.changeVisibility(false);
 
-        assertTrue(mQSCarrier.updateState(other));
+        assertTrue(mQSCarrier.updateState(other, false));
+    }
+
+    @Test
+    public void testUpdateState_singleCarrier_first() {
+        CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false);
+
+        assertTrue(mQSCarrier.updateState(c, true));
+    }
+
+    @Test
+    public void testUpdateState_singleCarrier_noShowIcon() {
+        CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false);
+
+        mQSCarrier.updateState(c, true);
+
+        assertEquals(View.GONE, mQSCarrier.getRSSIView().getVisibility());
+    }
+
+    @Test
+    public void testUpdateState_multiCarrier_showIcon() {
+        CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false);
+
+        mQSCarrier.updateState(c, false);
+
+        assertEquals(View.VISIBLE, mQSCarrier.getRSSIView().getVisibility());
+    }
+
+    @Test
+    public void testUpdateState_changeSingleMultiSingle() {
+        CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false);
+
+        mQSCarrier.updateState(c, true);
+        assertEquals(View.GONE, mQSCarrier.getRSSIView().getVisibility());
+
+        mQSCarrier.updateState(c, false);
+        assertEquals(View.VISIBLE, mQSCarrier.getRSSIView().getVisibility());
+
+        mQSCarrier.updateState(c, true);
+        assertEquals(View.GONE, mQSCarrier.getRSSIView().getVisibility());
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
index 17797b7..a70c2be 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
@@ -30,7 +30,6 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
@@ -257,19 +256,6 @@
     }
 
     @Test
-    public void testGetServiceLabelUnsafe_recreateWalletClient() {
-        doAnswer(invocation -> {
-            throw new Exception("Bad service label.");
-        }).when(mQuickAccessWalletClient).getServiceLabel();
-
-        QSTile.State state = new QSTile.State();
-
-        mTile.handleUpdateState(state, null);
-
-        verify(mController).reCreateWalletClient();
-    }
-
-    @Test
     public void testHandleUpdateState_updateLabelAndIcon() {
         QSTile.State state = new QSTile.State();
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index 1ba3831..f5ce673 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -81,6 +81,7 @@
 import com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
 import com.android.systemui.statusbar.phone.LockIcon;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
@@ -146,6 +147,8 @@
     private LockPatternUtils mLockPatternUtils;
     @Mock
     private IActivityManager mIActivityManager;
+    @Mock
+    private KeyguardBypassController mKeyguardBypassController;
     @Captor
     private ArgumentCaptor<DockManager.AlignmentStateListener> mAlignmentListener;
     @Captor
@@ -154,6 +157,9 @@
     private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor;
     @Captor
     private ArgumentCaptor<KeyguardIndication> mKeyguardIndicationCaptor;
+    @Captor
+    private ArgumentCaptor<KeyguardStateController.Callback> mKeyguardStateControllerCallbackCaptor;
+    private KeyguardStateController.Callback mKeyguardStateControllerCallback;
     private StatusBarStateController.StateListener mStatusBarStateListener;
     private BroadcastReceiver mBroadcastReceiver;
     private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
@@ -213,7 +219,8 @@
         mController = new KeyguardIndicationController(mContext, mWakeLockBuilder,
                 mKeyguardStateController, mStatusBarStateController, mKeyguardUpdateMonitor,
                 mDockManager, mBroadcastDispatcher, mDevicePolicyManager, mIBatteryStats,
-                mUserManager, mExecutor, mFalsingManager, mLockPatternUtils, mIActivityManager);
+                mUserManager, mExecutor, mFalsingManager, mLockPatternUtils, mIActivityManager,
+                mKeyguardBypassController);
         mController.init();
         mController.setIndicationArea(mIndicationArea);
         verify(mStatusBarStateController).addCallback(mStatusBarStateListenerCaptor.capture());
@@ -223,6 +230,10 @@
         mController.mRotateTextViewController = mRotateTextViewController;
         mController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
         clearInvocations(mIBatteryStats);
+
+        verify(mKeyguardStateController).addCallback(
+                mKeyguardStateControllerCallbackCaptor.capture());
+        mKeyguardStateControllerCallback = mKeyguardStateControllerCallbackCaptor.getValue();
     }
 
     @Test
@@ -500,6 +511,7 @@
         createController();
         String message = mContext.getString(R.string.keyguard_retry);
         when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(true);
+        when(mKeyguardUpdateMonitor.isFaceEnrolled()).thenReturn(true);
 
         mController.setVisible(true);
         mController.getKeyguardCallback().onBiometricError(FaceManager.FACE_ERROR_TIMEOUT,
@@ -529,7 +541,7 @@
         reset(mKeyguardUpdateMonitor);
         when(mKeyguardUpdateMonitor.isUserUnlocked(anyInt())).thenReturn(true);
         when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(false);
-        mController.onUnlockedChanged();
+        mKeyguardStateControllerCallback.onUnlockedChanged();
         verifyIndicationMessage(INDICATION_TYPE_RESTING, restingIndication);
     }
 
@@ -572,7 +584,7 @@
     @Test
     public void updateMonitor_listener() {
         createController();
-        verify(mKeyguardStateController).addCallback(eq(mController));
+        verify(mKeyguardStateController).addCallback(any());
         verify(mKeyguardUpdateMonitor, times(2)).registerCallback(any());
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
index d6c2797..d23a9ce 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
@@ -196,6 +196,13 @@
     }
 
     @Test
+    fun onDozeAmountChanged_appliesBlur() {
+        statusBarStateListener.onDozeAmountChanged(1f, 1f)
+        notificationShadeDepthController.updateBlurCallback.doFrame(0)
+        verify(blurUtils).applyBlur(any(), eq(maxBlur), eq(false))
+    }
+
+    @Test
     fun setFullShadeTransition_appliesBlur_onlyIfSupported() {
         reset(blurUtils)
         `when`(blurUtils.blurRadiusOfRatio(anyFloat())).then { answer ->
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
index 9640423..bc53074 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
@@ -39,10 +39,14 @@
 import com.android.systemui.SysuiBaseFragmentTest;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.FeatureFlags;
+import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.NetworkController;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mockito;
@@ -54,10 +58,17 @@
 
     private NotificationIconAreaController mMockNotificationAreaController;
     private View mNotificationAreaInner;
-    private StatusBarStateController mStatusBarStateController;
     private OngoingCallController mOngoingCallController;
     private SystemStatusAnimationScheduler mAnimationScheduler;
     private StatusBarLocationPublisher mLocationPublisher;
+    // Set in instantiate()
+    private StatusBarIconController mStatusBarIconController;
+    private NetworkController mNetworkController;
+    private StatusBarStateController mStatusBarStateController;
+    private KeyguardStateController mKeyguardStateController;
+
+    private final StatusBar mStatusBar = mock(StatusBar.class);
+    private final CommandQueue mCommandQueue = mock(CommandQueue.class);
 
     public CollapsedStatusBarFragmentTest() {
         super(CollapsedStatusBarFragment.class);
@@ -65,12 +76,8 @@
 
     @Before
     public void setup() {
-        StatusBar statusBar = mock(StatusBar.class);
-        mDependency.injectTestDependency(StatusBar.class, statusBar);
-        mStatusBarStateController = mDependency
-                .injectMockDependency(StatusBarStateController.class);
         injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
-        when(statusBar.getPanelController()).thenReturn(
+        when(mStatusBar.getPanelController()).thenReturn(
                 mock(NotificationPanelViewController.class));
     }
 
@@ -202,6 +209,7 @@
                 mFragment.getView().findViewById(R.id.ongoing_call_chip).getVisibility());
     }
 
+    @Ignore("b/192618546")
     @Test
     public void testOnDozingChanged() throws Exception {
         mFragments.dispatchResume();
@@ -225,13 +233,23 @@
         mOngoingCallController = mock(OngoingCallController.class);
         mAnimationScheduler = mock(SystemStatusAnimationScheduler.class);
         mLocationPublisher = mock(StatusBarLocationPublisher.class);
+        mStatusBarIconController = mock(StatusBarIconController.class);
+        mNetworkController = mock(NetworkController.class);
+        mStatusBarStateController = mock(StatusBarStateController.class);
+        mKeyguardStateController = mock(KeyguardStateController.class);
         setUpNotificationIconAreaController();
         return new CollapsedStatusBarFragment(
                 mOngoingCallController,
                 mAnimationScheduler,
                 mLocationPublisher,
                 mMockNotificationAreaController,
-                mock(FeatureFlags.class));
+                mock(FeatureFlags.class),
+                mStatusBarIconController,
+                mKeyguardStateController,
+                mNetworkController,
+                mStatusBarStateController,
+                mStatusBar,
+                mCommandQueue);
     }
 
     private void setUpNotificationIconAreaController() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index f8fc224..d7661be 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -85,6 +85,7 @@
 import com.android.systemui.biometrics.AuthController;
 import com.android.systemui.classifier.FalsingCollectorFake;
 import com.android.systemui.classifier.FalsingManagerFake;
+import com.android.systemui.controls.dagger.ControlsComponent;
 import com.android.systemui.doze.DozeLog;
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.fragments.FragmentService;
@@ -298,6 +299,8 @@
     private RemoteInputController mRemoteInputController;
     @Mock
     private RecordingController mRecordingController;
+    @Mock
+    private ControlsComponent mControlsComponent;
 
     private SysuiStatusBarStateController mStatusBarStateController;
     private NotificationPanelViewController mNotificationPanelViewController;
@@ -369,16 +372,17 @@
                         mKeyguardBypassController,
                         mDozeParameters,
                         mUnlockedScreenOffAnimationController);
+        mConfigurationController = new ConfigurationControllerImpl(mContext);
         PulseExpansionHandler expansionHandler = new PulseExpansionHandler(
                 mContext,
                 coordinator,
                 mKeyguardBypassController, mHeadsUpManager,
                 mock(NotificationRoundnessManager.class),
+                mConfigurationController,
                 mStatusBarStateController,
                 mFalsingManager,
                 mLockscreenShadeTransitionController,
                 new FalsingCollectorFake());
-        mConfigurationController = new ConfigurationControllerImpl(mContext);
         when(mKeyguardStatusViewComponentFactory.build(any()))
                 .thenReturn(mKeyguardStatusViewComponent);
         when(mKeyguardStatusViewComponent.getKeyguardClockSwitchController())
@@ -440,7 +444,8 @@
                 new FakeExecutor(new FakeSystemClock()),
                 mSecureSettings,
                 mUnlockedScreenOffAnimationController,
-                mNotificationRemoteInputManager);
+                mNotificationRemoteInputManager,
+                mControlsComponent);
         mNotificationPanelViewController.initDependencies(
                 mStatusBar,
                 mNotificationShelfController);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt
index 4796cd7..10eb71f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt
@@ -47,7 +47,8 @@
     @Test
     fun testGetBoundingRectForPrivacyChipForRotation_noCutout() {
         val screenBounds = Rect(0, 0, 1080, 2160)
-        val roundedCornerPadding = 20
+        val minLeftPadding = 20
+        val minRightPadding = 20
         val sbHeightPortrait = 100
         val sbHeightLandscape = 60
         val currentRotation = ROTATION_NONE
@@ -64,7 +65,8 @@
                 null,
                 windowMetrics,
                 sbHeightPortrait,
-                roundedCornerPadding)
+                minLeftPadding,
+                minRightPadding)
 
         var chipBounds = getPrivacyChipBoundingRectForInsets(bounds, dotWidth, chipWidth, isRtl)
         /* 1080 - 20 (rounded corner) - 30 (chip),
@@ -92,7 +94,8 @@
                 dc,
                 windowMetrics,
                 sbHeightLandscape,
-                roundedCornerPadding)
+                minLeftPadding,
+                minRightPadding)
 
         chipBounds = getPrivacyChipBoundingRectForInsets(bounds, dotWidth, chipWidth, isRtl)
         /* 2160 - 20 (rounded corner) - 30 (chip),
@@ -118,7 +121,8 @@
         // GIVEN a device in portrait mode with width < height and a display cutout in the top-left
         val screenBounds = Rect(0, 0, 1080, 2160)
         val dcBounds = Rect(0, 0, 100, 100)
-        val roundedCornerPadding = 20
+        val minLeftPadding = 20
+        val minRightPadding = 20
         val sbHeightPortrait = 100
         val sbHeightLandscape = 60
         val currentRotation = ROTATION_NONE
@@ -131,7 +135,7 @@
         var targetRotation = ROTATION_NONE
         var expectedBounds = Rect(dcBounds.right,
                 0,
-                screenBounds.right - roundedCornerPadding,
+                screenBounds.right - minRightPadding,
                 sbHeightPortrait)
 
         var bounds = calculateInsetsForRotationWithRotatedResources(
@@ -140,14 +144,15 @@
                 dc,
                 windowMetrics,
                 sbHeightPortrait,
-                roundedCornerPadding)
+                minLeftPadding,
+                minRightPadding)
 
         assertRects(expectedBounds, bounds, currentRotation, targetRotation)
 
         targetRotation = ROTATION_LANDSCAPE
         expectedBounds = Rect(dcBounds.height(),
                 0,
-                screenBounds.height() - roundedCornerPadding,
+                screenBounds.height() - minRightPadding,
                 sbHeightLandscape)
 
         bounds = calculateInsetsForRotationWithRotatedResources(
@@ -156,16 +161,17 @@
                 dc,
                 windowMetrics,
                 sbHeightLandscape,
-                roundedCornerPadding)
+                minLeftPadding,
+                minRightPadding)
 
         assertRects(expectedBounds, bounds, currentRotation, targetRotation)
 
         // THEN the side that does NOT share a short side with the display cutout ignores the
         // display cutout bounds
         targetRotation = ROTATION_UPSIDE_DOWN
-        expectedBounds = Rect(roundedCornerPadding,
+        expectedBounds = Rect(minLeftPadding,
                 0,
-                screenBounds.width() - roundedCornerPadding,
+                screenBounds.width() - minRightPadding,
                 sbHeightPortrait)
 
         bounds = calculateInsetsForRotationWithRotatedResources(
@@ -174,13 +180,14 @@
                 dc,
                 windowMetrics,
                 sbHeightPortrait,
-                roundedCornerPadding)
+                minLeftPadding,
+                minRightPadding)
 
         assertRects(expectedBounds, bounds, currentRotation, targetRotation)
 
         // Phone in portrait, seascape (rot_270) bounds
         targetRotation = ROTATION_SEASCAPE
-        expectedBounds = Rect(roundedCornerPadding,
+        expectedBounds = Rect(minLeftPadding,
                 0,
                 screenBounds.height() - dcBounds.height(),
                 sbHeightLandscape)
@@ -191,7 +198,8 @@
                 dc,
                 windowMetrics,
                 sbHeightLandscape,
-                roundedCornerPadding)
+                minLeftPadding,
+                minRightPadding)
 
         assertRects(expectedBounds, bounds, currentRotation, targetRotation)
     }
@@ -205,7 +213,8 @@
         val screenBounds = Rect(0, 0, 1080, 2160)
         // cutout centered at the top
         val dcBounds = Rect(490, 0, 590, 100)
-        val roundedCornerPadding = 20
+        val minLeftPadding = 20
+        val minRightPadding = 20
         val sbHeightPortrait = 100
         val sbHeightLandscape = 60
         val currentRotation = ROTATION_NONE
@@ -216,9 +225,9 @@
         // THEN only the landscape/seascape rotations should avoid the cutout area because of the
         // potential letterboxing
         var targetRotation = ROTATION_NONE
-        var expectedBounds = Rect(roundedCornerPadding,
+        var expectedBounds = Rect(minLeftPadding,
                 0,
-                screenBounds.right - roundedCornerPadding,
+                screenBounds.right - minRightPadding,
                 sbHeightPortrait)
 
         var bounds = calculateInsetsForRotationWithRotatedResources(
@@ -227,14 +236,15 @@
                 dc,
                 windowMetrics,
                 sbHeightPortrait,
-                roundedCornerPadding)
+                minLeftPadding,
+                minRightPadding)
 
         assertRects(expectedBounds, bounds, currentRotation, targetRotation)
 
         targetRotation = ROTATION_LANDSCAPE
         expectedBounds = Rect(dcBounds.height(),
                 0,
-                screenBounds.height() - roundedCornerPadding,
+                screenBounds.height() - minRightPadding,
                 sbHeightLandscape)
 
         bounds = calculateInsetsForRotationWithRotatedResources(
@@ -243,14 +253,15 @@
                 dc,
                 windowMetrics,
                 sbHeightLandscape,
-                roundedCornerPadding)
+                minLeftPadding,
+                minRightPadding)
 
         assertRects(expectedBounds, bounds, currentRotation, targetRotation)
 
         targetRotation = ROTATION_UPSIDE_DOWN
-        expectedBounds = Rect(roundedCornerPadding,
+        expectedBounds = Rect(minLeftPadding,
                 0,
-                screenBounds.right - roundedCornerPadding,
+                screenBounds.right - minRightPadding,
                 sbHeightPortrait)
 
         bounds = calculateInsetsForRotationWithRotatedResources(
@@ -259,12 +270,13 @@
                 dc,
                 windowMetrics,
                 sbHeightPortrait,
-                roundedCornerPadding)
+                minLeftPadding,
+                minRightPadding)
 
         assertRects(expectedBounds, bounds, currentRotation, targetRotation)
 
         targetRotation = ROTATION_SEASCAPE
-        expectedBounds = Rect(roundedCornerPadding,
+        expectedBounds = Rect(minLeftPadding,
                 0,
                 screenBounds.height() - dcBounds.height(),
                 sbHeightLandscape)
@@ -275,7 +287,8 @@
                 dc,
                 windowMetrics,
                 sbHeightLandscape,
-                roundedCornerPadding)
+                minLeftPadding,
+                minRightPadding)
 
         assertRects(expectedBounds, bounds, currentRotation, targetRotation)
     }
@@ -285,7 +298,8 @@
         // GIVEN device in portrait mode, where width < height and no cutout
         val currentRotation = ROTATION_NONE
         val screenBounds = Rect(0, 0, 1080, 2160)
-        val roundedCornerPadding = 20
+        val minLeftPadding = 20
+        val minRightPadding = 20
         val sbHeightPortrait = 100
         val sbHeightLandscape = 60
 
@@ -293,9 +307,9 @@
 
         // THEN content insets should only use rounded corner padding
         var targetRotation = ROTATION_NONE
-        var expectedBounds = Rect(roundedCornerPadding,
+        var expectedBounds = Rect(minLeftPadding,
                 0,
-                screenBounds.right - roundedCornerPadding,
+                screenBounds.right - minRightPadding,
                 sbHeightPortrait)
 
         var bounds = calculateInsetsForRotationWithRotatedResources(
@@ -304,13 +318,14 @@
                 null, /* no cutout */
                 windowMetrics,
                 sbHeightPortrait,
-                roundedCornerPadding)
+                minLeftPadding,
+                minRightPadding)
         assertRects(expectedBounds, bounds, currentRotation, targetRotation)
 
         targetRotation = ROTATION_LANDSCAPE
-        expectedBounds = Rect(roundedCornerPadding,
+        expectedBounds = Rect(minLeftPadding,
                 0,
-                screenBounds.height() - roundedCornerPadding,
+                screenBounds.height() - minRightPadding,
                 sbHeightLandscape)
 
         bounds = calculateInsetsForRotationWithRotatedResources(
@@ -319,13 +334,14 @@
                 null, /* no cutout */
                 windowMetrics,
                 sbHeightLandscape,
-                roundedCornerPadding)
+                minLeftPadding,
+                minRightPadding)
         assertRects(expectedBounds, bounds, currentRotation, targetRotation)
 
         targetRotation = ROTATION_UPSIDE_DOWN
-        expectedBounds = Rect(roundedCornerPadding,
+        expectedBounds = Rect(minLeftPadding,
                 0,
-                screenBounds.width() - roundedCornerPadding,
+                screenBounds.width() - minRightPadding,
                 sbHeightPortrait)
 
         bounds = calculateInsetsForRotationWithRotatedResources(
@@ -334,13 +350,14 @@
                 null, /* no cutout */
                 windowMetrics,
                 sbHeightPortrait,
-                roundedCornerPadding)
+                minLeftPadding,
+                minRightPadding)
         assertRects(expectedBounds, bounds, currentRotation, targetRotation)
 
         targetRotation = ROTATION_LANDSCAPE
-        expectedBounds = Rect(roundedCornerPadding,
+        expectedBounds = Rect(minLeftPadding,
                 0,
-                screenBounds.height() - roundedCornerPadding,
+                screenBounds.height() - minRightPadding,
                 sbHeightLandscape)
 
         bounds = calculateInsetsForRotationWithRotatedResources(
@@ -349,7 +366,41 @@
                 null, /* no cutout */
                 windowMetrics,
                 sbHeightLandscape,
-                roundedCornerPadding)
+                minLeftPadding,
+                minRightPadding)
+        assertRects(expectedBounds, bounds, currentRotation, targetRotation)
+    }
+
+    @Test
+    fun testMinLeftRight_accountsForDisplayCutout() {
+        // GIVEN a device in portrait mode with width < height and a display cutout in the top-left
+        val screenBounds = Rect(0, 0, 1080, 2160)
+        val dcBounds = Rect(0, 0, 100, 100)
+        val minLeftPadding = 80
+        val minRightPadding = 150
+        val sbHeightPortrait = 100
+        val sbHeightLandscape = 60
+        val currentRotation = ROTATION_NONE
+
+        `when`(windowMetrics.bounds).thenReturn(screenBounds)
+        `when`(dc.boundingRects).thenReturn(listOf(dcBounds))
+
+        // THEN left should be set to the display cutout width, and right should use the minRight
+        var targetRotation = ROTATION_NONE
+        var expectedBounds = Rect(dcBounds.right,
+                0,
+                screenBounds.right - minRightPadding,
+                sbHeightPortrait)
+
+        var bounds = calculateInsetsForRotationWithRotatedResources(
+                currentRotation,
+                targetRotation,
+                dc,
+                windowMetrics,
+                sbHeightPortrait,
+                minLeftPadding,
+                minRightPadding)
+
         assertRects(expectedBounds, bounds, currentRotation, targetRotation)
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index f126ed0..2c2833a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -269,6 +269,7 @@
     @Mock private OngoingCallController mOngoingCallController;
     @Mock private SystemStatusAnimationScheduler mAnimationScheduler;
     @Mock private StatusBarLocationPublisher mLocationPublisher;
+    @Mock private StatusBarIconController mIconController;
     @Mock private LockscreenShadeTransitionController mLockscreenTransitionController;
     @Mock private FeatureFlags mFeatureFlags;
     @Mock private IWallpaperManager mWallpaperManager;
@@ -442,6 +443,7 @@
                 mOngoingCallController,
                 mAnimationScheduler,
                 mLocationPublisher,
+                mIconController,
                 mLockscreenTransitionController,
                 mFeatureFlags,
                 mKeyguardUnlockAnimationController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeConfigurationController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeConfigurationController.java
index f5ccac3..516eb6e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeConfigurationController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeConfigurationController.java
@@ -33,4 +33,9 @@
     @Override
     public void notifyThemeChanged() {
     }
+
+    @Override
+    public boolean isLayoutRtl() {
+        return false;
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/QuickAccessWalletControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/QuickAccessWalletControllerTest.java
index ce0098e..72a329a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/QuickAccessWalletControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/QuickAccessWalletControllerTest.java
@@ -37,6 +37,7 @@
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.util.settings.SecureSettings;
+import com.android.systemui.util.time.FakeSystemClock;
 
 import com.google.common.util.concurrent.MoreExecutors;
 
@@ -62,6 +63,7 @@
     @Captor
     private ArgumentCaptor<GetWalletCardsRequest> mRequestCaptor;
 
+    private FakeSystemClock mClock = new FakeSystemClock();
     private QuickAccessWalletController mController;
 
     @Before
@@ -70,12 +72,14 @@
         when(mQuickAccessWalletClient.isWalletServiceAvailable()).thenReturn(true);
         when(mQuickAccessWalletClient.isWalletFeatureAvailable()).thenReturn(true);
         when(mQuickAccessWalletClient.isWalletFeatureAvailableWhenDeviceLocked()).thenReturn(true);
+        mClock.setElapsedRealtime(100L);
 
         mController = new QuickAccessWalletController(
                 mContext,
                 MoreExecutors.directExecutor(),
                 mSecureSettings,
-                mQuickAccessWalletClient);
+                mQuickAccessWalletClient,
+                mClock);
     }
 
     @Test
@@ -125,6 +129,23 @@
     }
 
     @Test
+    public void queryWalletCards_avoidStale_recreateClient() {
+        // advance current time by 100 seconds, should not recreate the client.
+        mClock.setElapsedRealtime(100100L);
+
+        mController.queryWalletCards(mCardsRetriever);
+
+        assertSame(mQuickAccessWalletClient, mController.getWalletClient());
+
+        // advance current time by another 501 seconds, should recreate the client.
+        mClock.setElapsedRealtime(601100L);
+
+        mController.queryWalletCards(mCardsRetriever);
+
+        assertNotSame(mQuickAccessWalletClient, mController.getWalletClient());
+    }
+
+    @Test
     public void queryWalletCards_walletEnabled_queryCards() {
         mController.queryWalletCards(mCardsRetriever);
 
diff --git a/packages/VpnDialogs/res/values-gu/strings.xml b/packages/VpnDialogs/res/values-gu/strings.xml
index b5a8831..5ffdcb1 100644
--- a/packages/VpnDialogs/res/values-gu/strings.xml
+++ b/packages/VpnDialogs/res/values-gu/strings.xml
@@ -29,7 +29,7 @@
     <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g>ને હંમેશાં જોડાયેલ રહેવા માટે સેટ કરેલ છે, પરંતુ તે હાલમાં કનેક્ટ કરી શકાતું નથી. તમારો ફોન જ્યાં સુધી <xliff:g id="VPN_APP_1">%1$s</xliff:g> સાથે ફરીથી કનેક્ટ ન થાય ત્યાં સુધી તે સાર્વજનિક નેટવર્કનો ઉપયોગ કરશે."</string>
     <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g>ને હંમેશાં જોડાયેલ રહેવા માટે સેટ કરેલ છે, પરંતુ તે હાલમાં કનેક્ટ કરી શકાતું નથી. VPN ફરીથી કનેક્ટ ન થઈ શકે ત્યાં સુધી તમારી પાસે કોઈ કનેક્શન હશે નહીં."</string>
     <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string>
-    <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"VPN સેટિંગ્સ બદલો"</string>
+    <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"VPN સેટિંગ બદલો"</string>
     <string name="configure" msgid="4905518375574791375">"ગોઠવો"</string>
     <string name="disconnect" msgid="971412338304200056">"ડિસ્કનેક્ટ કરો"</string>
     <string name="open_app" msgid="3717639178595958667">"ઍપ ખોલો"</string>
diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java
index f440ee8..c9608a5 100644
--- a/services/core/java/com/android/server/NsdService.java
+++ b/services/core/java/com/android/server/NsdService.java
@@ -82,6 +82,8 @@
 
     private static final int INVALID_ID = 0;
     private int mUniqueId = 1;
+    // The count of the connected legacy clients.
+    private int mLegacyClientCount = 0;
 
     private class NsdStateMachine extends StateMachine {
 
@@ -107,7 +109,9 @@
             sendMessageDelayed(NsdManager.DAEMON_CLEANUP, mCleanupDelayMs);
         }
         private void maybeScheduleStop() {
-            if (!isAnyRequestActive()) {
+            // The native daemon should stay alive and can't be cleanup
+            // if any legacy client connected.
+            if (!isAnyRequestActive() && mLegacyClientCount == 0) {
                 scheduleStop();
             }
         }
@@ -175,11 +179,11 @@
                         if (cInfo != null) {
                             cInfo.expungeAllRequests();
                             mClients.remove(msg.replyTo);
+                            if (cInfo.isLegacy()) {
+                                mLegacyClientCount -= 1;
+                            }
                         }
-                        //Last client
-                        if (mClients.size() == 0) {
-                            scheduleStop();
-                        }
+                        maybeScheduleStop();
                         break;
                     case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION:
                         AsyncChannel ac = new AsyncChannel();
@@ -208,6 +212,17 @@
                     case NsdManager.DAEMON_CLEANUP:
                         mDaemon.maybeStop();
                         break;
+                    // This event should be only sent by the legacy (target SDK < S) clients.
+                    // Mark the sending client as legacy.
+                    case NsdManager.DAEMON_STARTUP:
+                        cInfo = mClients.get(msg.replyTo);
+                        if (cInfo != null) {
+                            cancelStop();
+                            cInfo.setLegacy();
+                            mLegacyClientCount += 1;
+                            maybeStartDaemon();
+                        }
+                        break;
                     case NsdManager.NATIVE_DAEMON_EVENT:
                     default:
                         Slog.e(TAG, "Unhandled " + msg);
@@ -863,6 +878,9 @@
         /* A map from client id to the type of the request we had received */
         private final SparseIntArray mClientRequests = new SparseIntArray();
 
+        // The target SDK of this client < Build.VERSION_CODES.S
+        private boolean mIsLegacy = false;
+
         private ClientInfo(AsyncChannel c, Messenger m) {
             mChannel = c;
             mMessenger = m;
@@ -875,6 +893,7 @@
             sb.append("mChannel ").append(mChannel).append("\n");
             sb.append("mMessenger ").append(mMessenger).append("\n");
             sb.append("mResolvedService ").append(mResolvedService).append("\n");
+            sb.append("mIsLegacy ").append(mIsLegacy).append("\n");
             for(int i = 0; i< mClientIds.size(); i++) {
                 int clientID = mClientIds.keyAt(i);
                 sb.append("clientId ").append(clientID).
@@ -884,6 +903,14 @@
             return sb.toString();
         }
 
+        private boolean isLegacy() {
+            return mIsLegacy;
+        }
+
+        private void setLegacy() {
+            mIsLegacy = true;
+        }
+
         // Remove any pending requests from the global map when we get rid of a client,
         // and send cancellations to the daemon.
         private void expungeAllRequests() {
diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java
index e336b6b..16645df 100644
--- a/services/core/java/com/android/server/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/PersistentDataBlockService.java
@@ -375,15 +375,38 @@
 
         try {
             FileChannel channel = getBlockOutputChannel();
+            // Format the data selectively.
+            //
+            // 1. write header, set length = 0
             int header_size = DIGEST_SIZE_BYTES + HEADER_SIZE;
             ByteBuffer buf = ByteBuffer.allocate(header_size);
             buf.put(new byte[DIGEST_SIZE_BYTES]);
             buf.putInt(PARTITION_TYPE_MARKER);
             buf.putInt(0);
+            buf.flip();
             channel.write(buf);
-            // corrupt the payload explicitly
+            channel.force(true);
+
+            // 2. corrupt the legacy FRP data explicitly
             int payload_size = (int) getBlockDeviceSize() - header_size;
-            buf = ByteBuffer.allocate(payload_size);
+            buf = ByteBuffer.allocate(payload_size
+                          - TEST_MODE_RESERVED_SIZE - FRP_CREDENTIAL_RESERVED_SIZE - 1);
+            channel.write(buf);
+            channel.force(true);
+
+            // 3. skip the test mode data and leave it unformat
+            //    This is for a feature that enables testing.
+            channel.position(channel.position() + TEST_MODE_RESERVED_SIZE);
+
+            // 4. wipe the FRP_CREDENTIAL explicitly
+            buf = ByteBuffer.allocate(FRP_CREDENTIAL_RESERVED_SIZE);
+            channel.write(buf);
+            channel.force(true);
+
+            // 5. set unlock = 0 because it's a formatPartitionLocked
+            buf = ByteBuffer.allocate(FRP_CREDENTIAL_RESERVED_SIZE);
+            buf.put((byte)0);
+            buf.flip();
             channel.write(buf);
             channel.force(true);
         } catch (IOException e) {
diff --git a/services/core/java/com/android/server/SensorPrivacyService.java b/services/core/java/com/android/server/SensorPrivacyService.java
index ac43fbd..019e4ea 100644
--- a/services/core/java/com/android/server/SensorPrivacyService.java
+++ b/services/core/java/com/android/server/SensorPrivacyService.java
@@ -232,14 +232,14 @@
     public void onUserStarting(TargetUser user) {
         if (mCurrentUser == -1) {
             mCurrentUser = user.getUserIdentifier();
-            setGlobalRestriction();
+            mSensorPrivacyServiceImpl.userSwitching(-1, user.getUserIdentifier());
         }
     }
 
     @Override
     public void onUserSwitching(TargetUser from, TargetUser to) {
         mCurrentUser = to.getUserIdentifier();
-        setGlobalRestriction();
+        mSensorPrivacyServiceImpl.userSwitching(from.getUserIdentifier(), to.getUserIdentifier());
     }
 
     class SensorPrivacyServiceImpl extends ISensorPrivacyManager.Stub implements
@@ -897,18 +897,22 @@
         public boolean isIndividualSensorPrivacyEnabled(@UserIdInt int userId, int sensor) {
             enforceObserveSensorPrivacyPermission();
             synchronized (mLock) {
-                SparseArray<SensorState> states = mIndividualEnabled.get(userId);
-                if (states == null) {
-                    return false;
-                }
-                SensorState state = states.get(sensor);
-                if (state == null) {
-                    return false;
-                }
-                return state.mEnabled;
+                return isIndividualSensorPrivacyEnabledLocked(userId, sensor);
             }
         }
 
+        private boolean isIndividualSensorPrivacyEnabledLocked(int userId, int sensor) {
+            SparseArray<SensorState> states = mIndividualEnabled.get(userId);
+            if (states == null) {
+                return false;
+            }
+            SensorState state = states.get(sensor);
+            if (state == null) {
+                return false;
+            }
+            return state.mEnabled;
+        }
+
         /**
          * Returns the state of sensor privacy from persistent storage.
          */
@@ -1149,11 +1153,27 @@
                 ISensorPrivacyListener listener) {
             enforceObserveSensorPrivacyPermission();
             if (listener == null) {
-                throw new NullPointerException("listener cannot be null");
+                throw new IllegalArgumentException("listener cannot be null");
             }
             mHandler.addListener(userId, sensor, listener);
         }
 
+
+        /**
+         * Registers a listener to be notified when the sensor privacy state changes. The callback
+         * can be called if the user changes and the setting is different between the transitioning
+         * users.
+         */
+        @Override
+        public void addUserGlobalIndividualSensorPrivacyListener(int sensor,
+                ISensorPrivacyListener listener) {
+            enforceObserveSensorPrivacyPermission();
+            if (listener == null) {
+                throw new IllegalArgumentException("listener cannot be null");
+            }
+            mHandler.addUserGlobalListener(sensor, listener);
+        }
+
         /**
          * Unregisters a listener from sensor privacy state change notifications.
          */
@@ -1174,12 +1194,22 @@
                 ISensorPrivacyListener listener) {
             enforceObserveSensorPrivacyPermission();
             if (listener == null) {
-                throw new NullPointerException("listener cannot be null");
+                throw new IllegalArgumentException("listener cannot be null");
             }
             mHandler.removeListener(sensor, listener);
         }
 
         @Override
+        public void removeUserGlobalIndividualSensorPrivacyListener(int sensor,
+                ISensorPrivacyListener listener) {
+            enforceObserveSensorPrivacyPermission();
+            if (listener == null) {
+                throw new IllegalArgumentException("listener cannot be null");
+            }
+            mHandler.removeUserGlobalListener(sensor, listener);
+        }
+
+        @Override
         public void suppressIndividualSensorPrivacyReminders(int userId, int sensor,
                 IBinder token, boolean suppress) {
             enforceManageSensorPrivacyPermission();
@@ -1209,6 +1239,40 @@
             }
         }
 
+        private void userSwitching(int from, int to) {
+            boolean micState;
+            boolean camState;
+            boolean prevMicState;
+            boolean prevCamState;
+            synchronized (mLock) {
+                prevMicState = isIndividualSensorPrivacyEnabledLocked(from, MICROPHONE);
+                prevCamState = isIndividualSensorPrivacyEnabledLocked(from, CAMERA);
+                micState = isIndividualSensorPrivacyEnabledLocked(to, MICROPHONE);
+                camState = isIndividualSensorPrivacyEnabledLocked(to, CAMERA);
+            }
+            if (prevMicState != micState) {
+                mHandler.onUserGlobalSensorPrivacyChanged(MICROPHONE, micState);
+                setGlobalRestriction(MICROPHONE, micState);
+            }
+            if (prevCamState != camState) {
+                mHandler.onUserGlobalSensorPrivacyChanged(CAMERA, camState);
+                setGlobalRestriction(CAMERA, micState);
+            }
+        }
+
+        private void setGlobalRestriction(int sensor, boolean enabled) {
+            switch(sensor) {
+                case MICROPHONE:
+                    mAppOpsManagerInternal.setGlobalRestriction(OP_RECORD_AUDIO, enabled,
+                            mAppOpsRestrictionToken);
+                    break;
+                case CAMERA:
+                    mAppOpsManagerInternal.setGlobalRestriction(OP_CAMERA, enabled,
+                            mAppOpsRestrictionToken);
+                    break;
+            }
+        }
+
         /**
          * Remove a sensor use reminder suppression token.
          *
@@ -1454,7 +1518,12 @@
         @GuardedBy("mListenerLock")
         private final SparseArray<SparseArray<RemoteCallbackList<ISensorPrivacyListener>>>
                 mIndividualSensorListeners = new SparseArray<>();
-        private final ArrayMap<ISensorPrivacyListener, DeathRecipient> mDeathRecipients;
+        @GuardedBy("mListenerLock")
+        private final SparseArray<RemoteCallbackList<ISensorPrivacyListener>>
+                mUserGlobalIndividualSensorListeners = new SparseArray<>();
+        @GuardedBy("mListenerLock")
+        private final ArrayMap<ISensorPrivacyListener, Pair<DeathRecipient, Integer>>
+                mDeathRecipients;
         private final Context mContext;
 
         SensorPrivacyHandler(Looper looper, Context context) {
@@ -1479,18 +1548,22 @@
                             mSensorPrivacyServiceImpl));
         }
 
+        public void onUserGlobalSensorPrivacyChanged(int sensor, boolean enabled) {
+            sendMessage(PooledLambda.obtainMessage(
+                    SensorPrivacyHandler::handleUserGlobalSensorPrivacyChanged,
+                    this, sensor, enabled));
+        }
+
         public void addListener(ISensorPrivacyListener listener) {
             synchronized (mListenerLock) {
-                DeathRecipient deathRecipient = new DeathRecipient(listener);
-                mDeathRecipients.put(listener, deathRecipient);
-                mListeners.register(listener);
+                if (mListeners.register(listener)) {
+                    addDeathRecipient(listener);
+                }
             }
         }
 
         public void addListener(int userId, int sensor, ISensorPrivacyListener listener) {
             synchronized (mListenerLock) {
-                DeathRecipient deathRecipient = new DeathRecipient(listener);
-                mDeathRecipients.put(listener, deathRecipient);
                 SparseArray<RemoteCallbackList<ISensorPrivacyListener>> listenersForUser =
                         mIndividualSensorListeners.get(userId);
                 if (listenersForUser == null) {
@@ -1502,32 +1575,55 @@
                     listeners = new RemoteCallbackList<>();
                     listenersForUser.put(sensor, listeners);
                 }
-                listeners.register(listener);
+                if (listeners.register(listener)) {
+                    addDeathRecipient(listener);
+                }
+            }
+        }
+
+        public void addUserGlobalListener(int sensor, ISensorPrivacyListener listener) {
+            synchronized (mListenerLock) {
+                RemoteCallbackList<ISensorPrivacyListener> listeners =
+                        mUserGlobalIndividualSensorListeners.get(sensor);
+                if (listeners == null) {
+                    listeners = new RemoteCallbackList<>();
+                    mUserGlobalIndividualSensorListeners.put(sensor, listeners);
+                }
+                if (listeners.register(listener)) {
+                    addDeathRecipient(listener);
+                }
             }
         }
 
         public void removeListener(ISensorPrivacyListener listener) {
             synchronized (mListenerLock) {
-                DeathRecipient deathRecipient = mDeathRecipients.remove(listener);
-                if (deathRecipient != null) {
-                    deathRecipient.destroy();
+                if (mListeners.unregister(listener)) {
+                    removeDeathRecipient(listener);
                 }
-                mListeners.unregister(listener);
             }
         }
 
         public void removeListener(int sensor, ISensorPrivacyListener listener) {
             synchronized (mListenerLock) {
-                DeathRecipient deathRecipient = mDeathRecipients.remove(listener);
-                if (deathRecipient != null) {
-                    deathRecipient.destroy();
-                }
-
                 for (int i = 0, numUsers = mIndividualSensorListeners.size(); i < numUsers; i++) {
                     RemoteCallbackList callbacks =
                             mIndividualSensorListeners.valueAt(i).get(sensor);
                     if (callbacks != null) {
-                        callbacks.unregister(listener);
+                        if (callbacks.unregister(listener)) {
+                            removeDeathRecipient(listener);
+                        }
+                    }
+                }
+            }
+        }
+
+        public void removeUserGlobalListener(int sensor, ISensorPrivacyListener listener) {
+            synchronized (mListenerLock) {
+                RemoteCallbackList callbacks =
+                        mUserGlobalIndividualSensorListeners.get(sensor);
+                if (callbacks != null) {
+                    if (callbacks.unregister(listener)) {
+                        removeDeathRecipient(listener);
                     }
                 }
             }
@@ -1551,9 +1647,12 @@
             SparseArray<RemoteCallbackList<ISensorPrivacyListener>> listenersForUser =
                     mIndividualSensorListeners.get(userId);
 
-            setGlobalRestriction();
             if (userId == mCurrentUser) {
-                setGlobalRestriction();
+                mSensorPrivacyServiceImpl.setGlobalRestriction(sensor, enabled);
+            }
+
+            if (userId == mCurrentUser) {
+                onUserGlobalSensorPrivacyChanged(sensor, enabled);
             }
 
             if (listenersForUser == null) {
@@ -1563,16 +1662,42 @@
             if (listeners == null) {
                 return;
             }
-            final int count = listeners.beginBroadcast();
-            for (int i = 0; i < count; i++) {
-                ISensorPrivacyListener listener = listeners.getBroadcastItem(i);
-                try {
-                    listener.onSensorPrivacyChanged(enabled);
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Caught an exception notifying listener " + listener + ": ", e);
+            try {
+                final int count = listeners.beginBroadcast();
+                for (int i = 0; i < count; i++) {
+                    ISensorPrivacyListener listener = listeners.getBroadcastItem(i);
+                    try {
+                        listener.onSensorPrivacyChanged(enabled);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Caught an exception notifying listener " + listener + ": ", e);
+                    }
                 }
+            } finally {
+                listeners.finishBroadcast();
             }
-            listeners.finishBroadcast();
+        }
+
+        public void handleUserGlobalSensorPrivacyChanged(int sensor, boolean enabled) {
+            RemoteCallbackList<ISensorPrivacyListener> listeners =
+                    mUserGlobalIndividualSensorListeners.get(sensor);
+
+            if (listeners == null) {
+                return;
+            }
+
+            try {
+                final int count = listeners.beginBroadcast();
+                for (int i = 0; i < count; i++) {
+                    ISensorPrivacyListener listener = listeners.getBroadcastItem(i);
+                    try {
+                        listener.onSensorPrivacyChanged(enabled);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Caught an exception notifying listener " + listener + ": ", e);
+                    }
+                }
+            } finally {
+                listeners.finishBroadcast();
+            }
         }
 
         public void removeSuppressPackageReminderToken(Pair<Integer, UserHandle> key,
@@ -1581,20 +1706,33 @@
                     SensorPrivacyServiceImpl::removeSuppressPackageReminderToken,
                     mSensorPrivacyServiceImpl, key, token));
         }
-    }
 
-    private void setGlobalRestriction() {
-        boolean camState =
-                mSensorPrivacyServiceImpl
-                        .isIndividualSensorPrivacyEnabled(mCurrentUser, CAMERA);
-        boolean micState =
-                mSensorPrivacyServiceImpl
-                        .isIndividualSensorPrivacyEnabled(mCurrentUser, MICROPHONE);
+        private void addDeathRecipient(ISensorPrivacyListener listener) {
+            Pair<DeathRecipient, Integer> deathRecipient = mDeathRecipients.get(listener);
+            if (deathRecipient == null) {
+                deathRecipient = new Pair<>(new DeathRecipient(listener), 1);
+            } else {
+                int newRefCount = deathRecipient.second + 1;
+                deathRecipient = new Pair<>(deathRecipient.first, newRefCount);
+            }
+            mDeathRecipients.put(listener, deathRecipient);
+        }
 
-        mAppOpsManagerInternal
-                .setGlobalRestriction(OP_CAMERA, camState, mAppOpsRestrictionToken);
-        mAppOpsManagerInternal
-                .setGlobalRestriction(OP_RECORD_AUDIO, micState, mAppOpsRestrictionToken);
+        private void removeDeathRecipient(ISensorPrivacyListener listener) {
+            Pair<DeathRecipient, Integer> deathRecipient = mDeathRecipients.get(listener);
+            if (deathRecipient == null) {
+                return;
+            } else {
+                int newRefCount = deathRecipient.second - 1;
+                if (newRefCount == 0) {
+                    mDeathRecipients.remove(listener);
+                    deathRecipient.first.destroy();
+                    return;
+                }
+                deathRecipient = new Pair<>(deathRecipient.first, newRefCount);
+            }
+            mDeathRecipients.put(listener, deathRecipient);
+        }
     }
 
     private final class DeathRecipient implements IBinder.DeathRecipient {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 795d3d6..07847f1 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1934,6 +1934,28 @@
                 if (smap != null) {
                     decActiveForegroundAppLocked(smap, r);
                 }
+
+                // Adjust notification handling before setting isForeground to false, because
+                // that state is relevant to the notification policy side.
+                // Leave the time-to-display as already set: re-entering foreground mode will
+                // only resume the previous quiet timeout, or will display immediately if the
+                // deferral period had already passed.
+                if ((flags & Service.STOP_FOREGROUND_REMOVE) != 0) {
+                    cancelForegroundNotificationLocked(r);
+                    r.foregroundId = 0;
+                    r.foregroundNoti = null;
+                } else if (r.appInfo.targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
+                    // if it's been deferred, force to visibility
+                    if (!r.mFgsNotificationShown) {
+                        r.postNotification();
+                    }
+                    dropFgsNotificationStateLocked(r);
+                    if ((flags & Service.STOP_FOREGROUND_DETACH) != 0) {
+                        r.foregroundId = 0;
+                        r.foregroundNoti = null;
+                    }
+                }
+
                 r.isForeground = false;
                 r.mFgsExitTime = SystemClock.uptimeMillis();
                 ServiceState stracker = r.getTracker();
@@ -1957,20 +1979,6 @@
                     updateServiceForegroundLocked(r.app.mServices, true);
                 }
             }
-            // Leave the time-to-display as already set: re-entering foreground mode will
-            // only resume the previous quiet timeout, or will display immediately if the
-            // deferral period had already passed.
-            if ((flags & Service.STOP_FOREGROUND_REMOVE) != 0) {
-                cancelForegroundNotificationLocked(r);
-                r.foregroundId = 0;
-                r.foregroundNoti = null;
-            } else if (r.appInfo.targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
-                dropFgsNotificationStateLocked(r);
-                if ((flags & Service.STOP_FOREGROUND_DETACH) != 0) {
-                    r.foregroundId = 0;
-                    r.foregroundNoti = null;
-                }
-            }
         }
     }
 
diff --git a/services/core/java/com/android/server/am/AppExitInfoTracker.java b/services/core/java/com/android/server/am/AppExitInfoTracker.java
index abb8243..979a9ee 100644
--- a/services/core/java/com/android/server/am/AppExitInfoTracker.java
+++ b/services/core/java/com/android/server/am/AppExitInfoTracker.java
@@ -430,7 +430,13 @@
 
         final ApplicationExitInfo info = new ApplicationExitInfo(raw);
         final String[] packages = raw.getPackageList();
-        final int uid = raw.getPackageUid();
+        int uid = raw.getRealUid();
+        if (UserHandle.isIsolated(uid)) {
+            Integer k = mIsolatedUidRecords.getUidByIsolatedUid(uid);
+            if (k != null) {
+                uid = k;
+            }
+        }
         for (int i = 0; i < packages.length; i++) {
             addExitInfoInnerLocked(packages[i], uid, info);
         }
@@ -833,14 +839,14 @@
         pw.println(prefix + "package: " + packageName);
         int size = array.size();
         for (int i = 0; i < size; i++) {
-            pw.println(prefix + "  Historical Process Exit for userId=" + array.keyAt(i));
+            pw.println(prefix + "  Historical Process Exit for uid=" + array.keyAt(i));
             array.valueAt(i).dumpLocked(pw, prefix + "    ", sdf);
         }
     }
 
     @GuardedBy("mLock")
-    private void addExitInfoInnerLocked(String packageName, int userId, ApplicationExitInfo info) {
-        AppExitInfoContainer container = mData.get(packageName, userId);
+    private void addExitInfoInnerLocked(String packageName, int uid, ApplicationExitInfo info) {
+        AppExitInfoContainer container = mData.get(packageName, uid);
         if (container == null) {
             container = new AppExitInfoContainer(mAppExitInfoHistoryListSize);
             if (UserHandle.isIsolated(info.getRealUid())) {
@@ -851,7 +857,7 @@
             } else {
                 container.mUid = info.getRealUid();
             }
-            mData.put(packageName, userId, container);
+            mData.put(packageName, uid, container);
         }
         container.addExitInfoLocked(info);
     }
@@ -997,7 +1003,7 @@
             info.setPackageList(app.getPackageList());
             info.setReason(ApplicationExitInfo.REASON_UNKNOWN);
             info.setStatus(0);
-            info.setImportance(procStateToImportance(app.mState.getSetProcState()));
+            info.setImportance(procStateToImportance(app.mState.getReportedProcState()));
             info.setPss(app.mProfile.getLastPss());
             info.setRss(app.mProfile.getLastRss());
             info.setTimestamp(timestamp);
diff --git a/services/core/java/com/android/server/am/LmkdConnection.java b/services/core/java/com/android/server/am/LmkdConnection.java
index 1ecb9eb..598f086 100644
--- a/services/core/java/com/android/server/am/LmkdConnection.java
+++ b/services/core/java/com/android/server/am/LmkdConnection.java
@@ -50,7 +50,7 @@
      * Used to hold the data for the statsd atoms logging
      * Must be in sync with statslog.h
      */
-    private static final int LMKD_REPLY_MAX_SIZE = 214;
+    private static final int LMKD_REPLY_MAX_SIZE = 222;
 
     // connection listener interface
     interface LmkdConnectionListener {
diff --git a/services/core/java/com/android/server/am/LmkdStatsReporter.java b/services/core/java/com/android/server/am/LmkdStatsReporter.java
index c702d78..9158891 100644
--- a/services/core/java/com/android/server/am/LmkdStatsReporter.java
+++ b/services/core/java/com/android/server/am/LmkdStatsReporter.java
@@ -43,6 +43,7 @@
     private static final int LOW_MEM_AND_THRASHING = 4;
     private static final int DIRECT_RECL_AND_THRASHING = 5;
     private static final int LOW_MEM_AND_SWAP_UTIL = 6;
+    private static final int LOW_FILECACHE_AFTER_THRASHING = 7;
 
     /**
      * Processes the LMK_KILL_OCCURRED packet data
@@ -63,11 +64,14 @@
             final int freeMemKb = inputData.readInt();
             final int freeSwapKb = inputData.readInt();
             final int killReason = inputData.readInt();
+            final int thrashing = inputData.readInt();
+            final int maxThrashing = inputData.readInt();
             final String procName = inputData.readUTF();
 
             FrameworkStatsLog.write(FrameworkStatsLog.LMK_KILL_OCCURRED, uid, procName, oomScore,
                     pgFault, pgMajFault, rssInBytes, cacheInBytes, swapInBytes, processStartTimeNS,
-                    minOomScore, freeMemKb, freeSwapKb, mapKillReason(killReason));
+                    minOomScore, freeMemKb, freeSwapKb, mapKillReason(killReason), thrashing,
+                    maxThrashing);
         } catch (IOException e) {
             Slog.e(TAG, "Invalid buffer data. Failed to log LMK_KILL_OCCURRED");
             return;
@@ -100,6 +104,8 @@
                 return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__DIRECT_RECL_AND_THRASHING;
             case LOW_MEM_AND_SWAP_UTIL:
                 return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__LOW_MEM_AND_SWAP_UTIL;
+            case LOW_FILECACHE_AFTER_THRASHING:
+                return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__LOW_FILECACHE_AFTER_THRASHING;
             default:
                 return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__UNKNOWN;
         }
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index f7c777e..dc924c1 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -24,6 +24,7 @@
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
+import android.app.BroadcastOptions;
 import android.app.PendingIntent;
 import android.content.IIntentReceiver;
 import android.content.IIntentSender;
@@ -408,6 +409,18 @@
                 }
                 controller.mAmInternal.tempAllowlistForPendingIntent(callingPid, callingUid,
                         uid, duration.duration, duration.type, duration.reasonCode, tag.toString());
+            } else if (key.type == ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE
+                    && options != null) {
+                // If this is a getForegroundService() type pending intent, use its BroadcastOptions
+                // temp allowlist duration as its pending intent temp allowlist duration.
+                BroadcastOptions brOptions = new BroadcastOptions(options);
+                if (brOptions.getTemporaryAppAllowlistDuration() > 0) {
+                    controller.mAmInternal.tempAllowlistForPendingIntent(callingPid, callingUid,
+                            uid, brOptions.getTemporaryAppAllowlistDuration(),
+                            brOptions.getTemporaryAppAllowlistType(),
+                            brOptions.getTemporaryAppAllowlistReasonCode(),
+                            brOptions.getTemporaryAppAllowlistReason());
+                }
             }
 
             boolean sendFinish = finishedReceiver != null;
diff --git a/services/core/java/com/android/server/am/PhantomProcessList.java b/services/core/java/com/android/server/am/PhantomProcessList.java
index 4f3438fe..ca31681 100644
--- a/services/core/java/com/android/server/am/PhantomProcessList.java
+++ b/services/core/java/com/android/server/am/PhantomProcessList.java
@@ -305,7 +305,7 @@
             }
             // Somehow our record doesn't match, remove it anyway
             Slog.w(TAG, "Stale " + proc + ", removing");
-            mPhantomProcesses.removeAt(index);
+            onPhantomProcessKilledLocked(proc);
         } else {
             // Is this one of the zombie processes we've known?
             final int idx = mZombiePhantomProcesses.indexOfKey(pid);
diff --git a/services/core/java/com/android/server/am/ProcessStateRecord.java b/services/core/java/com/android/server/am/ProcessStateRecord.java
index 7520d88..dc6bcd8 100644
--- a/services/core/java/com/android/server/am/ProcessStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessStateRecord.java
@@ -1086,7 +1086,7 @@
         mCurRawAdj = mSetRawAdj = mCurAdj = mSetAdj = mVerifiedAdj = ProcessList.INVALID_ADJ;
         mCurCapability = mSetCapability = PROCESS_CAPABILITY_NONE;
         mCurSchedGroup = mSetSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
-        mCurProcState = mRepProcState = mCurRawProcState = mSetProcState = mAllowStartFgsState =
+        mCurProcState = mCurRawProcState = mSetProcState = mAllowStartFgsState =
                 PROCESS_STATE_NONEXISTENT;
     }
 
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 24edc01..a9905dc 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -7297,6 +7297,30 @@
                 }
             }
         }
+
+        @Override
+        public int getOpRestrictionCount(int code, UserHandle user, String pkg,
+                String attributionTag) {
+            int number = 0;
+            synchronized (AppOpsService.this) {
+                int numRestrictions = mOpUserRestrictions.size();
+                for (int i = 0; i < numRestrictions; i++) {
+                    if (mOpUserRestrictions.valueAt(i)
+                            .hasRestriction(code, pkg, attributionTag, user.getIdentifier())) {
+                        number++;
+                    }
+                }
+
+                numRestrictions = mOpGlobalRestrictions.size();
+                for (int i = 0; i < numRestrictions; i++) {
+                    if (mOpGlobalRestrictions.valueAt(i).hasRestriction(code)) {
+                        number++;
+                    }
+                }
+            }
+
+            return number;
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index fed320d..6b7787a 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -73,6 +73,7 @@
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.util.DumpUtils;
 import com.android.server.SystemService;
+import com.android.server.biometrics.sensors.CoexCoordinator;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -1100,6 +1101,12 @@
             }
             return new ArrayList<>();
         }
+
+        public boolean isAdvancedCoexLogicEnabled(Context context) {
+            return (Build.IS_USERDEBUG || Build.IS_ENG)
+                    && Settings.Secure.getInt(context.getContentResolver(),
+                    CoexCoordinator.SETTING_ENABLE_NAME, 0) != 0;
+        }
     }
 
     /**
@@ -1126,6 +1133,12 @@
         mSettingObserver = mInjector.getSettingObserver(context, mHandler,
                 mEnabledOnKeyguardCallbacks);
 
+        // TODO(b/193089985) This logic lives here (outside of CoexCoordinator) so that it doesn't
+        //  need to depend on context. We can remove this code once the advanced logic is enabled
+        //  by default.
+        CoexCoordinator coexCoordinator = CoexCoordinator.getInstance();
+        coexCoordinator.setAdvancedLogicEnabled(injector.isAdvancedCoexLogicEnabled(context));
+
         try {
             injector.getActivityManagerService().registerUserSwitchObserver(
                     new UserSwitchObserver() {
@@ -1437,5 +1450,7 @@
         pw.println();
         pw.println("CurrentSession: " + mCurrentAuthSession);
         pw.println();
+        pw.println("CoexCoordinator: " + CoexCoordinator.getInstance().toString());
+        pw.println();
     }
 }
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
index 28c949d..6463e04 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@@ -16,6 +16,7 @@
 
 package com.android.server.biometrics.sensors;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
@@ -30,6 +31,7 @@
 import android.hardware.biometrics.BiometricsProtoEnums;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.os.SystemClock;
 import android.security.KeyStore;
 import android.util.EventLog;
 import android.util.Slog;
@@ -48,6 +50,18 @@
 
     private static final String TAG = "Biometrics/AuthenticationClient";
 
+    // New, has not started yet
+    public static final int STATE_NEW = 0;
+    // Framework/HAL have started this operation
+    public static final int STATE_STARTED = 1;
+    // Operation is started, but requires some user action (such as finger lift & re-touch)
+    public static final int STATE_STARTED_PAUSED = 2;
+    // Done, errored, canceled, etc. HAL/framework are not running this sensor anymore.
+    public static final int STATE_STOPPED = 3;
+
+    @IntDef({STATE_NEW, STATE_STARTED, STATE_STARTED_PAUSED, STATE_STOPPED})
+    @interface State {}
+
     private final boolean mIsStrongBiometric;
     private final boolean mRequireConfirmation;
     private final ActivityTaskManager mActivityTaskManager;
@@ -63,6 +77,20 @@
 
     protected boolean mAuthAttempted;
 
+    // TODO: This is currently hard to maintain, as each AuthenticationClient subclass must update
+    //  the state. We should think of a way to improve this in the future.
+    protected @State int mState = STATE_NEW;
+
+    /**
+     * Handles lifecycle, e.g. {@link BiometricScheduler},
+     * {@link com.android.server.biometrics.sensors.BaseClientMonitor.Callback} after authentication
+     * results are known. Note that this happens asynchronously from (but shortly after)
+     * {@link #onAuthenticated(BiometricAuthenticator.Identifier, boolean, ArrayList)} and allows
+     * {@link CoexCoordinator} a chance to invoke/delay this event.
+     * @param authenticated
+     */
+    protected abstract void handleLifecycleAfterAuth(boolean authenticated);
+
     public AuthenticationClient(@NonNull Context context, @NonNull LazyDaemon<T> lazyDaemon,
             @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener,
             int targetUserId, long operationId, boolean restricted, @NonNull String owner,
@@ -221,7 +249,8 @@
             }
 
             final CoexCoordinator coordinator = CoexCoordinator.getInstance();
-            coordinator.onAuthenticationSucceeded(this, new CoexCoordinator.Callback() {
+            coordinator.onAuthenticationSucceeded(SystemClock.uptimeMillis(), this,
+                    new CoexCoordinator.Callback() {
                 @Override
                 public void sendAuthenticationResult(boolean addAuthTokenIfStrong) {
                     if (addAuthTokenIfStrong && mIsStrongBiometric) {
@@ -262,6 +291,11 @@
                         vibrateSuccess();
                     }
                 }
+
+                @Override
+                public void handleLifecycleAfterAuth() {
+                    AuthenticationClient.this.handleLifecycleAfterAuth(true /* authenticated */);
+                }
             });
         } else {
             // Allow system-defined limit of number of attempts before giving up
@@ -272,7 +306,7 @@
             }
 
             final CoexCoordinator coordinator = CoexCoordinator.getInstance();
-            coordinator.onAuthenticationRejected(this, lockoutMode,
+            coordinator.onAuthenticationRejected(SystemClock.uptimeMillis(), this, lockoutMode,
                     new CoexCoordinator.Callback() {
                 @Override
                 public void sendAuthenticationResult(boolean addAuthTokenIfStrong) {
@@ -291,6 +325,11 @@
                         vibrateError();
                     }
                 }
+
+                @Override
+                public void handleLifecycleAfterAuth() {
+                    AuthenticationClient.this.handleLifecycleAfterAuth(false /* authenticated */);
+                }
             });
         }
     }
@@ -307,6 +346,12 @@
         }
     }
 
+    @Override
+    public void onError(int errorCode, int vendorCode) {
+        super.onError(errorCode, vendorCode);
+        mState = STATE_STOPPED;
+    }
+
     /**
      * Start authentication
      */
@@ -345,6 +390,10 @@
         }
     }
 
+    public @State int getState() {
+        return mState;
+    }
+
     @Override
     public int getProtoEnum() {
         return BiometricsProto.CM_AUTHENTICATE;
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
index 6126607..b20316e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
@@ -356,10 +356,12 @@
     /**
      * Creates a new scheduler.
      * @param tag for the specific instance of the scheduler. Should be unique.
+     * @param sensorType the sensorType that this scheduler is handling.
      * @param gestureAvailabilityDispatcher may be null if the sensor does not support gestures
      *                                      (such as fingerprint swipe).
      */
-    public BiometricScheduler(@NonNull String tag, @SensorType int sensorType,
+    public BiometricScheduler(@NonNull String tag,
+            @SensorType int sensorType,
             @Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
         this(tag, sensorType, gestureAvailabilityDispatcher, IBiometricService.Stub.asInterface(
                 ServiceManager.getService(Context.BIOMETRIC_SERVICE)), LOG_NUM_RECENT_OPERATIONS,
diff --git a/services/core/java/com/android/server/biometrics/sensors/CoexCoordinator.java b/services/core/java/com/android/server/biometrics/sensors/CoexCoordinator.java
index 08bf2e0..f732a14 100644
--- a/services/core/java/com/android/server/biometrics/sensors/CoexCoordinator.java
+++ b/services/core/java/com/android/server/biometrics/sensors/CoexCoordinator.java
@@ -16,12 +16,23 @@
 
 package com.android.server.biometrics.sensors;
 
+import static com.android.server.biometrics.sensors.BiometricScheduler.SENSOR_TYPE_FACE;
+import static com.android.server.biometrics.sensors.BiometricScheduler.SENSOR_TYPE_UDFPS;
 import static com.android.server.biometrics.sensors.BiometricScheduler.sensorTypeToString;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Handler;
+import android.os.Looper;
 import android.util.Slog;
 
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.biometrics.sensors.BiometricScheduler.SensorType;
+import com.android.server.biometrics.sensors.fingerprint.Udfps;
+
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.Map;
 
 /**
@@ -33,8 +44,13 @@
 public class CoexCoordinator {
 
     private static final String TAG = "BiometricCoexCoordinator";
+    public static final String SETTING_ENABLE_NAME =
+            "com.android.server.biometrics.sensors.CoexCoordinator.enable";
     private static final boolean DEBUG = true;
 
+    // Successful authentications should be used within this amount of time.
+    static final long SUCCESSFUL_AUTH_VALID_DURATION_MS = 5000;
+
     /**
      * Callback interface notifying the owner of "results" from the CoexCoordinator's business
      * logic.
@@ -50,24 +66,101 @@
          * Requests the owner to initiate a vibration for this event.
          */
         void sendHapticFeedback();
+
+        /**
+         * Requests the owner to handle the AuthenticationClient's lifecycle (e.g. finish and remove
+         * from scheduler if auth was successful).
+         */
+        void handleLifecycleAfterAuth();
     }
 
     private static CoexCoordinator sInstance;
 
+    @VisibleForTesting
+    public static class SuccessfulAuth {
+        final long mAuthTimestamp;
+        final @SensorType int mSensorType;
+        final AuthenticationClient<?> mAuthenticationClient;
+        final Callback mCallback;
+        final CleanupRunnable mCleanupRunnable;
+
+        public static class CleanupRunnable implements Runnable {
+            @NonNull final LinkedList<SuccessfulAuth> mSuccessfulAuths;
+            @NonNull final SuccessfulAuth mAuth;
+            @NonNull final Callback mCallback;
+
+            public CleanupRunnable(@NonNull LinkedList<SuccessfulAuth> successfulAuths,
+                    @NonNull SuccessfulAuth auth, @NonNull Callback callback) {
+                mSuccessfulAuths = successfulAuths;
+                mAuth = auth;
+                mCallback = callback;
+            }
+
+            @Override
+            public void run() {
+                final boolean removed = mSuccessfulAuths.remove(mAuth);
+                Slog.w(TAG, "Removing stale successfulAuth: " + mAuth.toString()
+                        + ", success: " + removed);
+                mCallback.handleLifecycleAfterAuth();
+            }
+        }
+
+        public SuccessfulAuth(@NonNull Handler handler,
+                @NonNull LinkedList<SuccessfulAuth> successfulAuths,
+                long currentTimeMillis,
+                @SensorType int sensorType,
+                @NonNull AuthenticationClient<?> authenticationClient,
+                @NonNull Callback callback) {
+            mAuthTimestamp = currentTimeMillis;
+            mSensorType = sensorType;
+            mAuthenticationClient = authenticationClient;
+            mCallback = callback;
+
+            mCleanupRunnable = new CleanupRunnable(successfulAuths, this, callback);
+
+            handler.postDelayed(mCleanupRunnable, SUCCESSFUL_AUTH_VALID_DURATION_MS);
+        }
+
+        @Override
+        public String toString() {
+            return "SensorType: " + sensorTypeToString(mSensorType)
+                    + ", mAuthTimestamp: " + mAuthTimestamp
+                    + ", authenticationClient: " + mAuthenticationClient;
+        }
+    }
+
+    /**
+     * @return a singleton instance.
+     */
     @NonNull
-    static CoexCoordinator getInstance() {
+    public static CoexCoordinator getInstance() {
         if (sInstance == null) {
             sInstance = new CoexCoordinator();
         }
         return sInstance;
     }
 
+    @VisibleForTesting
+    public void setAdvancedLogicEnabled(boolean enabled) {
+        mAdvancedLogicEnabled = enabled;
+    }
+
+    @VisibleForTesting
+    void reset() {
+        mClientMap.clear();
+    }
+
     // SensorType to AuthenticationClient map
     private final Map<Integer, AuthenticationClient<?>> mClientMap;
+    @VisibleForTesting final LinkedList<SuccessfulAuth> mSuccessfulAuths;
+    private boolean mAdvancedLogicEnabled;
+    private final Handler mHandler;
 
     private CoexCoordinator() {
         // Singleton
         mClientMap = new HashMap<>();
+        mSuccessfulAuths = new LinkedList<>();
+        mHandler = new Handler(Looper.getMainLooper());
     }
 
     public void addAuthenticationClient(@BiometricScheduler.SensorType int sensorType,
@@ -99,23 +192,132 @@
         mClientMap.remove(sensorType);
     }
 
-    public void onAuthenticationSucceeded(@NonNull AuthenticationClient<?> client,
+    public void onAuthenticationSucceeded(long currentTimeMillis,
+            @NonNull AuthenticationClient<?> client,
             @NonNull Callback callback) {
         if (client.isBiometricPrompt()) {
             callback.sendHapticFeedback();
             // For BP, BiometricService will add the authToken to Keystore.
             callback.sendAuthenticationResult(false /* addAuthTokenIfStrong */);
-        } else {
-            // Keyguard, FingerprintManager, FaceManager, etc
+            callback.handleLifecycleAfterAuth();
+        } else if (isUnknownClient(client)) {
+            // Client doesn't exist in our map for some reason. Give the user feedback so the
+            // device doesn't feel like it's stuck. All other cases below can assume that the
+            // client exists in our map.
             callback.sendHapticFeedback();
             callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */);
+            callback.handleLifecycleAfterAuth();
+        } else if (mAdvancedLogicEnabled && client.isKeyguard()) {
+            if (isSingleAuthOnly(client)) {
+                // Single sensor authentication
+                callback.sendHapticFeedback();
+                callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */);
+                callback.handleLifecycleAfterAuth();
+            } else {
+                // Multi sensor authentication
+                AuthenticationClient<?> udfps = mClientMap.getOrDefault(SENSOR_TYPE_UDFPS, null);
+                AuthenticationClient<?> face = mClientMap.getOrDefault(SENSOR_TYPE_FACE, null);
+                if (isCurrentFaceAuth(client)) {
+                    if (isUdfpsActivelyAuthing(udfps)) {
+                        // Face auth success while UDFPS is actively authing. No callback, no haptic
+                        // Feedback will be provided after UDFPS result:
+                        // 1) UDFPS succeeds - simply remove this from the queue
+                        // 2) UDFPS rejected - use this face auth success to notify clients
+                        mSuccessfulAuths.add(new SuccessfulAuth(mHandler, mSuccessfulAuths,
+                                currentTimeMillis, SENSOR_TYPE_FACE, client, callback));
+                    } else {
+                        callback.sendHapticFeedback();
+                        callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */);
+                        callback.handleLifecycleAfterAuth();
+                    }
+                } else if (isCurrentUdfps(client)) {
+                    if (isFaceScanning()) {
+                        // UDFPS succeeds while face is still scanning
+                        // Cancel face auth and/or prevent it from invoking haptics/callbacks after
+                        face.cancel();
+                    }
+
+                    removeAndFinishAllFaceFromQueue();
+
+                    callback.sendHapticFeedback();
+                    callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */);
+                    callback.handleLifecycleAfterAuth();
+                }
+            }
+        } else {
+            // Non-keyguard authentication. For example, Fingerprint Settings use of
+            // FingerprintManager for highlighting fingers
+            callback.sendHapticFeedback();
+            callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */);
+            callback.handleLifecycleAfterAuth();
         }
     }
 
-    public void onAuthenticationRejected(@NonNull AuthenticationClient<?> client,
+    public void onAuthenticationRejected(long currentTimeMillis,
+            @NonNull AuthenticationClient<?> client,
             @LockoutTracker.LockoutMode int lockoutMode,
             @NonNull Callback callback) {
-        callback.sendHapticFeedback();
+        final boolean keyguardAdvancedLogic = mAdvancedLogicEnabled && client.isKeyguard();
+
+        if (keyguardAdvancedLogic) {
+            if (isSingleAuthOnly(client)) {
+                callback.sendHapticFeedback();
+                callback.handleLifecycleAfterAuth();
+            } else {
+                // Multi sensor authentication
+                AuthenticationClient<?> udfps = mClientMap.getOrDefault(SENSOR_TYPE_UDFPS, null);
+                AuthenticationClient<?> face = mClientMap.getOrDefault(SENSOR_TYPE_FACE, null);
+                if (isCurrentFaceAuth(client)) {
+                    if (isUdfpsActivelyAuthing(udfps)) {
+                        // UDFPS should still be running in this case, do not vibrate. However, we
+                        // should notify the callback and finish the client, so that Keyguard and
+                        // BiometricScheduler do not get stuck.
+                        Slog.d(TAG, "Face rejected in multi-sensor auth, udfps: " + udfps);
+                        callback.handleLifecycleAfterAuth();
+                    } else {
+                        // UDFPS is not actively authenticating (finger not touching, already
+                        // rejected, etc).
+                        callback.sendHapticFeedback();
+                        callback.handleLifecycleAfterAuth();
+                    }
+                } else if (isCurrentUdfps(client)) {
+                    // Face should either be running, or have already finished
+                    SuccessfulAuth auth = popSuccessfulFaceAuthIfExists(currentTimeMillis);
+                    if (auth != null) {
+                        Slog.d(TAG, "Using recent auth: " + auth);
+                        callback.handleLifecycleAfterAuth();
+
+                        auth.mCallback.sendHapticFeedback();
+                        auth.mCallback.sendAuthenticationResult(true /* addAuthTokenIfStrong */);
+                        auth.mCallback.handleLifecycleAfterAuth();
+                    } else if (isFaceScanning()) {
+                        // UDFPS rejected but face is still scanning
+                        Slog.d(TAG, "UDFPS rejected in multi-sensor auth, face: " + face);
+                        callback.handleLifecycleAfterAuth();
+
+                        // TODO(b/193089985): Enforce/ensure that face auth finishes (whether
+                        //  accept/reject) within X amount of time. Otherwise users will be stuck
+                        //  waiting with their finger down for a long time.
+                    } else {
+                        // Face not scanning, and was not found in the queue. Most likely, face
+                        // auth was too long ago.
+                        Slog.d(TAG, "UDFPS rejected in multi-sensor auth, face not scanning");
+                        callback.sendHapticFeedback();
+                        callback.handleLifecycleAfterAuth();
+                    }
+                } else {
+                    Slog.d(TAG, "Unknown client rejected: " + client);
+                    callback.sendHapticFeedback();
+                    callback.handleLifecycleAfterAuth();
+                }
+            }
+        } else {
+            callback.sendHapticFeedback();
+            callback.handleLifecycleAfterAuth();
+        }
+
+        // Always notify keyguard, otherwise the cached "running" state in KeyguardUpdateMonitor
+        // will get stuck.
         if (lockoutMode == LockoutTracker.LOCKOUT_NONE) {
             // Don't send onAuthenticationFailed if we're in lockout, it causes a
             // janky UI on Keyguard/BiometricPrompt since "authentication failed"
@@ -123,4 +325,82 @@
             callback.sendAuthenticationResult(false /* addAuthTokenIfStrong */);
         }
     }
+
+    @Nullable
+    private SuccessfulAuth popSuccessfulFaceAuthIfExists(long currentTimeMillis) {
+        for (SuccessfulAuth auth : mSuccessfulAuths) {
+            if (currentTimeMillis - auth.mAuthTimestamp >= SUCCESSFUL_AUTH_VALID_DURATION_MS) {
+                Slog.d(TAG, "Removing stale auth: " + auth);
+                mSuccessfulAuths.remove(auth);
+            } else if (auth.mSensorType == SENSOR_TYPE_FACE) {
+                mSuccessfulAuths.remove(auth);
+                return auth;
+            }
+        }
+        return null;
+    }
+
+    private void removeAndFinishAllFaceFromQueue() {
+        for (SuccessfulAuth auth : mSuccessfulAuths) {
+            if (auth.mSensorType == SENSOR_TYPE_FACE) {
+                Slog.d(TAG, "Removing from queue and finishing: " + auth);
+                auth.mCallback.handleLifecycleAfterAuth();
+                mSuccessfulAuths.remove(auth);
+            }
+        }
+    }
+
+    private boolean isCurrentFaceAuth(@NonNull AuthenticationClient<?> client) {
+        return client == mClientMap.getOrDefault(SENSOR_TYPE_FACE, null);
+    }
+
+    private boolean isCurrentUdfps(@NonNull AuthenticationClient<?> client) {
+        return client == mClientMap.getOrDefault(SENSOR_TYPE_UDFPS, null);
+    }
+
+    private boolean isFaceScanning() {
+        AuthenticationClient<?> client = mClientMap.getOrDefault(SENSOR_TYPE_FACE, null);
+        return client != null && client.getState() == AuthenticationClient.STATE_STARTED;
+    }
+
+    private static boolean isUdfpsActivelyAuthing(@Nullable AuthenticationClient<?> client) {
+        if (client instanceof Udfps) {
+            return client.getState() == AuthenticationClient.STATE_STARTED;
+        }
+        return false;
+    }
+
+    private boolean isUnknownClient(@NonNull AuthenticationClient<?> client) {
+        for (AuthenticationClient<?> c : mClientMap.values()) {
+            if (c == client) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private boolean isSingleAuthOnly(@NonNull AuthenticationClient<?> client) {
+        if (mClientMap.values().size() != 1) {
+            return false;
+        }
+
+        for (AuthenticationClient<?> c : mClientMap.values()) {
+            if (c != client) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("Enabled: ").append(mAdvancedLogicEnabled);
+        sb.append(", Queue size: " ).append(mSuccessfulAuths.size());
+        for (SuccessfulAuth auth : mSuccessfulAuths) {
+            sb.append(", Auth: ").append(auth.toString());
+        }
+
+        return sb.toString();
+    }
 }
diff --git a/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java b/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java
index c8867ea..b4c82f2 100644
--- a/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java
@@ -48,6 +48,64 @@
     private boolean mLightSensorEnabled = false;
     private boolean mShouldLogMetrics = true;
 
+    /**
+     * Probe for loggable attributes that can be continuously monitored, such as ambient light.
+     *
+     * Disable probes when the sensors are in states that are not interesting for monitoring
+     * purposes to save power.
+     */
+    protected interface Probe {
+        /** Ensure the probe is actively sampling for new data. */
+        void enable();
+        /** Stop sampling data. */
+        void disable();
+    }
+
+    /**
+     * Client monitor callback that exposes a probe.
+     *
+     * Disables the probe when the operation completes.
+     */
+    protected static class CallbackWithProbe<T extends Probe>
+            implements BaseClientMonitor.Callback {
+        private final boolean mStartWithClient;
+        private final T mProbe;
+
+        public CallbackWithProbe(@NonNull T probe, boolean startWithClient) {
+            mProbe = probe;
+            mStartWithClient = startWithClient;
+        }
+
+        @Override
+        public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
+            if (mStartWithClient) {
+                mProbe.enable();
+            }
+        }
+
+        @Override
+        public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, boolean success) {
+            mProbe.disable();
+        }
+
+        @NonNull
+        public T getProbe() {
+            return mProbe;
+        }
+    }
+
+    private class ALSProbe implements Probe {
+        @Override
+        public void enable() {
+            setLightSensorLoggingEnabled(getAmbientLightSensor(mSensorManager));
+        }
+
+        @Override
+        public void disable() {
+            setLightSensorLoggingEnabled(null);
+        }
+    }
+
     // report only the most recent value
     // consider com.android.server.display.utils.AmbientFilter or similar if need arises
     private volatile float mLastAmbientLux = 0;
@@ -285,21 +343,17 @@
         return latency;
     }
 
-    /** Get a callback to start/stop ALS capture when client runs. */
+    /**
+     * Get a callback to start/stop ALS capture when client runs.
+     *
+     * If the probe should not run for the entire operation, do not set startWithClient and
+     * start/stop the problem when needed.
+     *
+     * @param startWithClient if probe should start automatically when the operation starts.
+     */
     @NonNull
-    protected BaseClientMonitor.Callback createALSCallback() {
-        return new BaseClientMonitor.Callback() {
-            @Override
-            public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
-                setLightSensorLoggingEnabled(getAmbientLightSensor(mSensorManager));
-            }
-
-            @Override
-            public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
-                    boolean success) {
-                setLightSensorLoggingEnabled(null);
-            }
-        };
+    protected CallbackWithProbe<Probe> createALSCallback(boolean startWithClient) {
+        return new CallbackWithProbe<>(new ALSProbe(), startWithClient);
     }
 
     /** The sensor to use for ALS logging. */
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
index 779558e..219e063 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
@@ -215,7 +215,7 @@
         @Override // Binder call
         public void enroll(int userId, final IBinder token, final byte[] hardwareAuthToken,
                 final IFaceServiceReceiver receiver, final String opPackageName,
-                final int[] disabledFeatures, Surface surface, boolean debugConsent) {
+                final int[] disabledFeatures, Surface previewSurface, boolean debugConsent) {
             Utils.checkPermission(getContext(), MANAGE_BIOMETRIC);
 
             final Pair<Integer, ServiceProvider> provider = getSingleProvider();
@@ -225,8 +225,7 @@
             }
 
             provider.second.scheduleEnroll(provider.first, token, hardwareAuthToken, userId,
-                    receiver, opPackageName, disabledFeatures,
-                    convertSurfaceToNativeHandle(surface), debugConsent);
+                    receiver, opPackageName, disabledFeatures, previewSurface, debugConsent);
         }
 
         @Override // Binder call
@@ -703,5 +702,27 @@
         publishBinderService(Context.FACE_SERVICE, mServiceWrapper);
     }
 
-    private native NativeHandle convertSurfaceToNativeHandle(Surface surface);
+    /**
+     * Acquires a NativeHandle that can be used to access the provided surface. The returned handle
+     * must be explicitly released with {@link #releaseSurfaceHandle(NativeHandle)} to avoid memory
+     * leaks.
+     *
+     * The caller is responsible for ensuring that the surface is valid while using the handle.
+     * This method provides no lifecycle synchronization between the surface and the handle.
+     *
+     * @param surface a valid Surface.
+     * @return {@link android.os.NativeHandle} a NativeHandle for the provided surface.
+     */
+    public static native NativeHandle acquireSurfaceHandle(@NonNull Surface surface);
+
+    /**
+     * Releases resources associated with a NativeHandle that was acquired with
+     * {@link #acquireSurfaceHandle(Surface)}.
+     *
+     * This method has no affect on the surface for which the handle was acquired. It only frees up
+     * the resources that are associated with the handle.
+     *
+     * @param handle a handle that was obtained from {@link #acquireSurfaceHandle(Surface)}.
+     */
+    public static native void releaseSurfaceHandle(@NonNull NativeHandle handle);
 }
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
index 6d6c2e9..1d2ac3b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
@@ -26,8 +26,8 @@
 import android.hardware.face.FaceSensorPropertiesInternal;
 import android.hardware.face.IFaceServiceReceiver;
 import android.os.IBinder;
-import android.os.NativeHandle;
 import android.util.proto.ProtoOutputStream;
+import android.view.Surface;
 
 import com.android.server.biometrics.sensors.BaseClientMonitor;
 import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
@@ -75,8 +75,8 @@
     int getLockoutModeForUser(int sensorId, int userId);
 
     /**
-     * Requests for the authenticatorId (whose source of truth is in the TEE or equivalent) to
-     * be invalidated. See {@link com.android.server.biometrics.sensors.InvalidationRequesterClient}
+     * Requests for the authenticatorId (whose source of truth is in the TEE or equivalent) to be
+     * invalidated. See {@link com.android.server.biometrics.sensors.InvalidationRequesterClient}
      */
     default void scheduleInvalidateAuthenticatorId(int sensorId, int userId,
             @NonNull IInvalidationCallback callback) {
@@ -96,7 +96,7 @@
 
     void scheduleEnroll(int sensorId, @NonNull IBinder token, @NonNull byte[] hardwareAuthToken,
             int userId, @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName,
-            @NonNull int[] disabledFeatures, @Nullable NativeHandle surfaceHandle,
+            @NonNull int[] disabledFeatures, @Nullable Surface previewSurface,
             boolean debugConsent);
 
     void cancelEnrollment(int sensorId, @NonNull IBinder token);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/BiometricTestSessionImpl.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/BiometricTestSessionImpl.java
index 57c1c74..66b942b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/BiometricTestSessionImpl.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/BiometricTestSessionImpl.java
@@ -150,8 +150,8 @@
         Utils.checkPermission(mContext, TEST_BIOMETRIC);
 
         mProvider.scheduleEnroll(mSensorId, new Binder(), new byte[69], userId, mReceiver,
-                mContext.getOpPackageName(), new int[0] /* disabledFeatures */, null /* surface */,
-                false /* debugConsent */);
+                mContext.getOpPackageName(), new int[0] /* disabledFeatures */,
+                null /* previewSurface */, false /* debugConsent */);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
index 0525d2d..0c06b20 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
@@ -89,10 +89,16 @@
                 R.array.config_face_acquire_vendor_keyguard_ignorelist);
     }
 
+    @Override
+    public void start(@NonNull Callback callback) {
+        super.start(callback);
+        mState = STATE_STARTED;
+    }
+
     @NonNull
     @Override
     protected Callback wrapCallbackForStart(@NonNull Callback callback) {
-        return new CompositeCallback(createALSCallback(), callback);
+        return new CompositeCallback(createALSCallback(true /* startWithClient */), callback);
     }
 
     @Override
@@ -128,10 +134,20 @@
     }
 
     @Override
+    protected void handleLifecycleAfterAuth(boolean authenticated) {
+        // For face, the authentication lifecycle ends either when
+        // 1) Authenticated == true
+        // 2) Error occurred
+        // 3) Authenticated == false
+        mCallback.onClientFinished(this, true /* success */);
+    }
+
+    @Override
     public void onAuthenticated(BiometricAuthenticator.Identifier identifier,
             boolean authenticated, ArrayList<Byte> token) {
         super.onAuthenticated(identifier, authenticated, token);
 
+        mState = STATE_STOPPED;
         mUsageStats.addEvent(new UsageStats.AuthenticationEvent(
                 getStartTimeMs(),
                 System.currentTimeMillis() - getStartTimeMs() /* latency */,
@@ -139,12 +155,6 @@
                 0 /* error */,
                 0 /* vendorError */,
                 getTargetUserId()));
-
-        // For face, the authentication lifecycle ends either when
-        // 1) Authenticated == true
-        // 2) Error occurred
-        // 3) Authenticated == false
-        mCallback.onClientFinished(this, true /* success */);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
index 0400e22..a806277 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
@@ -26,21 +26,24 @@
 import android.hardware.biometrics.face.Feature;
 import android.hardware.biometrics.face.IFace;
 import android.hardware.biometrics.face.ISession;
+import android.hardware.common.NativeHandle;
 import android.hardware.face.Face;
 import android.hardware.face.FaceEnrollFrame;
 import android.hardware.face.FaceManager;
 import android.os.IBinder;
-import android.os.NativeHandle;
 import android.os.RemoteException;
 import android.util.Slog;
+import android.view.Surface;
 
 import com.android.internal.R;
 import com.android.server.biometrics.HardwareAuthTokenUtils;
 import com.android.server.biometrics.Utils;
+import com.android.server.biometrics.sensors.BaseClientMonitor;
 import com.android.server.biometrics.sensors.BiometricNotificationUtils;
 import com.android.server.biometrics.sensors.BiometricUtils;
 import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
 import com.android.server.biometrics.sensors.EnrollClient;
+import com.android.server.biometrics.sensors.face.FaceService;
 import com.android.server.biometrics.sensors.face.FaceUtils;
 
 import java.io.IOException;
@@ -57,16 +60,31 @@
     @NonNull private final int[] mEnrollIgnoreList;
     @NonNull private final int[] mEnrollIgnoreListVendor;
     @NonNull private final int[] mDisabledFeatures;
+    @Nullable private final Surface mPreviewSurface;
+    @Nullable private android.os.NativeHandle mOsPreviewHandle;
+    @Nullable private NativeHandle mHwPreviewHandle;
     @Nullable private ICancellationSignal mCancellationSignal;
-    @Nullable private android.hardware.common.NativeHandle mPreviewSurface;
     private final int mMaxTemplatesPerUser;
     private final boolean mDebugConsent;
 
+    private final BaseClientMonitor.Callback mPreviewHandleDeleterCallback =
+            new BaseClientMonitor.Callback() {
+                @Override
+                public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
+                }
+
+                @Override
+                public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
+                        boolean success) {
+                    releaseSurfaceHandlesIfNeeded();
+                }
+            };
+
     FaceEnrollClient(@NonNull Context context, @NonNull LazyDaemon<ISession> lazyDaemon,
             @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId,
             @NonNull byte[] hardwareAuthToken, @NonNull String opPackageName,
             @NonNull BiometricUtils<Face> utils, @NonNull int[] disabledFeatures, int timeoutSec,
-            @Nullable NativeHandle previewSurface, int sensorId, int maxTemplatesPerUser,
+            @Nullable Surface previewSurface, int sensorId, int maxTemplatesPerUser,
             boolean debugConsent) {
         super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, opPackageName, utils,
                 timeoutSec, BiometricsProtoEnums.MODALITY_FACE, sensorId,
@@ -78,14 +96,7 @@
         mMaxTemplatesPerUser = maxTemplatesPerUser;
         mDebugConsent = debugConsent;
         mDisabledFeatures = disabledFeatures;
-        try {
-            // We must manually close the duplicate handle after it's no longer needed.
-            // The caller is responsible for closing the original handle.
-            mPreviewSurface = AidlNativeHandleUtils.dup(previewSurface);
-        } catch (IOException e) {
-            mPreviewSurface = null;
-            Slog.e(TAG, "Failed to dup previewSurface", e);
-        }
+        mPreviewSurface = previewSurface;
     }
 
     @Override
@@ -98,17 +109,8 @@
     @NonNull
     @Override
     protected Callback wrapCallbackForStart(@NonNull Callback callback) {
-        return new CompositeCallback(createALSCallback(), callback);
-    }
-
-    @Override
-    public void destroy() {
-        try {
-            AidlNativeHandleUtils.close(mPreviewSurface);
-        } catch (IOException e) {
-            Slog.e(TAG, "Failed to close mPreviewSurface", e);
-        }
-        super.destroy();
+        return new CompositeCallback(mPreviewHandleDeleterCallback,
+                createALSCallback(true /* startWithClient */), callback);
     }
 
     @Override
@@ -153,22 +155,23 @@
 
     @Override
     protected void startHalOperation() {
+        obtainSurfaceHandlesIfNeeded();
         try {
             List<Byte> featureList = new ArrayList<Byte>();
             if (mDebugConsent) {
-                featureList.add(new Byte(Feature.DEBUG));
+                featureList.add(Feature.DEBUG);
             }
 
             boolean shouldAddDiversePoses = true;
-            for (int i = 0; i < mDisabledFeatures.length; i++) {
-                if (AidlConversionUtils.convertFrameworkToAidlFeature(mDisabledFeatures[i])
+            for (int disabledFeature : mDisabledFeatures) {
+                if (AidlConversionUtils.convertFrameworkToAidlFeature(disabledFeature)
                         == Feature.REQUIRE_DIVERSE_POSES) {
                     shouldAddDiversePoses = false;
                 }
             }
 
             if (shouldAddDiversePoses) {
-                featureList.add(new Byte(Feature.REQUIRE_DIVERSE_POSES));
+                featureList.add(Feature.REQUIRE_DIVERSE_POSES);
             }
 
             byte[] features = new byte[featureList.size()];
@@ -178,7 +181,7 @@
 
             mCancellationSignal = getFreshDaemon().enroll(
                     HardwareAuthTokenUtils.toHardwareAuthToken(mHardwareAuthToken),
-                    EnrollmentType.DEFAULT, features, mPreviewSurface);
+                    EnrollmentType.DEFAULT, features, mHwPreviewHandle);
         } catch (RemoteException | IllegalArgumentException e) {
             Slog.e(TAG, "Exception when requesting enroll", e);
             onError(BiometricFaceConstants.FACE_ERROR_UNABLE_TO_PROCESS, 0 /* vendorCode */);
@@ -198,4 +201,55 @@
             }
         }
     }
+
+    private void obtainSurfaceHandlesIfNeeded() {
+        if (mPreviewSurface != null) {
+            // There is no direct way to convert Surface to android.hardware.common.NativeHandle. We
+            // first convert Surface to android.os.NativeHandle, and then android.os.NativeHandle to
+            // android.hardware.common.NativeHandle, which can be passed to the HAL.
+            // The resources for both handles must be explicitly freed to avoid memory leaks.
+            mOsPreviewHandle = FaceService.acquireSurfaceHandle(mPreviewSurface);
+            try {
+                // We must manually free up the resources for both handles after they are no longer
+                // needed. mHwPreviewHandle must be closed, but mOsPreviewHandle must be released
+                // through FaceService.
+                mHwPreviewHandle = AidlNativeHandleUtils.dup(mOsPreviewHandle);
+                Slog.v(TAG, "Obtained handles for the preview surface.");
+            } catch (IOException e) {
+                mHwPreviewHandle = null;
+                Slog.e(TAG, "Failed to dup mOsPreviewHandle", e);
+            }
+        }
+    }
+
+    private void releaseSurfaceHandlesIfNeeded() {
+        if (mPreviewSurface != null && mHwPreviewHandle == null) {
+            Slog.w(TAG, "mHwPreviewHandle is null even though mPreviewSurface is not null.");
+        }
+        if (mHwPreviewHandle != null) {
+            try {
+                Slog.v(TAG, "Closing mHwPreviewHandle");
+                AidlNativeHandleUtils.close(mHwPreviewHandle);
+            } catch (IOException e) {
+                Slog.e(TAG, "Failed to close mPreviewSurface", e);
+            }
+            mHwPreviewHandle = null;
+        }
+        if (mOsPreviewHandle != null) {
+            Slog.v(TAG, "Releasing mOsPreviewHandle");
+            FaceService.releaseSurfaceHandle(mOsPreviewHandle);
+            mOsPreviewHandle = null;
+        }
+        if (mPreviewSurface != null) {
+            Slog.v(TAG, "Releasing mPreviewSurface");
+            // We need to manually release this surface because it's a copy of the original surface
+            // that was sent to us by an app (e.g. Settings). The app cleans up its own surface (as
+            // part of the SurfaceView lifecycle, for example), but there is no mechanism in place
+            // that will clean up this copy.
+            // If this copy isn't cleaned up, it will eventually be garbage collected. However, this
+            // surface could be holding onto the native buffers that the GC is not aware of,
+            // exhausting the native memory before the GC feels the need to garbage collect.
+            mPreviewSurface.release();
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
index 36a1292..5c24108 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
@@ -37,13 +37,13 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
-import android.os.NativeHandle;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserManager;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.proto.ProtoOutputStream;
+import android.view.Surface;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.biometrics.Utils;
@@ -327,7 +327,7 @@
     public void scheduleEnroll(int sensorId, @NonNull IBinder token,
             @NonNull byte[] hardwareAuthToken, int userId, @NonNull IFaceServiceReceiver receiver,
             @NonNull String opPackageName, @NonNull int[] disabledFeatures,
-            @Nullable NativeHandle previewSurface, boolean debugConsent) {
+            @Nullable Surface previewSurface, boolean debugConsent) {
         mHandler.post(() -> {
             final int maxTemplatesPerUser = mSensors.get(
                     sensorId).getSensorProperties().maxEnrollmentsPerUser;
@@ -400,7 +400,7 @@
     @Override
     public void scheduleRemove(int sensorId, @NonNull IBinder token, int faceId, int userId,
             @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName) {
-        scheduleRemoveSpecifiedIds(sensorId, token, new int[] {faceId}, userId, receiver,
+        scheduleRemoveSpecifiedIds(sensorId, token, new int[]{faceId}, userId, receiver,
                 opPackageName);
     }
 
@@ -561,7 +561,8 @@
     }
 
     @Override
-    public void dumpHal(int sensorId, @NonNull FileDescriptor fd, @NonNull String[] args) {}
+    public void dumpHal(int sensorId, @NonNull FileDescriptor fd, @NonNull String[] args) {
+    }
 
     @Override
     public void binderDied() {
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
index 4abd402..206b8f0 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
@@ -494,8 +494,8 @@
         mToken = new Binder();
         mHandler = handler;
         mSensorProperties = sensorProperties;
-        mScheduler = new UserAwareBiometricScheduler(tag, BiometricScheduler.SENSOR_TYPE_FACE,
-                null /* gestureAvailabilityDispatcher */,
+        mScheduler = new UserAwareBiometricScheduler(tag,
+                BiometricScheduler.SENSOR_TYPE_FACE, null /* gestureAvailabilityDispatcher */,
                 () -> mCurrentSession != null ? mCurrentSession.mUserId : UserHandle.USER_NULL,
                 new UserAwareBiometricScheduler.UserSwitchCallback() {
                     @NonNull
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/BiometricTestSessionImpl.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/BiometricTestSessionImpl.java
index d0580c7..b45578b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/BiometricTestSessionImpl.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/BiometricTestSessionImpl.java
@@ -139,7 +139,7 @@
 
         mFace10.scheduleEnroll(mSensorId, new Binder(), new byte[69], userId, mReceiver,
                 mContext.getOpPackageName(), new int[0] /* disabledFeatures */,
-                null /* surfaceHandle */, false /* debugConsent */);
+                null /* previewSurface */, false /* debugConsent */);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
index e95273a..da4ad86 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
@@ -47,6 +47,7 @@
 import android.provider.Settings;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
+import android.view.Surface;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.FrameworkStatsLog;
@@ -88,8 +89,8 @@
 import java.util.Map;
 
 /**
- * Supports a single instance of the {@link android.hardware.biometrics.face.V1_0} or
- * its extended minor versions.
+ * Supports a single instance of the {@link android.hardware.biometrics.face.V1_0} or its extended
+ * minor versions.
  */
 public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
 
@@ -325,7 +326,8 @@
         }
     }
 
-    @VisibleForTesting Face10(@NonNull Context context,
+    @VisibleForTesting
+    Face10(@NonNull Context context,
             @NonNull FaceSensorPropertiesInternal sensorProps,
             @NonNull LockoutResetDispatcher lockoutResetDispatcher,
             @NonNull BiometricScheduler scheduler) {
@@ -571,7 +573,7 @@
     public void scheduleEnroll(int sensorId, @NonNull IBinder token,
             @NonNull byte[] hardwareAuthToken, int userId, @NonNull IFaceServiceReceiver receiver,
             @NonNull String opPackageName, @NonNull int[] disabledFeatures,
-            @Nullable NativeHandle surfaceHandle, boolean debugConsent) {
+            @Nullable Surface previewSurface, boolean debugConsent) {
         mHandler.post(() -> {
             scheduleUpdateActiveUserWithoutHandler(userId);
 
@@ -580,7 +582,7 @@
             final FaceEnrollClient client = new FaceEnrollClient(mContext, mLazyDaemon, token,
                     new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken,
                     opPackageName, FaceUtils.getLegacyInstance(mSensorId), disabledFeatures,
-                    ENROLL_TIMEOUT_SEC, surfaceHandle, mSensorId);
+                    ENROLL_TIMEOUT_SEC, previewSurface, mSensorId);
 
             mScheduler.scheduleClientMonitor(client, new BaseClientMonitor.Callback() {
                 @Override
@@ -858,8 +860,8 @@
     }
 
     /**
-     * Schedules the {@link FaceUpdateActiveUserClient} without posting the work onto the
-     * handler. Many/most APIs are user-specific. However, the HAL requires explicit "setActiveUser"
+     * Schedules the {@link FaceUpdateActiveUserClient} without posting the work onto the handler.
+     * Many/most APIs are user-specific. However, the HAL requires explicit "setActiveUser"
      * invocation prior to authenticate/enroll/etc. Thus, internally we usually want to schedule
      * this operation on the same lambda/runnable as those operations so that the ordering is
      * correct.
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
index 5731d73..868f379 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
@@ -79,10 +79,16 @@
                 R.array.config_face_acquire_vendor_keyguard_ignorelist);
     }
 
+    @Override
+    public void start(@NonNull Callback callback) {
+        super.start(callback);
+        mState = STATE_STARTED;
+    }
+
     @NonNull
     @Override
     protected Callback wrapCallbackForStart(@NonNull Callback callback) {
-        return new CompositeCallback(createALSCallback(), callback);
+        return new CompositeCallback(createALSCallback(true /* startWithClient */), callback);
     }
 
     @Override
@@ -115,10 +121,20 @@
     }
 
     @Override
+    protected void handleLifecycleAfterAuth(boolean authenticated) {
+        // For face, the authentication lifecycle ends either when
+        // 1) Authenticated == true
+        // 2) Error occurred
+        // 3) Authenticated == false
+        mCallback.onClientFinished(this, true /* success */);
+    }
+
+    @Override
     public void onAuthenticated(BiometricAuthenticator.Identifier identifier,
             boolean authenticated, ArrayList<Byte> token) {
         super.onAuthenticated(identifier, authenticated, token);
 
+        mState = STATE_STOPPED;
         mUsageStats.addEvent(new UsageStats.AuthenticationEvent(
                 getStartTimeMs(),
                 System.currentTimeMillis() - getStartTimeMs() /* latency */,
@@ -126,12 +142,6 @@
                 0 /* error */,
                 0 /* vendorError */,
                 getTargetUserId()));
-
-        // For face, the authentication lifecycle ends either when
-        // 1) Authenticated == true
-        // 2) Error occurred
-        // 3) Authenticated == false
-        mCallback.onClientFinished(this, true /* success */);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java
index d3bd18b..80828cced 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java
@@ -26,9 +26,9 @@
 import android.hardware.face.Face;
 import android.hardware.face.FaceManager;
 import android.os.IBinder;
-import android.os.NativeHandle;
 import android.os.RemoteException;
 import android.util.Slog;
+import android.view.Surface;
 
 import com.android.internal.R;
 import com.android.server.biometrics.Utils;
@@ -40,15 +40,14 @@
 import java.util.Arrays;
 
 /**
- * Face-specific enroll client supporting the {@link android.hardware.biometrics.face.V1_0}
- * HIDL interface.
+ * Face-specific enroll client supporting the {@link android.hardware.biometrics.face.V1_0} HIDL
+ * interface.
  */
 public class FaceEnrollClient extends EnrollClient<IBiometricsFace> {
 
     private static final String TAG = "FaceEnrollClient";
 
     @NonNull private final int[] mDisabledFeatures;
-    @Nullable private final NativeHandle mSurfaceHandle;
     @NonNull private final int[] mEnrollIgnoreList;
     @NonNull private final int[] mEnrollIgnoreListVendor;
 
@@ -56,12 +55,11 @@
             @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId,
             @NonNull byte[] hardwareAuthToken, @NonNull String owner,
             @NonNull BiometricUtils<Face> utils, @NonNull int[] disabledFeatures, int timeoutSec,
-            @Nullable NativeHandle surfaceHandle, int sensorId) {
+            @Nullable Surface previewSurface, int sensorId) {
         super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, owner, utils,
                 timeoutSec, BiometricsProtoEnums.MODALITY_FACE, sensorId,
                 false /* shouldVibrate */);
         mDisabledFeatures = Arrays.copyOf(disabledFeatures, disabledFeatures.length);
-        mSurfaceHandle = surfaceHandle;
         mEnrollIgnoreList = getContext().getResources()
                 .getIntArray(R.array.config_face_acquire_enroll_ignorelist);
         mEnrollIgnoreListVendor = getContext().getResources()
@@ -71,7 +69,7 @@
     @NonNull
     @Override
     protected Callback wrapCallbackForStart(@NonNull Callback callback) {
-        return new CompositeCallback(createALSCallback(), callback);
+        return new CompositeCallback(createALSCallback(true /* startWithClient */), callback);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/Udfps.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/Udfps.java
index 150e69c6..a2c0751 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/Udfps.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/Udfps.java
@@ -27,4 +27,5 @@
     void onPointerDown(int x, int y, float minor, float major);
     void onPointerUp();
     void onUiReady();
+    boolean isPointerDown();
 }
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
index 8681ad7..fb2f2ef 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
@@ -54,7 +54,11 @@
 
     @NonNull private final LockoutCache mLockoutCache;
     @Nullable private final IUdfpsOverlayController mUdfpsOverlayController;
+    @NonNull private final FingerprintSensorPropertiesInternal mSensorProps;
+    @NonNull private final CallbackWithProbe<Probe> mALSProbeCallback;
+
     @Nullable private ICancellationSignal mCancellationSignal;
+    private boolean mIsPointerDown;
 
     FingerprintAuthenticationClient(@NonNull Context context,
             @NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token,
@@ -71,12 +75,33 @@
                 lockoutCache, allowBackgroundAuthentication, true /* shouldVibrate */);
         mLockoutCache = lockoutCache;
         mUdfpsOverlayController = udfpsOverlayController;
+        mSensorProps = sensorProps;
+        mALSProbeCallback = createALSCallback(false /* startWithClient */);
+    }
+
+    @Override
+    public void start(@NonNull Callback callback) {
+        super.start(callback);
+
+        if (mSensorProps.isAnyUdfpsType()) {
+            // UDFPS requires user to touch before becoming "active"
+            mState = STATE_STARTED_PAUSED;
+        } else {
+            mState = STATE_STARTED;
+        }
     }
 
     @NonNull
     @Override
     protected Callback wrapCallbackForStart(@NonNull Callback callback) {
-        return new CompositeCallback(createALSCallback(), callback);
+        return new CompositeCallback(mALSProbeCallback, callback);
+    }
+
+    @Override
+    protected void handleLifecycleAfterAuth(boolean authenticated) {
+        if (authenticated) {
+            mCallback.onClientFinished(this, true /* success */);
+        }
     }
 
     @Override
@@ -85,8 +110,10 @@
         super.onAuthenticated(identifier, authenticated, token);
 
         if (authenticated) {
+            mState = STATE_STOPPED;
             UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
-            mCallback.onClientFinished(this, true /* success */);
+        } else {
+            mState = STATE_STARTED_PAUSED;
         }
     }
 
@@ -143,7 +170,11 @@
     @Override
     public void onPointerDown(int x, int y, float minor, float major) {
         try {
+            mIsPointerDown = true;
+            mState = STATE_STARTED;
+            mALSProbeCallback.getProbe().enable();
             getFreshDaemon().onPointerDown(0 /* pointerId */, x, y, minor, major);
+
             if (getListener() != null) {
                 getListener().onUdfpsPointerDown(getSensorId());
             }
@@ -155,7 +186,11 @@
     @Override
     public void onPointerUp() {
         try {
+            mIsPointerDown = false;
+            mState = STATE_STARTED_PAUSED;
+            mALSProbeCallback.getProbe().disable();
             getFreshDaemon().onPointerUp(0 /* pointerId */);
+
             if (getListener() != null) {
                 getListener().onUdfpsPointerUp(getSensorId());
             }
@@ -165,6 +200,11 @@
     }
 
     @Override
+    public boolean isPointerDown() {
+        return mIsPointerDown;
+    }
+
+    @Override
     public void onUiReady() {
         try {
             getFreshDaemon().onUiReady();
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
index a211bb5..c420c5c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
@@ -55,6 +55,7 @@
     private final @FingerprintManager.EnrollReason int mEnrollReason;
     @Nullable private ICancellationSignal mCancellationSignal;
     private final int mMaxTemplatesPerUser;
+    private boolean mIsPointerDown;
 
     FingerprintEnrollClient(@NonNull Context context,
             @NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token,
@@ -83,7 +84,7 @@
     @NonNull
     @Override
     protected Callback wrapCallbackForStart(@NonNull Callback callback) {
-        return new CompositeCallback(createALSCallback(), callback);
+        return new CompositeCallback(createALSCallback(true /* startWithClient */), callback);
     }
 
     @Override
@@ -167,6 +168,7 @@
     @Override
     public void onPointerDown(int x, int y, float minor, float major) {
         try {
+            mIsPointerDown = true;
             getFreshDaemon().onPointerDown(0 /* pointerId */, x, y, minor, major);
         } catch (RemoteException e) {
             Slog.e(TAG, "Unable to send pointer down", e);
@@ -176,6 +178,7 @@
     @Override
     public void onPointerUp() {
         try {
+            mIsPointerDown = false;
             getFreshDaemon().onPointerUp(0 /* pointerId */);
         } catch (RemoteException e) {
             Slog.e(TAG, "Unable to send pointer up", e);
@@ -183,6 +186,11 @@
     }
 
     @Override
+    public boolean isPointerDown() {
+        return mIsPointerDown;
+    }
+
+    @Override
     public void onUiReady() {
         try {
             getFreshDaemon().onUiReady();
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
index a6385a5..2f5b5c7 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
@@ -622,7 +622,7 @@
                     opPackageName, cookie, false /* requireConfirmation */,
                     mSensorProperties.sensorId, isStrongBiometric, statsClient,
                     mTaskStackListener, mLockoutTracker, mUdfpsOverlayController,
-                    allowBackgroundAuthentication);
+                    allowBackgroundAuthentication, mSensorProperties);
             mScheduler.scheduleClientMonitor(client, fingerprintStateCallback);
         });
     }
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
index 312c52c..24ce867 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
@@ -138,7 +138,8 @@
 
         TestableBiometricScheduler(@NonNull String tag,
                 @Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
-            super(tag, BiometricScheduler.SENSOR_TYPE_FP_OTHER, gestureAvailabilityDispatcher);
+            super(tag, BiometricScheduler.SENSOR_TYPE_FP_OTHER,
+                    gestureAvailabilityDispatcher);
             mInternalCallback = new TestableInternalCallback();
         }
 
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
index 40e3bc3..5c9a764 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
@@ -25,6 +25,7 @@
 import android.hardware.biometrics.BiometricFingerprintConstants;
 import android.hardware.biometrics.BiometricsProtoEnums;
 import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
+import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
 import android.hardware.fingerprint.IUdfpsOverlayController;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -52,6 +53,10 @@
 
     private final LockoutFrameworkImpl mLockoutFrameworkImpl;
     @Nullable private final IUdfpsOverlayController mUdfpsOverlayController;
+    @NonNull private final FingerprintSensorPropertiesInternal mSensorProps;
+    @NonNull private final CallbackWithProbe<Probe> mALSProbeCallback;
+
+    private boolean mIsPointerDown;
 
     FingerprintAuthenticationClient(@NonNull Context context,
             @NonNull LazyDaemon<IBiometricsFingerprint> lazyDaemon, @NonNull IBinder token,
@@ -61,19 +66,34 @@
             @NonNull TaskStackListener taskStackListener,
             @NonNull LockoutFrameworkImpl lockoutTracker,
             @Nullable IUdfpsOverlayController udfpsOverlayController,
-            boolean allowBackgroundAuthentication) {
+            boolean allowBackgroundAuthentication,
+            @NonNull FingerprintSensorPropertiesInternal sensorProps) {
         super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
                 owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
                 BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener,
                 lockoutTracker, allowBackgroundAuthentication, true /* shouldVibrate */);
         mLockoutFrameworkImpl = lockoutTracker;
         mUdfpsOverlayController = udfpsOverlayController;
+        mSensorProps = sensorProps;
+        mALSProbeCallback = createALSCallback(false /* startWithClient */);
+    }
+
+    @Override
+    public void start(@NonNull Callback callback) {
+        super.start(callback);
+
+        if (mSensorProps.isAnyUdfpsType()) {
+            // UDFPS requires user to touch before becoming "active"
+            mState = STATE_STARTED_PAUSED;
+        } else {
+            mState = STATE_STARTED;
+        }
     }
 
     @NonNull
     @Override
     protected Callback wrapCallbackForStart(@NonNull Callback callback) {
-        return new CompositeCallback(createALSCallback(), callback);
+        return new CompositeCallback(mALSProbeCallback, callback);
     }
 
     @Override
@@ -87,10 +107,11 @@
         // Note that authentication doesn't end when Authenticated == false
 
         if (authenticated) {
+            mState = STATE_STOPPED;
             resetFailedAttempts(getTargetUserId());
             UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
-            mCallback.onClientFinished(this, true /* success */);
         } else {
+            mState = STATE_STARTED_PAUSED;
             final @LockoutTracker.LockoutMode int lockoutMode =
                     mLockoutFrameworkImpl.getLockoutModeForUser(getTargetUserId());
             if (lockoutMode != LockoutTracker.LOCKOUT_NONE) {
@@ -124,6 +145,13 @@
     }
 
     @Override
+    protected void handleLifecycleAfterAuth(boolean authenticated) {
+        if (authenticated) {
+            mCallback.onClientFinished(this, true /* success */);
+        }
+    }
+
+    @Override
     public @LockoutTracker.LockoutMode int handleFailedAttempt(int userId) {
         mLockoutFrameworkImpl.addFailedAttemptForUser(userId);
         return super.handleFailedAttempt(userId);
@@ -160,7 +188,11 @@
 
     @Override
     public void onPointerDown(int x, int y, float minor, float major) {
+        mIsPointerDown = true;
+        mState = STATE_STARTED;
+        mALSProbeCallback.getProbe().enable();
         UdfpsHelper.onFingerDown(getFreshDaemon(), x, y, minor, major);
+
         if (getListener() != null) {
             try {
                 getListener().onUdfpsPointerDown(getSensorId());
@@ -172,7 +204,11 @@
 
     @Override
     public void onPointerUp() {
+        mIsPointerDown = false;
+        mState = STATE_STARTED_PAUSED;
+        mALSProbeCallback.getProbe().disable();
         UdfpsHelper.onFingerUp(getFreshDaemon());
+
         if (getListener() != null) {
             try {
                 getListener().onUdfpsPointerUp(getSensorId());
@@ -183,6 +219,11 @@
     }
 
     @Override
+    public boolean isPointerDown() {
+        return mIsPointerDown;
+    }
+
+    @Override
     public void onUiReady() {
         // Unsupported in HIDL.
     }
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
index af1e49d..8e73ee6b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
@@ -49,6 +49,7 @@
 
     private final boolean mIsStrongBiometric;
     @Nullable private final IUdfpsOverlayController mUdfpsOverlayController;
+    private boolean mIsPointerDown;
 
     public FingerprintDetectClient(@NonNull Context context,
             @NonNull LazyDaemon<IBiometricsFingerprint> lazyDaemon, @NonNull IBinder token,
@@ -99,15 +100,22 @@
 
     @Override
     public void onPointerDown(int x, int y, float minor, float major) {
+        mIsPointerDown = true;
         UdfpsHelper.onFingerDown(getFreshDaemon(), x, y, minor, major);
     }
 
     @Override
     public void onPointerUp() {
+        mIsPointerDown = false;
         UdfpsHelper.onFingerUp(getFreshDaemon());
     }
 
     @Override
+    public boolean isPointerDown() {
+        return mIsPointerDown;
+    }
+
+    @Override
     public void onUiReady() {
         // Unsupported in HIDL.
     }
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
index eba445f..dc70534 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
@@ -52,6 +52,7 @@
     @Nullable private final IUdfpsOverlayController mUdfpsOverlayController;
     @Nullable private final ISidefpsController mSidefpsController;
     private final @FingerprintManager.EnrollReason int mEnrollReason;
+    private boolean mIsPointerDown;
 
     FingerprintEnrollClient(@NonNull Context context,
             @NonNull LazyDaemon<IBiometricsFingerprint> lazyDaemon, @NonNull IBinder token,
@@ -76,7 +77,7 @@
     @NonNull
     @Override
     protected Callback wrapCallbackForStart(@NonNull Callback callback) {
-        return new CompositeCallback(createALSCallback(), callback);
+        return new CompositeCallback(createALSCallback(true /* startWithClient */), callback);
     }
 
     @Override
@@ -157,15 +158,22 @@
 
     @Override
     public void onPointerDown(int x, int y, float minor, float major) {
+        mIsPointerDown = true;
         UdfpsHelper.onFingerDown(getFreshDaemon(), x, y, minor, major);
     }
 
     @Override
     public void onPointerUp() {
+        mIsPointerDown = false;
         UdfpsHelper.onFingerUp(getFreshDaemon());
     }
 
     @Override
+    public boolean isPointerDown() {
+        return mIsPointerDown;
+    }
+
+    @Override
     public void onUiReady() {
         // Unsupported in HIDL.
     }
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index b6d65197..59f536c 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -96,7 +96,6 @@
  */
 final class DisplayPowerController implements AutomaticBrightnessController.Callbacks,
         DisplayWhiteBalanceController.Callbacks {
-    private static final String TAG = "DisplayPowerController";
     private static final String SCREEN_ON_BLOCKED_TRACE_NAME = "Screen on blocked";
     private static final String SCREEN_OFF_BLOCKED_TRACE_NAME = "Screen off blocked";
 
@@ -149,6 +148,8 @@
     private static final int REPORTED_TO_POLICY_SCREEN_ON = 2;
     private static final int REPORTED_TO_POLICY_SCREEN_TURNING_OFF = 3;
 
+    private final String TAG;
+
     private final Object mLock = new Object();
 
     private final Context mContext;
@@ -450,6 +451,7 @@
             Runnable onBrightnessChangeRunnable) {
         mLogicalDisplay = logicalDisplay;
         mDisplayId = mLogicalDisplay.getDisplayIdLocked();
+        TAG = "DisplayPowerController[" + mDisplayId + "]";
         mDisplayDevice = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
         mUniqueDisplayId = logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId();
         mHandler = new DisplayControllerHandler(handler.getLooper());
@@ -776,7 +778,7 @@
         setUpAutoBrightness(mContext.getResources(), mHandler);
         reloadReduceBrightColours();
         mHbmController.resetHbmData(info.width, info.height, token,
-                mDisplayDeviceConfig.getHighBrightnessModeData(), mBrightnessSetting);
+                mDisplayDeviceConfig.getHighBrightnessModeData());
     }
 
     private void sendUpdatePowerState() {
@@ -966,7 +968,6 @@
         final boolean mustNotify;
         final int previousPolicy;
         boolean mustInitialize = false;
-        boolean shouldSaveBrightnessInfo = true;
         int brightnessAdjustmentFlags = 0;
         mBrightnessReasonTemp.set(null);
         synchronized (mLock) {
@@ -1097,7 +1098,6 @@
         if (state == Display.STATE_OFF) {
             brightnessState = PowerManager.BRIGHTNESS_OFF_FLOAT;
             mBrightnessReasonTemp.setReason(BrightnessReason.REASON_SCREEN_OFF);
-            shouldSaveBrightnessInfo = false;
         }
 
         // Always use the VR brightness when in the VR state.
@@ -1215,6 +1215,10 @@
                 brightnessAdjustmentFlags = 0;
             }
         } else {
+            // Any non-auto-brightness values such as override or temporary should still be subject
+            // to clamping so that they don't go beyond the current max as specified by HBM
+            // Controller.
+            brightnessState = clampScreenBrightness(brightnessState);
             mAppliedAutoBrightness = false;
             brightnessAdjustmentFlags = 0;
         }
@@ -1222,9 +1226,8 @@
         // Use default brightness when dozing unless overridden.
         if ((Float.isNaN(brightnessState))
                 && Display.isDozeState(state)) {
-            brightnessState = mScreenBrightnessDozeConfig;
+            brightnessState = clampScreenBrightness(mScreenBrightnessDozeConfig);
             mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE_DEFAULT);
-            shouldSaveBrightnessInfo = false;
         }
 
         // Apply manual brightness.
@@ -1239,12 +1242,13 @@
             mBrightnessReasonTemp.setReason(BrightnessReason.REASON_MANUAL);
         }
 
-        // Save out the brightness info now that the brightness state for this iteration has been
-        // finalized and before we send out notifications about the brightness changing.
-        if (shouldSaveBrightnessInfo) {
-            saveBrightnessInfo(brightnessState);
-
-        }
+        // The current brightness to use has been calculated at this point (minus the adjustments
+        // like low-power and dim), and HbmController should be notified so that it can accurately
+        // calculate HDR or HBM levels. We specifically do it here instead of having HbmController
+        // listen to the brightness setting because certain brightness sources (just as an app
+        // override) are not saved to the setting, but should be reflected in HBM
+        // calculations.
+        mHbmController.onBrightnessChanged(brightnessState);
 
         if (updateScreenBrightnessSetting) {
             // Tell the rest of the system about the new brightness in case we had to change it
@@ -1255,6 +1259,10 @@
             putScreenBrightnessSetting(brightnessState, /* updateCurrent */ true);
         }
 
+        // We save the brightness info *after* the brightness setting has been changed so that
+        // the brightness info reflects the latest value.
+        saveBrightnessInfo(getScreenBrightnessSetting());
+
         // Apply dimming by at least some minimum amount when user activity
         // timeout is about to expire.
         if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
@@ -1531,7 +1539,7 @@
                     mHandler.post(mOnBrightnessChangeRunnable);
                     // TODO(b/192258832): Switch the HBMChangeCallback to a listener pattern.
                     mAutomaticBrightnessController.update();
-                }, mContext, mBrightnessSetting);
+                }, mContext);
     }
 
     private void blockScreenOn() {
@@ -2334,7 +2342,7 @@
             try {
                 // TODO(brightnessfloat): change BatteryStats to use float
                 mBatteryStats.noteScreenBrightness(BrightnessSynchronizer.brightnessFloatToInt(
-                        brightness));
+                        brightness, null));
             } catch (RemoteException e) {
                 // same process
             }
diff --git a/services/core/java/com/android/server/display/HighBrightnessModeController.java b/services/core/java/com/android/server/display/HighBrightnessModeController.java
index 645131c..2791f6a 100644
--- a/services/core/java/com/android/server/display/HighBrightnessModeController.java
+++ b/services/core/java/com/android/server/display/HighBrightnessModeController.java
@@ -37,7 +37,6 @@
 import android.view.SurfaceControlHdrLayerInfoListener;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.display.BrightnessSetting.BrightnessSettingListener;
 import com.android.server.display.DisplayDeviceConfig.HighBrightnessModeData;
 import com.android.server.display.DisplayManagerService.Clock;
 
@@ -70,7 +69,6 @@
     private final Context mContext;
     private final SettingsObserver mSettingsObserver;
     private final Injector mInjector;
-    private final BrightnessSettingListener mBrightnessSettingListener = this::onBrightnessChanged;
 
     private HdrListener mHdrListener;
     private HighBrightnessModeData mHbmData;
@@ -86,7 +84,6 @@
     private boolean mIsBlockedByLowPowerMode = false;
     private int mWidth;
     private int mHeight;
-    private BrightnessSetting mBrightnessSetting;
     private float mAmbientLux;
 
     /**
@@ -103,30 +100,30 @@
 
     HighBrightnessModeController(Handler handler, int width, int height, IBinder displayToken,
             float brightnessMin, float brightnessMax, HighBrightnessModeData hbmData,
-            Runnable hbmChangeCallback, Context context, BrightnessSetting brightnessSetting) {
+            Runnable hbmChangeCallback, Context context) {
         this(new Injector(), handler, width, height, displayToken, brightnessMin, brightnessMax,
-                hbmData, hbmChangeCallback, context, brightnessSetting);
+                hbmData, hbmChangeCallback, context);
     }
 
     @VisibleForTesting
     HighBrightnessModeController(Injector injector, Handler handler, int width, int height,
             IBinder displayToken, float brightnessMin, float brightnessMax,
             HighBrightnessModeData hbmData, Runnable hbmChangeCallback,
-            Context context, BrightnessSetting brightnessSetting) {
+            Context context) {
         mInjector = injector;
         mContext = context;
         mClock = injector.getClock();
         mHandler = handler;
+        mBrightness = brightnessMin;
         mBrightnessMin = brightnessMin;
         mBrightnessMax = brightnessMax;
-        mBrightness = brightnessSetting.getBrightness();
         mHbmChangeCallback = hbmChangeCallback;
         mSkinThermalStatusObserver = new SkinThermalStatusObserver(mInjector, mHandler);
         mSettingsObserver = new SettingsObserver(mHandler);
         mRecalcRunnable = this::recalculateTimeAllowance;
         mHdrListener = new HdrListener();
 
-        resetHbmData(width, height, displayToken, hbmData, brightnessSetting);
+        resetHbmData(width, height, displayToken, hbmData);
     }
 
     void setAutoBrightnessEnabled(boolean isEnabled) {
@@ -185,7 +182,6 @@
         }
     }
 
-    @VisibleForTesting
     void onBrightnessChanged(float brightness) {
         if (!deviceSupportsHbm()) {
             return;
@@ -224,12 +220,11 @@
         mSettingsObserver.stopObserving();
     }
 
-    void resetHbmData(int width, int height, IBinder displayToken, HighBrightnessModeData hbmData,
-            BrightnessSetting brightnessSetting) {
+    void resetHbmData(int width, int height, IBinder displayToken, HighBrightnessModeData hbmData) {
         mWidth = width;
         mHeight = height;
         mHbmData = hbmData;
-        resetBrightnessSetting(brightnessSetting);
+
         unregisterHdrListener();
         mSkinThermalStatusObserver.stopObserving();
         mSettingsObserver.stopObserving();
@@ -261,9 +256,12 @@
         pw.println("  mBrightness=" + mBrightness);
         pw.println("  mCurrentMin=" + getCurrentBrightnessMin());
         pw.println("  mCurrentMax=" + getCurrentBrightnessMax());
-        pw.println("  mHbmMode=" + BrightnessInfo.hbmToString(mHbmMode));
+        pw.println("  mHbmMode=" + BrightnessInfo.hbmToString(mHbmMode)
+                + (mHbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
+                ? "(" + getHdrBrightnessValue() + ")" : ""));
         pw.println("  mHbmData=" + mHbmData);
-        pw.println("  mAmbientLux=" + mAmbientLux);
+        pw.println("  mAmbientLux=" + mAmbientLux
+                + (mIsAutoBrightnessEnabled ? "" : " (old/invalid)"));
         pw.println("  mIsInAllowedAmbientRange=" + mIsInAllowedAmbientRange);
         pw.println("  mIsAutoBrightnessEnabled=" + mIsAutoBrightnessEnabled);
         pw.println("  mIsHdrLayerPresent=" + mIsHdrLayerPresent);
@@ -301,16 +299,6 @@
         return event.startTimeMillis;
     }
 
-    private void resetBrightnessSetting(BrightnessSetting brightnessSetting) {
-        if (mBrightnessSetting != null) {
-            mBrightnessSetting.unregisterListener(mBrightnessSettingListener);
-        }
-        mBrightnessSetting = brightnessSetting;
-        if (mBrightnessSetting != null) {
-            mBrightnessSetting.registerListener(mBrightnessSettingListener);
-        }
-    }
-
     private boolean isCurrentlyAllowed() {
         // Returns true if HBM is allowed (above the ambient lux threshold) and there's still
         // time within the current window for additional HBM usage. We return false if there is an
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index f953cc8..24d29d3 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -795,11 +795,12 @@
                             mBacklightAdapter.setBacklight(sdrBacklight, sdrNits, backlight, nits);
                             Trace.traceCounter(Trace.TRACE_TAG_POWER,
                                     "ScreenBrightness",
-                                    BrightnessSynchronizer.brightnessFloatToInt(brightnessState));
+                                    BrightnessSynchronizer.brightnessFloatToInt(
+                                            brightnessState, null));
                             Trace.traceCounter(Trace.TRACE_TAG_POWER,
                                     "SdrScreenBrightness",
                                     BrightnessSynchronizer.brightnessFloatToInt(
-                                            sdrBrightnessState));
+                                            sdrBrightnessState, null));
                         } finally {
                             Trace.traceEnd(Trace.TRACE_TAG_POWER);
                         }
diff --git a/services/core/java/com/android/server/lights/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java
index 91f14de..bebe6ed 100644
--- a/services/core/java/com/android/server/lights/LightsService.java
+++ b/services/core/java/com/android/server/lights/LightsService.java
@@ -293,7 +293,7 @@
                             + ": brightness=" + brightness);
                     return;
                 }
-                int brightnessInt = BrightnessSynchronizer.brightnessFloatToInt(brightness);
+                int brightnessInt = BrightnessSynchronizer.brightnessFloatToInt(brightness, null);
                 int color = brightnessInt & 0x000000ff;
                 color = 0xff000000 | (color << 16) | (color << 8) | color;
                 setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index c0b8648..7d5b7e5 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -2485,6 +2485,7 @@
 
     private void removeUser(int userId, boolean unknownUser) {
         Slog.i(TAG, "RemoveUser: " + userId);
+        removeBiometricsForUser(userId);
         mSpManager.removeUser(userId);
         mStrongAuth.removeUser(userId);
 
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 00ef97d..5429484 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -2252,12 +2252,29 @@
                     (params.installFlags & PackageManager.INSTALL_DISABLE_ALLOWED_APEX_UPDATE_CHECK)
                         == 0;
             synchronized (mLock) {
-                if (checkApexUpdateAllowed && !isApexUpdateAllowed(mPackageName)) {
+                if (checkApexUpdateAllowed && !isApexUpdateAllowed(mPackageName,
+                          mInstallSource.installerPackageName)) {
                     onSessionValidationFailure(PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE,
-                            "Update of APEX package " + mPackageName + " is not allowed");
+                            "Update of APEX package " + mPackageName + " is not allowed for "
+                                    + mInstallSource.installerPackageName);
                     return;
                 }
             }
+
+            if (!params.isStaged) {
+                // For non-staged APEX installs also check if there is a staged session that
+                // contains the same APEX. If that's the case, we should fail this session.
+                synchronized (mLock) {
+                    int sessionId = mStagingManager.getSessionIdByPackageName(mPackageName);
+                    if (sessionId != -1) {
+                        onSessionValidationFailure(
+                                PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE,
+                                "Staged session " + sessionId + " already contains "
+                                        + mPackageName);
+                        return;
+                    }
+                }
+            }
         }
 
         if (params.isStaged) {
@@ -2798,9 +2815,23 @@
         return sessionContains((s) -> !s.isApexSession());
     }
 
-    private boolean isApexUpdateAllowed(String apexPackageName) {
-        return mPm.getModuleInfo(apexPackageName, 0) != null
-                || SystemConfig.getInstance().getAllowedVendorApexes().contains(apexPackageName);
+    private boolean isApexUpdateAllowed(String apexPackageName, String installerPackageName) {
+        if (mPm.getModuleInfo(apexPackageName, 0) != null) {
+            final String modulesInstaller =
+                    SystemConfig.getInstance().getModulesInstallerPackageName();
+            if (modulesInstaller == null) {
+                Slog.w(TAG, "No modules installer defined");
+                return false;
+            }
+            return modulesInstaller.equals(installerPackageName);
+        }
+        final String vendorApexInstaller =
+                SystemConfig.getInstance().getAllowedVendorApexes().get(apexPackageName);
+        if (vendorApexInstaller == null) {
+            Slog.w(TAG, apexPackageName + " is not allowed to be updated");
+            return false;
+        }
+        return vendorApexInstaller.equals(installerPackageName);
     }
 
     /**
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 4ac5be2..bdbcb27 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -777,6 +777,26 @@
         }
     }
 
+    /**
+     * Returns id of a committed and non-finalized stated session that contains same
+     * {@code packageName}, or {@code -1} if no sessions have this {@code packageName} staged.
+     */
+    int getSessionIdByPackageName(@NonNull String packageName) {
+        synchronized (mStagedSessions) {
+            for (int i = 0; i < mStagedSessions.size(); i++) {
+                StagedSession stagedSession = mStagedSessions.valueAt(i);
+                if (!stagedSession.isCommitted() || stagedSession.isDestroyed()
+                        || stagedSession.isInTerminalState()) {
+                    continue;
+                }
+                if (stagedSession.getPackageName().equals(packageName)) {
+                    return stagedSession.sessionId();
+                }
+            }
+        }
+        return -1;
+    }
+
     @VisibleForTesting
     void createSession(@NonNull StagedSession sessionInfo) {
         synchronized (mStagedSessions) {
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 dfc14bd..2a5a721 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -172,6 +172,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.NoSuchElementException;
 import java.util.Objects;
 import java.util.Set;
 import java.util.WeakHashMap;
@@ -180,6 +181,7 @@
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.BiFunction;
 
@@ -219,6 +221,10 @@
     /** If the permission of the value is granted, so is the key */
     private static final Map<String, String> FULLER_PERMISSION_MAP = new HashMap<>();
 
+    /** Map of IBinder -> Running AttributionSource */
+    private static final ConcurrentHashMap<IBinder, RegisteredAttribution>
+            sRunningAttributionSources = new ConcurrentHashMap<>();
+
     static {
         FULLER_PERMISSION_MAP.put(Manifest.permission.ACCESS_COARSE_LOCATION,
                 Manifest.permission.ACCESS_FINE_LOCATION);
@@ -5555,8 +5561,15 @@
 
         @Override
         public void finishDataDelivery(int op,
+                @NonNull AttributionSourceState attributionSourceState, boolean fromDataSource) {
+            finishDataDelivery(mContext, op, attributionSourceState,
+                    fromDataSource);
+        }
+
+        private static void finishDataDelivery(Context context, int op,
                 @NonNull AttributionSourceState attributionSourceState, boolean fromDatasource) {
             Objects.requireNonNull(attributionSourceState);
+            AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
 
             if (op == AppOpsManager.OP_NONE) {
                 return;
@@ -5573,7 +5586,7 @@
                 // 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.asState() == attributionSourceState)
-                        && next != null && !current.isTrusted(mContext)) {
+                        && next != null && !current.isTrusted(context)) {
                     return;
                 }
 
@@ -5589,20 +5602,20 @@
                         ? current : next;
 
                 if (selfAccess) {
-                    final String resolvedPackageName = resolvePackageName(mContext, accessorSource);
+                    final String resolvedPackageName = resolvePackageName(context, accessorSource);
                     if (resolvedPackageName == null) {
                         return;
                     }
-                    mAppOpsManager.finishOp(accessorSource.getToken(), op,
+                    appOpsManager.finishOp(accessorSource.getToken(), op,
                             accessorSource.getUid(), resolvedPackageName,
                             accessorSource.getAttributionTag());
                 } else {
                     final AttributionSource resolvedAttributionSource =
-                            resolveAttributionSource(mContext, accessorSource);
+                            resolveAttributionSource(context, accessorSource);
                     if (resolvedAttributionSource.getPackageName() == null) {
                         return;
                     }
-                    mAppOpsManager.finishProxyOp(AppOpsManager.opToPublicName(op),
+                    appOpsManager.finishProxyOp(AppOpsManager.opToPublicName(op),
                             resolvedAttributionSource, skipCurrentFinish);
                 }
 
@@ -5610,6 +5623,11 @@
                     return;
                 }
 
+                RegisteredAttribution registered =
+                        sRunningAttributionSources.remove(current.getToken());
+                if (registered != null) {
+                    registered.unregister();
+                }
                 current = next;
             }
         }
@@ -5827,6 +5845,12 @@
                     }
                 }
 
+                if (startDataDelivery) {
+                    RegisteredAttribution registered = new RegisteredAttribution(context, op,
+                            current, fromDatasource);
+                    sRunningAttributionSources.put(current.getToken(), registered);
+                }
+
                 if (next == null || next.getNext() == null) {
                     return PermissionChecker.PERMISSION_GRANTED;
                 }
@@ -6153,4 +6177,43 @@
                     attributionSource));
         }
     }
+
+    private static final class RegisteredAttribution {
+        private final DeathRecipient mDeathRecipient;
+        private final IBinder mToken;
+        private final AtomicBoolean mFinished;
+
+        RegisteredAttribution(Context context, int op, AttributionSource source,
+                boolean fromDatasource) {
+            mFinished = new AtomicBoolean(false);
+            mDeathRecipient = () -> {
+                if (unregister()) {
+                    PermissionCheckerService
+                            .finishDataDelivery(context, op, source.asState(), fromDatasource);
+                }
+            };
+            mToken = source.getToken();
+            if (mToken != null) {
+                try {
+                    mToken.linkToDeath(mDeathRecipient, 0);
+                } catch (RemoteException e) {
+                    mDeathRecipient.binderDied();
+                }
+            }
+        }
+
+        public boolean unregister() {
+            if (mFinished.compareAndSet(false, true)) {
+                try {
+                    if (mToken != null) {
+                        mToken.unlinkToDeath(mDeathRecipient, 0);
+                    }
+                } catch (NoSuchElementException e) {
+                    // do nothing
+                }
+                return true;
+            }
+            return false;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
index f72adb60..1321873 100644
--- a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
+++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
@@ -970,6 +970,12 @@
         final long token = Binder.clearCallingIdentity();
         try {
             CompressedApexInfoList apexInfoList = getCompressedApexInfoList(packageFile);
+            if (apexInfoList == null) {
+                Log.i(TAG, "apex_info.pb not present in OTA package. "
+                            + "Assuming device doesn't support compressed"
+                            + "APEX, continueing without allocating space.");
+                return true;
+            }
             ApexManager apexManager = ApexManager.getInstance();
             apexManager.reserveSpaceForCompressedApex(apexInfoList);
             return true;
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java
index c1f8240..9999aff 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java
@@ -133,13 +133,8 @@
      * Throws a {@link SecurityException} iff the originator has permission to receive data.
      */
     void enforcePermissionsForDataDelivery(@NonNull Identity identity, @NonNull String reason) {
-        // TODO(b/186164881): remove
-        // START TEMP HACK
-        enforcePermissionForPreflight(mContext, identity, RECORD_AUDIO);
-        int hotwordOp = AppOpsManager.strOpToOp(AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD);
-        mContext.getSystemService(AppOpsManager.class).noteOpNoThrow(hotwordOp, identity.uid,
-                identity.packageName, identity.attributionTag, reason);
-        // END TEMP HACK
+        enforcePermissionForDataDelivery(mContext, identity, RECORD_AUDIO,
+                reason);
         enforcePermissionForDataDelivery(mContext, identity, CAPTURE_AUDIO_HOTWORD,
                 reason);
     }
@@ -167,8 +162,8 @@
 
     /**
      * Throws a {@link SecurityException} if originator permanently doesn't have the given
-     * permission, or a {@link ServiceSpecificException} with a {@link
-     * Status#TEMPORARY_PERMISSION_DENIED} if caller originator doesn't have the given permission.
+     * permission.
+     * Soft (temporary) denials are considered OK for preflight purposes.
      *
      * @param context    A {@link Context}, used for permission checks.
      * @param identity   The identity to check.
@@ -180,15 +175,12 @@
                 permission);
         switch (status) {
             case PermissionChecker.PERMISSION_GRANTED:
+            case PermissionChecker.PERMISSION_SOFT_DENIED:
                 return;
             case PermissionChecker.PERMISSION_HARD_DENIED:
                 throw new SecurityException(
                         String.format("Failed to obtain permission %s for identity %s", permission,
                                 ObjectPrinter.print(identity, true, 16)));
-            case PermissionChecker.PERMISSION_SOFT_DENIED:
-                throw new ServiceSpecificException(Status.TEMPORARY_PERMISSION_DENIED,
-                        String.format("Failed to obtain permission %s for identity %s", permission,
-                                ObjectPrinter.print(identity, true, 16)));
             default:
                 throw new RuntimeException("Unexpected perimission check result.");
         }
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
index 95a30c7..458eae9 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
@@ -318,6 +318,8 @@
          */
         private Map<Integer, ModelParameterRange> parameterSupport = new HashMap<>();
 
+        private RecognitionConfig mConfig;
+
         /**
          * Check that the given parameter is known to be supported for this model.
          *
@@ -369,6 +371,14 @@
         void setActivityState(Activity activity) {
             mActivityState.set(activity.ordinal());
         }
+
+        void setRecognitionConfig(@NonNull RecognitionConfig config) {
+            mConfig = config;
+        }
+
+        RecognitionConfig getRecognitionConfig() {
+            return mConfig;
+        }
     }
 
     /**
@@ -502,6 +512,7 @@
                     // Normally, we would set the state after the operation succeeds. However, since
                     // the activity state may be reset outside of the lock, we set it here first,
                     // and reset it in case of exception.
+                    modelState.setRecognitionConfig(config);
                     modelState.setActivityState(ModelState.Activity.ACTIVE);
                     mDelegate.startRecognition(modelHandle, config);
                 } catch (Exception e) {
@@ -542,6 +553,27 @@
             }
         }
 
+        private void restartIfIntercepted(int modelHandle) {
+            synchronized (SoundTriggerMiddlewareValidation.this) {
+                // State validation.
+                if (mState == ModuleStatus.DETACHED) {
+                    return;
+                }
+                ModelState modelState = mLoadedModels.get(modelHandle);
+                if (modelState == null
+                        || modelState.getActivityState() != ModelState.Activity.INTERCEPTED) {
+                    return;
+                }
+                try {
+                    mDelegate.startRecognition(modelHandle, modelState.getRecognitionConfig());
+                    modelState.setActivityState(ModelState.Activity.ACTIVE);
+                    Log.i(TAG, "Restarted intercepted model " + modelHandle);
+                } catch (Exception e) {
+                    Log.i(TAG, "Failed to restart intercepted model " + modelHandle, e);
+                }
+            }
+        }
+
         @Override
         public void forceRecognitionEvent(int modelHandle) {
             // Input validation (always valid).
@@ -753,6 +785,10 @@
                     Log.e(TAG, "Client callback exception.", e);
                     if (event.status != RecognitionStatus.FORCED) {
                         modelState.setActivityState(ModelState.Activity.INTERCEPTED);
+                        // If we failed to deliver an actual event to the client, they would never
+                        // know to restart it whenever circumstances change. Thus, we restart it
+                        // here. We do this from a separate thread to avoid any race conditions.
+                        new Thread(() -> restartIfIntercepted(modelHandle)).start();
                     }
                 }
             }
@@ -780,6 +816,10 @@
                     Log.e(TAG, "Client callback exception.", e);
                     if (event.common.status != RecognitionStatus.FORCED) {
                         modelState.setActivityState(ModelState.Activity.INTERCEPTED);
+                        // If we failed to deliver an actual event to the client, they would never
+                        // know to restart it whenever circumstances change. Thus, we restart it
+                        // here. We do this from a separate thread to avoid any race conditions.
+                        new Thread(() -> restartIfIntercepted(modelHandle)).start();
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 8658334..36a854e 100755
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -209,10 +209,11 @@
     private void registerBroadcastReceivers() {
         PackageMonitor monitor = new PackageMonitor() {
             private void buildTvInputList(String[] packages) {
+                int userId = getChangingUserId();
                 synchronized (mLock) {
-                    if (mCurrentUserId == getChangingUserId()) {
-                        buildTvInputListLocked(mCurrentUserId, packages);
-                        buildTvContentRatingSystemListLocked(mCurrentUserId);
+                    if (mCurrentUserId == userId || mRunningProfiles.contains(userId)) {
+                        buildTvInputListLocked(userId, packages);
+                        buildTvContentRatingSystemListLocked(userId);
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 3c0a05b..450257f 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -195,6 +195,7 @@
 
     @VisibleForTesting(visibility = Visibility.PRIVATE)
     static final int SAFEMODE_TIMEOUT_SECONDS = 30;
+    private static final int SAFEMODE_TIMEOUT_SECONDS_TEST_MODE = 10;
 
     private interface EventInfo {}
 
@@ -1082,7 +1083,9 @@
                 createScheduledAlarm(
                         SAFEMODE_TIMEOUT_ALARM,
                         delayedMessage,
-                        TimeUnit.SECONDS.toMillis(SAFEMODE_TIMEOUT_SECONDS));
+                        mVcnContext.isInTestMode()
+                                ? TimeUnit.SECONDS.toMillis(SAFEMODE_TIMEOUT_SECONDS_TEST_MODE)
+                                : TimeUnit.SECONDS.toMillis(SAFEMODE_TIMEOUT_SECONDS));
     }
 
     private void cancelSafeModeAlarm() {
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 0f6a718..494f496 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -933,9 +933,11 @@
         // This will avoid any races with other operations that modify the ActivityRecord.
         final TransitionInfoSnapshot infoSnapshot = new TransitionInfoSnapshot(info);
         if (info.isInterestingToLoggerAndObserver()) {
+            final long timestamp = info.mTransitionStartTimeNs;
+            final long uptime = info.mTransitionDeviceUptimeMs;
+            final int transitionDelay = info.mCurrentTransitionDelayMs;
             mLoggerHandler.post(() -> logAppTransition(
-                    info.mTransitionDeviceUptimeMs, info.mCurrentTransitionDelayMs,
-                    infoSnapshot, isHibernating));
+                    timestamp, uptime, transitionDelay, infoSnapshot, isHibernating));
         }
         mLoggerHandler.post(() -> logAppDisplayed(infoSnapshot));
         if (info.mPendingFullyDrawn != null) {
@@ -946,8 +948,8 @@
     }
 
     // This gets called on another thread without holding the activity manager lock.
-    private void logAppTransition(long transitionDeviceUptimeMs, int currentTransitionDelayMs,
-            TransitionInfoSnapshot info, boolean isHibernating) {
+    private void logAppTransition(long transitionStartTimeNs, long transitionDeviceUptimeMs,
+            int currentTransitionDelayMs, TransitionInfoSnapshot info, boolean isHibernating) {
         final LogMaker builder = new LogMaker(APP_TRANSITION);
         builder.setPackageName(info.packageName);
         builder.setType(info.type);
@@ -998,7 +1000,7 @@
                 info.launchedActivityName,
                 info.launchedActivityLaunchedFromPackage,
                 isInstantApp,
-                transitionDeviceUptimeMs,
+                0 /* deprecated transitionDeviceUptimeMs */,
                 info.reason,
                 currentTransitionDelayMs,
                 info.startingWindowDelayMs,
@@ -1012,7 +1014,8 @@
                 isHibernating,
                 isIncremental,
                 isLoading,
-                info.launchedActivityName.hashCode());
+                info.launchedActivityName.hashCode(),
+                TimeUnit.NANOSECONDS.toMillis(transitionStartTimeNs));
 
         if (DEBUG_METRICS) {
             Slog.i(TAG, String.format("APP_START_OCCURRED(%s, %s, %s, %s, %s)",
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 22bff21..308df2f 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -5033,6 +5033,12 @@
     void notifyAppStopped() {
         ProtoLog.v(WM_DEBUG_ADD_REMOVE, "notifyAppStopped: %s", this);
         mAppStopped = true;
+        // This is to fix the edge case that auto-enter-pip is finished in Launcher but app calls
+        // setAutoEnterEnabled(false) and transitions to STOPPED state, see b/191930787.
+        // Clear any surface transactions and content overlay in this case.
+        if (task != null && task.mLastRecentsAnimationTransaction != null) {
+            task.clearLastRecentsAnimationTransaction(true /* forceRemoveOverlay */);
+        }
         // Reset the last saved PiP snap fraction on app stop.
         mDisplayContent.mPinnedTaskController.onActivityHidden(mActivityComponent);
         mDisplayContent.mUnknownAppVisibilityController.appRemovedOrHidden(this);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index d3d1c1c..e3459a1 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -17,6 +17,7 @@
 package com.android.server.wm;
 
 import static android.Manifest.permission.ACTIVITY_EMBEDDING;
+import static android.Manifest.permission.CAMERA;
 import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
 import static android.Manifest.permission.START_ANY_ACTIVITY;
 import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
@@ -88,6 +89,7 @@
 import android.app.ActivityManagerInternal;
 import android.app.ActivityOptions;
 import android.app.AppOpsManager;
+import android.app.AppOpsManagerInternal;
 import android.app.IActivityClientController;
 import android.app.ProfilerInfo;
 import android.app.ResultInfo;
@@ -108,6 +110,8 @@
 import android.content.pm.UserInfo;
 import android.content.res.Configuration;
 import android.graphics.Rect;
+import android.hardware.SensorPrivacyManager;
+import android.hardware.SensorPrivacyManagerInternal;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -141,6 +145,7 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.function.pooled.PooledConsumer;
 import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.server.LocalServices;
 import com.android.server.am.ActivityManagerService;
 import com.android.server.am.UserState;
 import com.android.server.wm.ActivityMetricsLogger.LaunchingState;
@@ -1221,6 +1226,24 @@
 
         if (getAppOpsManager().noteOpNoThrow(opCode, callingUid,
                 callingPackage, callingFeatureId, "") != AppOpsManager.MODE_ALLOWED) {
+            if (CAMERA.equals(permission)) {
+                SensorPrivacyManagerInternal spmi =
+                        LocalServices.getService(SensorPrivacyManagerInternal.class);
+
+                final UserHandle user = UserHandle.getUserHandleForUid(callingUid);
+                final boolean cameraPrivacyEnabled = spmi.isSensorPrivacyEnabled(
+                        user.getIdentifier(), SensorPrivacyManager.Sensors.CAMERA);
+                if (cameraPrivacyEnabled) {
+                    AppOpsManagerInternal aomi = LocalServices.getService(
+                            AppOpsManagerInternal.class);
+                    int numCameraRestrictions = aomi.getOpRestrictionCount(
+                            AppOpsManager.OP_CAMERA, user, callingPackage, null);
+                    if (numCameraRestrictions == 1) {
+                        // Only restricted by the toggles, do not restrict
+                        return ACTIVITY_RESTRICTION_NONE;
+                    }
+                }
+            }
             return ACTIVITY_RESTRICTION_APPOP;
         }
 
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index 3dea686..c869ec6 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -362,8 +362,10 @@
             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Wallpaper animation!");
             switch (firstTransit) {
                 case TRANSIT_OPEN:
+                case TRANSIT_TO_FRONT:
                     return TRANSIT_OLD_WALLPAPER_INTRA_OPEN;
                 case TRANSIT_CLOSE:
+                case TRANSIT_TO_BACK:
                     return TRANSIT_OLD_WALLPAPER_INTRA_CLOSE;
             }
         } else if (oldWallpaper != null && !openingApps.isEmpty()
diff --git a/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java b/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
index 35add12..f61cc94 100644
--- a/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
+++ b/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
@@ -26,6 +26,7 @@
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.util.Slog;
 import android.view.SurfaceControl;
 import android.window.DisplayAreaAppearedInfo;
 import android.window.IDisplayAreaOrganizer;
@@ -49,7 +50,8 @@
 
     final ActivityTaskManagerService mService;
     private final WindowManagerGlobalLock mGlobalLock;
-    private final HashMap<Integer, IDisplayAreaOrganizer> mOrganizersByFeatureIds = new HashMap();
+    private final HashMap<Integer, DisplayAreaOrganizerState> mOrganizersByFeatureIds =
+            new HashMap();
 
     private class DeathRecipient implements IBinder.DeathRecipient {
         int mFeature;
@@ -63,12 +65,41 @@
         @Override
         public void binderDied() {
             synchronized (mGlobalLock) {
-                mOrganizersByFeatureIds.remove(mFeature);
-                removeOrganizer(mOrganizer);
+                mOrganizersByFeatureIds.remove(mFeature).destroy();
             }
         }
     }
 
+    private class DisplayAreaOrganizerState {
+        private final IDisplayAreaOrganizer mOrganizer;
+        private final DeathRecipient mDeathRecipient;
+
+        DisplayAreaOrganizerState(IDisplayAreaOrganizer organizer, int feature) {
+            mOrganizer = organizer;
+            mDeathRecipient = new DeathRecipient(organizer, feature);
+            try {
+                organizer.asBinder().linkToDeath(mDeathRecipient, 0);
+            } catch (RemoteException e) {
+                // Oh well...
+            }
+        }
+
+        void destroy() {
+            IBinder organizerBinder = mOrganizer.asBinder();
+            mService.mRootWindowContainer.forAllDisplayAreas((da) -> {
+                if (da.mOrganizer != null && da.mOrganizer.asBinder().equals(organizerBinder)) {
+                    if (da.isTaskDisplayArea() && da.asTaskDisplayArea().mCreatedByOrganizer) {
+                        // Delete the organizer created TDA when unregister.
+                        deleteTaskDisplayArea(da.asTaskDisplayArea());
+                    } else {
+                        da.setOrganizer(null);
+                    }
+                }
+            });
+            organizerBinder.unlinkToDeath(mDeathRecipient, 0);
+        }
+    }
+
     DisplayAreaOrganizerController(ActivityTaskManagerService atm) {
         mService = atm;
         mGlobalLock = atm.mGlobalLock;
@@ -80,7 +111,8 @@
 
     @Nullable
     IDisplayAreaOrganizer getOrganizerByFeature(int featureId) {
-        return mOrganizersByFeatureIds.get(featureId);
+        final DisplayAreaOrganizerState state = mOrganizersByFeatureIds.get(featureId);
+        return state != null ? state.mOrganizer : null;
     }
 
     @Override
@@ -94,17 +126,18 @@
                 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Register display organizer=%s uid=%d",
                         organizer.asBinder(), uid);
                 if (mOrganizersByFeatureIds.get(feature) != null) {
-                    throw new IllegalStateException(
-                            "Replacing existing organizer currently unsupported");
+                    if (mOrganizersByFeatureIds.get(feature).mOrganizer.asBinder()
+                            .isBinderAlive()) {
+                        throw new IllegalStateException(
+                                "Replacing existing organizer currently unsupported");
+                    }
+
+                    mOrganizersByFeatureIds.remove(feature).destroy();
+                    Slog.d(TAG, "Replacing dead organizer for feature=" + feature);
                 }
 
-                final DeathRecipient dr = new DeathRecipient(organizer, feature);
-                try {
-                    organizer.asBinder().linkToDeath(dr, 0);
-                } catch (RemoteException e) {
-                    // Oh well...
-                }
-
+                final DisplayAreaOrganizerState state = new DisplayAreaOrganizerState(organizer,
+                        feature);
                 final List<DisplayAreaAppearedInfo> displayAreaInfos = new ArrayList<>();
                 mService.mRootWindowContainer.forAllDisplays(dc -> {
                     if (!dc.isTrusted()) {
@@ -120,7 +153,7 @@
                     });
                 });
 
-                mOrganizersByFeatureIds.put(feature, organizer);
+                mOrganizersByFeatureIds.put(feature, state);
                 return new ParceledListSlice<>(displayAreaInfos);
             }
         } finally {
@@ -137,9 +170,14 @@
             synchronized (mGlobalLock) {
                 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Unregister display organizer=%s uid=%d",
                         organizer.asBinder(), uid);
-                mOrganizersByFeatureIds.entrySet().removeIf(
-                        entry -> entry.getValue().asBinder() == organizer.asBinder());
-                removeOrganizer(organizer);
+                mOrganizersByFeatureIds.entrySet().removeIf((entry) -> {
+                    final boolean matches = entry.getValue().mOrganizer.asBinder()
+                            == organizer.asBinder();
+                    if (matches) {
+                        entry.getValue().destroy();
+                    }
+                    return matches;
+                });
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -190,19 +228,15 @@
                 }
 
                 final int taskDisplayAreaFeatureId = mNextTaskDisplayAreaFeatureId++;
-                final DeathRecipient dr = new DeathRecipient(organizer, taskDisplayAreaFeatureId);
-                try {
-                    organizer.asBinder().linkToDeath(dr, 0);
-                } catch (RemoteException e) {
-                    // Oh well...
-                }
+                final DisplayAreaOrganizerState state = new DisplayAreaOrganizerState(organizer,
+                        taskDisplayAreaFeatureId);
 
                 final TaskDisplayArea tda = parentRoot != null
                         ? createTaskDisplayArea(parentRoot, name, taskDisplayAreaFeatureId)
                         : createTaskDisplayArea(parentTda, name, taskDisplayAreaFeatureId);
                 final DisplayAreaAppearedInfo tdaInfo = organizeDisplayArea(organizer, tda,
                         "DisplayAreaOrganizerController.createTaskDisplayArea");
-                mOrganizersByFeatureIds.put(taskDisplayAreaFeatureId, organizer);
+                mOrganizersByFeatureIds.put(taskDisplayAreaFeatureId, state);
                 return tdaInfo;
             }
         } finally {
@@ -230,8 +264,7 @@
                                     + "TaskDisplayArea=" + taskDisplayArea);
                 }
 
-                mOrganizersByFeatureIds.remove(taskDisplayArea.mFeatureId);
-                deleteTaskDisplayArea(taskDisplayArea);
+                mOrganizersByFeatureIds.remove(taskDisplayArea.mFeatureId).destroy();
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -251,6 +284,10 @@
 
     void onDisplayAreaVanished(IDisplayAreaOrganizer organizer, DisplayArea da) {
         ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "DisplayArea vanished name=%s", da.getName());
+        if (!organizer.asBinder().isBinderAlive()) {
+            Slog.d(TAG, "Organizer died before sending onDisplayAreaVanished");
+            return;
+        }
         try {
             organizer.onDisplayAreaVanished(da.getDisplayAreaInfo());
         } catch (RemoteException e) {
@@ -267,20 +304,6 @@
         }
     }
 
-    private void removeOrganizer(IDisplayAreaOrganizer organizer) {
-        IBinder organizerBinder = organizer.asBinder();
-        mService.mRootWindowContainer.forAllDisplayAreas((da) -> {
-            if (da.mOrganizer != null && da.mOrganizer.asBinder().equals(organizerBinder)) {
-                if (da.isTaskDisplayArea() && da.asTaskDisplayArea().mCreatedByOrganizer) {
-                    // Delete the organizer created TDA when unregister.
-                    deleteTaskDisplayArea(da.asTaskDisplayArea());
-                } else {
-                    da.setOrganizer(null);
-                }
-            }
-        });
-    }
-
     private DisplayAreaAppearedInfo organizeDisplayArea(IDisplayAreaOrganizer organizer,
             DisplayArea displayArea, String callsite) {
         displayArea.setOrganizer(organizer, true /* skipDisplayAreaAppeared */);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index a72d9aa..3144c87 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1884,7 +1884,7 @@
             forAllWindows(w -> {
                 w.seamlesslyRotateIfAllowed(transaction, oldRotation, rotation, rotateSeamlessly);
             }, true /* traverseTopToBottom */);
-            mPinnedTaskController.startSeamlessRotationIfNeeded(transaction);
+            mPinnedTaskController.startSeamlessRotationIfNeeded(transaction, oldRotation, rotation);
         }
 
         mWmService.mDisplayManagerInternal.performTraversal(transaction);
diff --git a/services/core/java/com/android/server/wm/PinnedTaskController.java b/services/core/java/com/android/server/wm/PinnedTaskController.java
index 31e2ede..7e95e7d 100644
--- a/services/core/java/com/android/server/wm/PinnedTaskController.java
+++ b/services/core/java/com/android/server/wm/PinnedTaskController.java
@@ -27,13 +27,16 @@
 import android.content.ComponentName;
 import android.content.pm.ParceledListSlice;
 import android.content.res.Resources;
+import android.graphics.Insets;
 import android.graphics.Matrix;
 import android.graphics.Rect;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Log;
+import android.util.RotationUtils;
 import android.util.Slog;
 import android.view.IPinnedTaskListener;
+import android.view.Surface;
 import android.view.SurfaceControl;
 import android.window.PictureInPictureSurfaceTransaction;
 
@@ -237,7 +240,8 @@
      * rotation of display. The final surface matrix will be replaced by PiPTaskOrganizer after it
      * receives the callback of fixed rotation completion.
      */
-    void startSeamlessRotationIfNeeded(SurfaceControl.Transaction t) {
+    void startSeamlessRotationIfNeeded(SurfaceControl.Transaction t,
+            int oldRotation, int newRotation) {
         final Rect bounds = mDestRotatedBounds;
         final PictureInPictureSurfaceTransaction pipTx = mPipTransaction;
         if (bounds == null && pipTx == null) {
@@ -280,6 +284,16 @@
                 ? params.getSourceRectHint()
                 : null;
         Slog.i(TAG, "Seamless rotation PiP bounds=" + bounds + " hintRect=" + sourceHintRect);
+        final int rotationDelta = RotationUtils.deltaRotation(oldRotation, newRotation);
+        // Adjust for display cutout if applicable.
+        if (sourceHintRect != null && rotationDelta == Surface.ROTATION_270) {
+            if (pinnedTask.getDisplayCutoutInsets() != null) {
+                final int rotationBackDelta = RotationUtils.deltaRotation(newRotation, oldRotation);
+                final Rect displayCutoutInsets = RotationUtils.rotateInsets(
+                        Insets.of(pinnedTask.getDisplayCutoutInsets()), rotationBackDelta).toRect();
+                sourceHintRect.offset(displayCutoutInsets.left, displayCutoutInsets.top);
+            }
+        }
         final Rect contentBounds = sourceHintRect != null && areaBounds.contains(sourceHintRect)
                 ? sourceHintRect : areaBounds;
         final int w = contentBounds.width();
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index b6e0d8d..bd688a6 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2151,7 +2151,7 @@
                     rootTask.setLastRecentsAnimationTransaction(
                             task.mLastRecentsAnimationTransaction,
                             task.mLastRecentsAnimationOverlay);
-                    task.clearLastRecentsAnimationTransaction();
+                    task.clearLastRecentsAnimationTransaction(false /* forceRemoveOverlay */);
                 }
 
                 // There are multiple activities in the task and moving the top activity should
@@ -2206,16 +2206,17 @@
         ensureActivitiesVisible(null, 0, false /* preserveWindows */);
         resumeFocusedTasksTopActivities();
 
-        notifyActivityPipModeChanged(r);
+        notifyActivityPipModeChanged(r.getTask(), r);
     }
 
     /**
      * Notifies when an activity enters or leaves PIP mode.
      *
+     * @param task the task of {@param r}
      * @param r indicates the activity currently in PIP, can be null to indicate no activity is
      *          currently in PIP mode.
      */
-    void notifyActivityPipModeChanged(@Nullable ActivityRecord r) {
+    void notifyActivityPipModeChanged(@NonNull Task task, @Nullable ActivityRecord r) {
         final boolean inPip = r != null;
         if (inPip) {
             mService.getTaskChangeNotificationController().notifyActivityPinned(r);
@@ -2223,6 +2224,9 @@
             mService.getTaskChangeNotificationController().notifyActivityUnpinned();
         }
         mWindowManager.mPolicy.setPipVisibilityLw(inPip);
+        mWmService.mTransactionFactory.get()
+                .setTrustedOverlay(task.getSurfaceControl(), inPip)
+                .apply();
     }
 
     void executeAppTransitionForAllDisplay() {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index a113254..ced5af1 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -1437,7 +1437,7 @@
                     && (newParent == null || !newParent.inPinnedWindowingMode())) {
                 // Notify if a task from the root pinned task is being removed
                 // (or moved depending on the mode).
-                mRootWindowContainer.notifyActivityPipModeChanged(null);
+                mRootWindowContainer.notifyActivityPipModeChanged(this, null);
             }
         }
 
@@ -4105,7 +4105,7 @@
         info.positionInParent = getRelativePosition();
 
         info.pictureInPictureParams = getPictureInPictureParams(top);
-        info.displayCutoutInsets = getDisplayCutoutInsets(top);
+        info.displayCutoutInsets = top != null ? top.getDisplayCutoutInsets() : null;
         info.topActivityInfo = mReuseActivitiesReport.top != null
                 ? mReuseActivitiesReport.top.info
                 : null;
@@ -4140,16 +4140,15 @@
                 ? null : new PictureInPictureParams(topVisibleActivity.pictureInPictureArgs);
     }
 
-    private Rect getDisplayCutoutInsets(Task top) {
-        if (top == null || top.mDisplayContent == null
-                || top.getDisplayInfo().displayCutout == null) return null;
-        final WindowState w = top.getTopVisibleAppMainWindow();
+    Rect getDisplayCutoutInsets() {
+        if (mDisplayContent == null || getDisplayInfo().displayCutout == null) return null;
+        final WindowState w = getTopVisibleAppMainWindow();
         final int displayCutoutMode = w == null
                 ? WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
                 : w.getAttrs().layoutInDisplayCutoutMode;
         return (displayCutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
                 || displayCutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES)
-                ? null : top.getDisplayInfo().displayCutout.getSafeInsets();
+                ? null : getDisplayInfo().displayCutout.getSafeInsets();
     }
 
     /**
@@ -4168,7 +4167,9 @@
     StartingWindowInfo getStartingWindowInfo(ActivityRecord activity) {
         final StartingWindowInfo info = new StartingWindowInfo();
         info.taskInfo = getTaskInfo();
-
+        info.targetActivityInfo = info.taskInfo.topActivityInfo != null
+                && activity.info != info.taskInfo.topActivityInfo
+                ? activity.info : null;
         info.isKeyguardOccluded =
             mAtmService.mKeyguardController.isDisplayOccluded(DEFAULT_DISPLAY);
 
@@ -5395,7 +5396,7 @@
                     : WINDOWING_MODE_FULLSCREEN;
         }
         if (currentMode == WINDOWING_MODE_PINNED) {
-            mRootWindowContainer.notifyActivityPipModeChanged(null);
+            mRootWindowContainer.notifyActivityPipModeChanged(this, null);
         }
         if (likelyResolvedMode == WINDOWING_MODE_PINNED) {
             // In the case that we've disabled affecting the SysUI flags as a part of seamlessly
@@ -7626,7 +7627,10 @@
         mLastRecentsAnimationOverlay = overlay;
     }
 
-    void clearLastRecentsAnimationTransaction() {
+    void clearLastRecentsAnimationTransaction(boolean forceRemoveOverlay) {
+        if (forceRemoveOverlay && mLastRecentsAnimationOverlay != null) {
+            getPendingTransaction().remove(mLastRecentsAnimationOverlay);
+        }
         mLastRecentsAnimationTransaction = null;
         mLastRecentsAnimationOverlay = null;
         // reset also the crop and transform introduced by mLastRecentsAnimationTransaction
diff --git a/services/core/jni/com_android_server_biometrics_SurfaceToNativeHandleConverter.cpp b/services/core/jni/com_android_server_biometrics_SurfaceToNativeHandleConverter.cpp
index e994c03..d3d532b 100644
--- a/services/core/jni/com_android_server_biometrics_SurfaceToNativeHandleConverter.cpp
+++ b/services/core/jni/com_android_server_biometrics_SurfaceToNativeHandleConverter.cpp
@@ -16,18 +16,19 @@
 
 #define LOG_TAG "SurfaceToNativeHandleConverter"
 
-#include <nativehelper/JNIHelp.h>
-#include "jni.h"
-
-#include <android/native_window_jni.h>
 #include <android_os_NativeHandle.h>
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/android_view_Surface.h>
 #include <gui/IGraphicBufferProducer.h>
 #include <gui/Surface.h>
 #include <gui/bufferqueue/1.0/WGraphicBufferProducer.h>
+#include <utils/Log.h>
+
+#include "jni.h"
 
 namespace android {
-
 namespace {
+
 constexpr int WINDOW_HAL_TOKEN_SIZE_MAX = 256;
 
 native_handle_t* convertHalTokenToNativeHandle(const HalToken& halToken) {
@@ -54,33 +55,73 @@
     memcpy(&(nh->data[1]), halToken.data(), nhDataByteSize);
     return nh;
 }
-} // namespace
 
-using ::android::sp;
+HalToken convertNativeHandleToHalToken(native_handle_t* handle) {
+    int size = handle->data[0];
+    auto data = reinterpret_cast<uint8_t*>(&handle->data[1]);
+    HalToken halToken;
+    halToken.setToExternal(data, size);
+    return halToken;
+}
 
-static jobject convertSurfaceToNativeHandle(JNIEnv* env, jobject /* clazz */,
-                                            jobject previewSurface) {
-    if (previewSurface == nullptr) {
+jobject acquireSurfaceHandle(JNIEnv* env, jobject /* clazz */, jobject jSurface) {
+    ALOGD("%s", __func__);
+    if (jSurface == nullptr) {
+        ALOGE("%s: jSurface is null", __func__);
         return nullptr;
     }
-    ANativeWindow* previewAnw = ANativeWindow_fromSurface(env, previewSurface);
-    sp<Surface> surface = static_cast<Surface*>(previewAnw);
+
+    sp<Surface> surface = android_view_Surface_getSurface(env, jSurface);
+    if (surface == nullptr) {
+        ALOGE("%s: surface is null", __func__);
+        return nullptr;
+    }
+
     sp<IGraphicBufferProducer> igbp = surface->getIGraphicBufferProducer();
     sp<HGraphicBufferProducer> hgbp = new TWGraphicBufferProducer<HGraphicBufferProducer>(igbp);
+    // The HAL token will be closed in releaseSurfaceHandle.
     HalToken halToken;
     createHalToken(hgbp, &halToken);
+
     native_handle_t* native_handle = convertHalTokenToNativeHandle(halToken);
-    return JNativeHandle::MakeJavaNativeHandleObj(env, native_handle);
+    if (native_handle == nullptr) {
+        ALOGE("%s: native_handle is null", __func__);
+        return nullptr;
+    }
+    jobject jHandle = JNativeHandle::MakeJavaNativeHandleObj(env, native_handle);
+    native_handle_delete(native_handle);
+
+    return jHandle;
 }
 
-static const JNINativeMethod method_table[] = {
-        {"convertSurfaceToNativeHandle", "(Landroid/view/Surface;)Landroid/os/NativeHandle;",
-         reinterpret_cast<void*>(convertSurfaceToNativeHandle)},
+void releaseSurfaceHandle(JNIEnv* env, jobject /* clazz */, jobject jHandle) {
+    ALOGD("%s", __func__);
+    // Creates a native handle from a Java handle. We must call native_handle_delete when we're done
+    // with it because we created it, but we shouldn't call native_handle_close because we don't own
+    // the underlying FDs.
+    native_handle_t* handle =
+            JNativeHandle::MakeCppNativeHandle(env, jHandle, nullptr /* storage */);
+    if (handle == nullptr) {
+        ALOGE("%s: handle is null", __func__);
+        return;
+    }
+
+    HalToken token = convertNativeHandleToHalToken(handle);
+    ALOGD("%s: deleteHalToken, success: %d", __func__, deleteHalToken(token));
+    ALOGD("%s: native_handle_delete, success: %d", __func__, !native_handle_delete(handle));
+}
+
+const JNINativeMethod method_table[] = {
+        {"acquireSurfaceHandle", "(Landroid/view/Surface;)Landroid/os/NativeHandle;",
+         reinterpret_cast<void*>(acquireSurfaceHandle)},
+        {"releaseSurfaceHandle", "(Landroid/os/NativeHandle;)V",
+         reinterpret_cast<void*>(releaseSurfaceHandle)},
 };
+} // namespace
 
 int register_android_server_FaceService(JNIEnv* env) {
-    return jniRegisterNativeMethods(env, "com/android/server/biometrics/sensors/face/FaceService",
-                                    method_table, NELEM(method_table));
+    return AndroidRuntime::
+            registerNativeMethods(env, "com/android/server/biometrics/sensors/face/FaceService",
+                                  method_table, NELEM(method_table));
 }
-
-}; // namespace android
+} // namespace android
diff --git a/services/midi/java/com/android/server/midi/MidiService.java b/services/midi/java/com/android/server/midi/MidiService.java
index e31be82..d0205ae 100644
--- a/services/midi/java/com/android/server/midi/MidiService.java
+++ b/services/midi/java/com/android/server/midi/MidiService.java
@@ -350,8 +350,10 @@
             }
 
             if (mDeviceConnections != null) {
-                for (DeviceConnection connection : mDeviceConnections) {
-                    connection.notifyClient(server);
+                synchronized (mDeviceConnections) {
+                    for (DeviceConnection connection : mDeviceConnections) {
+                        connection.notifyClient(server);
+                    }
                 }
             }
         }
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index e3e2708..fdf23d3 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -59,9 +59,7 @@
 
     private static final boolean DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG);
 
-    private static final long BG_PROCESS_PERIOD = DEBUG
-            ? TimeUnit.MINUTES.toMillis(1)
-            : TimeUnit.DAYS.toMillis(1);
+    private static final long BG_PROCESS_PERIOD = TimeUnit.DAYS.toMillis(1); // every 1 day.
 
     private IProfCollectd mIProfcollect;
     private static ProfcollectForwardingService sSelfService;
@@ -286,6 +284,11 @@
         updateEngine.bind(new UpdateEngineCallback() {
             @Override
             public void onStatusUpdate(int status, float percent) {
+                if (DEBUG) {
+                    Log.d(LOG_TAG, "Received OTA status update, status: " + status + ", percent: "
+                            + percent);
+                }
+
                 if (status == UpdateEngine.UpdateStatusConstants.UPDATED_NEED_REBOOT) {
                     packProfileReport();
                 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
index a254f68..16afef5 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
@@ -3002,7 +3002,8 @@
             final PendingIntent pi = getNewMockPendingIntent();
             setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i, pi);
 
-            verify(() -> MetricsHelper.pushAlarmScheduled(argThat(a -> a.matches(pi, null))));
+            verify(() -> MetricsHelper.pushAlarmScheduled(argThat(a -> a.matches(pi, null)),
+                    anyInt()));
         }
     }
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
index 803a0c1..26b5218 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
@@ -1003,7 +1003,7 @@
                     dummyPackageName, dummyClassName), "", definingUid));
         }
         app.mServices.setConnectionGroup(connectionGroup);
-        app.mState.setSetProcState(procState);
+        app.mState.setReportedProcState(procState);
         app.mProfile.setLastMemInfo(spy(new Debug.MemoryInfo()));
         app.mProfile.setLastPss(pss);
         app.mProfile.setLastRss(rss);
diff --git a/services/tests/mockingservicestests/src/com/android/server/appsearch/AppSearchConfigTest.java b/services/tests/mockingservicestests/src/com/android/server/appsearch/AppSearchConfigTest.java
index 8336663..9926953 100644
--- a/services/tests/mockingservicestests/src/com/android/server/appsearch/AppSearchConfigTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appsearch/AppSearchConfigTest.java
@@ -50,6 +50,14 @@
                 AppSearchConfig.DEFAULT_SAMPLING_INTERVAL);
         assertThat(appSearchConfig.getCachedSamplingIntervalForPutDocumentStats()).isEqualTo(
                 AppSearchConfig.DEFAULT_SAMPLING_INTERVAL);
+        assertThat(appSearchConfig.getCachedSamplingIntervalForInitializeStats()).isEqualTo(
+                AppSearchConfig.DEFAULT_SAMPLING_INTERVAL);
+        assertThat(appSearchConfig.getCachedSamplingIntervalForSearchStats()).isEqualTo(
+                AppSearchConfig.DEFAULT_SAMPLING_INTERVAL);
+        assertThat(appSearchConfig.getCachedSamplingIntervalForGlobalSearchStats()).isEqualTo(
+                AppSearchConfig.DEFAULT_SAMPLING_INTERVAL);
+        assertThat(appSearchConfig.getCachedSamplingIntervalForOptimizeStats()).isEqualTo(
+                AppSearchConfig.DEFAULT_SAMPLING_INTERVAL);
         assertThat(appSearchConfig.getCachedLimitConfigMaxDocumentSizeBytes()).isEqualTo(
                 AppSearchConfig.DEFAULT_LIMIT_CONFIG_MAX_DOCUMENT_SIZE_BYTES);
         assertThat(appSearchConfig.getCachedLimitConfigMaxDocumentCount()).isEqualTo(
@@ -100,6 +108,11 @@
         final int samplingIntervalDefault = -1;
         final int samplingIntervalPutDocumentStats = -2;
         final int samplingIntervalBatchCallStats = -3;
+        final int samplingIntervalInitializeStats = -4;
+        final int samplingIntervalSearchStats = -5;
+        final int samplingIntervalGlobalSearchStats = -6;
+        final int samplingIntervalOptimizeStats = -7;
+
         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
                 AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
                 Integer.toString(samplingIntervalDefault),
@@ -112,6 +125,22 @@
                 AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS,
                 Integer.toString(samplingIntervalBatchCallStats),
                 false);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+                AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS,
+                Integer.toString(samplingIntervalInitializeStats),
+                false);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+                AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS,
+                Integer.toString(samplingIntervalSearchStats),
+                false);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+                AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS,
+                Integer.toString(samplingIntervalGlobalSearchStats),
+                false);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+                AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS,
+                Integer.toString(samplingIntervalOptimizeStats),
+                false);
 
         AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR);
 
@@ -121,6 +150,14 @@
                 samplingIntervalPutDocumentStats);
         assertThat(appSearchConfig.getCachedSamplingIntervalForBatchCallStats()).isEqualTo(
                 samplingIntervalBatchCallStats);
+        assertThat(appSearchConfig.getCachedSamplingIntervalForInitializeStats()).isEqualTo(
+                samplingIntervalInitializeStats);
+        assertThat(appSearchConfig.getCachedSamplingIntervalForSearchStats()).isEqualTo(
+                samplingIntervalSearchStats);
+        assertThat(appSearchConfig.getCachedSamplingIntervalForGlobalSearchStats()).isEqualTo(
+                samplingIntervalGlobalSearchStats);
+        assertThat(appSearchConfig.getCachedSamplingIntervalForOptimizeStats()).isEqualTo(
+                samplingIntervalOptimizeStats);
     }
 
     @Test
@@ -128,6 +165,10 @@
         int samplingIntervalDefault = -1;
         int samplingIntervalPutDocumentStats = -2;
         int samplingIntervalBatchCallStats = -3;
+        int samplingIntervalInitializeStats = -4;
+        int samplingIntervalSearchStats = -5;
+        int samplingIntervalGlobalSearchStats = -6;
+        int samplingIntervalOptimizeStats = -7;
         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
                 AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
                 Integer.toString(samplingIntervalDefault),
@@ -140,12 +181,32 @@
                 AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS,
                 Integer.toString(samplingIntervalBatchCallStats),
                 false);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+                AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS,
+                Integer.toString(samplingIntervalInitializeStats),
+                false);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+                AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS,
+                Integer.toString(samplingIntervalSearchStats),
+                false);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+                AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS,
+                Integer.toString(samplingIntervalGlobalSearchStats),
+                false);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+                AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS,
+                Integer.toString(samplingIntervalOptimizeStats),
+                false);
         AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR);
 
         // Overrides
         samplingIntervalDefault = -4;
         samplingIntervalPutDocumentStats = -5;
         samplingIntervalBatchCallStats = -6;
+        samplingIntervalInitializeStats = -7;
+        samplingIntervalSearchStats = -8;
+        samplingIntervalGlobalSearchStats = -9;
+        samplingIntervalOptimizeStats = -10;
         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
                 AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
                 Integer.toString(samplingIntervalDefault),
@@ -158,6 +219,22 @@
                 AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS,
                 Integer.toString(samplingIntervalBatchCallStats),
                 false);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+                AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS,
+                Integer.toString(samplingIntervalInitializeStats),
+                false);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+                AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS,
+                Integer.toString(samplingIntervalSearchStats),
+                false);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+                AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS,
+                Integer.toString(samplingIntervalGlobalSearchStats),
+                false);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+                AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS,
+                Integer.toString(samplingIntervalOptimizeStats),
+                false);
 
         assertThat(appSearchConfig.getCachedSamplingIntervalDefault()).isEqualTo(
                 samplingIntervalDefault);
@@ -165,6 +242,14 @@
                 samplingIntervalPutDocumentStats);
         assertThat(appSearchConfig.getCachedSamplingIntervalForBatchCallStats()).isEqualTo(
                 samplingIntervalBatchCallStats);
+        assertThat(appSearchConfig.getCachedSamplingIntervalForInitializeStats()).isEqualTo(
+                samplingIntervalInitializeStats);
+        assertThat(appSearchConfig.getCachedSamplingIntervalForSearchStats()).isEqualTo(
+                samplingIntervalSearchStats);
+        assertThat(appSearchConfig.getCachedSamplingIntervalForGlobalSearchStats()).isEqualTo(
+                samplingIntervalGlobalSearchStats);
+        assertThat(appSearchConfig.getCachedSamplingIntervalForOptimizeStats()).isEqualTo(
+                samplingIntervalOptimizeStats);
     }
 
     /**
@@ -366,6 +451,18 @@
                 () -> appSearchConfig.getCachedSamplingIntervalForPutDocumentStats());
         Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
                 IllegalStateException.class,
+                () -> appSearchConfig.getCachedSamplingIntervalForInitializeStats());
+        Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
+                IllegalStateException.class,
+                () -> appSearchConfig.getCachedSamplingIntervalForSearchStats());
+        Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
+                IllegalStateException.class,
+                () -> appSearchConfig.getCachedSamplingIntervalForGlobalSearchStats());
+        Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
+                IllegalStateException.class,
+                () -> appSearchConfig.getCachedSamplingIntervalForOptimizeStats());
+        Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
+                IllegalStateException.class,
                 () -> appSearchConfig.getCachedBytesOptimizeThreshold());
         Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
                 IllegalStateException.class,
diff --git a/services/tests/mockingservicestests/src/com/android/server/appsearch/OWNERS b/services/tests/mockingservicestests/src/com/android/server/appsearch/OWNERS
new file mode 100644
index 0000000..24f6b0b
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/appsearch/OWNERS
@@ -0,0 +1 @@
+include /apex/appsearch/OWNERS
\ No newline at end of file
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java
index f91cb28..521be70 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java
@@ -459,6 +459,66 @@
         assertThat(apkSession.getErrorMessage()).isEqualTo("Another apex session failed");
     }
 
+    @Test
+    public void getSessionIdByPackageName() throws Exception {
+        FakeStagedSession session = new FakeStagedSession(239);
+        session.setCommitted(true);
+        session.setSessionReady();
+        session.setPackageName("com.foo");
+
+        mStagingManager.createSession(session);
+        assertThat(mStagingManager.getSessionIdByPackageName("com.foo")).isEqualTo(239);
+    }
+
+    @Test
+    public void getSessionIdByPackageName_appliedSession_ignores() throws Exception {
+        FakeStagedSession session = new FakeStagedSession(37);
+        session.setCommitted(true);
+        session.setSessionApplied();
+        session.setPackageName("com.foo");
+
+        mStagingManager.createSession(session);
+        assertThat(mStagingManager.getSessionIdByPackageName("com.foo")).isEqualTo(-1);
+    }
+
+    @Test
+    public void getSessionIdByPackageName_failedSession_ignores() throws Exception {
+        FakeStagedSession session = new FakeStagedSession(73);
+        session.setCommitted(true);
+        session.setSessionFailed(1, "whatevs");
+        session.setPackageName("com.foo");
+
+        mStagingManager.createSession(session);
+        assertThat(mStagingManager.getSessionIdByPackageName("com.foo")).isEqualTo(-1);
+    }
+
+    @Test
+    public void getSessionIdByPackageName_destroyedSession_ignores() throws Exception {
+        FakeStagedSession session = new FakeStagedSession(23);
+        session.setCommitted(true);
+        session.setDestroyed(true);
+        session.setPackageName("com.foo");
+
+        mStagingManager.createSession(session);
+        assertThat(mStagingManager.getSessionIdByPackageName("com.foo")).isEqualTo(-1);
+    }
+
+    @Test
+    public void getSessionIdByPackageName_noSessions() throws Exception {
+        assertThat(mStagingManager.getSessionIdByPackageName("com.foo")).isEqualTo(-1);
+    }
+
+    @Test
+    public void getSessionIdByPackageName_noSessionHasThisPackage() throws Exception {
+        FakeStagedSession session = new FakeStagedSession(37);
+        session.setCommitted(true);
+        session.setSessionApplied();
+        session.setPackageName("com.foo");
+
+        mStagingManager.createSession(session);
+        assertThat(mStagingManager.getSessionIdByPackageName("com.bar")).isEqualTo(-1);
+    }
+
     private StagingManager.StagedSession createSession(int sessionId, String packageName,
             long committedMillis) {
         PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
index 5b067bc..f40a5ad 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
@@ -42,6 +42,7 @@
 
 import com.android.server.appsearch.external.localstorage.converter.GenericDocumentToProtoConverter;
 import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
+import com.android.server.appsearch.external.localstorage.stats.OptimizeStats;
 import com.android.server.appsearch.external.localstorage.util.PrefixUtil;
 import com.android.server.appsearch.icing.proto.DocumentProto;
 import com.android.server.appsearch.icing.proto.GetOptimizeInfoResultProto;
@@ -451,19 +452,26 @@
         assertThat(optimizeInfo.getOptimizableDocs()).isEqualTo(1);
 
         // Increase mutation counter and stop before reach the threshold
-        mAppSearchImpl.checkForOptimize(AppSearchImpl.CHECK_OPTIMIZE_INTERVAL - 1);
+        mAppSearchImpl.checkForOptimize(
+                AppSearchImpl.CHECK_OPTIMIZE_INTERVAL - 1, /*builder=*/ null);
 
         // Verify the optimize() isn't triggered.
         optimizeInfo = mAppSearchImpl.getOptimizeInfoResultLocked();
         assertThat(optimizeInfo.getOptimizableDocs()).isEqualTo(1);
 
         // Increase the counter and reach the threshold, optimize() should be triggered.
-        mAppSearchImpl.checkForOptimize(/*mutateBatchSize=*/ 1);
+        OptimizeStats.Builder builder = new OptimizeStats.Builder();
+        mAppSearchImpl.checkForOptimize(/*mutateBatchSize=*/ 1, builder);
 
         // Verify optimize() is triggered.
         optimizeInfo = mAppSearchImpl.getOptimizeInfoResultLocked();
         assertThat(optimizeInfo.getOptimizableDocs()).isEqualTo(0);
         assertThat(optimizeInfo.getEstimatedOptimizableBytes()).isEqualTo(0);
+
+        // Verify the stats have been set.
+        OptimizeStats oStats = builder.build();
+        assertThat(oStats.getOriginalDocumentCount()).isEqualTo(1);
+        assertThat(oStats.getDeletedDocumentCount()).isEqualTo(1);
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java
index 7bacbb6..7c97687 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java
@@ -29,12 +29,14 @@
 
 import com.android.server.appsearch.external.localstorage.stats.CallStats;
 import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
+import com.android.server.appsearch.external.localstorage.stats.OptimizeStats;
 import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats;
 import com.android.server.appsearch.external.localstorage.stats.RemoveStats;
 import com.android.server.appsearch.external.localstorage.stats.SearchStats;
 import com.android.server.appsearch.icing.proto.DeleteStatsProto;
 import com.android.server.appsearch.icing.proto.DocumentProto;
 import com.android.server.appsearch.icing.proto.InitializeStatsProto;
+import com.android.server.appsearch.icing.proto.OptimizeStatsProto;
 import com.android.server.appsearch.icing.proto.PutDocumentStatsProto;
 import com.android.server.appsearch.icing.proto.PutResultProto;
 import com.android.server.appsearch.icing.proto.QueryStatsProto;
@@ -81,6 +83,7 @@
         @Nullable InitializeStats mInitializeStats;
         @Nullable SearchStats mSearchStats;
         @Nullable RemoveStats mRemoveStats;
+        @Nullable OptimizeStats mOptimizeStats;
 
         @Override
         public void logStats(@NonNull CallStats stats) {
@@ -106,6 +109,11 @@
         public void logStats(@NonNull RemoveStats stats) {
             mRemoveStats = stats;
         }
+
+        @Override
+        public void logStats(@NonNull OptimizeStats stats) {
+            mOptimizeStats = stats;
+        }
     }
 
     @Test
@@ -286,6 +294,48 @@
         assertThat(rStats.getDeletedDocumentCount()).isEqualTo(nativeNumDocumentDeleted);
     }
 
+    @Test
+    public void testAppSearchLoggerHelper_testCopyNativeStats_optimize() {
+        int nativeLatencyMillis = 1;
+        int nativeDocumentStoreOptimizeLatencyMillis = 2;
+        int nativeIndexRestorationLatencyMillis = 3;
+        int nativeNumOriginalDocuments = 4;
+        int nativeNumDeletedDocuments = 5;
+        int nativeNumExpiredDocuments = 6;
+        long nativeStorageSizeBeforeBytes = Integer.MAX_VALUE + 1;
+        long nativeStorageSizeAfterBytes = Integer.MAX_VALUE + 2;
+        long nativeTimeSinceLastOptimizeMillis = Integer.MAX_VALUE + 3;
+        OptimizeStatsProto optimizeStatsProto =
+                OptimizeStatsProto.newBuilder()
+                        .setLatencyMs(nativeLatencyMillis)
+                        .setDocumentStoreOptimizeLatencyMs(nativeDocumentStoreOptimizeLatencyMillis)
+                        .setIndexRestorationLatencyMs(nativeIndexRestorationLatencyMillis)
+                        .setNumOriginalDocuments(nativeNumOriginalDocuments)
+                        .setNumDeletedDocuments(nativeNumDeletedDocuments)
+                        .setNumExpiredDocuments(nativeNumExpiredDocuments)
+                        .setStorageSizeBefore(nativeStorageSizeBeforeBytes)
+                        .setStorageSizeAfter(nativeStorageSizeAfterBytes)
+                        .setTimeSinceLastOptimizeMs(nativeTimeSinceLastOptimizeMillis)
+                        .build();
+        OptimizeStats.Builder oBuilder = new OptimizeStats.Builder();
+
+        AppSearchLoggerHelper.copyNativeStats(optimizeStatsProto, oBuilder);
+
+        OptimizeStats oStats = oBuilder.build();
+        assertThat(oStats.getNativeLatencyMillis()).isEqualTo(nativeLatencyMillis);
+        assertThat(oStats.getDocumentStoreOptimizeLatencyMillis())
+                .isEqualTo(nativeDocumentStoreOptimizeLatencyMillis);
+        assertThat(oStats.getIndexRestorationLatencyMillis())
+                .isEqualTo(nativeIndexRestorationLatencyMillis);
+        assertThat(oStats.getOriginalDocumentCount()).isEqualTo(nativeNumOriginalDocuments);
+        assertThat(oStats.getDeletedDocumentCount()).isEqualTo(nativeNumDeletedDocuments);
+        assertThat(oStats.getExpiredDocumentCount()).isEqualTo(nativeNumExpiredDocuments);
+        assertThat(oStats.getStorageSizeBeforeBytes()).isEqualTo(nativeStorageSizeBeforeBytes);
+        assertThat(oStats.getStorageSizeAfterBytes()).isEqualTo(nativeStorageSizeAfterBytes);
+        assertThat(oStats.getTimeSinceLastOptimizeMillis())
+                .isEqualTo(nativeTimeSinceLastOptimizeMillis);
+    }
+
     //
     // Testing actual logging
     //
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/stats/AppSearchStatsTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/stats/AppSearchStatsTest.java
index 57d9941..c1dc0e4 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/stats/AppSearchStatsTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/stats/AppSearchStatsTest.java
@@ -348,4 +348,49 @@
         assertThat(rStats.getDeleteType()).isEqualTo(deleteType);
         assertThat(rStats.getDeletedDocumentCount()).isEqualTo(documentDeletedCount);
     }
+
+    @Test
+    public void testAppSearchStats_OptimizeStats() {
+        int nativeLatencyMillis = 1;
+        int nativeDocumentStoreOptimizeLatencyMillis = 2;
+        int nativeIndexRestorationLatencyMillis = 3;
+        int nativeNumOriginalDocuments = 4;
+        int nativeNumDeletedDocuments = 5;
+        int nativeNumExpiredDocuments = 6;
+        long nativeStorageSizeBeforeBytes = Integer.MAX_VALUE + 1;
+        long nativeStorageSizeAfterBytes = Integer.MAX_VALUE + 2;
+        long nativeTimeSinceLastOptimizeMillis = Integer.MAX_VALUE + 3;
+
+        final OptimizeStats oStats =
+                new OptimizeStats.Builder()
+                        .setStatusCode(TEST_STATUS_CODE)
+                        .setTotalLatencyMillis(TEST_TOTAL_LATENCY_MILLIS)
+                        .setNativeLatencyMillis(nativeLatencyMillis)
+                        .setDocumentStoreOptimizeLatencyMillis(
+                                nativeDocumentStoreOptimizeLatencyMillis)
+                        .setIndexRestorationLatencyMillis(nativeIndexRestorationLatencyMillis)
+                        .setOriginalDocumentCount(nativeNumOriginalDocuments)
+                        .setDeletedDocumentCount(nativeNumDeletedDocuments)
+                        .setExpiredDocumentCount(nativeNumExpiredDocuments)
+                        .setStorageSizeBeforeBytes(nativeStorageSizeBeforeBytes)
+                        .setStorageSizeAfterBytes(nativeStorageSizeAfterBytes)
+                        .setTimeSinceLastOptimizeMillis(nativeTimeSinceLastOptimizeMillis)
+                        .build();
+
+        assertThat(oStats.getStatusCode()).isEqualTo(TEST_STATUS_CODE);
+        assertThat(oStats.getTotalLatencyMillis()).isEqualTo(TEST_TOTAL_LATENCY_MILLIS);
+        assertThat(oStats.getNativeLatencyMillis()).isEqualTo(nativeLatencyMillis);
+        assertThat(oStats.getNativeLatencyMillis()).isEqualTo(nativeLatencyMillis);
+        assertThat(oStats.getDocumentStoreOptimizeLatencyMillis())
+                .isEqualTo(nativeDocumentStoreOptimizeLatencyMillis);
+        assertThat(oStats.getIndexRestorationLatencyMillis())
+                .isEqualTo(nativeIndexRestorationLatencyMillis);
+        assertThat(oStats.getOriginalDocumentCount()).isEqualTo(nativeNumOriginalDocuments);
+        assertThat(oStats.getDeletedDocumentCount()).isEqualTo(nativeNumDeletedDocuments);
+        assertThat(oStats.getExpiredDocumentCount()).isEqualTo(nativeNumExpiredDocuments);
+        assertThat(oStats.getStorageSizeBeforeBytes()).isEqualTo(nativeStorageSizeBeforeBytes);
+        assertThat(oStats.getStorageSizeAfterBytes()).isEqualTo(nativeStorageSizeAfterBytes);
+        assertThat(oStats.getTimeSinceLastOptimizeMillis())
+                .isEqualTo(nativeTimeSinceLastOptimizeMillis);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
index a8bf0c7..1fe4123 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
@@ -372,6 +372,11 @@
         protected void startHalOperation() {
 
         }
+
+        @Override
+        protected void handleLifecycleAfterAuth(boolean authenticated) {
+
+        }
     }
 
     private static class TestAuthenticationClient extends AuthenticationClient<Object> {
@@ -395,6 +400,11 @@
         protected void startHalOperation() {
 
         }
+
+        @Override
+        protected void handleLifecycleAfterAuth(boolean authenticated) {
+
+        }
     }
 
     private static class TestClientMonitor2 extends TestClientMonitor {
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/CoexCoordinatorTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/CoexCoordinatorTest.java
index 589463e..a169ebd 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/CoexCoordinatorTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/CoexCoordinatorTest.java
@@ -16,64 +16,362 @@
 
 package com.android.server.biometrics.sensors;
 
+import static com.android.server.biometrics.sensors.BiometricScheduler.SENSOR_TYPE_FACE;
+import static com.android.server.biometrics.sensors.BiometricScheduler.SENSOR_TYPE_UDFPS;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.withSettings;
 
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
 import android.platform.test.annotations.Presubmit;
 
+import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 
+import com.android.server.biometrics.sensors.fingerprint.Udfps;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.LinkedList;
+
 @Presubmit
 @SmallTest
 public class CoexCoordinatorTest {
 
-    private CoexCoordinator mCoexCoordinator;
+    private static final String TAG = "CoexCoordinatorTest";
 
+    private CoexCoordinator mCoexCoordinator;
+    private Handler mHandler;
+
+    @Mock
+    private Context mContext;
     @Mock
     private CoexCoordinator.Callback mCallback;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+
+        mHandler = new Handler(Looper.getMainLooper());
+
         mCoexCoordinator = CoexCoordinator.getInstance();
+        mCoexCoordinator.setAdvancedLogicEnabled(true);
     }
 
     @Test
     public void testBiometricPrompt_authSuccess() {
+        mCoexCoordinator.reset();
+
         AuthenticationClient<?> client = mock(AuthenticationClient.class);
         when(client.isBiometricPrompt()).thenReturn(true);
 
-        mCoexCoordinator.onAuthenticationSucceeded(client, mCallback);
+        mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, client);
+
+        mCoexCoordinator.onAuthenticationSucceeded(0 /* currentTimeMillis */, client, mCallback);
         verify(mCallback).sendHapticFeedback();
         verify(mCallback).sendAuthenticationResult(eq(false) /* addAuthTokenIfStrong */);
+        verify(mCallback).handleLifecycleAfterAuth();
     }
 
     @Test
     public void testBiometricPrompt_authReject_whenNotLockedOut() {
+        mCoexCoordinator.reset();
+
         AuthenticationClient<?> client = mock(AuthenticationClient.class);
         when(client.isBiometricPrompt()).thenReturn(true);
 
-        mCoexCoordinator.onAuthenticationRejected(client, LockoutTracker.LOCKOUT_NONE, mCallback);
+        mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, client);
+
+        mCoexCoordinator.onAuthenticationRejected(0 /* currentTimeMillis */,
+                client, LockoutTracker.LOCKOUT_NONE, mCallback);
         verify(mCallback).sendHapticFeedback();
         verify(mCallback).sendAuthenticationResult(eq(false) /* addAuthTokenIfStrong */);
+        verify(mCallback).handleLifecycleAfterAuth();
     }
 
     @Test
     public void testBiometricPrompt_authReject_whenLockedOut() {
+        mCoexCoordinator.reset();
+
         AuthenticationClient<?> client = mock(AuthenticationClient.class);
         when(client.isBiometricPrompt()).thenReturn(true);
 
-        mCoexCoordinator.onAuthenticationRejected(client, LockoutTracker.LOCKOUT_TIMED, mCallback);
+        mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, client);
+
+        mCoexCoordinator.onAuthenticationRejected(0 /* currentTimeMillis */,
+                client, LockoutTracker.LOCKOUT_TIMED, mCallback);
         verify(mCallback).sendHapticFeedback();
         verify(mCallback, never()).sendAuthenticationResult(anyBoolean());
+        verify(mCallback).handleLifecycleAfterAuth();
+    }
+
+    @Test
+    public void testKeyguard_faceAuthOnly_success() {
+        mCoexCoordinator.reset();
+
+        AuthenticationClient<?> client = mock(AuthenticationClient.class);
+        when(client.isKeyguard()).thenReturn(true);
+
+        mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, client);
+
+        mCoexCoordinator.onAuthenticationSucceeded(0 /* currentTimeMillis */, client, mCallback);
+        verify(mCallback).sendHapticFeedback();
+        verify(mCallback).sendAuthenticationResult(eq(true) /* addAuthTokenIfStrong */);
+        verify(mCallback).handleLifecycleAfterAuth();
+    }
+
+    @Test
+    public void testKeyguard_faceAuth_udfpsNotTouching_faceSuccess() {
+        mCoexCoordinator.reset();
+
+        AuthenticationClient<?> faceClient = mock(AuthenticationClient.class);
+        when(faceClient.isKeyguard()).thenReturn(true);
+
+        AuthenticationClient<?> udfpsClient = mock(AuthenticationClient.class,
+                withSettings().extraInterfaces(Udfps.class));
+        when(udfpsClient.isKeyguard()).thenReturn(true);
+        when(((Udfps) udfpsClient).isPointerDown()).thenReturn(false);
+
+        mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, faceClient);
+        mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_UDFPS, udfpsClient);
+
+        mCoexCoordinator.onAuthenticationSucceeded(0 /* currentTimeMillis */, faceClient,
+                mCallback);
+        verify(mCallback).sendHapticFeedback();
+        verify(mCallback).sendAuthenticationResult(eq(true) /* addAuthTokenIfStrong */);
+        verify(mCallback).handleLifecycleAfterAuth();
+    }
+
+    @Test
+    public void testKeyguard_faceAuth_udfpsTouching_faceSuccess_thenUdfpsRejectedWithinBounds() {
+        testKeyguard_faceAuth_udfpsTouching_faceSuccess(false /* thenUdfpsAccepted */,
+                0 /* udfpsRejectedAfterMs */);
+    }
+
+    @Test
+    public void testKeyguard_faceAuth_udfpsTouching_faceSuccess_thenUdfpsRejectedAfterBounds() {
+        testKeyguard_faceAuth_udfpsTouching_faceSuccess(false /* thenUdfpsAccepted */,
+                CoexCoordinator.SUCCESSFUL_AUTH_VALID_DURATION_MS + 1 /* udfpsRejectedAfterMs */);
+    }
+
+    @Test
+    public void testKeyguard_faceAuth_udfpsTouching_faceSuccess_thenUdfpsAccepted() {
+        testKeyguard_faceAuth_udfpsTouching_faceSuccess(true /* thenUdfpsAccepted */,
+                0 /* udfpsRejectedAfterMs */);
+    }
+
+    private void testKeyguard_faceAuth_udfpsTouching_faceSuccess(boolean thenUdfpsAccepted,
+            long udfpsRejectedAfterMs) {
+        mCoexCoordinator.reset();
+
+        AuthenticationClient<?> faceClient = mock(AuthenticationClient.class);
+        when(faceClient.isKeyguard()).thenReturn(true);
+
+        AuthenticationClient<?> udfpsClient = mock(AuthenticationClient.class,
+                withSettings().extraInterfaces(Udfps.class));
+        when(udfpsClient.isKeyguard()).thenReturn(true);
+        when(((Udfps) udfpsClient).isPointerDown()).thenReturn(true);
+        when (udfpsClient.getState()).thenReturn(AuthenticationClient.STATE_STARTED);
+
+        mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, faceClient);
+        mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_UDFPS, udfpsClient);
+
+        mCoexCoordinator.onAuthenticationSucceeded(0 /* currentTimeMillis */, faceClient,
+                mCallback);
+        verify(mCallback, never()).sendHapticFeedback();
+        verify(mCallback, never()).sendAuthenticationResult(anyBoolean());
+        // CoexCoordinator requests the system to hold onto this AuthenticationClient until
+        // UDFPS result is known
+        verify(mCallback, never()).handleLifecycleAfterAuth();
+
+        // Reset the mock
+        CoexCoordinator.Callback udfpsCallback = mock(CoexCoordinator.Callback.class);
+        assertEquals(1, mCoexCoordinator.mSuccessfulAuths.size());
+        assertEquals(faceClient, mCoexCoordinator.mSuccessfulAuths.get(0).mAuthenticationClient);
+        if (thenUdfpsAccepted) {
+            mCoexCoordinator.onAuthenticationSucceeded(0 /* currentTimeMillis */, udfpsClient,
+                    udfpsCallback);
+            verify(udfpsCallback).sendHapticFeedback();
+            verify(udfpsCallback).sendAuthenticationResult(true /* addAuthTokenIfStrong */);
+            verify(udfpsCallback).handleLifecycleAfterAuth();
+
+            assertTrue(mCoexCoordinator.mSuccessfulAuths.isEmpty());
+        } else {
+            mCoexCoordinator.onAuthenticationRejected(udfpsRejectedAfterMs, udfpsClient,
+                    LockoutTracker.LOCKOUT_NONE, udfpsCallback);
+            if (udfpsRejectedAfterMs <= CoexCoordinator.SUCCESSFUL_AUTH_VALID_DURATION_MS) {
+                verify(udfpsCallback, never()).sendHapticFeedback();
+
+                verify(mCallback).sendHapticFeedback();
+                verify(mCallback).sendAuthenticationResult(eq(true) /* addAuthTokenIfStrong */);
+                verify(mCallback).handleLifecycleAfterAuth();
+
+                assertTrue(mCoexCoordinator.mSuccessfulAuths.isEmpty());
+            } else {
+                assertTrue(mCoexCoordinator.mSuccessfulAuths.isEmpty());
+
+                verify(mCallback, never()).sendHapticFeedback();
+                verify(mCallback, never()).sendAuthenticationResult(anyBoolean());
+
+                verify(udfpsCallback).sendHapticFeedback();
+                verify(udfpsCallback)
+                        .sendAuthenticationResult(eq(false) /* addAuthTokenIfStrong */);
+                verify(udfpsCallback).handleLifecycleAfterAuth();
+            }
+        }
+    }
+
+    @Test
+    public void testKeyguard_udfpsAuthSuccess_whileFaceScanning() {
+        mCoexCoordinator.reset();
+
+        AuthenticationClient<?> faceClient = mock(AuthenticationClient.class);
+        when(faceClient.isKeyguard()).thenReturn(true);
+        when(faceClient.getState()).thenReturn(AuthenticationClient.STATE_STARTED);
+
+        AuthenticationClient<?> udfpsClient = mock(AuthenticationClient.class,
+                withSettings().extraInterfaces(Udfps.class));
+        when(udfpsClient.isKeyguard()).thenReturn(true);
+        when(((Udfps) udfpsClient).isPointerDown()).thenReturn(true);
+
+        mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, faceClient);
+        mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_UDFPS, udfpsClient);
+
+        mCoexCoordinator.onAuthenticationSucceeded(0 /* currentTimeMillis */, udfpsClient,
+                mCallback);
+        verify(mCallback).sendHapticFeedback();
+        verify(mCallback).sendAuthenticationResult(eq(true));
+        verify(faceClient).cancel();
+        verify(mCallback).handleLifecycleAfterAuth();
+    }
+
+    @Test
+    public void testKeyguard_faceRejectedWhenUdfpsTouching_thenUdfpsRejected() {
+        mCoexCoordinator.reset();
+
+        AuthenticationClient<?> faceClient = mock(AuthenticationClient.class);
+        when(faceClient.isKeyguard()).thenReturn(true);
+        when(faceClient.getState()).thenReturn(AuthenticationClient.STATE_STARTED);
+
+        AuthenticationClient<?> udfpsClient = mock(AuthenticationClient.class,
+                withSettings().extraInterfaces(Udfps.class));
+        when(udfpsClient.getState()).thenReturn(AuthenticationClient.STATE_STARTED);
+        when(udfpsClient.isKeyguard()).thenReturn(true);
+        when(((Udfps) udfpsClient).isPointerDown()).thenReturn(true);
+
+        mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, faceClient);
+        mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_UDFPS, udfpsClient);
+
+        mCoexCoordinator.onAuthenticationRejected(0 /* currentTimeMillis */, faceClient,
+                LockoutTracker.LOCKOUT_NONE, mCallback);
+        verify(mCallback, never()).sendHapticFeedback();
+        verify(mCallback).handleLifecycleAfterAuth();
+
+        // BiometricScheduler removes the face authentication client after rejection
+        mCoexCoordinator.removeAuthenticationClient(SENSOR_TYPE_FACE, faceClient);
+
+        // Then UDFPS rejected
+        CoexCoordinator.Callback udfpsCallback = mock(CoexCoordinator.Callback.class);
+        mCoexCoordinator.onAuthenticationRejected(1 /* currentTimeMillis */, udfpsClient,
+                LockoutTracker.LOCKOUT_NONE, udfpsCallback);
+        verify(udfpsCallback).sendHapticFeedback();
+        verify(udfpsCallback).sendAuthenticationResult(eq(false) /* addAuthTokenIfStrong */);
+        verify(mCallback, never()).sendHapticFeedback();
+    }
+
+    @Test
+    public void testKeyguard_udfpsRejected_thenFaceRejected() {
+        mCoexCoordinator.reset();
+
+        AuthenticationClient<?> faceClient = mock(AuthenticationClient.class);
+        when(faceClient.isKeyguard()).thenReturn(true);
+        when(faceClient.getState()).thenReturn(AuthenticationClient.STATE_STARTED);
+
+        AuthenticationClient<?> udfpsClient = mock(AuthenticationClient.class,
+                withSettings().extraInterfaces(Udfps.class));
+        when(udfpsClient.getState()).thenReturn(AuthenticationClient.STATE_STARTED);
+        when(udfpsClient.isKeyguard()).thenReturn(true);
+        when(((Udfps) udfpsClient).isPointerDown()).thenReturn(true);
+
+        mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, faceClient);
+        mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_UDFPS, udfpsClient);
+
+        mCoexCoordinator.onAuthenticationRejected(0 /* currentTimeMillis */, udfpsClient,
+                LockoutTracker.LOCKOUT_NONE, mCallback);
+        // Client becomes paused, but finger does not necessarily lift, since we suppress the haptic
+        when(udfpsClient.getState()).thenReturn(AuthenticationClient.STATE_STARTED_PAUSED);
+        verify(mCallback, never()).sendHapticFeedback();
+        verify(mCallback).handleLifecycleAfterAuth();
+
+        // Then face rejected. Note that scheduler leaves UDFPS in the CoexCoordinator since
+        // unlike face, its lifecycle becomes "paused" instead of "finished".
+        CoexCoordinator.Callback faceCallback = mock(CoexCoordinator.Callback.class);
+        mCoexCoordinator.onAuthenticationRejected(1 /* currentTimeMillis */, faceClient,
+                LockoutTracker.LOCKOUT_NONE, faceCallback);
+        verify(faceCallback).sendHapticFeedback();
+        verify(faceCallback).sendAuthenticationResult(eq(false) /* addAuthTokenIfStrong */);
+        verify(mCallback, never()).sendHapticFeedback();
+    }
+
+    @Test
+    public void testNonKeyguard_rejectAndNotLockedOut() {
+        mCoexCoordinator.reset();
+
+        AuthenticationClient<?> faceClient = mock(AuthenticationClient.class);
+        when(faceClient.isKeyguard()).thenReturn(false);
+        when(faceClient.isBiometricPrompt()).thenReturn(true);
+
+        mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, faceClient);
+        mCoexCoordinator.onAuthenticationRejected(0 /* currentTimeMillis */, faceClient,
+                LockoutTracker.LOCKOUT_NONE, mCallback);
+
+        verify(mCallback).sendHapticFeedback();
+        verify(mCallback).sendAuthenticationResult(eq(false));
+        verify(mCallback).handleLifecycleAfterAuth();
+    }
+
+    @Test
+    public void testNonKeyguard_rejectLockedOut() {
+        mCoexCoordinator.reset();
+
+        AuthenticationClient<?> faceClient = mock(AuthenticationClient.class);
+        when(faceClient.isKeyguard()).thenReturn(false);
+        when(faceClient.isBiometricPrompt()).thenReturn(true);
+
+        mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, faceClient);
+        mCoexCoordinator.onAuthenticationRejected(0 /* currentTimeMillis */, faceClient,
+                LockoutTracker.LOCKOUT_TIMED, mCallback);
+
+        verify(mCallback).sendHapticFeedback();
+        verify(mCallback, never()).sendAuthenticationResult(anyBoolean());
+        verify(mCallback).handleLifecycleAfterAuth();
+    }
+
+    @Test
+    public void testCleanupRunnable() {
+        LinkedList<CoexCoordinator.SuccessfulAuth> successfulAuths = mock(LinkedList.class);
+        CoexCoordinator.SuccessfulAuth auth = mock(CoexCoordinator.SuccessfulAuth.class);
+        CoexCoordinator.Callback callback = mock(CoexCoordinator.Callback.class);
+        CoexCoordinator.SuccessfulAuth.CleanupRunnable runnable =
+                new CoexCoordinator.SuccessfulAuth.CleanupRunnable(successfulAuths, auth, callback);
+        runnable.run();
+
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+        verify(callback).handleLifecycleAfterAuth();
+        verify(successfulAuths).remove(eq(auth));
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java b/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java
index 1ad8850..cc3591c8 100644
--- a/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java
@@ -92,7 +92,6 @@
 
     @Mock IThermalService mThermalServiceMock;
     @Mock Injector mInjectorMock;
-    @Mock BrightnessSetting mBrightnessSetting;
 
     @Captor ArgumentCaptor<IThermalEventListener> mThermalEventListenerCaptor;
 
@@ -123,7 +122,7 @@
         initHandler(null);
         final HighBrightnessModeController hbmc = new HighBrightnessModeController(
                 mInjectorMock, mHandler, DISPLAY_WIDTH, DISPLAY_HEIGHT, mDisplayToken, DEFAULT_MIN,
-                DEFAULT_MAX, null, () -> {}, mContextSpy, mBrightnessSetting);
+                DEFAULT_MAX, null, () -> {}, mContextSpy);
         assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF);
     }
 
@@ -132,7 +131,7 @@
         initHandler(null);
         final HighBrightnessModeController hbmc = new HighBrightnessModeController(
                 mInjectorMock, mHandler, DISPLAY_WIDTH, DISPLAY_HEIGHT, mDisplayToken, DEFAULT_MIN,
-                DEFAULT_MAX, null, () -> {}, mContextSpy, mBrightnessSetting);
+                DEFAULT_MAX, null, () -> {}, mContextSpy);
         hbmc.setAutoBrightnessEnabled(true);
         hbmc.onAmbientLuxChange(MINIMUM_LUX - 1); // below allowed range
         assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF);
@@ -464,7 +463,7 @@
         initHandler(clock);
         return new HighBrightnessModeController(mInjectorMock, mHandler, DISPLAY_WIDTH,
                 DISPLAY_HEIGHT, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, DEFAULT_HBM_DATA, () -> {},
-                mContextSpy, mBrightnessSetting);
+                mContextSpy);
     }
 
     private void initHandler(OffsettableClock clock) {
diff --git a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
index 9044b27..5eb21a5 100644
--- a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
@@ -19,6 +19,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.junit.Assert.assertEquals;
+import static org.testng.Assert.expectThrows;
 
 import android.platform.test.annotations.Presubmit;
 import android.util.ArrayMap;
@@ -200,6 +201,46 @@
 
         assertThat(mSysConfig.getWhitelistedStagedInstallers())
                 .containsExactly("com.android.package1");
+        assertThat(mSysConfig.getModulesInstallerPackageName()).isNull();
+    }
+
+    @Test
+    public void readPermissions_parsesStagedInstallerWhitelist_modulesInstaller()
+            throws IOException {
+        final String contents =
+                "<config>\n"
+                + "    <whitelisted-staged-installer package=\"com.android.package1\" "
+                + "         isModulesInstaller=\"true\" />\n"
+                + "</config>";
+        final File folder = createTempSubfolder("folder");
+        createTempFile(folder, "staged-installer-whitelist.xml", contents);
+
+        mSysConfig.readPermissions(folder, /* Grant all permission flags */ ~0);
+
+        assertThat(mSysConfig.getWhitelistedStagedInstallers())
+                .containsExactly("com.android.package1");
+        assertThat(mSysConfig.getModulesInstallerPackageName())
+                .isEqualTo("com.android.package1");
+    }
+
+    @Test
+    public void readPermissions_parsesStagedInstallerWhitelist_multipleModulesInstallers()
+            throws IOException {
+        final String contents =
+                "<config>\n"
+                + "    <whitelisted-staged-installer package=\"com.android.package1\" "
+                + "         isModulesInstaller=\"true\" />\n"
+                + "    <whitelisted-staged-installer package=\"com.android.package2\" "
+                + "         isModulesInstaller=\"true\" />\n"
+                + "</config>";
+        final File folder = createTempSubfolder("folder");
+        createTempFile(folder, "staged-installer-whitelist.xml", contents);
+
+        IllegalStateException e = expectThrows(
+                IllegalStateException.class,
+                () -> mSysConfig.readPermissions(folder, /* Grant all permission flags */ ~0));
+
+        assertThat(e).hasMessageThat().contains("Multiple modules installers");
     }
 
     /**
@@ -230,14 +271,16 @@
             throws IOException {
         final String contents =
                 "<config>\n"
-                        + "    <allowed-vendor-apex package=\"com.android.apex1\" />\n"
+                        + "    <allowed-vendor-apex package=\"com.android.apex1\" "
+                        + "installerPackage=\"com.installer\" />\n"
                         + "</config>";
         final File folder = createTempSubfolder("folder");
         createTempFile(folder, "vendor-apex-allowlist.xml", contents);
 
         mSysConfig.readPermissions(folder, /* Grant all permission flags */ ~0);
 
-        assertThat(mSysConfig.getAllowedVendorApexes()).containsExactly("com.android.apex1");
+        assertThat(mSysConfig.getAllowedVendorApexes())
+                .containsExactly("com.android.apex1", "com.installer");
     }
 
     /**
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index 645fa63..9e46e1f 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -93,6 +93,7 @@
 import android.view.Display;
 
 import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.FlakyTest;
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
@@ -103,7 +104,6 @@
 
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -502,6 +502,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testBoundWidgetPackageExempt() throws Exception {
         assumeTrue(mInjector.getContext().getSystemService(AppWidgetManager.class) != null);
         assertEquals(STANDBY_BUCKET_ACTIVE,
@@ -584,6 +585,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testIsAppIdle_Charging() throws Exception {
         TestParoleListener paroleListener = new TestParoleListener();
         mController.addListener(paroleListener);
@@ -616,6 +618,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testIsAppIdle_Enabled() throws Exception {
         setChargingState(mController, false);
         TestParoleListener paroleListener = new TestParoleListener();
@@ -715,6 +718,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testBuckets() throws Exception {
         assertTimeout(mController, 0, STANDBY_BUCKET_NEVER);
 
@@ -747,6 +751,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testSetAppStandbyBucket() throws Exception {
         // For a known package, standby bucket should be set properly
         reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
@@ -766,6 +771,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testAppStandbyBucketOnInstallAndUninstall() throws Exception {
         // On package install, standby bucket should be ACTIVE
         reportEvent(mController, USER_INTERACTION, 0, PACKAGE_UNKNOWN);
@@ -784,6 +790,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testScreenTimeAndBuckets() throws Exception {
         mInjector.setDisplayOn(false);
 
@@ -807,6 +814,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testForcedIdle() throws Exception {
         mController.forceIdleState(PACKAGE_1, USER_ID, true);
         assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
@@ -819,6 +827,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testNotificationEvent() throws Exception {
         reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
         assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
@@ -832,6 +841,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testSlicePinnedEvent() throws Exception {
         reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
         assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
@@ -845,6 +855,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testSlicePinnedPrivEvent() throws Exception {
         mController.forceIdleState(PACKAGE_1, USER_ID, true);
         reportEvent(mController, SLICE_PINNED_PRIV, mInjector.mElapsedRealtime, PACKAGE_1);
@@ -852,6 +863,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testPredictionTimedOut() throws Exception {
         // Set it to timeout or usage, so that prediction can override it
         mInjector.mElapsedRealtime = HOUR_MS;
@@ -882,6 +894,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testOverrides() throws Exception {
         // Can force to NEVER
         mInjector.mElapsedRealtime = HOUR_MS;
@@ -992,6 +1005,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testTimeout() throws Exception {
         reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
         assertBucket(STANDBY_BUCKET_ACTIVE);
@@ -1015,6 +1029,7 @@
 
     /** Test that timeouts still work properly even if invalid configuration values are set. */
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testTimeout_InvalidThresholds() throws Exception {
         mInjector.mSettingsBuilder
                 .setLong("screen_threshold_active", -1)
@@ -1052,6 +1067,7 @@
      * timeout has passed.
      */
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testTimeoutBeforeRestricted() throws Exception {
         reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
         assertBucket(STANDBY_BUCKET_ACTIVE);
@@ -1078,6 +1094,7 @@
      * Test that an app is put into the RESTRICTED bucket after enough time has passed.
      */
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testRestrictedDelay() throws Exception {
         reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
         assertBucket(STANDBY_BUCKET_ACTIVE);
@@ -1100,6 +1117,7 @@
      * Test that an app is put into the RESTRICTED bucket after enough time has passed.
      */
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testRestrictedDelay_DelayChange() throws Exception {
         reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
         assertBucket(STANDBY_BUCKET_ACTIVE);
@@ -1124,6 +1142,7 @@
      * a low bucket after the RESTRICTED timeout.
      */
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testRestrictedTimeoutOverridesRestoredLowBucketPrediction() throws Exception {
         reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
         assertBucket(STANDBY_BUCKET_ACTIVE);
@@ -1160,6 +1179,7 @@
      * a low bucket after the RESTRICTED timeout.
      */
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testRestrictedTimeoutOverridesPredictionLowBucket() throws Exception {
         reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
 
@@ -1187,6 +1207,7 @@
      * interaction.
      */
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testSystemInteractionOverridesRestrictedTimeout() throws Exception {
         reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
         assertBucket(STANDBY_BUCKET_ACTIVE);
@@ -1213,6 +1234,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testRestrictedBucketDisabled() throws Exception {
         mInjector.mIsRestrictedBucketEnabled = false;
         // Get the controller to read the new value. Capturing the ContentObserver isn't possible
@@ -1238,6 +1260,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testRestrictedBucket_EnabledToDisabled() throws Exception {
         reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
         mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD;
@@ -1255,6 +1278,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testPredictionRaiseFromRestrictedTimeout_highBucket() throws Exception {
         reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
 
@@ -1272,6 +1296,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testPredictionRaiseFromRestrictedTimeout_lowBucket() throws Exception {
         reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
 
@@ -1289,6 +1314,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testCascadingTimeouts() throws Exception {
         reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
         assertBucket(STANDBY_BUCKET_ACTIVE);
@@ -1312,6 +1338,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testOverlappingTimeouts() throws Exception {
         reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
         assertBucket(STANDBY_BUCKET_ACTIVE);
@@ -1343,6 +1370,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testSystemInteractionTimeout() throws Exception {
         reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
         // Fast forward to RARE
@@ -1366,6 +1394,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testInitialForegroundServiceTimeout() throws Exception {
         mInjector.mElapsedRealtime = 1 * RARE_THRESHOLD + 100;
         // Make sure app is in NEVER bucket
@@ -1399,6 +1428,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testPredictionNotOverridden() throws Exception {
         reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
         assertBucket(STANDBY_BUCKET_ACTIVE);
@@ -1424,8 +1454,8 @@
         assertBucket(STANDBY_BUCKET_ACTIVE);
     }
 
-    @Ignore
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testPredictionStrikesBack() throws Exception {
         reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
         assertBucket(STANDBY_BUCKET_ACTIVE);
@@ -1451,6 +1481,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testSystemForcedFlags_NotAddedForUserForce() throws Exception {
         final int expectedReason = REASON_MAIN_FORCED_BY_USER;
         mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
@@ -1465,6 +1496,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testSystemForcedFlags_AddedForSystemForce() throws Exception {
         mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
                 REASON_MAIN_DEFAULT);
@@ -1487,6 +1519,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testSystemForcedFlags_SystemForceChangesBuckets() throws Exception {
         mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
                 REASON_MAIN_DEFAULT);
@@ -1524,6 +1557,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testRestrictApp_MainReason() throws Exception {
         mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
                 REASON_MAIN_DEFAULT);
@@ -1598,6 +1632,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testUserInteraction_CrossProfile() throws Exception {
         mInjector.mRunningUsers = new int[] {USER_ID, USER_ID2, USER_ID3};
         mInjector.mCrossProfileTargets = Arrays.asList(USER_HANDLE_USER2);
@@ -1621,6 +1656,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testUnexemptedSyncScheduled() throws Exception {
         rearmLatch(PACKAGE_1);
         mController.addListener(mListener);
@@ -1642,6 +1678,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 185169504)
     public void testExemptedSyncScheduled() throws Exception {
         setAndAssertBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, REASON_MAIN_FORCED_BY_SYSTEM);
         mInjector.mDeviceIdleMode = true;
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
index c555612..3a6aac9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
@@ -19,6 +19,7 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.TRANSIT_CHANGE;
 import static android.view.WindowManager.TRANSIT_CLOSE;
@@ -27,6 +28,7 @@
 import static android.view.WindowManager.TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE;
 import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
 import static android.view.WindowManager.TRANSIT_OPEN;
+import static android.view.WindowManager.TRANSIT_TO_FRONT;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -167,6 +169,69 @@
         assertFalse(mAppTransitionController.isTransitWithinTask(TRANSIT_OLD_TASK_OPEN, task));
     }
 
+
+    @Test
+    public void testIntraWallpaper_open() {
+        final ActivityRecord opening = createActivityRecord(mDisplayContent,
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+        opening.setVisible(false);
+        final WindowManager.LayoutParams attrOpening = new WindowManager.LayoutParams(
+                TYPE_BASE_APPLICATION);
+        attrOpening.setTitle("WallpaperOpening");
+        attrOpening.flags |= FLAG_SHOW_WALLPAPER;
+        final TestWindowState appWindowOpening = createWindowState(attrOpening, opening);
+        opening.addWindow(appWindowOpening);
+
+        final ActivityRecord closing = createActivityRecord(mDisplayContent,
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+        final WindowManager.LayoutParams attrClosing = new WindowManager.LayoutParams(
+                TYPE_BASE_APPLICATION);
+        attrOpening.setTitle("WallpaperClosing");
+        attrClosing.flags |= FLAG_SHOW_WALLPAPER;
+        final TestWindowState appWindowClosing = createWindowState(attrClosing, closing);
+        closing.addWindow(appWindowClosing);
+
+        mDisplayContent.prepareAppTransition(TRANSIT_OPEN);
+        mDisplayContent.mOpeningApps.add(opening);
+        mDisplayContent.mClosingApps.add(closing);
+
+        assertEquals(WindowManager.TRANSIT_OLD_WALLPAPER_INTRA_OPEN,
+                AppTransitionController.getTransitCompatType(mDisplayContent.mAppTransition,
+                        mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
+                        appWindowClosing, null, false));
+    }
+
+    @Test
+    public void testIntraWallpaper_toFront() {
+        final ActivityRecord opening = createActivityRecord(mDisplayContent,
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+        opening.setVisible(false);
+        final WindowManager.LayoutParams attrOpening = new WindowManager.LayoutParams(
+                TYPE_BASE_APPLICATION);
+        attrOpening.setTitle("WallpaperOpening");
+        attrOpening.flags |= FLAG_SHOW_WALLPAPER;
+        final TestWindowState appWindowOpening = createWindowState(attrOpening, opening);
+        opening.addWindow(appWindowOpening);
+
+        final ActivityRecord closing = createActivityRecord(mDisplayContent,
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+        final WindowManager.LayoutParams attrClosing = new WindowManager.LayoutParams(
+                TYPE_BASE_APPLICATION);
+        attrOpening.setTitle("WallpaperClosing");
+        attrClosing.flags |= FLAG_SHOW_WALLPAPER;
+        final TestWindowState appWindowClosing = createWindowState(attrClosing, closing);
+        closing.addWindow(appWindowClosing);
+
+        mDisplayContent.prepareAppTransition(TRANSIT_TO_FRONT);
+        mDisplayContent.mOpeningApps.add(opening);
+        mDisplayContent.mClosingApps.add(closing);
+
+        assertEquals(WindowManager.TRANSIT_OLD_WALLPAPER_INTRA_OPEN,
+                AppTransitionController.getTransitCompatType(mDisplayContent.mAppTransition,
+                        mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
+                        appWindowClosing, null, false));
+    }
+
     @Test
     public void testGetAnimationTargets_visibilityAlreadyUpdated() {
         // [DisplayContent] -+- [Task1] - [ActivityRecord1] (opening, visible)
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java
index d5628fc..4e4e0ed 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java
@@ -24,6 +24,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER;
 import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST;
+import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_LAST;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -57,6 +58,7 @@
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Binder;
+import android.os.IBinder;
 import android.platform.test.annotations.Presubmit;
 import android.view.SurfaceControl;
 import android.view.View;
@@ -555,6 +557,7 @@
         final DisplayArea<WindowContainer> displayArea = new DisplayArea<>(
                 mWm, BELOW_TASKS, "NewArea", FEATURE_VENDOR_FIRST);
         final IDisplayAreaOrganizer mockDisplayAreaOrganizer = mock(IDisplayAreaOrganizer.class);
+        doReturn(mock(IBinder.class)).when(mockDisplayAreaOrganizer).asBinder();
         displayArea.mOrganizer = mockDisplayAreaOrganizer;
         spyOn(mWm.mAtmService.mWindowOrganizerController.mDisplayAreaOrganizerController);
         mDisplayContent.addChild(displayArea, 0);
@@ -566,6 +569,30 @@
                 .onDisplayAreaVanished(mockDisplayAreaOrganizer, displayArea);
     }
 
+    @Test
+    public void testRegisterSameFeatureOrganizer_expectThrowsException() {
+        final IDisplayAreaOrganizer mockDisplayAreaOrganizer = mock(IDisplayAreaOrganizer.class);
+        final IBinder binder = mock(IBinder.class);
+        doReturn(true).when(binder).isBinderAlive();
+        doReturn(binder).when(mockDisplayAreaOrganizer).asBinder();
+        final DisplayAreaOrganizerController controller =
+                mWm.mAtmService.mWindowOrganizerController.mDisplayAreaOrganizerController;
+        controller.registerOrganizer(mockDisplayAreaOrganizer, FEATURE_VENDOR_FIRST);
+        assertThrows(IllegalStateException.class,
+                () -> controller.registerOrganizer(mockDisplayAreaOrganizer, FEATURE_VENDOR_FIRST));
+    }
+
+    @Test
+    public void testRegisterUnregisterOrganizer() {
+        final IDisplayAreaOrganizer mockDisplayAreaOrganizer = mock(IDisplayAreaOrganizer.class);
+        doReturn(mock(IBinder.class)).when(mockDisplayAreaOrganizer).asBinder();
+        final DisplayAreaOrganizerController controller =
+                mWm.mAtmService.mWindowOrganizerController.mDisplayAreaOrganizerController;
+        controller.registerOrganizer(mockDisplayAreaOrganizer, FEATURE_VENDOR_FIRST);
+        controller.unregisterOrganizer(mockDisplayAreaOrganizer);
+        controller.registerOrganizer(mockDisplayAreaOrganizer, FEATURE_VENDOR_FIRST);
+    }
+
     private static class TestDisplayArea<T extends WindowContainer> extends DisplayArea<T> {
         private TestDisplayArea(WindowManagerService wms, Rect bounds) {
             super(wms, ANY, "half display area");
diff --git a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
index b89539c..3a2190d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
+++ b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
@@ -265,4 +265,10 @@
     public SurfaceControl.Transaction setColorSpace(SurfaceControl sc, ColorSpace colorSpace) {
         return this;
     }
+
+    @Override
+    public SurfaceControl.Transaction setTrustedOverlay(SurfaceControl sc,
+            boolean isTrustedOverlay) {
+        return this;
+    }
 }
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
index e408cfc..965f126 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
@@ -87,14 +87,14 @@
  */
 final class HotwordDetectionConnection {
     private static final String TAG = "HotwordDetectionConnection";
-    // TODO (b/177502877): Set the Debug flag to false before shipping.
-    static final boolean DEBUG = true;
+    static final boolean DEBUG = false;
 
     // TODO: These constants need to be refined.
     private static final long VALIDATION_TIMEOUT_MILLIS = 3000;
     private static final long MAX_UPDATE_TIMEOUT_MILLIS = 6000;
     private static final Duration MAX_UPDATE_TIMEOUT_DURATION =
             Duration.ofMillis(MAX_UPDATE_TIMEOUT_MILLIS);
+    private static final long RESET_DEBUG_HOTWORD_LOGGING_TIMEOUT_MILLIS = 60 * 60 * 1000; // 1 hour
 
     private final Executor mAudioCopyExecutor = Executors.newCachedThreadPool();
     // TODO: This may need to be a Handler(looper)
@@ -103,6 +103,7 @@
     private final AtomicBoolean mUpdateStateAfterStartFinished = new AtomicBoolean(false);
     private final IBinder.DeathRecipient mAudioServerDeathRecipient = this::audioServerDied;
     private final @NonNull ServiceConnectionFactory mServiceConnectionFactory;
+    private final IHotwordRecognitionStatusCallback mCallback;
 
     final Object mLock;
     final int mVoiceInteractionServiceUid;
@@ -110,11 +111,11 @@
     final int mUser;
     final Context mContext;
     volatile HotwordDetectionServiceIdentity mIdentity;
-    private IHotwordRecognitionStatusCallback mCallback;
     private IMicrophoneHotwordDetectionVoiceInteractionCallback mSoftwareCallback;
     private Instant mLastRestartInstant;
 
     private ScheduledFuture<?> mCancellationTaskFuture;
+    private ScheduledFuture<?> mDebugHotwordLoggingTimeoutFuture = null;
 
     /** Identity used for attributing app ops when delivering data to the Interactor. */
     @GuardedBy("mLock")
@@ -128,17 +129,24 @@
     private boolean mPerformingSoftwareHotwordDetection;
     private @NonNull ServiceConnection mRemoteHotwordDetectionService;
     private IBinder mAudioFlinger;
+    private boolean mDebugHotwordLogging = false;
 
     HotwordDetectionConnection(Object lock, Context context, int voiceInteractionServiceUid,
             Identity voiceInteractorIdentity, ComponentName serviceName, int userId,
             boolean bindInstantServiceAllowed, @Nullable PersistableBundle options,
-            @Nullable SharedMemory sharedMemory, IHotwordRecognitionStatusCallback callback) {
+            @Nullable SharedMemory sharedMemory,
+            @NonNull IHotwordRecognitionStatusCallback callback) {
+        if (callback == null) {
+            Slog.w(TAG, "Callback is null while creating connection");
+            throw new IllegalArgumentException("Callback is null while creating connection");
+        }
         mLock = lock;
         mContext = context;
         mVoiceInteractionServiceUid = voiceInteractionServiceUid;
         mVoiceInteractorIdentity = voiceInteractorIdentity;
         mDetectionComponentName = serviceName;
         mUser = userId;
+        mCallback = callback;
         final Intent intent = new Intent(HotwordDetectionService.SERVICE_INTERFACE);
         intent.setComponent(mDetectionComponentName);
         initAudioFlingerLocked();
@@ -147,22 +155,13 @@
 
         mRemoteHotwordDetectionService = mServiceConnectionFactory.createLocked();
 
-        if (callback == null) {
-            updateStateLocked(options, sharedMemory);
-            return;
-        }
-        mCallback = callback;
-
         mLastRestartInstant = Instant.now();
         updateStateAfterProcessStart(options, sharedMemory);
 
         // TODO(volnov): we need to be smarter here, e.g. schedule it a bit more often, but wait
         // until the current session is closed.
         mCancellationTaskFuture = mScheduledExecutorService.scheduleAtFixedRate(() -> {
-            if (DEBUG) {
-                Slog.i(TAG, "Time to restart the process, TTL has passed");
-            }
-
+            Slog.v(TAG, "Time to restart the process, TTL has passed");
             synchronized (mLock) {
                 restartProcessLocked();
             }
@@ -268,9 +267,9 @@
     }
 
     void cancelLocked() {
-        if (DEBUG) {
-            Slog.d(TAG, "cancelLocked");
-        }
+        Slog.v(TAG, "cancelLocked");
+        clearDebugHotwordLoggingTimeoutLocked();
+        mDebugHotwordLogging = false;
         if (mRemoteHotwordDetectionService.isBound()) {
             mRemoteHotwordDetectionService.unbind();
             LocalServices.getService(PermissionManagerServiceInternal.class)
@@ -288,6 +287,7 @@
         // TODO(b/191742511): this logic needs a test
         if (!mUpdateStateAfterStartFinished.get()
                 && Instant.now().minus(MAX_UPDATE_TIMEOUT_DURATION).isBefore(mLastRestartInstant)) {
+            Slog.v(TAG, "call updateStateAfterProcessStart");
             updateStateAfterProcessStart(options, sharedMemory);
         } else {
             mRemoteHotwordDetectionService.run(
@@ -330,6 +330,9 @@
                         if (result != null) {
                             Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result)
                                     + " bits from hotword trusted process");
+                            if (mDebugHotwordLogging) {
+                                Slog.i(TAG, "Egressed detected result: " + result);
+                            }
                         }
                     } else {
                         Slog.i(TAG, "Hotword detection has already completed");
@@ -407,15 +410,11 @@
 
     private void detectFromDspSourceForTest(SoundTrigger.KeyphraseRecognitionEvent recognitionEvent,
             IHotwordRecognitionStatusCallback externalCallback) {
-        if (DEBUG) {
-            Slog.d(TAG, "detectFromDspSourceForTest");
-        }
+        Slog.v(TAG, "detectFromDspSourceForTest");
         IDspHotwordDetectionCallback internalCallback = new IDspHotwordDetectionCallback.Stub() {
             @Override
             public void onDetected(HotwordDetectedResult result) throws RemoteException {
-                if (DEBUG) {
-                    Slog.d(TAG, "onDetected");
-                }
+                Slog.v(TAG, "onDetected");
                 synchronized (mLock) {
                     if (mValidatingDspTrigger) {
                         mValidatingDspTrigger = false;
@@ -424,6 +423,9 @@
                         if (result != null) {
                             Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result)
                                     + " bits from hotword trusted process");
+                            if (mDebugHotwordLogging) {
+                                Slog.i(TAG, "Egressed detected result: " + result);
+                            }
                         }
                     } else {
                         Slog.i(TAG, "Ignored hotword detected since trigger has been handled");
@@ -433,13 +435,14 @@
 
             @Override
             public void onRejected(HotwordRejectedResult result) throws RemoteException {
-                if (DEBUG) {
-                    Slog.d(TAG, "onRejected");
-                }
+                Slog.v(TAG, "onRejected");
                 synchronized (mLock) {
                     if (mValidatingDspTrigger) {
                         mValidatingDspTrigger = false;
                         externalCallback.onRejected(result);
+                        if (mDebugHotwordLogging && result != null) {
+                            Slog.i(TAG, "Egressed rejected result: " + result);
+                        }
                     } else {
                         Slog.i(TAG, "Ignored hotword rejected since trigger has been handled");
                     }
@@ -482,6 +485,9 @@
                     if (result != null) {
                         Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result)
                                 + " bits from hotword trusted process");
+                        if (mDebugHotwordLogging) {
+                            Slog.i(TAG, "Egressed detected result: " + result);
+                        }
                     }
                 }
             }
@@ -498,6 +504,9 @@
                     }
                     mValidatingDspTrigger = false;
                     externalCallback.onRejected(result);
+                    if (mDebugHotwordLogging && result != null) {
+                        Slog.i(TAG, "Egressed rejected result: " + result);
+                    }
                 }
             }
         };
@@ -514,19 +523,37 @@
     }
 
     void forceRestart() {
-        if (DEBUG) {
-            Slog.i(TAG, "Requested to restart the service internally. Performing the restart");
-        }
+        Slog.v(TAG, "Requested to restart the service internally. Performing the restart");
         synchronized (mLock) {
             restartProcessLocked();
         }
     }
 
-    private void restartProcessLocked() {
-        if (DEBUG) {
-            Slog.i(TAG, "Restarting hotword detection process");
-        }
+    void setDebugHotwordLoggingLocked(boolean logging) {
+        Slog.v(TAG, "setDebugHotwordLoggingLocked: " + logging);
+        clearDebugHotwordLoggingTimeoutLocked();
+        mDebugHotwordLogging = logging;
 
+        if (logging) {
+            // Reset mDebugHotwordLogging to false after one hour
+            mDebugHotwordLoggingTimeoutFuture = mScheduledExecutorService.schedule(() -> {
+                Slog.v(TAG, "Timeout to reset mDebugHotwordLogging to false");
+                synchronized (mLock) {
+                    mDebugHotwordLogging = false;
+                }
+            }, RESET_DEBUG_HOTWORD_LOGGING_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+        }
+    }
+
+    private void clearDebugHotwordLoggingTimeoutLocked() {
+        if (mDebugHotwordLoggingTimeoutFuture != null) {
+            mDebugHotwordLoggingTimeoutFuture.cancel(/* mayInterruptIfRunning= */true);
+            mDebugHotwordLoggingTimeoutFuture = null;
+        }
+    }
+
+    private void restartProcessLocked() {
+        Slog.v(TAG, "Restarting hotword detection process");
         ServiceConnection oldConnection = mRemoteHotwordDetectionService;
 
         // TODO(volnov): this can be done after connect() has been successful.
@@ -547,9 +574,7 @@
         // Recreate connection to reset the cache.
         mRemoteHotwordDetectionService = mServiceConnectionFactory.createLocked();
 
-        if (DEBUG) {
-            Slog.i(TAG, "Started the new process, issuing #onProcessRestarted");
-        }
+        Slog.v(TAG, "Started the new process, issuing #onProcessRestarted");
         try {
             mCallback.onProcessRestarted();
         } catch (RemoteException e) {
@@ -700,6 +725,9 @@
                                 bestEffortClose(serviceAudioSource);
                                 bestEffortClose(audioSource);
 
+                                if (mDebugHotwordLogging && result != null) {
+                                    Slog.i(TAG, "Egressed rejected result: " + result);
+                                }
                                 // TODO: Propagate the HotwordRejectedResult.
                             }
 
@@ -714,6 +742,9 @@
                                 if (triggerResult != null) {
                                     Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(
                                             triggerResult) + " bits from hotword trusted process");
+                                    if (mDebugHotwordLogging) {
+                                        Slog.i(TAG, "Egressed detected result: " + triggerResult);
+                                    }
                                 }
                                 // TODO: Add a delay before closing.
                                 bestEffortClose(audioSource);
@@ -773,9 +804,7 @@
             }
             synchronized (mLock) {
                 if (!mRespectServiceConnectionStatusChanged) {
-                    if (DEBUG) {
-                        Slog.d(TAG, "Ignored onServiceConnectionStatusChanged event");
-                    }
+                    Slog.v(TAG, "Ignored onServiceConnectionStatusChanged event");
                     return;
                 }
                 mIsBound = connected;
@@ -792,9 +821,7 @@
             super.binderDied();
             synchronized (mLock) {
                 if (!mRespectServiceConnectionStatusChanged) {
-                    if (DEBUG) {
-                        Slog.d(TAG, "Ignored #binderDied event");
-                    }
+                    Slog.v(TAG, "Ignored #binderDied event");
                     return;
                 }
 
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index ccf4267..71541ad 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -832,6 +832,17 @@
             mImpl.forceRestartHotwordDetector();
         }
 
+        // Called by Shell command
+        void setDebugHotwordLogging(boolean logging) {
+            synchronized (this) {
+                if (mImpl == null) {
+                    Slog.w(TAG, "setTemporaryLogging without running voice interaction service");
+                    return;
+                }
+                mImpl.setDebugHotwordLoggingLocked(logging);
+            }
+        }
+
         @Override
         public void showSession(Bundle args, int flags) {
             synchronized (this) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index cbcbf52..558a9ac 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -79,8 +79,7 @@
 
 class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConnection.Callback {
     final static String TAG = "VoiceInteractionServiceManager";
-    // TODO (b/177502877): Set the Debug flag to false before shipping.
-    static final boolean DEBUG = true;
+    static final boolean DEBUG = false;
 
     final static String CLOSE_REASON_VOICE_INTERACTION = "voiceinteraction";
 
@@ -420,9 +419,7 @@
             @Nullable PersistableBundle options,
             @Nullable SharedMemory sharedMemory,
             IHotwordRecognitionStatusCallback callback) {
-        if (DEBUG) {
-            Slog.d(TAG, "updateStateLocked");
-        }
+        Slog.v(TAG, "updateStateLocked");
         if (mHotwordDetectionComponentName == null) {
             Slog.w(TAG, "Hotword detection service name not found");
             throw new IllegalStateException("Hotword detection service name not found");
@@ -584,6 +581,14 @@
         mHotwordDetectionConnection.forceRestart();
     }
 
+    void setDebugHotwordLoggingLocked(boolean logging) {
+        if (mHotwordDetectionConnection == null) {
+            Slog.w(TAG, "Failed to set temporary debug logging: no hotword detection active");
+            return;
+        }
+        mHotwordDetectionConnection.setDebugHotwordLoggingLocked(logging);
+    }
+
     void resetHotwordDetectionConnectionLocked() {
         if (DEBUG) {
             Slog.d(TAG, "resetHotwordDetectionConnectionLocked");
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceShellCommand.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceShellCommand.java
index cdd8f7b..9bdf4e4 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceShellCommand.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceShellCommand.java
@@ -56,6 +56,8 @@
                 return requestDisable(pw);
             case "restart-detection":
                 return requestRestartDetection(pw);
+            case "set-debug-hotword-logging":
+                return setDebugHotwordLogging(pw);
             default:
                 return handleDefaultCommands(cmd);
         }
@@ -76,9 +78,14 @@
             pw.println("");
             pw.println("  disable [true|false]");
             pw.println("    Temporarily disable (when true) service");
+            pw.println("");
             pw.println("  restart-detection");
             pw.println("    Force a restart of a hotword detection service");
             pw.println("");
+            pw.println("  set-debug-hotword-logging [true|false]");
+            pw.println("    Temporarily enable or disable debug logging for hotword result.");
+            pw.println("    The debug logging will be reset after one hour from last enable.");
+            pw.println("");
         }
     }
 
@@ -157,6 +164,17 @@
         return 0;
     }
 
+    private int setDebugHotwordLogging(PrintWriter pw) {
+        boolean logging = Boolean.parseBoolean(getNextArgRequired());
+        Slog.i(TAG, "setDebugHotwordLogging(): " + logging);
+        try {
+            mService.setDebugHotwordLogging(logging);
+        } catch (Exception e) {
+            return handleError(pw, "setDebugHotwordLogging()", e);
+        }
+        return 0;
+    }
+
     private static int handleError(PrintWriter pw, String message, Exception e) {
         Slog.e(TAG,  "error calling " + message, e);
         pw.printf("Error calling %s: %s\n", message, e);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index f01519f..72ad23b 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -3538,7 +3538,7 @@
             "nr_advanced_capable_pco_id_int";
 
     /**
-     * This configuration allows the framework to use user data communication to detect RRC state,
+     * This configuration allows the framework to use user data communication to detect Idle state,
      * and this is used on the 5G icon.
      *
      * There is a new way for for RRC state detection at Android 12. If
@@ -3546,16 +3546,23 @@
      * {@link TelephonyManager#CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED}) returns true,
      * then framework can use PHYSICAL_CHANNEL_CONFIG for RRC state detection. Based on this
      * condition, some carriers want to use the legacy behavior that way is using user data
-     * communication to detect the RRC state. Therefore, this configuration allows the framework
-     * to use user data communication to detect RRC state.
+     * communication to detect the Idle state. Therefore, this configuration allows the framework
+     * to use user data communication to detect Idle state.
      *
-     * The precondition is
+     * There are 3 situations reflects the carrier define Idle state.
+     * 1. using PHYSICAL_CHANNEL_CONFIG to detect RRC Idle
+     * 2. using all of data connections to detect RRC Idle.
+     * 3. using data communication(consider internet data connection only) to detect data Idle.
+     *
+     * How to setup for above 3 cases?
+     * For below part, we call the condition#1 is device support
      * {@link android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported}(
-     * {@link TelephonyManager#CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED}) returns true,
-     * otherwise this config is not working.
-     * If this is true, framework uses the user data communication for RRC state detection.
-     * If this is false, framework uses the PHYSICAL_CHANNEL_CONFIG for RRC state detection.
+     * {@link TelephonyManager#CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED}).
+     * The condition#2 is carrier enable the KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL.
      *
+     * For case#1, the condition#1 is true and the condition#2 is false.
+     * For case#2, the condition#1 is false and the condition#2 is false.
+     * For case#3, the condition#2 is true.
      * @hide
      */
     public static final String KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL =
diff --git a/tests/StagedInstallTest/Android.bp b/tests/StagedInstallTest/Android.bp
index 1aa0499..cac14a7 100644
--- a/tests/StagedInstallTest/Android.bp
+++ b/tests/StagedInstallTest/Android.bp
@@ -32,6 +32,7 @@
     test_suites: ["general-tests"],
     java_resources: [
         ":com.android.apex.apkrollback.test_v2",
+        ":StagedInstallTestApexV2",
         ":StagedInstallTestApexV2_WrongSha",
         ":test.rebootless_apex_v1",
         ":test.rebootless_apex_v2",
diff --git a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
index 9cdaef7..4684f01 100644
--- a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
+++ b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
@@ -55,8 +55,11 @@
     private static final TestApp TEST_APEX_WITH_APK_V2 = new TestApp("TestApexWithApkV2",
             APK_IN_APEX_TESTAPEX_NAME, 2, /*isApex*/true, APK_IN_APEX_TESTAPEX_NAME + "_v2.apex");
     private static final TestApp APEX_WRONG_SHA_V2 = new TestApp(
-            "ApexWrongSha2", SHIM_APEX_PACKAGE_NAME, 2, /*isApex*/true,
+            "ApexWrongSha2", SHIM_APEX_PACKAGE_NAME, 2, /* isApex= */ true,
             "com.android.apex.cts.shim.v2_wrong_sha.apex");
+    private static final TestApp APEX_V2 = new TestApp(
+            "ApexV2", SHIM_APEX_PACKAGE_NAME, 2, /* isApex= */ true,
+            "com.android.apex.cts.shim.v2.apex");
 
     private File mTestStateFile = new File(
             InstrumentationRegistry.getInstrumentation().getContext().getFilesDir(),
@@ -196,6 +199,137 @@
     }
 
     @Test
+    public void testActiveApexIsRevertedOnCheckpointRollback_Prepare() throws Exception {
+        int sessionId = Install.single(TestApp.Apex2).setStaged().commit();
+        assertSessionReady(sessionId);
+        storeSessionId(sessionId);
+    }
+
+    @Test
+    public void testActiveApexIsRevertedOnCheckpointRollback_Commit() throws Exception {
+        // Verify apex installed during preparation was successful
+        int sessionId = retrieveLastSessionId();
+        assertSessionApplied(sessionId);
+        assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(2);
+        // Commit a new staged session
+        sessionId = Install.single(TestApp.Apex3).setStaged().commit();
+        assertSessionReady(sessionId);
+        storeSessionId(sessionId);
+    }
+
+    @Test
+    public void testActiveApexIsRevertedOnCheckpointRollback_VerifyPostReboot() throws Exception {
+        int sessionId = retrieveLastSessionId();
+        assertSessionFailed(sessionId);
+        assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(2);
+    }
+
+    @Test
+    public void testApexIsNotActivatedIfNotInCheckpointMode_Commit() throws Exception {
+        int sessionId = Install.single(TestApp.Apex2).setStaged().commit();
+        assertSessionReady(sessionId);
+        storeSessionId(sessionId);
+        assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+    }
+
+    @Test
+    public void testApexIsNotActivatedIfNotInCheckpointMode_VerifyPostReboot() throws Exception {
+        int sessionId = retrieveLastSessionId();
+        assertSessionFailed(sessionId);
+        assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+    }
+
+    @Test
+    public void testApexInstallerNotInAllowListCanNotInstall_staged() throws Exception {
+        assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+        // We don't really care which APEX we are trying to install here, since the session creation
+        // should fail immediately.
+        InstallUtils.commitExpectingFailure(
+                SecurityException.class,
+                "Installer not allowed to commit staged install",
+                Install.single(APEX_WRONG_SHA_V2).setBypassStangedInstallerCheck(false)
+                        .setStaged());
+    }
+
+    @Test
+    public void testApexInstallerNotInAllowListCanNotInstall_nonStaged() throws Exception {
+        assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+        // We don't really care which APEX we are trying to install here, since the session creation
+        // should fail immediately.
+        InstallUtils.commitExpectingFailure(
+                SecurityException.class,
+                "Installer not allowed to commit non-staged APEX install",
+                Install.single(APEX_WRONG_SHA_V2).setBypassStangedInstallerCheck(false));
+    }
+
+    @Test
+    public void testApexNotInAllowListCanNotInstall_staged() throws Exception {
+        assertThat(InstallUtils.getInstalledVersion("test.apex.rebootless")).isEqualTo(1);
+        TestApp apex = new TestApp("apex", "test.apex.rebootless", 2,
+                /* isApex= */ true, "test.rebootless_apex_v2.apex");
+        InstallUtils.commitExpectingFailure(
+                AssertionError.class,
+                "Update of APEX package test.apex.rebootless is not allowed "
+                        + "for com.android.tests.stagedinstallinternal",
+                Install.single(apex).setBypassAllowedApexUpdateCheck(false).setStaged());
+    }
+
+    @Test
+    public void testApexNotInAllowListCanNotInstall_nonStaged() throws Exception {
+        assertThat(InstallUtils.getInstalledVersion("test.apex.rebootless")).isEqualTo(1);
+        TestApp apex = new TestApp("apex", "test.apex.rebootless", 2,
+                /* isApex= */ true, "test.rebootless_apex_v2.apex");
+        InstallUtils.commitExpectingFailure(
+                AssertionError.class,
+                "Update of APEX package test.apex.rebootless is not allowed "
+                        + "for com.android.tests.stagedinstallinternal",
+                Install.single(apex).setBypassAllowedApexUpdateCheck(false));
+    }
+
+    @Test
+    public void testVendorApexWrongInstaller_staged() throws Exception {
+        assertThat(InstallUtils.getInstalledVersion("test.apex.rebootless")).isEqualTo(1);
+        TestApp apex = new TestApp("apex", "test.apex.rebootless", 2,
+                /* isApex= */ true, "test.rebootless_apex_v2.apex");
+        InstallUtils.commitExpectingFailure(
+                AssertionError.class,
+                "Update of APEX package test.apex.rebootless is not allowed "
+                        + "for com.android.tests.stagedinstallinternal",
+                Install.single(apex).setBypassAllowedApexUpdateCheck(false).setStaged());
+    }
+
+    @Test
+    public void testVendorApexWrongInstaller_nonStaged() throws Exception {
+        assertThat(InstallUtils.getInstalledVersion("test.apex.rebootless")).isEqualTo(1);
+        TestApp apex = new TestApp("apex", "test.apex.rebootless", 2,
+                /* isApex= */ true, "test.rebootless_apex_v2.apex");
+        InstallUtils.commitExpectingFailure(
+                AssertionError.class,
+                "Update of APEX package test.apex.rebootless is not allowed "
+                        + "for com.android.tests.stagedinstallinternal",
+                Install.single(apex).setBypassAllowedApexUpdateCheck(false));
+    }
+
+    @Test
+    public void testVendorApexCorrectInstaller_staged() throws Exception {
+        assertThat(InstallUtils.getInstalledVersion("test.apex.rebootless")).isEqualTo(1);
+        TestApp apex = new TestApp("apex", "test.apex.rebootless", 2,
+                /* isApex= */ true, "test.rebootless_apex_v2.apex");
+        int sessionId =
+                Install.single(apex).setBypassAllowedApexUpdateCheck(false).setStaged().commit();
+        InstallUtils.getPackageInstaller().abandonSession(sessionId);
+    }
+
+    @Test
+    public void testVendorApexCorrectInstaller_nonStaged() throws Exception {
+        assertThat(InstallUtils.getInstalledVersion("test.apex.rebootless")).isEqualTo(1);
+        TestApp apex = new TestApp("apex", "test.apex.rebootless", 2,
+                /* isApex= */ true, "test.rebootless_apex_v2.apex");
+        Install.single(apex).setBypassAllowedApexUpdateCheck(false).commit();
+        assertThat(InstallUtils.getInstalledVersion("test.apex.rebootless")).isEqualTo(2);
+    }
+
+    @Test
     public void testRebootlessUpdates() throws Exception {
         InstallUtils.dropShellPermissionIdentity();
         InstallUtils.adoptShellPermissionIdentity(Manifest.permission.INSTALL_PACKAGE_UPDATES);
@@ -257,6 +391,31 @@
         }
     }
 
+    @Test
+    public void testRebootlessUpdate_hasStagedSessionWithSameApex_fails() throws Exception {
+        assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+
+        int sessionId = Install.single(APEX_V2).setStaged().commit();
+        assertSessionReady(sessionId);
+        InstallUtils.commitExpectingFailure(
+                AssertionError.class,
+                "Staged session " + sessionId + " already contains " + SHIM_APEX_PACKAGE_NAME,
+                Install.single(APEX_V2));
+
+    }
+
+    private static void assertSessionApplied(int sessionId) {
+        assertSessionState(sessionId, (session) -> {
+            assertThat(session.isStagedSessionApplied()).isTrue();
+        });
+    }
+
+    private static void assertSessionFailed(int sessionId) {
+        assertSessionState(sessionId, (session) -> {
+            assertThat(session.isStagedSessionFailed()).isTrue();
+        });
+    }
+
     private static void assertSessionFailedWithMessage(int sessionId, String msg) {
         assertSessionState(sessionId, (session) -> {
             assertThat(session.isStagedSessionFailed()).isTrue();
diff --git a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
index e19f97b..5021009 100644
--- a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
+++ b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
@@ -43,7 +43,9 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.io.BufferedWriter;
 import java.io.File;
+import java.io.FileWriter;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -60,6 +62,9 @@
     private static final String APK_A = "TestAppAv1.apk";
     private static final String APK_IN_APEX_TESTAPEX_NAME = "com.android.apex.apkrollback.test";
 
+    private static final String TEST_VENDOR_APEX_ALLOW_LIST =
+            "/vendor/etc/sysconfig/test-vendor-apex-allow-list.xml";
+
     private final InstallUtilsHost mHostUtils = new InstallUtilsHost(this);
 
     /**
@@ -87,7 +92,8 @@
                 "/data/apex/active/" + APK_IN_APEX_TESTAPEX_NAME + "*.apex",
                 "/data/apex/active/" + SHIM_APEX_PACKAGE_NAME + "*.apex",
                 "/system/apex/test.rebootless_apex_v1.apex",
-                "/data/apex/active/test.apex.rebootless*.apex");
+                "/data/apex/active/test.apex.rebootless*.apex",
+                TEST_VENDOR_APEX_ALLOW_LIST);
     }
 
     @Before
@@ -134,7 +140,23 @@
         }
         getDevice().remountSystemWritable();
         assertTrue(getDevice().pushFile(apex, "/system/apex/" + fileName));
-        getDevice().reboot();
+    }
+
+    private void pushTestVendorApexAllowList(String installerPackageName) throws Exception {
+        if (!getDevice().isAdbRoot()) {
+            getDevice().enableAdbRoot();
+        }
+        getDevice().remountSystemWritable();
+        File file = File.createTempFile("test-vendor-apex-allow-list", ".xml");
+        try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
+            final String fmt =
+                    "<config>\n"
+                            + "    <allowed-vendor-apex package=\"test.apex.rebootless\" "
+                            + "       installerPackage=\"%s\" />\n"
+                            + "</config>";
+            writer.write(String.format(fmt, installerPackageName));
+        }
+        getDevice().pushFile(file, TEST_VENDOR_APEX_ALLOW_LIST);
     }
 
     /**
@@ -144,6 +166,8 @@
     @LargeTest
     public void testDuplicateApkInApexShouldFail() throws Exception {
         pushTestApex(APK_IN_APEX_TESTAPEX_NAME + "_v1.apex");
+        getDevice().reboot();
+
         runPhase("testDuplicateApkInApexShouldFail_Commit");
         getDevice().reboot();
         runPhase("testDuplicateApkInApexShouldFail_Verify");
@@ -346,11 +370,114 @@
     }
 
     @Test
+    public void testActiveApexIsRevertedOnCheckpointRollback() throws Exception {
+        assumeTrue("Device does not support updating APEX",
+                mHostUtils.isApexUpdateSupported());
+        assumeTrue("Device does not support file-system checkpoint",
+                mHostUtils.isCheckpointSupported());
+
+        // Install something so that /data/apex/active is not empty
+        runPhase("testActiveApexIsRevertedOnCheckpointRollback_Prepare");
+        getDevice().reboot();
+
+        // Stage another session which will be installed during fs-rollback mode
+        runPhase("testActiveApexIsRevertedOnCheckpointRollback_Commit");
+
+        // Set checkpoint to 0 so that we enter fs-rollback mode immediately on reboot
+        getDevice().enableAdbRoot();
+        getDevice().executeShellCommand("vdc checkpoint startCheckpoint 0");
+        getDevice().disableAdbRoot();
+        getDevice().reboot();
+
+        // Verify that session was reverted and we have fallen back to
+        // apex installed during preparation stage.
+        runPhase("testActiveApexIsRevertedOnCheckpointRollback_VerifyPostReboot");
+    }
+
+    @Test
+    public void testApexIsNotActivatedIfNotInCheckpointMode() throws Exception {
+        assumeTrue("Device does not support updating APEX",
+                mHostUtils.isApexUpdateSupported());
+        assumeTrue("Device does not support file-system checkpoint",
+                mHostUtils.isCheckpointSupported());
+
+        runPhase("testApexIsNotActivatedIfNotInCheckpointMode_Commit");
+        // Delete checkpoint file in /metadata so that device thinks
+        // fs-checkpointing was never activated
+        getDevice().enableAdbRoot();
+        getDevice().executeShellCommand("rm /metadata/vold/checkpoint");
+        getDevice().disableAdbRoot();
+        getDevice().reboot();
+        // Verify that session was not installed when not in fs-checkpoint mode
+        runPhase("testApexIsNotActivatedIfNotInCheckpointMode_VerifyPostReboot");
+    }
+
+    @Test
+    public void testApexInstallerNotInAllowListCanNotInstall() throws Exception {
+        assumeTrue("Device does not support updating APEX",
+                mHostUtils.isApexUpdateSupported());
+
+        runPhase("testApexInstallerNotInAllowListCanNotInstall_staged");
+        runPhase("testApexInstallerNotInAllowListCanNotInstall_nonStaged");
+    }
+
+    @Test
+    @LargeTest
+    public void testApexNotInAllowListCanNotInstall() throws Exception {
+        assumeTrue("Device does not support updating APEX",
+                mHostUtils.isApexUpdateSupported());
+
+        pushTestApex("test.rebootless_apex_v1.apex");
+        getDevice().reboot();
+
+        runPhase("testApexNotInAllowListCanNotInstall_staged");
+        runPhase("testApexNotInAllowListCanNotInstall_nonStaged");
+    }
+
+    @Test
+    @LargeTest
+    public void testVendorApexWrongInstaller() throws Exception {
+        assumeTrue("Device does not support updating APEX",
+                mHostUtils.isApexUpdateSupported());
+
+        pushTestVendorApexAllowList("com.wrong.installer");
+        pushTestApex("test.rebootless_apex_v1.apex");
+        getDevice().reboot();
+
+        runPhase("testVendorApexWrongInstaller_staged");
+        runPhase("testVendorApexWrongInstaller_nonStaged");
+    }
+
+    @Test
+    @LargeTest
+    public void testVendorApexCorrectInstaller() throws Exception {
+        assumeTrue("Device does not support updating APEX",
+                mHostUtils.isApexUpdateSupported());
+
+        pushTestVendorApexAllowList("com.android.tests.stagedinstallinternal");
+        pushTestApex("test.rebootless_apex_v1.apex");
+        getDevice().reboot();
+
+        runPhase("testVendorApexCorrectInstaller_staged");
+        runPhase("testVendorApexCorrectInstaller_nonStaged");
+    }
+
+    @Test
     public void testRebootlessUpdates() throws Exception {
         pushTestApex("test.rebootless_apex_v1.apex");
+        getDevice().reboot();
+
         runPhase("testRebootlessUpdates");
     }
 
+    @Test
+    public void testRebootlessUpdate_hasStagedSessionWithSameApex_fails() throws Exception {
+        assumeTrue("Device does not support updating APEX",
+                mHostUtils.isApexUpdateSupported());
+
+        runPhase("testRebootlessUpdate_hasStagedSessionWithSameApex_fails");
+    }
+
     private List<String> getStagingDirectories() throws DeviceNotAvailableException {
         String baseDir = "/data/app-staging";
         try {