Merge changes from topic "res-loader"

* changes:
  Refactor ResourcesLoader Tests
  Refactor ResourcesLoader APIs
diff --git a/Android.bp b/Android.bp
index 3ecb5a9..df276a0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -191,12 +191,20 @@
     path: "telephony/java",
 }
 
+genrule {
+    name: "statslog-telephony-common-java-gen",
+    tools: ["stats-log-api-gen"],
+    cmd: "$(location stats-log-api-gen) --java $(out) --module telephony_common"
+        + " --javaPackage com.android.internal.telephony --javaClass TelephonyCommonStatsLog",
+    out: ["com/android/internal/telephony/TelephonyCommonStatsLog.java"],
+}
+
 filegroup {
     name: "framework-telephony-common-sources",
     srcs: [
         "telephony/common/**/*.java",
+        ":statslog-telephony-common-java-gen",
     ],
-    path: "telephony/common",
 }
 
 filegroup {
@@ -265,7 +273,8 @@
 
         // etc.
         ":framework-javastream-protos",
-        ":framework-statslog-gen",
+        ":framework-statslog-gen", // StatsLogInternal.java
+        ":statslog-framework-java-gen", // FrameworkStatsLog.java
 
         // telephony annotations
         ":framework-telephony-annotations",
@@ -340,6 +349,7 @@
         "android.hardware.cas-V1.2-java",
         "android.hardware.contexthub-V1.0-java",
         "android.hardware.gnss-V1.0-java",
+        "android.hardware.gnss-V2.1-java",
         "android.hardware.health-V1.0-java-constants",
         "android.hardware.radio-V1.0-java",
         "android.hardware.radio-V1.1-java",
@@ -532,7 +542,7 @@
     srcs: [":framework-all-sources"],
     installable: false,
     static_libs: [
-        "exoplayer2-core",
+        "exoplayer2-extractor",
         "android.hardware.wifi-V1.0-java-constants",
     ],
     libs: ["icing-java-proto-lite"],
@@ -552,7 +562,7 @@
         "compat-changeid-annotation-processor",
     ],
     static_libs: [
-        "exoplayer2-core",
+        "exoplayer2-extractor",
         "android.hardware.wifi-V1.0-java-constants",
     ]
 }
@@ -603,6 +613,14 @@
     out: ["android/util/StatsLogInternal.java"],
 }
 
+genrule {
+    name: "statslog-framework-java-gen",
+    tools: ["stats-log-api-gen"],
+    cmd: "$(location stats-log-api-gen) --java $(out) --module framework" +
+         " --javaPackage com.android.internal.util --javaClass FrameworkStatsLog --worksource",
+    out: ["com/android/internal/util/FrameworkStatsLog.java"],
+}
+
 gensrcs {
     name: "framework-javastream-protos",
     depfile: true,
@@ -921,6 +939,8 @@
     srcs: [
         "core/java/android/os/incremental/IIncrementalManager.aidl",
         "core/java/android/os/incremental/IIncrementalManagerNative.aidl",
+        "core/java/android/os/incremental/IncrementalNewFileParams.aidl",
+        "core/java/android/os/incremental/IncrementalSignature.aidl",
     ],
     path: "core/java",
 }
@@ -1266,7 +1286,11 @@
     "--hide MissingPermission --hide BroadcastBehavior " +
     "--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
     "--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo " +
-    "--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.*"
+    "--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.* " +
+    "--api-lint-ignore-prefix android.icu. " +
+    "--api-lint-ignore-prefix java. " +
+    "--api-lint-ignore-prefix junit. " +
+    "--api-lint-ignore-prefix org. "
 
 build = [
     "StubLibraries.bp",
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 4d1ac0e..9abb308 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -8,6 +8,7 @@
                cmds/input/
                core/jni/
                libs/input/
+               services/core/jni/
 
 [Hook Scripts]
 checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT}
diff --git a/apct-tests/perftests/core/src/android/wm/RelayoutPerfTest.java b/apct-tests/perftests/core/src/android/wm/RelayoutPerfTest.java
index c62aad6..b6e39e1 100644
--- a/apct-tests/perftests/core/src/android/wm/RelayoutPerfTest.java
+++ b/apct-tests/perftests/core/src/android/wm/RelayoutPerfTest.java
@@ -150,7 +150,7 @@
                         mViewVisibility.getAsInt(), mFlags, mFrameNumber, mOutFrame,
                         mOutContentInsets, mOutVisibleInsets, mOutStableInsets,
                         mOutBackDropFrame, mOutDisplayCutout, mOutMergedConfiguration,
-                        mOutSurfaceControl, mOutInsetsState, new Point());
+                        mOutSurfaceControl, mOutInsetsState, new Point(), new SurfaceControl());
             }
         }
     }
diff --git a/apex/appsearch/apex_manifest.json b/apex/appsearch/apex_manifest.json
index 273b867..39a2d38 100644
--- a/apex/appsearch/apex_manifest.json
+++ b/apex/appsearch/apex_manifest.json
@@ -1,4 +1,4 @@
 {
   "name": "com.android.appsearch",
-  "version": 1
+  "version": 300000000
 }
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearch.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearch.java
deleted file mode 100644
index 8bf13ee..0000000
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearch.java
+++ /dev/null
@@ -1,854 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app.appsearch;
-
-import android.annotation.CurrentTimeMillisLong;
-import android.annotation.IntRange;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.appsearch.AppSearchSchema.PropertyConfig;
-import android.os.Bundle;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
-
-import com.google.android.icing.proto.DocumentProto;
-import com.google.android.icing.proto.PropertyProto;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Objects;
-
-/**
- * Collection of all AppSearch Document Types.
- *
- * @hide
- */
-// TODO(b/143789408) Spilt this class to make all subclasses to their own file.
-public final class AppSearch {
-
-    private AppSearch() {}
-    /**
-     * Represents a document unit.
-     *
-     * <p>Documents are constructed via {@link Document.Builder}.
-     *
-     * @hide
-     */
-    // TODO(b/143789408) set TTL for document in mProtoBuilder
-    // TODO(b/144518768) add visibility field if the stakeholders are comfortable with a no-op
-    //  opt-in for this release.
-    public static class Document {
-        private static final String TAG = "AppSearch.Document";
-
-        /**
-         * The maximum number of elements in a repeatable field. Will reject the request if exceed
-         * this limit.
-         */
-        private static final int MAX_REPEATED_PROPERTY_LENGTH = 100;
-
-        /**
-         * The maximum {@link String#length} of a {@link String} field. Will reject the request if
-         * {@link String}s longer than this.
-         */
-        private static final int MAX_STRING_LENGTH = 20_000;
-
-        /**
-         * Contains {@link Document} basic information (uri, schemaType etc) and properties ordered
-         * by keys.
-         */
-        @NonNull
-        private final DocumentProto mProto;
-
-        /** Contains all properties in {@link #mProto} to support get properties via keys. */
-        @NonNull
-        private final Bundle mPropertyBundle;
-
-        /**
-         * Create a new {@link Document}.
-         * @param proto Contains {@link Document} basic information (uri, schemaType etc) and
-         *               properties ordered by keys.
-         * @param propertyBundle Contains all properties in {@link #mProto} to support get
-         *                        properties via keys.
-         */
-        private Document(@NonNull DocumentProto proto, @NonNull Bundle propertyBundle) {
-            this.mProto = proto;
-            this.mPropertyBundle = propertyBundle;
-        }
-
-        /**
-         * Create a new {@link Document} from an existing instance.
-         *
-         * <p>This method should be only used by constructor of a subclass.
-         */
-        // TODO(b/143789408) add constructor take DocumentProto to create a document.
-        protected Document(@NonNull Document document) {
-            this(document.mProto, document.mPropertyBundle);
-        }
-
-        /** @hide */
-        Document(@NonNull DocumentProto documentProto) {
-            this(documentProto, new Bundle());
-            for (int i = 0; i < documentProto.getPropertiesCount(); i++) {
-                PropertyProto property = documentProto.getProperties(i);
-                String name = property.getName();
-                if (property.getStringValuesCount() > 0) {
-                    String[] values = new String[property.getStringValuesCount()];
-                    for (int j = 0; j < values.length; j++) {
-                        values[j] = property.getStringValues(j);
-                    }
-                    mPropertyBundle.putStringArray(name, values);
-                } else if (property.getInt64ValuesCount() > 0) {
-                    long[] values = new long[property.getInt64ValuesCount()];
-                    for (int j = 0; j < values.length; j++) {
-                        values[j] = property.getInt64Values(j);
-                    }
-                    mPropertyBundle.putLongArray(property.getName(), values);
-                } else if (property.getDoubleValuesCount() > 0) {
-                    double[] values = new double[property.getDoubleValuesCount()];
-                    for (int j = 0; j < values.length; j++) {
-                        values[j] = property.getDoubleValues(j);
-                    }
-                    mPropertyBundle.putDoubleArray(property.getName(), values);
-                } else if (property.getBooleanValuesCount() > 0) {
-                    boolean[] values = new boolean[property.getBooleanValuesCount()];
-                    for (int j = 0; j < values.length; j++) {
-                        values[j] = property.getBooleanValues(j);
-                    }
-                    mPropertyBundle.putBooleanArray(property.getName(), values);
-                } else if (property.getBytesValuesCount() > 0) {
-                    byte[][] values = new byte[property.getBytesValuesCount()][];
-                    for (int j = 0; j < values.length; j++) {
-                        values[j] = property.getBytesValues(j).toByteArray();
-                    }
-                    mPropertyBundle.putObject(name, values);
-                } else if (property.getDocumentValuesCount() > 0) {
-                    Document[] values = new Document[property.getDocumentValuesCount()];
-                    for (int j = 0; j < values.length; j++) {
-                        values[j] = new Document(property.getDocumentValues(j));
-                    }
-                    mPropertyBundle.putObject(name, values);
-                } else {
-                    throw new IllegalStateException("Unknown type of value: " + name);
-                }
-            }
-        }
-
-        /**
-         * Creates a new {@link Document.Builder}.
-         *
-         * @param uri The uri of {@link Document}.
-         * @param schemaType The schema type of the {@link Document}. The passed-in
-         *     {@code schemaType} must be defined using {@link AppSearchManager#setSchema} prior to
-         *     inserting a document of this {@code schemaType} into the AppSearch index using
-         *     {@link AppSearchManager#put}. Otherwise, the document will be rejected by
-         *     {@link AppSearchManager#put}.
-         * @hide
-         */
-        @NonNull
-        public static Builder newBuilder(@NonNull String uri, @NonNull String schemaType) {
-            return new Builder(uri, schemaType);
-        }
-
-        /**
-         * Get the {@link DocumentProto} of the {@link Document}.
-         *
-         * <p>The {@link DocumentProto} contains {@link Document}'s basic information and all
-         *    properties ordered by keys.
-         * @hide
-         */
-        @NonNull
-        @VisibleForTesting
-        public DocumentProto getProto() {
-            return mProto;
-        }
-
-        /**
-         * Get the uri of the {@link Document}.
-         *
-         * @hide
-         */
-        @NonNull
-        public String getUri() {
-            return mProto.getUri();
-        }
-
-        /**
-         * Get the schema type of the {@link Document}.
-         * @hide
-         */
-        @NonNull
-        public String getSchemaType() {
-            return mProto.getSchema();
-        }
-
-        /**
-         * Get the creation timestamp in milliseconds of the {@link Document}. Value will be in the
-         * {@link System#currentTimeMillis()} time base.
-         *
-         * @hide
-         */
-        @CurrentTimeMillisLong
-        public long getCreationTimestampMillis() {
-            return mProto.getCreationTimestampMs();
-        }
-
-        /**
-         * Returns the score of the {@link Document}.
-         *
-         * <p>The score is a query-independent measure of the document's quality, relative to other
-         * {@link Document}s of the same type.
-         *
-         * <p>The default value is 0.
-         *
-         * @hide
-         */
-        public int getScore() {
-            return mProto.getScore();
-        }
-
-        /**
-         * Retrieve a {@link String} value by key.
-         *
-         * @param key The key to look for.
-         * @return The first {@link String} associated with the given key or {@code null} if there
-         *     is no such key or the value is of a different type.
-         * @hide
-         */
-        @Nullable
-        public String getPropertyString(@NonNull String key) {
-            String[] propertyArray = getPropertyStringArray(key);
-            if (ArrayUtils.isEmpty(propertyArray)) {
-                return null;
-            }
-            warnIfSinglePropertyTooLong("String", key, propertyArray.length);
-            return propertyArray[0];
-        }
-
-        /**
-         * Retrieve a {@link Long} value by key.
-         *
-         * @param key The key to look for.
-         * @return The first {@link Long} associated with the given key or {@code null} if there
-         *     is no such key or the value is of a different type.
-         * @hide
-         */
-        @Nullable
-        public Long getPropertyLong(@NonNull String key) {
-            long[] propertyArray = getPropertyLongArray(key);
-            if (ArrayUtils.isEmpty(propertyArray)) {
-                return null;
-            }
-            warnIfSinglePropertyTooLong("Long", key, propertyArray.length);
-            return propertyArray[0];
-        }
-
-        /**
-         * Retrieve a {@link Double} value by key.
-         *
-         * @param key The key to look for.
-         * @return The first {@link Double} associated with the given key or {@code null} if there
-         *     is no such key or the value is of a different type.
-         * @hide
-         */
-        @Nullable
-        public Double getPropertyDouble(@NonNull String key) {
-            double[] propertyArray = getPropertyDoubleArray(key);
-            // TODO(tytytyww): Add support double array to ArraysUtils.isEmpty().
-            if (propertyArray == null || propertyArray.length == 0) {
-                return null;
-            }
-            warnIfSinglePropertyTooLong("Double", key, propertyArray.length);
-            return propertyArray[0];
-        }
-
-        /**
-         * Retrieve a {@link Boolean} value by key.
-         *
-         * @param key The key to look for.
-         * @return The first {@link Boolean} associated with the given key or {@code null} if there
-         *     is no such key or the value is of a different type.
-         * @hide
-         */
-        @Nullable
-        public Boolean getPropertyBoolean(@NonNull String key) {
-            boolean[] propertyArray = getPropertyBooleanArray(key);
-            if (ArrayUtils.isEmpty(propertyArray)) {
-                return null;
-            }
-            warnIfSinglePropertyTooLong("Boolean", key, propertyArray.length);
-            return propertyArray[0];
-        }
-
-        /** Prints a warning to logcat if the given propertyLength is greater than 1. */
-        private static void warnIfSinglePropertyTooLong(
-                @NonNull String propertyType, @NonNull String key, int propertyLength) {
-            if (propertyLength > 1) {
-                Log.w(TAG, "The value for \"" + key + "\" contains " + propertyLength
-                        + " elements. Only the first one will be returned from "
-                        + "getProperty" + propertyType + "(). Try getProperty" + propertyType
-                        + "Array().");
-            }
-        }
-
-        /**
-         * Retrieve a repeated {@code String} property by key.
-         *
-         * @param key The key to look for.
-         * @return The {@code String[]} associated with the given key, or {@code null} if no value
-         *     is set or the value is of a different type.
-         * @hide
-         */
-        @Nullable
-        public String[] getPropertyStringArray(@NonNull String key) {
-            return getAndCastPropertyArray(key, String[].class);
-        }
-
-        /**
-         * Retrieve a repeated {@code long} property by key.
-         *
-         * @param key The key to look for.
-         * @return The {@code long[]} associated with the given key, or {@code null} if no value is
-         *     set or the value is of a different type.
-         * @hide
-         */
-        @Nullable
-        public long[] getPropertyLongArray(@NonNull String key) {
-            return getAndCastPropertyArray(key, long[].class);
-        }
-
-        /**
-         * Retrieve a repeated {@code double} property by key.
-         *
-         * @param key The key to look for.
-         * @return The {@code double[]} associated with the given key, or {@code null} if no value
-         *     is set or the value is of a different type.
-         * @hide
-         */
-        @Nullable
-        public double[] getPropertyDoubleArray(@NonNull String key) {
-            return getAndCastPropertyArray(key, double[].class);
-        }
-
-        /**
-         * Retrieve a repeated {@code boolean} property by key.
-         *
-         * @param key The key to look for.
-         * @return The {@code boolean[]} associated with the given key, or {@code null} if no value
-         *     is set or the value is of a different type.
-         * @hide
-         */
-        @Nullable
-        public boolean[] getPropertyBooleanArray(@NonNull String key) {
-            return getAndCastPropertyArray(key, boolean[].class);
-        }
-
-        /**
-         * Gets a repeated property of the given key, and casts it to the given class type, which
-         * must be an array class type.
-         */
-        @Nullable
-        private <T> T getAndCastPropertyArray(@NonNull String key, @NonNull Class<T> tClass) {
-            Object value = mPropertyBundle.get(key);
-            if (value == null) {
-                return null;
-            }
-            try {
-                return tClass.cast(value);
-            } catch (ClassCastException e) {
-                Log.w(TAG, "Error casting to requested type for key \"" + key + "\"", e);
-                return null;
-            }
-        }
-
-        @Override
-        public boolean equals(@Nullable Object other) {
-            // Check only proto's equality is sufficient here since all properties in
-            // mPropertyBundle are ordered by keys and stored in proto.
-            if (this == other) {
-                return true;
-            }
-            if (!(other instanceof Document)) {
-                return false;
-            }
-            Document otherDocument = (Document) other;
-            return this.mProto.equals(otherDocument.mProto);
-        }
-
-        @Override
-        public int hashCode() {
-            // Hash only proto is sufficient here since all properties in mPropertyBundle are
-            // ordered by keys and stored in proto.
-            return mProto.hashCode();
-        }
-
-        @Override
-        public String toString() {
-            return mProto.toString();
-        }
-
-        /**
-         * The builder class for {@link Document}.
-         *
-         * @param <BuilderType> Type of subclass who extend this.
-         * @hide
-         */
-        public static class Builder<BuilderType extends Builder> {
-
-            private final Bundle mPropertyBundle = new Bundle();
-            private final DocumentProto.Builder mProtoBuilder = DocumentProto.newBuilder();
-            private final BuilderType mBuilderTypeInstance;
-
-            /**
-             * Create a new {@link Document.Builder}.
-             *
-             * @param uri The uri of {@link Document}.
-             * @param schemaType The schema type of the {@link Document}. The passed-in
-             *     {@code schemaType} must be defined using {@link AppSearchManager#setSchema} prior
-             *     to inserting a document of this {@code schemaType} into the AppSearch index using
-             *     {@link AppSearchManager#put}. Otherwise, the document will be rejected by
-             *     {@link AppSearchManager#put}.
-             * @hide
-             */
-            protected Builder(@NonNull String uri, @NonNull String schemaType) {
-                mBuilderTypeInstance = (BuilderType) this;
-                mProtoBuilder.setUri(uri).setSchema(schemaType);
-                 // Set current timestamp for creation timestamp by default.
-                setCreationTimestampMillis(System.currentTimeMillis());
-            }
-
-            /**
-             * Set the score of the {@link Document}.
-             *
-             * <p>The score is a query-independent measure of the document's quality, relative to
-             * other {@link Document}s of the same type.
-             *
-             * @throws IllegalArgumentException If the provided value is negative.
-             * @hide
-             */
-            @NonNull
-            public BuilderType setScore(@IntRange(from = 0, to = Integer.MAX_VALUE) int score) {
-                if (score < 0) {
-                    throw new IllegalArgumentException("Document score cannot be negative");
-                }
-                mProtoBuilder.setScore(score);
-                return mBuilderTypeInstance;
-            }
-
-            /**
-             * Set the creation timestamp in milliseconds of the {@link Document}. Should be set
-             * using a value obtained from the {@link System#currentTimeMillis()} time base.
-             *
-             * @hide
-             */
-            @NonNull
-            public BuilderType setCreationTimestampMillis(
-                    @CurrentTimeMillisLong long creationTimestampMillis) {
-                mProtoBuilder.setCreationTimestampMs(creationTimestampMillis);
-                return mBuilderTypeInstance;
-            }
-
-            /**
-             * Sets one or multiple {@code String} values for a property, replacing its previous
-             * values.
-             *
-             * @param key The key associated with the {@code values}.
-             * @param values The {@code String} values of the property.
-             * @hide
-             */
-            @NonNull
-            public BuilderType setProperty(@NonNull String key, @NonNull String... values) {
-                putInBundle(mPropertyBundle, key, values);
-                return mBuilderTypeInstance;
-            }
-
-            /**
-             * Sets one or multiple {@code boolean} values for a property, replacing its previous
-             * values.
-             *
-             * @param key The key associated with the {@code values}.
-             * @param values The {@code boolean} values of the schema.org property.
-             * @hide
-             */
-            @NonNull
-            public BuilderType setProperty(@NonNull String key, @NonNull boolean... values) {
-                putInBundle(mPropertyBundle, key, values);
-                return mBuilderTypeInstance;
-            }
-
-            /**
-             * Sets one or multiple {@code long} values for a property, replacing its previous
-             * values.
-             *
-             * @param key The key associated with the {@code values}.
-             * @param values The {@code long} values of the schema.org property.
-             * @hide
-             */
-            @NonNull
-            public BuilderType setProperty(@NonNull String key, @NonNull long... values) {
-                putInBundle(mPropertyBundle, key, values);
-                return mBuilderTypeInstance;
-            }
-
-            /**
-             * Sets one or multiple {@code double} values for a property, replacing its previous
-             * values.
-             *
-             * @param key The key associated with the {@code values}.
-             * @param values The {@code double} values of the schema.org property.
-             * @hide
-             */
-            @NonNull
-            public BuilderType setProperty(@NonNull String key, @NonNull double... values) {
-                putInBundle(mPropertyBundle, key, values);
-                return mBuilderTypeInstance;
-            }
-
-            private static void putInBundle(
-                    @NonNull Bundle bundle, @NonNull String key, @NonNull String... values)
-                    throws IllegalArgumentException {
-                Objects.requireNonNull(key);
-                Objects.requireNonNull(values);
-                validateRepeatedPropertyLength(key, values.length);
-                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 + ".");
-                    }
-                }
-                bundle.putStringArray(key, values);
-            }
-
-            private static void putInBundle(
-                    @NonNull Bundle bundle, @NonNull String key, @NonNull boolean... values) {
-                Objects.requireNonNull(key);
-                Objects.requireNonNull(values);
-                validateRepeatedPropertyLength(key, values.length);
-                bundle.putBooleanArray(key, values);
-            }
-
-            private static void putInBundle(
-                    @NonNull Bundle bundle, @NonNull String key, @NonNull double... values) {
-                Objects.requireNonNull(key);
-                Objects.requireNonNull(values);
-                validateRepeatedPropertyLength(key, values.length);
-                bundle.putDoubleArray(key, values);
-            }
-
-            private static void putInBundle(
-                    @NonNull Bundle bundle, @NonNull String key, @NonNull long... values) {
-                Objects.requireNonNull(key);
-                Objects.requireNonNull(values);
-                validateRepeatedPropertyLength(key, values.length);
-                bundle.putLongArray(key, values);
-            }
-
-            private static void validateRepeatedPropertyLength(@NonNull String key, int length) {
-                if (length == 0) {
-                    throw new IllegalArgumentException("The input array is empty.");
-                } else if (length > MAX_REPEATED_PROPERTY_LENGTH) {
-                    throw new IllegalArgumentException(
-                            "Repeated property \"" + key + "\" has length " + length
-                                    + ", which exceeds the limit of "
-                                    + MAX_REPEATED_PROPERTY_LENGTH);
-                }
-            }
-
-            /**
-             * Builds the {@link Document} object.
-             * @hide
-             */
-            public Document build() {
-                // Build proto by sorting the keys in propertyBundle to exclude the influence of
-                // order. Therefore documents will generate same proto as long as the contents are
-                // same. Note that the order of repeated fields is still preserved.
-                ArrayList<String> keys = new ArrayList<>(mPropertyBundle.keySet());
-                Collections.sort(keys);
-                for (String key : keys) {
-                    Object values = mPropertyBundle.get(key);
-                    PropertyProto.Builder propertyProto = PropertyProto.newBuilder().setName(key);
-                    if (values instanceof boolean[]) {
-                        for (boolean value : (boolean[]) values) {
-                            propertyProto.addBooleanValues(value);
-                        }
-                    } else if (values instanceof long[]) {
-                        for (long value : (long[]) values) {
-                            propertyProto.addInt64Values(value);
-                        }
-                    } else if (values instanceof double[]) {
-                        for (double value : (double[]) values) {
-                            propertyProto.addDoubleValues(value);
-                        }
-                    } else if (values instanceof String[]) {
-                        for (String value : (String[]) values) {
-                            propertyProto.addStringValues(value);
-                        }
-                    } else {
-                        throw new IllegalStateException(
-                                "Property \"" + key + "\" has unsupported value type \""
-                                        + values.getClass().getSimpleName() + "\"");
-                    }
-                    mProtoBuilder.addProperties(propertyProto);
-                }
-                return new Document(mProtoBuilder.build(), mPropertyBundle);
-            }
-        }
-    }
-
-    /**
-     * Encapsulates a {@link Document} that represent an email.
-     *
-     * <p>This class is a higher level implement of {@link Document}.
-     *
-     * <p>This class will eventually migrate to Jetpack, where it will become public API.
-     *
-     * @hide
-     */
-    public static class Email extends Document {
-        private static final String KEY_FROM = "from";
-        private static final String KEY_TO = "to";
-        private static final String KEY_CC = "cc";
-        private static final String KEY_BCC = "bcc";
-        private static final String KEY_SUBJECT = "subject";
-        private static final String KEY_BODY = "body";
-
-        /** The name of the schema type for {@link Email} documents.*/
-        public static final String SCHEMA_TYPE = "builtin:Email";
-
-        public static final AppSearchSchema SCHEMA = AppSearchSchema.newBuilder(SCHEMA_TYPE)
-                .addProperty(AppSearchSchema.newPropertyBuilder(KEY_FROM)
-                        .setDataType(PropertyConfig.DATA_TYPE_STRING)
-                        .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
-                        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
-                        .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
-                        .build()
-
-                ).addProperty(AppSearchSchema.newPropertyBuilder(KEY_TO)
-                        .setDataType(PropertyConfig.DATA_TYPE_STRING)
-                        .setCardinality(PropertyConfig.CARDINALITY_REPEATED)
-                        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
-                        .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
-                        .build()
-
-                ).addProperty(AppSearchSchema.newPropertyBuilder(KEY_CC)
-                        .setDataType(PropertyConfig.DATA_TYPE_STRING)
-                        .setCardinality(PropertyConfig.CARDINALITY_REPEATED)
-                        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
-                        .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
-                        .build()
-
-                ).addProperty(AppSearchSchema.newPropertyBuilder(KEY_BCC)
-                        .setDataType(PropertyConfig.DATA_TYPE_STRING)
-                        .setCardinality(PropertyConfig.CARDINALITY_REPEATED)
-                        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
-                        .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
-                        .build()
-
-                ).addProperty(AppSearchSchema.newPropertyBuilder(KEY_SUBJECT)
-                        .setDataType(PropertyConfig.DATA_TYPE_STRING)
-                        .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
-                        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
-                        .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
-                        .build()
-
-                ).addProperty(AppSearchSchema.newPropertyBuilder(KEY_BODY)
-                        .setDataType(PropertyConfig.DATA_TYPE_STRING)
-                        .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
-                        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
-                        .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
-                        .build()
-
-                ).build();
-
-        /**
-         * Creates a new {@link Email.Builder}.
-         *
-         * @param uri The uri of {@link Email}.
-         */
-        public static Builder newBuilder(@NonNull String uri) {
-            return new Builder(uri);
-        }
-
-        /**
-         * Creates a new {@link Email} from the contents of an existing {@link Document}.
-         *
-         * @param document The {@link Document} containing the email content.
-         */
-        public Email(@NonNull Document document) {
-            super(document);
-        }
-
-        /**
-         * Get the from address of {@link Email}.
-         *
-         * @return Returns the subject of {@link Email} or {@code null} if it's not been set yet.
-         * @hide
-         */
-        @Nullable
-        public String getFrom() {
-            return getPropertyString(KEY_FROM);
-        }
-
-        /**
-         * Get the destination addresses of {@link Email}.
-         *
-         * @return Returns the destination addresses of {@link Email} or {@code null} if it's not
-         *         been set yet.
-         * @hide
-         */
-        @Nullable
-        public String[] getTo() {
-            return getPropertyStringArray(KEY_TO);
-        }
-
-        /**
-         * Get the CC list of {@link Email}.
-         *
-         * @return Returns the CC list of {@link Email} or {@code null} if it's not been set yet.
-         * @hide
-         */
-        @Nullable
-        public String[] getCc() {
-            return getPropertyStringArray(KEY_CC);
-        }
-
-        /**
-         * Get the BCC list of {@link Email}.
-         *
-         * @return Returns the BCC list of {@link Email} or {@code null} if it's not been set yet.
-         * @hide
-         */
-        @Nullable
-        public String[] getBcc() {
-            return getPropertyStringArray(KEY_BCC);
-        }
-
-        /**
-         * Get the subject of {@link Email}.
-         *
-         * @return Returns the value subject of {@link Email} or {@code null} if it's not been set
-         * yet.
-         * @hide
-         */
-        @Nullable
-        public String getSubject() {
-            return getPropertyString(KEY_SUBJECT);
-        }
-
-        /**
-         * Get the body of {@link Email}.
-         *
-         * @return Returns the body of {@link Email} or {@code null} if it's not been set yet.
-         * @hide
-         */
-        @Nullable
-        public String getBody() {
-            return getPropertyString(KEY_BODY);
-        }
-
-        /**
-         * The builder class for {@link Email}.
-         * @hide
-         */
-        public static class Builder extends Document.Builder<Email.Builder> {
-
-            /**
-             * Create a new {@link Email.Builder}
-             * @param uri The Uri of the Email.
-             * @hide
-             */
-            private Builder(@NonNull String uri) {
-                super(uri, SCHEMA_TYPE);
-            }
-
-            /**
-             * Set the from address of {@link Email}
-             * @hide
-             */
-            @NonNull
-            public Email.Builder setFrom(@NonNull String from) {
-                setProperty(KEY_FROM, from);
-                return this;
-            }
-
-            /**
-             * Set the destination address of {@link Email}
-             * @hide
-             */
-            @NonNull
-            public Email.Builder setTo(@NonNull String... to) {
-                setProperty(KEY_TO, to);
-                return this;
-            }
-
-            /**
-             * Set the CC list of {@link Email}
-             * @hide
-             */
-            @NonNull
-            public Email.Builder setCc(@NonNull String... cc) {
-                setProperty(KEY_CC, cc);
-                return this;
-            }
-
-            /**
-             * Set the BCC list of {@link Email}
-             * @hide
-             */
-            @NonNull
-            public Email.Builder setBcc(@NonNull String... bcc) {
-                setProperty(KEY_BCC, bcc);
-                return this;
-            }
-
-            /**
-             * Set the subject of {@link Email}
-             * @hide
-             */
-            @NonNull
-            public Email.Builder setSubject(@NonNull String subject) {
-                setProperty(KEY_SUBJECT, subject);
-                return this;
-            }
-
-            /**
-             * Set the body of {@link Email}
-             * @hide
-             */
-            @NonNull
-            public Email.Builder setBody(@NonNull String body) {
-                setProperty(KEY_BODY, body);
-                return this;
-            }
-
-            /**
-             * Builds the {@link Email} object.
-             *
-             * @hide
-             */
-            @NonNull
-            @Override
-            public Email build() {
-                return new Email(super.build());
-            }
-        }
-    }
-}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchDocument.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchDocument.java
new file mode 100644
index 0000000..ff0f0dd
--- /dev/null
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchDocument.java
@@ -0,0 +1,724 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.appsearch;
+
+import android.annotation.CurrentTimeMillisLong;
+import android.annotation.DurationMillisLong;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.Preconditions;
+
+import com.google.android.icing.proto.DocumentProto;
+import com.google.android.icing.proto.PropertyProto;
+import com.google.android.icing.protobuf.ByteString;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Represents a document unit.
+ *
+ * <p>Documents are constructed via {@link AppSearchDocument.Builder}.
+ * @hide
+ */
+public class AppSearchDocument {
+    private static final String TAG = "AppSearchDocument";
+
+    /**
+     * The maximum number of elements in a repeatable field. Will reject the request if exceed
+     * this limit.
+     */
+    private static final int MAX_REPEATED_PROPERTY_LENGTH = 100;
+
+    /**
+     * The maximum {@link String#length} of a {@link String} field. Will reject the request if
+     * {@link String}s longer than this.
+     */
+    private static final int MAX_STRING_LENGTH = 20_000;
+
+    /**
+     * Contains {@link AppSearchDocument} basic information (uri, schemaType etc) and properties
+     * ordered by keys.
+     */
+    @NonNull
+    private final DocumentProto mProto;
+
+    /** Contains all properties in {@link #mProto} to support getting properties via keys. */
+    @NonNull
+    private final Map<String, Object> mProperties;
+
+    /**
+     * Create a new {@link AppSearchDocument}.
+     * @param proto Contains {@link AppSearchDocument} basic information (uri, schemaType etc) and
+     *               properties ordered by keys.
+     * @param propertiesMap Contains all properties in {@link #mProto} to support get properties
+     *                      via keys.
+     */
+    private AppSearchDocument(@NonNull DocumentProto proto,
+            @NonNull Map<String, Object> propertiesMap) {
+        mProto = proto;
+        mProperties = propertiesMap;
+    }
+
+    /**
+     * Create a new {@link AppSearchDocument} from an existing instance.
+     *
+     * <p>This method should be only used by constructor of a subclass.
+     */
+    protected AppSearchDocument(@NonNull AppSearchDocument document) {
+        this(document.mProto, document.mProperties);
+    }
+
+    /** @hide */
+    AppSearchDocument(@NonNull DocumentProto documentProto) {
+        this(documentProto, new ArrayMap<>());
+        for (int i = 0; i < documentProto.getPropertiesCount(); i++) {
+            PropertyProto property = documentProto.getProperties(i);
+            String name = property.getName();
+            if (property.getStringValuesCount() > 0) {
+                String[] values = new String[property.getStringValuesCount()];
+                for (int j = 0; j < values.length; j++) {
+                    values[j] = property.getStringValues(j);
+                }
+                mProperties.put(name, values);
+            } else if (property.getInt64ValuesCount() > 0) {
+                long[] values = new long[property.getInt64ValuesCount()];
+                for (int j = 0; j < values.length; j++) {
+                    values[j] = property.getInt64Values(j);
+                }
+                mProperties.put(property.getName(), values);
+            } else if (property.getDoubleValuesCount() > 0) {
+                double[] values = new double[property.getDoubleValuesCount()];
+                for (int j = 0; j < values.length; j++) {
+                    values[j] = property.getDoubleValues(j);
+                }
+                mProperties.put(property.getName(), values);
+            } else if (property.getBooleanValuesCount() > 0) {
+                boolean[] values = new boolean[property.getBooleanValuesCount()];
+                for (int j = 0; j < values.length; j++) {
+                    values[j] = property.getBooleanValues(j);
+                }
+                mProperties.put(property.getName(), values);
+            } else if (property.getBytesValuesCount() > 0) {
+                byte[][] values = new byte[property.getBytesValuesCount()][];
+                for (int j = 0; j < values.length; j++) {
+                    values[j] = property.getBytesValues(j).toByteArray();
+                }
+                mProperties.put(name, values);
+            } else if (property.getDocumentValuesCount() > 0) {
+                AppSearchDocument[] values =
+                        new AppSearchDocument[property.getDocumentValuesCount()];
+                for (int j = 0; j < values.length; j++) {
+                    values[j] = new AppSearchDocument(property.getDocumentValues(j));
+                }
+                mProperties.put(name, values);
+            } else {
+                throw new IllegalStateException("Unknown type of value: " + name);
+            }
+        }
+    }
+
+    /**
+     * Get the {@link DocumentProto} of the {@link AppSearchDocument}.
+     *
+     * <p>The {@link DocumentProto} contains {@link AppSearchDocument}'s basic information and all
+     *    properties ordered by keys.
+     * @hide
+     */
+    @NonNull
+    @VisibleForTesting
+    public DocumentProto getProto() {
+        return mProto;
+    }
+
+    /**
+     * Get the uri of the {@link AppSearchDocument}.
+     *
+     * @hide
+     */
+    @NonNull
+    public String getUri() {
+        return mProto.getUri();
+    }
+
+    /**
+     * Get the schema type of the {@link AppSearchDocument}.
+     * @hide
+     */
+    @NonNull
+    public String getSchemaType() {
+        return mProto.getSchema();
+    }
+
+    /**
+     * Get the creation timestamp in milliseconds of the {@link AppSearchDocument}. Value will be in
+     * the {@link System#currentTimeMillis()} time base.
+     *
+     * @hide
+     */
+    @CurrentTimeMillisLong
+    public long getCreationTimestampMillis() {
+        return mProto.getCreationTimestampMs();
+    }
+
+    /**
+     * Returns the TTL (Time To Live) of the {@link AppSearchDocument}, in milliseconds.
+     *
+     * <p>The default value is 0, which means the document is permanent and won't be auto-deleted
+     *    until the app is uninstalled.
+     *
+     * @hide
+     */
+    @DurationMillisLong
+    public long getTtlMillis() {
+        return mProto.getTtlMs();
+    }
+
+    /**
+     * Returns the score of the {@link AppSearchDocument}.
+     *
+     * <p>The score is a query-independent measure of the document's quality, relative to other
+     * {@link AppSearchDocument}s of the same type.
+     *
+     * <p>The default value is 0.
+     *
+     * @hide
+     */
+    public int getScore() {
+        return mProto.getScore();
+    }
+
+    /**
+     * Retrieve a {@link String} value by key.
+     *
+     * @param key The key to look for.
+     * @return The first {@link String} associated with the given key or {@code null} if there
+     *         is no such key or the value is of a different type.
+     * @hide
+     */
+    @Nullable
+    public String getPropertyString(@NonNull String key) {
+        String[] propertyArray = getPropertyStringArray(key);
+        if (ArrayUtils.isEmpty(propertyArray)) {
+            return null;
+        }
+        warnIfSinglePropertyTooLong("String", key, propertyArray.length);
+        return propertyArray[0];
+    }
+
+    /**
+     * Retrieve a {@link Long} value by key.
+     *
+     * @param key The key to look for.
+     * @return The first {@link Long} associated with the given key or {@code null} if there
+     *         is no such key or the value is of a different type.
+     * @hide
+     */
+    @Nullable
+    public Long getPropertyLong(@NonNull String key) {
+        long[] propertyArray = getPropertyLongArray(key);
+        if (ArrayUtils.isEmpty(propertyArray)) {
+            return null;
+        }
+        warnIfSinglePropertyTooLong("Long", key, propertyArray.length);
+        return propertyArray[0];
+    }
+
+    /**
+     * Retrieve a {@link Double} value by key.
+     *
+     * @param key The key to look for.
+     * @return The first {@link Double} associated with the given key or {@code null} if there
+     *         is no such key or the value is of a different type.
+     * @hide
+     */
+    @Nullable
+    public Double getPropertyDouble(@NonNull String key) {
+        double[] propertyArray = getPropertyDoubleArray(key);
+        // TODO(tytytyww): Add support double array to ArraysUtils.isEmpty().
+        if (propertyArray == null || propertyArray.length == 0) {
+            return null;
+        }
+        warnIfSinglePropertyTooLong("Double", key, propertyArray.length);
+        return propertyArray[0];
+    }
+
+    /**
+     * Retrieve a {@link Boolean} value by key.
+     *
+     * @param key The key to look for.
+     * @return The first {@link Boolean} associated with the given key or {@code null} if there
+     *         is no such key or the value is of a different type.
+     * @hide
+     */
+    @Nullable
+    public Boolean getPropertyBoolean(@NonNull String key) {
+        boolean[] propertyArray = getPropertyBooleanArray(key);
+        if (ArrayUtils.isEmpty(propertyArray)) {
+            return null;
+        }
+        warnIfSinglePropertyTooLong("Boolean", key, propertyArray.length);
+        return propertyArray[0];
+    }
+
+    /**
+     * Retrieve a {@code byte[]} value by key.
+     *
+     * @param key The key to look for.
+     * @return The first {@code byte[]} associated with the given key or {@code null} if there
+     *         is no such key or the value is of a different type.
+     */
+    @Nullable
+    public byte[] getPropertyBytes(@NonNull String key) {
+        byte[][] propertyArray = getPropertyBytesArray(key);
+        if (ArrayUtils.isEmpty(propertyArray)) {
+            return null;
+        }
+        warnIfSinglePropertyTooLong("ByteArray", key, propertyArray.length);
+        return propertyArray[0];
+    }
+
+    /**
+     * Retrieve a {@link AppSearchDocument} value by key.
+     *
+     * @param key The key to look for.
+     * @return The first {@link AppSearchDocument} associated with the given key or {@code null} if
+     *         there is no such key or the value is of a different type.
+     */
+    @Nullable
+    public AppSearchDocument getPropertyDocument(@NonNull String key) {
+        AppSearchDocument[] propertyArray = getPropertyDocumentArray(key);
+        if (ArrayUtils.isEmpty(propertyArray)) {
+            return null;
+        }
+        warnIfSinglePropertyTooLong("Document", key, propertyArray.length);
+        return propertyArray[0];
+    }
+
+    /** Prints a warning to logcat if the given propertyLength is greater than 1. */
+    private static void warnIfSinglePropertyTooLong(
+            @NonNull String propertyType, @NonNull String key, int propertyLength) {
+        if (propertyLength > 1) {
+            Log.w(TAG, "The value for \"" + key + "\" contains " + propertyLength
+                    + " elements. Only the first one will be returned from "
+                    + "getProperty" + propertyType + "(). Try getProperty" + propertyType
+                    + "Array().");
+        }
+    }
+
+    /**
+     * Retrieve a repeated {@code String} property by key.
+     *
+     * @param key The key to look for.
+     * @return The {@code String[]} associated with the given key, or {@code null} if no value
+     *         is set or the value is of a different type.
+     * @hide
+     */
+    @Nullable
+    public String[] getPropertyStringArray(@NonNull String key) {
+        return getAndCastPropertyArray(key, String[].class);
+    }
+
+    /**
+     * Retrieve a repeated {@code long} property by key.
+     *
+     * @param key The key to look for.
+     * @return The {@code long[]} associated with the given key, or {@code null} if no value is
+     *         set or the value is of a different type.
+     * @hide
+     */
+    @Nullable
+    public long[] getPropertyLongArray(@NonNull String key) {
+        return getAndCastPropertyArray(key, long[].class);
+    }
+
+    /**
+     * Retrieve a repeated {@code double} property by key.
+     *
+     * @param key The key to look for.
+     * @return The {@code double[]} associated with the given key, or {@code null} if no value
+     *         is set or the value is of a different type.
+     * @hide
+     */
+    @Nullable
+    public double[] getPropertyDoubleArray(@NonNull String key) {
+        return getAndCastPropertyArray(key, double[].class);
+    }
+
+    /**
+     * Retrieve a repeated {@code boolean} property by key.
+     *
+     * @param key The key to look for.
+     * @return The {@code boolean[]} associated with the given key, or {@code null} if no value
+     *         is set or the value is of a different type.
+     * @hide
+     */
+    @Nullable
+    public boolean[] getPropertyBooleanArray(@NonNull String key) {
+        return getAndCastPropertyArray(key, boolean[].class);
+    }
+
+    /**
+     * Retrieve a {@code byte[][]} property by key.
+     *
+     * @param key The key to look for.
+     * @return The {@code byte[][]} associated with the given key, or {@code null} if no value
+     *         is set or the value is of a different type.
+     */
+    @Nullable
+    public byte[][] getPropertyBytesArray(@NonNull String key) {
+        return getAndCastPropertyArray(key, byte[][].class);
+    }
+
+    /**
+     * Retrieve a repeated {@link AppSearchDocument} property by key.
+     *
+     * @param key The key to look for.
+     * @return The {@link AppSearchDocument[]} associated with the given key, or {@code null} if no
+     *         value is set or the value is of a different type.
+     */
+    @Nullable
+    public AppSearchDocument[] getPropertyDocumentArray(@NonNull String key) {
+        return getAndCastPropertyArray(key, AppSearchDocument[].class);
+    }
+
+    /**
+     * Gets a repeated property of the given key, and casts it to the given class type, which
+     * must be an array class type.
+     */
+    @Nullable
+    private <T> T getAndCastPropertyArray(@NonNull String key, @NonNull Class<T> tClass) {
+        Object value = mProperties.get(key);
+        if (value == null) {
+            return null;
+        }
+        try {
+            return tClass.cast(value);
+        } catch (ClassCastException e) {
+            Log.w(TAG, "Error casting to requested type for key \"" + key + "\"", e);
+            return null;
+        }
+    }
+
+    @Override
+    public boolean equals(@Nullable Object other) {
+        // Check only proto's equality is sufficient here since all properties in
+        // mProperties are ordered by keys and stored in proto.
+        if (this == other) {
+            return true;
+        }
+        if (!(other instanceof AppSearchDocument)) {
+            return false;
+        }
+        AppSearchDocument otherDocument = (AppSearchDocument) other;
+        return this.mProto.equals(otherDocument.mProto);
+    }
+
+    @Override
+    public int hashCode() {
+        // Hash only proto is sufficient here since all properties in mProperties are ordered by
+        // keys and stored in proto.
+        return mProto.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return mProto.toString();
+    }
+
+    /**
+     * The builder class for {@link AppSearchDocument}.
+     *
+     * @param <BuilderType> Type of subclass who extend this.
+     * @hide
+     */
+    public static class Builder<BuilderType extends Builder> {
+
+        private final Map<String, Object> mProperties = new ArrayMap<>();
+        private final DocumentProto.Builder mProtoBuilder = DocumentProto.newBuilder();
+        private final BuilderType mBuilderTypeInstance;
+
+        /**
+         * Create a new {@link AppSearchDocument.Builder}.
+         *
+         * @param uri The uri of {@link AppSearchDocument}.
+         * @param schemaType The schema type of the {@link AppSearchDocument}. The passed-in
+         *       {@code schemaType} must be defined using {@link AppSearchManager#setSchema} prior
+         *       to inserting a document of this {@code schemaType} into the AppSearch index using
+         *       {@link AppSearchManager#putDocuments(List)}. Otherwise, the document will be
+         *       rejected by {@link AppSearchManager#putDocuments(List)}.
+         * @hide
+         */
+        public Builder(@NonNull String uri, @NonNull String schemaType) {
+            mBuilderTypeInstance = (BuilderType) this;
+            mProtoBuilder.setUri(uri).setSchema(schemaType);
+            // Set current timestamp for creation timestamp by default.
+            setCreationTimestampMillis(System.currentTimeMillis());
+        }
+
+        /**
+         * Sets the score of the {@link AppSearchDocument}.
+         *
+         * <p>The score is a query-independent measure of the document's quality, relative to
+         * other {@link AppSearchDocument}s of the same type.
+         *
+         * @throws IllegalArgumentException If the provided value is negative.
+         * @hide
+         */
+        @NonNull
+        public BuilderType setScore(@IntRange(from = 0, to = Integer.MAX_VALUE) int score) {
+            if (score < 0) {
+                throw new IllegalArgumentException("Document score cannot be negative.");
+            }
+            mProtoBuilder.setScore(score);
+            return mBuilderTypeInstance;
+        }
+
+        /**
+         * Set the creation timestamp in milliseconds of the {@link AppSearchDocument}. Should be
+         * set using a value obtained from the {@link System#currentTimeMillis()} time base.
+         *
+         * @hide
+         */
+        @NonNull
+        public BuilderType setCreationTimestampMillis(
+                @CurrentTimeMillisLong long creationTimestampMillis) {
+            mProtoBuilder.setCreationTimestampMs(creationTimestampMillis);
+            return mBuilderTypeInstance;
+        }
+
+        /**
+         * Set the TTL (Time To Live) of the {@link AppSearchDocument}, in milliseconds.
+         *
+         * <p>After this many milliseconds since the {@link #setCreationTimestampMillis(long)}
+         * creation timestamp}, the document is deleted.
+         *
+         * @param ttlMillis A non-negative duration in milliseconds.
+         * @throws IllegalArgumentException If the provided value is negative.
+         */
+        @NonNull
+        public BuilderType setTtlMillis(@DurationMillisLong long ttlMillis) {
+            Preconditions.checkArgumentNonNegative(
+                    ttlMillis, "Document ttlMillis cannot be negative.");
+            mProtoBuilder.setTtlMs(ttlMillis);
+            return mBuilderTypeInstance;
+        }
+
+        /**
+         * Sets one or multiple {@code String} values for a property, replacing its previous
+         * values.
+         *
+         * @param key The key associated with the {@code values}.
+         * @param values The {@code String} values of the property.
+         * @hide
+         */
+        @NonNull
+        public BuilderType setProperty(@NonNull String key, @NonNull String... values) {
+            putInPropertyMap(key, values);
+            return mBuilderTypeInstance;
+        }
+
+        /**
+         * Sets one or multiple {@code boolean} values for a property, replacing its previous
+         * values.
+         *
+         * @param key The key associated with the {@code values}.
+         * @param values The {@code boolean} values of the property.
+         */
+        @NonNull
+        public BuilderType setProperty(@NonNull String key, @NonNull boolean... values) {
+            putInPropertyMap(key, values);
+            return mBuilderTypeInstance;
+        }
+
+        /**
+         * Sets one or multiple {@code long} values for a property, replacing its previous
+         * values.
+         *
+         * @param key The key associated with the {@code values}.
+         * @param values The {@code long} values of the property.
+         */
+        @NonNull
+        public BuilderType setProperty(@NonNull String key, @NonNull long... values) {
+            putInPropertyMap(key, values);
+            return mBuilderTypeInstance;
+        }
+
+        /**
+         * Sets one or multiple {@code double} values for a property, replacing its previous
+         * values.
+         *
+         * @param key The key associated with the {@code values}.
+         * @param values The {@code double} values of the property.
+         */
+        @NonNull
+        public BuilderType setProperty(@NonNull String key, @NonNull double... values) {
+            putInPropertyMap(key, values);
+            return mBuilderTypeInstance;
+        }
+
+        /**
+         * Sets one or multiple {@code byte[]} for a property, replacing its previous values.
+         *
+         * @param key The key associated with the {@code values}.
+         * @param values The {@code byte[]} of the property.
+         */
+        @NonNull
+        public BuilderType setProperty(@NonNull String key, @NonNull byte[]... values) {
+            putInPropertyMap(key, values);
+            return mBuilderTypeInstance;
+        }
+
+        /**
+         * Sets one or multiple {@link AppSearchDocument} values for a property, replacing its
+         * previous values.
+         *
+         * @param key The key associated with the {@code values}.
+         * @param values The {@link AppSearchDocument} values of the property.
+         */
+        @NonNull
+        public BuilderType setProperty(@NonNull String key, @NonNull AppSearchDocument... values) {
+            putInPropertyMap(key, values);
+            return mBuilderTypeInstance;
+        }
+
+        private void putInPropertyMap(@NonNull String key, @NonNull String[] values)
+                throws IllegalArgumentException {
+            Objects.requireNonNull(key);
+            Objects.requireNonNull(values);
+            validateRepeatedPropertyLength(key, values.length);
+            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.put(key, values);
+        }
+
+        private void putInPropertyMap(@NonNull String key, @NonNull boolean[] values) {
+            Objects.requireNonNull(key);
+            Objects.requireNonNull(values);
+            validateRepeatedPropertyLength(key, values.length);
+            mProperties.put(key, values);
+        }
+
+        private void putInPropertyMap(@NonNull String key, @NonNull double[] values) {
+            Objects.requireNonNull(key);
+            Objects.requireNonNull(values);
+            validateRepeatedPropertyLength(key, values.length);
+            mProperties.put(key, values);
+        }
+
+        private void putInPropertyMap(@NonNull String key, @NonNull long[] values) {
+            Objects.requireNonNull(key);
+            Objects.requireNonNull(values);
+            validateRepeatedPropertyLength(key, values.length);
+            mProperties.put(key, values);
+        }
+
+        private void putInPropertyMap(@NonNull String key, @NonNull byte[][] values) {
+            Objects.requireNonNull(key);
+            Objects.requireNonNull(values);
+            validateRepeatedPropertyLength(key, values.length);
+            mProperties.put(key, values);
+        }
+
+        private void putInPropertyMap(@NonNull String key, @NonNull AppSearchDocument[] values) {
+            Objects.requireNonNull(key);
+            Objects.requireNonNull(values);
+            for (int i = 0; i < values.length; i++) {
+                if (values[i] == null) {
+                    throw new IllegalArgumentException("The document at " + i + " is null.");
+                }
+            }
+            validateRepeatedPropertyLength(key, values.length);
+            mProperties.put(key, values);
+        }
+
+        private static void validateRepeatedPropertyLength(@NonNull String key, int length) {
+            if (length == 0) {
+                throw new IllegalArgumentException("The input array is empty.");
+            } else if (length > MAX_REPEATED_PROPERTY_LENGTH) {
+                throw new IllegalArgumentException(
+                        "Repeated property \"" + key + "\" has length " + length
+                                + ", which exceeds the limit of "
+                                + MAX_REPEATED_PROPERTY_LENGTH);
+            }
+        }
+
+        /**
+         * Builds the {@link AppSearchDocument} object.
+         * @hide
+         */
+        public AppSearchDocument build() {
+            // Build proto by sorting the keys in mProperties to exclude the influence of
+            // order. Therefore documents will generate same proto as long as the contents are
+            // same. Note that the order of repeated fields is still preserved.
+            ArrayList<String> keys = new ArrayList<>(mProperties.keySet());
+            Collections.sort(keys);
+            for (int i = 0; i < keys.size(); i++) {
+                String name = keys.get(i);
+                Object values = mProperties.get(name);
+                PropertyProto.Builder propertyProto = PropertyProto.newBuilder().setName(name);
+                if (values instanceof boolean[]) {
+                    for (boolean value : (boolean[]) values) {
+                        propertyProto.addBooleanValues(value);
+                    }
+                } else if (values instanceof long[]) {
+                    for (long value : (long[]) values) {
+                        propertyProto.addInt64Values(value);
+                    }
+                } else if (values instanceof double[]) {
+                    for (double value : (double[]) values) {
+                        propertyProto.addDoubleValues(value);
+                    }
+                } else if (values instanceof String[]) {
+                    for (String value : (String[]) values) {
+                        propertyProto.addStringValues(value);
+                    }
+                } else if (values instanceof AppSearchDocument[]) {
+                    for (AppSearchDocument value : (AppSearchDocument[]) values) {
+                        propertyProto.addDocumentValues(value.getProto());
+                    }
+                } else if (values instanceof byte[][]) {
+                    for (byte[] value : (byte[][]) values) {
+                        propertyProto.addBytesValues(ByteString.copyFrom(value));
+                    }
+                } else {
+                    throw new IllegalStateException(
+                            "Property \"" + name + "\" has unsupported value type \""
+                                    + values.getClass().getSimpleName() + "\"");
+                }
+                mProtoBuilder.addProperties(propertyProto);
+            }
+            return new AppSearchDocument(mProtoBuilder.build(), mProperties);
+        }
+    }
+}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchEmail.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchEmail.java
new file mode 100644
index 0000000..5b9457b
--- /dev/null
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchEmail.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.appsearch;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.appsearch.AppSearchSchema.PropertyConfig;
+
+/**
+ * Encapsulates a {@link AppSearchDocument} that represent an email.
+ *
+ * <p>This class is a higher level implement of {@link AppSearchDocument}.
+ *
+ * <p>This class will eventually migrate to Jetpack, where it will become public API.
+ *
+ * @hide
+ */
+public class AppSearchEmail extends AppSearchDocument {
+    private static final String KEY_FROM = "from";
+    private static final String KEY_TO = "to";
+    private static final String KEY_CC = "cc";
+    private static final String KEY_BCC = "bcc";
+    private static final String KEY_SUBJECT = "subject";
+    private static final String KEY_BODY = "body";
+
+    /** The name of the schema type for {@link AppSearchEmail} documents.*/
+    public static final String SCHEMA_TYPE = "builtin:Email";
+
+    public static final AppSearchSchema SCHEMA = AppSearchSchema.newBuilder(SCHEMA_TYPE)
+            .addProperty(AppSearchSchema.newPropertyBuilder(KEY_FROM)
+                    .setDataType(PropertyConfig.DATA_TYPE_STRING)
+                    .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+                    .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+                    .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+                    .build()
+
+            ).addProperty(AppSearchSchema.newPropertyBuilder(KEY_TO)
+                    .setDataType(PropertyConfig.DATA_TYPE_STRING)
+                    .setCardinality(PropertyConfig.CARDINALITY_REPEATED)
+                    .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+                    .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+                    .build()
+
+            ).addProperty(AppSearchSchema.newPropertyBuilder(KEY_CC)
+                    .setDataType(PropertyConfig.DATA_TYPE_STRING)
+                    .setCardinality(PropertyConfig.CARDINALITY_REPEATED)
+                    .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+                    .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+                    .build()
+
+            ).addProperty(AppSearchSchema.newPropertyBuilder(KEY_BCC)
+                    .setDataType(PropertyConfig.DATA_TYPE_STRING)
+                    .setCardinality(PropertyConfig.CARDINALITY_REPEATED)
+                    .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+                    .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+                    .build()
+
+            ).addProperty(AppSearchSchema.newPropertyBuilder(KEY_SUBJECT)
+                    .setDataType(PropertyConfig.DATA_TYPE_STRING)
+                    .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+                    .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+                    .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+                    .build()
+
+            ).addProperty(AppSearchSchema.newPropertyBuilder(KEY_BODY)
+                    .setDataType(PropertyConfig.DATA_TYPE_STRING)
+                    .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+                    .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+                    .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+                    .build()
+
+            ).build();
+
+    /**
+     * Creates a new {@link AppSearchEmail} from the contents of an existing
+     * {@link AppSearchDocument}.
+     *
+     * @param document The {@link AppSearchDocument} containing the email content.
+     */
+    public AppSearchEmail(@NonNull AppSearchDocument document) {
+        super(document);
+    }
+
+    /**
+     * Get the from address of {@link AppSearchEmail}.
+     *
+     * @return Returns the subject of {@link AppSearchEmail} or {@code null} if it's not been set
+     *         yet.
+     * @hide
+     */
+    @Nullable
+    public String getFrom() {
+        return getPropertyString(KEY_FROM);
+    }
+
+    /**
+     * Get the destination addresses of {@link AppSearchEmail}.
+     *
+     * @return Returns the destination addresses of {@link AppSearchEmail} or {@code null} if it's
+     *         not been set yet.
+     * @hide
+     */
+    @Nullable
+    public String[] getTo() {
+        return getPropertyStringArray(KEY_TO);
+    }
+
+    /**
+     * Get the CC list of {@link AppSearchEmail}.
+     *
+     * @return Returns the CC list of {@link AppSearchEmail} or {@code null} if it's not been set
+     *         yet.
+     * @hide
+     */
+    @Nullable
+    public String[] getCc() {
+        return getPropertyStringArray(KEY_CC);
+    }
+
+    /**
+     * Get the BCC list of {@link AppSearchEmail}.
+     *
+     * @return Returns the BCC list of {@link AppSearchEmail} or {@code null} if it's not been set
+     *         yet.
+     * @hide
+     */
+    @Nullable
+    public String[] getBcc() {
+        return getPropertyStringArray(KEY_BCC);
+    }
+
+    /**
+     * Get the subject of {@link AppSearchEmail}.
+     *
+     * @return Returns the value subject of {@link AppSearchEmail} or {@code null} if it's not been
+     *         set yet.
+     * @hide
+     */
+    @Nullable
+    public String getSubject() {
+        return getPropertyString(KEY_SUBJECT);
+    }
+
+    /**
+     * Get the body of {@link AppSearchEmail}.
+     *
+     * @return Returns the body of {@link AppSearchEmail} or {@code null} if it's not been set yet.
+     * @hide
+     */
+    @Nullable
+    public String getBody() {
+        return getPropertyString(KEY_BODY);
+    }
+
+    /**
+     * The builder class for {@link AppSearchEmail}.
+     * @hide
+     */
+    public static class Builder extends AppSearchDocument.Builder<AppSearchEmail.Builder> {
+
+        /**
+         * Create a new {@link AppSearchEmail.Builder}
+         * @param uri The Uri of the Email.
+         * @hide
+         */
+        public Builder(@NonNull String uri) {
+            super(uri, SCHEMA_TYPE);
+        }
+
+        /**
+         * Set the from address of {@link AppSearchEmail}
+         * @hide
+         */
+        @NonNull
+        public AppSearchEmail.Builder setFrom(@NonNull String from) {
+            setProperty(KEY_FROM, from);
+            return this;
+        }
+
+        /**
+         * Set the destination address of {@link AppSearchEmail}
+         * @hide
+         */
+        @NonNull
+        public AppSearchEmail.Builder setTo(@NonNull String... to) {
+            setProperty(KEY_TO, to);
+            return this;
+        }
+
+        /**
+         * Set the CC list of {@link AppSearchEmail}
+         * @hide
+         */
+        @NonNull
+        public AppSearchEmail.Builder setCc(@NonNull String... cc) {
+            setProperty(KEY_CC, cc);
+            return this;
+        }
+
+        /**
+         * Set the BCC list of {@link AppSearchEmail}
+         * @hide
+         */
+        @NonNull
+        public AppSearchEmail.Builder setBcc(@NonNull String... bcc) {
+            setProperty(KEY_BCC, bcc);
+            return this;
+        }
+
+        /**
+         * Set the subject of {@link AppSearchEmail}
+         * @hide
+         */
+        @NonNull
+        public AppSearchEmail.Builder setSubject(@NonNull String subject) {
+            setProperty(KEY_SUBJECT, subject);
+            return this;
+        }
+
+        /**
+         * Set the body of {@link AppSearchEmail}
+         * @hide
+         */
+        @NonNull
+        public AppSearchEmail.Builder setBody(@NonNull String body) {
+            setProperty(KEY_BODY, body);
+            return this;
+        }
+
+        /**
+         * Builds the {@link AppSearchEmail} object.
+         *
+         * @hide
+         */
+        @NonNull
+        @Override
+        public AppSearchEmail build() {
+            return new AppSearchEmail(super.build());
+        }
+    }
+}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
index 15c3368..e2c9b0f 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
@@ -18,7 +18,6 @@
 import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
 import android.annotation.SystemService;
-import android.app.appsearch.AppSearch.Document;
 import android.content.Context;
 import android.os.RemoteException;
 
@@ -150,25 +149,26 @@
     }
 
     /**
-     * Index {@link android.app.appsearch.AppSearch.Document Documents} into AppSearch.
+     * Index {@link AppSearchDocument Documents} into AppSearch.
      *
      * <p>You should not call this method directly; instead, use the
      * {@code AppSearch#putDocuments()} API provided by JetPack.
      *
-     * <p>Each {@link AppSearch.Document Document's} {@code schemaType} field must be set to the
+     * <p>Each {@link AppSearchDocument Document's} {@code schemaType} field must be set to the
      * name of a schema type previously registered via the {@link #setSchema} method.
      *
-     * @param documents {@link Document Documents} that need to be indexed.
+     * @param documents {@link AppSearchDocument Documents} that need to be indexed.
      * @return An {@link AppSearchBatchResult} mapping the document URIs to {@link Void} if they
      *     were successfully indexed, or a {@link Throwable} describing the failure if they could
      *     not be indexed.
      * @hide
      */
-    public AppSearchBatchResult<String, Void> putDocuments(@NonNull List<Document> documents) {
+    public AppSearchBatchResult<String, Void> putDocuments(
+            @NonNull List<AppSearchDocument> documents) {
         // TODO(b/146386470): Transmit these documents as a RemoteStream instead of sending them in
         // one big list.
         List<byte[]> documentsBytes = new ArrayList<>(documents.size());
-        for (Document document : documents) {
+        for (AppSearchDocument document : documents) {
             documentsBytes.add(document.getProto().toByteArray());
         }
         AndroidFuture<AppSearchBatchResult> future = new AndroidFuture<>();
diff --git a/apex/appsearch/framework/java/android/app/appsearch/MatchInfo.java b/apex/appsearch/framework/java/android/app/appsearch/MatchInfo.java
index 6aa91a3f..5ce2960 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/MatchInfo.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/MatchInfo.java
@@ -70,7 +70,7 @@
 
     private final String mPropertyPath;
     private final SnippetMatchProto mSnippetMatch;
-    private final AppSearch.Document mDocument;
+    private final AppSearchDocument mDocument;
     /**
      * List of content with same property path in a document when there are multiple matches in
      * repeated sections.
@@ -79,7 +79,7 @@
 
     /** @hide */
     public MatchInfo(@NonNull String propertyPath, @NonNull SnippetMatchProto snippetMatch,
-            @NonNull AppSearch.Document document) {
+            @NonNull AppSearchDocument document) {
         mPropertyPath = propertyPath;
         mSnippetMatch = snippetMatch;
         mDocument = document;
diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java b/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java
index f48ebde..7287fe6 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java
@@ -71,21 +71,21 @@
         private final SearchResultProto.ResultProto mResultProto;
 
         @Nullable
-        private AppSearch.Document mDocument;
+        private AppSearchDocument mDocument;
 
         private Result(SearchResultProto.ResultProto resultProto) {
             mResultProto = resultProto;
         }
 
         /**
-         * Contains the matching {@link AppSearch.Document}.
+         * Contains the matching {@link AppSearchDocument}.
          * @return Document object which matched the query.
          * @hide
          */
         @NonNull
-        public AppSearch.Document getDocument() {
+        public AppSearchDocument getDocument() {
             if (mDocument == null) {
-                mDocument = new AppSearch.Document(mResultProto.getDocument());
+                mDocument = new AppSearchDocument(mResultProto.getDocument());
             }
             return mDocument;
         }
@@ -106,7 +106,7 @@
             if (!mResultProto.hasSnippet()) {
                 return null;
             }
-            AppSearch.Document document = getDocument();
+            AppSearchDocument document = getDocument();
             List<MatchInfo> matchList = new ArrayList<>();
             for (Iterator entryProtoIterator = mResultProto.getSnippet()
                     .getEntriesList().iterator(); entryProtoIterator.hasNext(); ) {
diff --git a/apex/blobstore/framework/java/android/app/blob/BlobHandle.java b/apex/blobstore/framework/java/android/app/blob/BlobHandle.java
index 60c3136..f7e6a98 100644
--- a/apex/blobstore/framework/java/android/app/blob/BlobHandle.java
+++ b/apex/blobstore/framework/java/android/app/blob/BlobHandle.java
@@ -15,13 +15,26 @@
  */
 package android.app.blob;
 
+import static android.app.blob.XmlTags.ATTR_ALGO;
+import static android.app.blob.XmlTags.ATTR_DIGEST;
+import static android.app.blob.XmlTags.ATTR_EXPIRY_TIME;
+import static android.app.blob.XmlTags.ATTR_LABEL;
+import static android.app.blob.XmlTags.ATTR_TAG;
+
 import android.annotation.CurrentTimeMillisLong;
 import android.annotation.NonNull;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.Base64;
 
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
+import com.android.internal.util.XmlUtils;
 
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
 import java.util.Arrays;
 import java.util.Objects;
 
@@ -41,17 +54,20 @@
      * @hide
      */
     @NonNull public final String algorithm;
+
     /**
      * Hash of the blob this handle is representing using {@link #algorithm}.
      *
      * @hide
      */
     @NonNull public final byte[] digest;
+
     /**
      * Label of the blob that can be surfaced to the user.
      * @hide
      */
     @NonNull public final CharSequence label;
+
     /**
      * Time in milliseconds after which the blob should be invalidated and not
      * allowed to be accessed by any other app, in {@link System#currentTimeMillis()} timebase.
@@ -59,6 +75,7 @@
      * @hide
      */
     @CurrentTimeMillisLong public final long expiryTimeMillis;
+
     /**
      * An opaque {@link String} associated with the blob.
      *
@@ -197,6 +214,15 @@
         return Objects.hash(algorithm, Arrays.hashCode(digest), label, expiryTimeMillis, tag);
     }
 
+    /** @hide */
+    public void dump(IndentingPrintWriter fout) {
+        fout.println("algo: " + algorithm);
+        fout.println("digest: " + Base64.encodeToString(digest, Base64.NO_WRAP));
+        fout.println("label: " + label);
+        fout.println("expiryMs: " + expiryTimeMillis);
+        fout.println("tag: " + tag);
+    }
+
     public static final @NonNull Creator<BlobHandle> CREATOR = new Creator<BlobHandle>() {
         @Override
         public @NonNull BlobHandle createFromParcel(@NonNull Parcel source) {
@@ -208,4 +234,25 @@
             return new BlobHandle[size];
         }
     };
+
+    /** @hide */
+    public void writeToXml(@NonNull XmlSerializer out) throws IOException {
+        XmlUtils.writeStringAttribute(out, ATTR_ALGO, algorithm);
+        XmlUtils.writeByteArrayAttribute(out, ATTR_DIGEST, digest);
+        XmlUtils.writeStringAttribute(out, ATTR_LABEL, label);
+        XmlUtils.writeLongAttribute(out, ATTR_EXPIRY_TIME, expiryTimeMillis);
+        XmlUtils.writeStringAttribute(out, ATTR_TAG, tag);
+    }
+
+    /** @hide */
+    @NonNull
+    public static BlobHandle createFromXml(@NonNull XmlPullParser in) throws IOException {
+        final String algo = XmlUtils.readStringAttribute(in, ATTR_ALGO);
+        final byte[] digest = XmlUtils.readByteArrayAttribute(in, ATTR_DIGEST);
+        final CharSequence label = XmlUtils.readStringAttribute(in, ATTR_LABEL);
+        final long expiryTimeMs = XmlUtils.readLongAttribute(in, ATTR_EXPIRY_TIME);
+        final String tag = XmlUtils.readStringAttribute(in, ATTR_TAG);
+
+        return BlobHandle.create(algo, digest, label, expiryTimeMs, tag);
+    }
 }
diff --git a/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java b/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java
index 47af7c0..8cea645 100644
--- a/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java
+++ b/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java
@@ -25,23 +25,115 @@
 import android.content.Context;
 import android.os.ParcelFileDescriptor;
 import android.os.ParcelableException;
+import android.os.RemoteCallback;
 import android.os.RemoteException;
 
 import com.android.internal.util.function.pooled.PooledLambda;
 
 import java.io.Closeable;
 import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import java.util.function.Consumer;
 
 /**
  * This class provides access to the blob store managed by the system.
  *
- * Apps can publish data blobs which might be useful for other apps on the device to be
- * managed by the system and apps that would like to access these data blobs can do so
- * by addressing them via their cryptographically secure hashes.
+ * <p> Apps can publish and access a data blob using a {@link BlobHandle} object which can
+ * be created with {@link BlobHandle#createWithSha256(byte[], CharSequence, long, String)}.
+ * This {@link BlobHandle} object encapsulates the following pieces of information used for
+ * identifying the blobs:
+ * <ul>
+ *     <li> {@link BlobHandle#getSha256Digest()}
+ *     <li> {@link BlobHandle#getLabel()}
+ *     <li> {@link BlobHandle#getExpiryTimeMillis()}
+ *     <li> {@link BlobHandle#getTag()}
+ * </ul>
+ * For two {@link BlobHandle} objects to be considered identical, all these pieces of information
+ * must be equal.
  *
- * TODO: More documentation.
+ * <p> For contributing a new data blob, an app needs to create a session using
+ * {@link BlobStoreManager#createSession(BlobHandle)} and then open this session for writing using
+ * {@link BlobStoreManager#openSession(long)}.
+ *
+ * <p> The following code snippet shows how to create and open a session for writing:
+ * <pre class="prettyprint">
+ *     final long sessionId = blobStoreManager.createSession(blobHandle);
+ *     try (BlobStoreManager.Session session = blobStoreManager.openSession(sessionId)) {
+ *         try (ParcelFileDescriptor pfd = new ParcelFileDescriptor.AutoCloseOutputStream(
+ *                 session.openWrite(offsetBytes, lengthBytes))) {
+ *             writeData(pfd);
+ *         }
+ *     }
+ * </pre>
+ *
+ * <p> If all the data could not be written in a single attempt, apps can close this session
+ * and re-open it again using the session id obtained via
+ * {@link BlobStoreManager#createSession(BlobHandle)}. Note that the session data is persisted
+ * and can be re-opened for completing the data contribution, even across device reboots.
+ *
+ * <p> After the data is written to the session, it can be committed using
+ * {@link Session#commit(Executor, Consumer)}. Until the session is committed, data written
+ * to the session will not be shared with any app.
+ *
+ * <p class="note"> Once a session is committed using {@link Session#commit(Executor, Consumer)},
+ * any data written as part of this session is sealed and cannot be modified anymore.
+ *
+ * <p> Before committing the session, apps can indicate which apps are allowed to access the
+ * contributed data using one or more of the following access modes:
+ * <ul>
+ *     <li> {@link Session#allowPackageAccess(String, byte[])} which will allow whitelisting
+ *          specific packages to access the blobs.
+ *     <li> {@link Session#allowSameSignatureAccess()} which will allow only apps which are signed
+ *          with the same certificate as the app which contributed the blob to access it.
+ *     <li> {@link Session#allowPublicAccess()} which will allow any app on the device to access
+ *          the blob.
+ * </ul>
+ *
+ * <p> The following code snippet shows how to specify the access mode and commit the session:
+ * <pre class="prettyprint">
+ *     try (BlobStoreManager.Session session = blobStoreManager.openSession(sessionId)) {
+ *         try (ParcelFileDescriptor pfd = new ParcelFileDescriptor.AutoCloseOutputStream(
+ *                 session.openWrite(offsetBytes, lengthBytes))) {
+ *             writeData(pfd);
+ *         }
+ *         session.allowSameSignatureAccess();
+ *         session.allowPackageAccess(packageName, certificate);
+ *         session.commit(executor, callback);
+ *     }
+ * </pre>
+ *
+ * <p> Apps that satisfy at least one of the access mode constraints specified by the publisher
+ * of the data blob will be able to access it.
+ *
+ * <p> A data blob published without specifying any of
+ * these access modes will be considered private and only the app that contributed the data
+ * blob will be allowed to access it. This is still useful for overall device system health as
+ * the System can try to keep one copy of data blob on disk when multiple apps contribute the
+ * same data.
+ *
+ * <p class="note"> It is strongly recommended that apps use one of
+ * {@link Session#allowPackageAccess(String, byte[])} or {@link Session#allowSameSignatureAccess()}
+ * when they know, ahead of time, the set of apps they would like to share the blobs with.
+ * {@link Session#allowPublicAccess()} is meant for publicly available data committed from
+ * libraries and SDKs.
+ *
+ * <p> Once a data blob is committed with {@link Session#commit(Executor, Consumer)}, it
+ * can be accessed using {@link BlobStoreManager#openBlob(BlobHandle)}, assuming the caller
+ * satisfies constraints of any of the access modes associated with that data blob. An app may
+ * acquire a lease on a blob with {@link BlobStoreManager#acquireLease(BlobHandle, int)} and
+ * release the lease with {@link BlobStoreManager#releaseLease(BlobHandle)}. A blob will not be
+ * deleted from the system while there is at least one app leasing it.
+ *
+ * <p> The following code snippet shows how to access the data blob:
+ * <pre class="prettyprint">
+ *     try (ParcelFileDescriptor pfd = new ParcelFileDescriptor.AutoCloseInputStream(
+ *             blobStoreManager.openBlob(blobHandle)) {
+ *         useData(pfd);
+ *     }
+ * </pre>
  */
 @SystemService(Context.BLOB_STORE_SERVICE)
 public class BlobStoreManager {
@@ -265,6 +357,25 @@
     }
 
     /**
+     * Wait until any pending tasks (like persisting data to disk) have finished.
+     *
+     * @hide
+     */
+    public void waitForIdle(long timeoutMillis) throws InterruptedException, TimeoutException {
+        try {
+            final CountDownLatch countDownLatch = new CountDownLatch(1);
+            mService.waitForIdle(new RemoteCallback((result) -> countDownLatch.countDown()));
+            if (!countDownLatch.await(timeoutMillis, TimeUnit.MILLISECONDS)) {
+                throw new TimeoutException("Timed out waiting for service to become idle");
+            }
+        } catch (ParcelableException e) {
+            throw new RuntimeException(e);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Represents an ongoing session of a blob's contribution to the blob store managed by the
      * system.
      *
@@ -323,6 +434,28 @@
         }
 
         /**
+         * Opens a file descriptor to read the blob content already written into this session.
+         *
+         * @return a {@link ParcelFileDescriptor} for reading from the blob file.
+         *
+         * @throws IOException when there is an I/O error while opening the file to read.
+         * @throws SecurityException when the caller is not the owner of the session.
+         * @throws IllegalStateException when the caller tries to read the file after it is
+         *                               abandoned (using {@link #abandon()})
+         *                               or closed (using {@link #close()}).
+         */
+        public @NonNull ParcelFileDescriptor openRead() throws IOException {
+            try {
+                return mSession.openRead();
+            } catch (ParcelableException e) {
+                e.maybeRethrow(IOException.class);
+                throw new RuntimeException(e);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        /**
          * Gets the size of the blob file that was written to the session so far.
          *
          * @return the size of the blob file so far.
diff --git a/apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl b/apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl
index dfbf78f..e2128b4 100644
--- a/apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl
+++ b/apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl
@@ -17,6 +17,7 @@
 
 import android.app.blob.BlobHandle;
 import android.app.blob.IBlobStoreSession;
+import android.os.RemoteCallback;
 
 /** {@hide} */
 interface IBlobStoreManager {
@@ -28,4 +29,6 @@
     void acquireLease(in BlobHandle handle, int descriptionResId, long leaseTimeout,
             in String packageName);
     void releaseLease(in BlobHandle handle, in String packageName);
+
+    void waitForIdle(in RemoteCallback callback);
 }
\ No newline at end of file
diff --git a/apex/blobstore/framework/java/android/app/blob/IBlobStoreSession.aidl b/apex/blobstore/framework/java/android/app/blob/IBlobStoreSession.aidl
index 4ae919b..4035b96 100644
--- a/apex/blobstore/framework/java/android/app/blob/IBlobStoreSession.aidl
+++ b/apex/blobstore/framework/java/android/app/blob/IBlobStoreSession.aidl
@@ -21,6 +21,7 @@
 /** {@hide} */
 interface IBlobStoreSession {
     ParcelFileDescriptor openWrite(long offsetBytes, long lengthBytes);
+    ParcelFileDescriptor openRead();
 
     void allowPackageAccess(in String packageName, in byte[] certificate);
     void allowSameSignatureAccess();
diff --git a/apex/blobstore/framework/java/android/app/blob/XmlTags.java b/apex/blobstore/framework/java/android/app/blob/XmlTags.java
new file mode 100644
index 0000000..803c9a4
--- /dev/null
+++ b/apex/blobstore/framework/java/android/app/blob/XmlTags.java
@@ -0,0 +1,55 @@
+/*
+ * 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.blob;
+
+/** @hide */
+public final class XmlTags {
+    public static final String ATTR_VERSION = "v";
+
+    public static final String TAG_SESSIONS = "ss";
+    public static final String TAG_BLOBS = "bs";
+
+    // For BlobStoreSession
+    public static final String TAG_SESSION = "s";
+    public static final String ATTR_ID = "id";
+    public static final String ATTR_PACKAGE = "p";
+    public static final String ATTR_UID = "u";
+
+    // For BlobMetadata
+    public static final String TAG_BLOB = "b";
+    public static final String ATTR_USER_ID = "us";
+
+    // For BlobAccessMode
+    public static final String TAG_ACCESS_MODE = "am";
+    public static final String ATTR_TYPE = "t";
+    public static final String TAG_WHITELISTED_PACKAGE = "wl";
+    public static final String ATTR_CERTIFICATE = "ct";
+
+    // For BlobHandle
+    public static final String TAG_BLOB_HANDLE = "bh";
+    public static final String ATTR_ALGO = "al";
+    public static final String ATTR_DIGEST = "dg";
+    public static final String ATTR_LABEL = "lbl";
+    public static final String ATTR_EXPIRY_TIME = "ex";
+    public static final String ATTR_TAG = "tg";
+
+    // For committer
+    public static final String TAG_COMMITTER = "c";
+
+    // For leasee
+    public static final String TAG_LEASEE = "l";
+    public static final String ATTR_DESCRIPTION_RES_ID = "rid";
+}
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java b/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java
index 357250a..ec7ba28 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java
@@ -15,12 +15,27 @@
  */
 package com.android.server.blob;
 
+import static android.app.blob.XmlTags.ATTR_CERTIFICATE;
+import static android.app.blob.XmlTags.ATTR_PACKAGE;
+import static android.app.blob.XmlTags.ATTR_TYPE;
+import static android.app.blob.XmlTags.TAG_WHITELISTED_PACKAGE;
+
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.util.ArraySet;
+import android.util.Base64;
+import android.util.DebugUtils;
 
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Arrays;
@@ -40,10 +55,10 @@
             ACCESS_TYPE_WHITELIST,
     })
     @interface AccessType {}
-    static final int ACCESS_TYPE_PRIVATE = 1 << 0;
-    static final int ACCESS_TYPE_PUBLIC = 1 << 1;
-    static final int ACCESS_TYPE_SAME_SIGNATURE = 1 << 2;
-    static final int ACCESS_TYPE_WHITELIST = 1 << 3;
+    public static final int ACCESS_TYPE_PRIVATE = 1 << 0;
+    public static final int ACCESS_TYPE_PUBLIC = 1 << 1;
+    public static final int ACCESS_TYPE_SAME_SIGNATURE = 1 << 2;
+    public static final int ACCESS_TYPE_WHITELIST = 1 << 3;
 
     private int mAccessType = ACCESS_TYPE_PRIVATE;
 
@@ -112,6 +127,51 @@
         return false;
     }
 
+    void dump(IndentingPrintWriter fout) {
+        fout.println("accessType: " + DebugUtils.flagsToString(
+                BlobAccessMode.class, "ACCESS_TYPE_", mAccessType));
+        fout.print("Whitelisted pkgs:");
+        if (mWhitelistedPackages.isEmpty()) {
+            fout.println(" (Empty)");
+        } else {
+            fout.increaseIndent();
+            for (int i = 0, count = mWhitelistedPackages.size(); i < count; ++i) {
+                fout.println(mWhitelistedPackages.valueAt(i).toString());
+            }
+            fout.decreaseIndent();
+        }
+    }
+
+    void writeToXml(@NonNull XmlSerializer out) throws IOException {
+        XmlUtils.writeIntAttribute(out, ATTR_TYPE, mAccessType);
+        for (int i = 0, count = mWhitelistedPackages.size(); i < count; ++i) {
+            out.startTag(null, TAG_WHITELISTED_PACKAGE);
+            final PackageIdentifier packageIdentifier = mWhitelistedPackages.valueAt(i);
+            XmlUtils.writeStringAttribute(out, ATTR_PACKAGE, packageIdentifier.packageName);
+            XmlUtils.writeByteArrayAttribute(out, ATTR_CERTIFICATE, packageIdentifier.certificate);
+            out.endTag(null, TAG_WHITELISTED_PACKAGE);
+        }
+    }
+
+    @NonNull
+    static BlobAccessMode createFromXml(@NonNull XmlPullParser in)
+            throws IOException, XmlPullParserException {
+        final BlobAccessMode blobAccessMode = new BlobAccessMode();
+
+        final int accessType = XmlUtils.readIntAttribute(in, ATTR_TYPE);
+        blobAccessMode.mAccessType = accessType;
+
+        final int depth = in.getDepth();
+        while (XmlUtils.nextElementWithin(in, depth)) {
+            if (TAG_WHITELISTED_PACKAGE.equals(in.getName())) {
+                final String packageName = XmlUtils.readStringAttribute(in, ATTR_PACKAGE);
+                final byte[] certificate = XmlUtils.readByteArrayAttribute(in, ATTR_CERTIFICATE);
+                blobAccessMode.allowPackageAccess(packageName, certificate);
+            }
+        }
+        return blobAccessMode;
+    }
+
     private static final class PackageIdentifier {
         public final String packageName;
         public final byte[] certificate;
@@ -143,5 +203,11 @@
         public int hashCode() {
             return Objects.hash(packageName, Arrays.hashCode(certificate));
         }
+
+        @Override
+        public String toString() {
+            return "[" + packageName + ", "
+                    + Base64.encodeToString(certificate, Base64.NO_WRAP) + "]";
+        }
     }
 }
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java b/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
index d3a2271..e9838d6 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
@@ -15,20 +15,45 @@
  */
 package com.android.server.blob;
 
+import static android.app.blob.XmlTags.ATTR_DESCRIPTION_RES_ID;
+import static android.app.blob.XmlTags.ATTR_EXPIRY_TIME;
+import static android.app.blob.XmlTags.ATTR_ID;
+import static android.app.blob.XmlTags.ATTR_PACKAGE;
+import static android.app.blob.XmlTags.ATTR_UID;
+import static android.app.blob.XmlTags.ATTR_USER_ID;
+import static android.app.blob.XmlTags.TAG_ACCESS_MODE;
+import static android.app.blob.XmlTags.TAG_BLOB_HANDLE;
+import static android.app.blob.XmlTags.TAG_COMMITTER;
+import static android.app.blob.XmlTags.TAG_LEASEE;
 import static android.system.OsConstants.O_RDONLY;
 
+import static com.android.server.blob.BlobStoreConfig.TAG;
+
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.blob.BlobHandle;
 import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
 import android.os.ParcelFileDescriptor;
 import android.os.RevocableFileDescriptor;
+import android.os.UserHandle;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.util.ArrayMap;
 import android.util.ArraySet;
+import android.util.Slog;
+import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.XmlUtils;
 
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.util.Objects;
@@ -37,8 +62,10 @@
     private final Object mMetadataLock = new Object();
 
     private final Context mContext;
-    private final long mBlobId;
-    private final BlobHandle mBlobHandle;
+
+    public final long blobId;
+    public final BlobHandle blobHandle;
+    public final int userId;
 
     @GuardedBy("mMetadataLock")
     private final ArraySet<Committer> mCommitters = new ArraySet<>();
@@ -57,15 +84,47 @@
     private final ArrayMap<String, ArraySet<RevocableFileDescriptor>> mRevocableFds =
             new ArrayMap<>();
 
-    BlobMetadata(Context context, long blobId, BlobHandle blobHandle) {
+    // Do not access this directly, instead use getSessionFile().
+    private File mBlobFile;
+
+    BlobMetadata(Context context, long blobId, BlobHandle blobHandle, int userId) {
         mContext = context;
-        mBlobId = blobId;
-        mBlobHandle = blobHandle;
+        this.blobId = blobId;
+        this.blobHandle = blobHandle;
+        this.userId = userId;
     }
 
-    void addCommitter(String packageName, int uid, BlobAccessMode blobAccessMode) {
+    void addCommitter(@NonNull Committer committer) {
         synchronized (mMetadataLock) {
-            mCommitters.add(new Committer(packageName, uid, blobAccessMode));
+            mCommitters.add(committer);
+        }
+    }
+
+    void addCommitters(ArraySet<Committer> committers) {
+        synchronized (mMetadataLock) {
+            mCommitters.addAll(committers);
+        }
+    }
+
+    void removeCommitter(@NonNull String packageName, int uid) {
+        synchronized (mMetadataLock) {
+            mCommitters.removeIf((committer) ->
+                    committer.uid == uid && committer.packageName.equals(packageName));
+        }
+    }
+
+    void removeInvalidCommitters(SparseArray<String> packages) {
+        synchronized (mMetadataLock) {
+            mCommitters.removeIf(committer ->
+                    !committer.packageName.equals(packages.get(committer.uid)));
+        }
+    }
+
+    @Nullable
+    Committer getExistingCommitter(@NonNull Committer newCommitter) {
+        synchronized (mCommitters) {
+            final int index = mCommitters.indexOf(newCommitter);
+            return index >= 0 ? mCommitters.valueAt(index) : null;
         }
     }
 
@@ -77,9 +136,23 @@
         }
     }
 
+    void addLeasees(ArraySet<Leasee> leasees) {
+        synchronized (mMetadataLock) {
+            mLeasees.addAll(leasees);
+        }
+    }
+
     void removeLeasee(String packageName, int uid) {
         synchronized (mMetadataLock) {
-            mLeasees.remove(new Accessor(packageName, uid));
+            mLeasees.removeIf((leasee) ->
+                    leasee.uid == uid && leasee.packageName.equals(packageName));
+        }
+    }
+
+    void removeInvalidLeasees(SparseArray<String> packages) {
+        synchronized (mMetadataLock) {
+            mLeasees.removeIf(leasee ->
+                    !leasee.packageName.equals(packages.get(leasee.uid)));
         }
     }
 
@@ -114,11 +187,18 @@
         return false;
     }
 
+    File getBlobFile() {
+        if (mBlobFile == null) {
+            mBlobFile = BlobStoreConfig.getBlobFile(blobId);
+        }
+        return mBlobFile;
+    }
+
     ParcelFileDescriptor openForRead(String callingPackage) throws IOException {
         // TODO: Add limit on opened fds
         FileDescriptor fd;
         try {
-            fd = Os.open(BlobStoreConfig.getBlobFile(mBlobId).getPath(), O_RDONLY, 0);
+            fd = Os.open(getBlobFile().getPath(), O_RDONLY, 0);
         } catch (ErrnoException e) {
             throw e.rethrowAsIOException();
         }
@@ -154,6 +234,94 @@
         return revocableFd.getRevocableFileDescriptor();
     }
 
+    void dump(IndentingPrintWriter fout) {
+        fout.println("blobHandle:");
+        fout.increaseIndent();
+        blobHandle.dump(fout);
+        fout.decreaseIndent();
+
+        fout.println("Committers:");
+        fout.increaseIndent();
+        for (int i = 0, count = mCommitters.size(); i < count; ++i) {
+            final Committer committer = mCommitters.valueAt(i);
+            fout.println("committer " + committer.toString());
+            fout.increaseIndent();
+            committer.dump(fout);
+            fout.decreaseIndent();
+        }
+        fout.decreaseIndent();
+
+        fout.println("Leasees:");
+        fout.increaseIndent();
+        for (int i = 0, count = mLeasees.size(); i < count; ++i) {
+            final Leasee leasee = mLeasees.valueAt(i);
+            fout.println("leasee " + leasee.toString());
+            fout.increaseIndent();
+            leasee.dump(mContext, fout);
+            fout.decreaseIndent();
+        }
+        fout.decreaseIndent();
+
+        fout.println("Open fds: #" + mRevocableFds.size());
+    }
+
+    void writeToXml(XmlSerializer out) throws IOException {
+        synchronized (mMetadataLock) {
+            XmlUtils.writeLongAttribute(out, ATTR_ID, blobId);
+            XmlUtils.writeIntAttribute(out, ATTR_USER_ID, userId);
+
+            out.startTag(null, TAG_BLOB_HANDLE);
+            blobHandle.writeToXml(out);
+            out.endTag(null, TAG_BLOB_HANDLE);
+
+            for (int i = 0, count = mCommitters.size(); i < count; ++i) {
+                out.startTag(null, TAG_COMMITTER);
+                mCommitters.valueAt(i).writeToXml(out);
+                out.endTag(null, TAG_COMMITTER);
+            }
+
+            for (int i = 0, count = mLeasees.size(); i < count; ++i) {
+                out.startTag(null, TAG_LEASEE);
+                mLeasees.valueAt(i).writeToXml(out);
+                out.endTag(null, TAG_LEASEE);
+            }
+        }
+    }
+
+    @Nullable
+    static BlobMetadata createFromXml(Context context, XmlPullParser in)
+            throws XmlPullParserException, IOException {
+        final long blobId = XmlUtils.readLongAttribute(in, ATTR_ID);
+        final int userId = XmlUtils.readIntAttribute(in, ATTR_USER_ID);
+
+        BlobHandle blobHandle = null;
+        final ArraySet<Committer> committers = new ArraySet<>();
+        final ArraySet<Leasee> leasees = new ArraySet<>();
+        final int depth = in.getDepth();
+        while (XmlUtils.nextElementWithin(in, depth)) {
+            if (TAG_BLOB_HANDLE.equals(in.getName())) {
+                blobHandle = BlobHandle.createFromXml(in);
+            } else if (TAG_COMMITTER.equals(in.getName())) {
+                final Committer committer = Committer.createFromXml(in);
+                if (committer != null) {
+                    committers.add(committer);
+                }
+            } else if (TAG_LEASEE.equals(in.getName())) {
+                leasees.add(Leasee.createFromXml(in));
+            }
+        }
+
+        if (blobHandle == null) {
+            Slog.wtf(TAG, "blobHandle should be available");
+            return null;
+        }
+
+        final BlobMetadata blobMetadata = new BlobMetadata(context, blobId, blobHandle, userId);
+        blobMetadata.addCommitters(committers);
+        blobMetadata.addLeasees(leasees);
+        return blobMetadata;
+    }
+
     static final class Committer extends Accessor {
         public final BlobAccessMode blobAccessMode;
 
@@ -161,6 +329,42 @@
             super(packageName, uid);
             this.blobAccessMode = blobAccessMode;
         }
+
+        void dump(IndentingPrintWriter fout) {
+            fout.println("accessMode:");
+            fout.increaseIndent();
+            blobAccessMode.dump(fout);
+            fout.decreaseIndent();
+        }
+
+        void writeToXml(@NonNull XmlSerializer out) throws IOException {
+            XmlUtils.writeStringAttribute(out, ATTR_PACKAGE, packageName);
+            XmlUtils.writeIntAttribute(out, ATTR_UID, uid);
+
+            out.startTag(null, TAG_ACCESS_MODE);
+            blobAccessMode.writeToXml(out);
+            out.endTag(null, TAG_ACCESS_MODE);
+        }
+
+        @Nullable
+        static Committer createFromXml(@NonNull XmlPullParser in)
+                throws XmlPullParserException, IOException {
+            final String packageName = XmlUtils.readStringAttribute(in, ATTR_PACKAGE);
+            final int uid = XmlUtils.readIntAttribute(in, ATTR_UID);
+
+            final int depth = in.getDepth();
+            BlobAccessMode blobAccessMode = null;
+            while (XmlUtils.nextElementWithin(in, depth)) {
+                if (TAG_ACCESS_MODE.equals(in.getName())) {
+                    blobAccessMode = BlobAccessMode.createFromXml(in);
+                }
+            }
+            if (blobAccessMode == null) {
+                Slog.wtf(TAG, "blobAccessMode should be available");
+                return null;
+            }
+            return new Committer(packageName, uid, blobAccessMode);
+        }
     }
 
     static final class Leasee extends Accessor {
@@ -176,6 +380,38 @@
         boolean isStillValid() {
             return expiryTimeMillis == 0 || expiryTimeMillis <= System.currentTimeMillis();
         }
+
+        void dump(Context context, IndentingPrintWriter fout) {
+            String desc = null;
+            try {
+                final Resources leaseeRes = context.getPackageManager()
+                        .getResourcesForApplicationAsUser(packageName, UserHandle.getUserId(uid));
+                desc = leaseeRes.getString(descriptionResId);
+            } catch (PackageManager.NameNotFoundException e) {
+                Slog.d(TAG, "Unknown package in user " + UserHandle.getUserId(uid) + ": "
+                        + packageName, e);
+                desc = "<none>";
+            }
+            fout.println("desc: " + desc);
+            fout.println("expiryMs: " + expiryTimeMillis);
+        }
+
+        void writeToXml(@NonNull XmlSerializer out) throws IOException {
+            XmlUtils.writeStringAttribute(out, ATTR_PACKAGE, packageName);
+            XmlUtils.writeIntAttribute(out, ATTR_UID, uid);
+            XmlUtils.writeIntAttribute(out, ATTR_DESCRIPTION_RES_ID, descriptionResId);
+            XmlUtils.writeLongAttribute(out, ATTR_EXPIRY_TIME, expiryTimeMillis);
+        }
+
+        @NonNull
+        static Leasee createFromXml(@NonNull XmlPullParser in) throws IOException {
+            final String packageName = XmlUtils.readStringAttribute(in, ATTR_PACKAGE);
+            final int uid = XmlUtils.readIntAttribute(in, ATTR_UID);
+            final int descriptionResId = XmlUtils.readIntAttribute(in, ATTR_DESCRIPTION_RES_ID);
+            final long expiryTimeMillis = XmlUtils.readLongAttribute(in, ATTR_EXPIRY_TIME);
+
+            return new Leasee(packageName, uid, descriptionResId, expiryTimeMillis);
+        }
     }
 
     static class Accessor {
@@ -207,5 +443,10 @@
         public int hashCode() {
             return Objects.hash(packageName, uid);
         }
+
+        @Override
+        public String toString() {
+            return "[" + packageName + ", " + uid + "]";
+        }
     }
 }
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java
index b9a4b17..eb414b0 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java
@@ -25,6 +25,13 @@
 class BlobStoreConfig {
     public static final String TAG = "BlobStore";
 
+    public static final int CURRENT_XML_VERSION = 1;
+
+    private static final String ROOT_DIR_NAME = "blobstore";
+    private static final String BLOBS_DIR_NAME = "blobs";
+    private static final String SESSIONS_INDEX_FILE_NAME = "sessions_index.xml";
+    private static final String BLOBS_INDEX_FILE_NAME = "blobs_index.xml";
+
     @Nullable
     public static File prepareBlobFile(long sessionId) {
         final File blobsDir = prepareBlobsDir();
@@ -58,7 +65,25 @@
 
     @NonNull
     private static File getBlobsDir(File blobsRootDir) {
-        return new File(blobsRootDir, "blobs");
+        return new File(blobsRootDir, BLOBS_DIR_NAME);
+    }
+
+    @Nullable
+    public static File prepareSessionIndexFile() {
+        final File blobStoreRootDir = prepareBlobStoreRootDir();
+        if (blobStoreRootDir == null) {
+            return null;
+        }
+        return new File(blobStoreRootDir, SESSIONS_INDEX_FILE_NAME);
+    }
+
+    @Nullable
+    public static File prepareBlobsIndexFile() {
+        final File blobsStoreRootDir = prepareBlobStoreRootDir();
+        if (blobsStoreRootDir == null) {
+            return null;
+        }
+        return new File(blobsStoreRootDir, BLOBS_INDEX_FILE_NAME);
     }
 
     @Nullable
@@ -73,6 +98,6 @@
 
     @NonNull
     public static File getBlobStoreRootDir() {
-        return new File(Environment.getDataSystemDirectory(), "blobstore");
+        return new File(Environment.getDataSystemDirectory(), ROOT_DIR_NAME);
     }
 }
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
index 9d60f86..fcc30e3 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
@@ -15,8 +15,19 @@
  */
 package com.android.server.blob;
 
+import static android.app.blob.BlobStoreManager.COMMIT_RESULT_ERROR;
 import static android.app.blob.BlobStoreManager.COMMIT_RESULT_SUCCESS;
+import static android.app.blob.XmlTags.ATTR_VERSION;
+import static android.app.blob.XmlTags.TAG_BLOB;
+import static android.app.blob.XmlTags.TAG_BLOBS;
+import static android.app.blob.XmlTags.TAG_SESSION;
+import static android.app.blob.XmlTags.TAG_SESSIONS;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
+import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
+import static android.os.UserHandle.USER_NULL;
 
+import static com.android.server.blob.BlobStoreConfig.CURRENT_XML_VERSION;
 import static com.android.server.blob.BlobStoreConfig.TAG;
 import static com.android.server.blob.BlobStoreSession.STATE_ABANDONED;
 import static com.android.server.blob.BlobStoreSession.STATE_COMMITTED;
@@ -28,32 +39,58 @@
 import android.annotation.IdRes;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.blob.BlobHandle;
 import android.app.blob.IBlobStoreManager;
 import android.app.blob.IBlobStoreSession;
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManagerInternal;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
+import android.os.RemoteCallback;
+import android.os.SystemClock;
 import android.os.UserHandle;
+import android.os.UserManagerInternal;
 import android.util.ArrayMap;
+import android.util.AtomicFile;
 import android.util.ExceptionUtils;
 import android.util.LongSparseArray;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.Xml;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.DumpUtils;
+import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
+import com.android.internal.util.XmlUtils;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.LocalServices;
 import com.android.server.ServiceThread;
 import com.android.server.SystemService;
 import com.android.server.Watchdog;
+import com.android.server.blob.BlobMetadata.Committer;
 
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Service responsible for maintaining and facilitating access to data blobs published by apps.
@@ -96,14 +133,34 @@
         publishBinderService(Context.BLOB_STORE_SERVICE, new Stub());
 
         mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
+        registerReceivers();
     }
 
+    @Override
+    public void onBootPhase(int phase) {
+        if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
+            synchronized (mBlobsLock) {
+                final SparseArray<SparseArray<String>> allPackages = getAllPackages();
+                readBlobSessionsLocked(allPackages);
+                readBlobsInfoLocked(allPackages);
+            }
+        }
+    }
 
     @GuardedBy("mBlobsLock")
     private long generateNextSessionIdLocked() {
         return ++mCurrentMaxSessionId;
     }
 
+    private void registerReceivers() {
+        final IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
+        intentFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
+        intentFilter.addAction(Intent.ACTION_USER_REMOVED);
+        mContext.registerReceiverAsUser(new PackageChangedReceiver(), UserHandle.ALL,
+                intentFilter, null, mHandler);
+    }
+
     @GuardedBy("mBlobsLock")
     private LongSparseArray<BlobStoreSession> getUserSessionsLocked(int userId) {
         LongSparseArray<BlobStoreSession> userSessions = mSessions.get(userId);
@@ -133,7 +190,7 @@
                     sessionId, blobHandle, callingUid, callingPackage,
                     mSessionStateChangeListener);
             getUserSessionsLocked(UserHandle.getUserId(callingUid)).put(sessionId, session);
-            // TODO: persist sessions data
+            writeBlobSessionsAsync();
             return sessionId;
         }
     }
@@ -160,7 +217,8 @@
                     callingUid, callingPackage);
             session.open();
             session.abandon();
-            // TODO: persist sessions data
+
+            writeBlobSessionsAsync();
         }
     }
 
@@ -194,7 +252,7 @@
             }
             blobMetadata.addLeasee(callingPackage, callingUid,
                     descriptionResId, leaseExpiryTimeMillis);
-            // TODO: persist blobs data
+            writeBlobsInfoAsync();
         }
     }
 
@@ -209,6 +267,7 @@
                         + "; callingUid=" + callingUid + ", callingPackage=" + callingPackage);
             }
             blobMetadata.removeLeasee(callingPackage, callingUid);
+            writeBlobsInfoAsync();
         }
     }
 
@@ -241,18 +300,25 @@
                     session.verifyBlobData();
                     break;
                 case STATE_VERIFIED_VALID:
-                    final ArrayMap<BlobHandle, BlobMetadata> userBlobs =
-                            getUserBlobsLocked(UserHandle.getUserId(session.ownerUid));
+                    final int userId = UserHandle.getUserId(session.ownerUid);
+                    final ArrayMap<BlobHandle, BlobMetadata> userBlobs = getUserBlobsLocked(userId);
                     BlobMetadata blob = userBlobs.get(session.blobHandle);
                     if (blob == null) {
                         blob = new BlobMetadata(mContext,
-                                session.sessionId, session.blobHandle);
+                                session.sessionId, session.blobHandle, userId);
                         userBlobs.put(session.blobHandle, blob);
                     }
-                    blob.addCommitter(session.ownerPackageName, session.ownerUid,
-                            session.getBlobAccessMode());
-                    // TODO: Persist blobs data.
-                    session.sendCommitCallbackResult(COMMIT_RESULT_SUCCESS);
+                    final Committer newCommitter = new Committer(session.ownerPackageName,
+                            session.ownerUid, session.getBlobAccessMode());
+                    final Committer existingCommitter = blob.getExistingCommitter(newCommitter);
+                    blob.addCommitter(newCommitter);
+                    try {
+                        writeBlobsInfoLocked();
+                        session.sendCommitCallbackResult(COMMIT_RESULT_SUCCESS);
+                    } catch (Exception e) {
+                        blob.addCommitter(existingCommitter);
+                        session.sendCommitCallbackResult(COMMIT_RESULT_ERROR);
+                    }
                     getUserSessionsLocked(UserHandle.getUserId(session.ownerUid))
                             .remove(session.sessionId);
                     break;
@@ -260,7 +326,330 @@
                     Slog.wtf(TAG, "Invalid session state: "
                             + stateToString(session.getState()));
             }
-            // TODO: Persist sessions data.
+            try {
+                writeBlobSessionsLocked();
+            } catch (Exception e) {
+                // already logged, ignore.
+            }
+        }
+    }
+
+    @GuardedBy("mBlobsLock")
+    private void writeBlobSessionsLocked() throws Exception {
+        final AtomicFile sessionsIndexFile = prepareSessionsIndexFile();
+        if (sessionsIndexFile == null) {
+            Slog.wtf(TAG, "Error creating sessions index file");
+            return;
+        }
+        FileOutputStream fos = null;
+        try {
+            fos = sessionsIndexFile.startWrite(SystemClock.uptimeMillis());
+            final XmlSerializer out = new FastXmlSerializer();
+            out.setOutput(fos, StandardCharsets.UTF_8.name());
+            out.startDocument(null, true);
+            out.startTag(null, TAG_SESSIONS);
+            XmlUtils.writeIntAttribute(out, ATTR_VERSION, CURRENT_XML_VERSION);
+
+            for (int i = 0, userCount = mSessions.size(); i < userCount; ++i) {
+                final LongSparseArray<BlobStoreSession> userSessions =
+                        mSessions.valueAt(i);
+                for (int j = 0, sessionsCount = userSessions.size(); j < sessionsCount; ++j) {
+                    out.startTag(null, TAG_SESSION);
+                    userSessions.valueAt(j).writeToXml(out);
+                    out.endTag(null, TAG_SESSION);
+                }
+            }
+
+            out.endTag(null, TAG_SESSIONS);
+            out.endDocument();
+            sessionsIndexFile.finishWrite(fos);
+        } catch (Exception e) {
+            sessionsIndexFile.failWrite(fos);
+            Slog.wtf(TAG, "Error writing sessions data", e);
+            throw e;
+        }
+    }
+
+    @GuardedBy("mBlobsLock")
+    private void readBlobSessionsLocked(SparseArray<SparseArray<String>> allPackages) {
+        if (!BlobStoreConfig.getBlobStoreRootDir().exists()) {
+            return;
+        }
+        final AtomicFile sessionsIndexFile = prepareSessionsIndexFile();
+        if (sessionsIndexFile == null) {
+            Slog.wtf(TAG, "Error creating sessions index file");
+            return;
+        }
+
+        mSessions.clear();
+        try (FileInputStream fis = sessionsIndexFile.openRead()) {
+            final XmlPullParser in = Xml.newPullParser();
+            in.setInput(fis, StandardCharsets.UTF_8.name());
+            XmlUtils.beginDocument(in, TAG_SESSIONS);
+            while (true) {
+                XmlUtils.nextElement(in);
+                if (in.getEventType() == XmlPullParser.END_DOCUMENT) {
+                    break;
+                }
+
+                if (TAG_SESSION.equals(in.getName())) {
+                    final BlobStoreSession session = BlobStoreSession.createFromXml(
+                            in, mContext, mSessionStateChangeListener);
+                    if (session == null) {
+                        continue;
+                    }
+                    final SparseArray<String> userPackages = allPackages.get(
+                            UserHandle.getUserId(session.ownerUid));
+                    if (userPackages != null
+                            && session.ownerPackageName.equals(
+                                    userPackages.get(session.ownerUid))) {
+                        getUserSessionsLocked(UserHandle.getUserId(session.ownerUid)).put(
+                                session.sessionId, session);
+                    } else {
+                        // Unknown package or the session data does not belong to this package.
+                        session.getSessionFile().delete();
+                    }
+                    mCurrentMaxSessionId = Math.max(mCurrentMaxSessionId, session.sessionId);
+                }
+            }
+        } catch (Exception e) {
+            Slog.wtf(TAG, "Error reading sessions data", e);
+        }
+    }
+
+    @GuardedBy("mBlobsLock")
+    private void writeBlobsInfoLocked() throws Exception {
+        final AtomicFile blobsIndexFile = prepareBlobsIndexFile();
+        if (blobsIndexFile == null) {
+            Slog.wtf(TAG, "Error creating blobs index file");
+            return;
+        }
+        FileOutputStream fos = null;
+        try {
+            fos = blobsIndexFile.startWrite(SystemClock.uptimeMillis());
+            final XmlSerializer out = new FastXmlSerializer();
+            out.setOutput(fos, StandardCharsets.UTF_8.name());
+            out.startDocument(null, true);
+            out.startTag(null, TAG_BLOBS);
+            XmlUtils.writeIntAttribute(out, ATTR_VERSION, CURRENT_XML_VERSION);
+
+            for (int i = 0, userCount = mBlobsMap.size(); i < userCount; ++i) {
+                final ArrayMap<BlobHandle, BlobMetadata> userBlobs = mBlobsMap.valueAt(i);
+                for (int j = 0, blobsCount = userBlobs.size(); j < blobsCount; ++j) {
+                    out.startTag(null, TAG_BLOB);
+                    userBlobs.valueAt(j).writeToXml(out);
+                    out.endTag(null, TAG_BLOB);
+                }
+            }
+
+            out.endTag(null, TAG_BLOBS);
+            out.endDocument();
+            blobsIndexFile.finishWrite(fos);
+        } catch (Exception e) {
+            blobsIndexFile.failWrite(fos);
+            Slog.wtf(TAG, "Error writing blobs data", e);
+            throw e;
+        }
+    }
+
+    @GuardedBy("mBlobsLock")
+    private void readBlobsInfoLocked(SparseArray<SparseArray<String>> allPackages) {
+        if (!BlobStoreConfig.getBlobStoreRootDir().exists()) {
+            return;
+        }
+        final AtomicFile blobsIndexFile = prepareBlobsIndexFile();
+        if (blobsIndexFile == null) {
+            Slog.wtf(TAG, "Error creating blobs index file");
+            return;
+        }
+
+        mBlobsMap.clear();
+        try (FileInputStream fis = blobsIndexFile.openRead()) {
+            final XmlPullParser in = Xml.newPullParser();
+            in.setInput(fis, StandardCharsets.UTF_8.name());
+            XmlUtils.beginDocument(in, TAG_BLOBS);
+            while (true) {
+                XmlUtils.nextElement(in);
+                if (in.getEventType() == XmlPullParser.END_DOCUMENT) {
+                    break;
+                }
+
+                if (TAG_BLOB.equals(in.getName())) {
+                    final BlobMetadata blobMetadata = BlobMetadata.createFromXml(mContext, in);
+                    final SparseArray<String> userPackages = allPackages.get(blobMetadata.userId);
+                    if (userPackages == null) {
+                        blobMetadata.getBlobFile().delete();
+                    } else {
+                        getUserBlobsLocked(blobMetadata.userId).put(
+                                blobMetadata.blobHandle, blobMetadata);
+                        blobMetadata.removeInvalidCommitters(userPackages);
+                        blobMetadata.removeInvalidLeasees(userPackages);
+                    }
+                    mCurrentMaxSessionId = Math.max(mCurrentMaxSessionId, blobMetadata.blobId);
+                }
+            }
+        } catch (Exception e) {
+            Slog.wtf(TAG, "Error reading blobs data", e);
+        }
+    }
+
+    private void writeBlobsInfo() {
+        synchronized (mBlobsLock) {
+            try {
+                writeBlobsInfoLocked();
+            } catch (Exception e) {
+                // Already logged, ignore
+            }
+        }
+    }
+
+    private void writeBlobsInfoAsync() {
+        mHandler.post(PooledLambda.obtainRunnable(
+                BlobStoreManagerService::writeBlobsInfo,
+                BlobStoreManagerService.this).recycleOnUse());
+    }
+
+    private void writeBlobSessions() {
+        synchronized (mBlobsLock) {
+            try {
+                writeBlobSessionsLocked();
+            } catch (Exception e) {
+                // Already logged, ignore
+            }
+        }
+    }
+
+    private void writeBlobSessionsAsync() {
+        mHandler.post(PooledLambda.obtainRunnable(
+                BlobStoreManagerService::writeBlobSessions,
+                BlobStoreManagerService.this).recycleOnUse());
+    }
+
+    private int getPackageUid(String packageName, int userId) {
+        final int uid = mPackageManagerInternal.getPackageUid(
+                packageName,
+                MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE | MATCH_UNINSTALLED_PACKAGES,
+                userId);
+        return uid;
+    }
+
+    private SparseArray<SparseArray<String>> getAllPackages() {
+        final SparseArray<SparseArray<String>> allPackages = new SparseArray<>();
+        final int[] allUsers = LocalServices.getService(UserManagerInternal.class).getUserIds();
+        for (int userId : allUsers) {
+            final SparseArray<String> userPackages = new SparseArray<>();
+            allPackages.put(userId, userPackages);
+            final List<ApplicationInfo> applicationInfos = mPackageManagerInternal
+                    .getInstalledApplications(
+                            MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE
+                                    | MATCH_UNINSTALLED_PACKAGES,
+                            userId, Process.myUid());
+            for (int i = 0, count = applicationInfos.size(); i < count; ++i) {
+                final ApplicationInfo applicationInfo = applicationInfos.get(i);
+                userPackages.put(applicationInfo.uid, applicationInfo.packageName);
+            }
+        }
+        return allPackages;
+    }
+
+    AtomicFile prepareSessionsIndexFile() {
+        final File file = BlobStoreConfig.prepareSessionIndexFile();
+        if (file == null) {
+            return null;
+        }
+        return new AtomicFile(file, "session_index" /* commitLogTag */);
+    }
+
+    AtomicFile prepareBlobsIndexFile() {
+        final File file = BlobStoreConfig.prepareBlobsIndexFile();
+        if (file == null) {
+            return null;
+        }
+        return new AtomicFile(file, "blobs_index" /* commitLogTag */);
+    }
+
+    private void handlePackageRemoved(String packageName, int uid) {
+        synchronized (mBlobsLock) {
+            // Clean up any pending sessions
+            final LongSparseArray<BlobStoreSession> userSessions =
+                    getUserSessionsLocked(UserHandle.getUserId(uid));
+            final ArrayList<Integer> indicesToRemove = new ArrayList<>();
+            for (int i = 0, count = userSessions.size(); i < count; ++i) {
+                final BlobStoreSession session = userSessions.valueAt(i);
+                if (session.ownerUid == uid
+                        && session.ownerPackageName.equals(packageName)) {
+                    session.getSessionFile().delete();
+                    indicesToRemove.add(i);
+                }
+            }
+            for (int i = 0, count = indicesToRemove.size(); i < count; ++i) {
+                userSessions.removeAt(i);
+            }
+
+            // Remove the package from the committer and leasee list
+            final ArrayMap<BlobHandle, BlobMetadata> userBlobs =
+                    getUserBlobsLocked(UserHandle.getUserId(uid));
+            for (int i = 0, count = userBlobs.size(); i < count; ++i) {
+                final BlobMetadata blobMetadata = userBlobs.valueAt(i);
+                blobMetadata.removeCommitter(packageName, uid);
+                blobMetadata.removeLeasee(packageName, uid);
+            }
+            // TODO: clean-up blobs which doesn't have any active leases.
+        }
+    }
+
+    private void handleUserRemoved(int userId) {
+        synchronized (mBlobsLock) {
+            final LongSparseArray<BlobStoreSession> userSessions =
+                    mSessions.removeReturnOld(userId);
+            if (userSessions != null) {
+                for (int i = 0, count = userSessions.size(); i < count; ++i) {
+                    final BlobStoreSession session = userSessions.valueAt(i);
+                    session.getSessionFile().delete();
+                }
+            }
+
+            final ArrayMap<BlobHandle, BlobMetadata> userBlobs =
+                    mBlobsMap.removeReturnOld(userId);
+            if (userBlobs != null) {
+                for (int i = 0, count = userBlobs.size(); i < count; ++i) {
+                    final BlobMetadata blobMetadata = userBlobs.valueAt(i);
+                    blobMetadata.getBlobFile().delete();
+                }
+            }
+        }
+    }
+
+    private class PackageChangedReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            switch (intent.getAction()) {
+                case Intent.ACTION_PACKAGE_FULLY_REMOVED:
+                case Intent.ACTION_PACKAGE_DATA_CLEARED:
+                    final String packageName = intent.getData().getSchemeSpecificPart();
+                    if (packageName == null) {
+                        Slog.wtf(TAG, "Package name is missing in the intent: " + intent);
+                        return;
+                    }
+                    final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
+                    if (uid == -1) {
+                        Slog.wtf(TAG, "uid is missing in the intent: " + intent);
+                        return;
+                    }
+                    handlePackageRemoved(packageName, uid);
+                    break;
+                case Intent.ACTION_USER_REMOVED:
+                    final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
+                            USER_NULL);
+                    if (userId == USER_NULL) {
+                        Slog.wtf(TAG, "userId is missing in the intent: " + intent);
+                        return;
+                    }
+                    handleUserRemoved(userId);
+                    break;
+                default:
+                    Slog.wtf(TAG, "Received unknown intent: " + intent);
+            }
         }
     }
 
@@ -341,6 +730,8 @@
                 @CurrentTimeSecondsLong long leaseTimeoutSecs, @NonNull String packageName) {
             Preconditions.checkNotNull(blobHandle, "blobHandle must not be null");
             Preconditions.checkNotNull(packageName, "packageName must not be null");
+            Preconditions.checkArgumentPositive(descriptionResId,
+                    "descriptionResId must be positive; value=" + descriptionResId);
 
             final int callingUid = Binder.getCallingUid();
             verifyCallingPackage(callingUid, packageName);
@@ -360,5 +751,62 @@
 
             releaseLeaseInternal(blobHandle, callingUid, packageName);
         }
+
+        @Override
+        public void waitForIdle(@NonNull RemoteCallback remoteCallback) {
+            Preconditions.checkNotNull(remoteCallback, "remoteCallback must not be null");
+
+            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP,
+                    "Caller is not allowed to call this; caller=" + Binder.getCallingUid());
+            mHandler.post(PooledLambda.obtainRunnable(remoteCallback::sendResult, null)
+                    .recycleOnUse());
+        }
+
+        @Override
+        public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer,
+                @Nullable String[] args) {
+            // TODO: add proto-based version of this.
+            if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
+
+            final IndentingPrintWriter fout = new IndentingPrintWriter(writer, "    ");
+            synchronized (mBlobsLock) {
+                fout.println("mCurrentMaxSessionId: " + mCurrentMaxSessionId);
+                fout.println();
+                for (int i = 0, userCount = mSessions.size(); i < userCount; ++i) {
+                    final int userId = mSessions.keyAt(i);
+                    final LongSparseArray<BlobStoreSession> userSessions = mSessions.valueAt(i);
+                    fout.println("List of sessions in user #"
+                            + userId + " (" + userSessions.size() + "):");
+                    fout.increaseIndent();
+                    for (int j = 0, sessionsCount = userSessions.size(); j < sessionsCount; ++j) {
+                        final long sessionId = userSessions.keyAt(j);
+                        final BlobStoreSession session = userSessions.valueAt(j);
+                        fout.println("Session #" + sessionId);
+                        fout.increaseIndent();
+                        session.dump(fout);
+                        fout.decreaseIndent();
+                    }
+                    fout.decreaseIndent();
+                }
+
+                fout.print("\n\n");
+
+                for (int i = 0, userCount = mBlobsMap.size(); i < userCount; ++i) {
+                    final int userId = mBlobsMap.keyAt(i);
+                    final ArrayMap<BlobHandle, BlobMetadata> userBlobs = mBlobsMap.valueAt(i);
+                    fout.println("List of blobs in user #"
+                            + userId + " (" + userBlobs.size() + "):");
+                    fout.increaseIndent();
+                    for (int j = 0, blobsCount = userBlobs.size(); j < blobsCount; ++j) {
+                        final BlobMetadata blobMetadata = userBlobs.valueAt(j);
+                        fout.println("Blob #" + blobMetadata.blobId);
+                        fout.increaseIndent();
+                        blobMetadata.dump(fout);
+                        fout.decreaseIndent();
+                    }
+                    fout.decreaseIndent();
+                }
+            }
+        }
     }
-}
+}
\ No newline at end of file
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
index 29092b3..7d1c166 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
@@ -16,7 +16,13 @@
 package com.android.server.blob;
 
 import static android.app.blob.BlobStoreManager.COMMIT_RESULT_ERROR;
+import static android.app.blob.XmlTags.ATTR_ID;
+import static android.app.blob.XmlTags.ATTR_PACKAGE;
+import static android.app.blob.XmlTags.ATTR_UID;
+import static android.app.blob.XmlTags.TAG_ACCESS_MODE;
+import static android.app.blob.XmlTags.TAG_BLOB_HANDLE;
 import static android.system.OsConstants.O_CREAT;
+import static android.system.OsConstants.O_RDONLY;
 import static android.system.OsConstants.O_RDWR;
 import static android.system.OsConstants.SEEK_SET;
 
@@ -41,9 +47,15 @@
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
+import com.android.internal.util.XmlUtils;
 import com.android.server.blob.BlobStoreManagerService.SessionStateChangeListener;
 
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -187,9 +199,43 @@
     }
 
     @Override
+    @NonNull
+    public ParcelFileDescriptor openRead() {
+        assertCallerIsOwner();
+        synchronized (mSessionLock) {
+            if (mState != STATE_OPENED) {
+                throw new IllegalStateException("Not allowed to read in state: "
+                        + stateToString(mState));
+            }
+
+            try {
+                return openReadLocked();
+            } catch (IOException e) {
+                throw ExceptionUtils.wrap(e);
+            }
+        }
+    }
+
+    @GuardedBy("mSessionLock")
+    @NonNull
+    private ParcelFileDescriptor openReadLocked() throws IOException {
+        FileDescriptor fd = null;
+        try {
+            final File sessionFile = getSessionFile();
+            if (sessionFile == null) {
+                throw new IllegalStateException("Couldn't get the file for this session");
+            }
+            fd = Os.open(sessionFile.getPath(), O_RDONLY, 0);
+        } catch (ErrnoException e) {
+            e.rethrowAsIOException();
+        }
+        return createRevocableFdLocked(fd);
+    }
+
+    @Override
     @BytesLong
     public long getSize() {
-        return 0;
+        return getSessionFile().length();
     }
 
     @Override
@@ -331,8 +377,8 @@
     private void revokeAllFdsLocked() {
         for (int i = mRevocableFds.size() - 1; i >= 0; --i) {
             mRevocableFds.get(i).revoke();
-            mRevocableFds.remove(i);
         }
+        mRevocableFds.clear();
     }
 
     @GuardedBy("mSessionLock")
@@ -383,4 +429,74 @@
             throw new SecurityException(ownerUid + " is not the session owner");
         }
     }
+
+    void dump(IndentingPrintWriter fout) {
+        synchronized (mSessionLock) {
+            fout.println("state: " + stateToString(mState));
+            fout.println("ownerUid: " + ownerUid);
+            fout.println("ownerPkg: " + ownerPackageName);
+
+            fout.println("blobHandle:");
+            fout.increaseIndent();
+            blobHandle.dump(fout);
+            fout.decreaseIndent();
+
+            fout.println("accessMode:");
+            fout.increaseIndent();
+            mBlobAccessMode.dump(fout);
+            fout.decreaseIndent();
+
+            fout.println("Open fds: #" + mRevocableFds.size());
+        }
+    }
+
+    void writeToXml(@NonNull XmlSerializer out) throws IOException {
+        synchronized (mSessionLock) {
+            XmlUtils.writeLongAttribute(out, ATTR_ID, sessionId);
+            XmlUtils.writeStringAttribute(out, ATTR_PACKAGE, ownerPackageName);
+            XmlUtils.writeIntAttribute(out, ATTR_UID, ownerUid);
+
+            out.startTag(null, TAG_BLOB_HANDLE);
+            blobHandle.writeToXml(out);
+            out.endTag(null, TAG_BLOB_HANDLE);
+
+            out.startTag(null, TAG_ACCESS_MODE);
+            mBlobAccessMode.writeToXml(out);
+            out.endTag(null, TAG_ACCESS_MODE);
+        }
+    }
+
+    @Nullable
+    static BlobStoreSession createFromXml(@NonNull XmlPullParser in,
+            @NonNull Context context, @NonNull SessionStateChangeListener stateChangeListener)
+            throws IOException, XmlPullParserException {
+        final int sessionId = XmlUtils.readIntAttribute(in, ATTR_ID);
+        final String ownerPackageName = XmlUtils.readStringAttribute(in, ATTR_PACKAGE);
+        final int ownerUid = XmlUtils.readIntAttribute(in, ATTR_UID);
+
+        final int depth = in.getDepth();
+        BlobHandle blobHandle = null;
+        BlobAccessMode blobAccessMode = null;
+        while (XmlUtils.nextElementWithin(in, depth)) {
+            if (TAG_BLOB_HANDLE.equals(in.getName())) {
+                blobHandle = BlobHandle.createFromXml(in);
+            } else if (TAG_ACCESS_MODE.equals(in.getName())) {
+                blobAccessMode = BlobAccessMode.createFromXml(in);
+            }
+        }
+
+        if (blobHandle == null) {
+            Slog.wtf(TAG, "blobHandle should be available");
+            return null;
+        }
+        if (blobAccessMode == null) {
+            Slog.wtf(TAG, "blobAccessMode should be available");
+            return null;
+        }
+
+        final BlobStoreSession blobStoreSession = new BlobStoreSession(context, sessionId,
+                blobHandle, ownerUid, ownerPackageName, stateChangeListener);
+        blobStoreSession.mBlobAccessMode.allow(blobAccessMode);
+        return blobStoreSession;
+    }
 }
diff --git a/apex/extservices/apex_manifest.json b/apex/extservices/apex_manifest.json
index 7ba2157..b4acf128 100644
--- a/apex/extservices/apex_manifest.json
+++ b/apex/extservices/apex_manifest.json
@@ -1,4 +1,4 @@
 {
   "name": "com.android.extservices",
-  "version": 1
+  "version": 300000000
 }
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
index a0e83da..bb94275 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
@@ -144,14 +144,18 @@
     public void startTrackingRestrictedJobLocked(JobStatus jobStatus) {
         // Don't need to start tracking the job. If the job needed network, it would already be
         // tracked.
-        updateConstraintsSatisfied(jobStatus);
+        if (jobStatus.hasConnectivityConstraint()) {
+            updateConstraintsSatisfied(jobStatus);
+        }
     }
 
     @Override
     public void stopTrackingRestrictedJobLocked(JobStatus jobStatus) {
         // Shouldn't stop tracking the job here. If the job was tracked, it still needs network,
         // even after being unrestricted.
-        updateConstraintsSatisfied(jobStatus);
+        if (jobStatus.hasConnectivityConstraint()) {
+            updateConstraintsSatisfied(jobStatus);
+        }
     }
 
     /**
diff --git a/apex/media/framework/Android.bp b/apex/media/framework/Android.bp
index 18382a4..2266d04 100644
--- a/apex/media/framework/Android.bp
+++ b/apex/media/framework/Android.bp
@@ -50,7 +50,7 @@
     ],
 
     static_libs: [
-        "exoplayer2-core"
+        "exoplayer2-extractor"
     ],
     jarjar_rules: "jarjar_rules.txt",
 
diff --git a/apex/media/framework/java/android/media/MediaParser.java b/apex/media/framework/java/android/media/MediaParser.java
index ac66d1b..d59270c 100644
--- a/apex/media/framework/java/android/media/MediaParser.java
+++ b/apex/media/framework/java/android/media/MediaParser.java
@@ -223,7 +223,7 @@
     public static final class SeekPoint {
 
         /** A {@link SeekPoint} whose time and byte offset are both set to 0. */
-        public static final @NonNull SeekPoint START = new SeekPoint(0, 0);
+        @NonNull public static final SeekPoint START = new SeekPoint(0, 0);
 
         /** The time of the seek point, in microseconds. */
         public final long timeUs;
@@ -241,7 +241,8 @@
         }
 
         @Override
-        public @NonNull String toString() {
+        @NonNull
+        public String toString() {
             return "[timeUs=" + timeUs + ", position=" + position + "]";
         }
 
@@ -414,7 +415,8 @@
      * @return A new instance.
      * @throws IllegalArgumentException If an invalid name is provided.
      */
-    public static @NonNull MediaParser createByName(
+    @NonNull
+    public static MediaParser createByName(
             @NonNull String name, @NonNull OutputConsumer outputConsumer) {
         String[] nameAsArray = new String[] {name};
         assertValidNames(nameAsArray);
@@ -431,7 +433,8 @@
      *     default array of names is used.
      * @return A new instance.
      */
-    public static @NonNull MediaParser create(
+    @NonNull
+    public static MediaParser create(
             @NonNull OutputConsumer outputConsumer, @NonNull String... extractorNames) {
         assertValidNames(extractorNames);
         if (extractorNames.length == 0) {
@@ -448,7 +451,8 @@
      *
      * <p>TODO: List which properties are taken into account. E.g. MimeType.
      */
-    public static @NonNull List<String> getExtractorNames(@NonNull MediaFormat mediaFormat) {
+    @NonNull
+    public static List<String> getExtractorNames(@NonNull MediaFormat mediaFormat) {
         throw new UnsupportedOperationException();
     }
 
@@ -479,7 +483,8 @@
      * @return The name of the backing extractor implementation, or null if the backing extractor
      *     implementation has not yet been selected.
      */
-    public @Nullable String getExtractorName() {
+    @Nullable
+    public String getExtractorName() {
         return mExtractorName;
     }
 
diff --git a/apex/permission/apex_manifest.json b/apex/permission/apex_manifest.json
index 2a8c4f7..7960598 100644
--- a/apex/permission/apex_manifest.json
+++ b/apex/permission/apex_manifest.json
@@ -1,4 +1,4 @@
 {
   "name": "com.android.permission",
-  "version": 1
+  "version": 300000000
 }
diff --git a/apex/permission/service/java/com/android/permission/persistence/RuntimePermissionsPersistenceImpl.java b/apex/permission/service/java/com/android/permission/persistence/RuntimePermissionsPersistenceImpl.java
index 1dbad45..90b1c4b 100644
--- a/apex/permission/service/java/com/android/permission/persistence/RuntimePermissionsPersistenceImpl.java
+++ b/apex/permission/service/java/com/android/permission/persistence/RuntimePermissionsPersistenceImpl.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.ApexContext;
+import android.content.pm.PackageManager;
 import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.AtomicFile;
@@ -242,9 +243,10 @@
             serializer.startTag(null, TAG_PERMISSION);
             serializer.attribute(null, ATTRIBUTE_NAME, permissionState.getName());
             serializer.attribute(null, ATTRIBUTE_GRANTED, Boolean.toString(
-                    permissionState.isGranted()));
+                    permissionState.isGranted() && (permissionState.getFlags()
+                            & PackageManager.FLAG_PERMISSION_ONE_TIME) == 0));
             serializer.attribute(null, ATTRIBUTE_FLAGS, Integer.toHexString(
-                    permissionState.getFlags()));
+                    permissionState.getFlags() & ~PackageManager.FLAG_PERMISSION_ONE_TIME));
             serializer.endTag(null, TAG_PERMISSION);
         }
     }
diff --git a/apex/sdkextensions/OWNERS b/apex/sdkextensions/OWNERS
index feb2742..a6e5522 100644
--- a/apex/sdkextensions/OWNERS
+++ b/apex/sdkextensions/OWNERS
@@ -1 +1,2 @@
+dariofreni@google.com
 hansson@google.com
diff --git a/apex/sdkextensions/framework/Android.bp b/apex/sdkextensions/framework/Android.bp
index dd17473..245a96b 100644
--- a/apex/sdkextensions/framework/Android.bp
+++ b/apex/sdkextensions/framework/Android.bp
@@ -32,6 +32,7 @@
     libs: [ "framework-annotations-lib" ],
     permitted_packages: [ "android.os.ext" ],
     installable: true,
+    plugins: ["java_api_finder"],
     visibility: [
         "//frameworks/base/apex/sdkextensions",
         "//frameworks/base/apex/sdkextensions/testing",
diff --git a/apex/sdkextensions/manifest.json b/apex/sdkextensions/manifest.json
index 048f5c4..deeb29e 100644
--- a/apex/sdkextensions/manifest.json
+++ b/apex/sdkextensions/manifest.json
@@ -1,4 +1,4 @@
 {
   "name": "com.android.sdkext",
-  "version": 1
+  "version": 300000000
 }
diff --git a/apex/statsd/aidl/Android.bp b/apex/statsd/aidl/Android.bp
index cc5172c6..6d639fd 100644
--- a/apex/statsd/aidl/Android.bp
+++ b/apex/statsd/aidl/Android.bp
@@ -14,7 +14,7 @@
 // limitations under the License.
 //
 
-// TODO(b/145815909): move StatsDimensionsValue.aidl and StatsLogEventWrapper.aidl here
+// TODO(b/145815909): move StatsDimensionsValue.aidl here
 filegroup {
     name: "statsd_aidl",
     srcs: [
diff --git a/apex/statsd/apex_manifest.json b/apex/statsd/apex_manifest.json
index 0c0ad86..e2972e7 100644
--- a/apex/statsd/apex_manifest.json
+++ b/apex/statsd/apex_manifest.json
@@ -1,5 +1,5 @@
 {
   "name": "com.android.os.statsd",
-  "version": 1
+  "version": 300000000
 }
 
diff --git a/apex/statsd/framework/Android.bp b/apex/statsd/framework/Android.bp
index 0b46645a..f66f034 100644
--- a/apex/statsd/framework/Android.bp
+++ b/apex/statsd/framework/Android.bp
@@ -24,7 +24,7 @@
     name: "framework-statsd",
     installable: true,
     // TODO(b/146209659): Use system_current instead.
-    sdk_version: "core_current",
+    sdk_version: "core_platform",
     srcs: [
         ":framework-statsd-sources",
     ],
@@ -35,7 +35,9 @@
     libs: [
         "framework-annotations-lib",
         // TODO(b/146230220): Use framework-system-stubs instead.
-        "android_system_stubs_current",
+        //"android_system_stubs_current",
+        //"framework_module_lib_stubs_current",
+        "framework-all",
     ],
     hostdex: true, // for hiddenapi check
     visibility: [
@@ -52,12 +54,14 @@
 droidstubs {
     name: "framework-statsd-stubs-docs",
     defaults: [
-        "framework-module-stubs-defaults-publicapi"
+        "framework-module-stubs-defaults-systemapi"
     ],
     srcs: [
+        ":framework-annotations",
         ":framework-statsd-sources",
     ],
     libs: [
+        // TODO(b/148218250): Change to android_system_stubs_current
         "framework-all",
     ],
     sdk_version: "core_platform",
@@ -70,6 +74,7 @@
         ":framework-statsd-stubs-docs",
     ],
     libs: [
+        // TODO(b/148218250): Change to android_system_stubs_current
         "framework-all",
     ],
     sdk_version: "core_platform",
diff --git a/core/java/android/app/StatsManager.java b/apex/statsd/framework/java/android/app/StatsManager.java
similarity index 97%
rename from core/java/android/app/StatsManager.java
rename to apex/statsd/framework/java/android/app/StatsManager.java
index 0ea05d8..a1de330 100644
--- a/core/java/android/app/StatsManager.java
+++ b/apex/statsd/framework/java/android/app/StatsManager.java
@@ -30,7 +30,7 @@
 import android.os.IStatsManagerService;
 import android.os.IStatsd;
 import android.os.RemoteException;
-import android.os.ServiceManager;
+import android.os.StatsFrameworkInitializer;
 import android.util.AndroidException;
 import android.util.Slog;
 import android.util.StatsEvent;
@@ -474,17 +474,6 @@
     }
 
     /**
-     * Temp registration for while the migration is in progress.
-     *
-     * @hide
-     */
-    public void registerPullAtomCallback(int atomTag, @Nullable PullAtomMetadata metadata,
-            @NonNull StatsPullAtomCallback callback,
-            @NonNull @CallbackExecutor Executor executor) {
-        registerPullAtomCallback(atomTag, metadata, executor, callback);
-    }
-
-    /**
      * Registers a callback for an atom when that atom is to be pulled. The stats service will
      * invoke pullData in the callback when the stats service determines that this atom needs to be
      * pulled.
@@ -591,15 +580,6 @@
         }
 
         /**
-         * Temp for while migrations are in progress.
-         *
-         * @hide
-         */
-        public static PullAtomMetadata.Builder newBuilder() {
-            return new PullAtomMetadata.Builder();
-        }
-
-        /**
          *  Builder for PullAtomMetadata.
          */
         public static class Builder {
@@ -702,7 +682,10 @@
             return mStatsManagerService;
         }
         mStatsManagerService = IStatsManagerService.Stub.asInterface(
-                ServiceManager.getService(Context.STATS_MANAGER_SERVICE));
+                StatsFrameworkInitializer
+                .getStatsServiceManager()
+                .getStatsManagerServiceRegisterer()
+                .get());
         return mStatsManagerService;
     }
 
diff --git a/apex/statsd/framework/java/android/os/StatsFrameworkInitializer.java b/apex/statsd/framework/java/android/os/StatsFrameworkInitializer.java
new file mode 100644
index 0000000..3d95533
--- /dev/null
+++ b/apex/statsd/framework/java/android/os/StatsFrameworkInitializer.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.os;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.app.StatsManager;
+import android.app.SystemServiceRegistry;
+import android.content.Context;
+
+/**
+ * Class for performing registration for all stats services
+ *
+ * TODO(b/148225705) Change to @SystemApi(client=MODULE_LIBRARIES) when the build system is ready.
+ * @hide
+ */
+@SystemApi
+public class StatsFrameworkInitializer {
+    private StatsFrameworkInitializer() {
+    }
+
+    private static volatile StatsServiceManager sStatsServiceManager;
+
+    /**
+     * Sets an instance of {@link StatsServiceManager} that allows
+     * the statsd mainline module to register/obtain stats binder services. This is called
+     * by the platform during the system initialization.
+     *
+     * @param statsServiceManager instance of {@link StatsServiceManager} that allows
+     * the statsd mainline module to register/obtain statsd binder services.
+     */
+    public static void setStatsServiceManager(
+            @NonNull StatsServiceManager statsServiceManager) {
+        if (sStatsServiceManager != null) {
+            throw new IllegalStateException("setStatsServiceManager called twice!");
+        }
+
+        if (statsServiceManager == null) {
+            throw new NullPointerException("statsServiceManager is null");
+        }
+
+        sStatsServiceManager = statsServiceManager;
+    }
+
+    /** @hide */
+    public static StatsServiceManager getStatsServiceManager() {
+        return sStatsServiceManager;
+    }
+
+    /**
+     * Called by {@link SystemServiceRegistry}'s static initializer and registers all statsd
+     * services to {@link Context}, so that {@link Context#getSystemService} can return them.
+     *
+     * @throws IllegalStateException if this is called from anywhere besides
+     * {@link SystemServiceRegistry}
+     */
+    public static void registerServiceWrappers() {
+        SystemServiceRegistry.registerContextAwareService(
+                Context.STATS_MANAGER,
+                StatsManager.class,
+                context -> new StatsManager(context)
+        );
+    }
+}
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
index bcbb5a1..1e92826 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
@@ -15,160 +15,51 @@
  */
 package com.android.server.stats;
 
-import static android.app.AppOpsManager.OP_FLAGS_ALL_TRUSTED;
-import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
-import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;
 import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
-import static android.os.Process.getUidForPid;
-import static android.os.storage.VolumeInfo.TYPE_PRIVATE;
-import static android.os.storage.VolumeInfo.TYPE_PUBLIC;
 
-import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
-import static com.android.server.stats.pull.IonMemoryUtil.readProcessSystemIonHeapSizesFromDebugfs;
-import static com.android.server.stats.pull.IonMemoryUtil.readSystemIonHeapSizeFromDebugfs;
-import static com.android.server.stats.pull.ProcfsMemoryUtil.forEachPid;
-import static com.android.server.stats.pull.ProcfsMemoryUtil.readCmdlineFromProcfs;
-import static com.android.server.stats.pull.ProcfsMemoryUtil.readMemorySnapshotFromProcfs;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.ActivityManagerInternal;
 import android.app.AlarmManager;
 import android.app.AlarmManager.OnAlarmListener;
-import android.app.AppOpsManager;
-import android.app.AppOpsManager.HistoricalOps;
-import android.app.AppOpsManager.HistoricalOpsRequest;
-import android.app.AppOpsManager.HistoricalPackageOps;
-import android.app.AppOpsManager.HistoricalUidOps;
-import android.app.INotificationManager;
-import android.app.ProcessMemoryState;
 import android.app.StatsManager;
-import android.bluetooth.BluetoothActivityEnergyInfo;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.UidTraffic;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.PermissionInfo;
-import android.content.pm.UserInfo;
-import android.hardware.biometrics.BiometricsProtoEnums;
-import android.hardware.face.FaceManager;
-import android.hardware.fingerprint.FingerprintManager;
-import android.net.ConnectivityManager;
-import android.net.INetworkStatsService;
-import android.net.Network;
-import android.net.NetworkRequest;
-import android.net.NetworkStats;
-import android.net.wifi.WifiManager;
-import android.os.BatteryStats;
-import android.os.BatteryStatsInternal;
 import android.os.Binder;
-import android.os.Build;
 import android.os.Bundle;
-import android.os.CoolingDevice;
-import android.os.Environment;
-import android.os.FileUtils;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.IStatsCompanionService;
 import android.os.IStatsd;
-import android.os.IStoraged;
-import android.os.IThermalEventListener;
-import android.os.IThermalService;
 import android.os.Looper;
 import android.os.ParcelFileDescriptor;
-import android.os.Parcelable;
 import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.StatFs;
-import android.os.StatsLogEventWrapper;
-import android.os.SynchronousResultReceiver;
+import android.os.StatsFrameworkInitializer;
 import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.os.Temperature;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.os.connectivity.WifiActivityEnergyInfo;
-import android.os.storage.DiskInfo;
-import android.os.storage.StorageManager;
-import android.os.storage.VolumeInfo;
-import android.provider.Settings;
-import android.stats.storage.StorageEnums;
-import android.telephony.ModemActivityInfo;
-import android.telephony.TelephonyManager;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.Log;
 import android.util.Slog;
-import android.util.StatsLog;
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.app.procstats.IProcessStats;
-import com.android.internal.app.procstats.ProcessStats;
-import com.android.internal.os.BatterySipper;
-import com.android.internal.os.BatteryStatsHelper;
-import com.android.internal.os.BinderCallsStats.ExportedCallStat;
-import com.android.internal.os.KernelCpuSpeedReader;
-import com.android.internal.os.KernelCpuThreadReader;
-import com.android.internal.os.KernelCpuThreadReaderDiff;
-import com.android.internal.os.KernelCpuThreadReaderSettingsObserver;
-import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader;
-import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader;
-import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
-import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
-import com.android.internal.os.KernelWakelockReader;
-import com.android.internal.os.KernelWakelockStats;
 import com.android.internal.os.LooperStats;
-import com.android.internal.os.PowerProfile;
-import com.android.internal.os.ProcessCpuTracker;
-import com.android.internal.os.StoragedUidIoStatsReader;
 import com.android.internal.util.DumpUtils;
 import com.android.server.BinderCallsStatsService;
 import com.android.server.LocalServices;
-import com.android.server.SystemServiceManager;
-import com.android.server.am.MemoryStatUtil.MemoryStat;
-import com.android.server.notification.NotificationManagerService;
-import com.android.server.role.RoleManagerInternal;
-import com.android.server.stats.pull.IonMemoryUtil.IonAllocations;
-import com.android.server.stats.pull.ProcfsMemoryUtil.MemorySnapshot;
-import com.android.server.storage.DiskStatsFileLogger;
-import com.android.server.storage.DiskStatsLoggingService;
-
-import com.google.android.collect.Sets;
 
 import libcore.io.IoUtils;
 
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Objects;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
 
 /**
  * Helper service for statsd (the native stats management service in cmds/statsd/).
@@ -177,10 +68,7 @@
  * @hide
  */
 public class StatsCompanionService extends IStatsCompanionService.Stub {
-    /**
-     * How long to wait on an individual subsystem to return its stats.
-     */
-    private static final long EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS = 2000;
+
     private static final long MILLIS_IN_A_DAY = TimeUnit.DAYS.toMillis(1);
 
     public static final String RESULT_RECEIVER_CONTROLLER_KEY = "controller_activity";
@@ -200,45 +88,6 @@
     private static final int INSTALLER_FIELD_ID = 5;
 
     public static final int DEATH_THRESHOLD = 10;
-    /**
-     * Which native processes to snapshot memory for.
-     *
-     * <p>Processes are matched by their cmdline in procfs. Example: cat /proc/pid/cmdline returns
-     * /system/bin/statsd for the stats daemon.
-     */
-    private static final Set<String> MEMORY_INTERESTING_NATIVE_PROCESSES = Sets.newHashSet(
-            "/system/bin/statsd",  // Stats daemon.
-            "/system/bin/surfaceflinger",
-            "/system/bin/apexd",  // APEX daemon.
-            "/system/bin/audioserver",
-            "/system/bin/cameraserver",
-            "/system/bin/drmserver",
-            "/system/bin/healthd",
-            "/system/bin/incidentd",
-            "/system/bin/installd",
-            "/system/bin/lmkd",  // Low memory killer daemon.
-            "/system/bin/logd",
-            "media.codec",
-            "media.extractor",
-            "media.metrics",
-            "/system/bin/mediadrmserver",
-            "/system/bin/mediaserver",
-            "/system/bin/performanced",
-            "/system/bin/tombstoned",
-            "/system/bin/traced",  // Perfetto.
-            "/system/bin/traced_probes",  // Perfetto.
-            "webview_zygote",
-            "zygote",
-            "zygote64");
-    /**
-     * Lowest available uid for apps.
-     *
-     * <p>Used to quickly discard memory snapshots of the zygote forks from native process
-     * measurements.
-     */
-    private static final int MIN_APP_UID = 10_000;
-
-    private static final int CPU_TIME_PER_THREAD_FREQ_MAX_NUM_FREQUENCIES = 8;
 
     static final class CompanionHandler extends Handler {
         CompanionHandler(Looper looper) {
@@ -248,7 +97,6 @@
 
     private final Context mContext;
     private final AlarmManager mAlarmManager;
-    private final INetworkStatsService mNetworkStatsService;
     @GuardedBy("sStatsdLock")
     private static IStatsd sStatsd;
     private static final Object sStatsdLock = new Object();
@@ -262,52 +110,16 @@
 
     private StatsManagerService mStatsManagerService;
 
-    private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader();
-    private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
-    private WifiManager mWifiManager = null;
-    private TelephonyManager mTelephony = null;
     @GuardedBy("sStatsdLock")
     private final HashSet<Long> mDeathTimeMillis = new HashSet<>();
     @GuardedBy("sStatsdLock")
     private final HashMap<Long, String> mDeletedFiles = new HashMap<>();
     private final CompanionHandler mHandler;
 
-    // Disables throttler on CPU time readers.
-    private KernelCpuUidUserSysTimeReader mCpuUidUserSysTimeReader =
-            new KernelCpuUidUserSysTimeReader(false);
-    private KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
-    private KernelCpuUidFreqTimeReader mCpuUidFreqTimeReader =
-            new KernelCpuUidFreqTimeReader(false);
-    private KernelCpuUidActiveTimeReader mCpuUidActiveTimeReader =
-            new KernelCpuUidActiveTimeReader(false);
-    private KernelCpuUidClusterTimeReader mCpuUidClusterTimeReader =
-            new KernelCpuUidClusterTimeReader(false);
-    private StoragedUidIoStatsReader mStoragedUidIoStatsReader =
-            new StoragedUidIoStatsReader();
-    @Nullable
-    private final KernelCpuThreadReaderDiff mKernelCpuThreadReader;
-
-    private long mDebugElapsedClockPreviousValue = 0;
-    private long mDebugElapsedClockPullCount = 0;
-    private long mDebugFailingElapsedClockPreviousValue = 0;
-    private long mDebugFailingElapsedClockPullCount = 0;
-    private BatteryStatsHelper mBatteryStatsHelper = null;
-    private static final int MAX_BATTERY_STATS_HELPER_FREQUENCY_MS = 1000;
-    private long mBatteryStatsHelperTimestampMs = -MAX_BATTERY_STATS_HELPER_FREQUENCY_MS;
-
-    private static IThermalService sThermalService;
-    private File mBaseDir =
-            new File(SystemServiceManager.ensureSystemDir(), "stats_companion");
-    @GuardedBy("this")
-    ProcessCpuTracker mProcessCpuTracker = null;
-
     public StatsCompanionService(Context context) {
         super();
         mContext = context;
         mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
-        mNetworkStatsService = INetworkStatsService.Stub.asInterface(
-              ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
-        mBaseDir.mkdirs();
         mAppUpdateReceiver = new AppUpdateReceiver();
         mUserUpdateReceiver = new BroadcastReceiver() {
             @Override
@@ -330,47 +142,10 @@
         };
         mShutdownEventReceiver = new ShutdownEventReceiver();
         if (DEBUG) Slog.d(TAG, "Registered receiver for ACTION_PACKAGE_REPLACED and ADDED.");
-        PowerProfile powerProfile = new PowerProfile(context);
-        final int numClusters = powerProfile.getNumCpuClusters();
-        mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters];
-        int firstCpuOfCluster = 0;
-        for (int i = 0; i < numClusters; i++) {
-            final int numSpeedSteps = powerProfile.getNumSpeedStepsInCpuCluster(i);
-            mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster,
-                    numSpeedSteps);
-            firstCpuOfCluster += powerProfile.getNumCoresInCpuCluster(i);
-        }
-
-        // Enable push notifications of throttling from vendor thermal
-        // management subsystem via thermalservice.
-        IBinder b = ServiceManager.getService("thermalservice");
-
-        if (b != null) {
-            sThermalService = IThermalService.Stub.asInterface(b);
-            try {
-                sThermalService.registerThermalEventListener(
-                        new ThermalEventListener());
-                Slog.i(TAG, "register thermal listener successfully");
-            } catch (RemoteException e) {
-                // Should never happen.
-                Slog.e(TAG, "register thermal listener error");
-            }
-        } else {
-            Slog.e(TAG, "cannot find thermalservice, no throttling push notifications");
-        }
-
-        // Default NetworkRequest should cover all transport types.
-        final NetworkRequest request = new NetworkRequest.Builder().build();
-        final ConnectivityManager connectivityManager =
-                (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
-        connectivityManager.registerNetworkCallback(request, new ConnectivityStatsCallback());
-
         HandlerThread handlerThread = new HandlerThread(TAG);
         handlerThread.start();
         mHandler = new CompanionHandler(handlerThread.getLooper());
 
-        mKernelCpuThreadReader =
-                KernelCpuThreadReaderSettingsObserver.getSettingsModifiedReader(mContext);
     }
 
     private final static int[] toIntArray(List<Integer> list) {
@@ -750,7 +525,10 @@
      * sStatsd with a null check.
      */
     private static IStatsd fetchStatsdService() {
-        return IStatsd.Stub.asInterface(ServiceManager.getService("stats"));
+        return IStatsd.Stub.asInterface(StatsFrameworkInitializer
+            .getStatsServiceManager()
+            .getStatsdServiceRegisterer()
+            .get());
     }
 
     /**
@@ -851,8 +629,8 @@
                 mDeathTimeMillis.add(now);
                 if (mDeathTimeMillis.size() >= DEATH_THRESHOLD) {
                     mDeathTimeMillis.clear();
-                    File[] configs = FileUtils.listFilesOrEmpty(new File(CONFIG_DIR));
-                    if (configs.length > 0) {
+                    File[] configs = new File(CONFIG_DIR).listFiles();
+                    if (configs != null && configs.length > 0) {
                         String fileName = configs[0].getName();
                         if (configs[0].delete()) {
                             mDeletedFiles.put(now, fileName);
@@ -905,28 +683,4 @@
             }
         }
     }
-
-    // Thermal event received from vendor thermal management subsystem
-    private static final class ThermalEventListener extends IThermalEventListener.Stub {
-        @Override
-        public void notifyThrottling(Temperature temp) {
-            StatsLog.write(StatsLog.THERMAL_THROTTLING_SEVERITY_STATE_CHANGED, temp.getType(),
-                    temp.getName(), (int) (temp.getValue() * 10), temp.getStatus());
-        }
-    }
-
-    private static final class ConnectivityStatsCallback extends
-            ConnectivityManager.NetworkCallback {
-        @Override
-        public void onAvailable(Network network) {
-            StatsLog.write(StatsLog.CONNECTIVITY_STATE_CHANGED, network.netId,
-                    StatsLog.CONNECTIVITY_STATE_CHANGED__STATE__CONNECTED);
-        }
-
-        @Override
-        public void onLost(Network network) {
-            StatsLog.write(StatsLog.CONNECTIVITY_STATE_CHANGED, network.netId,
-                    StatsLog.CONNECTIVITY_STATE_CHANGED__STATE__DISCONNECTED);
-        }
-    }
 }
diff --git a/apex/statsd/tests/libstatspull/Android.bp b/apex/statsd/tests/libstatspull/Android.bp
new file mode 100644
index 0000000..e813964
--- /dev/null
+++ b/apex/statsd/tests/libstatspull/Android.bp
@@ -0,0 +1,56 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+    name: "LibStatsPullTests",
+    static_libs: [
+        "androidx.test.rules",
+        "platformprotoslite",
+        "statsdprotolite",
+        "truth-prebuilt",
+    ],
+    libs: [
+        "android.test.runner.stubs",
+        "android.test.base.stubs",
+    ],
+    jni_libs: [
+        "libstatspull_testhelper",
+    ],
+    srcs: [
+        "src/**/*.java",
+        "protos/**/*.proto",
+        ],
+    test_suites: [
+        "general-tests",
+    ],
+    platform_apis: true,
+    privileged: true,
+    certificate: "platform",
+    compile_multilib: "both",
+}
+
+cc_library_shared {
+    name: "libstatspull_testhelper",
+    srcs: ["jni/stats_pull_helper.cpp"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    shared_libs: [
+        "libbinder",
+        "libutils",
+        "libstatspull",
+        "libstatssocket",
+    ],
+}
\ No newline at end of file
diff --git a/apex/statsd/tests/libstatspull/AndroidManifest.xml b/apex/statsd/tests/libstatspull/AndroidManifest.xml
new file mode 100644
index 0000000..bffd400
--- /dev/null
+++ b/apex/statsd/tests/libstatspull/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.internal.os.statsd.libstats" >
+
+
+    <uses-permission android:name="android.permission.DUMP" />
+    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.internal.os.statsd.libstats"
+                     android:label="Tests for libstatspull">
+    </instrumentation>
+</manifest>
+
diff --git a/apex/statsd/tests/libstatspull/TEST_MAPPING b/apex/statsd/tests/libstatspull/TEST_MAPPING
new file mode 100644
index 0000000..5e1178c
--- /dev/null
+++ b/apex/statsd/tests/libstatspull/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit" : [
+    {
+      "name" : "LibStatsPullTests"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/apex/statsd/tests/libstatspull/jni/stats_pull_helper.cpp b/apex/statsd/tests/libstatspull/jni/stats_pull_helper.cpp
new file mode 100644
index 0000000..e4ab823
--- /dev/null
+++ b/apex/statsd/tests/libstatspull/jni/stats_pull_helper.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <binder/ProcessState.h>
+#include <jni.h>
+#include <log/log.h>
+#include <stats_event.h>
+#include <stats_pull_atom_callback.h>
+
+#include <chrono>
+#include <thread>
+
+using std::this_thread::sleep_for;
+using namespace android;
+
+namespace {
+static int32_t sAtomTag;
+static int32_t sPullReturnVal;
+static int64_t sLatencyMillis;
+static int32_t sAtomsPerPull;
+static int32_t sNumPulls = 0;
+
+static bool initialized = false;
+
+static void init() {
+    if (!initialized) {
+        initialized = true;
+        // Set up the binder
+        sp<ProcessState> ps(ProcessState::self());
+        ps->setThreadPoolMaxThreadCount(9);
+        ps->startThreadPool();
+        ps->giveThreadPoolName();
+    }
+}
+
+static status_pull_atom_return_t pullAtomCallback(int32_t atomTag, pulled_stats_event_list* data,
+                                                  void* /*cookie*/) {
+    sNumPulls++;
+    sleep_for(std::chrono::milliseconds(sLatencyMillis));
+    for (int i = 0; i < sAtomsPerPull; i++) {
+        stats_event* event = add_stats_event_to_pull_data(data);
+        stats_event_set_atom_id(event, atomTag);
+        stats_event_write_int64(event, (int64_t) sNumPulls);
+        stats_event_build(event);
+    }
+    return sPullReturnVal;
+}
+
+extern "C"
+JNIEXPORT void JNICALL
+Java_com_android_internal_os_statsd_libstats_LibStatsPullTests_registerStatsPuller(
+        JNIEnv* /*env*/, jobject /* this */, jint atomTag, jlong timeoutNs, jlong coolDownNs,
+        jint pullRetVal, jlong latencyMillis, int atomsPerPull)
+{
+    init();
+    sAtomTag = atomTag;
+    sPullReturnVal = pullRetVal;
+    sLatencyMillis = latencyMillis;
+    sAtomsPerPull = atomsPerPull;
+    sNumPulls = 0;
+    pull_atom_metadata metadata = {.cool_down_ns = coolDownNs,
+                                   .timeout_ns = timeoutNs,
+                                   .additive_fields = nullptr,
+                                   .additive_fields_size = 0};
+    register_stats_pull_atom_callback(sAtomTag, &pullAtomCallback, &metadata, nullptr);
+}
+
+extern "C"
+JNIEXPORT void JNICALL
+Java_com_android_internal_os_statsd_libstats_LibStatsPullTests_unregisterStatsPuller(
+        JNIEnv* /*env*/, jobject /* this */, jint /*atomTag*/)
+{
+    unregister_stats_pull_atom_callback(sAtomTag);
+}
+} // namespace
\ No newline at end of file
diff --git a/apex/statsd/tests/libstatspull/protos/test_atoms.proto b/apex/statsd/tests/libstatspull/protos/test_atoms.proto
new file mode 100644
index 0000000..56c1b53
--- /dev/null
+++ b/apex/statsd/tests/libstatspull/protos/test_atoms.proto
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+syntax = "proto2";
+
+package com.android.internal.os.statsd.protos;
+
+option java_package = "com.android.internal.os.statsd.protos";
+option java_outer_classname = "TestAtoms";
+
+message PullCallbackAtomWrapper {
+  optional PullCallbackAtom pull_callback_atom = 150030;
+}
+
+message PullCallbackAtom {
+  optional int64 long_val = 1;
+}
+
+
+
diff --git a/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/StatsConfigUtils.java b/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/StatsConfigUtils.java
new file mode 100644
index 0000000..d0d1400
--- /dev/null
+++ b/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/StatsConfigUtils.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.os.statsd;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.StatsManager;
+import android.util.Log;
+
+import com.android.internal.os.StatsdConfigProto.AtomMatcher;
+import com.android.internal.os.StatsdConfigProto.FieldValueMatcher;
+import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
+import com.android.internal.os.StatsdConfigProto.StatsdConfig;
+import com.android.os.AtomsProto.AppBreadcrumbReported;
+import com.android.os.AtomsProto.Atom;
+import com.android.os.StatsLog.ConfigMetricsReport;
+import com.android.os.StatsLog.ConfigMetricsReportList;
+import com.android.os.StatsLog.GaugeBucketInfo;
+import com.android.os.StatsLog.GaugeMetricData;
+import com.android.os.StatsLog.StatsLogReport;
+import com.android.os.StatsLog.StatsdStatsReport;
+import com.android.os.StatsLog.StatsdStatsReport.ConfigStats;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Util class for constructing statsd configs.
+ */
+public class StatsConfigUtils {
+    public static final String TAG = "statsd.StatsConfigUtils";
+    public static final int SHORT_WAIT = 2_000; // 2 seconds.
+
+    /**
+     * @return An empty StatsdConfig in serialized proto format.
+     */
+    public static StatsdConfig.Builder getSimpleTestConfig(long configId) {
+        return StatsdConfig.newBuilder().setId(configId)
+                .addAllowedLogSource(StatsConfigUtils.class.getPackage().getName());
+    }
+
+
+    public static boolean verifyValidConfigExists(StatsManager statsManager, long configId) {
+        StatsdStatsReport report = null;
+        try {
+            report = StatsdStatsReport.parser().parseFrom(statsManager.getStatsMetadata());
+        } catch (Exception e) {
+            Log.e(TAG, "getMetadata failed", e);
+        }
+        assertThat(report).isNotNull();
+        boolean foundConfig = false;
+        for (ConfigStats configStats : report.getConfigStatsList()) {
+            if (configStats.getId() == configId && configStats.getIsValid()
+                    && configStats.getDeletionTimeSec() == 0) {
+                foundConfig = true;
+            }
+        }
+        return foundConfig;
+    }
+
+    public static AtomMatcher getAppBreadcrumbMatcher(long id, int label) {
+        return AtomMatcher.newBuilder()
+                .setId(id)
+                .setSimpleAtomMatcher(
+                        SimpleAtomMatcher.newBuilder()
+                                .setAtomId(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
+                                .addFieldValueMatcher(FieldValueMatcher.newBuilder()
+                                        .setField(AppBreadcrumbReported.LABEL_FIELD_NUMBER)
+                                        .setEqInt(label)
+                                )
+                )
+                .build();
+    }
+
+    public static ConfigMetricsReport getConfigMetricsReport(StatsManager statsManager,
+            long configId) {
+        ConfigMetricsReportList reportList = null;
+        try {
+            reportList = ConfigMetricsReportList.parser()
+                    .parseFrom(statsManager.getReports(configId));
+        } catch (Exception e) {
+            Log.e(TAG, "getData failed", e);
+        }
+        assertThat(reportList).isNotNull();
+        assertThat(reportList.getReportsCount()).isEqualTo(1);
+        ConfigMetricsReport report = reportList.getReports(0);
+        assertThat(report.getDumpReportReason())
+                .isEqualTo(ConfigMetricsReport.DumpReportReason.GET_DATA_CALLED);
+        return report;
+
+    }
+    public static List<Atom> getGaugeMetricDataList(ConfigMetricsReport report) {
+        List<Atom> data = new ArrayList<>();
+        for (StatsLogReport metric : report.getMetricsList()) {
+            for (GaugeMetricData gaugeMetricData : metric.getGaugeMetrics().getDataList()) {
+                for (GaugeBucketInfo bucketInfo : gaugeMetricData.getBucketInfoList()) {
+                    for (Atom atom : bucketInfo.getAtomList()) {
+                        data.add(atom);
+                    }
+                }
+            }
+        }
+        return data;
+    }
+
+    public static List<Atom> getGaugeMetricDataList(StatsManager statsManager, long configId) {
+        ConfigMetricsReport report = getConfigMetricsReport(statsManager, configId);
+        return getGaugeMetricDataList(report);
+    }
+}
+
diff --git a/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java b/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java
new file mode 100644
index 0000000..dbd636d
--- /dev/null
+++ b/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.os.statsd.libstats;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.StatsManager;
+import android.content.Context;
+import android.util.Log;
+import android.util.StatsLog;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.os.StatsdConfigProto.AtomMatcher;
+import com.android.internal.os.StatsdConfigProto.FieldFilter;
+import com.android.internal.os.StatsdConfigProto.GaugeMetric;
+import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
+import com.android.internal.os.StatsdConfigProto.StatsdConfig;
+import com.android.internal.os.StatsdConfigProto.TimeUnit;
+import com.android.internal.os.statsd.StatsConfigUtils;
+import com.android.internal.os.statsd.protos.TestAtoms;
+import com.android.os.AtomsProto.Atom;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+/**
+ * Test puller registration.
+ */
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class LibStatsPullTests {
+    private static final String LOG_TAG = LibStatsPullTests.class.getSimpleName();
+    private static final int SHORT_SLEEP_MILLIS = 250;
+    private static final int LONG_SLEEP_MILLIS = 1_000;
+    private Context mContext;
+    private static final int PULL_ATOM_TAG = 150030;
+    private static final int APP_BREADCRUMB_LABEL = 3;
+    private static int sPullReturnValue;
+    private static long sConfigId;
+    private static long sPullLatencyMillis;
+    private static long sPullTimeoutNs;
+    private static long sCoolDownNs;
+    private static int sAtomsPerPull;
+
+    static {
+        System.loadLibrary("statspull_testhelper");
+    }
+
+    /**
+     * Setup the tests. Initialize shared data.
+     */
+    @Before
+    public void setup() {
+//        Debug.waitForDebugger();
+        mContext = InstrumentationRegistry.getTargetContext();
+        assertThat(InstrumentationRegistry.getInstrumentation()).isNotNull();
+        sPullReturnValue = StatsManager.PULL_SUCCESS;
+        sPullLatencyMillis = 0;
+        sPullTimeoutNs = 10_000_000_000L;
+        sCoolDownNs = 1_000_000_000L;
+        sAtomsPerPull = 1;
+    }
+
+    /**
+     * Teardown the tests.
+     */
+    @After
+    public void tearDown() throws Exception {
+        unregisterStatsPuller(PULL_ATOM_TAG);
+        StatsManager statsManager = (StatsManager) mContext.getSystemService(
+                Context.STATS_MANAGER);
+        statsManager.removeConfig(sConfigId);
+    }
+
+    /**
+     * Tests adding a puller callback and that pulls complete successfully.
+     */
+    @Test
+    public void testPullAtomCallbackRegistration() throws Exception {
+        StatsManager statsManager = (StatsManager) mContext.getSystemService(
+                Context.STATS_MANAGER);
+        // Upload a config that captures that pulled atom.
+        createAndAddConfigToStatsd(statsManager);
+
+        // Add the puller.
+        registerStatsPuller(PULL_ATOM_TAG, sPullTimeoutNs, sCoolDownNs, sPullReturnValue,
+                sPullLatencyMillis, sAtomsPerPull);
+        Thread.sleep(SHORT_SLEEP_MILLIS);
+        StatsLog.logStart(APP_BREADCRUMB_LABEL);
+        // Let the current bucket finish.
+        Thread.sleep(LONG_SLEEP_MILLIS);
+        List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId);
+        unregisterStatsPuller(PULL_ATOM_TAG);
+        assertThat(data.size()).isEqualTo(1);
+        TestAtoms.PullCallbackAtomWrapper atomWrapper = null;
+        try {
+            atomWrapper = TestAtoms.PullCallbackAtomWrapper.parser()
+                    .parseFrom(data.get(0).toByteArray());
+        } catch (Exception e) {
+            Log.e(LOG_TAG, "Failed to parse primitive atoms");
+        }
+        assertThat(atomWrapper).isNotNull();
+        assertThat(atomWrapper.hasPullCallbackAtom()).isTrue();
+        TestAtoms.PullCallbackAtom atom =
+                atomWrapper.getPullCallbackAtom();
+        assertThat(atom.getLongVal()).isEqualTo(1);
+    }
+
+    /**
+     * Tests that a failed pull is skipped.
+     */
+    @Test
+    public void testPullAtomCallbackFailure() throws Exception {
+        StatsManager statsManager = (StatsManager) mContext.getSystemService(
+                Context.STATS_MANAGER);
+        createAndAddConfigToStatsd(statsManager);
+        sPullReturnValue = StatsManager.PULL_SKIP;
+        // Add the puller.
+        registerStatsPuller(PULL_ATOM_TAG, sPullTimeoutNs, sCoolDownNs, sPullReturnValue,
+                sPullLatencyMillis, sAtomsPerPull);
+        Thread.sleep(SHORT_SLEEP_MILLIS);
+        StatsLog.logStart(APP_BREADCRUMB_LABEL);
+        // Let the current bucket finish.
+        Thread.sleep(LONG_SLEEP_MILLIS);
+        List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId);
+        unregisterStatsPuller(PULL_ATOM_TAG);
+        assertThat(data.size()).isEqualTo(0);
+    }
+
+    /**
+     * Tests that a pull that times out is skipped.
+     */
+    @Test
+    public void testPullAtomCallbackTimeout() throws Exception {
+        StatsManager statsManager = (StatsManager) mContext.getSystemService(
+                Context.STATS_MANAGER);
+        createAndAddConfigToStatsd(statsManager);
+        // The puller will sleep for 1.5 sec.
+        sPullLatencyMillis = 1_500;
+        // 1 second timeout
+        sPullTimeoutNs = 1_000_000_000;
+
+        // Add the puller.
+        registerStatsPuller(PULL_ATOM_TAG, sPullTimeoutNs, sCoolDownNs, sPullReturnValue,
+                sPullLatencyMillis, sAtomsPerPull);
+        Thread.sleep(SHORT_SLEEP_MILLIS);
+        StatsLog.logStart(APP_BREADCRUMB_LABEL);
+        // Let the current bucket finish and the pull timeout.
+        Thread.sleep(sPullLatencyMillis * 2);
+        List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId);
+        unregisterStatsPuller(PULL_ATOM_TAG);
+        assertThat(data.size()).isEqualTo(0);
+    }
+
+    /**
+     * Tests that 2 pulls in quick succession use the cache instead of pulling again.
+     */
+    @Test
+    public void testPullAtomCallbackCache() throws Exception {
+        StatsManager statsManager = (StatsManager) mContext.getSystemService(
+                Context.STATS_MANAGER);
+        createAndAddConfigToStatsd(statsManager);
+
+        // Set the cooldown to 10 seconds
+        sCoolDownNs = 10_000_000_000L;
+        // Add the puller.
+        registerStatsPuller(PULL_ATOM_TAG, sPullTimeoutNs, sCoolDownNs, sPullReturnValue,
+                sPullLatencyMillis, sAtomsPerPull);
+
+        Thread.sleep(SHORT_SLEEP_MILLIS);
+        StatsLog.logStart(APP_BREADCRUMB_LABEL);
+        // Pull from cache.
+        StatsLog.logStart(APP_BREADCRUMB_LABEL);
+        Thread.sleep(LONG_SLEEP_MILLIS);
+        List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId);
+        unregisterStatsPuller(PULL_ATOM_TAG);
+        assertThat(data.size()).isEqualTo(2);
+        for (int i = 0; i < data.size(); i++) {
+            TestAtoms.PullCallbackAtomWrapper atomWrapper = null;
+            try {
+                atomWrapper = TestAtoms.PullCallbackAtomWrapper.parser()
+                        .parseFrom(data.get(i).toByteArray());
+            } catch (Exception e) {
+                Log.e(LOG_TAG, "Failed to parse primitive atoms");
+            }
+            assertThat(atomWrapper).isNotNull();
+            assertThat(atomWrapper.hasPullCallbackAtom()).isTrue();
+            TestAtoms.PullCallbackAtom atom =
+                    atomWrapper.getPullCallbackAtom();
+            assertThat(atom.getLongVal()).isEqualTo(1);
+        }
+    }
+
+    /**
+     * Tests that a pull that returns 1000 stats events works properly.
+     */
+    @Test
+    public void testPullAtomCallbackStress() throws Exception {
+        StatsManager statsManager = (StatsManager) mContext.getSystemService(
+                Context.STATS_MANAGER);
+        // Upload a config that captures that pulled atom.
+        createAndAddConfigToStatsd(statsManager);
+        sAtomsPerPull = 1000;
+        // Add the puller.
+        registerStatsPuller(PULL_ATOM_TAG, sPullTimeoutNs, sCoolDownNs, sPullReturnValue,
+                sPullLatencyMillis, sAtomsPerPull);
+
+        Thread.sleep(SHORT_SLEEP_MILLIS);
+        StatsLog.logStart(APP_BREADCRUMB_LABEL);
+        // Let the current bucket finish.
+        Thread.sleep(LONG_SLEEP_MILLIS);
+        List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId);
+        statsManager.unregisterPullAtomCallback(PULL_ATOM_TAG);
+        assertThat(data.size()).isEqualTo(sAtomsPerPull);
+
+        for (int i = 0; i < data.size(); i++) {
+            TestAtoms.PullCallbackAtomWrapper atomWrapper = null;
+            try {
+                atomWrapper = TestAtoms.PullCallbackAtomWrapper.parser()
+                        .parseFrom(data.get(i).toByteArray());
+            } catch (Exception e) {
+                Log.e(LOG_TAG, "Failed to parse primitive atoms");
+            }
+            assertThat(atomWrapper).isNotNull();
+            assertThat(atomWrapper.hasPullCallbackAtom()).isTrue();
+            TestAtoms.PullCallbackAtom atom =
+                    atomWrapper.getPullCallbackAtom();
+            assertThat(atom.getLongVal()).isEqualTo(1);
+        }
+    }
+
+    private void createAndAddConfigToStatsd(StatsManager statsManager) throws Exception {
+        sConfigId = System.currentTimeMillis();
+        long triggerMatcherId = sConfigId + 10;
+        long pullerMatcherId = sConfigId + 11;
+        long metricId = sConfigId + 100;
+        StatsdConfig config = StatsConfigUtils.getSimpleTestConfig(sConfigId)
+                .addAtomMatcher(
+                        StatsConfigUtils.getAppBreadcrumbMatcher(triggerMatcherId,
+                                APP_BREADCRUMB_LABEL))
+                .addAtomMatcher(AtomMatcher.newBuilder()
+                        .setId(pullerMatcherId)
+                        .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
+                                .setAtomId(PULL_ATOM_TAG))
+                )
+                .addGaugeMetric(GaugeMetric.newBuilder()
+                        .setId(metricId)
+                        .setWhat(pullerMatcherId)
+                        .setTriggerEvent(triggerMatcherId)
+                        .setGaugeFieldsFilter(FieldFilter.newBuilder().setIncludeAll(true))
+                        .setBucket(TimeUnit.CTS)
+                        .setSamplingType(GaugeMetric.SamplingType.FIRST_N_SAMPLES)
+                        .setMaxNumGaugeAtomsPerBucket(1000)
+                )
+                .build();
+        statsManager.addConfig(sConfigId, config.toByteArray());
+        assertThat(StatsConfigUtils.verifyValidConfigExists(statsManager, sConfigId)).isTrue();
+    }
+
+    private native void registerStatsPuller(int atomTag, long timeoutNs, long coolDownNs,
+            int pullReturnVal, long latencyMillis, int atomPerPull);
+
+    private native void unregisterStatsPuller(int atomTag);
+}
+
diff --git a/api/current.txt b/api/current.txt
index 2303f8d..77dec70 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -333,6 +333,9 @@
     field public static final int autoUrlDetect = 16843404; // 0x101028c
     field public static final int autoVerify = 16844014; // 0x10104ee
     field public static final int autofillHints = 16844118; // 0x1010556
+    field public static final int autofillInlineSuggestionChip = 16844307; // 0x1010613
+    field public static final int autofillInlineSuggestionSubtitle = 16844309; // 0x1010615
+    field public static final int autofillInlineSuggestionTitle = 16844308; // 0x1010614
     field public static final int autofilledHighlight = 16844136; // 0x1010568
     field public static final int background = 16842964; // 0x10100d4
     field public static final int backgroundDimAmount = 16842802; // 0x1010032
@@ -2253,6 +2256,7 @@
     field public static final int ThemeOverlay_Material_Dialog = 16974550; // 0x10302d6
     field public static final int ThemeOverlay_Material_Dialog_Alert = 16974551; // 0x10302d7
     field public static final int ThemeOverlay_Material_Light = 16974410; // 0x103024a
+    field public static final int Theme_AutofillInlineSuggestion = 16974565; // 0x10302e5
     field public static final int Theme_Black = 16973832; // 0x1030008
     field public static final int Theme_Black_NoTitleBar = 16973833; // 0x1030009
     field public static final int Theme_Black_NoTitleBar_Fullscreen = 16973834; // 0x103000a
@@ -2869,6 +2873,8 @@
     method public final boolean performGlobalAction(int);
     method public final void setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo);
     method public boolean takeScreenshot(int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.graphics.Bitmap>);
+    field public static final int GESTURE_DOUBLE_TAP = 17; // 0x11
+    field public static final int GESTURE_DOUBLE_TAP_AND_HOLD = 18; // 0x12
     field public static final int GESTURE_SWIPE_DOWN = 2; // 0x2
     field public static final int GESTURE_SWIPE_DOWN_AND_LEFT = 15; // 0xf
     field public static final int GESTURE_SWIPE_DOWN_AND_RIGHT = 16; // 0x10
@@ -2982,9 +2988,11 @@
     field @Deprecated public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 8; // 0x8
     field public static final int FLAG_REQUEST_FILTER_KEY_EVENTS = 32; // 0x20
     field public static final int FLAG_REQUEST_FINGERPRINT_GESTURES = 512; // 0x200
+    field public static final int FLAG_REQUEST_MULTI_FINGER_GESTURES = 4096; // 0x1000
     field public static final int FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK = 1024; // 0x400
     field public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 4; // 0x4
     field public static final int FLAG_RETRIEVE_INTERACTIVE_WINDOWS = 64; // 0x40
+    field public static final int FLAG_SERVICE_HANDLES_DOUBLE_TAP = 2048; // 0x800
     field public int eventTypes;
     field public int feedbackType;
     field public int flags;
@@ -3897,6 +3905,7 @@
     method public void setImmersive(boolean);
     method public void setInheritShowWhenLocked(boolean);
     method public void setIntent(android.content.Intent);
+    method public void setLocusContext(@Nullable android.content.LocusId, @Nullable android.os.Bundle);
     method public final void setMediaController(android.media.session.MediaController);
     method public void setPictureInPictureParams(@NonNull android.app.PictureInPictureParams);
     method @Deprecated public final void setProgress(int);
@@ -6827,6 +6836,7 @@
     method public int getLockTaskFeatures(@NonNull android.content.ComponentName);
     method @NonNull public String[] getLockTaskPackages(@NonNull android.content.ComponentName);
     method @Nullable public CharSequence getLongSupportMessage(@NonNull android.content.ComponentName);
+    method public long getManagedProfileMaximumTimeOff(@NonNull android.content.ComponentName);
     method public int getMaximumFailedPasswordsForWipe(@Nullable android.content.ComponentName);
     method public long getMaximumTimeToLock(@Nullable android.content.ComponentName);
     method @NonNull public java.util.List<java.lang.String> getMeteredDataDisabledPackages(@NonNull android.content.ComponentName);
@@ -6913,6 +6923,7 @@
     method public boolean removeOverrideApn(@NonNull android.content.ComponentName, int);
     method public boolean removeUser(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle);
     method public boolean requestBugreport(@NonNull android.content.ComponentName);
+    method public void requestSetLocationProviderAllowed(@NonNull android.content.ComponentName, @NonNull String, boolean);
     method @Deprecated public boolean resetPassword(String, int);
     method public boolean resetPasswordWithToken(@NonNull android.content.ComponentName, String, byte[], int);
     method @Nullable public java.util.List<android.app.admin.NetworkEvent> retrieveNetworkLogs(@Nullable android.content.ComponentName, long);
@@ -6956,6 +6967,7 @@
     method public void setLockdownAdminConfiguredNetworks(@NonNull android.content.ComponentName, boolean);
     method public void setLogoutEnabled(@NonNull android.content.ComponentName, boolean);
     method public void setLongSupportMessage(@NonNull android.content.ComponentName, @Nullable CharSequence);
+    method public void setManagedProfileMaximumTimeOff(@NonNull android.content.ComponentName, long);
     method public void setMasterVolumeMuted(@NonNull android.content.ComponentName, boolean);
     method public void setMaximumFailedPasswordsForWipe(@NonNull android.content.ComponentName, int);
     method public void setMaximumTimeToLock(@NonNull android.content.ComponentName, long);
@@ -7142,6 +7154,7 @@
     field public static final int PERMISSION_POLICY_PROMPT = 0; // 0x0
     field public static final int PERSONAL_APPS_NOT_SUSPENDED = 0; // 0x0
     field public static final int PERSONAL_APPS_SUSPENDED_EXPLICITLY = 1; // 0x1
+    field public static final int PERSONAL_APPS_SUSPENDED_PROFILE_TIMEOUT = 2; // 0x2
     field public static final String POLICY_DISABLE_CAMERA = "policy_disable_camera";
     field public static final String POLICY_DISABLE_SCREEN_CAPTURE = "policy_disable_screen_capture";
     field public static final int PRIVATE_DNS_MODE_OFF = 1; // 0x1
@@ -7543,6 +7556,7 @@
     method public boolean isPackageAccessAllowed(@NonNull String, @NonNull byte[]) throws java.io.IOException;
     method public boolean isPublicAccessAllowed() throws java.io.IOException;
     method public boolean isSameSignatureAccessAllowed() throws java.io.IOException;
+    method @NonNull public android.os.ParcelFileDescriptor openRead() throws java.io.IOException;
     method @NonNull public android.os.ParcelFileDescriptor openWrite(long, long) throws java.io.IOException;
   }
 
@@ -10159,6 +10173,7 @@
     field public static final String STORAGE_STATS_SERVICE = "storagestats";
     field public static final String SYSTEM_HEALTH_SERVICE = "systemhealth";
     field public static final String TELECOM_SERVICE = "telecom";
+    field public static final String TELEPHONY_IMS_SERVICE = "telephony_ims";
     field public static final String TELEPHONY_SERVICE = "phone";
     field public static final String TELEPHONY_SUBSCRIPTION_SERVICE = "telephony_subscription_service";
     field public static final String TEXT_CLASSIFICATION_SERVICE = "textclassification";
@@ -10169,6 +10184,7 @@
     field public static final String USB_SERVICE = "usb";
     field public static final String USER_SERVICE = "user";
     field public static final String VIBRATOR_SERVICE = "vibrator";
+    field public static final String VPN_MANAGEMENT_SERVICE = "vpn_management";
     field public static final String WALLPAPER_SERVICE = "wallpaper";
     field public static final String WIFI_AWARE_SERVICE = "wifiaware";
     field public static final String WIFI_P2P_SERVICE = "wifip2p";
@@ -12001,6 +12017,7 @@
     field public static final String FEATURE_CAMERA_CAPABILITY_MANUAL_POST_PROCESSING = "android.hardware.camera.capability.manual_post_processing";
     field public static final String FEATURE_CAMERA_CAPABILITY_MANUAL_SENSOR = "android.hardware.camera.capability.manual_sensor";
     field public static final String FEATURE_CAMERA_CAPABILITY_RAW = "android.hardware.camera.capability.raw";
+    field public static final String FEATURE_CAMERA_CONCURRENT = "android.hardware.camera.concurrent";
     field public static final String FEATURE_CAMERA_EXTERNAL = "android.hardware.camera.external";
     field public static final String FEATURE_CAMERA_FLASH = "android.hardware.camera.flash";
     field public static final String FEATURE_CAMERA_FRONT = "android.hardware.camera.front";
@@ -12058,6 +12075,7 @@
     field public static final String FEATURE_SENSOR_GYROSCOPE = "android.hardware.sensor.gyroscope";
     field public static final String FEATURE_SENSOR_HEART_RATE = "android.hardware.sensor.heartrate";
     field public static final String FEATURE_SENSOR_HEART_RATE_ECG = "android.hardware.sensor.heartrate.ecg";
+    field public static final String FEATURE_SENSOR_HINGE_ANGLE = "android.hardware.sensor.hinge_angle";
     field public static final String FEATURE_SENSOR_LIGHT = "android.hardware.sensor.light";
     field public static final String FEATURE_SENSOR_PROXIMITY = "android.hardware.sensor.proximity";
     field public static final String FEATURE_SENSOR_RELATIVE_HUMIDITY = "android.hardware.sensor.relative_humidity";
@@ -13535,227 +13553,227 @@
 
 package android.drm {
 
-  public class DrmConvertedStatus {
-    ctor public DrmConvertedStatus(int, byte[], int);
-    field public static final int STATUS_ERROR = 3; // 0x3
-    field public static final int STATUS_INPUTDATA_ERROR = 2; // 0x2
-    field public static final int STATUS_OK = 1; // 0x1
-    field public final byte[] convertedData;
-    field public final int offset;
-    field public final int statusCode;
+  @Deprecated public class DrmConvertedStatus {
+    ctor @Deprecated public DrmConvertedStatus(int, byte[], int);
+    field @Deprecated public static final int STATUS_ERROR = 3; // 0x3
+    field @Deprecated public static final int STATUS_INPUTDATA_ERROR = 2; // 0x2
+    field @Deprecated public static final int STATUS_OK = 1; // 0x1
+    field @Deprecated public final byte[] convertedData;
+    field @Deprecated public final int offset;
+    field @Deprecated public final int statusCode;
   }
 
-  public class DrmErrorEvent extends android.drm.DrmEvent {
-    ctor public DrmErrorEvent(int, int, String);
-    ctor public DrmErrorEvent(int, int, String, java.util.HashMap<java.lang.String,java.lang.Object>);
-    field public static final int TYPE_ACQUIRE_DRM_INFO_FAILED = 2008; // 0x7d8
-    field public static final int TYPE_NOT_SUPPORTED = 2003; // 0x7d3
-    field public static final int TYPE_NO_INTERNET_CONNECTION = 2005; // 0x7d5
-    field public static final int TYPE_OUT_OF_MEMORY = 2004; // 0x7d4
-    field public static final int TYPE_PROCESS_DRM_INFO_FAILED = 2006; // 0x7d6
-    field public static final int TYPE_REMOVE_ALL_RIGHTS_FAILED = 2007; // 0x7d7
-    field public static final int TYPE_RIGHTS_NOT_INSTALLED = 2001; // 0x7d1
-    field public static final int TYPE_RIGHTS_RENEWAL_NOT_ALLOWED = 2002; // 0x7d2
+  @Deprecated public class DrmErrorEvent extends android.drm.DrmEvent {
+    ctor @Deprecated public DrmErrorEvent(int, int, String);
+    ctor @Deprecated public DrmErrorEvent(int, int, String, java.util.HashMap<java.lang.String,java.lang.Object>);
+    field @Deprecated public static final int TYPE_ACQUIRE_DRM_INFO_FAILED = 2008; // 0x7d8
+    field @Deprecated public static final int TYPE_NOT_SUPPORTED = 2003; // 0x7d3
+    field @Deprecated public static final int TYPE_NO_INTERNET_CONNECTION = 2005; // 0x7d5
+    field @Deprecated public static final int TYPE_OUT_OF_MEMORY = 2004; // 0x7d4
+    field @Deprecated public static final int TYPE_PROCESS_DRM_INFO_FAILED = 2006; // 0x7d6
+    field @Deprecated public static final int TYPE_REMOVE_ALL_RIGHTS_FAILED = 2007; // 0x7d7
+    field @Deprecated public static final int TYPE_RIGHTS_NOT_INSTALLED = 2001; // 0x7d1
+    field @Deprecated public static final int TYPE_RIGHTS_RENEWAL_NOT_ALLOWED = 2002; // 0x7d2
   }
 
-  public class DrmEvent {
-    ctor protected DrmEvent(int, int, String, java.util.HashMap<java.lang.String,java.lang.Object>);
-    ctor protected DrmEvent(int, int, String);
-    method public Object getAttribute(String);
-    method public String getMessage();
-    method public int getType();
-    method public int getUniqueId();
-    field public static final String DRM_INFO_OBJECT = "drm_info_object";
-    field public static final String DRM_INFO_STATUS_OBJECT = "drm_info_status_object";
-    field public static final int TYPE_ALL_RIGHTS_REMOVED = 1001; // 0x3e9
-    field public static final int TYPE_DRM_INFO_PROCESSED = 1002; // 0x3ea
+  @Deprecated public class DrmEvent {
+    ctor @Deprecated protected DrmEvent(int, int, String, java.util.HashMap<java.lang.String,java.lang.Object>);
+    ctor @Deprecated protected DrmEvent(int, int, String);
+    method @Deprecated public Object getAttribute(String);
+    method @Deprecated public String getMessage();
+    method @Deprecated public int getType();
+    method @Deprecated public int getUniqueId();
+    field @Deprecated public static final String DRM_INFO_OBJECT = "drm_info_object";
+    field @Deprecated public static final String DRM_INFO_STATUS_OBJECT = "drm_info_status_object";
+    field @Deprecated public static final int TYPE_ALL_RIGHTS_REMOVED = 1001; // 0x3e9
+    field @Deprecated public static final int TYPE_DRM_INFO_PROCESSED = 1002; // 0x3ea
   }
 
-  public class DrmInfo {
-    ctor public DrmInfo(int, byte[], String);
-    ctor public DrmInfo(int, String, String);
-    method public Object get(String);
-    method public byte[] getData();
-    method public int getInfoType();
-    method public String getMimeType();
-    method public java.util.Iterator<java.lang.Object> iterator();
-    method public java.util.Iterator<java.lang.String> keyIterator();
-    method public void put(String, Object);
+  @Deprecated public class DrmInfo {
+    ctor @Deprecated public DrmInfo(int, byte[], String);
+    ctor @Deprecated public DrmInfo(int, String, String);
+    method @Deprecated public Object get(String);
+    method @Deprecated public byte[] getData();
+    method @Deprecated public int getInfoType();
+    method @Deprecated public String getMimeType();
+    method @Deprecated public java.util.Iterator<java.lang.Object> iterator();
+    method @Deprecated public java.util.Iterator<java.lang.String> keyIterator();
+    method @Deprecated public void put(String, Object);
   }
 
-  public class DrmInfoEvent extends android.drm.DrmEvent {
-    ctor public DrmInfoEvent(int, int, String);
-    ctor public DrmInfoEvent(int, int, String, java.util.HashMap<java.lang.String,java.lang.Object>);
-    field public static final int TYPE_ACCOUNT_ALREADY_REGISTERED = 5; // 0x5
-    field public static final int TYPE_ALREADY_REGISTERED_BY_ANOTHER_ACCOUNT = 1; // 0x1
-    field public static final int TYPE_REMOVE_RIGHTS = 2; // 0x2
-    field public static final int TYPE_RIGHTS_INSTALLED = 3; // 0x3
-    field public static final int TYPE_RIGHTS_REMOVED = 6; // 0x6
-    field public static final int TYPE_WAIT_FOR_RIGHTS = 4; // 0x4
+  @Deprecated public class DrmInfoEvent extends android.drm.DrmEvent {
+    ctor @Deprecated public DrmInfoEvent(int, int, String);
+    ctor @Deprecated public DrmInfoEvent(int, int, String, java.util.HashMap<java.lang.String,java.lang.Object>);
+    field @Deprecated public static final int TYPE_ACCOUNT_ALREADY_REGISTERED = 5; // 0x5
+    field @Deprecated public static final int TYPE_ALREADY_REGISTERED_BY_ANOTHER_ACCOUNT = 1; // 0x1
+    field @Deprecated public static final int TYPE_REMOVE_RIGHTS = 2; // 0x2
+    field @Deprecated public static final int TYPE_RIGHTS_INSTALLED = 3; // 0x3
+    field @Deprecated public static final int TYPE_RIGHTS_REMOVED = 6; // 0x6
+    field @Deprecated public static final int TYPE_WAIT_FOR_RIGHTS = 4; // 0x4
   }
 
-  public class DrmInfoRequest {
-    ctor public DrmInfoRequest(int, String);
-    method public Object get(String);
-    method public int getInfoType();
-    method public String getMimeType();
-    method public java.util.Iterator<java.lang.Object> iterator();
-    method public java.util.Iterator<java.lang.String> keyIterator();
-    method public void put(String, Object);
-    field public static final String ACCOUNT_ID = "account_id";
-    field public static final String SUBSCRIPTION_ID = "subscription_id";
-    field public static final int TYPE_REGISTRATION_INFO = 1; // 0x1
-    field public static final int TYPE_RIGHTS_ACQUISITION_INFO = 3; // 0x3
-    field public static final int TYPE_RIGHTS_ACQUISITION_PROGRESS_INFO = 4; // 0x4
-    field public static final int TYPE_UNREGISTRATION_INFO = 2; // 0x2
+  @Deprecated public class DrmInfoRequest {
+    ctor @Deprecated public DrmInfoRequest(int, String);
+    method @Deprecated public Object get(String);
+    method @Deprecated public int getInfoType();
+    method @Deprecated public String getMimeType();
+    method @Deprecated public java.util.Iterator<java.lang.Object> iterator();
+    method @Deprecated public java.util.Iterator<java.lang.String> keyIterator();
+    method @Deprecated public void put(String, Object);
+    field @Deprecated public static final String ACCOUNT_ID = "account_id";
+    field @Deprecated public static final String SUBSCRIPTION_ID = "subscription_id";
+    field @Deprecated public static final int TYPE_REGISTRATION_INFO = 1; // 0x1
+    field @Deprecated public static final int TYPE_RIGHTS_ACQUISITION_INFO = 3; // 0x3
+    field @Deprecated public static final int TYPE_RIGHTS_ACQUISITION_PROGRESS_INFO = 4; // 0x4
+    field @Deprecated public static final int TYPE_UNREGISTRATION_INFO = 2; // 0x2
   }
 
-  public class DrmInfoStatus {
-    ctor public DrmInfoStatus(int, int, android.drm.ProcessedData, String);
-    field public static final int STATUS_ERROR = 2; // 0x2
-    field public static final int STATUS_OK = 1; // 0x1
-    field public final android.drm.ProcessedData data;
-    field public final int infoType;
-    field public final String mimeType;
-    field public final int statusCode;
+  @Deprecated public class DrmInfoStatus {
+    ctor @Deprecated public DrmInfoStatus(int, int, android.drm.ProcessedData, String);
+    field @Deprecated public static final int STATUS_ERROR = 2; // 0x2
+    field @Deprecated public static final int STATUS_OK = 1; // 0x1
+    field @Deprecated public final android.drm.ProcessedData data;
+    field @Deprecated public final int infoType;
+    field @Deprecated public final String mimeType;
+    field @Deprecated public final int statusCode;
   }
 
-  public class DrmManagerClient implements java.lang.AutoCloseable {
-    ctor public DrmManagerClient(android.content.Context);
-    method public android.drm.DrmInfo acquireDrmInfo(android.drm.DrmInfoRequest);
-    method public int acquireRights(android.drm.DrmInfoRequest);
-    method public boolean canHandle(String, String);
-    method public boolean canHandle(android.net.Uri, String);
-    method public int checkRightsStatus(String);
-    method public int checkRightsStatus(android.net.Uri);
-    method public int checkRightsStatus(String, int);
-    method public int checkRightsStatus(android.net.Uri, int);
-    method public void close();
-    method public android.drm.DrmConvertedStatus closeConvertSession(int);
-    method public android.drm.DrmConvertedStatus convertData(int, byte[]);
-    method public String[] getAvailableDrmEngines();
-    method @NonNull public java.util.Collection<android.drm.DrmSupportInfo> getAvailableDrmSupportInfo();
-    method public android.content.ContentValues getConstraints(String, int);
-    method public android.content.ContentValues getConstraints(android.net.Uri, int);
-    method public int getDrmObjectType(String, String);
-    method public int getDrmObjectType(android.net.Uri, String);
-    method public android.content.ContentValues getMetadata(String);
-    method public android.content.ContentValues getMetadata(android.net.Uri);
-    method public String getOriginalMimeType(String);
-    method public String getOriginalMimeType(android.net.Uri);
-    method public int openConvertSession(String);
-    method public int processDrmInfo(android.drm.DrmInfo);
+  @Deprecated public class DrmManagerClient implements java.lang.AutoCloseable {
+    ctor @Deprecated public DrmManagerClient(android.content.Context);
+    method @Deprecated public android.drm.DrmInfo acquireDrmInfo(android.drm.DrmInfoRequest);
+    method @Deprecated public int acquireRights(android.drm.DrmInfoRequest);
+    method @Deprecated public boolean canHandle(String, String);
+    method @Deprecated public boolean canHandle(android.net.Uri, String);
+    method @Deprecated public int checkRightsStatus(String);
+    method @Deprecated public int checkRightsStatus(android.net.Uri);
+    method @Deprecated public int checkRightsStatus(String, int);
+    method @Deprecated public int checkRightsStatus(android.net.Uri, int);
+    method @Deprecated public void close();
+    method @Deprecated public android.drm.DrmConvertedStatus closeConvertSession(int);
+    method @Deprecated public android.drm.DrmConvertedStatus convertData(int, byte[]);
+    method @Deprecated public String[] getAvailableDrmEngines();
+    method @Deprecated @NonNull public java.util.Collection<android.drm.DrmSupportInfo> getAvailableDrmSupportInfo();
+    method @Deprecated public android.content.ContentValues getConstraints(String, int);
+    method @Deprecated public android.content.ContentValues getConstraints(android.net.Uri, int);
+    method @Deprecated public int getDrmObjectType(String, String);
+    method @Deprecated public int getDrmObjectType(android.net.Uri, String);
+    method @Deprecated public android.content.ContentValues getMetadata(String);
+    method @Deprecated public android.content.ContentValues getMetadata(android.net.Uri);
+    method @Deprecated public String getOriginalMimeType(String);
+    method @Deprecated public String getOriginalMimeType(android.net.Uri);
+    method @Deprecated public int openConvertSession(String);
+    method @Deprecated public int processDrmInfo(android.drm.DrmInfo);
     method @Deprecated public void release();
-    method public int removeAllRights();
-    method public int removeRights(String);
-    method public int removeRights(android.net.Uri);
-    method public int saveRights(android.drm.DrmRights, String, String) throws java.io.IOException;
-    method public void setOnErrorListener(android.drm.DrmManagerClient.OnErrorListener);
-    method public void setOnEventListener(android.drm.DrmManagerClient.OnEventListener);
-    method public void setOnInfoListener(android.drm.DrmManagerClient.OnInfoListener);
-    field public static final int ERROR_NONE = 0; // 0x0
-    field public static final int ERROR_UNKNOWN = -2000; // 0xfffff830
+    method @Deprecated public int removeAllRights();
+    method @Deprecated public int removeRights(String);
+    method @Deprecated public int removeRights(android.net.Uri);
+    method @Deprecated public int saveRights(android.drm.DrmRights, String, String) throws java.io.IOException;
+    method @Deprecated public void setOnErrorListener(android.drm.DrmManagerClient.OnErrorListener);
+    method @Deprecated public void setOnEventListener(android.drm.DrmManagerClient.OnEventListener);
+    method @Deprecated public void setOnInfoListener(android.drm.DrmManagerClient.OnInfoListener);
+    field @Deprecated public static final int ERROR_NONE = 0; // 0x0
+    field @Deprecated public static final int ERROR_UNKNOWN = -2000; // 0xfffff830
   }
 
-  public static interface DrmManagerClient.OnErrorListener {
-    method public void onError(android.drm.DrmManagerClient, android.drm.DrmErrorEvent);
+  @Deprecated public static interface DrmManagerClient.OnErrorListener {
+    method @Deprecated public void onError(android.drm.DrmManagerClient, android.drm.DrmErrorEvent);
   }
 
-  public static interface DrmManagerClient.OnEventListener {
-    method public void onEvent(android.drm.DrmManagerClient, android.drm.DrmEvent);
+  @Deprecated public static interface DrmManagerClient.OnEventListener {
+    method @Deprecated public void onEvent(android.drm.DrmManagerClient, android.drm.DrmEvent);
   }
 
-  public static interface DrmManagerClient.OnInfoListener {
-    method public void onInfo(android.drm.DrmManagerClient, android.drm.DrmInfoEvent);
+  @Deprecated public static interface DrmManagerClient.OnInfoListener {
+    method @Deprecated public void onInfo(android.drm.DrmManagerClient, android.drm.DrmInfoEvent);
   }
 
-  public class DrmRights {
-    ctor public DrmRights(String, String);
-    ctor public DrmRights(String, String, String);
-    ctor public DrmRights(String, String, String, String);
-    ctor public DrmRights(java.io.File, String);
-    ctor public DrmRights(android.drm.ProcessedData, String);
-    method public String getAccountId();
-    method public byte[] getData();
-    method public String getMimeType();
-    method public String getSubscriptionId();
+  @Deprecated public class DrmRights {
+    ctor @Deprecated public DrmRights(String, String);
+    ctor @Deprecated public DrmRights(String, String, String);
+    ctor @Deprecated public DrmRights(String, String, String, String);
+    ctor @Deprecated public DrmRights(java.io.File, String);
+    ctor @Deprecated public DrmRights(android.drm.ProcessedData, String);
+    method @Deprecated public String getAccountId();
+    method @Deprecated public byte[] getData();
+    method @Deprecated public String getMimeType();
+    method @Deprecated public String getSubscriptionId();
   }
 
-  public class DrmStore {
+  @Deprecated public class DrmStore {
     ctor @Deprecated public DrmStore();
   }
 
-  public static class DrmStore.Action {
+  @Deprecated public static class DrmStore.Action {
     ctor @Deprecated public DrmStore.Action();
-    field public static final int DEFAULT = 0; // 0x0
-    field public static final int DISPLAY = 7; // 0x7
-    field public static final int EXECUTE = 6; // 0x6
-    field public static final int OUTPUT = 4; // 0x4
-    field public static final int PLAY = 1; // 0x1
-    field public static final int PREVIEW = 5; // 0x5
-    field public static final int RINGTONE = 2; // 0x2
-    field public static final int TRANSFER = 3; // 0x3
+    field @Deprecated public static final int DEFAULT = 0; // 0x0
+    field @Deprecated public static final int DISPLAY = 7; // 0x7
+    field @Deprecated public static final int EXECUTE = 6; // 0x6
+    field @Deprecated public static final int OUTPUT = 4; // 0x4
+    field @Deprecated public static final int PLAY = 1; // 0x1
+    field @Deprecated public static final int PREVIEW = 5; // 0x5
+    field @Deprecated public static final int RINGTONE = 2; // 0x2
+    field @Deprecated public static final int TRANSFER = 3; // 0x3
   }
 
-  public static interface DrmStore.ConstraintsColumns {
-    field public static final String EXTENDED_METADATA = "extended_metadata";
-    field public static final String LICENSE_AVAILABLE_TIME = "license_available_time";
-    field public static final String LICENSE_EXPIRY_TIME = "license_expiry_time";
-    field public static final String LICENSE_START_TIME = "license_start_time";
-    field public static final String MAX_REPEAT_COUNT = "max_repeat_count";
-    field public static final String REMAINING_REPEAT_COUNT = "remaining_repeat_count";
+  @Deprecated public static interface DrmStore.ConstraintsColumns {
+    field @Deprecated public static final String EXTENDED_METADATA = "extended_metadata";
+    field @Deprecated public static final String LICENSE_AVAILABLE_TIME = "license_available_time";
+    field @Deprecated public static final String LICENSE_EXPIRY_TIME = "license_expiry_time";
+    field @Deprecated public static final String LICENSE_START_TIME = "license_start_time";
+    field @Deprecated public static final String MAX_REPEAT_COUNT = "max_repeat_count";
+    field @Deprecated public static final String REMAINING_REPEAT_COUNT = "remaining_repeat_count";
   }
 
-  public static class DrmStore.DrmObjectType {
+  @Deprecated public static class DrmStore.DrmObjectType {
     ctor @Deprecated public DrmStore.DrmObjectType();
-    field public static final int CONTENT = 1; // 0x1
-    field public static final int RIGHTS_OBJECT = 2; // 0x2
-    field public static final int TRIGGER_OBJECT = 3; // 0x3
-    field public static final int UNKNOWN = 0; // 0x0
+    field @Deprecated public static final int CONTENT = 1; // 0x1
+    field @Deprecated public static final int RIGHTS_OBJECT = 2; // 0x2
+    field @Deprecated public static final int TRIGGER_OBJECT = 3; // 0x3
+    field @Deprecated public static final int UNKNOWN = 0; // 0x0
   }
 
-  public static class DrmStore.Playback {
+  @Deprecated public static class DrmStore.Playback {
     ctor @Deprecated public DrmStore.Playback();
-    field public static final int PAUSE = 2; // 0x2
-    field public static final int RESUME = 3; // 0x3
-    field public static final int START = 0; // 0x0
-    field public static final int STOP = 1; // 0x1
+    field @Deprecated public static final int PAUSE = 2; // 0x2
+    field @Deprecated public static final int RESUME = 3; // 0x3
+    field @Deprecated public static final int START = 0; // 0x0
+    field @Deprecated public static final int STOP = 1; // 0x1
   }
 
-  public static class DrmStore.RightsStatus {
+  @Deprecated public static class DrmStore.RightsStatus {
     ctor @Deprecated public DrmStore.RightsStatus();
-    field public static final int RIGHTS_EXPIRED = 2; // 0x2
-    field public static final int RIGHTS_INVALID = 1; // 0x1
-    field public static final int RIGHTS_NOT_ACQUIRED = 3; // 0x3
-    field public static final int RIGHTS_VALID = 0; // 0x0
+    field @Deprecated public static final int RIGHTS_EXPIRED = 2; // 0x2
+    field @Deprecated public static final int RIGHTS_INVALID = 1; // 0x1
+    field @Deprecated public static final int RIGHTS_NOT_ACQUIRED = 3; // 0x3
+    field @Deprecated public static final int RIGHTS_VALID = 0; // 0x0
   }
 
-  public class DrmSupportInfo {
-    ctor public DrmSupportInfo();
-    method public void addFileSuffix(String);
-    method public void addMimeType(String);
+  @Deprecated public class DrmSupportInfo {
+    ctor @Deprecated public DrmSupportInfo();
+    method @Deprecated public void addFileSuffix(String);
+    method @Deprecated public void addMimeType(String);
     method @Deprecated public String getDescriprition();
-    method public String getDescription();
-    method public java.util.Iterator<java.lang.String> getFileSuffixIterator();
-    method public java.util.Iterator<java.lang.String> getMimeTypeIterator();
-    method public void setDescription(String);
+    method @Deprecated public String getDescription();
+    method @Deprecated public java.util.Iterator<java.lang.String> getFileSuffixIterator();
+    method @Deprecated public java.util.Iterator<java.lang.String> getMimeTypeIterator();
+    method @Deprecated public void setDescription(String);
   }
 
-  public class DrmUtils {
-    ctor public DrmUtils();
-    method public static android.drm.DrmUtils.ExtendedMetadataParser getExtendedMetadataParser(byte[]);
+  @Deprecated public class DrmUtils {
+    ctor @Deprecated public DrmUtils();
+    method @Deprecated public static android.drm.DrmUtils.ExtendedMetadataParser getExtendedMetadataParser(byte[]);
   }
 
-  public static class DrmUtils.ExtendedMetadataParser {
-    method public String get(String);
-    method public java.util.Iterator<java.lang.String> iterator();
-    method public java.util.Iterator<java.lang.String> keyIterator();
+  @Deprecated public static class DrmUtils.ExtendedMetadataParser {
+    method @Deprecated public String get(String);
+    method @Deprecated public java.util.Iterator<java.lang.String> iterator();
+    method @Deprecated public java.util.Iterator<java.lang.String> keyIterator();
   }
 
-  public class ProcessedData {
-    method public String getAccountId();
-    method public byte[] getData();
-    method public String getSubscriptionId();
+  @Deprecated public class ProcessedData {
+    method @Deprecated public String getAccountId();
+    method @Deprecated public byte[] getData();
+    method @Deprecated public String getSubscriptionId();
   }
 
 }
@@ -14241,9 +14259,12 @@
     method public int getWidth();
     method public boolean isHardwareAccelerated();
     method public boolean isOpaque();
-    method public boolean quickReject(@NonNull android.graphics.RectF, @NonNull android.graphics.Canvas.EdgeType);
-    method public boolean quickReject(@NonNull android.graphics.Path, @NonNull android.graphics.Canvas.EdgeType);
-    method public boolean quickReject(float, float, float, float, @NonNull android.graphics.Canvas.EdgeType);
+    method @Deprecated public boolean quickReject(@NonNull android.graphics.RectF, @NonNull android.graphics.Canvas.EdgeType);
+    method public boolean quickReject(@NonNull android.graphics.RectF);
+    method @Deprecated public boolean quickReject(@NonNull android.graphics.Path, @NonNull android.graphics.Canvas.EdgeType);
+    method public boolean quickReject(@NonNull android.graphics.Path);
+    method @Deprecated public boolean quickReject(float, float, float, float, @NonNull android.graphics.Canvas.EdgeType);
+    method public boolean quickReject(float, float, float, float);
     method public void restore();
     method public void restoreToCount(int);
     method public void rotate(float);
@@ -14268,9 +14289,9 @@
     field public static final int ALL_SAVE_FLAG = 31; // 0x1f
   }
 
-  public enum Canvas.EdgeType {
-    enum_constant public static final android.graphics.Canvas.EdgeType AA;
-    enum_constant public static final android.graphics.Canvas.EdgeType BW;
+  @Deprecated public enum Canvas.EdgeType {
+    enum_constant @Deprecated public static final android.graphics.Canvas.EdgeType AA;
+    enum_constant @Deprecated public static final android.graphics.Canvas.EdgeType BW;
   }
 
   public enum Canvas.VertexMode {
@@ -16738,6 +16759,7 @@
     field public static final String STRING_TYPE_GYROSCOPE_UNCALIBRATED = "android.sensor.gyroscope_uncalibrated";
     field public static final String STRING_TYPE_HEART_BEAT = "android.sensor.heart_beat";
     field public static final String STRING_TYPE_HEART_RATE = "android.sensor.heart_rate";
+    field public static final String STRING_TYPE_HINGE_ANGLE = "android.sensor.hinge_angle";
     field public static final String STRING_TYPE_LIGHT = "android.sensor.light";
     field public static final String STRING_TYPE_LINEAR_ACCELERATION = "android.sensor.linear_acceleration";
     field public static final String STRING_TYPE_LOW_LATENCY_OFFBODY_DETECT = "android.sensor.low_latency_offbody_detect";
@@ -16767,6 +16789,7 @@
     field public static final int TYPE_GYROSCOPE_UNCALIBRATED = 16; // 0x10
     field public static final int TYPE_HEART_BEAT = 31; // 0x1f
     field public static final int TYPE_HEART_RATE = 21; // 0x15
+    field public static final int TYPE_HINGE_ANGLE = 36; // 0x24
     field public static final int TYPE_LIGHT = 5; // 0x5
     field public static final int TYPE_LINEAR_ACCELERATION = 10; // 0xa
     field public static final int TYPE_LOW_LATENCY_OFFBODY_DETECT = 34; // 0x22
@@ -17163,7 +17186,9 @@
     field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_PARTIAL_RESULT_COUNT;
     field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Byte> REQUEST_PIPELINE_MAX_DEPTH;
     field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Float> SCALER_AVAILABLE_MAX_DIGITAL_ZOOM;
+    field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> SCALER_AVAILABLE_ROTATE_AND_CROP_MODES;
     field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> SCALER_CROPPING_TYPE;
+    field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<android.hardware.camera2.params.MandatoryStreamCombination[]> SCALER_MANDATORY_CONCURRENT_STREAM_COMBINATIONS;
     field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<android.hardware.camera2.params.MandatoryStreamCombination[]> SCALER_MANDATORY_STREAM_COMBINATIONS;
     field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<android.hardware.camera2.params.StreamConfigurationMap> SCALER_STREAM_CONFIGURATION_MAP;
     field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> SENSOR_AVAILABLE_TEST_PATTERN_MODES;
@@ -17253,6 +17278,8 @@
   public final class CameraManager {
     method @NonNull public android.hardware.camera2.CameraCharacteristics getCameraCharacteristics(@NonNull String) throws android.hardware.camera2.CameraAccessException;
     method @NonNull public String[] getCameraIdList() throws android.hardware.camera2.CameraAccessException;
+    method @NonNull public java.util.Set<java.util.Set<java.lang.String>> getConcurrentStreamingCameraIds() throws android.hardware.camera2.CameraAccessException;
+    method @RequiresPermission(android.Manifest.permission.CAMERA) public boolean isConcurrentSessionConfigurationSupported(@NonNull java.util.Map<java.lang.String,android.hardware.camera2.params.SessionConfiguration>) throws android.hardware.camera2.CameraAccessException;
     method @RequiresPermission(android.Manifest.permission.CAMERA) public void openCamera(@NonNull String, @NonNull android.hardware.camera2.CameraDevice.StateCallback, @Nullable android.os.Handler) throws android.hardware.camera2.CameraAccessException;
     method @RequiresPermission(android.Manifest.permission.CAMERA) public void openCamera(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.hardware.camera2.CameraDevice.StateCallback) throws android.hardware.camera2.CameraAccessException;
     method public void registerAvailabilityCallback(@NonNull android.hardware.camera2.CameraManager.AvailabilityCallback, @Nullable android.os.Handler);
@@ -17269,6 +17296,8 @@
     method public void onCameraAccessPrioritiesChanged();
     method public void onCameraAvailable(@NonNull String);
     method public void onCameraUnavailable(@NonNull String);
+    method public void onPhysicalCameraAvailable(@NonNull String, @NonNull String);
+    method public void onPhysicalCameraUnavailable(@NonNull String, @NonNull String);
   }
 
   public abstract static class CameraManager.TorchCallback {
@@ -17441,6 +17470,11 @@
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING = 7; // 0x7
     field public static final int SCALER_CROPPING_TYPE_CENTER_ONLY = 0; // 0x0
     field public static final int SCALER_CROPPING_TYPE_FREEFORM = 1; // 0x1
+    field public static final int SCALER_ROTATE_AND_CROP_180 = 2; // 0x2
+    field public static final int SCALER_ROTATE_AND_CROP_270 = 3; // 0x3
+    field public static final int SCALER_ROTATE_AND_CROP_90 = 1; // 0x1
+    field public static final int SCALER_ROTATE_AND_CROP_AUTO = 4; // 0x4
+    field public static final int SCALER_ROTATE_AND_CROP_NONE = 0; // 0x0
     field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR = 3; // 0x3
     field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG = 2; // 0x2
     field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG = 1; // 0x1
@@ -17576,6 +17610,7 @@
     field @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> NOISE_REDUCTION_MODE;
     field @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Float> REPROCESS_EFFECTIVE_EXPOSURE_FACTOR;
     field @NonNull public static final android.hardware.camera2.CaptureRequest.Key<android.graphics.Rect> SCALER_CROP_REGION;
+    field @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> SCALER_ROTATE_AND_CROP;
     field @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Long> SENSOR_EXPOSURE_TIME;
     field @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Long> SENSOR_FRAME_DURATION;
     field @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> SENSOR_SENSITIVITY;
@@ -17672,6 +17707,7 @@
     field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Float> REPROCESS_EFFECTIVE_EXPOSURE_FACTOR;
     field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Byte> REQUEST_PIPELINE_DEPTH;
     field @NonNull public static final android.hardware.camera2.CaptureResult.Key<android.graphics.Rect> SCALER_CROP_REGION;
+    field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> SCALER_ROTATE_AND_CROP;
     field @NonNull public static final android.hardware.camera2.CaptureResult.Key<float[]> SENSOR_DYNAMIC_BLACK_LEVEL;
     field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> SENSOR_DYNAMIC_WHITE_LEVEL;
     field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Long> SENSOR_EXPOSURE_TIME;
@@ -23400,6 +23436,9 @@
     method public long getFullBiasNanos();
     method public int getHardwareClockDiscontinuityCount();
     method public int getLeapSecond();
+    method @FloatRange(from=0.0) public double getReferenceCarrierFrequencyHzForIsb();
+    method @NonNull public String getReferenceCodeTypeForIsb();
+    method public int getReferenceConstellationTypeForIsb();
     method public long getTimeNanos();
     method @FloatRange(from=0.0f) public double getTimeUncertaintyNanos();
     method public boolean hasBiasNanos();
@@ -23410,6 +23449,9 @@
     method public boolean hasElapsedRealtimeUncertaintyNanos();
     method public boolean hasFullBiasNanos();
     method public boolean hasLeapSecond();
+    method public boolean hasReferenceCarrierFrequencyHzForIsb();
+    method public boolean hasReferenceCodeTypeForIsb();
+    method public boolean hasReferenceConstellationTypeForIsb();
     method public boolean hasTimeUncertaintyNanos();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssClock> CREATOR;
@@ -23434,6 +23476,10 @@
     method public double getPseudorangeRateUncertaintyMetersPerSecond();
     method public long getReceivedSvTimeNanos();
     method public long getReceivedSvTimeUncertaintyNanos();
+    method public double getReceiverInterSignalBiasNanos();
+    method @FloatRange(from=0.0) public double getReceiverInterSignalBiasUncertaintyNanos();
+    method public double getSatelliteInterSignalBiasNanos();
+    method @FloatRange(from=0.0) public double getSatelliteInterSignalBiasUncertaintyNanos();
     method public double getSnrInDb();
     method public int getState();
     method public int getSvid();
@@ -23445,6 +23491,10 @@
     method @Deprecated public boolean hasCarrierPhase();
     method @Deprecated public boolean hasCarrierPhaseUncertainty();
     method public boolean hasCodeType();
+    method public boolean hasReceiverInterSignalBiasNanos();
+    method public boolean hasReceiverInterSignalBiasUncertaintyNanos();
+    method public boolean hasSatelliteInterSignalBiasNanos();
+    method public boolean hasSatelliteInterSignalBiasUncertaintyNanos();
     method public boolean hasSnrInDb();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int ADR_STATE_CYCLE_SLIP = 4; // 0x4
@@ -25963,6 +26013,7 @@
     field public static final String KEY_CAPTURE_RATE = "capture-rate";
     field public static final String KEY_CHANNEL_COUNT = "channel-count";
     field public static final String KEY_CHANNEL_MASK = "channel-mask";
+    field public static final String KEY_CODECS_STRING = "codecs-string";
     field public static final String KEY_COLOR_FORMAT = "color-format";
     field public static final String KEY_COLOR_RANGE = "color-range";
     field public static final String KEY_COLOR_STANDARD = "color-standard";
@@ -26663,7 +26714,6 @@
     method public int getVolume();
     method public int getVolumeHandling();
     method public int getVolumeMax();
-    method public boolean hasAnyFeatures(@NonNull java.util.Collection<java.lang.String>);
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field public static final int CONNECTION_STATE_CONNECTED = 2; // 0x2
     field public static final int CONNECTION_STATE_CONNECTING = 1; // 0x1
@@ -27644,6 +27694,8 @@
     field public static final int CONTENT_TYPE_VOICE = 3; // 0x3
     field public static final String EFFECT_AUXILIARY = "Auxiliary";
     field public static final String EFFECT_INSERT = "Insert";
+    field public static final String EFFECT_POST_PROCESSING = "Post Processing";
+    field public static final String EFFECT_PRE_PROCESSING = "Pre Processing";
     field public static final java.util.UUID EFFECT_TYPE_AEC;
     field public static final java.util.UUID EFFECT_TYPE_AGC;
     field public static final java.util.UUID EFFECT_TYPE_BASS_BOOST;
@@ -29160,6 +29212,7 @@
     method public void onAppPrivateCommand(@NonNull String, android.os.Bundle);
     method public abstract void onRelease();
     method public abstract void onStartRecording(@Nullable android.net.Uri);
+    method public void onStartRecording(@Nullable android.net.Uri, @NonNull android.os.Bundle);
     method public abstract void onStopRecording();
     method public abstract void onTune(android.net.Uri);
     method public void onTune(android.net.Uri, android.os.Bundle);
@@ -29210,6 +29263,7 @@
     method public void release();
     method public void sendAppPrivateCommand(@NonNull String, android.os.Bundle);
     method public void startRecording(@Nullable android.net.Uri);
+    method public void startRecording(@Nullable android.net.Uri, @NonNull android.os.Bundle);
     method public void stopRecording();
     method public void tune(String, android.net.Uri);
     method public void tune(String, android.net.Uri, android.os.Bundle);
@@ -29594,6 +29648,18 @@
     method public long getReportTimestamp();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.net.ConnectivityDiagnosticsManager.ConnectivityReport> CREATOR;
+    field public static final String KEY_NETWORK_PROBES_ATTEMPTED_BITMASK = "networkProbesAttemped";
+    field public static final String KEY_NETWORK_PROBES_SUCCEEDED_BITMASK = "networkProbesSucceeded";
+    field public static final String KEY_NETWORK_VALIDATION_RESULT = "networkValidationResult";
+    field public static final int NETWORK_PROBE_DNS = 4; // 0x4
+    field public static final int NETWORK_PROBE_FALLBACK = 32; // 0x20
+    field public static final int NETWORK_PROBE_HTTP = 8; // 0x8
+    field public static final int NETWORK_PROBE_HTTPS = 16; // 0x10
+    field public static final int NETWORK_PROBE_PRIVATE_DNS = 64; // 0x40
+    field public static final int NETWORK_VALIDATION_RESULT_INVALID = 0; // 0x0
+    field public static final int NETWORK_VALIDATION_RESULT_PARTIALLY_VALID = 2; // 0x2
+    field public static final int NETWORK_VALIDATION_RESULT_SKIPPED = 3; // 0x3
+    field public static final int NETWORK_VALIDATION_RESULT_VALID = 1; // 0x1
   }
 
   public static final class ConnectivityDiagnosticsManager.DataStallReport implements android.os.Parcelable {
@@ -29607,6 +29673,9 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.net.ConnectivityDiagnosticsManager.DataStallReport> CREATOR;
     field public static final int DETECTION_METHOD_DNS_EVENTS = 1; // 0x1
     field public static final int DETECTION_METHOD_TCP_METRICS = 2; // 0x2
+    field public static final String KEY_DNS_CONSECUTIVE_TIMEOUTS = "dnsConsecutiveTimeouts";
+    field public static final String KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS = "tcpMetricsCollectionPeriodMillis";
+    field public static final String KEY_TCP_PACKET_FAIL_RATE = "tcpPacketFailRate";
   }
 
   public class ConnectivityManager {
@@ -29749,6 +29818,35 @@
     field public final int code;
   }
 
+  public final class Ikev2VpnProfile extends android.net.PlatformVpnProfile {
+    method @NonNull public java.util.List<java.lang.String> getAllowedAlgorithms();
+    method public int getMaxMtu();
+    method @Nullable public String getPassword();
+    method @Nullable public byte[] getPresharedKey();
+    method @Nullable public android.net.ProxyInfo getProxyInfo();
+    method @Nullable public java.security.PrivateKey getRsaPrivateKey();
+    method @NonNull public String getServerAddr();
+    method @Nullable public java.security.cert.X509Certificate getServerRootCaCert();
+    method @Nullable public java.security.cert.X509Certificate getUserCert();
+    method @NonNull public String getUserIdentity();
+    method @Nullable public String getUsername();
+    method public boolean isBypassable();
+    method public boolean isMetered();
+  }
+
+  public static final class Ikev2VpnProfile.Builder {
+    ctor public Ikev2VpnProfile.Builder(@NonNull String, @NonNull String);
+    method @NonNull public android.net.Ikev2VpnProfile build();
+    method @NonNull public android.net.Ikev2VpnProfile.Builder setAllowedAlgorithms(@NonNull java.util.List<java.lang.String>);
+    method @NonNull public android.net.Ikev2VpnProfile.Builder setAuthDigitalSignature(@NonNull java.security.cert.X509Certificate, @NonNull java.security.PrivateKey, @Nullable java.security.cert.X509Certificate);
+    method @NonNull public android.net.Ikev2VpnProfile.Builder setAuthPsk(@NonNull byte[]);
+    method @NonNull public android.net.Ikev2VpnProfile.Builder setAuthUsernamePassword(@NonNull String, @NonNull String, @Nullable java.security.cert.X509Certificate);
+    method @NonNull public android.net.Ikev2VpnProfile.Builder setBypassable(boolean);
+    method @NonNull public android.net.Ikev2VpnProfile.Builder setMaxMtu(int);
+    method @NonNull public android.net.Ikev2VpnProfile.Builder setMetered(boolean);
+    method @NonNull public android.net.Ikev2VpnProfile.Builder setProxy(@Nullable android.net.ProxyInfo);
+  }
+
   public class InetAddresses {
     method public static boolean isNumericAddress(@NonNull String);
     method @NonNull public static java.net.InetAddress parseNumericAddress(@NonNull String);
@@ -29977,6 +30075,7 @@
     method public int getLinkDownstreamBandwidthKbps();
     method public int getLinkUpstreamBandwidthKbps();
     method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier();
+    method public int getOwnerUid();
     method public int getSignalStrength();
     method @Nullable public android.net.TransportInfo getTransportInfo();
     method public boolean hasCapability(int);
@@ -29986,6 +30085,7 @@
     method @NonNull public android.net.NetworkCapabilities setLinkDownstreamBandwidthKbps(int);
     method @NonNull public android.net.NetworkCapabilities setLinkUpstreamBandwidthKbps(int);
     method @NonNull public android.net.NetworkCapabilities setNetworkSpecifier(@NonNull android.net.NetworkSpecifier);
+    method public void setOwnerUid(int);
     method @NonNull public android.net.NetworkCapabilities setSignalStrength(int);
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkCapabilities> CREATOR;
@@ -30097,6 +30197,14 @@
     field public String response;
   }
 
+  public abstract class PlatformVpnProfile {
+    method public final int getType();
+    method @NonNull public final String getTypeString();
+    field public static final int TYPE_IKEV2_IPSEC_PSK = 7; // 0x7
+    field public static final int TYPE_IKEV2_IPSEC_RSA = 8; // 0x8
+    field public static final int TYPE_IKEV2_IPSEC_USER_PASS = 6; // 0x6
+  }
+
   public final class Proxy {
     ctor public Proxy();
     method @Deprecated public static String getDefaultHost();
@@ -30377,6 +30485,13 @@
     method public String sanitize(String);
   }
 
+  public class VpnManager {
+    method public void deleteProvisionedVpnProfile();
+    method @Nullable public android.content.Intent provisionVpnProfile(@NonNull android.net.PlatformVpnProfile);
+    method public void startProvisionedVpnProfile();
+    method public void stopProvisionedVpnProfile();
+  }
+
   public class VpnService extends android.app.Service {
     ctor public VpnService();
     method public final boolean isAlwaysOn();
@@ -31104,7 +31219,7 @@
     method public void addOrUpdatePasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
     method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_WIFI_STATE}) public void addSuggestionConnectionStatusListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.SuggestionConnectionStatusListener);
     method @Deprecated public static int calculateSignalLevel(int, int);
-    method public int calculateSignalLevel(int);
+    method @IntRange(from=0) public int calculateSignalLevel(int);
     method @Deprecated public void cancelWps(android.net.wifi.WifiManager.WpsCallback);
     method public static int compareSignalLevel(int, int);
     method public android.net.wifi.WifiManager.MulticastLock createMulticastLock(String);
@@ -31117,7 +31232,7 @@
     method public android.net.wifi.WifiInfo getConnectionInfo();
     method public android.net.DhcpInfo getDhcpInfo();
     method public int getMaxNumberOfNetworkSuggestionsPerApp();
-    method public int getMaxSignalLevel();
+    method @IntRange(from=0) public int getMaxSignalLevel();
     method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public java.util.List<android.net.wifi.WifiNetworkSuggestion> getNetworkSuggestions();
     method @Deprecated @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", "android.permission.NETWORK_SETUP_WIZARD"}) public java.util.List<android.net.wifi.hotspot2.PasspointConfiguration> getPasspointConfigurations();
     method public java.util.List<android.net.wifi.ScanResult> getScanResults();
@@ -36382,7 +36497,7 @@
     method public boolean isSustainedPerformanceModeSupported();
     method public boolean isWakeLockLevelSupported(int);
     method public android.os.PowerManager.WakeLock newWakeLock(int, String);
-    method public void reboot(@Nullable String);
+    method @RequiresPermission(android.Manifest.permission.REBOOT) public void reboot(@Nullable String);
     method public void removeThermalStatusListener(@NonNull android.os.PowerManager.OnThermalStatusChangedListener);
     field public static final int ACQUIRE_CAUSES_WAKEUP = 268435456; // 0x10000000
     field public static final String ACTION_DEVICE_IDLE_MODE_CHANGED = "android.os.action.DEVICE_IDLE_MODE_CHANGED";
@@ -36824,6 +36939,7 @@
     method public static android.os.VibrationEffect createWaveform(long[], int);
     method public static android.os.VibrationEffect createWaveform(long[], int[], int);
     method public int describeContents();
+    method @NonNull public static android.os.VibrationEffect.Composition startComposition();
     field @NonNull public static final android.os.Parcelable.Creator<android.os.VibrationEffect> CREATOR;
     field public static final int DEFAULT_AMPLITUDE = -1; // 0xffffffff
     field public static final int EFFECT_CLICK = 0; // 0x0
@@ -36832,7 +36948,26 @@
     field public static final int EFFECT_TICK = 2; // 0x2
   }
 
+  public static class VibrationEffect.Composition {
+    ctor public VibrationEffect.Composition();
+    method @Nullable public android.os.VibrationEffect.Composition addPrimitive(int);
+    method @Nullable public android.os.VibrationEffect.Composition addPrimitive(int, @FloatRange(from=0.0f, to=1.0f) float);
+    method @Nullable public android.os.VibrationEffect.Composition addPrimitive(int, @FloatRange(from=0.0f, to=1.0f) float, @IntRange(from=0) int);
+    method @NonNull public android.os.VibrationEffect compose();
+    field public static final int PRIMITIVE_CLICK = 1; // 0x1
+    field public static final int PRIMITIVE_LIGHT_TICK = 7; // 0x7
+    field public static final int PRIMITIVE_QUICK_FALL = 6; // 0x6
+    field public static final int PRIMITIVE_QUICK_RISE = 4; // 0x4
+    field public static final int PRIMITIVE_SLOW_RISE = 5; // 0x5
+    field public static final int PRIMITIVE_SPIN = 3; // 0x3
+    field public static final int PRIMITIVE_THUD = 2; // 0x2
+  }
+
   public abstract class Vibrator {
+    method @Nullable public Boolean areAllEffectsSupported(@NonNull int...);
+    method public boolean areAllPrimitivesSupported(@NonNull int...);
+    method @Nullable public boolean[] areEffectsSupported(@NonNull int...);
+    method @NonNull public boolean[] arePrimitivesSupported(@NonNull int...);
     method @RequiresPermission(android.Manifest.permission.VIBRATE) public abstract void cancel();
     method public abstract boolean hasAmplitudeControl();
     method public abstract boolean hasVibrator();
@@ -39773,6 +39908,7 @@
     field public static final int MATCH_ONLY = 3; // 0x3
     field public static final String MEDIA_IGNORE_FILENAME = ".nomedia";
     field public static final String MEDIA_SCANNER_VOLUME = "volume";
+    field public static final String META_DATA_REVIEW_GALLERY_PREWARM_SERVICE = "android.media.review_gallery_prewarm_service";
     field public static final String META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE = "android.media.still_image_camera_preview_service";
     field public static final String QUERY_ARG_MATCH_FAVORITE = "android:query-arg-match-favorite";
     field public static final String QUERY_ARG_MATCH_PENDING = "android:query-arg-match-pending";
@@ -42759,6 +42895,7 @@
   public static final class FillResponse.Builder {
     ctor public FillResponse.Builder();
     method @NonNull public android.service.autofill.FillResponse.Builder addDataset(@Nullable android.service.autofill.Dataset);
+    method @NonNull public android.service.autofill.FillResponse.Builder addInlineAction(@NonNull android.service.autofill.InlinePresentation);
     method @NonNull public android.service.autofill.FillResponse build();
     method @NonNull public android.service.autofill.FillResponse.Builder disableAutofill(long);
     method @NonNull public android.service.autofill.FillResponse.Builder setAuthentication(@NonNull android.view.autofill.AutofillId[], @Nullable android.content.IntentSender, @Nullable android.widget.RemoteViews);
@@ -42788,10 +42925,11 @@
   }
 
   public final class InlinePresentation implements android.os.Parcelable {
-    ctor public InlinePresentation(@NonNull android.app.slice.Slice, @NonNull android.view.inline.InlinePresentationSpec);
+    ctor public InlinePresentation(@NonNull android.app.slice.Slice, @NonNull android.view.inline.InlinePresentationSpec, boolean);
     method public int describeContents();
     method @NonNull public android.view.inline.InlinePresentationSpec getInlinePresentationSpec();
     method @NonNull public android.app.slice.Slice getSlice();
+    method public boolean isPinned();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.service.autofill.InlinePresentation> CREATOR;
   }
@@ -43039,6 +43177,307 @@
 
 }
 
+package android.service.controls {
+
+  public final class Control implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public android.app.PendingIntent getAppIntent();
+    method @NonNull public String getControlId();
+    method @NonNull public android.service.controls.templates.ControlTemplate getControlTemplate();
+    method @Nullable public android.content.res.ColorStateList getCustomColor();
+    method @Nullable public android.graphics.drawable.Icon getCustomIcon();
+    method public int getDeviceType();
+    method public int getStatus();
+    method @NonNull public CharSequence getStatusText();
+    method @Nullable public CharSequence getStructure();
+    method @NonNull public CharSequence getSubtitle();
+    method @NonNull public CharSequence getTitle();
+    method @Nullable public CharSequence getZone();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.service.controls.Control> CREATOR;
+    field public static final int STATUS_DISABLED = 4; // 0x4
+    field public static final int STATUS_ERROR = 3; // 0x3
+    field public static final int STATUS_NOT_FOUND = 2; // 0x2
+    field public static final int STATUS_OK = 1; // 0x1
+    field public static final int STATUS_UNKNOWN = 0; // 0x0
+  }
+
+  public static final class Control.StatefulBuilder {
+    ctor public Control.StatefulBuilder(@NonNull String, @NonNull android.app.PendingIntent);
+    ctor public Control.StatefulBuilder(@NonNull android.service.controls.Control);
+    method @NonNull public android.service.controls.Control build();
+    method @NonNull public android.service.controls.Control.StatefulBuilder setAppIntent(@NonNull android.app.PendingIntent);
+    method @NonNull public android.service.controls.Control.StatefulBuilder setControlId(@NonNull String);
+    method @NonNull public android.service.controls.Control.StatefulBuilder setControlTemplate(@NonNull android.service.controls.templates.ControlTemplate);
+    method @NonNull public android.service.controls.Control.StatefulBuilder setCustomColor(@Nullable android.content.res.ColorStateList);
+    method @NonNull public android.service.controls.Control.StatefulBuilder setCustomIcon(@Nullable android.graphics.drawable.Icon);
+    method @NonNull public android.service.controls.Control.StatefulBuilder setDeviceType(int);
+    method @NonNull public android.service.controls.Control.StatefulBuilder setStatus(int);
+    method @NonNull public android.service.controls.Control.StatefulBuilder setStatusText(@NonNull CharSequence);
+    method @NonNull public android.service.controls.Control.StatefulBuilder setStructure(@Nullable CharSequence);
+    method @NonNull public android.service.controls.Control.StatefulBuilder setSubtitle(@NonNull CharSequence);
+    method @NonNull public android.service.controls.Control.StatefulBuilder setTitle(@NonNull CharSequence);
+    method @NonNull public android.service.controls.Control.StatefulBuilder setZone(@Nullable CharSequence);
+  }
+
+  public static final class Control.StatelessBuilder {
+    ctor public Control.StatelessBuilder(@NonNull String, @NonNull android.app.PendingIntent);
+    ctor public Control.StatelessBuilder(@NonNull android.service.controls.Control);
+    method @NonNull public android.service.controls.Control build();
+    method @NonNull public android.service.controls.Control.StatelessBuilder setAppIntent(@NonNull android.app.PendingIntent);
+    method @NonNull public android.service.controls.Control.StatelessBuilder setControlId(@NonNull String);
+    method @NonNull public android.service.controls.Control.StatelessBuilder setCustomColor(@Nullable android.content.res.ColorStateList);
+    method @NonNull public android.service.controls.Control.StatelessBuilder setCustomIcon(@Nullable android.graphics.drawable.Icon);
+    method @NonNull public android.service.controls.Control.StatelessBuilder setDeviceType(int);
+    method @NonNull public android.service.controls.Control.StatelessBuilder setStructure(@Nullable CharSequence);
+    method @NonNull public android.service.controls.Control.StatelessBuilder setSubtitle(@NonNull CharSequence);
+    method @NonNull public android.service.controls.Control.StatelessBuilder setTitle(@NonNull CharSequence);
+    method @NonNull public android.service.controls.Control.StatelessBuilder setZone(@Nullable CharSequence);
+  }
+
+  public abstract class ControlsProviderService extends android.app.Service {
+    ctor public ControlsProviderService();
+    method public abstract void loadAvailableControls(@NonNull java.util.function.Consumer<java.util.List<android.service.controls.Control>>);
+    method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
+    method public abstract void performControlAction(@NonNull String, @NonNull android.service.controls.actions.ControlAction, @NonNull java.util.function.Consumer<java.lang.Integer>);
+    method @NonNull public abstract java.util.concurrent.Flow.Publisher<android.service.controls.Control> publisherFor(@NonNull java.util.List<java.lang.String>);
+    field public static final String SERVICE_CONTROLS = "android.service.controls.ControlsProviderService";
+    field @NonNull public static final String TAG = "ControlsProviderService";
+  }
+
+  public class DeviceTypes {
+    method public static boolean validDeviceType(int);
+    field public static final int TYPE_AC_HEATER = 1; // 0x1
+    field public static final int TYPE_AC_UNIT = 2; // 0x2
+    field public static final int TYPE_AIR_FRESHENER = 3; // 0x3
+    field public static final int TYPE_AIR_PURIFIER = 4; // 0x4
+    field public static final int TYPE_AWNING = 33; // 0x21
+    field public static final int TYPE_BLINDS = 34; // 0x22
+    field public static final int TYPE_CAMERA = 50; // 0x32
+    field public static final int TYPE_CLOSET = 35; // 0x23
+    field public static final int TYPE_COFFEE_MAKER = 5; // 0x5
+    field public static final int TYPE_CURTAIN = 36; // 0x24
+    field public static final int TYPE_DEHUMIDIFIER = 6; // 0x6
+    field public static final int TYPE_DISHWASHER = 24; // 0x18
+    field public static final int TYPE_DISPLAY = 7; // 0x7
+    field public static final int TYPE_DOOR = 37; // 0x25
+    field public static final int TYPE_DOORBELL = 51; // 0x33
+    field public static final int TYPE_DRAWER = 38; // 0x26
+    field public static final int TYPE_DRYER = 25; // 0x19
+    field public static final int TYPE_FAN = 8; // 0x8
+    field public static final int TYPE_GARAGE = 39; // 0x27
+    field public static final int TYPE_GATE = 40; // 0x28
+    field public static final int TYPE_GENERIC_ARM_DISARM = -5; // 0xfffffffb
+    field public static final int TYPE_GENERIC_LOCK_UNLOCK = -4; // 0xfffffffc
+    field public static final int TYPE_GENERIC_ON_OFF = -1; // 0xffffffff
+    field public static final int TYPE_GENERIC_OPEN_CLOSE = -3; // 0xfffffffd
+    field public static final int TYPE_GENERIC_START_STOP = -2; // 0xfffffffe
+    field public static final int TYPE_GENERIC_TEMP_SETTING = -6; // 0xfffffffa
+    field public static final int TYPE_GENERIC_VIEWSTREAM = -7; // 0xfffffff9
+    field public static final int TYPE_HEATER = 47; // 0x2f
+    field public static final int TYPE_HOOD = 10; // 0xa
+    field public static final int TYPE_HUMIDIFIER = 11; // 0xb
+    field public static final int TYPE_KETTLE = 12; // 0xc
+    field public static final int TYPE_LIGHT = 13; // 0xd
+    field public static final int TYPE_LOCK = 45; // 0x2d
+    field public static final int TYPE_MICROWAVE = 14; // 0xe
+    field public static final int TYPE_MOP = 26; // 0x1a
+    field public static final int TYPE_MOWER = 27; // 0x1b
+    field public static final int TYPE_MULTICOOKER = 28; // 0x1c
+    field public static final int TYPE_OUTLET = 15; // 0xf
+    field public static final int TYPE_PERGOLA = 41; // 0x29
+    field public static final int TYPE_RADIATOR = 16; // 0x10
+    field public static final int TYPE_REFRIGERATOR = 48; // 0x30
+    field public static final int TYPE_REMOTE_CONTROL = 17; // 0x11
+    field public static final int TYPE_SECURITY_SYSTEM = 46; // 0x2e
+    field public static final int TYPE_SET_TOP = 18; // 0x12
+    field public static final int TYPE_SHOWER = 29; // 0x1d
+    field public static final int TYPE_SHUTTER = 42; // 0x2a
+    field public static final int TYPE_SPRINKLER = 30; // 0x1e
+    field public static final int TYPE_STANDMIXER = 19; // 0x13
+    field public static final int TYPE_STYLER = 20; // 0x14
+    field public static final int TYPE_SWITCH = 21; // 0x15
+    field public static final int TYPE_THERMOSTAT = 49; // 0x31
+    field public static final int TYPE_TV = 22; // 0x16
+    field public static final int TYPE_UNKNOWN = 0; // 0x0
+    field public static final int TYPE_VACUUM = 32; // 0x20
+    field public static final int TYPE_VALVE = 44; // 0x2c
+    field public static final int TYPE_WASHER = 31; // 0x1f
+    field public static final int TYPE_WATER_HEATER = 23; // 0x17
+    field public static final int TYPE_WINDOW = 43; // 0x2b
+  }
+
+}
+
+package android.service.controls.actions {
+
+  public final class BooleanAction extends android.service.controls.actions.ControlAction {
+    ctor public BooleanAction(@NonNull String, boolean);
+    ctor public BooleanAction(@NonNull String, boolean, @Nullable String);
+    method public int getActionType();
+    method public boolean getNewState();
+  }
+
+  public final class CommandAction extends android.service.controls.actions.ControlAction {
+    ctor public CommandAction(@NonNull String, @Nullable String);
+    ctor public CommandAction(@NonNull String);
+    method public int getActionType();
+  }
+
+  public abstract class ControlAction {
+    method public abstract int getActionType();
+    method @Nullable public String getChallengeValue();
+    method @NonNull public String getTemplateId();
+    method public static final boolean isValidResponse(int);
+    field @NonNull public static final android.service.controls.actions.ControlAction ERROR_ACTION;
+    field public static final int RESPONSE_CHALLENGE_ACK = 3; // 0x3
+    field public static final int RESPONSE_CHALLENGE_PASSPHRASE = 5; // 0x5
+    field public static final int RESPONSE_CHALLENGE_PIN = 4; // 0x4
+    field public static final int RESPONSE_FAIL = 2; // 0x2
+    field public static final int RESPONSE_OK = 1; // 0x1
+    field public static final int RESPONSE_UNKNOWN = 0; // 0x0
+    field public static final int TYPE_BOOLEAN = 1; // 0x1
+    field public static final int TYPE_COMMAND = 5; // 0x5
+    field public static final int TYPE_ERROR = -1; // 0xffffffff
+    field public static final int TYPE_FLOAT = 2; // 0x2
+    field public static final int TYPE_MODE = 4; // 0x4
+    field public static final int TYPE_MULTI_FLOAT = 3; // 0x3
+  }
+
+  public final class FloatAction extends android.service.controls.actions.ControlAction {
+    ctor public FloatAction(@NonNull String, float);
+    ctor public FloatAction(@NonNull String, float, @Nullable String);
+    method public int getActionType();
+    method public float getNewValue();
+  }
+
+  public final class ModeAction extends android.service.controls.actions.ControlAction {
+    ctor public ModeAction(@NonNull String, int, @Nullable String);
+    ctor public ModeAction(@NonNull String, int);
+    method public int getActionType();
+    method public int getNewMode();
+  }
+
+  public final class MultiFloatAction extends android.service.controls.actions.ControlAction {
+    ctor public MultiFloatAction(@NonNull String, @NonNull float[], @Nullable String);
+    ctor public MultiFloatAction(@NonNull String, @NonNull float[]);
+    method public int getActionType();
+    method @NonNull public float[] getNewValues();
+  }
+
+}
+
+package android.service.controls.templates {
+
+  public final class ControlButton implements android.os.Parcelable {
+    ctor public ControlButton(boolean, @NonNull CharSequence);
+    method public int describeContents();
+    method @NonNull public CharSequence getActionDescription();
+    method public boolean isChecked();
+    method @NonNull public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.service.controls.templates.ControlButton> CREATOR;
+  }
+
+  public abstract class ControlTemplate {
+    method @NonNull public String getTemplateId();
+    method public abstract int getTemplateType();
+    field @NonNull public static final android.service.controls.templates.ControlTemplate ERROR_TEMPLATE;
+    field @NonNull public static final android.service.controls.templates.ControlTemplate NO_TEMPLATE;
+    field public static final int TYPE_DISCRETE_TOGGLE = 4; // 0x4
+    field public static final int TYPE_ERROR = -1; // 0xffffffff
+    field public static final int TYPE_NONE = 0; // 0x0
+    field public static final int TYPE_RANGE = 2; // 0x2
+    field public static final int TYPE_STATELESS = 8; // 0x8
+    field public static final int TYPE_TEMPERATURE = 7; // 0x7
+    field public static final int TYPE_THUMBNAIL = 3; // 0x3
+    field public static final int TYPE_TOGGLE = 1; // 0x1
+    field public static final int TYPE_TOGGLE_RANGE = 6; // 0x6
+  }
+
+  public final class CoordinatedRangeTemplate extends android.service.controls.templates.ControlTemplate {
+    ctor public CoordinatedRangeTemplate(@NonNull String, float, @NonNull android.service.controls.templates.RangeTemplate, @NonNull android.service.controls.templates.RangeTemplate);
+    ctor public CoordinatedRangeTemplate(@NonNull String, float, float, float, float, float, float, float, float, @Nullable CharSequence);
+    method public float getCurrentValueHigh();
+    method public float getCurrentValueLow();
+    method @NonNull public CharSequence getFormatString();
+    method public float getMaxValueHigh();
+    method public float getMaxValueLow();
+    method public float getMinGap();
+    method public float getMinValueHigh();
+    method public float getMinValueLow();
+    method @NonNull public android.service.controls.templates.RangeTemplate getRangeHigh();
+    method @NonNull public android.service.controls.templates.RangeTemplate getRangeLow();
+    method public float getStepValue();
+    method public int getTemplateType();
+  }
+
+  public final class DiscreteToggleTemplate extends android.service.controls.templates.ControlTemplate {
+    ctor public DiscreteToggleTemplate(@NonNull String, @NonNull android.service.controls.templates.ControlButton, @NonNull android.service.controls.templates.ControlButton);
+    method @NonNull public android.service.controls.templates.ControlButton getNegativeButton();
+    method @NonNull public android.service.controls.templates.ControlButton getPositiveButton();
+    method public int getTemplateType();
+  }
+
+  public final class RangeTemplate extends android.service.controls.templates.ControlTemplate {
+    ctor public RangeTemplate(@NonNull String, float, float, float, float, @Nullable CharSequence);
+    method public float getCurrentValue();
+    method @NonNull public CharSequence getFormatString();
+    method public float getMaxValue();
+    method public float getMinValue();
+    method public float getStepValue();
+    method public int getTemplateType();
+  }
+
+  public final class StatelessTemplate extends android.service.controls.templates.ControlTemplate {
+    ctor public StatelessTemplate(@NonNull String);
+    method public int getTemplateType();
+  }
+
+  public final class TemperatureControlTemplate extends android.service.controls.templates.ControlTemplate {
+    ctor public TemperatureControlTemplate(@NonNull String, @NonNull android.service.controls.templates.ControlTemplate, int, int, int);
+    method public int getCurrentActiveMode();
+    method public int getCurrentMode();
+    method public int getModes();
+    method @NonNull public android.service.controls.templates.ControlTemplate getTemplate();
+    method public int getTemplateType();
+    field public static final int FLAG_MODE_COOL = 8; // 0x8
+    field public static final int FLAG_MODE_ECO = 32; // 0x20
+    field public static final int FLAG_MODE_HEAT = 4; // 0x4
+    field public static final int FLAG_MODE_HEAT_COOL = 16; // 0x10
+    field public static final int FLAG_MODE_OFF = 2; // 0x2
+    field public static final int MODE_COOL = 3; // 0x3
+    field public static final int MODE_ECO = 5; // 0x5
+    field public static final int MODE_HEAT = 2; // 0x2
+    field public static final int MODE_HEAT_COOL = 4; // 0x4
+    field public static final int MODE_OFF = 1; // 0x1
+    field public static final int MODE_UNKNOWN = 0; // 0x0
+  }
+
+  public final class ThumbnailTemplate extends android.service.controls.templates.ControlTemplate {
+    ctor public ThumbnailTemplate(@NonNull String, @NonNull android.graphics.drawable.Icon, @NonNull CharSequence);
+    method @NonNull public CharSequence getContentDescription();
+    method public int getTemplateType();
+    method @NonNull public android.graphics.drawable.Icon getThumbnail();
+  }
+
+  public final class ToggleRangeTemplate extends android.service.controls.templates.ControlTemplate {
+    ctor public ToggleRangeTemplate(@NonNull String, @NonNull android.service.controls.templates.ControlButton, @NonNull android.service.controls.templates.RangeTemplate);
+    ctor public ToggleRangeTemplate(@NonNull String, boolean, @NonNull CharSequence, @NonNull android.service.controls.templates.RangeTemplate);
+    method @NonNull public CharSequence getActionDescription();
+    method @NonNull public android.service.controls.templates.RangeTemplate getRange();
+    method public int getTemplateType();
+    method public boolean isChecked();
+  }
+
+  public final class ToggleTemplate extends android.service.controls.templates.ControlTemplate {
+    ctor public ToggleTemplate(@NonNull String, @NonNull android.service.controls.templates.ControlButton);
+    method @NonNull public CharSequence getContentDescription();
+    method public int getTemplateType();
+    method public boolean isChecked();
+  }
+
+}
+
 package android.service.dreams {
 
   public class DreamService extends android.app.Service implements android.view.Window.Callback {
@@ -43463,11 +43902,13 @@
     method public android.graphics.drawable.Icon getIcon();
     method public CharSequence getLabel();
     method public int getState();
+    method @Nullable public CharSequence getStateDescription();
     method @Nullable public CharSequence getSubtitle();
     method public void setContentDescription(CharSequence);
     method public void setIcon(android.graphics.drawable.Icon);
     method public void setLabel(CharSequence);
     method public void setState(int);
+    method public void setStateDescription(@Nullable CharSequence);
     method public void setSubtitle(@Nullable CharSequence);
     method public void updateTile();
     method public void writeToParcel(android.os.Parcel, int);
@@ -44813,6 +45254,7 @@
     method public void registerCallback(android.telecom.Call.Callback);
     method public void registerCallback(android.telecom.Call.Callback, android.os.Handler);
     method public void reject(boolean, String);
+    method public void reject(int);
     method public void removeExtras(java.util.List<java.lang.String>);
     method public void removeExtras(java.lang.String...);
     method public void respondToRttRequest(int, boolean);
@@ -44828,6 +45270,8 @@
     field public static final String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS = "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS";
     field public static final String EXTRA_SILENT_RINGING_REQUESTED = "android.telecom.extra.SILENT_RINGING_REQUESTED";
     field public static final String EXTRA_SUGGESTED_PHONE_ACCOUNTS = "android.telecom.extra.SUGGESTED_PHONE_ACCOUNTS";
+    field public static final int REJECT_REASON_DECLINED = 1; // 0x1
+    field public static final int REJECT_REASON_UNWANTED = 2; // 0x2
     field public static final int STATE_ACTIVE = 4; // 0x4
     field public static final int STATE_AUDIO_PROCESSING = 12; // 0xc
     field public static final int STATE_CONNECTING = 9; // 0x9
@@ -45095,6 +45539,7 @@
     method public void onPostDialContinue(boolean);
     method public void onPullExternalCall();
     method public void onReject();
+    method public void onReject(int);
     method public void onReject(String);
     method public void onSeparate();
     method public void onShowIncomingCallUi();
@@ -45338,6 +45783,9 @@
     field public static final int MISSED = 5; // 0x5
     field public static final int OTHER = 9; // 0x9
     field public static final String REASON_EMERGENCY_CALL_PLACED = "REASON_EMERGENCY_CALL_PLACED";
+    field public static final String REASON_EMULATING_SINGLE_CALL = "EMULATING_SINGLE_CALL";
+    field public static final String REASON_IMS_ACCESS_BLOCKED = "REASON_IMS_ACCESS_BLOCKED";
+    field public static final String REASON_WIFI_ON_BUT_WFC_OFF = "REASON_WIFI_ON_BUT_WFC_OFF";
     field public static final int REJECTED = 6; // 0x6
     field public static final int REMOTE = 3; // 0x3
     field public static final int RESTRICTED = 8; // 0x8
@@ -45666,6 +46114,7 @@
     field public static final int DURATION_SHORT = 1; // 0x1
     field public static final int DURATION_VERY_SHORT = 0; // 0x0
     field public static final String EXTRA_CALL_BACK_NUMBER = "android.telecom.extra.CALL_BACK_NUMBER";
+    field public static final String EXTRA_CALL_CREATED_TIME_MILLIS = "android.telecom.extra.CALL_CREATED_TIME_MILLIS";
     field public static final String EXTRA_CALL_DISCONNECT_CAUSE = "android.telecom.extra.CALL_DISCONNECT_CAUSE";
     field public static final String EXTRA_CALL_DISCONNECT_MESSAGE = "android.telecom.extra.CALL_DISCONNECT_MESSAGE";
     field public static final String EXTRA_CALL_DURATION = "android.telecom.extra.CALL_DURATION";
@@ -47724,10 +48173,10 @@
     field public static final int ERROR_CERTIFICATE_ERROR = 10012; // 0x271c
     field public static final int ERROR_CONNECTION_ERROR = 10014; // 0x271e
     field public static final int ERROR_DISALLOWED_BY_PPR = 10010; // 0x271a
-    field public static final int ERROR_EUICC_GSMA_INSTALL_ERROR = 10009; // 0x2719
     field public static final int ERROR_EUICC_INSUFFICIENT_MEMORY = 10004; // 0x2714
     field public static final int ERROR_EUICC_MISSING = 10006; // 0x2716
     field public static final int ERROR_INCOMPATIBLE_CARRIER = 10003; // 0x2713
+    field public static final int ERROR_INSTALL_PROFILE = 10009; // 0x2719
     field public static final int ERROR_INVALID_ACTIVATION_CODE = 10001; // 0x2711
     field public static final int ERROR_INVALID_CONFIRMATION_CODE = 10002; // 0x2712
     field public static final int ERROR_INVALID_RESPONSE = 10015; // 0x271f
@@ -47850,13 +48299,20 @@
 
   public final class ImsException extends java.lang.Exception {
     method public int getCode();
+    field public static final int CODE_ERROR_INVALID_SUBSCRIPTION = 3; // 0x3
     field public static final int CODE_ERROR_SERVICE_UNAVAILABLE = 1; // 0x1
     field public static final int CODE_ERROR_UNSPECIFIED = 0; // 0x0
     field public static final int CODE_ERROR_UNSUPPORTED_OPERATION = 2; // 0x2
   }
 
+  public class ImsManager {
+    method @NonNull public android.telephony.ims.ImsMmTelManager getImsMmTelManager(int);
+    field public static final String ACTION_WFC_IMS_REGISTRATION_ERROR = "android.telephony.ims.action.WFC_IMS_REGISTRATION_ERROR";
+    field public static final String EXTRA_WFC_REGISTRATION_FAILURE_MESSAGE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_MESSAGE";
+    field public static final String EXTRA_WFC_REGISTRATION_FAILURE_TITLE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_TITLE";
+  }
+
   public class ImsMmTelManager implements android.telephony.ims.RegistrationManager {
-    method @NonNull @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
     method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
     method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public int getVoWiFiModeSetting();
@@ -52627,6 +53083,7 @@
     method public android.graphics.Canvas lockHardwareCanvas();
     method public void readFromParcel(android.os.Parcel);
     method public void release();
+    method public void setFrameRate(@FloatRange(from=0.0) float);
     method @Deprecated public void unlockCanvas(android.graphics.Canvas);
     method public void unlockCanvasAndPost(android.graphics.Canvas);
     method public void writeToParcel(android.os.Parcel, int);
@@ -52670,6 +53127,7 @@
     method @NonNull public android.view.SurfaceControl.Transaction reparent(@NonNull android.view.SurfaceControl, @Nullable android.view.SurfaceControl);
     method @NonNull public android.view.SurfaceControl.Transaction setAlpha(@NonNull android.view.SurfaceControl, @FloatRange(from=0.0, to=1.0) float);
     method @NonNull public android.view.SurfaceControl.Transaction setBufferSize(@NonNull android.view.SurfaceControl, @IntRange(from=0) int, @IntRange(from=0) int);
+    method @NonNull public android.view.SurfaceControl.Transaction setFrameRate(@NonNull android.view.SurfaceControl, @FloatRange(from=0.0) float);
     method @NonNull public android.view.SurfaceControl.Transaction setGeometry(@NonNull android.view.SurfaceControl, @Nullable android.graphics.Rect, @Nullable android.graphics.Rect, int);
     method @NonNull public android.view.SurfaceControl.Transaction setLayer(@NonNull android.view.SurfaceControl, @IntRange(from=java.lang.Integer.MIN_VALUE, to=java.lang.Integer.MAX_VALUE) int);
     method @NonNull public android.view.SurfaceControl.Transaction setVisibility(@NonNull android.view.SurfaceControl, boolean);
@@ -55752,6 +56210,7 @@
     method public boolean isContentCaptureEnabled();
     method public void removeData(@NonNull android.view.contentcapture.DataRemovalRequest);
     method public void setContentCaptureEnabled(boolean);
+    method public void shareData(@NonNull android.view.contentcapture.DataShareRequest, @NonNull java.util.concurrent.Executor, @NonNull android.view.contentcapture.DataShareWriteAdapter);
   }
 
   public abstract class ContentCaptureSession implements java.lang.AutoCloseable {
@@ -55800,6 +56259,24 @@
     method @NonNull public android.content.LocusId getLocusId();
   }
 
+  public final class DataShareRequest implements android.os.Parcelable {
+    ctor public DataShareRequest(@Nullable android.content.LocusId, @NonNull String);
+    method public int describeContents();
+    method @Nullable public android.content.LocusId getLocusId();
+    method @NonNull public String getMimeType();
+    method @NonNull public String getPackageName();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.view.contentcapture.DataShareRequest> CREATOR;
+  }
+
+  public interface DataShareWriteAdapter {
+    method public default void onError(int);
+    method public void onRejected();
+    method public void onWrite(@NonNull android.os.ParcelFileDescriptor, @NonNull android.os.CancellationSignal);
+    field public static final int ERROR_CONCURRENT_REQUEST = 1; // 0x1
+    field public static final int ERROR_UNKNOWN = 2; // 0x2
+  }
+
 }
 
 package android.view.inline {
@@ -56001,10 +56478,13 @@
     method @Nullable public String[] getAutofillHints();
     method @NonNull public android.view.inline.InlinePresentationSpec getPresentationSpec();
     method @NonNull public String getSource();
+    method @NonNull public String getType();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.InlineSuggestionInfo> CREATOR;
     field public static final String SOURCE_AUTOFILL = "android:autofill";
     field public static final String SOURCE_PLATFORM = "android:platform";
+    field public static final String TYPE_ACTION = "android:autofill:action";
+    field public static final String TYPE_SUGGESTION = "android:autofill:suggestion";
   }
 
   public final class InlineSuggestionsRequest implements android.os.Parcelable {
diff --git a/api/system-current.txt b/api/system-current.txt
index 0cd7d2a..23beedb 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5,6 +5,7 @@
     field public static final String ACCESS_AMBIENT_LIGHT_STATS = "android.permission.ACCESS_AMBIENT_LIGHT_STATS";
     field public static final String ACCESS_BROADCAST_RADIO = "android.permission.ACCESS_BROADCAST_RADIO";
     field public static final String ACCESS_CACHE_FILESYSTEM = "android.permission.ACCESS_CACHE_FILESYSTEM";
+    field public static final String ACCESS_CONTEXT_HUB = "android.permission.ACCESS_CONTEXT_HUB";
     field public static final String ACCESS_DRM_CERTIFICATES = "android.permission.ACCESS_DRM_CERTIFICATES";
     field @Deprecated public static final String ACCESS_FM_RADIO = "android.permission.ACCESS_FM_RADIO";
     field public static final String ACCESS_INSTANT_APPS = "android.permission.ACCESS_INSTANT_APPS";
@@ -246,10 +247,15 @@
 
   public static final class R.array {
     field public static final int config_keySystemUuidMapping = 17235973; // 0x1070005
+    field public static final int config_restrictedPreinstalledCarrierApps = 17235975; // 0x1070007
+    field public static final int config_sms_enabled_locking_shift_tables = 17235977; // 0x1070009
+    field public static final int config_sms_enabled_single_shift_tables = 17235976; // 0x1070008
+    field public static final int simColors = 17235974; // 0x1070006
   }
 
   public static final class R.attr {
     field public static final int allowClearUserDataOnFailedRestore = 16844288; // 0x1010600
+    field public static final int isAutofillInlineSuggestionTheme = 16844310; // 0x1010616
     field public static final int isVrOnly = 16844152; // 0x1010578
     field public static final int minExtensionVersion = 16844306; // 0x1010612
     field public static final int requiredSystemPropertyName = 16844133; // 0x1010565
@@ -297,6 +303,7 @@
     field public static final int config_helpPackageNameKey = 17039387; // 0x104001b
     field public static final int config_helpPackageNameValue = 17039388; // 0x104001c
     field public static final int config_systemGallery = 17039402; // 0x104002a
+    field public static final int low_memory = 17039403; // 0x104002b
   }
 
   public static final class R.style {
@@ -621,9 +628,12 @@
 
   public class KeyguardManager {
     method public android.content.Intent createConfirmFactoryResetCredentialIntent(CharSequence, CharSequence, CharSequence);
+    method @RequiresPermission("android.permission.SET_INITIAL_LOCK") public int getMinLockLength(boolean, int);
     method @RequiresPermission(android.Manifest.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS) public boolean getPrivateNotificationsAllowed();
     method @RequiresPermission(android.Manifest.permission.SHOW_KEYGUARD_MESSAGE) public void requestDismissKeyguard(@NonNull android.app.Activity, @Nullable CharSequence, @Nullable android.app.KeyguardManager.KeyguardDismissCallback);
+    method @RequiresPermission("android.permission.SET_INITIAL_LOCK") public boolean setLock(int, @NonNull byte[], int);
     method @RequiresPermission(android.Manifest.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS) public void setPrivateNotificationsAllowed(boolean);
+    method @RequiresPermission("android.permission.SET_INITIAL_LOCK") public boolean validateLockPasswordComplexity(boolean, @NonNull byte[], int);
   }
 
   public class Notification implements android.os.Parcelable {
@@ -1770,6 +1780,7 @@
     field public static final String BUGREPORT_SERVICE = "bugreport";
     field public static final String CONTENT_SUGGESTIONS_SERVICE = "content_suggestions";
     field public static final String CONTEXTHUB_SERVICE = "contexthub";
+    field public static final String ETHERNET_SERVICE = "ethernet";
     field public static final String EUICC_CARD_SERVICE = "euicc_card";
     field public static final String HDMI_CONTROL_SERVICE = "hdmi_control";
     field public static final String NETD_SERVICE = "netd";
@@ -1785,7 +1796,6 @@
     field public static final String STATUS_BAR_SERVICE = "statusbar";
     field public static final String SYSTEM_CONFIG_SERVICE = "system_config";
     field public static final String SYSTEM_UPDATE_SERVICE = "system_update";
-    field public static final String TELEPHONY_IMS_SERVICE = "telephony_ims";
     field public static final String TELEPHONY_REGISTRY_SERVICE = "telephony_registry";
     field public static final String TETHERING_SERVICE = "tethering";
     field public static final String VR_SERVICE = "vrmanager";
@@ -1824,6 +1834,7 @@
     field @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public static final String ACTION_MANAGE_SPECIAL_APP_ACCESSES = "android.intent.action.MANAGE_SPECIAL_APP_ACCESSES";
     field public static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION";
     field public static final String ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION = "android.intent.action.PACKAGE_NEEDS_INTEGRITY_VERIFICATION";
+    field public static final String ACTION_PACKAGE_UNSUSPENDED_MANUALLY = "android.intent.action.PACKAGE_UNSUSPENDED_MANUALLY";
     field public static final String ACTION_PENDING_INCIDENT_REPORTS_CHANGED = "android.intent.action.PENDING_INCIDENT_REPORTS_CHANGED";
     field public static final String ACTION_PRE_BOOT_COMPLETED = "android.intent.action.PRE_BOOT_COMPLETED";
     field public static final String ACTION_QUERY_PACKAGE_RESTART = "android.intent.action.QUERY_PACKAGE_RESTART";
@@ -1839,6 +1850,7 @@
     field public static final String ACTION_UPGRADE_SETUP = "android.intent.action.UPGRADE_SETUP";
     field public static final String ACTION_USER_ADDED = "android.intent.action.USER_ADDED";
     field public static final String ACTION_USER_REMOVED = "android.intent.action.USER_REMOVED";
+    field @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public static final String ACTION_USER_SWITCHED = "android.intent.action.USER_SWITCHED";
     field public static final String ACTION_VOICE_ASSIST = "android.intent.action.VOICE_ASSIST";
     field public static final String CATEGORY_LEANBACK_SETTINGS = "android.intent.category.LEANBACK_SETTINGS";
     field public static final String EXTRA_CALLING_PACKAGE = "android.intent.extra.CALLING_PACKAGE";
@@ -1891,26 +1903,6 @@
 
 package android.content.integrity {
 
-  public final class AppInstallMetadata {
-    method @NonNull public String getAppCertificate();
-    method @Nullable public String getInstallerCertificate();
-    method @Nullable public String getInstallerName();
-    method @NonNull public String getPackageName();
-    method public int getVersionCode();
-    method public boolean isPreInstalled();
-  }
-
-  public static final class AppInstallMetadata.Builder {
-    ctor public AppInstallMetadata.Builder();
-    method @NonNull public android.content.integrity.AppInstallMetadata build();
-    method @NonNull public android.content.integrity.AppInstallMetadata.Builder setAppCertificate(@NonNull String);
-    method @NonNull public android.content.integrity.AppInstallMetadata.Builder setInstallerCertificate(@NonNull String);
-    method @NonNull public android.content.integrity.AppInstallMetadata.Builder setInstallerName(@NonNull String);
-    method @NonNull public android.content.integrity.AppInstallMetadata.Builder setIsPreInstalled(boolean);
-    method @NonNull public android.content.integrity.AppInstallMetadata.Builder setPackageName(@NonNull String);
-    method @NonNull public android.content.integrity.AppInstallMetadata.Builder setVersionCode(int);
-  }
-
   public class AppIntegrityManager {
     method @NonNull public String getCurrentRuleSetProvider();
     method @NonNull public String getCurrentRuleSetVersion();
@@ -1920,84 +1912,28 @@
     field public static final int STATUS_SUCCESS = 0; // 0x0
   }
 
-  public abstract class AtomicFormula implements android.content.integrity.Formula {
-    ctor public AtomicFormula(int);
-    method public int getKey();
-    field public static final int APP_CERTIFICATE = 1; // 0x1
-    field public static final int EQ = 0; // 0x0
-    field public static final int GE = 4; // 0x4
-    field public static final int GT = 3; // 0x3
-    field public static final int INSTALLER_CERTIFICATE = 3; // 0x3
-    field public static final int INSTALLER_NAME = 2; // 0x2
-    field public static final int LE = 2; // 0x2
-    field public static final int LT = 1; // 0x1
-    field public static final int PACKAGE_NAME = 0; // 0x0
-    field public static final int PRE_INSTALLED = 5; // 0x5
-    field public static final int VERSION_CODE = 4; // 0x4
-  }
-
-  public static final class AtomicFormula.BooleanAtomicFormula extends android.content.integrity.AtomicFormula implements android.os.Parcelable {
-    ctor public AtomicFormula.BooleanAtomicFormula(int, boolean);
-    method public int describeContents();
-    method public int getTag();
-    method public boolean getValue();
-    method public boolean isSatisfied(@NonNull android.content.integrity.AppInstallMetadata);
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.content.integrity.AtomicFormula.BooleanAtomicFormula> CREATOR;
-  }
-
-  public static final class AtomicFormula.IntAtomicFormula extends android.content.integrity.AtomicFormula implements android.os.Parcelable {
-    ctor public AtomicFormula.IntAtomicFormula(int, int, int);
-    method public int describeContents();
-    method public int getOperator();
-    method public int getTag();
-    method public int getValue();
-    method public boolean isSatisfied(@NonNull android.content.integrity.AppInstallMetadata);
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.content.integrity.AtomicFormula.IntAtomicFormula> CREATOR;
-  }
-
-  public static final class AtomicFormula.StringAtomicFormula extends android.content.integrity.AtomicFormula implements android.os.Parcelable {
-    ctor public AtomicFormula.StringAtomicFormula(int, @NonNull String, boolean);
-    method public int describeContents();
-    method public boolean getIsHashedValue();
-    method public int getTag();
-    method @NonNull public String getValue();
-    method public boolean isSatisfied(@NonNull android.content.integrity.AppInstallMetadata);
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.content.integrity.AtomicFormula.StringAtomicFormula> CREATOR;
-  }
-
-  public final class CompoundFormula implements android.content.integrity.Formula android.os.Parcelable {
-    ctor public CompoundFormula(int, @NonNull java.util.List<android.content.integrity.Formula>);
-    method public int describeContents();
-    method public int getConnector();
-    method @NonNull public java.util.List<android.content.integrity.Formula> getFormulas();
-    method public int getTag();
-    method public boolean isSatisfied(@NonNull android.content.integrity.AppInstallMetadata);
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field public static final int AND = 0; // 0x0
-    field @NonNull public static final android.os.Parcelable.Creator<android.content.integrity.CompoundFormula> CREATOR;
-    field public static final int NOT = 2; // 0x2
-    field public static final int OR = 1; // 0x1
-  }
-
-  public interface Formula {
-    method public int getTag();
-    method public boolean isSatisfied(@NonNull android.content.integrity.AppInstallMetadata);
-    method @NonNull public static android.content.integrity.Formula readFromParcel(@NonNull android.os.Parcel);
-    method public static void writeToParcel(@NonNull android.content.integrity.Formula, @NonNull android.os.Parcel, int);
-    field public static final int BOOLEAN_ATOMIC_FORMULA_TAG = 3; // 0x3
-    field public static final int COMPOUND_FORMULA_TAG = 0; // 0x0
-    field public static final int INT_ATOMIC_FORMULA_TAG = 2; // 0x2
-    field public static final int STRING_ATOMIC_FORMULA_TAG = 1; // 0x1
+  public abstract class IntegrityFormula {
+    method @NonNull public static android.content.integrity.IntegrityFormula all(@NonNull android.content.integrity.IntegrityFormula...);
+    method @NonNull public static android.content.integrity.IntegrityFormula any(@NonNull android.content.integrity.IntegrityFormula...);
+    method @NonNull public android.content.integrity.IntegrityFormula equalTo(@NonNull String);
+    method @NonNull public android.content.integrity.IntegrityFormula equalTo(boolean);
+    method @NonNull public android.content.integrity.IntegrityFormula equalTo(long);
+    method @NonNull public android.content.integrity.IntegrityFormula greaterThan(long);
+    method @NonNull public android.content.integrity.IntegrityFormula greaterThanOrEquals(long);
+    method @NonNull public static android.content.integrity.IntegrityFormula not(@NonNull android.content.integrity.IntegrityFormula);
+    field @NonNull public static final android.content.integrity.IntegrityFormula APP_CERTIFICATE;
+    field @NonNull public static final android.content.integrity.IntegrityFormula INSTALLER_CERTIFICATE;
+    field @NonNull public static final android.content.integrity.IntegrityFormula INSTALLER_NAME;
+    field @NonNull public static final android.content.integrity.IntegrityFormula PACKAGE_NAME;
+    field @NonNull public static final android.content.integrity.IntegrityFormula PRE_INSTALLED;
+    field @NonNull public static final android.content.integrity.IntegrityFormula VERSION_CODE;
   }
 
   public final class Rule implements android.os.Parcelable {
-    ctor public Rule(@NonNull android.content.integrity.Formula, int);
+    ctor public Rule(@NonNull android.content.integrity.IntegrityFormula, int);
     method public int describeContents();
     method public int getEffect();
-    method @NonNull public android.content.integrity.Formula getFormula();
+    method @NonNull public android.content.integrity.IntegrityFormula getFormula();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.content.integrity.Rule> CREATOR;
     field public static final int DENY = 0; // 0x0
@@ -2035,8 +1971,8 @@
   public class OverlayManager {
     method @Nullable public android.content.om.OverlayInfo getOverlayInfo(@NonNull String, @NonNull android.os.UserHandle);
     method @NonNull @RequiresPermission(anyOf={"android.permission.INTERACT_ACROSS_USERS", "android.permission.INTERACT_ACROSS_USERS_FULL"}) public java.util.List<android.content.om.OverlayInfo> getOverlayInfosForTarget(@NonNull String, @NonNull android.os.UserHandle);
-    method @RequiresPermission(anyOf={"android.permission.INTERACT_ACROSS_USERS", "android.permission.INTERACT_ACROSS_USERS_FULL"}) public void setEnabled(@NonNull String, boolean, @NonNull android.os.UserHandle);
-    method @RequiresPermission(anyOf={"android.permission.INTERACT_ACROSS_USERS", "android.permission.INTERACT_ACROSS_USERS_FULL"}) public void setEnabledExclusiveInCategory(@NonNull String, @NonNull android.os.UserHandle);
+    method @RequiresPermission(anyOf={"android.permission.INTERACT_ACROSS_USERS", "android.permission.INTERACT_ACROSS_USERS_FULL"}) public void setEnabled(@NonNull String, boolean, @NonNull android.os.UserHandle) throws java.lang.IllegalStateException, java.lang.SecurityException;
+    method @RequiresPermission(anyOf={"android.permission.INTERACT_ACROSS_USERS", "android.permission.INTERACT_ACROSS_USERS_FULL"}) public void setEnabledExclusiveInCategory(@NonNull String, @NonNull android.os.UserHandle) throws java.lang.IllegalStateException, java.lang.SecurityException;
   }
 
 }
@@ -2063,6 +1999,21 @@
     method @NonNull public final int getType();
   }
 
+  public final class InstallationFile implements android.os.Parcelable {
+    ctor public InstallationFile(@NonNull String, long, @Nullable byte[]);
+    method public int describeContents();
+    method public int getFileType();
+    method @Nullable public byte[] getMetadata();
+    method @NonNull public String getName();
+    method public long getSize();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.InstallationFile> CREATOR;
+    field public static final int FILE_TYPE_APK = 0; // 0x0
+    field public static final int FILE_TYPE_LIB = 1; // 0x1
+    field public static final int FILE_TYPE_OBB = 2; // 0x2
+    field public static final int FILE_TYPE_UNKNOWN = -1; // 0xffffffff
+  }
+
   public final class InstantAppInfo implements android.os.Parcelable {
     ctor public InstantAppInfo(android.content.pm.ApplicationInfo, String[], String[]);
     ctor public InstantAppInfo(String, CharSequence, String[], String[]);
@@ -2153,11 +2104,16 @@
     field public static final int DATA_LOADER_TYPE_NONE = 0; // 0x0
     field public static final int DATA_LOADER_TYPE_STREAMING = 1; // 0x1
     field public static final String EXTRA_DATA_LOADER_TYPE = "android.content.pm.extra.DATA_LOADER_TYPE";
+    field public static final int LOCATION_DATA_APP = 0; // 0x0
+    field public static final int LOCATION_MEDIA_DATA = 2; // 0x2
+    field public static final int LOCATION_MEDIA_OBB = 1; // 0x1
   }
 
   public static class PackageInstaller.Session implements java.io.Closeable {
-    method public void addFile(@NonNull String, long, @NonNull byte[]);
+    method public void addFile(int, @NonNull String, long, @NonNull byte[], @Nullable byte[]);
     method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void commitTransferred(@NonNull android.content.IntentSender);
+    method @Nullable public android.content.pm.DataLoaderParams getDataLoaderParams();
+    method public void removeFile(int, @NonNull String);
   }
 
   public static class PackageInstaller.SessionInfo implements android.os.Parcelable {
@@ -2232,6 +2188,7 @@
     method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.SUSPEND_APPS) public String[] setPackagesSuspended(@Nullable String[], boolean, @Nullable android.os.PersistableBundle, @Nullable android.os.PersistableBundle, @Nullable String);
     method @Nullable @RequiresPermission(android.Manifest.permission.SUSPEND_APPS) public String[] setPackagesSuspended(@Nullable String[], boolean, @Nullable android.os.PersistableBundle, @Nullable android.os.PersistableBundle, @Nullable android.content.pm.SuspendDialogInfo);
     method @RequiresPermission(value=android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE, conditional=true) public void setSyntheticAppDetailsActivityEnabled(@NonNull String, boolean);
+    method public void setSystemAppState(@NonNull String, int);
     method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public abstract void setUpdateAvailable(@NonNull String, boolean);
     method @RequiresPermission(android.Manifest.permission.SET_PREFERRED_APPLICATIONS) public abstract boolean updateIntentVerificationStatusAsUser(@NonNull String, int, int);
     method @RequiresPermission(anyOf={android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS}) public abstract void updatePermissionFlags(@NonNull String, @NonNull String, @android.content.pm.PackageManager.PermissionFlags int, @android.content.pm.PackageManager.PermissionFlags int, @NonNull android.os.UserHandle);
@@ -2242,6 +2199,7 @@
     field public static final String FEATURE_BROADCAST_RADIO = "android.hardware.broadcastradio";
     field public static final String FEATURE_REBOOT_ESCROW = "android.hardware.reboot_escrow";
     field public static final String FEATURE_TELEPHONY_CARRIERLOCK = "android.hardware.telephony.carrierlock";
+    field public static final int FLAGS_PERMISSION_RESERVED_PERMISSIONCONTROLLER = -268435456; // 0xf0000000
     field public static final int FLAG_PERMISSION_APPLY_RESTRICTION = 16384; // 0x4000
     field public static final int FLAG_PERMISSION_GRANTED_BY_DEFAULT = 32; // 0x20
     field public static final int FLAG_PERMISSION_GRANTED_BY_ROLE = 32768; // 0x8000
@@ -2305,11 +2263,16 @@
     field @Deprecated public static final int MASK_PERMISSION_FLAGS = 255; // 0xff
     field public static final int MATCH_ANY_USER = 4194304; // 0x400000
     field public static final int MATCH_FACTORY_ONLY = 2097152; // 0x200000
+    field public static final int MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS = 536870912; // 0x20000000
     field public static final int MATCH_INSTANT = 8388608; // 0x800000
     field public static final int MODULE_APEX_NAME = 1; // 0x1
     field public static final int RESTRICTION_HIDE_FROM_SUGGESTIONS = 1; // 0x1
     field public static final int RESTRICTION_HIDE_NOTIFICATIONS = 2; // 0x2
     field public static final int RESTRICTION_NONE = 0; // 0x0
+    field public static final int SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN = 0; // 0x0
+    field public static final int SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_VISIBLE = 1; // 0x1
+    field public static final int SYSTEM_APP_STATE_INSTALLED = 2; // 0x2
+    field public static final int SYSTEM_APP_STATE_UNINSTALLED = 3; // 0x3
   }
 
   public abstract static class PackageManager.DexModuleRegisterCallback {
@@ -2370,6 +2333,8 @@
   public final class SuspendDialogInfo implements android.os.Parcelable {
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
+    field public static final int BUTTON_ACTION_MORE_DETAILS = 0; // 0x0
+    field public static final int BUTTON_ACTION_UNSUSPEND = 1; // 0x1
     field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.SuspendDialogInfo> CREATOR;
   }
 
@@ -2379,6 +2344,7 @@
     method @NonNull public android.content.pm.SuspendDialogInfo.Builder setIcon(@DrawableRes int);
     method @NonNull public android.content.pm.SuspendDialogInfo.Builder setMessage(@NonNull String);
     method @NonNull public android.content.pm.SuspendDialogInfo.Builder setMessage(@StringRes int);
+    method @NonNull public android.content.pm.SuspendDialogInfo.Builder setNeutralButtonAction(int);
     method @NonNull public android.content.pm.SuspendDialogInfo.Builder setNeutralButtonText(@StringRes int);
     method @NonNull public android.content.pm.SuspendDialogInfo.Builder setTitle(@StringRes int);
   }
@@ -2553,7 +2519,7 @@
     method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByPackageName(@NonNull String);
     method public android.util.Pair<float[],float[]> getCurve();
     method public float getShortTermModelLowerLuxMultiplier();
-    method public long getShortTermModelTimeout();
+    method public long getShortTermModelTimeoutMillis();
     method public float getShortTermModelUpperLuxMultiplier();
     method public boolean shouldCollectColorSamples();
     method public void writeToParcel(android.os.Parcel, int);
@@ -2570,7 +2536,7 @@
     method public int getMaxCorrectionsByPackageName();
     method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setDescription(@Nullable String);
     method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelLowerLuxMultiplier(@FloatRange(from=0.0f) float);
-    method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelTimeout(long);
+    method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelTimeoutMillis(long);
     method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelUpperLuxMultiplier(@FloatRange(from=0.0f) float);
     method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShouldCollectColorSamples(boolean);
   }
@@ -2975,7 +2941,7 @@
   public class ContextHubClient implements java.io.Closeable {
     method public void close();
     method @NonNull public android.hardware.location.ContextHubInfo getAttachedHub();
-    method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int sendMessageToNanoApp(@NonNull android.hardware.location.NanoAppMessage);
+    method @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public int sendMessageToNanoApp(@NonNull android.hardware.location.NanoAppMessage);
   }
 
   public class ContextHubClientCallback {
@@ -3024,24 +2990,24 @@
   }
 
   public final class ContextHubManager {
-    method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.ContextHubClientCallback, @NonNull java.util.concurrent.Executor);
-    method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.ContextHubClientCallback);
-    method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.app.PendingIntent, long);
-    method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubTransaction<java.lang.Void> disableNanoApp(@NonNull android.hardware.location.ContextHubInfo, long);
-    method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubTransaction<java.lang.Void> enableNanoApp(@NonNull android.hardware.location.ContextHubInfo, long);
-    method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int[] findNanoAppOnHub(int, @NonNull android.hardware.location.NanoAppFilter);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int[] getContextHubHandles();
-    method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubInfo getContextHubInfo(int);
-    method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public java.util.List<android.hardware.location.ContextHubInfo> getContextHubs();
-    method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.NanoAppInstanceInfo getNanoAppInstanceInfo(int);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int loadNanoApp(int, @NonNull android.hardware.location.NanoApp);
-    method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubTransaction<java.lang.Void> loadNanoApp(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.NanoAppBinary);
-    method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubTransaction<java.util.List<android.hardware.location.NanoAppState>> queryNanoApps(@NonNull android.hardware.location.ContextHubInfo);
+    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.ContextHubClientCallback, @NonNull java.util.concurrent.Executor);
+    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.ContextHubClientCallback);
+    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.app.PendingIntent, long);
+    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubTransaction<java.lang.Void> disableNanoApp(@NonNull android.hardware.location.ContextHubInfo, long);
+    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubTransaction<java.lang.Void> enableNanoApp(@NonNull android.hardware.location.ContextHubInfo, long);
+    method @Deprecated @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public int[] findNanoAppOnHub(int, @NonNull android.hardware.location.NanoAppFilter);
+    method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public int[] getContextHubHandles();
+    method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubInfo getContextHubInfo(int);
+    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public java.util.List<android.hardware.location.ContextHubInfo> getContextHubs();
+    method @Deprecated @Nullable @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.NanoAppInstanceInfo getNanoAppInstanceInfo(int);
+    method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public int loadNanoApp(int, @NonNull android.hardware.location.NanoApp);
+    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubTransaction<java.lang.Void> loadNanoApp(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.NanoAppBinary);
+    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubTransaction<java.util.List<android.hardware.location.NanoAppState>> queryNanoApps(@NonNull android.hardware.location.ContextHubInfo);
     method @Deprecated public int registerCallback(@NonNull android.hardware.location.ContextHubManager.Callback);
     method @Deprecated public int registerCallback(android.hardware.location.ContextHubManager.Callback, android.os.Handler);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int sendMessage(int, int, @NonNull android.hardware.location.ContextHubMessage);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int unloadNanoApp(int);
-    method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubTransaction<java.lang.Void> unloadNanoApp(@NonNull android.hardware.location.ContextHubInfo, long);
+    method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public int sendMessage(int, int, @NonNull android.hardware.location.ContextHubMessage);
+    method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public int unloadNanoApp(int);
+    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubTransaction<java.lang.Void> unloadNanoApp(@NonNull android.hardware.location.ContextHubInfo, long);
     method @Deprecated public int unregisterCallback(@NonNull android.hardware.location.ContextHubManager.Callback);
     field public static final int EVENT_HUB_RESET = 6; // 0x6
     field public static final int EVENT_NANOAPP_ABORTED = 4; // 0x4
@@ -3774,10 +3740,12 @@
     method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void setCurrentFunctions(long);
     field @RequiresPermission(android.Manifest.permission.MANAGE_USB) public static final String ACTION_USB_PORT_CHANGED = "android.hardware.usb.action.USB_PORT_CHANGED";
     field public static final String ACTION_USB_STATE = "android.hardware.usb.action.USB_STATE";
+    field public static final long FUNCTION_NCM = 1024L; // 0x400L
     field public static final long FUNCTION_NONE = 0L; // 0x0L
     field public static final long FUNCTION_RNDIS = 32L; // 0x20L
     field public static final String USB_CONFIGURED = "configured";
     field public static final String USB_CONNECTED = "connected";
+    field public static final String USB_FUNCTION_NCM = "ncm";
     field public static final String USB_FUNCTION_RNDIS = "rndis";
   }
 
@@ -3833,12 +3801,15 @@
   public final class GnssMeasurementCorrections implements android.os.Parcelable {
     method public int describeContents();
     method @FloatRange(from=-1000.0F, to=10000.0f) public double getAltitudeMeters();
+    method @FloatRange(from=0.0f, to=360.0f) public float getEnvironmentBearingDegrees();
+    method @FloatRange(from=0.0f, to=180.0f) public float getEnvironmentBearingUncertaintyDegrees();
     method @FloatRange(from=0.0f) public double getHorizontalPositionUncertaintyMeters();
     method @FloatRange(from=-90.0F, to=90.0f) public double getLatitudeDegrees();
     method @FloatRange(from=-180.0F, to=180.0f) public double getLongitudeDegrees();
     method @NonNull public java.util.List<android.location.GnssSingleSatCorrection> getSingleSatelliteCorrectionList();
     method @IntRange(from=0) public long getToaGpsNanosecondsOfWeek();
     method @FloatRange(from=0.0f) public double getVerticalPositionUncertaintyMeters();
+    method public boolean hasEnvironmentBearing();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssMeasurementCorrections> CREATOR;
   }
@@ -3847,6 +3818,8 @@
     ctor public GnssMeasurementCorrections.Builder();
     method @NonNull public android.location.GnssMeasurementCorrections build();
     method @NonNull public android.location.GnssMeasurementCorrections.Builder setAltitudeMeters(@FloatRange(from=-1000.0F, to=10000.0f) double);
+    method @NonNull public android.location.GnssMeasurementCorrections.Builder setEnvironmentBearingDegrees(@FloatRange(from=0.0f, to=360.0f) float);
+    method @NonNull public android.location.GnssMeasurementCorrections.Builder setEnvironmentBearingUncertaintyDegrees(@FloatRange(from=0.0f, to=180.0f) float);
     method @NonNull public android.location.GnssMeasurementCorrections.Builder setHorizontalPositionUncertaintyMeters(@FloatRange(from=0.0f) double);
     method @NonNull public android.location.GnssMeasurementCorrections.Builder setLatitudeDegrees(@FloatRange(from=-90.0F, to=90.0f) double);
     method @NonNull public android.location.GnssMeasurementCorrections.Builder setLongitudeDegrees(@FloatRange(from=-180.0F, to=180.0f) double);
@@ -4591,8 +4564,8 @@
   public final class DvbDeviceInfo implements android.os.Parcelable {
     ctor public DvbDeviceInfo(int, int);
     method public int describeContents();
-    method public int getAdapterId();
-    method public int getDeviceId();
+    method @IntRange(from=0) public int getAdapterId();
+    method @IntRange(from=0) public int getDeviceId();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.DvbDeviceInfo> CREATOR;
   }
@@ -6073,8 +6046,8 @@
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_AIRPLANE_MODE, android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void setAirplaneMode(boolean);
     method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public boolean shouldAvoidBadWifi();
     method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(@NonNull android.net.Network, @NonNull android.os.Bundle);
-    method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback);
-    method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback, android.os.Handler);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback, android.os.Handler);
     method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void stopTethering(int);
     method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void unregisterNetworkProvider(@NonNull android.net.NetworkProvider);
     method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void unregisterTetheringEventCallback(@NonNull android.net.ConnectivityManager.OnTetheringEventCallback);
@@ -6090,10 +6063,10 @@
     field @Deprecated public static final int TYPE_WIFI_P2P = 13; // 0xd
   }
 
-  public abstract static class ConnectivityManager.OnStartTetheringCallback {
-    ctor public ConnectivityManager.OnStartTetheringCallback();
-    method public void onTetheringFailed();
-    method public void onTetheringStarted();
+  @Deprecated public abstract static class ConnectivityManager.OnStartTetheringCallback {
+    ctor @Deprecated public ConnectivityManager.OnStartTetheringCallback();
+    method @Deprecated public void onTetheringFailed();
+    method @Deprecated public void onTetheringStarted();
   }
 
   @Deprecated public static interface ConnectivityManager.OnTetheringEntitlementResultListener {
@@ -6105,6 +6078,19 @@
     method @Deprecated public void onUpstreamChanged(@Nullable android.net.Network);
   }
 
+  public class EthernetManager {
+    method @NonNull public android.net.EthernetManager.TetheredInterfaceRequest requestTetheredInterface(@NonNull android.net.EthernetManager.TetheredInterfaceCallback);
+  }
+
+  public static interface EthernetManager.TetheredInterfaceCallback {
+    method public void onAvailable(@NonNull String);
+    method public void onUnavailable();
+  }
+
+  public static class EthernetManager.TetheredInterfaceRequest {
+    method public void release();
+  }
+
   public class InvalidPacketException extends java.lang.Exception {
     ctor public InvalidPacketException(int);
     field public static final int ERROR_INVALID_IP_ADDRESS = -21; // 0xffffffeb
@@ -6174,13 +6160,18 @@
 
   public class LinkAddress implements android.os.Parcelable {
     ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int, int, int);
+    ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int, int, int, long, long);
     ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int);
     ctor public LinkAddress(@NonNull String);
     ctor public LinkAddress(@NonNull String, int, int);
+    method public long getDeprecationTime();
+    method public long getExpirationTime();
     method public boolean isGlobalPreferred();
     method public boolean isIpv4();
     method public boolean isIpv6();
     method public boolean isSameAddressAs(@Nullable android.net.LinkAddress);
+    field public static final long LIFETIME_PERMANENT = 9223372036854775807L; // 0x7fffffffffffffffL
+    field public static final long LIFETIME_UNKNOWN = -1L; // 0xffffffffffffffffL
   }
 
   public final class LinkProperties implements android.os.Parcelable {
@@ -6297,9 +6288,11 @@
 
   public final class NetworkCapabilities implements android.os.Parcelable {
     method public boolean deduceRestrictedCapability();
+    method @NonNull public java.util.List<java.lang.Integer> getAdministratorUids();
     method @Nullable public String getSSID();
     method @NonNull public int[] getTransportTypes();
     method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities);
+    method public void setAdministratorUids(@NonNull java.util.List<java.lang.Integer>);
     method @NonNull public android.net.NetworkCapabilities setSSID(@Nullable String);
     method @NonNull public android.net.NetworkCapabilities setTransportInfo(@NonNull android.net.TransportInfo);
     field public static final int NET_CAPABILITY_OEM_PAID = 22; // 0x16
@@ -6495,19 +6488,41 @@
     method public boolean satisfiedBy(android.net.NetworkSpecifier);
   }
 
+  public final class TetheredClient implements android.os.Parcelable {
+    ctor public TetheredClient(@NonNull android.net.MacAddress, @NonNull java.util.Collection<android.net.TetheredClient.AddressInfo>, int);
+    method public int describeContents();
+    method @NonNull public java.util.List<android.net.TetheredClient.AddressInfo> getAddresses();
+    method @NonNull public android.net.MacAddress getMacAddress();
+    method public int getTetheringType();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.TetheredClient> CREATOR;
+  }
+
+  public static final class TetheredClient.AddressInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public android.net.LinkAddress getAddress();
+    method @Nullable public String getHostname();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.TetheredClient.AddressInfo> CREATOR;
+  }
+
   public class TetheringManager {
-    method public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.TetheringEventCallback);
-    method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void requestLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.OnTetheringEntitlementResultListener);
-    method public void stopAllTethering();
-    method public void stopTethering(int);
-    method public void unregisterTetheringEventCallback(@NonNull android.net.TetheringManager.TetheringEventCallback);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.TetheringEventCallback);
+    method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void requestLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.OnTetheringEntitlementResultListener);
+    method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(@NonNull android.net.TetheringManager.TetheringRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback);
+    method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(int, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback);
+    method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void stopAllTethering();
+    method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void stopTethering(int);
+    method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.ACCESS_NETWORK_STATE}) public void unregisterTetheringEventCallback(@NonNull android.net.TetheringManager.TetheringEventCallback);
     field public static final String ACTION_TETHER_STATE_CHANGED = "android.net.conn.TETHER_STATE_CHANGED";
     field public static final String EXTRA_ACTIVE_LOCAL_ONLY = "android.net.extra.ACTIVE_LOCAL_ONLY";
     field public static final String EXTRA_ACTIVE_TETHER = "tetherArray";
     field public static final String EXTRA_AVAILABLE_TETHER = "availableArray";
     field public static final String EXTRA_ERRORED_TETHER = "erroredArray";
     field public static final int TETHERING_BLUETOOTH = 2; // 0x2
+    field public static final int TETHERING_ETHERNET = 5; // 0x5
     field public static final int TETHERING_INVALID = -1; // 0xffffffff
+    field public static final int TETHERING_NCM = 4; // 0x4
     field public static final int TETHERING_USB = 1; // 0x1
     field public static final int TETHERING_WIFI = 0; // 0x0
     field public static final int TETHERING_WIFI_P2P = 3; // 0x3
@@ -6533,8 +6548,15 @@
     method public void onTetheringEntitlementResult(int);
   }
 
+  public abstract static class TetheringManager.StartTetheringCallback {
+    ctor public TetheringManager.StartTetheringCallback();
+    method public void onTetheringFailed(int);
+    method public void onTetheringStarted();
+  }
+
   public abstract static class TetheringManager.TetheringEventCallback {
     ctor public TetheringManager.TetheringEventCallback();
+    method public void onClientsChanged(@NonNull java.util.Collection<android.net.TetheredClient>);
     method public void onError(@NonNull String, int);
     method @Deprecated public void onTetherableInterfaceRegexpsChanged(@NonNull android.net.TetheringManager.TetheringInterfaceRegexps);
     method public void onTetherableInterfacesChanged(@NonNull java.util.List<java.lang.String>);
@@ -6550,6 +6572,17 @@
     method @Deprecated @NonNull public java.util.List<java.lang.String> getTetherableWifiRegexs();
   }
 
+  public static class TetheringManager.TetheringRequest {
+  }
+
+  public static class TetheringManager.TetheringRequest.Builder {
+    ctor public TetheringManager.TetheringRequest.Builder(int);
+    method @NonNull public android.net.TetheringManager.TetheringRequest build();
+    method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setExemptFromEntitlementCheck(boolean);
+    method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setSilentProvisioning(boolean);
+    method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder useStaticIpv4Addresses(@NonNull android.net.LinkAddress);
+  }
+
   public class TrafficStats {
     method public static void setThreadStatsTagApp();
     method public static void setThreadStatsTagBackup();
@@ -6739,7 +6772,7 @@
   }
 
   public final class IkeSessionConfiguration {
-    ctor public IkeSessionConfiguration();
+    method @NonNull public java.util.List<java.net.InetAddress> getPcscfServers();
     method @NonNull public String getRemoteApplicationVersion();
     method @NonNull public java.util.List<byte[]> getRemoteVendorIDs();
     method public boolean isIkeExtensionEnabled(int);
@@ -6748,6 +6781,7 @@
   }
 
   public final class IkeSessionParams {
+    method @NonNull public java.util.List<android.net.ipsec.ike.IkeSessionParams.IkeConfigRequest> getConfigurationRequests();
     method public long getHardLifetime();
     method @NonNull public android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig getLocalAuthConfig();
     method @NonNull public android.net.ipsec.ike.IkeIdentification getLocalIdentification();
@@ -6761,6 +6795,8 @@
 
   public static final class IkeSessionParams.Builder {
     ctor public IkeSessionParams.Builder();
+    method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder addPcscfServerRequest(@NonNull java.net.InetAddress);
+    method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder addPcscfServerRequest(int);
     method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder addSaProposal(@NonNull android.net.ipsec.ike.IkeSaProposal);
     method @NonNull public android.net.ipsec.ike.IkeSessionParams build();
     method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setAuthDigitalSignature(@Nullable java.security.cert.X509Certificate, @NonNull java.security.cert.X509Certificate, @NonNull java.security.PrivateKey);
@@ -6774,6 +6810,14 @@
     method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setUdpEncapsulationSocket(@NonNull android.net.IpSecManager.UdpEncapsulationSocket);
   }
 
+  public static interface IkeSessionParams.ConfigRequestIpv4PcscfServer extends android.net.ipsec.ike.IkeSessionParams.IkeConfigRequest {
+    method @Nullable public java.net.Inet4Address getAddress();
+  }
+
+  public static interface IkeSessionParams.ConfigRequestIpv6PcscfServer extends android.net.ipsec.ike.IkeSessionParams.IkeConfigRequest {
+    method @Nullable public java.net.Inet6Address getAddress();
+  }
+
   public abstract static class IkeSessionParams.IkeAuthConfig {
   }
 
@@ -6795,6 +6839,9 @@
     method @NonNull public byte[] getPsk();
   }
 
+  public static interface IkeSessionParams.IkeConfigRequest {
+  }
+
   public final class IkeTrafficSelector {
     ctor public IkeTrafficSelector(int, int, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress);
     field public final int endPort;
@@ -6842,7 +6889,7 @@
   }
 
   public final class TunnelModeChildSessionParams extends android.net.ipsec.ike.ChildSessionParams {
-    method @NonNull public java.util.List<android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequest> getConfigurationRequests();
+    method @NonNull public java.util.List<android.net.ipsec.ike.TunnelModeChildSessionParams.TunnelModeChildConfigRequest> getConfigurationRequests();
   }
 
   public static final class TunnelModeChildSessionParams.Builder {
@@ -6859,33 +6906,33 @@
     method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder setLifetime(long, long);
   }
 
-  public static interface TunnelModeChildSessionParams.ConfigRequest {
-  }
-
-  public static interface TunnelModeChildSessionParams.ConfigRequestIpv4Address extends android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequest {
+  public static interface TunnelModeChildSessionParams.ConfigRequestIpv4Address extends android.net.ipsec.ike.TunnelModeChildSessionParams.TunnelModeChildConfigRequest {
     method @Nullable public java.net.Inet4Address getAddress();
   }
 
-  public static interface TunnelModeChildSessionParams.ConfigRequestIpv4DhcpServer extends android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequest {
+  public static interface TunnelModeChildSessionParams.ConfigRequestIpv4DhcpServer extends android.net.ipsec.ike.TunnelModeChildSessionParams.TunnelModeChildConfigRequest {
     method @Nullable public java.net.Inet4Address getAddress();
   }
 
-  public static interface TunnelModeChildSessionParams.ConfigRequestIpv4DnsServer extends android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequest {
+  public static interface TunnelModeChildSessionParams.ConfigRequestIpv4DnsServer extends android.net.ipsec.ike.TunnelModeChildSessionParams.TunnelModeChildConfigRequest {
     method @Nullable public java.net.Inet4Address getAddress();
   }
 
-  public static interface TunnelModeChildSessionParams.ConfigRequestIpv4Netmask extends android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequest {
+  public static interface TunnelModeChildSessionParams.ConfigRequestIpv4Netmask extends android.net.ipsec.ike.TunnelModeChildSessionParams.TunnelModeChildConfigRequest {
   }
 
-  public static interface TunnelModeChildSessionParams.ConfigRequestIpv6Address extends android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequest {
+  public static interface TunnelModeChildSessionParams.ConfigRequestIpv6Address extends android.net.ipsec.ike.TunnelModeChildSessionParams.TunnelModeChildConfigRequest {
     method @Nullable public java.net.Inet6Address getAddress();
     method public int getPrefixLength();
   }
 
-  public static interface TunnelModeChildSessionParams.ConfigRequestIpv6DnsServer extends android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequest {
+  public static interface TunnelModeChildSessionParams.ConfigRequestIpv6DnsServer extends android.net.ipsec.ike.TunnelModeChildSessionParams.TunnelModeChildConfigRequest {
     method @Nullable public java.net.Inet6Address getAddress();
   }
 
+  public static interface TunnelModeChildSessionParams.TunnelModeChildConfigRequest {
+  }
+
 }
 
 package android.net.ipsec.ike.exceptions {
@@ -7507,12 +7554,12 @@
     method @NonNull public String getCaPath();
     method @NonNull public String getClientCertificateAlias();
     method public int getOcsp();
-    method @Nullable public String getWapiCertSuite();
+    method @NonNull public String getWapiCertSuite();
     method public void setCaCertificateAliases(@Nullable String[]);
-    method public void setCaPath(@Nullable String);
-    method public void setClientCertificateAlias(@Nullable String);
+    method public void setCaPath(@NonNull String);
+    method public void setClientCertificateAlias(@NonNull String);
     method public void setOcsp(int);
-    method public void setWapiCertSuite(@Nullable String);
+    method public void setWapiCertSuite(@NonNull String);
     field public static final int OCSP_NONE = 0; // 0x0
     field public static final int OCSP_REQUEST_CERT_STATUS = 1; // 0x1
     field public static final int OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS = 3; // 0x3
@@ -7524,12 +7571,12 @@
   }
 
   public class WifiInfo implements android.os.Parcelable {
-    method @Nullable public String getAppPackageName();
-    method public double getRxSuccessRate();
+    method public double getLostTxPacketsPerSecond();
+    method @Nullable public String getRequestingPackageName();
+    method public double getRetriedTxPacketsPerSecond();
     method public int getScore();
-    method public double getTxBadRate();
-    method public double getTxRetriesRate();
-    method public double getTxSuccessRate();
+    method public double getSuccessfulRxPacketsPerSecond();
+    method public double getSuccessfulTxPacketsPerSecond();
     method public boolean isEphemeral();
     method public boolean isOsuAp();
     method public boolean isPasspointAp();
@@ -7557,19 +7604,17 @@
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void connect(int, @Nullable android.net.wifi.WifiManager.ActionListener);
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void disable(int, @Nullable android.net.wifi.WifiManager.ActionListener);
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK}) public void disableEphemeralNetwork(@NonNull String);
-    method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void enableVerboseLogging(int);
     method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void factoryReset();
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void forget(int, @Nullable android.net.wifi.WifiManager.ActionListener);
     method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.util.Pair<android.net.wifi.WifiConfiguration,java.util.Map<java.lang.Integer,java.util.List<android.net.wifi.ScanResult>>>> getAllMatchingWifiConfigs(@NonNull java.util.List<android.net.wifi.ScanResult>);
     method @Nullable @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public String getCountryCode();
-    method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public android.net.Network getCurrentNetwork();
+    method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public android.net.Network getCurrentNetwork();
     method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public String[] getFactoryMacAddresses();
     method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.Map<android.net.wifi.hotspot2.OsuProvider,java.util.List<android.net.wifi.ScanResult>> getMatchingOsuProviders(@Nullable java.util.List<android.net.wifi.ScanResult>);
     method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.Map<android.net.wifi.hotspot2.OsuProvider,android.net.wifi.hotspot2.PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders(@NonNull java.util.Set<android.net.wifi.hotspot2.OsuProvider>);
     method @NonNull @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_WIFI_STATE}) public java.util.Map<android.net.wifi.WifiNetworkSuggestion,java.util.List<android.net.wifi.ScanResult>> getMatchingScanResults(@NonNull java.util.List<android.net.wifi.WifiNetworkSuggestion>, @Nullable java.util.List<android.net.wifi.ScanResult>);
     method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_WIFI_STATE, android.Manifest.permission.READ_WIFI_CREDENTIAL}) public java.util.List<android.net.wifi.WifiConfiguration> getPrivilegedConfiguredNetworks();
     method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public android.net.wifi.SoftApConfiguration getSoftApConfiguration();
-    method public int getVerboseLoggingLevel();
     method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void getWifiActivityEnergyInfoAsync(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.OnWifiActivityEnergyInfoListener);
     method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public android.net.wifi.WifiConfiguration getWifiApConfiguration();
     method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public int getWifiApState();
@@ -7579,24 +7624,24 @@
     method @Deprecated public boolean isDeviceToDeviceRttSupported();
     method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public boolean isDualModeSupported();
     method public boolean isPortableHotspotSupported();
+    method public boolean isVerboseLoggingEnabled();
     method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public boolean isWifiApEnabled();
     method public boolean isWifiScannerSupported();
-    method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void registerNetworkRequestMatchCallback(@NonNull android.net.wifi.WifiManager.NetworkRequestMatchCallback);
     method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void registerNetworkRequestMatchCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.NetworkRequestMatchCallback);
-    method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void registerSoftApCallback(@NonNull android.net.wifi.WifiManager.SoftApCallback);
     method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void registerSoftApCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.SoftApCallback);
-    method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void registerTrafficStateCallback(@NonNull android.net.wifi.WifiManager.TrafficStateCallback);
     method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void registerTrafficStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.TrafficStateCallback);
     method @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) public void removeOnWifiUsabilityStatsListener(@NonNull android.net.wifi.WifiManager.OnWifiUsabilityStatsListener);
     method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void restoreBackupData(@NonNull byte[]);
     method @Nullable @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public android.net.wifi.SoftApConfiguration restoreSoftApBackupData(@NonNull byte[]);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void restoreSupplicantBackupData(@NonNull byte[], @NonNull byte[]);
+    method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void restoreSupplicantBackupData(@NonNull byte[], @NonNull byte[]);
     method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public byte[] retrieveBackupData();
     method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public byte[] retrieveSoftApBackupData();
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void save(@NonNull android.net.wifi.WifiConfiguration, @Nullable android.net.wifi.WifiManager.ActionListener);
     method @RequiresPermission(android.Manifest.permission.WIFI_SET_DEVICE_MOBILITY_STATE) public void setDeviceMobilityState(int);
     method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setMacRandomizationSettingPasspointEnabled(@NonNull String, boolean);
+    method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setMeteredOverridePasspoint(@NonNull String, int);
     method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public boolean setSoftApConfiguration(@NonNull android.net.wifi.SoftApConfiguration);
+    method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setVerboseLoggingEnabled(boolean);
     method @Deprecated @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration);
     method @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) public boolean setWifiConnectedNetworkScorer(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.WifiConnectedNetworkScorer);
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startEasyConnectAsConfiguratorInitiator(@NonNull String, int, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.EasyConnectStatusCallback);
@@ -7961,6 +8006,7 @@
   }
 
   public final class PasspointConfiguration implements android.os.Parcelable {
+    method public int getMeteredOverride();
     method public boolean isAutoJoinEnabled();
     method public boolean isMacRandomizationEnabled();
   }
@@ -8321,22 +8367,22 @@
     method @NonNull public android.os.BatterySaverPolicyConfig.Builder setLocationMode(int);
   }
 
-  public class BatteryStatsManager {
+  public final class BatteryStatsManager {
     method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.os.connectivity.CellularBatteryStats getCellularBatteryStats();
     method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.os.connectivity.WifiBatteryStats getWifiBatteryStats();
-    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void noteFullWifiLockAcquiredFromSource(@NonNull android.os.WorkSource);
-    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void noteFullWifiLockReleasedFromSource(@NonNull android.os.WorkSource);
-    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void noteWifiBatchedScanStartedFromSource(@NonNull android.os.WorkSource, @IntRange(from=0) int);
-    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void noteWifiBatchedScanStoppedFromSource(@NonNull android.os.WorkSource);
-    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void noteWifiMulticastDisabled(int);
-    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void noteWifiMulticastEnabled(int);
-    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void noteWifiOff();
-    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void noteWifiOn();
-    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void noteWifiRssiChanged(@IntRange(from=0xffffff81, to=0) int);
-    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void noteWifiScanStartedFromSource(@NonNull android.os.WorkSource);
-    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void noteWifiScanStoppedFromSource(@NonNull android.os.WorkSource);
-    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void noteWifiState(int, @Nullable String);
-    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void noteWifiSupplicantStateChanged(int, boolean);
+    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportFullWifiLockAcquiredFromSource(@NonNull android.os.WorkSource);
+    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportFullWifiLockReleasedFromSource(@NonNull android.os.WorkSource);
+    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiBatchedScanStartedFromSource(@NonNull android.os.WorkSource, @IntRange(from=0) int);
+    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiBatchedScanStoppedFromSource(@NonNull android.os.WorkSource);
+    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiMulticastDisabled(int);
+    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiMulticastEnabled(int);
+    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiOff();
+    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiOn();
+    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiRssiChanged(@IntRange(from=0xffffff81, to=0) int);
+    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiScanStartedFromSource(@NonNull android.os.WorkSource);
+    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiScanStoppedFromSource(@NonNull android.os.WorkSource);
+    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiState(int, @Nullable String);
+    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiSupplicantStateChanged(int, boolean);
     field public static final int WIFI_STATE_OFF = 0; // 0x0
     field public static final int WIFI_STATE_OFF_SCANNING = 1; // 0x1
     field public static final int WIFI_STATE_ON_CONNECTED_P2P = 5; // 0x5
@@ -8560,9 +8606,6 @@
     field public static final int STATUS_SUCCESS = 0; // 0x0
   }
 
-  @IntDef(prefix={"STATUS_"}, value={android.os.HwParcel.STATUS_SUCCESS}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface HwParcel.Status {
-  }
-
   public interface IHwBinder {
     method public boolean linkToDeath(android.os.IHwBinder.DeathRecipient, long);
     method public android.os.IHwInterface queryLocalInterface(String);
@@ -8746,6 +8789,26 @@
     field public static final int TUPLE_VALUE_TYPE = 7; // 0x7
   }
 
+  public class StatsFrameworkInitializer {
+    method public static void registerServiceWrappers();
+    method public static void setStatsServiceManager(@NonNull android.os.StatsServiceManager);
+  }
+
+  public class StatsServiceManager {
+    method @NonNull public android.os.StatsServiceManager.ServiceRegisterer getStatsCompanionServiceRegisterer();
+    method @NonNull public android.os.StatsServiceManager.ServiceRegisterer getStatsManagerServiceRegisterer();
+    method @NonNull public android.os.StatsServiceManager.ServiceRegisterer getStatsdServiceRegisterer();
+  }
+
+  public static class StatsServiceManager.ServiceNotFoundException extends java.lang.Exception {
+    ctor public StatsServiceManager.ServiceNotFoundException(@NonNull String);
+  }
+
+  public static final class StatsServiceManager.ServiceRegisterer {
+    method @Nullable public android.os.IBinder get();
+    method @Nullable public android.os.IBinder getOrThrow() throws android.os.StatsServiceManager.ServiceNotFoundException;
+  }
+
   public class SystemConfigManager {
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_CARRIER_APP_INFO) public java.util.Set<java.lang.String> getDisabledUntilUsedPreinstalledCarrierApps();
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_CARRIER_APP_INFO) public java.util.Map<java.lang.String,java.util.List<java.lang.String>> getDisabledUntilUsedPreinstalledCarrierAssociatedApps();
@@ -8780,16 +8843,12 @@
     method @NonNull public android.os.TelephonyServiceManager.ServiceRegisterer getEuiccCardControllerServiceRegisterer();
     method @NonNull public android.os.TelephonyServiceManager.ServiceRegisterer getEuiccControllerService();
     method @NonNull public android.os.TelephonyServiceManager.ServiceRegisterer getIccPhoneBookServiceRegisterer();
-    method @NonNull public android.os.TelephonyServiceManager.ServiceRegisterer getNetworkPolicyServiceRegisterer();
     method @NonNull public android.os.TelephonyServiceManager.ServiceRegisterer getOpportunisticNetworkServiceRegisterer();
-    method @NonNull public android.os.TelephonyServiceManager.ServiceRegisterer getPackageManagerServiceRegisterer();
-    method @NonNull public android.os.TelephonyServiceManager.ServiceRegisterer getPermissionManagerServiceRegisterer();
     method @NonNull public android.os.TelephonyServiceManager.ServiceRegisterer getPhoneSubServiceRegisterer();
     method @NonNull public android.os.TelephonyServiceManager.ServiceRegisterer getSmsServiceRegisterer();
     method @NonNull public android.os.TelephonyServiceManager.ServiceRegisterer getSubscriptionServiceRegisterer();
     method @NonNull public android.os.TelephonyServiceManager.ServiceRegisterer getTelephonyImsServiceRegisterer();
     method @NonNull public android.os.TelephonyServiceManager.ServiceRegisterer getTelephonyRcsMessageServiceRegisterer();
-    method @NonNull public android.os.TelephonyServiceManager.ServiceRegisterer getTelephonyRegistryServiceRegisterer();
     method @NonNull public android.os.TelephonyServiceManager.ServiceRegisterer getTelephonyServiceRegisterer();
   }
 
@@ -8797,7 +8856,7 @@
     ctor public TelephonyServiceManager.ServiceNotFoundException(@NonNull String);
   }
 
-  public final class TelephonyServiceManager.ServiceRegisterer {
+  public static final class TelephonyServiceManager.ServiceRegisterer {
     method @Nullable public android.os.IBinder get();
     method @NonNull public android.os.IBinder getOrThrow() throws android.os.TelephonyServiceManager.ServiceNotFoundException;
     method public void register(@NonNull android.os.IBinder);
@@ -8983,23 +9042,15 @@
   }
 
   public final class WifiActivityEnergyInfo implements android.os.Parcelable {
-    ctor public WifiActivityEnergyInfo(long, int, long, long, long, long);
+    ctor public WifiActivityEnergyInfo(long, int, @IntRange(from=0) long, @IntRange(from=0) long, @IntRange(from=0) long, @IntRange(from=0) long);
     method public int describeContents();
-    method public long getControllerEnergyUsedMicroJoules();
-    method public long getControllerIdleDurationMillis();
-    method public long getControllerRxDurationMillis();
-    method public long getControllerScanDurationMillis();
-    method public long getControllerTxDurationMillis();
+    method @IntRange(from=0) public long getControllerEnergyUsedMicroJoules();
+    method @IntRange(from=0) public long getControllerIdleDurationMillis();
+    method @IntRange(from=0) public long getControllerRxDurationMillis();
+    method @IntRange(from=0) public long getControllerScanDurationMillis();
+    method @IntRange(from=0) public long getControllerTxDurationMillis();
     method public int getStackState();
     method public long getTimeSinceBootMillis();
-    method public boolean isValid();
-    method public void setControllerEnergyUsedMicroJoules(long);
-    method public void setControllerIdleDurationMillis(long);
-    method public void setControllerRxDurationMillis(long);
-    method public void setControllerScanDurationMillis(long);
-    method public void setControllerTxDurationMillis(long);
-    method public void setStackState(int);
-    method public void setTimeSinceBootMillis(long);
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.os.connectivity.WifiActivityEnergyInfo> CREATOR;
     field public static final int STACK_STATE_INVALID = 0; // 0x0
@@ -9010,12 +9061,12 @@
 
   public final class WifiBatteryStats implements android.os.Parcelable {
     method public int describeContents();
+    method public long getAppScanRequestCount();
     method public long getEnergyConsumedMaMillis();
     method public long getIdleTimeMillis();
     method public long getKernelActiveTimeMillis();
     method public long getLoggingDurationMillis();
     method public long getMonitoredRailChargeConsumedMaMillis();
-    method public long getNumAppScanRequest();
     method public long getNumBytesRx();
     method public long getNumBytesTx();
     method public long getNumPacketsRx();
@@ -9125,6 +9176,7 @@
   public final class PermissionManager {
     method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY) public int getRuntimePermissionsVersion();
     method @NonNull public java.util.List<android.permission.PermissionManager.SplitPermissionInfo> getSplitPermissions();
+    method @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS) public void grantDefaultPermissionsToEnabledCarrierApps(@NonNull String[], @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
     method @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS) public void grantDefaultPermissionsToEnabledImsServices(@NonNull String[], @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
     method @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS) public void grantDefaultPermissionsToEnabledTelephonyDataServices(@NonNull String[], @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
     method @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS) public void grantDefaultPermissionsToLuiApp(@NonNull String, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
@@ -9557,6 +9609,7 @@
     field public static final String AUTOFILL_USER_DATA_MAX_USER_DATA_SIZE = "autofill_user_data_max_user_data_size";
     field public static final String AUTOFILL_USER_DATA_MAX_VALUE_LENGTH = "autofill_user_data_max_value_length";
     field public static final String AUTOFILL_USER_DATA_MIN_VALUE_LENGTH = "autofill_user_data_min_value_length";
+    field public static final String CARRIER_APPS_HANDLED = "carrier_apps_handled";
     field public static final String COMPLETED_CATEGORY_PREFIX = "suggested.completed_category.";
     field public static final String DOZE_ALWAYS_ON = "doze_always_on";
     field public static final String HUSH_GESTURE_USED = "hush_gesture_used";
@@ -9615,6 +9668,7 @@
 
   public static final class Telephony.Carriers implements android.provider.BaseColumns {
     field public static final String APN_SET_ID = "apn_set_id";
+    field @Deprecated public static final String BEARER_BITMASK = "bearer_bitmask";
     field public static final int CARRIER_EDITED = 4; // 0x4
     field @NonNull public static final android.net.Uri DPC_URI;
     field public static final String EDITED_STATUS = "edited";
@@ -9623,6 +9677,11 @@
     field public static final String MODEM_PERSIST = "modem_cognitive";
     field public static final String MTU = "mtu";
     field public static final int NO_APN_SET_ID = 0; // 0x0
+    field public static final String PROFILE_ID = "profile_id";
+    field public static final String SKIP_464XLAT = "skip_464xlat";
+    field public static final int SKIP_464XLAT_DEFAULT = -1; // 0xffffffff
+    field public static final int SKIP_464XLAT_DISABLE = 0; // 0x0
+    field public static final int SKIP_464XLAT_ENABLE = 1; // 0x1
     field public static final String TIME_LIMIT_FOR_MAX_CONNECTIONS = "max_conns_time";
     field public static final int UNEDITED = 0; // 0x0
     field public static final int USER_DELETED = 2; // 0x2
@@ -9644,6 +9703,7 @@
     field public static final String CMAS_SEVERITY = "cmas_severity";
     field public static final String CMAS_URGENCY = "cmas_urgency";
     field @NonNull public static final android.net.Uri CONTENT_URI;
+    field public static final String DATA_CODING_SCHEME = "dcs";
     field public static final String DEFAULT_SORT_ORDER = "date DESC";
     field public static final String DELIVERY_TIME = "date";
     field public static final String ETWS_WARNING_TYPE = "etws_warning_type";
@@ -9651,9 +9711,11 @@
     field public static final String GEOMETRIES = "geometries";
     field public static final String LAC = "lac";
     field public static final String LANGUAGE_CODE = "language";
+    field public static final String LOCATION_CHECK_TIME = "location_check_time";
     field public static final String MAXIMUM_WAIT_TIME = "maximum_wait_time";
     field public static final String MESSAGE_BODY = "body";
     field public static final String MESSAGE_BROADCASTED = "message_broadcasted";
+    field public static final String MESSAGE_DISPLAYED = "message_displayed";
     field public static final String MESSAGE_FORMAT = "format";
     field @NonNull @RequiresPermission(android.Manifest.permission.READ_CELL_BROADCASTS) public static final android.net.Uri MESSAGE_HISTORY_URI;
     field public static final String MESSAGE_PRIORITY = "priority";
@@ -9714,6 +9776,7 @@
     field public static final String HPLMNS = "hplmns";
     field public static final String ICC_ID = "icc_id";
     field public static final String IMSI = "imsi";
+    field public static final String IMS_RCS_UCE_ENABLED = "ims_rcs_uce_enabled";
     field public static final String ISO_COUNTRY_CODE = "iso_country_code";
     field public static final String IS_EMBEDDED = "is_embedded";
     field public static final String IS_OPPORTUNISTIC = "is_opportunistic";
@@ -9771,6 +9834,14 @@
 
 }
 
+package android.se.omapi {
+
+  public final class Reader {
+    method @RequiresPermission(android.Manifest.permission.SECURE_ELEMENT_PRIVILEGED) public boolean reset();
+  }
+
+}
+
 package android.security.keystore {
 
   public class AndroidKeyStoreProvider extends java.security.Provider {
@@ -9978,6 +10049,13 @@
     method @NonNull public android.service.autofill.Dataset.Builder setInlinePresentation(@NonNull android.view.autofill.AutofillId, @Nullable android.view.autofill.AutofillValue, @Nullable java.util.regex.Pattern, @NonNull android.service.autofill.InlinePresentation);
   }
 
+  public abstract class InlineSuggestionRenderService extends android.app.Service {
+    ctor public InlineSuggestionRenderService();
+    method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
+    method @Nullable public android.view.View onRenderSuggestion(@NonNull android.service.autofill.InlinePresentation, int, int);
+    field public static final String SERVICE_INTERFACE = "android.service.autofill.InlineSuggestionRenderService";
+  }
+
 }
 
 package android.service.autofill.augmented {
@@ -10090,6 +10168,7 @@
     method public void onContentCaptureEvent(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.view.contentcapture.ContentCaptureEvent);
     method public void onCreateContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureContext, @NonNull android.view.contentcapture.ContentCaptureSessionId);
     method public void onDataRemovalRequest(@NonNull android.view.contentcapture.DataRemovalRequest);
+    method public void onDataShareRequest(@NonNull android.view.contentcapture.DataShareRequest, @NonNull android.service.contentcapture.DataShareCallback);
     method public void onDestroyContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureSessionId);
     method public void onDisconnected();
     method public final void setContentCaptureConditions(@NonNull String, @Nullable java.util.Set<android.view.contentcapture.ContentCaptureCondition>);
@@ -10098,6 +10177,16 @@
     field public static final String SERVICE_META_DATA = "android.content_capture";
   }
 
+  public interface DataShareCallback {
+    method public void onAccept(@NonNull java.util.concurrent.Executor, @NonNull android.service.contentcapture.DataShareReadAdapter);
+    method public void onReject();
+  }
+
+  public interface DataShareReadAdapter {
+    method public void onError(int);
+    method public void onStart(@NonNull android.os.ParcelFileDescriptor, @NonNull android.os.CancellationSignal);
+  }
+
   public final class SnapshotData implements android.os.Parcelable {
     method public int describeContents();
     method @Nullable public android.app.assist.AssistContent getAssistContent();
@@ -10126,6 +10215,16 @@
 
   public abstract class DataLoaderService extends android.app.Service {
     ctor public DataLoaderService();
+    method @Nullable public android.service.dataloader.DataLoaderService.DataLoader onCreateDataLoader();
+  }
+
+  public static interface DataLoaderService.DataLoader {
+    method public boolean onCreate(@NonNull android.content.pm.DataLoaderParams, @NonNull android.service.dataloader.DataLoaderService.FileSystemConnector);
+    method public boolean onPrepareImage(@NonNull java.util.Collection<android.content.pm.InstallationFile>, @NonNull java.util.Collection<java.lang.String>);
+  }
+
+  public static final class DataLoaderService.FileSystemConnector {
+    method public void writeData(@NonNull String, long, long, @NonNull android.os.ParcelFileDescriptor) throws java.io.IOException;
   }
 
 }
@@ -10804,7 +10903,14 @@
   }
 
   public final class PhoneAccount implements android.os.Parcelable {
+    field public static final int CAPABILITY_EMERGENCY_CALLS_ONLY = 128; // 0x80
+    field public static final int CAPABILITY_EMERGENCY_PREFERRED = 8192; // 0x2000
+    field public static final int CAPABILITY_EMERGENCY_VIDEO_CALLING = 512; // 0x200
     field public static final int CAPABILITY_MULTI_USER = 32; // 0x20
+    field public static final String EXTRA_ALWAYS_USE_VOIP_AUDIO_MODE = "android.telecom.extra.ALWAYS_USE_VOIP_AUDIO_MODE";
+    field public static final String EXTRA_PLAY_CALL_RECORDING_TONE = "android.telecom.extra.PLAY_CALL_RECORDING_TONE";
+    field public static final String EXTRA_SORT_ORDER = "android.telecom.extra.SORT_ORDER";
+    field public static final String EXTRA_SUPPORTS_VIDEO_CALLING_FALLBACK = "android.telecom.extra.SUPPORTS_VIDEO_CALLING_FALLBACK";
   }
 
   public static class PhoneAccount.Builder {
@@ -10890,10 +10996,20 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean isInEmergencyCall();
     method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRinging();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUserSelectedOutgoingPhoneAccount(@Nullable android.telecom.PhoneAccountHandle);
+    field public static final String ACTION_CURRENT_TTY_MODE_CHANGED = "android.telecom.action.CURRENT_TTY_MODE_CHANGED";
+    field public static final String ACTION_TTY_PREFERRED_MODE_CHANGED = "android.telecom.action.TTY_PREFERRED_MODE_CHANGED";
+    field public static final int CALL_SOURCE_EMERGENCY_DIALPAD = 1; // 0x1
+    field public static final int CALL_SOURCE_EMERGENCY_SHORTCUT = 2; // 0x2
+    field public static final int CALL_SOURCE_UNSPECIFIED = 0; // 0x0
     field public static final String EXTRA_CALL_BACK_INTENT = "android.telecom.extra.CALL_BACK_INTENT";
+    field public static final String EXTRA_CALL_SOURCE = "android.telecom.extra.CALL_SOURCE";
+    field public static final String EXTRA_CALL_TECHNOLOGY_TYPE = "android.telecom.extra.CALL_TECHNOLOGY_TYPE";
     field public static final String EXTRA_CLEAR_MISSED_CALLS_INTENT = "android.telecom.extra.CLEAR_MISSED_CALLS_INTENT";
     field public static final String EXTRA_CONNECTION_SERVICE = "android.telecom.extra.CONNECTION_SERVICE";
+    field public static final String EXTRA_CURRENT_TTY_MODE = "android.telecom.extra.CURRENT_TTY_MODE";
     field public static final String EXTRA_IS_USER_INTENT_EMERGENCY_CALL = "android.telecom.extra.IS_USER_INTENT_EMERGENCY_CALL";
+    field public static final String EXTRA_TTY_PREFERRED_MODE = "android.telecom.extra.TTY_PREFERRED_MODE";
+    field public static final String EXTRA_UNKNOWN_CALL_HANDLE = "android.telecom.extra.UNKNOWN_CALL_HANDLE";
     field public static final int TTY_MODE_FULL = 1; // 0x1
     field public static final int TTY_MODE_HCO = 2; // 0x2
     field public static final int TTY_MODE_OFF = 0; // 0x0
@@ -10930,6 +11046,27 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallAttributes> CREATOR;
   }
 
+  public final class CallForwardingInfo implements android.os.Parcelable {
+    ctor public CallForwardingInfo(int, int, @Nullable String, int);
+    method public int describeContents();
+    method @Nullable public String getNumber();
+    method public int getReason();
+    method public int getStatus();
+    method public int getTimeoutSeconds();
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallForwardingInfo> CREATOR;
+    field public static final int REASON_ALL = 4; // 0x4
+    field public static final int REASON_ALL_CONDITIONAL = 5; // 0x5
+    field public static final int REASON_BUSY = 1; // 0x1
+    field public static final int REASON_NOT_REACHABLE = 3; // 0x3
+    field public static final int REASON_NO_REPLY = 2; // 0x2
+    field public static final int REASON_UNCONDITIONAL = 0; // 0x0
+    field public static final int STATUS_ACTIVE = 1; // 0x1
+    field public static final int STATUS_FDN_CHECK_FAILURE = 2; // 0x2
+    field public static final int STATUS_INACTIVE = 0; // 0x0
+    field public static final int STATUS_NOT_SUPPORTED = 4; // 0x4
+    field public static final int STATUS_UNKNOWN_ERROR = 3; // 0x3
+  }
+
   public final class CallQuality implements android.os.Parcelable {
     ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int);
     ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int, boolean, boolean, boolean);
@@ -11040,7 +11177,7 @@
   }
 
   public class CellBroadcastIntents {
-    method public static void sendOrderedBroadcastForBackgroundReceivers(@NonNull android.content.Context, @Nullable android.os.UserHandle, @NonNull android.content.Intent, @Nullable String, @Nullable String, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle);
+    method public static void sendSmsCbReceivedBroadcast(@NonNull android.content.Context, @Nullable android.os.UserHandle, @NonNull android.telephony.SmsCbMessage, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, int);
   }
 
   public abstract class CellBroadcastService extends android.app.Service {
@@ -11551,7 +11688,7 @@
   }
 
   public final class ModemActivityInfo implements android.os.Parcelable {
-    ctor public ModemActivityInfo(long, int, int, @Nullable int[], int);
+    ctor public ModemActivityInfo(long, int, int, @NonNull int[], int);
     method public int describeContents();
     method public int getIdleTimeMillis();
     method public int getReceiveTimeMillis();
@@ -11913,11 +12050,12 @@
   }
 
   public final class SmsCbMessage implements android.os.Parcelable {
-    ctor public SmsCbMessage(int, int, int, @NonNull android.telephony.SmsCbLocation, int, @Nullable String, @Nullable String, int, @Nullable android.telephony.SmsCbEtwsInfo, @Nullable android.telephony.SmsCbCmasInfo, int, @Nullable java.util.List<android.telephony.CbGeoUtils.Geometry>, long, int, int);
+    ctor public SmsCbMessage(int, int, int, @NonNull android.telephony.SmsCbLocation, int, @Nullable String, int, @Nullable String, int, @Nullable android.telephony.SmsCbEtwsInfo, @Nullable android.telephony.SmsCbCmasInfo, int, @Nullable java.util.List<android.telephony.CbGeoUtils.Geometry>, long, int, int);
     method @NonNull public static android.telephony.SmsCbMessage createFromCursor(@NonNull android.database.Cursor);
     method public int describeContents();
     method @Nullable public android.telephony.SmsCbCmasInfo getCmasWarningInfo();
     method @NonNull public android.content.ContentValues getContentValues();
+    method public int getDataCodingScheme();
     method @Nullable public android.telephony.SmsCbEtwsInfo getEtwsWarningInfo();
     method public int getGeographicalScope();
     method @NonNull public java.util.List<android.telephony.CbGeoUtils.Geometry> getGeometries();
@@ -12060,6 +12198,8 @@
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getAidForAppType(int);
     method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getAllowedNetworkTypes();
+    method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CallForwardingInfo getCallForwarding(int);
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCallWaitingStatus();
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int);
     method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
     method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int);
@@ -12143,12 +12283,15 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestNumberVerification(@NonNull android.telephony.PhoneNumberRange, long, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.NumberVerificationCallback);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetAllCarrierActions();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetCarrierKeysForImsiEncryption();
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void resetIms(int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean resetRadioConfig();
     method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void resetSettings();
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAllowedNetworkTypes(long);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAlwaysAllowMmsData(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAlwaysReportSignalStrength(boolean);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setCallForwarding(@NonNull android.telephony.CallForwardingInfo);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setCallWaitingStatus(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setCarrierRestrictionRules(@NonNull android.telephony.CarrierRestrictionRules);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setCdmaRoamingMode(int);
@@ -12199,6 +12342,10 @@
     field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED";
     field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED";
     field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED";
+    field public static final int CALL_WAITING_STATUS_ACTIVE = 1; // 0x1
+    field public static final int CALL_WAITING_STATUS_INACTIVE = 2; // 0x2
+    field public static final int CALL_WAITING_STATUS_NOT_SUPPORTED = 4; // 0x4
+    field public static final int CALL_WAITING_STATUS_UNKNOWN_ERROR = 3; // 0x3
     field public static final int CARD_POWER_DOWN = 0; // 0x0
     field public static final int CARD_POWER_UP = 1; // 0x1
     field public static final int CARD_POWER_UP_PASS_THROUGH = 2; // 0x2
@@ -12290,6 +12437,7 @@
   public class TelephonyRegistryManager {
     method public void addOnOpportunisticSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener, @NonNull java.util.concurrent.Executor);
     method public void addOnSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnSubscriptionsChangedListener, @NonNull java.util.concurrent.Executor);
+    method public void listenForSubscriber(int, @NonNull String, @NonNull String, @NonNull android.telephony.PhoneStateListener, int, boolean);
     method public void notifyActiveDataSubIdChanged(int);
     method public void notifyBarringInfoChanged(int, int, @NonNull android.telephony.BarringInfo);
     method public void notifyCallForwardingChanged(int, boolean);
@@ -12306,6 +12454,9 @@
     method public void notifyEmergencyNumberList(int, int);
     method public void notifyImsDisconnectCause(int, @NonNull android.telephony.ims.ImsReasonInfo);
     method public void notifyMessageWaitingChanged(int, int, boolean);
+    method public void notifyOpportunisticSubscriptionInfoChanged();
+    method public void notifyOutgoingEmergencyCall(int, int, @NonNull android.telephony.emergency.EmergencyNumber);
+    method public void notifyOutgoingEmergencySms(int, int, @NonNull android.telephony.emergency.EmergencyNumber);
     method public void notifyPhoneCapabilityChanged(@NonNull android.telephony.PhoneCapability);
     method public void notifyPreciseCallState(int, int, int, int, int);
     method public void notifyPreciseDataConnectionFailed(int, int, int, @Nullable String, int);
@@ -12314,6 +12465,7 @@
     method public void notifyServiceStateChanged(int, int, @NonNull android.telephony.ServiceState);
     method public void notifySignalStrengthChanged(int, int, @NonNull android.telephony.SignalStrength);
     method public void notifySrvccStateChanged(int, int);
+    method public void notifySubscriptionInfoChanged();
     method public void notifyUserMobileDataStateChanged(int, int, boolean);
     method public void notifyVoiceActivationStateChanged(int, int, int);
     method public void removeOnOpportunisticSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener);
@@ -12619,6 +12771,11 @@
     method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void getDefaultDownloadableSubscriptionList(android.app.PendingIntent);
     method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void getDownloadableSubscriptionMetadata(android.telephony.euicc.DownloadableSubscription, android.app.PendingIntent);
     method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public int getOtaStatus();
+    method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public java.util.List<java.lang.String> getSupportedCountries();
+    method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public java.util.List<java.lang.String> getUnsupportedCountries();
+    method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public boolean isSupportedCountry(@NonNull String);
+    method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void setSupportedCountries(@NonNull java.util.List<java.lang.String>);
+    method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void setUnsupportedCountries(@NonNull java.util.List<java.lang.String>);
     field public static final String ACTION_DELETE_SUBSCRIPTION_PRIVILEGED = "android.telephony.euicc.action.DELETE_SUBSCRIPTION_PRIVILEGED";
     field @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public static final String ACTION_OTA_STATUS_CHANGED = "android.telephony.euicc.action.OTA_STATUS_CHANGED";
     field public static final String ACTION_PROVISION_EMBEDDED_SUBSCRIPTION = "android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION";
@@ -12893,21 +13050,18 @@
   }
 
   public class ImsManager {
-    method @NonNull public android.telephony.ims.ImsMmTelManager getImsMmTelManager(int);
     method @NonNull public android.telephony.ims.ImsRcsManager getImsRcsManager(int);
     field public static final String ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION = "com.android.internal.intent.action.ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION";
-    field public static final String ACTION_WFC_IMS_REGISTRATION_ERROR = "android.telephony.ims.action.WFC_IMS_REGISTRATION_ERROR";
-    field public static final String EXTRA_WFC_REGISTRATION_FAILURE_MESSAGE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_MESSAGE";
-    field public static final String EXTRA_WFC_REGISTRATION_FAILURE_TITLE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_TITLE";
   }
 
   public class ImsMmTelManager implements android.telephony.ims.RegistrationManager {
+    method @Deprecated @NonNull @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws android.telephony.ims.ImsException;
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiRoamingModeSetting();
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAvailable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isCapable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void isSupported(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>) throws android.telephony.ims.ImsException;
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAvailable(int, int);
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isCapable(int, int);
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void isSupported(int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>) throws android.telephony.ims.ImsException;
     method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException;
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAdvancedCallingSettingEnabled(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRttCapabilitySetting(boolean);
@@ -13171,13 +13325,13 @@
   public class ProvisioningManager {
     method @NonNull public static android.telephony.ims.ProvisioningManager createForSubscriptionId(int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public int getProvisioningIntValue(int);
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getProvisioningStatusForCapability(int, int);
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public String getProvisioningStringValue(int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getRcsProvisioningStatusForCapability(int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException;
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningIntValue(int, int);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, boolean);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(int, int, boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback);
@@ -13269,8 +13423,8 @@
     method public int describeContents();
     method @NonNull public java.util.List<java.lang.String> getCapableExtensionTags();
     method @NonNull public android.net.Uri getContactUri();
-    method @Nullable public android.net.Uri getServiceUri(int);
-    method public boolean isCapable(int);
+    method @Nullable public android.net.Uri getServiceUri(long);
+    method public boolean isCapable(long);
     method public boolean isCapable(@NonNull String);
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field public static final int CAPABILITY_CALL_COMPOSER = 4194304; // 0x400000
@@ -13292,6 +13446,7 @@
     field public static final int CAPABILITY_IMAGE_SHARE = 256; // 0x100
     field public static final int CAPABILITY_IP_VIDEO_CALL = 16384; // 0x4000
     field public static final int CAPABILITY_IP_VOICE_CALL = 8192; // 0x2000
+    field public static final int CAPABILITY_MMTEL_CALL_COMPOSER = 1073741824; // 0x40000000
     field public static final int CAPABILITY_PLUG_IN = 268435456; // 0x10000000
     field public static final int CAPABILITY_POST_CALL = 8388608; // 0x800000
     field public static final int CAPABILITY_RCS_VIDEO_CALL = 1048576; // 0x100000
@@ -13300,6 +13455,7 @@
     field public static final int CAPABILITY_SHARED_MAP = 16777216; // 0x1000000
     field public static final int CAPABILITY_SHARED_SKETCH = 33554432; // 0x2000000
     field public static final int CAPABILITY_SOCIAL_PRESENCE = 2048; // 0x800
+    field public static final int CAPABILITY_STANDALONE_CHAT_BOT = 536870912; // 0x20000000
     field public static final int CAPABILITY_VIDEO_SHARE = 1024; // 0x400
     field public static final int CAPABILITY_VIDEO_SHARE_DURING_CS_CALL = 512; // 0x200
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.RcsContactUceCapability> CREATOR;
@@ -13307,19 +13463,50 @@
 
   public static class RcsContactUceCapability.Builder {
     ctor public RcsContactUceCapability.Builder(@NonNull android.net.Uri);
-    method @NonNull public android.telephony.ims.RcsContactUceCapability.Builder add(int, @NonNull android.net.Uri);
-    method @NonNull public android.telephony.ims.RcsContactUceCapability.Builder add(int);
+    method @NonNull public android.telephony.ims.RcsContactUceCapability.Builder add(long, @NonNull android.net.Uri);
+    method @NonNull public android.telephony.ims.RcsContactUceCapability.Builder add(long);
     method @NonNull public android.telephony.ims.RcsContactUceCapability.Builder add(@NonNull String);
     method @NonNull public android.telephony.ims.RcsContactUceCapability build();
   }
 
+  public class RcsUceAdapter {
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getUcePublishState() throws android.telephony.ims.ImsException;
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isUceSettingEnabled() throws android.telephony.ims.ImsException;
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void requestCapabilities(@NonNull java.util.concurrent.Executor, @NonNull java.util.List<android.net.Uri>, @NonNull android.telephony.ims.RcsUceAdapter.CapabilitiesCallback) throws android.telephony.ims.ImsException;
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean) throws android.telephony.ims.ImsException;
+    field public static final int ERROR_ALREADY_IN_QUEUE = 13; // 0xd
+    field public static final int ERROR_FORBIDDEN = 6; // 0x6
+    field public static final int ERROR_GENERIC_FAILURE = 1; // 0x1
+    field public static final int ERROR_INSUFFICIENT_MEMORY = 11; // 0xb
+    field public static final int ERROR_LOST_NETWORK = 12; // 0xc
+    field public static final int ERROR_NOT_AUTHORIZED = 5; // 0x5
+    field public static final int ERROR_NOT_AVAILABLE = 3; // 0x3
+    field public static final int ERROR_NOT_ENABLED = 2; // 0x2
+    field public static final int ERROR_NOT_FOUND = 7; // 0x7
+    field public static final int ERROR_NOT_REGISTERED = 4; // 0x4
+    field public static final int ERROR_REQUEST_TIMEOUT = 10; // 0xa
+    field public static final int ERROR_REQUEST_TOO_LARGE = 8; // 0x8
+    field public static final int PUBLISH_STATE_200_OK = 1; // 0x1
+    field public static final int PUBLISH_STATE_NOT_PUBLISHED = 2; // 0x2
+    field public static final int PUBLISH_STATE_OTHER_ERROR = 6; // 0x6
+    field public static final int PUBLISH_STATE_RCS_PROVISION_ERROR = 4; // 0x4
+    field public static final int PUBLISH_STATE_REQUEST_TIMEOUT = 5; // 0x5
+    field public static final int PUBLISH_STATE_VOLTE_PROVISION_ERROR = 3; // 0x3
+  }
+
+  public static class RcsUceAdapter.CapabilitiesCallback {
+    ctor public RcsUceAdapter.CapabilitiesCallback();
+    method public void onCapabilitiesReceived(@NonNull java.util.List<android.telephony.ims.RcsContactUceCapability>);
+    method public void onError(int);
+  }
+
 }
 
 package android.telephony.ims.feature {
 
   public final class CapabilityChangeRequest implements android.os.Parcelable {
-    method public void addCapabilitiesToDisableForTech(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
-    method public void addCapabilitiesToEnableForTech(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
+    method public void addCapabilitiesToDisableForTech(int, int);
+    method public void addCapabilitiesToEnableForTech(int, int);
     method public int describeContents();
     method public java.util.List<android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair> getCapabilitiesToDisable();
     method public java.util.List<android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair> getCapabilitiesToEnable();
@@ -13328,8 +13515,8 @@
   }
 
   public static class CapabilityChangeRequest.CapabilityPair {
-    ctor public CapabilityChangeRequest.CapabilityPair(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
-    method @android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability public int getCapability();
+    ctor public CapabilityChangeRequest.CapabilityPair(int, int);
+    method public int getCapability();
     method public int getRadioTech();
   }
 
@@ -13374,10 +13561,10 @@
     method public final void notifyVoiceMessageCountUpdate(int);
     method public void onFeatureReady();
     method public void onFeatureRemoved();
-    method public boolean queryCapabilityConfiguration(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
+    method public boolean queryCapabilityConfiguration(int, int);
     method @NonNull public final android.telephony.ims.feature.MmTelFeature.MmTelCapabilities queryCapabilityStatus();
     method public void setUiTtyMode(int, @Nullable android.os.Message);
-    method @android.telephony.ims.feature.MmTelFeature.ProcessCallResult public int shouldProcessCall(@NonNull String[]);
+    method public int shouldProcessCall(@NonNull String[]);
     field public static final String EXTRA_IS_UNKNOWN_CALL = "android.telephony.ims.feature.extra.IS_UNKNOWN_CALL";
     field public static final String EXTRA_IS_USSD = "android.telephony.ims.feature.extra.IS_USSD";
     field public static final int PROCESS_CALL_CSFB = 1; // 0x1
@@ -13387,21 +13574,17 @@
   public static class MmTelFeature.MmTelCapabilities extends android.telephony.ims.feature.ImsFeature.Capabilities {
     ctor public MmTelFeature.MmTelCapabilities();
     ctor @Deprecated public MmTelFeature.MmTelCapabilities(android.telephony.ims.feature.ImsFeature.Capabilities);
-    ctor public MmTelFeature.MmTelCapabilities(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int);
-    method public final void addCapabilities(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int);
-    method public final boolean isCapable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int);
-    method public final void removeCapabilities(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int);
-  }
-
-  @IntDef(flag=true, value={android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO, android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT, android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_SMS}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface MmTelFeature.MmTelCapabilities.MmTelCapability {
-  }
-
-  @IntDef(flag=true, value={android.telephony.ims.feature.MmTelFeature.PROCESS_CALL_IMS, android.telephony.ims.feature.MmTelFeature.PROCESS_CALL_CSFB}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface MmTelFeature.ProcessCallResult {
+    ctor public MmTelFeature.MmTelCapabilities(int);
+    method public final void addCapabilities(int);
+    method public final boolean isCapable(int);
+    method public final void removeCapabilities(int);
   }
 
   public class RcsFeature extends android.telephony.ims.feature.ImsFeature {
     ctor public RcsFeature();
     method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+    method @NonNull public android.telephony.ims.stub.RcsSipOptionsImplBase getOptionsExchangeImpl();
+    method @NonNull public android.telephony.ims.stub.RcsPresenceExchangeImplBase getPresenceExchangeImpl();
     method public final void notifyCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.RcsFeature.RcsImsCapabilities);
     method public void onFeatureReady();
     method public void onFeatureRemoved();
@@ -13594,6 +13777,71 @@
     field public static final int INVALID_RESULT = -1; // 0xffffffff
   }
 
+  public class RcsCapabilityExchange {
+    ctor public RcsCapabilityExchange();
+    method public final void onCommandUpdate(int, int) throws android.telephony.ims.ImsException;
+    field public static final int COMMAND_CODE_FETCH_ERROR = 4; // 0x4
+    field public static final int COMMAND_CODE_GENERIC_FAILURE = 2; // 0x2
+    field public static final int COMMAND_CODE_INSUFFICIENT_MEMORY = 6; // 0x6
+    field public static final int COMMAND_CODE_INVALID_PARAM = 3; // 0x3
+    field public static final int COMMAND_CODE_LOST_NETWORK_CONNECTION = 7; // 0x7
+    field public static final int COMMAND_CODE_NOT_FOUND = 9; // 0x9
+    field public static final int COMMAND_CODE_NOT_SUPPORTED = 8; // 0x8
+    field public static final int COMMAND_CODE_NO_CHANGE_IN_CAP = 11; // 0xb
+    field public static final int COMMAND_CODE_REQUEST_TIMEOUT = 5; // 0x5
+    field public static final int COMMAND_CODE_SERVICE_UNAVAILABLE = 10; // 0xa
+    field public static final int COMMAND_CODE_SERVICE_UNKNOWN = 0; // 0x0
+    field public static final int COMMAND_CODE_SUCCESS = 1; // 0x1
+  }
+
+  public class RcsPresenceExchangeImplBase extends android.telephony.ims.stub.RcsCapabilityExchange {
+    ctor public RcsPresenceExchangeImplBase();
+    method public final void onCapabilityRequestResponse(@NonNull java.util.List<android.telephony.ims.RcsContactUceCapability>, int) throws android.telephony.ims.ImsException;
+    method public final void onNetworkResponse(int, @NonNull String, int) throws android.telephony.ims.ImsException;
+    method public final void onNotifyUpdateCapabilites(int) throws android.telephony.ims.ImsException;
+    method public final void onUnpublish() throws android.telephony.ims.ImsException;
+    method public void requestCapabilities(@NonNull java.util.List<android.net.Uri>, int);
+    method public void updateCapabilities(@NonNull android.telephony.ims.RcsContactUceCapability, int);
+    field public static final int CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED = 0; // 0x0
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G = 6; // 0x6
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G = 5; // 0x5
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD = 3; // 0x3
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS = 4; // 0x4
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN = 8; // 0x8
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED = 1; // 0x1
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED = 2; // 0x2
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED = 10; // 0xa
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED = 11; // 0xb
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN = 7; // 0x7
+    field public static final int CAPABILITY_UPDATE_TRIGGER_UNKNOWN = 9; // 0x9
+    field public static final int RESPONSE_FORBIDDEN = 3; // 0x3
+    field public static final int RESPONSE_NOT_AUTHORIZED_FOR_PRESENCE = 2; // 0x2
+    field public static final int RESPONSE_NOT_FOUND = 4; // 0x4
+    field public static final int RESPONSE_NOT_REGISTERED = 1; // 0x1
+    field public static final int RESPONSE_SIP_INTERVAL_TOO_SHORT = 7; // 0x7
+    field public static final int RESPONSE_SIP_REQUEST_TIMEOUT = 5; // 0x5
+    field public static final int RESPONSE_SIP_SERVICE_UNAVAILABLE = 8; // 0x8
+    field public static final int RESPONSE_SUBSCRIBE_GENERIC_FAILURE = -1; // 0xffffffff
+    field public static final int RESPONSE_SUBSCRIBE_TOO_LARGE = 6; // 0x6
+    field public static final int RESPONSE_SUCCESS = 0; // 0x0
+  }
+
+  public class RcsSipOptionsImplBase extends android.telephony.ims.stub.RcsCapabilityExchange {
+    ctor public RcsSipOptionsImplBase();
+    method public final void onCapabilityRequestResponse(int, @NonNull String, @Nullable android.telephony.ims.RcsContactUceCapability, int) throws android.telephony.ims.ImsException;
+    method public final void onRemoteCapabilityRequest(@NonNull android.net.Uri, @NonNull android.telephony.ims.RcsContactUceCapability, int) throws android.telephony.ims.ImsException;
+    method public void respondToCapabilityRequest(@NonNull String, @NonNull android.telephony.ims.RcsContactUceCapability, int);
+    method public void respondToCapabilityRequestWithError(@NonNull android.net.Uri, int, @NonNull String, int);
+    method public void sendCapabilityRequest(@NonNull android.net.Uri, @NonNull android.telephony.ims.RcsContactUceCapability, int);
+    field public static final int RESPONSE_BAD_REQUEST = 5; // 0x5
+    field public static final int RESPONSE_DOES_NOT_EXIST_ANYWHERE = 4; // 0x4
+    field public static final int RESPONSE_GENERIC_FAILURE = -1; // 0xffffffff
+    field public static final int RESPONSE_NOT_FOUND = 3; // 0x3
+    field public static final int RESPONSE_REQUEST_TIMEOUT = 2; // 0x2
+    field public static final int RESPONSE_SUCCESS = 0; // 0x0
+    field public static final int RESPONSE_TEMPORARILY_UNAVAILABLE = 1; // 0x1
+  }
+
 }
 
 package android.telephony.mbms {
@@ -14244,3 +14492,4 @@
   }
 
 }
+
diff --git a/api/system-lint-baseline.txt b/api/system-lint-baseline.txt
index 23e1ed7..2f1889c 100644
--- a/api/system-lint-baseline.txt
+++ b/api/system-lint-baseline.txt
@@ -252,6 +252,12 @@
     
 
 
+ResourceValueFieldName: android.R.array#config_sms_enabled_locking_shift_tables:
+    Expected resource name in `android.R.array` to be in the `fooBarBaz` style, was `config_sms_enabled_locking_shift_tables`
+ResourceValueFieldName: android.R.array#config_sms_enabled_single_shift_tables:
+    Expected resource name in `android.R.array` to be in the `fooBarBaz` style, was `config_sms_enabled_single_shift_tables`
+
+
 SamShouldBeLast: android.accounts.AccountManager#addAccount(String, String, String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
     
 SamShouldBeLast: android.accounts.AccountManager#addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean):
diff --git a/api/test-current.txt b/api/test-current.txt
index e2407d6..917e938 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -77,6 +77,8 @@
     method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public void scheduleApplicationInfoChanged(java.util.List<java.lang.String>, int);
     method @RequiresPermission("android.permission.MANAGE_USERS") public boolean switchUser(@NonNull android.os.UserHandle);
     field public static final int PROCESS_CAPABILITY_ALL = 7; // 0x7
+    field public static final int PROCESS_CAPABILITY_ALL_EXPLICIT = 1; // 0x1
+    field public static final int PROCESS_CAPABILITY_ALL_IMPLICIT = 6; // 0x6
     field public static final int PROCESS_CAPABILITY_FOREGROUND_CAMERA = 2; // 0x2
     field public static final int PROCESS_CAPABILITY_FOREGROUND_LOCATION = 1; // 0x1
     field public static final int PROCESS_CAPABILITY_FOREGROUND_MICROPHONE = 4; // 0x4
@@ -769,12 +771,12 @@
     field public static final String BUGREPORT_SERVICE = "bugreport";
     field public static final String CONTENT_CAPTURE_MANAGER_SERVICE = "content_capture";
     field public static final String DEVICE_IDLE_CONTROLLER = "deviceidle";
+    field public static final String ETHERNET_SERVICE = "ethernet";
     field public static final String NETWORK_STACK_SERVICE = "network_stack";
     field public static final String PERMISSION_SERVICE = "permission";
     field public static final String POWER_WHITELIST_MANAGER = "power_whitelist";
     field public static final String ROLLBACK_SERVICE = "rollback";
     field public static final String STATUS_BAR_SERVICE = "statusbar";
-    field public static final String TELEPHONY_IMS_SERVICE = "telephony_ims";
     field public static final String TEST_NETWORK_SERVICE = "test_network";
   }
 
@@ -1089,7 +1091,7 @@
     method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByPackageName(@NonNull String);
     method public android.util.Pair<float[],float[]> getCurve();
     method public float getShortTermModelLowerLuxMultiplier();
-    method public long getShortTermModelTimeout();
+    method public long getShortTermModelTimeoutMillis();
     method public float getShortTermModelUpperLuxMultiplier();
     method public boolean shouldCollectColorSamples();
     method public void writeToParcel(android.os.Parcel, int);
@@ -1106,7 +1108,7 @@
     method public int getMaxCorrectionsByPackageName();
     method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setDescription(@Nullable String);
     method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelLowerLuxMultiplier(@FloatRange(from=0.0f) float);
-    method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelTimeout(long);
+    method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelTimeoutMillis(long);
     method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelUpperLuxMultiplier(@FloatRange(from=0.0f) float);
     method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShouldCollectColorSamples(boolean);
   }
@@ -1187,6 +1189,9 @@
     method public void resetElapsedRealtimeUncertaintyNanos();
     method public void resetFullBiasNanos();
     method public void resetLeapSecond();
+    method public void resetReferenceCarrierFrequencyHzForIsb();
+    method public void resetReferenceCodeTypeForIsb();
+    method public void resetReferenceConstellationTypeForIsb();
     method public void resetTimeUncertaintyNanos();
     method public void set(android.location.GnssClock);
     method public void setBiasNanos(double);
@@ -1198,6 +1203,9 @@
     method public void setFullBiasNanos(long);
     method public void setHardwareClockDiscontinuityCount(int);
     method public void setLeapSecond(int);
+    method public void setReferenceCarrierFrequencyHzForIsb(@FloatRange(from=0.0) double);
+    method public void setReferenceCodeTypeForIsb(@NonNull String);
+    method public void setReferenceConstellationTypeForIsb(int);
     method public void setTimeNanos(long);
     method public void setTimeUncertaintyNanos(@FloatRange(from=0.0f) double);
   }
@@ -1212,6 +1220,10 @@
     method @Deprecated public void resetCarrierPhase();
     method @Deprecated public void resetCarrierPhaseUncertainty();
     method public void resetCodeType();
+    method public void resetReceiverInterSignalBiasNanos();
+    method public void resetReceiverInterSignalBiasUncertaintyNanos();
+    method public void resetSatelliteInterSignalBiasNanos();
+    method public void resetSatelliteInterSignalBiasUncertaintyNanos();
     method public void resetSnrInDb();
     method public void set(android.location.GnssMeasurement);
     method public void setAccumulatedDeltaRangeMeters(double);
@@ -1231,6 +1243,10 @@
     method public void setPseudorangeRateUncertaintyMetersPerSecond(double);
     method public void setReceivedSvTimeNanos(long);
     method public void setReceivedSvTimeUncertaintyNanos(long);
+    method public void setReceiverInterSignalBiasNanos(double);
+    method public void setReceiverInterSignalBiasUncertaintyNanos(@FloatRange(from=0.0) double);
+    method public void setSatelliteInterSignalBiasNanos(double);
+    method public void setSatelliteInterSignalBiasUncertaintyNanos(@FloatRange(from=0.0) double);
     method public void setSnrInDb(double);
     method public void setState(int);
     method public void setSvid(int);
@@ -1596,6 +1612,19 @@
     field public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = "android.net.extra.CAPTIVE_PORTAL_USER_AGENT";
   }
 
+  public class EthernetManager {
+    method @NonNull public android.net.EthernetManager.TetheredInterfaceRequest requestTetheredInterface(@NonNull android.net.EthernetManager.TetheredInterfaceCallback);
+  }
+
+  public static interface EthernetManager.TetheredInterfaceCallback {
+    method public void onAvailable(@NonNull String);
+    method public void onUnavailable();
+  }
+
+  public static class EthernetManager.TetheredInterfaceRequest {
+    method public void release();
+  }
+
   public final class IpPrefix implements android.os.Parcelable {
     ctor public IpPrefix(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int);
     ctor public IpPrefix(@NonNull String);
@@ -1607,9 +1636,12 @@
 
   public class LinkAddress implements android.os.Parcelable {
     ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int, int, int);
+    ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int, int, int, long, long);
     ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int);
     ctor public LinkAddress(@NonNull String);
     ctor public LinkAddress(@NonNull String, int, int);
+    method public long getDeprecationTime();
+    method public long getExpirationTime();
     method public boolean isGlobalPreferred();
     method public boolean isIpv4();
     method public boolean isIpv6();
@@ -1709,19 +1741,41 @@
     method public void teardownTestNetwork(@NonNull android.net.Network);
   }
 
+  public final class TetheredClient implements android.os.Parcelable {
+    ctor public TetheredClient(@NonNull android.net.MacAddress, @NonNull java.util.Collection<android.net.TetheredClient.AddressInfo>, int);
+    method public int describeContents();
+    method @NonNull public java.util.List<android.net.TetheredClient.AddressInfo> getAddresses();
+    method @NonNull public android.net.MacAddress getMacAddress();
+    method public int getTetheringType();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.TetheredClient> CREATOR;
+  }
+
+  public static final class TetheredClient.AddressInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public android.net.LinkAddress getAddress();
+    method @Nullable public String getHostname();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.TetheredClient.AddressInfo> CREATOR;
+  }
+
   public class TetheringManager {
-    method public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.TetheringEventCallback);
-    method @RequiresPermission("android.permission.TETHER_PRIVILEGED") public void requestLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.OnTetheringEntitlementResultListener);
-    method public void stopAllTethering();
-    method public void stopTethering(int);
-    method public void unregisterTetheringEventCallback(@NonNull android.net.TetheringManager.TetheringEventCallback);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.TetheringEventCallback);
+    method @RequiresPermission(anyOf={"android.permission.TETHER_PRIVILEGED", android.Manifest.permission.WRITE_SETTINGS}) public void requestLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.OnTetheringEntitlementResultListener);
+    method @RequiresPermission(anyOf={"android.permission.TETHER_PRIVILEGED", android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(@NonNull android.net.TetheringManager.TetheringRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback);
+    method @RequiresPermission(anyOf={"android.permission.TETHER_PRIVILEGED", android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(int, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback);
+    method @RequiresPermission(anyOf={"android.permission.TETHER_PRIVILEGED", android.Manifest.permission.WRITE_SETTINGS}) public void stopAllTethering();
+    method @RequiresPermission(anyOf={"android.permission.TETHER_PRIVILEGED", android.Manifest.permission.WRITE_SETTINGS}) public void stopTethering(int);
+    method @RequiresPermission(anyOf={"android.permission.TETHER_PRIVILEGED", android.Manifest.permission.ACCESS_NETWORK_STATE}) public void unregisterTetheringEventCallback(@NonNull android.net.TetheringManager.TetheringEventCallback);
     field public static final String ACTION_TETHER_STATE_CHANGED = "android.net.conn.TETHER_STATE_CHANGED";
     field public static final String EXTRA_ACTIVE_LOCAL_ONLY = "android.net.extra.ACTIVE_LOCAL_ONLY";
     field public static final String EXTRA_ACTIVE_TETHER = "tetherArray";
     field public static final String EXTRA_AVAILABLE_TETHER = "availableArray";
     field public static final String EXTRA_ERRORED_TETHER = "erroredArray";
     field public static final int TETHERING_BLUETOOTH = 2; // 0x2
+    field public static final int TETHERING_ETHERNET = 5; // 0x5
     field public static final int TETHERING_INVALID = -1; // 0xffffffff
+    field public static final int TETHERING_NCM = 4; // 0x4
     field public static final int TETHERING_USB = 1; // 0x1
     field public static final int TETHERING_WIFI = 0; // 0x0
     field public static final int TETHERING_WIFI_P2P = 3; // 0x3
@@ -1747,8 +1801,15 @@
     method public void onTetheringEntitlementResult(int);
   }
 
+  public abstract static class TetheringManager.StartTetheringCallback {
+    ctor public TetheringManager.StartTetheringCallback();
+    method public void onTetheringFailed(int);
+    method public void onTetheringStarted();
+  }
+
   public abstract static class TetheringManager.TetheringEventCallback {
     ctor public TetheringManager.TetheringEventCallback();
+    method public void onClientsChanged(@NonNull java.util.Collection<android.net.TetheredClient>);
     method public void onError(@NonNull String, int);
     method @Deprecated public void onTetherableInterfaceRegexpsChanged(@NonNull android.net.TetheringManager.TetheringInterfaceRegexps);
     method public void onTetherableInterfacesChanged(@NonNull java.util.List<java.lang.String>);
@@ -1764,6 +1825,17 @@
     method @Deprecated @NonNull public java.util.List<java.lang.String> getTetherableWifiRegexs();
   }
 
+  public static class TetheringManager.TetheringRequest {
+  }
+
+  public static class TetheringManager.TetheringRequest.Builder {
+    ctor public TetheringManager.TetheringRequest.Builder(int);
+    method @NonNull public android.net.TetheringManager.TetheringRequest build();
+    method @NonNull @RequiresPermission("android.permission.TETHER_PRIVILEGED") public android.net.TetheringManager.TetheringRequest.Builder setExemptFromEntitlementCheck(boolean);
+    method @NonNull @RequiresPermission("android.permission.TETHER_PRIVILEGED") public android.net.TetheringManager.TetheringRequest.Builder setSilentProvisioning(boolean);
+    method @NonNull @RequiresPermission("android.permission.TETHER_PRIVILEGED") public android.net.TetheringManager.TetheringRequest.Builder useStaticIpv4Addresses(@NonNull android.net.LinkAddress);
+  }
+
   public class TrafficStats {
     method public static long getLoopbackRxBytes();
     method public static long getLoopbackRxPackets();
@@ -2146,9 +2218,6 @@
     field public static final int STATUS_SUCCESS = 0; // 0x0
   }
 
-  @IntDef(prefix={"STATUS_"}, value={android.os.HwParcel.STATUS_SUCCESS}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface HwParcel.Status {
-  }
-
   public interface IHwBinder {
     method public boolean linkToDeath(android.os.IHwBinder.DeathRecipient, long);
     method public android.os.IHwInterface queryLocalInterface(String);
@@ -2777,6 +2846,7 @@
     field public static final String CMAS_SEVERITY = "cmas_severity";
     field public static final String CMAS_URGENCY = "cmas_urgency";
     field @NonNull public static final android.net.Uri CONTENT_URI;
+    field public static final String DATA_CODING_SCHEME = "dcs";
     field public static final String DEFAULT_SORT_ORDER = "date DESC";
     field public static final String DELIVERY_TIME = "date";
     field public static final String ETWS_WARNING_TYPE = "etws_warning_type";
@@ -2784,9 +2854,11 @@
     field public static final String GEOMETRIES = "geometries";
     field public static final String LAC = "lac";
     field public static final String LANGUAGE_CODE = "language";
+    field public static final String LOCATION_CHECK_TIME = "location_check_time";
     field public static final String MAXIMUM_WAIT_TIME = "maximum_wait_time";
     field public static final String MESSAGE_BODY = "body";
     field public static final String MESSAGE_BROADCASTED = "message_broadcasted";
+    field public static final String MESSAGE_DISPLAYED = "message_displayed";
     field public static final String MESSAGE_FORMAT = "format";
     field @NonNull @RequiresPermission(android.Manifest.permission.READ_CELL_BROADCASTS) public static final android.net.Uri MESSAGE_HISTORY_URI;
     field public static final String MESSAGE_PRIORITY = "priority";
@@ -2921,6 +2993,13 @@
     method public void apply(@NonNull android.service.autofill.ValueFinder, @NonNull android.widget.RemoteViews, int) throws java.lang.Exception;
   }
 
+  public abstract class InlineSuggestionRenderService extends android.app.Service {
+    ctor public InlineSuggestionRenderService();
+    method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
+    method @Nullable public android.view.View onRenderSuggestion(@NonNull android.service.autofill.InlinePresentation, int, int);
+    field public static final String SERVICE_INTERFACE = "android.service.autofill.InlineSuggestionRenderService";
+  }
+
   public abstract class InternalOnClickAction implements android.service.autofill.OnClickAction android.os.Parcelable {
     ctor public InternalOnClickAction();
     method public abstract void onClick(@NonNull android.view.ViewGroup);
@@ -3483,6 +3562,7 @@
   public class TelephonyRegistryManager {
     method public void addOnOpportunisticSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener, @NonNull java.util.concurrent.Executor);
     method public void addOnSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnSubscriptionsChangedListener, @NonNull java.util.concurrent.Executor);
+    method public void listenForSubscriber(int, @NonNull String, @NonNull String, @NonNull android.telephony.PhoneStateListener, int, boolean);
     method public void notifyActiveDataSubIdChanged(int);
     method public void notifyBarringInfoChanged(int, int, @NonNull android.telephony.BarringInfo);
     method public void notifyCallForwardingChanged(int, boolean);
@@ -3499,6 +3579,8 @@
     method public void notifyEmergencyNumberList(int, int);
     method public void notifyImsDisconnectCause(int, @NonNull android.telephony.ims.ImsReasonInfo);
     method public void notifyMessageWaitingChanged(int, int, boolean);
+    method public void notifyOutgoingEmergencyCall(int, int, @NonNull android.telephony.emergency.EmergencyNumber);
+    method public void notifyOutgoingEmergencySms(int, int, @NonNull android.telephony.emergency.EmergencyNumber);
     method public void notifyPhoneCapabilityChanged(@NonNull android.telephony.PhoneCapability);
     method public void notifyPreciseCallState(int, int, int, int, int);
     method public void notifyPreciseDataConnectionFailed(int, int, int, @Nullable String, int);
@@ -3732,21 +3814,18 @@
   }
 
   public class ImsManager {
-    method @NonNull public android.telephony.ims.ImsMmTelManager getImsMmTelManager(int);
     method @NonNull public android.telephony.ims.ImsRcsManager getImsRcsManager(int);
     field public static final String ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION = "com.android.internal.intent.action.ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION";
-    field public static final String ACTION_WFC_IMS_REGISTRATION_ERROR = "android.telephony.ims.action.WFC_IMS_REGISTRATION_ERROR";
-    field public static final String EXTRA_WFC_REGISTRATION_FAILURE_MESSAGE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_MESSAGE";
-    field public static final String EXTRA_WFC_REGISTRATION_FAILURE_TITLE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_TITLE";
   }
 
   public class ImsMmTelManager implements android.telephony.ims.RegistrationManager {
+    method @Deprecated @NonNull @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws android.telephony.ims.ImsException;
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getVoWiFiRoamingModeSetting();
-    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isAvailable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
-    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isCapable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
-    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void isSupported(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>) throws android.telephony.ims.ImsException;
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isAvailable(int, int);
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isCapable(int, int);
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void isSupported(int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>) throws android.telephony.ims.ImsException;
     method @Deprecated @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException;
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAdvancedCallingSettingEnabled(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRttCapabilitySetting(boolean);
@@ -4006,13 +4085,13 @@
   public class ProvisioningManager {
     method @NonNull public static android.telephony.ims.ProvisioningManager createForSubscriptionId(int);
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @WorkerThread public int getProvisioningIntValue(int);
-    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @WorkerThread public boolean getProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @WorkerThread public boolean getProvisioningStatusForCapability(int, int);
     method @Nullable @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @WorkerThread public String getProvisioningStringValue(int);
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @WorkerThread public boolean getRcsProvisioningStatusForCapability(int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean);
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException;
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningIntValue(int, int);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, boolean);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(int, int, boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean);
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback);
@@ -4100,13 +4179,94 @@
     method public void onProvisioningStringChanged(int, @NonNull String);
   }
 
+  public final class RcsContactUceCapability implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public java.util.List<java.lang.String> getCapableExtensionTags();
+    method @NonNull public android.net.Uri getContactUri();
+    method @Nullable public android.net.Uri getServiceUri(long);
+    method public boolean isCapable(long);
+    method public boolean isCapable(@NonNull String);
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field public static final int CAPABILITY_CALL_COMPOSER = 4194304; // 0x400000
+    field public static final int CAPABILITY_CHAT_BOT = 67108864; // 0x4000000
+    field public static final int CAPABILITY_CHAT_BOT_ROLE = 134217728; // 0x8000000
+    field public static final int CAPABILITY_CHAT_SESSION = 2; // 0x2
+    field public static final int CAPABILITY_CHAT_SESSION_STORE_FORWARD = 4; // 0x4
+    field public static final int CAPABILITY_CHAT_STANDALONE = 1; // 0x1
+    field public static final int CAPABILITY_DISCOVERY_VIA_PRESENCE = 4096; // 0x1000
+    field public static final int CAPABILITY_FILE_TRANSFER = 8; // 0x8
+    field public static final int CAPABILITY_FILE_TRANSFER_HTTP = 64; // 0x40
+    field public static final int CAPABILITY_FILE_TRANSFER_SMS = 128; // 0x80
+    field public static final int CAPABILITY_FILE_TRANSFER_STORE_FORWARD = 32; // 0x20
+    field public static final int CAPABILITY_FILE_TRANSFER_THUMBNAIL = 16; // 0x10
+    field public static final int CAPABILITY_GEOLOCATION_PULL = 131072; // 0x20000
+    field public static final int CAPABILITY_GEOLOCATION_PULL_FILE_TRANSFER = 262144; // 0x40000
+    field public static final int CAPABILITY_GEOLOCATION_PUSH = 32768; // 0x8000
+    field public static final int CAPABILITY_GEOLOCATION_PUSH_SMS = 65536; // 0x10000
+    field public static final int CAPABILITY_IMAGE_SHARE = 256; // 0x100
+    field public static final int CAPABILITY_IP_VIDEO_CALL = 16384; // 0x4000
+    field public static final int CAPABILITY_IP_VOICE_CALL = 8192; // 0x2000
+    field public static final int CAPABILITY_MMTEL_CALL_COMPOSER = 1073741824; // 0x40000000
+    field public static final int CAPABILITY_PLUG_IN = 268435456; // 0x10000000
+    field public static final int CAPABILITY_POST_CALL = 8388608; // 0x800000
+    field public static final int CAPABILITY_RCS_VIDEO_CALL = 1048576; // 0x100000
+    field public static final int CAPABILITY_RCS_VIDEO_ONLY_CALL = 2097152; // 0x200000
+    field public static final int CAPABILITY_RCS_VOICE_CALL = 524288; // 0x80000
+    field public static final int CAPABILITY_SHARED_MAP = 16777216; // 0x1000000
+    field public static final int CAPABILITY_SHARED_SKETCH = 33554432; // 0x2000000
+    field public static final int CAPABILITY_SOCIAL_PRESENCE = 2048; // 0x800
+    field public static final int CAPABILITY_STANDALONE_CHAT_BOT = 536870912; // 0x20000000
+    field public static final int CAPABILITY_VIDEO_SHARE = 1024; // 0x400
+    field public static final int CAPABILITY_VIDEO_SHARE_DURING_CS_CALL = 512; // 0x200
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.RcsContactUceCapability> CREATOR;
+  }
+
+  public static class RcsContactUceCapability.Builder {
+    ctor public RcsContactUceCapability.Builder(@NonNull android.net.Uri);
+    method @NonNull public android.telephony.ims.RcsContactUceCapability.Builder add(long, @NonNull android.net.Uri);
+    method @NonNull public android.telephony.ims.RcsContactUceCapability.Builder add(long);
+    method @NonNull public android.telephony.ims.RcsContactUceCapability.Builder add(@NonNull String);
+    method @NonNull public android.telephony.ims.RcsContactUceCapability build();
+  }
+
+  public class RcsUceAdapter {
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getUcePublishState() throws android.telephony.ims.ImsException;
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isUceSettingEnabled() throws android.telephony.ims.ImsException;
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void requestCapabilities(@NonNull java.util.concurrent.Executor, @NonNull java.util.List<android.net.Uri>, @NonNull android.telephony.ims.RcsUceAdapter.CapabilitiesCallback) throws android.telephony.ims.ImsException;
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean) throws android.telephony.ims.ImsException;
+    field public static final int ERROR_ALREADY_IN_QUEUE = 13; // 0xd
+    field public static final int ERROR_FORBIDDEN = 6; // 0x6
+    field public static final int ERROR_GENERIC_FAILURE = 1; // 0x1
+    field public static final int ERROR_INSUFFICIENT_MEMORY = 11; // 0xb
+    field public static final int ERROR_LOST_NETWORK = 12; // 0xc
+    field public static final int ERROR_NOT_AUTHORIZED = 5; // 0x5
+    field public static final int ERROR_NOT_AVAILABLE = 3; // 0x3
+    field public static final int ERROR_NOT_ENABLED = 2; // 0x2
+    field public static final int ERROR_NOT_FOUND = 7; // 0x7
+    field public static final int ERROR_NOT_REGISTERED = 4; // 0x4
+    field public static final int ERROR_REQUEST_TIMEOUT = 10; // 0xa
+    field public static final int ERROR_REQUEST_TOO_LARGE = 8; // 0x8
+    field public static final int PUBLISH_STATE_200_OK = 1; // 0x1
+    field public static final int PUBLISH_STATE_NOT_PUBLISHED = 2; // 0x2
+    field public static final int PUBLISH_STATE_OTHER_ERROR = 6; // 0x6
+    field public static final int PUBLISH_STATE_RCS_PROVISION_ERROR = 4; // 0x4
+    field public static final int PUBLISH_STATE_REQUEST_TIMEOUT = 5; // 0x5
+    field public static final int PUBLISH_STATE_VOLTE_PROVISION_ERROR = 3; // 0x3
+  }
+
+  public static class RcsUceAdapter.CapabilitiesCallback {
+    ctor public RcsUceAdapter.CapabilitiesCallback();
+    method public void onCapabilitiesReceived(@NonNull java.util.List<android.telephony.ims.RcsContactUceCapability>);
+    method public void onError(int);
+  }
+
 }
 
 package android.telephony.ims.feature {
 
   public final class CapabilityChangeRequest implements android.os.Parcelable {
-    method public void addCapabilitiesToDisableForTech(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
-    method public void addCapabilitiesToEnableForTech(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
+    method public void addCapabilitiesToDisableForTech(int, int);
+    method public void addCapabilitiesToEnableForTech(int, int);
     method public int describeContents();
     method public java.util.List<android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair> getCapabilitiesToDisable();
     method public java.util.List<android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair> getCapabilitiesToEnable();
@@ -4115,8 +4275,8 @@
   }
 
   public static class CapabilityChangeRequest.CapabilityPair {
-    ctor public CapabilityChangeRequest.CapabilityPair(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
-    method @android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability public int getCapability();
+    ctor public CapabilityChangeRequest.CapabilityPair(int, int);
+    method public int getCapability();
     method public int getRadioTech();
   }
 
@@ -4161,10 +4321,10 @@
     method public final void notifyVoiceMessageCountUpdate(int);
     method public void onFeatureReady();
     method public void onFeatureRemoved();
-    method public boolean queryCapabilityConfiguration(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
+    method public boolean queryCapabilityConfiguration(int, int);
     method @NonNull public final android.telephony.ims.feature.MmTelFeature.MmTelCapabilities queryCapabilityStatus();
     method public void setUiTtyMode(int, @Nullable android.os.Message);
-    method @android.telephony.ims.feature.MmTelFeature.ProcessCallResult public int shouldProcessCall(@NonNull String[]);
+    method public int shouldProcessCall(@NonNull String[]);
     field public static final String EXTRA_IS_UNKNOWN_CALL = "android.telephony.ims.feature.extra.IS_UNKNOWN_CALL";
     field public static final String EXTRA_IS_USSD = "android.telephony.ims.feature.extra.IS_USSD";
     field public static final int PROCESS_CALL_CSFB = 1; // 0x1
@@ -4174,21 +4334,17 @@
   public static class MmTelFeature.MmTelCapabilities extends android.telephony.ims.feature.ImsFeature.Capabilities {
     ctor public MmTelFeature.MmTelCapabilities();
     ctor @Deprecated public MmTelFeature.MmTelCapabilities(android.telephony.ims.feature.ImsFeature.Capabilities);
-    ctor public MmTelFeature.MmTelCapabilities(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int);
-    method public final void addCapabilities(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int);
-    method public final boolean isCapable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int);
-    method public final void removeCapabilities(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int);
-  }
-
-  @IntDef(flag=true, value={android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO, android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT, android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_SMS}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface MmTelFeature.MmTelCapabilities.MmTelCapability {
-  }
-
-  @IntDef(flag=true, value={android.telephony.ims.feature.MmTelFeature.PROCESS_CALL_IMS, android.telephony.ims.feature.MmTelFeature.PROCESS_CALL_CSFB}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface MmTelFeature.ProcessCallResult {
+    ctor public MmTelFeature.MmTelCapabilities(int);
+    method public final void addCapabilities(int);
+    method public final boolean isCapable(int);
+    method public final void removeCapabilities(int);
   }
 
   public class RcsFeature extends android.telephony.ims.feature.ImsFeature {
     ctor public RcsFeature();
     method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+    method @NonNull public android.telephony.ims.stub.RcsSipOptionsImplBase getOptionsExchangeImpl();
+    method @NonNull public android.telephony.ims.stub.RcsPresenceExchangeImplBase getPresenceExchangeImpl();
     method public final void notifyCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.RcsFeature.RcsImsCapabilities);
     method public void onFeatureReady();
     method public void onFeatureRemoved();
@@ -4381,6 +4537,71 @@
     field public static final int INVALID_RESULT = -1; // 0xffffffff
   }
 
+  public class RcsCapabilityExchange {
+    ctor public RcsCapabilityExchange();
+    method public final void onCommandUpdate(int, int) throws android.telephony.ims.ImsException;
+    field public static final int COMMAND_CODE_FETCH_ERROR = 4; // 0x4
+    field public static final int COMMAND_CODE_GENERIC_FAILURE = 2; // 0x2
+    field public static final int COMMAND_CODE_INSUFFICIENT_MEMORY = 6; // 0x6
+    field public static final int COMMAND_CODE_INVALID_PARAM = 3; // 0x3
+    field public static final int COMMAND_CODE_LOST_NETWORK_CONNECTION = 7; // 0x7
+    field public static final int COMMAND_CODE_NOT_FOUND = 9; // 0x9
+    field public static final int COMMAND_CODE_NOT_SUPPORTED = 8; // 0x8
+    field public static final int COMMAND_CODE_NO_CHANGE_IN_CAP = 11; // 0xb
+    field public static final int COMMAND_CODE_REQUEST_TIMEOUT = 5; // 0x5
+    field public static final int COMMAND_CODE_SERVICE_UNAVAILABLE = 10; // 0xa
+    field public static final int COMMAND_CODE_SERVICE_UNKNOWN = 0; // 0x0
+    field public static final int COMMAND_CODE_SUCCESS = 1; // 0x1
+  }
+
+  public class RcsPresenceExchangeImplBase extends android.telephony.ims.stub.RcsCapabilityExchange {
+    ctor public RcsPresenceExchangeImplBase();
+    method public final void onCapabilityRequestResponse(@NonNull java.util.List<android.telephony.ims.RcsContactUceCapability>, int) throws android.telephony.ims.ImsException;
+    method public final void onNetworkResponse(int, @NonNull String, int) throws android.telephony.ims.ImsException;
+    method public final void onNotifyUpdateCapabilites(int) throws android.telephony.ims.ImsException;
+    method public final void onUnpublish() throws android.telephony.ims.ImsException;
+    method public void requestCapabilities(@NonNull java.util.List<android.net.Uri>, int);
+    method public void updateCapabilities(@NonNull android.telephony.ims.RcsContactUceCapability, int);
+    field public static final int CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED = 0; // 0x0
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G = 6; // 0x6
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G = 5; // 0x5
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD = 3; // 0x3
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS = 4; // 0x4
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN = 8; // 0x8
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED = 1; // 0x1
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED = 2; // 0x2
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED = 10; // 0xa
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED = 11; // 0xb
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN = 7; // 0x7
+    field public static final int CAPABILITY_UPDATE_TRIGGER_UNKNOWN = 9; // 0x9
+    field public static final int RESPONSE_FORBIDDEN = 3; // 0x3
+    field public static final int RESPONSE_NOT_AUTHORIZED_FOR_PRESENCE = 2; // 0x2
+    field public static final int RESPONSE_NOT_FOUND = 4; // 0x4
+    field public static final int RESPONSE_NOT_REGISTERED = 1; // 0x1
+    field public static final int RESPONSE_SIP_INTERVAL_TOO_SHORT = 7; // 0x7
+    field public static final int RESPONSE_SIP_REQUEST_TIMEOUT = 5; // 0x5
+    field public static final int RESPONSE_SIP_SERVICE_UNAVAILABLE = 8; // 0x8
+    field public static final int RESPONSE_SUBSCRIBE_GENERIC_FAILURE = -1; // 0xffffffff
+    field public static final int RESPONSE_SUBSCRIBE_TOO_LARGE = 6; // 0x6
+    field public static final int RESPONSE_SUCCESS = 0; // 0x0
+  }
+
+  public class RcsSipOptionsImplBase extends android.telephony.ims.stub.RcsCapabilityExchange {
+    ctor public RcsSipOptionsImplBase();
+    method public final void onCapabilityRequestResponse(int, @NonNull String, @Nullable android.telephony.ims.RcsContactUceCapability, int) throws android.telephony.ims.ImsException;
+    method public final void onRemoteCapabilityRequest(@NonNull android.net.Uri, @NonNull android.telephony.ims.RcsContactUceCapability, int) throws android.telephony.ims.ImsException;
+    method public void respondToCapabilityRequest(@NonNull String, @NonNull android.telephony.ims.RcsContactUceCapability, int);
+    method public void respondToCapabilityRequestWithError(@NonNull android.net.Uri, int, @NonNull String, int);
+    method public void sendCapabilityRequest(@NonNull android.net.Uri, @NonNull android.telephony.ims.RcsContactUceCapability, int);
+    field public static final int RESPONSE_BAD_REQUEST = 5; // 0x5
+    field public static final int RESPONSE_DOES_NOT_EXIST_ANYWHERE = 4; // 0x4
+    field public static final int RESPONSE_GENERIC_FAILURE = -1; // 0xffffffff
+    field public static final int RESPONSE_NOT_FOUND = 3; // 0x3
+    field public static final int RESPONSE_REQUEST_TIMEOUT = 2; // 0x2
+    field public static final int RESPONSE_SUCCESS = 0; // 0x0
+    field public static final int RESPONSE_TEMPORARILY_UNAVAILABLE = 1; // 0x1
+  }
+
 }
 
 package android.telephony.mbms {
diff --git a/api/test-lint-baseline.txt b/api/test-lint-baseline.txt
index 54f7f68..94db346 100644
--- a/api/test-lint-baseline.txt
+++ b/api/test-lint-baseline.txt
@@ -406,7 +406,13 @@
 GetterSetterNames: android.location.GnssClock#setFullBiasNanos(long):
     
 GetterSetterNames: android.location.GnssClock#setLeapSecond(int):
-    
+
+GetterSetterNames: android.location.GnssClock#setReferenceConstellationTypeForIsb(int):
+
+GetterSetterNames: android.location.GnssClock#setReferenceCarrierFrequencyHzForIsb(double):
+
+GetterSetterNames: android.location.GnssClock#setReferenceCodeTypeForIsb(String):
+
 GetterSetterNames: android.location.GnssClock#setTimeUncertaintyNanos(double):
     
 GetterSetterNames: android.location.GnssMeasurement#setBasebandCn0DbHz(double):
@@ -414,7 +420,15 @@
 GetterSetterNames: android.location.GnssMeasurement#setCarrierFrequencyHz(float):
     
 GetterSetterNames: android.location.GnssMeasurement#setCodeType(String):
-    
+
+GetterSetterNames: android.location.GnssMeasurement#setReceiverInterSignalBiasNanos(double):
+
+GetterSetterNames: android.location.GnssMeasurement#setReceiverInterSignalBiasUncertaintyNanos(double):
+
+GetterSetterNames: android.location.GnssMeasurement#setSatelliteInterSignalBiasNanos(double):
+
+GetterSetterNames: android.location.GnssMeasurement#setSatelliteInterSignalBiasUncertaintyNanos(double):
+
 GetterSetterNames: android.location.GnssMeasurement#setSnrInDb(double):
     
 GetterSetterNames: android.location.LocationRequest#isLocationSettingsIgnored():
@@ -2437,14 +2451,6 @@
     
 
 
-PublicTypedef: android.os.HwParcel.Status:
-    
-PublicTypedef: android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability:
-    
-PublicTypedef: android.telephony.ims.feature.MmTelFeature.ProcessCallResult:
-    
-
-
 RawAidl: android.telephony.mbms.vendor.MbmsDownloadServiceBase:
     
 RawAidl: android.telephony.mbms.vendor.MbmsStreamingServiceBase:
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 080b1af..ac24a55 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -50,7 +50,6 @@
 
     srcs: [
         ":statsd_aidl",
-        ":ICarStatsService.aidl",
         "src/active_config_list.proto",
         "src/anomaly/AlarmMonitor.cpp",
         "src/anomaly/AlarmTracker.cpp",
@@ -65,7 +64,6 @@
         "src/config/ConfigKey.cpp",
         "src/config/ConfigListener.cpp",
         "src/config/ConfigManager.cpp",
-        "src/external/CarStatsPuller.cpp",
         "src/external/GpuStatsPuller.cpp",
         "src/external/Perfetto.cpp",
         "src/external/PowerStatsPuller.cpp",
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index d05ac18..1fdc8af 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -78,9 +78,9 @@
     // Pushed atoms start at 2.
     oneof pushed {
         // For StatsLog reasons, 1 is illegal and will not work. Must start at 2.
-        BleScanStateChanged ble_scan_state_changed = 2;
+        BleScanStateChanged ble_scan_state_changed = 2 [(module) = "bluetooth"];
         ProcessStateChanged process_state_changed = 3;
-        BleScanResultReceived ble_scan_result_received = 4;
+        BleScanResultReceived ble_scan_result_received = 4 [(module) = "bluetooth"];
         SensorStateChanged sensor_state_changed = 5;
         GpsScanStateChanged gps_scan_state_changed = 6;
         SyncStateChanged sync_state_changed = 7;
@@ -137,22 +137,23 @@
         DaveyOccurred davey_occurred = 58 [(allow_from_any_uid) = true];
         OverlayStateChanged overlay_state_changed = 59;
         ForegroundServiceStateChanged foreground_service_state_changed = 60;
-        CallStateChanged call_state_changed = 61;
+        CallStateChanged call_state_changed = 61 [(module) = "telecom"];
         KeyguardStateChanged keyguard_state_changed = 62 [(module) = "sysui"];
         KeyguardBouncerStateChanged keyguard_bouncer_state_changed = 63 [(module) = "sysui"];
         KeyguardBouncerPasswordEntered keyguard_bouncer_password_entered = 64 [(module) = "sysui"];
         AppDied app_died = 65;
         ResourceConfigurationChanged resource_configuration_changed = 66;
         BluetoothEnabledStateChanged bluetooth_enabled_state_changed = 67;
-        BluetoothConnectionStateChanged bluetooth_connection_state_changed = 68;
+        BluetoothConnectionStateChanged bluetooth_connection_state_changed =
+                68 [(module) = "bluetooth"];
         GpsSignalQualityChanged gps_signal_quality_changed = 69;
         UsbConnectorStateChanged usb_connector_state_changed = 70;
         SpeakerImpedanceReported speaker_impedance_reported = 71;
         HardwareFailed hardware_failed = 72;
         PhysicalDropDetected physical_drop_detected = 73;
         ChargeCyclesReported charge_cycles_reported = 74;
-        MobileConnectionStateChanged mobile_connection_state_changed = 75;
-        MobileRadioTechnologyChanged mobile_radio_technology_changed = 76;
+        MobileConnectionStateChanged mobile_connection_state_changed = 75 [(module) = "telephony"];
+        MobileRadioTechnologyChanged mobile_radio_technology_changed = 76 [(module) = "telephony"];
         UsbDeviceAttached usb_device_attached = 77;
         AppCrashOccurred app_crash_occurred = 78;
         ANROccurred anr_occurred = 79;
@@ -207,9 +208,12 @@
         RescuePartyResetReported rescue_party_reset_reported = 122;
         SignedConfigReported signed_config_reported = 123;
         GnssNiEventReported gnss_ni_event_reported = 124;
-        BluetoothLinkLayerConnectionEvent bluetooth_link_layer_connection_event = 125;
-        BluetoothAclConnectionStateChanged bluetooth_acl_connection_state_changed = 126;
-        BluetoothScoConnectionStateChanged bluetooth_sco_connection_state_changed = 127;
+        BluetoothLinkLayerConnectionEvent bluetooth_link_layer_connection_event =
+                125 [(module) = "bluetooth"];
+        BluetoothAclConnectionStateChanged bluetooth_acl_connection_state_changed =
+                126 [(module) = "bluetooth"];
+        BluetoothScoConnectionStateChanged bluetooth_sco_connection_state_changed =
+                127 [(module) = "bluetooth"];
         AppDowngraded app_downgraded = 128;
         AppOptimizedAfterDowngraded app_optimized_after_downgraded = 129;
         LowStorageStateChanged low_storage_state_changed = 130;
@@ -233,33 +237,51 @@
         BiometricSystemHealthIssueDetected biometric_system_health_issue_detected = 148;
         BubbleUIChanged bubble_ui_changed = 149 [(module) = "sysui"];
         ScheduledJobConstraintChanged scheduled_job_constraint_changed = 150;
-        BluetoothActiveDeviceChanged bluetooth_active_device_changed = 151;
-        BluetoothA2dpPlaybackStateChanged bluetooth_a2dp_playback_state_changed = 152;
-        BluetoothA2dpCodecConfigChanged bluetooth_a2dp_codec_config_changed = 153;
-        BluetoothA2dpCodecCapabilityChanged bluetooth_a2dp_codec_capability_changed = 154;
-        BluetoothA2dpAudioUnderrunReported bluetooth_a2dp_audio_underrun_reported = 155;
-        BluetoothA2dpAudioOverrunReported bluetooth_a2dp_audio_overrun_reported = 156;
-        BluetoothDeviceRssiReported bluetooth_device_rssi_reported = 157;
-        BluetoothDeviceFailedContactCounterReported bluetooth_device_failed_contact_counter_reported = 158;
-        BluetoothDeviceTxPowerLevelReported bluetooth_device_tx_power_level_reported = 159;
-        BluetoothHciTimeoutReported bluetooth_hci_timeout_reported = 160;
-        BluetoothQualityReportReported bluetooth_quality_report_reported = 161;
-        BluetoothDeviceInfoReported bluetooth_device_info_reported = 162;
-        BluetoothRemoteVersionInfoReported bluetooth_remote_version_info_reported = 163;
-        BluetoothSdpAttributeReported bluetooth_sdp_attribute_reported = 164;
-        BluetoothBondStateChanged bluetooth_bond_state_changed = 165;
-        BluetoothClassicPairingEventReported bluetooth_classic_pairing_event_reported = 166;
-        BluetoothSmpPairingEventReported bluetooth_smp_pairing_event_reported = 167;
+        BluetoothActiveDeviceChanged bluetooth_active_device_changed =
+                151 [(module) = "bluetooth"];
+        BluetoothA2dpPlaybackStateChanged bluetooth_a2dp_playback_state_changed =
+                152 [(module) = "bluetooth"];
+        BluetoothA2dpCodecConfigChanged bluetooth_a2dp_codec_config_changed =
+                153 [(module) = "bluetooth"];
+        BluetoothA2dpCodecCapabilityChanged bluetooth_a2dp_codec_capability_changed =
+                154 [(module) = "bluetooth"];
+        BluetoothA2dpAudioUnderrunReported bluetooth_a2dp_audio_underrun_reported =
+                155 [(module) = "bluetooth"];
+        BluetoothA2dpAudioOverrunReported bluetooth_a2dp_audio_overrun_reported =
+                156 [(module) = "bluetooth"];
+        BluetoothDeviceRssiReported bluetooth_device_rssi_reported =
+                157 [(module) = "bluetooth"];
+        BluetoothDeviceFailedContactCounterReported
+                bluetooth_device_failed_contact_counter_reported = 158 [(module) = "bluetooth"];
+        BluetoothDeviceTxPowerLevelReported bluetooth_device_tx_power_level_reported =
+                159 [(module) = "bluetooth"];
+        BluetoothHciTimeoutReported bluetooth_hci_timeout_reported =
+                160 [(module) = "bluetooth"];
+        BluetoothQualityReportReported bluetooth_quality_report_reported =
+                161 [(module) = "bluetooth"];
+        BluetoothDeviceInfoReported bluetooth_device_info_reported =
+                162 [(module) = "bluetooth"];
+        BluetoothRemoteVersionInfoReported bluetooth_remote_version_info_reported =
+                163 [(module) = "bluetooth"];
+        BluetoothSdpAttributeReported bluetooth_sdp_attribute_reported =
+                164 [(module) = "bluetooth"];
+        BluetoothBondStateChanged bluetooth_bond_state_changed =
+                165 [(module) = "bluetooth"];
+        BluetoothClassicPairingEventReported bluetooth_classic_pairing_event_reported =
+                166 [(module) = "bluetooth"];
+        BluetoothSmpPairingEventReported bluetooth_smp_pairing_event_reported =
+                167 [(module) = "bluetooth"];
         ScreenTimeoutExtensionReported screen_timeout_extension_reported = 168;
         ProcessStartTime process_start_time = 169;
         PermissionGrantRequestResultReported permission_grant_request_result_reported =
             170 [(module) = "permissioncontroller"];
         BluetoothSocketConnectionStateChanged bluetooth_socket_connection_state_changed = 171;
-        DeviceIdentifierAccessDenied device_identifier_access_denied = 172;
+        DeviceIdentifierAccessDenied device_identifier_access_denied =
+                172 [(module) = "telephony_common"];
         BubbleDeveloperErrorReported bubble_developer_error_reported = 173;
-        AssistGestureStageReported assist_gesture_stage_reported = 174;
-        AssistGestureFeedbackReported assist_gesture_feedback_reported = 175;
-        AssistGestureProgressReported assist_gesture_progress_reported = 176;
+        AssistGestureStageReported assist_gesture_stage_reported = 174 [(module) = "sysui"];
+        AssistGestureFeedbackReported assist_gesture_feedback_reported = 175 [(module) = "sysui"];
+        AssistGestureProgressReported assist_gesture_progress_reported = 176 [(module) = "sysui"];
         TouchGestureClassified touch_gesture_classified = 177;
         HiddenApiUsed hidden_api_used = 178 [(allow_from_any_uid) = true];
         StyleUIChanged style_ui_changed = 179 [(module) = "sysui"];
@@ -271,7 +293,8 @@
         BiometricEnrolled biometric_enrolled = 184;
         SystemServerWatchdogOccurred system_server_watchdog_occurred = 185;
         TombStoneOccurred tomb_stone_occurred = 186;
-        BluetoothClassOfDeviceReported bluetooth_class_of_device_reported = 187;
+        BluetoothClassOfDeviceReported bluetooth_class_of_device_reported =
+                187 [(module) = "bluetooth"];
         IntelligenceEventReported intelligence_event_reported =
             188 [(module) = "intelligence"];
         ThermalThrottlingSeverityStateChanged thermal_throttling_severity_state_changed = 189;
@@ -288,8 +311,8 @@
         MediametricsNuPlayerReported mediametrics_nuplayer_reported = 199;
         MediametricsRecorderReported mediametrics_recorder_reported = 200;
         MediametricsDrmManagerReported mediametrics_drmmanager_reported = 201;
-        CarPowerStateChanged car_power_state_changed = 203;
-        GarageModeInfo garage_mode_info = 204;
+        CarPowerStateChanged car_power_state_changed = 203 [(module) = "car"];
+        GarageModeInfo garage_mode_info = 204 [(module) = "car"];
         TestAtomReported test_atom_reported = 205 [(module) = "cts"];
         ContentCaptureCallerMismatchReported content_capture_caller_mismatch_reported = 206;
         ContentCaptureServiceEvents content_capture_service_events = 207;
@@ -324,7 +347,8 @@
         AppCompatibilityChangeReported app_compatibility_change_reported =
             228 [(allow_from_any_uid) = true];
         PerfettoUploaded perfetto_uploaded = 229 [(module) = "perfetto"];
-        VmsClientConnectionStateChanged vms_client_connection_state_changed = 230;
+        VmsClientConnectionStateChanged vms_client_connection_state_changed =
+                230 [(module) = "car"];
         MediaProviderScanEvent media_provider_scan_event = 233 [(module) = "mediaprovider"];
         MediaProviderDeletionEvent media_provider_deletion_event = 234 [(module) = "mediaprovider"];
         MediaProviderPermissionEvent media_provider_permission_event =
@@ -341,6 +365,12 @@
         NotificationReported notification_reported = 244;
         NotificationPanelReported notification_panel_reported = 245;
         NotificationChannelModified notification_panel_modified = 246;
+        IntegrityCheckResultReported integrity_check_result_reported = 247;
+        IntegrityRulesPushed integrity_rules_pushed = 248;
+        CellBroadcastMessageReported cb_message_reported =
+            249 [(module) = "cellbroadcast"];
+        CellBroadcastMessageError cb_message_error =
+            250 [(module) = "cellbroadcast"];
     }
 
     // Pulled events will start at field 10000.
@@ -410,7 +440,7 @@
         SurfaceflingerStatsGlobalInfo surfaceflinger_stats_global_info = 10062;
         SurfaceflingerStatsLayerInfo surfaceflinger_stats_layer_info = 10063;
         ProcessMemorySnapshot process_memory_snapshot = 10064;
-        VmsClientStats vms_client_stats = 10065;
+        VmsClientStats vms_client_stats = 10065 [(module) = "car"];
         NotificationRemoteViews notification_remote_views = 10066;
         DangerousPermissionStateSampled dangerous_permission_state_sampled = 10067;
         GraphicsStats graphics_stats = 10068;
@@ -1724,6 +1754,7 @@
         REASON_EXPLICIT_HEALTH_CHECK = 2;
         REASON_APP_CRASH = 3;
         REASON_APP_NOT_RESPONDING = 4;
+        REASON_NATIVE_CRASH_DURING_BOOT = 5;
     }
     optional RollbackReasonType rollback_reason = 4;
 
@@ -8069,3 +8100,95 @@
     // State of primary user's encryption storage at the moment boot completed. Always set.
     optional UserEncryptionState user_encryption_state = 3;
 }
+
+/*
+ * Logs integrity check information during each install.
+ *
+ * Logged from:
+ *   frameworks/base/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
+ */
+message IntegrityCheckResultReported {
+    optional string package_name = 1;
+    optional string app_certificate_hash = 2;
+    optional int64 version_code = 3;
+    optional string installer_package_name = 4;
+    enum Response {
+        UNKNOWN = 0;
+        ALLOWED = 1;
+        REJECTED = 2;
+        FORCE_ALLOWED = 3;
+    }
+    optional Response response = 5;
+    // An estimate on the cause of the response. This will only be populated for
+    // REJECTED and FORCE_ALLOWED
+    optional bool caused_by_app_cert_rule = 6;
+    optional bool caused_by_installer_rule = 7;
+}
+
+/**
+ * Logs the information about the rules and the provider whenever rules are
+ * pushed into AppIntegrityManager.
+ *
+ * Logged from:
+ *   frameworks/base/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
+ */
+message IntegrityRulesPushed {
+    optional bool success = 1;
+    // Package name of the app that pushed the rules.
+    optional string rule_provider = 2;
+    // Version string of arbitrary format provided by the rule provider to
+    // identify the rules.
+    optional string rule_version = 3;
+}
+
+/**
+ * Logs when a cell broadcast message is received on the device.
+ *
+ * Logged from CellBroadcastService module:
+ *   packages/modules/CellBroadcastService/src/com/android/cellbroadcastservice/
+ */
+message CellBroadcastMessageReported {
+    // The type of Cell Broadcast message
+    enum CbType {
+        UNKNOWN_TYPE = 0;
+        GSM = 1;
+        CDMA = 2;
+        CDMA_SPC = 3;
+    }
+
+    // GSM, CDMA, CDMA-SCP
+    optional CbType type = 1;
+}
+
+/**
+ * Logs when an error occurs while handling a cell broadcast message;
+ *
+ * Logged from CellBroadcastService module:
+ *   packages/modules/CellBroadcastService/src/com/android/cellbroadcastservice/
+ */
+message CellBroadcastMessageError {
+    // The type of error raised when trying to handle a cell broadcast message
+    enum ErrorType {
+        UNKNOWN_TYPE = 0;
+        CDMA_DECODING_ERROR = 1;
+        CDMA_SCP_EMPTY = 2;
+        CDMA_SCP_HANDLING_ERROR = 3;
+        GSM_INVALID_HEADER_LENGTH = 4;
+        GSM_UNSUPPORTED_HEADER_MESSAGE_TYPE = 5;
+        GSM_UNSUPPORTED_HEADER_DATA_CODING_SCHEME = 6;
+        GSM_INVALID_PDU = 7;
+        GSM_INVALID_GEO_FENCING_DATA = 8;
+        GSM_UMTS_INVALID_WAC = 9;
+        FAILED_TO_INSERT_TO_DB = 10;
+        UNEXPECTED_GEOMETRY_FROM_FWK = 11;
+        UNEXPECTED_GSM_MESSAGE_TYPE_FROM_FWK = 12;
+        UNEXPECTED_CDMA_MESSAGE_TYPE_FROM_FWK = 13;
+        UNEXPECTED_CDMA_SCP_MESSAGE_TYPE_FROM_FWK = 14;
+    }
+
+    // What kind of error occurred
+    optional ErrorType type = 1;
+
+    // Exception message (or log message) associated with the error (max 1000 chars)
+    optional string exception_message = 2;
+}
diff --git a/cmds/statsd/src/external/CarStatsPuller.cpp b/cmds/statsd/src/external/CarStatsPuller.cpp
deleted file mode 100644
index 70c0456..0000000
--- a/cmds/statsd/src/external/CarStatsPuller.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define DEBUG false
-#include "Log.h"
-
-#include <binder/IServiceManager.h>
-#include <com/android/internal/car/ICarStatsService.h>
-
-#include "CarStatsPuller.h"
-#include "logd/LogEvent.h"
-#include "stats_log_util.h"
-
-using android::binder::Status;
-using com::android::internal::car::ICarStatsService;
-
-namespace android {
-namespace os {
-namespace statsd {
-
-static std::mutex gCarStatsMutex;
-static sp<ICarStatsService> gCarStats = nullptr;
-
-class CarStatsDeathRecipient : public android::IBinder::DeathRecipient {
- public:
-     CarStatsDeathRecipient() = default;
-     ~CarStatsDeathRecipient() override = default;
-
-  // android::IBinder::DeathRecipient override:
-  void binderDied(const android::wp<android::IBinder>& /* who */) override {
-      ALOGE("Car service has died");
-      std::lock_guard<std::mutex> lock(gCarStatsMutex);
-      if (gCarStats) {
-          sp<IBinder> binder = IInterface::asBinder(gCarStats);
-          binder->unlinkToDeath(this);
-          gCarStats = nullptr;
-      }
-  }
-};
-
-static sp<CarStatsDeathRecipient> gDeathRecipient = new CarStatsDeathRecipient();
-
-static sp<ICarStatsService> getCarService() {
-    std::lock_guard<std::mutex> lock(gCarStatsMutex);
-    if (!gCarStats) {
-        const sp<IBinder> binder = defaultServiceManager()->checkService(String16("car_stats"));
-        if (!binder) {
-            ALOGW("Car service is unavailable");
-            return nullptr;
-        }
-        gCarStats = interface_cast<ICarStatsService>(binder);
-        binder->linkToDeath(gDeathRecipient);
-    }
-    return gCarStats;
-}
-
-CarStatsPuller::CarStatsPuller(const int tagId) : StatsPuller(tagId) {
-}
-
-bool CarStatsPuller::PullInternal(std::vector<std::shared_ptr<LogEvent>>* data) {
-    const sp<ICarStatsService> carService = getCarService();
-    if (!carService) {
-        return false;
-    }
-
-    vector<StatsLogEventWrapper> returned_value;
-    Status status = carService->pullData(mTagId, &returned_value);
-    if (!status.isOk()) {
-        ALOGW("CarStatsPuller::pull failed for %d", mTagId);
-        return false;
-    }
-
-    data->clear();
-    for (const StatsLogEventWrapper& it : returned_value) {
-        LogEvent::createLogEvents(it, *data);
-    }
-    VLOG("CarStatsPuller::pull succeeded for %d", mTagId);
-    return true;
-}
-
-}  // namespace statsd
-}  // namespace os
-}  // namespace android
diff --git a/cmds/statsd/src/external/CarStatsPuller.h b/cmds/statsd/src/external/CarStatsPuller.h
deleted file mode 100644
index ca0f1a9..0000000
--- a/cmds/statsd/src/external/CarStatsPuller.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include "StatsPuller.h"
-
-namespace android {
-namespace os {
-namespace statsd {
-
-/**
- * Pull atoms from CarService.
- */
-class CarStatsPuller : public StatsPuller {
-public:
-    explicit CarStatsPuller(const int tagId);
-    bool PullInternal(std::vector<std::shared_ptr<LogEvent>>* data) override;
-};
-
-}  // namespace statsd
-}  // namespace os
-}  // namespace android
diff --git a/cmds/statsd/src/external/Perfetto.h b/cmds/statsd/src/external/Perfetto.h
index ab2c195..095782a 100644
--- a/cmds/statsd/src/external/Perfetto.h
+++ b/cmds/statsd/src/external/Perfetto.h
@@ -16,10 +16,6 @@
 
 #pragma once
 
-#include <android/os/StatsLogEventWrapper.h>
-
-using android::os::StatsLogEventWrapper;
-
 namespace android {
 namespace os {
 namespace statsd {
diff --git a/cmds/statsd/src/external/StatsCallbackPuller.cpp b/cmds/statsd/src/external/StatsCallbackPuller.cpp
index e5a83a2..6257771 100644
--- a/cmds/statsd/src/external/StatsCallbackPuller.cpp
+++ b/cmds/statsd/src/external/StatsCallbackPuller.cpp
@@ -36,8 +36,9 @@
 namespace statsd {
 
 StatsCallbackPuller::StatsCallbackPuller(int tagId, const sp<IPullAtomCallback>& callback,
-                                         int64_t timeoutNs)
-    : StatsPuller(tagId), mCallback(callback), mTimeoutNs(timeoutNs) {
+                                         const int64_t coolDownNs, int64_t timeoutNs,
+                                         const vector<int> additiveFields)
+    : StatsPuller(tagId, coolDownNs, timeoutNs, additiveFields), mCallback(callback) {
     VLOG("StatsCallbackPuller created for tag %d", tagId);
 }
 
@@ -86,7 +87,7 @@
     {
         unique_lock<mutex> unique_lk(*cv_mutex);
         // Wait until the pull finishes, or until the pull timeout.
-        cv->wait_for(unique_lk, chrono::nanoseconds(mTimeoutNs),
+        cv->wait_for(unique_lk, chrono::nanoseconds(mPullTimeoutNs),
                      [pullFinish] { return *pullFinish; });
         if (!*pullFinish) {
             // Note: The parent stats puller will also note that there was a timeout and that the
diff --git a/cmds/statsd/src/external/StatsCallbackPuller.h b/cmds/statsd/src/external/StatsCallbackPuller.h
index d943f9d..ac88524 100644
--- a/cmds/statsd/src/external/StatsCallbackPuller.h
+++ b/cmds/statsd/src/external/StatsCallbackPuller.h
@@ -28,12 +28,12 @@
 class StatsCallbackPuller : public StatsPuller {
 public:
     explicit StatsCallbackPuller(int tagId, const sp<IPullAtomCallback>& callback,
-                                 int64_t timeoutNs);
+                                 const int64_t coolDownNs, const int64_t timeoutNs,
+                                 const std::vector<int> additiveFields);
 
 private:
     bool PullInternal(vector<std::shared_ptr<LogEvent> >* data) override;
     const sp<IPullAtomCallback> mCallback;
-    const int64_t mTimeoutNs;
 
     FRIEND_TEST(StatsCallbackPullerTest, PullFail);
     FRIEND_TEST(StatsCallbackPullerTest, PullSuccess);
diff --git a/cmds/statsd/src/external/StatsPuller.cpp b/cmds/statsd/src/external/StatsPuller.cpp
index 883bd28..5192ddf 100644
--- a/cmds/statsd/src/external/StatsPuller.cpp
+++ b/cmds/statsd/src/external/StatsPuller.cpp
@@ -32,17 +32,20 @@
 sp<UidMap> StatsPuller::mUidMap = nullptr;
 void StatsPuller::SetUidMap(const sp<UidMap>& uidMap) { mUidMap = uidMap; }
 
-StatsPuller::StatsPuller(const int tagId)
-    : mTagId(tagId), mLastPullTimeNs(0) {
+StatsPuller::StatsPuller(const int tagId, const int64_t coolDownNs, const int64_t pullTimeoutNs,
+                         const std::vector<int> additiveFields)
+    : mTagId(tagId),
+      mPullTimeoutNs(pullTimeoutNs),
+      mCoolDownNs(coolDownNs),
+      mAdditiveFields(additiveFields),
+      mLastPullTimeNs(0) {
 }
 
 bool StatsPuller::Pull(std::vector<std::shared_ptr<LogEvent>>* data) {
     lock_guard<std::mutex> lock(mLock);
     int64_t elapsedTimeNs = getElapsedRealtimeNs();
     StatsdStats::getInstance().notePull(mTagId);
-    const bool shouldUseCache =
-            elapsedTimeNs - mLastPullTimeNs <
-            StatsPullerManager::kAllPullAtomInfo.at({.atomTag = mTagId}).coolDownNs;
+    const bool shouldUseCache = elapsedTimeNs - mLastPullTimeNs < mCoolDownNs;
     if (shouldUseCache) {
         if (mHasGoodData) {
             (*data) = mCachedData;
@@ -64,9 +67,7 @@
     }
     const int64_t pullDurationNs = getElapsedRealtimeNs() - elapsedTimeNs;
     StatsdStats::getInstance().notePullTime(mTagId, pullDurationNs);
-    const bool pullTimeOut =
-            pullDurationNs >
-            StatsPullerManager::kAllPullAtomInfo.at({.atomTag = mTagId}).pullTimeoutNs;
+    const bool pullTimeOut = pullDurationNs > mPullTimeoutNs;
     if (pullTimeOut) {
         // Something went wrong. Discard the data.
         clearCacheLocked();
@@ -78,7 +79,7 @@
     }
 
     if (mCachedData.size() > 0) {
-        mapAndMergeIsolatedUidsToHostUid(mCachedData, mUidMap, mTagId);
+        mapAndMergeIsolatedUidsToHostUid(mCachedData, mUidMap, mTagId, mAdditiveFields);
     }
 
     (*data) = mCachedData;
@@ -102,8 +103,7 @@
 }
 
 int StatsPuller::ClearCacheIfNecessary(int64_t timestampNs) {
-    if (timestampNs - mLastPullTimeNs >
-        StatsPullerManager::kAllPullAtomInfo.at({.atomTag = mTagId}).coolDownNs) {
+    if (timestampNs - mLastPullTimeNs > mCoolDownNs) {
         return clearCache();
     } else {
         return 0;
diff --git a/cmds/statsd/src/external/StatsPuller.h b/cmds/statsd/src/external/StatsPuller.h
index c83c4f8..9c21695 100644
--- a/cmds/statsd/src/external/StatsPuller.h
+++ b/cmds/statsd/src/external/StatsPuller.h
@@ -32,7 +32,10 @@
 
 class StatsPuller : public virtual RefBase {
 public:
-    explicit StatsPuller(const int tagId);
+    explicit StatsPuller(const int tagId,
+                         const int64_t coolDownNs = NS_PER_SEC,
+                         const int64_t pullTimeoutNs = StatsdStats::kPullMaxDelayNs,
+                         const std::vector<int> additiveFields = std::vector<int>());
 
     virtual ~StatsPuller() {}
 
@@ -60,6 +63,12 @@
 protected:
     const int mTagId;
 
+    // Max time allowed to pull this atom.
+    // We cannot reliably kill a pull thread. So we don't terminate the puller.
+    // The data is discarded if the pull takes longer than this and mHasGoodData
+    // marked as false.
+    const int64_t mPullTimeoutNs = StatsdStats::kPullMaxDelayNs;
+
 private:
     mutable std::mutex mLock;
 
@@ -68,6 +77,17 @@
 
     bool mHasGoodData = false;
 
+    // Minimum time before this puller does actual pull again.
+    // Pullers can cause significant impact to system health and battery.
+    // So that we don't pull too frequently.
+    // If a pull request comes before cooldown, a cached version from previous pull
+    // will be returned.
+    const int64_t mCoolDownNs = 1 * NS_PER_SEC;
+
+    // The field numbers of the fields that need to be summed when merging
+    // isolated uid with host uid.
+    const std::vector<int> mAdditiveFields;
+
     int64_t mLastPullTimeNs;
 
     // Cache of data from last pull. If next request comes before cool down finishes,
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 8d67b5c..85d1e38 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -32,7 +32,6 @@
 #include "../logd/LogEvent.h"
 #include "../stats_log_util.h"
 #include "../statscompanion_util.h"
-#include "CarStatsPuller.h"
 #include "GpuStatsPuller.h"
 #include "PowerStatsPuller.h"
 #include "ResourceHealthManagerPuller.h"
@@ -55,54 +54,47 @@
 // Values smaller than this may require to update the alarm.
 const int64_t NO_ALARM_UPDATE = INT64_MAX;
 
-std::map<PullerKey, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = {
+StatsPullerManager::StatsPullerManager()
+    : kAllPullAtomInfo({
+              // subsystem_sleep_state
+              {{.atomTag = android::util::SUBSYSTEM_SLEEP_STATE}, new SubsystemSleepStatePuller()},
 
-        // subsystem_sleep_state
-        {{.atomTag = android::util::SUBSYSTEM_SLEEP_STATE},
-         {.puller = new SubsystemSleepStatePuller()}},
+              // on_device_power_measurement
+              {{.atomTag = android::util::ON_DEVICE_POWER_MEASUREMENT}, new PowerStatsPuller()},
 
-        // on_device_power_measurement
-        {{.atomTag = android::util::ON_DEVICE_POWER_MEASUREMENT},
-         {.puller = new PowerStatsPuller()}},
+              // remaining_battery_capacity
+              {{.atomTag = android::util::REMAINING_BATTERY_CAPACITY},
+               new ResourceHealthManagerPuller(android::util::REMAINING_BATTERY_CAPACITY)},
 
-        // remaining_battery_capacity
-        {{.atomTag = android::util::REMAINING_BATTERY_CAPACITY},
-         {.puller = new ResourceHealthManagerPuller(android::util::REMAINING_BATTERY_CAPACITY)}},
+              // full_battery_capacity
+              {{.atomTag = android::util::FULL_BATTERY_CAPACITY},
+               new ResourceHealthManagerPuller(android::util::FULL_BATTERY_CAPACITY)},
 
-        // full_battery_capacity
-        {{.atomTag = android::util::FULL_BATTERY_CAPACITY},
-         {.puller = new ResourceHealthManagerPuller(android::util::FULL_BATTERY_CAPACITY)}},
+              // battery_voltage
+              {{.atomTag = android::util::BATTERY_VOLTAGE},
+               new ResourceHealthManagerPuller(android::util::BATTERY_VOLTAGE)},
 
-        // battery_voltage
-        {{.atomTag = android::util::BATTERY_VOLTAGE},
-         {.puller = new ResourceHealthManagerPuller(android::util::BATTERY_VOLTAGE)}},
+              // battery_level
+              {{.atomTag = android::util::BATTERY_LEVEL},
+               new ResourceHealthManagerPuller(android::util::BATTERY_LEVEL)},
 
-        // battery_level
-        {{.atomTag = android::util::BATTERY_LEVEL},
-         {.puller = new ResourceHealthManagerPuller(android::util::BATTERY_LEVEL)}},
+              // battery_cycle_count
+              {{.atomTag = android::util::BATTERY_CYCLE_COUNT},
+               new ResourceHealthManagerPuller(android::util::BATTERY_CYCLE_COUNT)},
 
-        // battery_cycle_count
-        {{.atomTag = android::util::BATTERY_CYCLE_COUNT},
-         {.puller = new ResourceHealthManagerPuller(android::util::BATTERY_CYCLE_COUNT)}},
+              // TrainInfo.
+              {{.atomTag = android::util::TRAIN_INFO}, new TrainInfoPuller()},
 
-        // TrainInfo.
-        {{.atomTag = android::util::TRAIN_INFO}, {.puller = new TrainInfoPuller()}},
+              // GpuStatsGlobalInfo
+              {{.atomTag = android::util::GPU_STATS_GLOBAL_INFO},
+               new GpuStatsPuller(android::util::GPU_STATS_GLOBAL_INFO)},
 
-        // GpuStatsGlobalInfo
-        {{.atomTag = android::util::GPU_STATS_GLOBAL_INFO},
-         {.puller = new GpuStatsPuller(android::util::GPU_STATS_GLOBAL_INFO)}},
+              // GpuStatsAppInfo
+              {{.atomTag = android::util::GPU_STATS_APP_INFO},
+               new GpuStatsPuller(android::util::GPU_STATS_APP_INFO)},
 
-        // GpuStatsAppInfo
-        {{.atomTag = android::util::GPU_STATS_APP_INFO},
-         {.puller = new GpuStatsPuller(android::util::GPU_STATS_APP_INFO)}},
-
-        // VmsClientStats
-        {{.atomTag = android::util::VMS_CLIENT_STATS},
-         {.additiveFields = {5, 6, 7, 8, 9, 10},
-          .puller = new CarStatsPuller(android::util::VMS_CLIENT_STATS)}},
-};
-
-StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
+      }),
+      mNextPullTimeNs(NO_ALARM_UPDATE) {
 }
 
 bool StatsPullerManager::Pull(int tagId, vector<shared_ptr<LogEvent>>* data) {
@@ -114,7 +106,7 @@
     VLOG("Initiating pulling %d", tagId);
 
     if (kAllPullAtomInfo.find({.atomTag = tagId}) != kAllPullAtomInfo.end()) {
-        bool ret = kAllPullAtomInfo.find({.atomTag = tagId})->second.puller->Pull(data);
+        bool ret = kAllPullAtomInfo.find({.atomTag = tagId})->second->Pull(data);
         VLOG("pulled %d items", (int)data->size());
         if (!ret) {
             StatsdStats::getInstance().notePullFailed(tagId);
@@ -127,9 +119,9 @@
 }
 
 bool StatsPullerManager::PullerForMatcherExists(int tagId) const {
-    // Vendor pulled atoms might be registered after we parse the config.
-    return isVendorPulledAtom(tagId) ||
-           kAllPullAtomInfo.find({.atomTag = tagId}) != kAllPullAtomInfo.end();
+    // Pulled atoms might be registered after we parse the config, so just make sure the id is in
+    // an appropriate range.
+    return isVendorPulledAtom(tagId) || isPulledAtom(tagId);
 }
 
 void StatsPullerManager::updateAlarmLocked() {
@@ -153,7 +145,7 @@
     sp<IStatsCompanionService> tmpForLock = mStatsCompanionService;
     mStatsCompanionService = statsCompanionService;
     for (const auto& pulledAtom : kAllPullAtomInfo) {
-        pulledAtom.second.puller->SetStatsCompanionService(statsCompanionService);
+        pulledAtom.second->SetStatsCompanionService(statsCompanionService);
     }
     if (mStatsCompanionService != nullptr) {
         updateAlarmLocked();
@@ -285,7 +277,7 @@
 int StatsPullerManager::ForceClearPullerCache() {
     int totalCleared = 0;
     for (const auto& pulledAtom : kAllPullAtomInfo) {
-        totalCleared += pulledAtom.second.puller->ForceClearCache();
+        totalCleared += pulledAtom.second->ForceClearCache();
     }
     return totalCleared;
 }
@@ -293,7 +285,7 @@
 int StatsPullerManager::ClearPullerCacheIfNecessary(int64_t timestampNs) {
     int totalCleared = 0;
     for (const auto& pulledAtom : kAllPullAtomInfo) {
-        totalCleared += pulledAtom.second.puller->ClearCacheIfNecessary(timestampNs);
+        totalCleared += pulledAtom.second->ClearCacheIfNecessary(timestampNs);
     }
     return totalCleared;
 }
@@ -306,12 +298,8 @@
     VLOG("RegisterPullerCallback: adding puller for tag %d", atomTag);
     // TODO: linkToDeath with the callback so that we can remove it and delete the puller.
     StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag, /*registered=*/true);
-    kAllPullAtomInfo[{.atomTag = atomTag}] = {
-            .additiveFields = additiveFields,
-            .coolDownNs = coolDownNs,
-            .puller = new StatsCallbackPuller(atomTag, callback, timeoutNs),
-            .pullTimeoutNs = timeoutNs,
-    };
+    kAllPullAtomInfo[{.atomTag = atomTag}] =
+            new StatsCallbackPuller(atomTag, callback, coolDownNs, timeoutNs, additiveFields);
 }
 
 void StatsPullerManager::UnregisterPullAtomCallback(const int uid, const int32_t atomTag) {
diff --git a/cmds/statsd/src/external/StatsPullerManager.h b/cmds/statsd/src/external/StatsPullerManager.h
index 4b6ab57..f5d6057 100644
--- a/cmds/statsd/src/external/StatsPullerManager.h
+++ b/cmds/statsd/src/external/StatsPullerManager.h
@@ -36,24 +36,6 @@
 namespace os {
 namespace statsd {
 
-typedef struct {
-    // The field numbers of the fields that need to be summed when merging
-    // isolated uid with host uid.
-    std::vector<int> additiveFields;
-    // Minimum time before this puller does actual pull again.
-    // Pullers can cause significant impact to system health and battery.
-    // So that we don't pull too frequently.
-    // If a pull request comes before cooldown, a cached version from previous pull
-    // will be returned.
-    int64_t coolDownNs = 1 * NS_PER_SEC;
-    // The actual puller
-    sp<StatsPuller> puller;
-    // Max time allowed to pull this atom.
-    // We cannot reliably kill a pull thread. So we don't terminate the puller.
-    // The data is discarded if the pull takes longer than this and mHasGoodData
-    // marked as false.
-    int64_t pullTimeoutNs = StatsdStats::kPullMaxDelayNs;
-} PullAtomInfo;
 
 typedef struct PullerKey {
     // The uid of the process that registers this puller.
@@ -121,7 +103,7 @@
 
     void UnregisterPullAtomCallback(const int uid, const int32_t atomTag);
 
-    static std::map<PullerKey, PullAtomInfo> kAllPullAtomInfo;
+    std::map<const PullerKey, sp<StatsPuller>> kAllPullAtomInfo;
 
 private:
     sp<IStatsCompanionService> mStatsCompanionService = nullptr;
diff --git a/cmds/statsd/src/external/puller_util.cpp b/cmds/statsd/src/external/puller_util.cpp
index 031c437..aee7256 100644
--- a/cmds/statsd/src/external/puller_util.cpp
+++ b/cmds/statsd/src/external/puller_util.cpp
@@ -17,7 +17,6 @@
 #define DEBUG false  // STOPSHIP if true
 #include "Log.h"
 
-#include "StatsPullerManager.h"
 #include "atoms_info.h"
 #include "puller_util.h"
 
@@ -25,12 +24,7 @@
 namespace os {
 namespace statsd {
 
-using std::list;
-using std::map;
-using std::set;
-using std::shared_ptr;
-using std::sort;
-using std::vector;
+using namespace std;
 
 /**
  * Process all data and merge isolated with host if necessary.
@@ -54,12 +48,7 @@
  * All atoms should be of the same tagId. All fields should be present.
  */
 void mapAndMergeIsolatedUidsToHostUid(vector<shared_ptr<LogEvent>>& data, const sp<UidMap>& uidMap,
-                                      int tagId) {
-    if (StatsPullerManager::kAllPullAtomInfo.find({.atomTag = tagId}) ==
-        StatsPullerManager::kAllPullAtomInfo.end()) {
-        VLOG("Unknown pull atom id %d", tagId);
-        return;
-    }
+                                      int tagId, const vector<int>& additiveFieldsVec) {
     if ((android::util::AtomsInfo::kAtomsWithAttributionChain.find(tagId) ==
          android::util::AtomsInfo::kAtomsWithAttributionChain.end()) &&
         (android::util::AtomsInfo::kAtomsWithUidField.find(tagId) ==
@@ -120,8 +109,6 @@
          });
 
     vector<shared_ptr<LogEvent>> mergedData;
-    const vector<int>& additiveFieldsVec =
-            StatsPullerManager::kAllPullAtomInfo.find({.atomTag = tagId})->second.additiveFields;
     const set<int> additiveFields(additiveFieldsVec.begin(), additiveFieldsVec.end());
     bool needMerge = true;
 
diff --git a/cmds/statsd/src/external/puller_util.h b/cmds/statsd/src/external/puller_util.h
index f703e6c..afcf68c 100644
--- a/cmds/statsd/src/external/puller_util.h
+++ b/cmds/statsd/src/external/puller_util.h
@@ -26,7 +26,8 @@
 namespace statsd {
 
 void mapAndMergeIsolatedUidsToHostUid(std::vector<std::shared_ptr<LogEvent>>& data,
-                                      const sp<UidMap>& uidMap, int tagId);
+                                      const sp<UidMap>& uidMap, int tagId,
+                                      const vector<int>& additiveFieldsVec);
 
 }  // namespace statsd
 }  // namespace os
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index 3282785..df810aa 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -164,6 +164,12 @@
     // Maximum number of pushed atoms statsd stats will track above kMaxPushedAtomId.
     static const int kMaxNonPlatformPushedAtoms = 100;
 
+    // Atom id that is the start of the pulled atoms.
+    static const int kPullAtomStartTag = 10000;
+
+    // Atom id that is the start of vendor atoms.
+    static const int kVendorAtomStartTag = 100000;
+
     // Vendor pulled atom start id.
     static const int32_t kVendorPulledAtomStartTag = 150000;
 
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index 36f4623..3827b9e 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -71,70 +71,6 @@
     mValues = event.mValues;
 }
 
-LogEvent::LogEvent(const StatsLogEventWrapper& statsLogEventWrapper, int workChainIndex) {
-    mTagId = statsLogEventWrapper.getTagId();
-    mLogdTimestampNs = statsLogEventWrapper.getWallClockTimeNs();
-    mElapsedTimestampNs = statsLogEventWrapper.getElapsedRealTimeNs();
-    mLogUid = 0;
-    int workChainPosOffset = 0;
-    if (workChainIndex != -1) {
-        const WorkChain& wc = statsLogEventWrapper.getWorkChains()[workChainIndex];
-        // chains are at field 1, level 2
-        int depth = 2;
-        for (int i = 0; i < (int)wc.uids.size(); i++) {
-            int pos[] = {1, i + 1, 1};
-            mValues.push_back(FieldValue(Field(mTagId, pos, depth), Value(wc.uids[i])));
-            pos[2]++;
-            mValues.push_back(FieldValue(Field(mTagId, pos, depth), Value(wc.tags[i])));
-            mValues.back().mField.decorateLastPos(2);
-        }
-        mValues.back().mField.decorateLastPos(1);
-        workChainPosOffset = 1;
-    }
-    for (int i = 0; i < (int)statsLogEventWrapper.getElements().size(); i++) {
-        Field field(statsLogEventWrapper.getTagId(), getSimpleField(i + 1 + workChainPosOffset));
-        switch (statsLogEventWrapper.getElements()[i].type) {
-            case android::os::StatsLogValue::STATS_LOG_VALUE_TYPE::INT:
-                mValues.push_back(
-                        FieldValue(field, Value(statsLogEventWrapper.getElements()[i].int_value)));
-                break;
-            case android::os::StatsLogValue::STATS_LOG_VALUE_TYPE::LONG:
-                mValues.push_back(
-                        FieldValue(field, Value(statsLogEventWrapper.getElements()[i].long_value)));
-                break;
-            case android::os::StatsLogValue::STATS_LOG_VALUE_TYPE::FLOAT:
-                mValues.push_back(FieldValue(
-                        field, Value(statsLogEventWrapper.getElements()[i].float_value)));
-                break;
-            case android::os::StatsLogValue::STATS_LOG_VALUE_TYPE::DOUBLE:
-                mValues.push_back(FieldValue(
-                        field, Value(statsLogEventWrapper.getElements()[i].double_value)));
-                break;
-            case android::os::StatsLogValue::STATS_LOG_VALUE_TYPE::STRING:
-                mValues.push_back(
-                        FieldValue(field, Value(statsLogEventWrapper.getElements()[i].str_value)));
-                break;
-            case android::os::StatsLogValue::STATS_LOG_VALUE_TYPE::STORAGE:
-                mValues.push_back(FieldValue(
-                        field, Value(statsLogEventWrapper.getElements()[i].storage_value)));
-                break;
-            default:
-                break;
-        }
-    }
-}
-
-void LogEvent::createLogEvents(const StatsLogEventWrapper& statsLogEventWrapper,
-                               std::vector<std::shared_ptr<LogEvent>>& logEvents) {
-    if (statsLogEventWrapper.getWorkChains().size() == 0) {
-        logEvents.push_back(std::make_shared<LogEvent>(statsLogEventWrapper, -1));
-    } else {
-        for (size_t i = 0; i < statsLogEventWrapper.getWorkChains().size(); i++) {
-            logEvents.push_back(std::make_shared<LogEvent>(statsLogEventWrapper, i));
-        }
-    }
-}
-
 LogEvent::LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs) {
     mLogdTimestampNs = wallClockTimestampNs;
     mElapsedTimestampNs = elapsedTimestampNs;
diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h
index 596d623..0f33c56 100644
--- a/cmds/statsd/src/logd/LogEvent.h
+++ b/cmds/statsd/src/logd/LogEvent.h
@@ -19,7 +19,6 @@
 #include "FieldValue.h"
 
 #include <android/frameworks/stats/1.0/types.h>
-#include <android/os/StatsLogEventWrapper.h>
 #include <android/util/ProtoOutputStream.h>
 #include <log/log_read.h>
 #include <private/android_logger.h>
@@ -80,17 +79,6 @@
     explicit LogEvent(uint8_t* msg, uint32_t len, uint32_t uid, bool useNewSchema);
 
     /**
-     * Creates LogEvent from StatsLogEventWrapper.
-     */
-    static void createLogEvents(const StatsLogEventWrapper& statsLogEventWrapper,
-                                std::vector<std::shared_ptr<LogEvent>>& logEvents);
-
-    /**
-     * Construct one LogEvent from a StatsLogEventWrapper with the i-th work chain. -1 if no chain.
-     */
-    explicit LogEvent(const StatsLogEventWrapper& statsLogEventWrapper, int workChainIndex);
-
-    /**
      * Constructs a LogEvent with synthetic data for testing. Must call init() before reading.
      */
     explicit LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs);
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index 73c1212..17f62b0 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -426,7 +426,6 @@
                                 config.event_metric_size() + config.gauge_metric_size() +
                                 config.value_metric_size();
     allMetricProducers.reserve(allMetricsCount);
-    StatsPullerManager statsPullerManager;
 
     // Construct map from metric id to metric activation index. The map will be used to determine
     // the metric activation corresponding to a metric.
@@ -661,7 +660,7 @@
             return false;
         }
         int atomTagId = *(atomMatcher->getAtomIds().begin());
-        int pullTagId = statsPullerManager.PullerForMatcherExists(atomTagId) ? atomTagId : -1;
+        int pullTagId = pullerManager->PullerForMatcherExists(atomTagId) ? atomTagId : -1;
 
         int conditionIndex = -1;
         if (metric.has_condition()) {
@@ -753,7 +752,7 @@
             return false;
         }
         int atomTagId = *(atomMatcher->getAtomIds().begin());
-        int pullTagId = statsPullerManager.PullerForMatcherExists(atomTagId) ? atomTagId : -1;
+        int pullTagId = pullerManager->PullerForMatcherExists(atomTagId) ? atomTagId : -1;
 
         int triggerTrackerIndex;
         int triggerAtomId = -1;
diff --git a/cmds/statsd/src/stats_log_util.h b/cmds/statsd/src/stats_log_util.h
index f3e9433..5fdf6e2 100644
--- a/cmds/statsd/src/stats_log_util.h
+++ b/cmds/statsd/src/stats_log_util.h
@@ -99,6 +99,10 @@
     return atomId >= StatsdStats::kVendorPulledAtomStartTag && atomId < StatsdStats::kMaxAtomTag;
 }
 
+inline bool isPulledAtom(int atomId) {
+    return atomId >= StatsdStats::kPullAtomStartTag && atomId < StatsdStats::kVendorAtomStartTag;
+}
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/tests/LogEvent_test.cpp b/cmds/statsd/tests/LogEvent_test.cpp
index 9f50701..1cf9fb6 100644
--- a/cmds/statsd/tests/LogEvent_test.cpp
+++ b/cmds/statsd/tests/LogEvent_test.cpp
@@ -665,168 +665,6 @@
     EXPECT_EQ(1.1f, item16.mValue.float_value);
 }
 
-TEST(LogEventTest, TestStatsLogEventWrapperNoChain) {
-    Parcel parcel;
-    // tag id
-    parcel.writeInt32(1);
-    // elapsed realtime
-    parcel.writeInt64(1111L);
-    // wallclock time
-    parcel.writeInt64(2222L);
-    // no chain
-    parcel.writeInt32(0);
-    // 2 data
-    parcel.writeInt32(2);
-    // int 6
-    parcel.writeInt32(1);
-    parcel.writeInt32(6);
-    // long 10
-    parcel.writeInt32(2);
-    parcel.writeInt64(10);
-    parcel.setDataPosition(0);
-
-    StatsLogEventWrapper statsLogEventWrapper;
-    EXPECT_EQ(NO_ERROR, statsLogEventWrapper.readFromParcel(&parcel));
-    EXPECT_EQ(1, statsLogEventWrapper.getTagId());
-    EXPECT_EQ(1111L, statsLogEventWrapper.getElapsedRealTimeNs());
-    EXPECT_EQ(2222L, statsLogEventWrapper.getWallClockTimeNs());
-    EXPECT_EQ(0, statsLogEventWrapper.getWorkChains().size());
-    EXPECT_EQ(2, statsLogEventWrapper.getElements().size());
-    EXPECT_EQ(6, statsLogEventWrapper.getElements()[0].int_value);
-    EXPECT_EQ(10L, statsLogEventWrapper.getElements()[1].long_value);
-    LogEvent event(statsLogEventWrapper, -1);
-    EXPECT_EQ(1, event.GetTagId());
-    EXPECT_EQ(1111L, event.GetElapsedTimestampNs());
-    EXPECT_EQ(2222L, event.GetLogdTimestampNs());
-    EXPECT_EQ(2, event.size());
-    EXPECT_EQ(6, event.getValues()[0].mValue.int_value);
-    EXPECT_EQ(10, event.getValues()[1].mValue.long_value);
-}
-
-TEST(LogEventTest, TestStatsLogEventWrapperWithChain) {
-    Parcel parcel;
-    // tag id
-    parcel.writeInt32(1);
-    // elapsed realtime
-    parcel.writeInt64(1111L);
-    // wallclock time
-    parcel.writeInt64(2222L);
-    // 3 chains
-    parcel.writeInt32(3);
-    // chain1, 2 nodes (1, "tag1") (2, "tag2")
-    parcel.writeInt32(2);
-    parcel.writeInt32(1);
-    parcel.writeString16(String16("tag1"));
-    parcel.writeInt32(2);
-    parcel.writeString16(String16("tag2"));
-    // chain2, 1 node (3, "tag3")
-    parcel.writeInt32(1);
-    parcel.writeInt32(3);
-    parcel.writeString16(String16("tag3"));
-    // chain3, 2 nodes (4, "") (5, "")
-    parcel.writeInt32(2);
-    parcel.writeInt32(4);
-    parcel.writeString16(String16(""));
-    parcel.writeInt32(5);
-    parcel.writeString16(String16(""));
-    // 2 data
-    parcel.writeInt32(2);
-    // int 6
-    parcel.writeInt32(1);
-    parcel.writeInt32(6);
-    // long 10
-    parcel.writeInt32(2);
-    parcel.writeInt64(10);
-    parcel.setDataPosition(0);
-
-    StatsLogEventWrapper statsLogEventWrapper;
-    EXPECT_EQ(NO_ERROR, statsLogEventWrapper.readFromParcel(&parcel));
-    EXPECT_EQ(1, statsLogEventWrapper.getTagId());
-    EXPECT_EQ(1111L, statsLogEventWrapper.getElapsedRealTimeNs());
-    EXPECT_EQ(2222L, statsLogEventWrapper.getWallClockTimeNs());
-    EXPECT_EQ(3, statsLogEventWrapper.getWorkChains().size());
-    EXPECT_EQ(2, statsLogEventWrapper.getWorkChains()[0].uids.size());
-    EXPECT_EQ(1, statsLogEventWrapper.getWorkChains()[0].uids[0]);
-    EXPECT_EQ(2, statsLogEventWrapper.getWorkChains()[0].uids[1]);
-    EXPECT_EQ(2, statsLogEventWrapper.getWorkChains()[0].tags.size());
-    EXPECT_EQ("tag1", statsLogEventWrapper.getWorkChains()[0].tags[0]);
-    EXPECT_EQ("tag2", statsLogEventWrapper.getWorkChains()[0].tags[1]);
-    EXPECT_EQ(1, statsLogEventWrapper.getWorkChains()[1].uids.size());
-    EXPECT_EQ(3, statsLogEventWrapper.getWorkChains()[1].uids[0]);
-    EXPECT_EQ(1, statsLogEventWrapper.getWorkChains()[1].tags.size());
-    EXPECT_EQ("tag3", statsLogEventWrapper.getWorkChains()[1].tags[0]);
-    EXPECT_EQ(2, statsLogEventWrapper.getElements().size());
-    EXPECT_EQ(6, statsLogEventWrapper.getElements()[0].int_value);
-    EXPECT_EQ(10L, statsLogEventWrapper.getElements()[1].long_value);
-    EXPECT_EQ(2, statsLogEventWrapper.getWorkChains()[2].uids.size());
-    EXPECT_EQ(4, statsLogEventWrapper.getWorkChains()[2].uids[0]);
-    EXPECT_EQ(5, statsLogEventWrapper.getWorkChains()[2].uids[1]);
-    EXPECT_EQ(2, statsLogEventWrapper.getWorkChains()[2].tags.size());
-    EXPECT_EQ("", statsLogEventWrapper.getWorkChains()[2].tags[0]);
-    EXPECT_EQ("", statsLogEventWrapper.getWorkChains()[2].tags[1]);
-
-    LogEvent event(statsLogEventWrapper, -1);
-    EXPECT_EQ(1, event.GetTagId());
-    EXPECT_EQ(1111L, event.GetElapsedTimestampNs());
-    EXPECT_EQ(2222L, event.GetLogdTimestampNs());
-    EXPECT_EQ(2, event.size());
-    EXPECT_EQ(6, event.getValues()[0].mValue.int_value);
-    EXPECT_EQ(10, event.getValues()[1].mValue.long_value);
-
-    LogEvent event1(statsLogEventWrapper, 0);
-
-    EXPECT_EQ(1, event1.GetTagId());
-    EXPECT_EQ(1111L, event1.GetElapsedTimestampNs());
-    EXPECT_EQ(2222L, event1.GetLogdTimestampNs());
-    EXPECT_EQ(6, event1.size());
-    EXPECT_EQ(1, event1.getValues()[0].mValue.int_value);
-    EXPECT_EQ(0x2010101, event1.getValues()[0].mField.getField());
-    EXPECT_EQ("tag1", event1.getValues()[1].mValue.str_value);
-    EXPECT_EQ(0x2010182, event1.getValues()[1].mField.getField());
-    EXPECT_EQ(2, event1.getValues()[2].mValue.int_value);
-    EXPECT_EQ(0x2010201, event1.getValues()[2].mField.getField());
-    EXPECT_EQ("tag2", event1.getValues()[3].mValue.str_value);
-    EXPECT_EQ(0x2018282, event1.getValues()[3].mField.getField());
-    EXPECT_EQ(6, event1.getValues()[4].mValue.int_value);
-    EXPECT_EQ(0x20000, event1.getValues()[4].mField.getField());
-    EXPECT_EQ(10, event1.getValues()[5].mValue.long_value);
-    EXPECT_EQ(0x30000, event1.getValues()[5].mField.getField());
-
-    LogEvent event2(statsLogEventWrapper, 1);
-
-    EXPECT_EQ(1, event2.GetTagId());
-    EXPECT_EQ(1111L, event2.GetElapsedTimestampNs());
-    EXPECT_EQ(2222L, event2.GetLogdTimestampNs());
-    EXPECT_EQ(4, event2.size());
-    EXPECT_EQ(3, event2.getValues()[0].mValue.int_value);
-    EXPECT_EQ(0x2010101, event2.getValues()[0].mField.getField());
-    EXPECT_EQ("tag3", event2.getValues()[1].mValue.str_value);
-    EXPECT_EQ(0x2018182, event2.getValues()[1].mField.getField());
-    EXPECT_EQ(6, event2.getValues()[2].mValue.int_value);
-    EXPECT_EQ(0x20000, event2.getValues()[2].mField.getField());
-    EXPECT_EQ(10, event2.getValues()[3].mValue.long_value);
-    EXPECT_EQ(0x30000, event2.getValues()[3].mField.getField());
-
-    LogEvent event3(statsLogEventWrapper, 2);
-
-    EXPECT_EQ(1, event3.GetTagId());
-    EXPECT_EQ(1111L, event3.GetElapsedTimestampNs());
-    EXPECT_EQ(2222L, event3.GetLogdTimestampNs());
-    EXPECT_EQ(6, event3.size());
-    EXPECT_EQ(4, event3.getValues()[0].mValue.int_value);
-    EXPECT_EQ(0x2010101, event3.getValues()[0].mField.getField());
-    EXPECT_EQ("", event3.getValues()[1].mValue.str_value);
-    EXPECT_EQ(0x2010182, event3.getValues()[1].mField.getField());
-    EXPECT_EQ(5, event3.getValues()[2].mValue.int_value);
-    EXPECT_EQ(0x2010201, event3.getValues()[2].mField.getField());
-    EXPECT_EQ("", event3.getValues()[3].mValue.str_value);
-    EXPECT_EQ(0x2018282, event3.getValues()[3].mField.getField());
-    EXPECT_EQ(6, event3.getValues()[4].mValue.int_value);
-    EXPECT_EQ(0x20000, event3.getValues()[4].mField.getField());
-    EXPECT_EQ(10, event3.getValues()[5].mValue.long_value);
-    EXPECT_EQ(0x30000, event3.getValues()[5].mField.getField());
-}
-
 TEST(LogEventTest, TestBinaryFieldAtom) {
     Atom launcherAtom;
     auto launcher_event = launcherAtom.mutable_launcher_event();
diff --git a/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp b/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp
index 2b0590d..2576cf5 100644
--- a/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp
+++ b/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp
@@ -116,7 +116,7 @@
     pullSuccess = true;
     values.push_back(value);
 
-    StatsCallbackPuller puller(pullTagId, cb, pullTimeoutNs);
+    StatsCallbackPuller puller(pullTagId, cb, pullCoolDownNs, pullTimeoutNs, {});
 
     vector<std::shared_ptr<LogEvent>> dataHolder;
     int64_t startTimeNs = getElapsedRealtimeNs();
@@ -137,7 +137,7 @@
     int64_t value = 1234;
     values.push_back(value);
 
-    StatsCallbackPuller puller(pullTagId, cb, pullTimeoutNs);
+    StatsCallbackPuller puller(pullTagId, cb, pullCoolDownNs, pullTimeoutNs, {});
 
     vector<std::shared_ptr<LogEvent>> dataHolder;
     EXPECT_FALSE(puller.PullInternal(&dataHolder));
@@ -152,7 +152,7 @@
     int64_t value = 4321;
     values.push_back(value);
 
-    StatsCallbackPuller puller(pullTagId, cb, pullTimeoutNs);
+    StatsCallbackPuller puller(pullTagId, cb, pullCoolDownNs, pullTimeoutNs, {});
 
     vector<std::shared_ptr<LogEvent>> dataHolder;
     int64_t startTimeNs = getElapsedRealtimeNs();
diff --git a/cmds/statsd/tests/external/StatsPuller_test.cpp b/cmds/statsd/tests/external/StatsPuller_test.cpp
index c40719a..f42356a 100644
--- a/cmds/statsd/tests/external/StatsPuller_test.cpp
+++ b/cmds/statsd/tests/external/StatsPuller_test.cpp
@@ -45,7 +45,7 @@
 
 class FakePuller : public StatsPuller {
 public:
-    FakePuller() : StatsPuller(pullTagId){};
+    FakePuller() : StatsPuller(pullTagId, /*coolDown=*/NS_PER_SEC, /*timeout=*/NS_PER_SEC / 2){};
 
 private:
     bool PullInternal(vector<std::shared_ptr<LogEvent>>* data) override {
diff --git a/cmds/statsd/tests/external/puller_util_test.cpp b/cmds/statsd/tests/external/puller_util_test.cpp
index 6730828..c25e657 100644
--- a/cmds/statsd/tests/external/puller_util_test.cpp
+++ b/cmds/statsd/tests/external/puller_util_test.cpp
@@ -34,8 +34,9 @@
 /*
  * Test merge isolated and host uid
  */
-
+namespace {
 int uidAtomTagId = android::util::CPU_CLUSTER_TIME;
+const vector<int> uidAdditiveFields = {3};
 int nonUidAtomTagId = android::util::SYSTEM_UPTIME;
 int timestamp = 1234;
 int isolatedUid = 30;
@@ -57,6 +58,7 @@
     ret.push_back(vec);
   }
 }
+}  // anonymous namespace
 
 TEST(puller_util, MergeNoDimension) {
   vector<shared_ptr<LogEvent>> inputData;
@@ -81,7 +83,7 @@
       .WillRepeatedly(Return(hostUid));
   EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
       .WillRepeatedly(ReturnArg<0>());
-  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
+  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
 
   vector<vector<int>> actual;
   extractIntoVector(inputData, actual);
@@ -121,7 +123,7 @@
       .WillRepeatedly(Return(hostUid));
   EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
       .WillRepeatedly(ReturnArg<0>());
-  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
+  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
 
   vector<vector<int>> actual;
   extractIntoVector(inputData, actual);
@@ -155,7 +157,7 @@
       .WillRepeatedly(Return(hostUid));
   EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
       .WillRepeatedly(ReturnArg<0>());
-  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
+  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
 
   // 20->32->31
   // 20->22->21
@@ -191,7 +193,7 @@
       .WillRepeatedly(Return(hostUid));
   EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
       .WillRepeatedly(ReturnArg<0>());
-  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
+  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
 
   // 20->32->31
   // 20->22->21
@@ -232,7 +234,7 @@
 
   sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
   EXPECT_CALL(*uidMap, getHostUidOrSelf(_)).WillRepeatedly(Return(hostUid));
-  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
+  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
 
   vector<vector<int>> actual;
   extractIntoVector(inputData, actual);
@@ -257,7 +259,7 @@
   inputData.push_back(event);
 
   sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
-  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, nonUidAtomTagId);
+  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, nonUidAtomTagId, {} /*no additive fields*/);
 
   EXPECT_EQ(2, (int)inputData.size());
 }
diff --git a/cmds/statsd/tests/storage/StorageManager_test.cpp b/cmds/statsd/tests/storage/StorageManager_test.cpp
index 9e15e99..b91e5a0 100644
--- a/cmds/statsd/tests/storage/StorageManager_test.cpp
+++ b/cmds/statsd/tests/storage/StorageManager_test.cpp
@@ -12,6 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include <android-base/unique_fd.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <stdio.h>
diff --git a/cmds/telecom/src/com/android/commands/telecom/Telecom.java b/cmds/telecom/src/com/android/commands/telecom/Telecom.java
index 1987440..9707405 100644
--- a/cmds/telecom/src/com/android/commands/telecom/Telecom.java
+++ b/cmds/telecom/src/com/android/commands/telecom/Telecom.java
@@ -366,12 +366,8 @@
     }
 
     private void runGetMaxPhones() throws RemoteException {
-        // This assumes the max number of SIMs is 2, which it currently is
-        if (TelephonyManager.MULTISIM_ALLOWED == mTelephonyManager.isMultiSimSupported()) {
-            System.out.println("2");
-        } else {
-            System.out.println("1");
-        }
+        // how many logical modems can be potentially active simultaneously
+        System.out.println(mTelephonyManager.getSupportedModemCount());
     }
 
     private void runSetEmergencyPhoneAccountPackageFilter() throws RemoteException {
diff --git a/config/boot-image-profile.txt b/config/boot-image-profile.txt
index 4aaf727..e649c30 100644
--- a/config/boot-image-profile.txt
+++ b/config/boot-image-profile.txt
@@ -1515,7 +1515,6 @@
 HSPLandroid/app/IActivityTaskManager$Stub$Proxy;->activityIdle(Landroid/os/IBinder;Landroid/content/res/Configuration;Z)V
 HSPLandroid/app/IActivityTaskManager$Stub$Proxy;->activityPaused(Landroid/os/IBinder;)V
 HSPLandroid/app/IActivityTaskManager$Stub$Proxy;->activityResumed(Landroid/os/IBinder;)V
-HSPLandroid/app/IActivityTaskManager$Stub$Proxy;->activitySlept(Landroid/os/IBinder;)V
 HSPLandroid/app/IActivityTaskManager$Stub$Proxy;->activityStopped(Landroid/os/IBinder;Landroid/os/Bundle;Landroid/os/PersistableBundle;Ljava/lang/CharSequence;)V
 HSPLandroid/app/IActivityTaskManager$Stub$Proxy;->activityTopResumedStateLost()V
 HSPLandroid/app/IActivityTaskManager$Stub$Proxy;->finishActivity(Landroid/os/IBinder;ILandroid/content/Intent;I)Z
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 9a8e130..fb27f74 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -7,8 +7,3 @@
     name: "IDropBoxManagerService.aidl",
     srcs: ["com/android/internal/os/IDropBoxManagerService.aidl"],
 }
-
-filegroup {
-    name: "ICarStatsService.aidl",
-    srcs: ["com/android/internal/car/ICarStatsService.aidl"],
-}
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index ee6ccc2..7722dc3 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -310,13 +310,11 @@
 
     /**
      * The user has performed a double tap gesture on the touch screen.
-     * @hide
      */
     public static final int GESTURE_DOUBLE_TAP = 17;
 
     /**
      * The user has performed a double tap and hold gesture on the touch screen.
-     * @hide
      */
     public static final int GESTURE_DOUBLE_TAP_AND_HOLD = 18;
 
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 12f2c3b..82c7635 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -341,6 +341,26 @@
      */
     public static final int FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK = 0x00000400;
 
+    /**
+     * This flag requests that when {@link #FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is enabled,
+     * double tap and double tap and hold gestures are dispatched to the service rather than being
+     * handled by the framework. If {@link #FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is disabled this
+     * flag has no effect.
+     *
+     * @see #FLAG_REQUEST_TOUCH_EXPLORATION_MODE
+     */
+    public static final int FLAG_SERVICE_HANDLES_DOUBLE_TAP = 0x0000800;
+
+    /**
+     * This flag requests that when when {@link #FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is enabled,
+     * multi-finger gestures are also enabled. As a consequence, two-finger bypass gestures will be
+     * disabled. If {@link #FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is disabled this flag has no
+     * effect.
+     *
+     * @see #FLAG_REQUEST_TOUCH_EXPLORATION_MODE
+     */
+    public static final int FLAG_REQUEST_MULTI_FINGER_GESTURES = 0x0001000;
+
     /** {@hide} */
     public static final int FLAG_FORCE_DIRECT_BOOT_AWARE = 0x00010000;
 
@@ -1221,6 +1241,10 @@
                 return "FLAG_INCLUDE_NOT_IMPORTANT_VIEWS";
             case FLAG_REQUEST_TOUCH_EXPLORATION_MODE:
                 return "FLAG_REQUEST_TOUCH_EXPLORATION_MODE";
+            case FLAG_SERVICE_HANDLES_DOUBLE_TAP:
+                return "FLAG_SERVICE_HANDLES_DOUBLE_TAP";
+            case FLAG_REQUEST_MULTI_FINGER_GESTURES:
+                return "FLAG_REQUEST_MULTI_FINGER_GESTURES";
             case FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY:
                 return "FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY";
             case FLAG_REPORT_VIEW_IDS:
diff --git a/core/java/android/annotation/SystemApi.java b/core/java/android/annotation/SystemApi.java
index 2cb93e4..ecbfed9 100644
--- a/core/java/android/annotation/SystemApi.java
+++ b/core/java/android/annotation/SystemApi.java
@@ -23,6 +23,7 @@
 import static java.lang.annotation.ElementType.PACKAGE;
 import static java.lang.annotation.ElementType.TYPE;
 
+import java.lang.annotation.Repeatable;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
@@ -40,39 +41,48 @@
  */
 @Target({TYPE, FIELD, METHOD, CONSTRUCTOR, ANNOTATION_TYPE, PACKAGE})
 @Retention(RetentionPolicy.RUNTIME)
+@Repeatable(SystemApi.Container.class) // TODO(b/146727827): make this non-repeatable
 public @interface SystemApi {
     enum Client {
         /**
          * Specifies that the intended clients of a SystemApi are privileged apps.
-         * This is the default value for {@link #client}. This implies
-         * MODULE_APPS and MODULE_LIBRARIES as well, which means that APIs will also
-         * be available to module apps and jars.
+         * This is the default value for {@link #client}.
+         * TODO Update the javadoc according to the final spec
          */
         PRIVILEGED_APPS,
 
         /**
-         * Specifies that the intended clients of a SystemApi are modules implemented
-         * as apps, like the NetworkStack app. This implies MODULE_LIBRARIES as well,
-         * which means that APIs will also be available to module jars.
+         * DO NOT USE. Use PRIVILEGED_APPS instead.
+         * (This would provide no further protection over PRIVILEGED_APPS; do not rely on it)
+         * @deprecated Use #PRIVILEGED_APPS instead
          */
+        @Deprecated
         MODULE_APPS,
 
         /**
          * Specifies that the intended clients of a SystemApi are modules implemented
          * as libraries, like the conscrypt.jar in the conscrypt APEX.
+         * TODO Update the javadoc according to the final spec
          */
-        MODULE_LIBRARIES
+        MODULE_LIBRARIES,
+
+        /**
+         * Specifies that the system API is available only in the system server process.
+         * Use this to expose APIs from code loaded by the system server process <em>but</em>
+         * not in <pre>BOOTCLASSPATH</pre>.
+         * TODO(b/148177503) Update "services-stubs" and actually use it.
+         */
+        SYSTEM_SERVER
     }
 
+    /** @deprecated do not use */
+    @Deprecated
     enum Process {
-        /**
-         * Specifies that the SystemAPI is available in every Java processes.
-         * This is the default value for {@link #process}.
-         */
+        /** @deprecated do not use */
         ALL,
 
         /**
-         * Specifies that the SystemAPI is available only in the system server process.
+         * @deprecated use Client#SYSTEM_SERVER instead
          */
         SYSTEM_SERVER
     }
@@ -83,7 +93,18 @@
     Client client() default android.annotation.SystemApi.Client.PRIVILEGED_APPS;
 
     /**
-     * The process(es) that this SystemAPI is available
+     * @deprecated use Client#SYSTEM_SERVER instead for system_server APIs
      */
+    @Deprecated
     Process process() default android.annotation.SystemApi.Process.ALL;
+
+
+    /**
+     * Container for {@link SystemApi} that allows it to be applied repeatedly to types.
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(TYPE)
+    @interface Container {
+        SystemApi[] value();
+    }
 }
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index d952be5..d8b5e7f 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -45,6 +45,7 @@
 import android.content.IIntentSender;
 import android.content.Intent;
 import android.content.IntentSender;
+import android.content.LocusId;
 import android.content.SharedPreferences;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
@@ -1025,6 +1026,39 @@
         mIntent = newIntent;
     }
 
+    /**
+     * Sets the {@link android.content.LocusId} for this activity. The locus id
+     * helps identify different instances of the same {@code Activity} class.
+     * <p> For example, a locus id based on a specific conversation could be set on a
+     * conversation app's chat {@code Activity}. The system can then use this locus id
+     * along with app's contents to provide ranking signals in various UI surfaces
+     * including sharing, notifications, shortcuts and so on.
+     * <p> It is recommended to set the same locus id in the shortcut's locus id using
+     * {@link android.content.pm.ShortcutInfo.Builder#setLocusId(android.content.LocusId)
+     *      setLocusId}
+     * so that the system can learn appropriate ranking signals linking the activity's
+     * locus id with the matching shortcut.
+     *
+     * @param locusId  a unique, stable id that identifies this {@code Activity} instance from
+     *      others. This can be linked to a shortcut using
+     *      {@link android.content.pm.ShortcutInfo.Builder#setLocusId(android.content.LocusId)
+     *      setLocusId} with the same locus id string.
+     * @param bundle extras set or updated as part of this locus context. This may help provide
+     *      additional metadata such as URLs, conversation participants specific to this
+     *      {@code Activity}'s context.
+     *
+     * @see android.view.contentcapture.ContentCaptureManager
+     * @see android.view.contentcapture.ContentCaptureContext
+     */
+    public void setLocusContext(@Nullable LocusId locusId, @Nullable Bundle bundle) {
+        try {
+            ActivityManager.getService().setActivityLocusContext(mComponent, locusId, mToken);
+        } catch (RemoteException re) {
+            re.rethrowFromSystemServer();
+        }
+        // TODO(b/147750355): Pass locusId and bundle to the Content Capture.
+    }
+
     /** Return the application that owns this activity. */
     public final Application getApplication() {
         return mApplication;
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index f7c4d96..206c771 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -73,6 +73,7 @@
 import android.util.Singleton;
 import android.util.Size;
 import android.view.IWindowContainer;
+import android.view.Surface;
 
 import com.android.internal.app.LocalePicker;
 import com.android.internal.app.procstats.ProcessStats;
@@ -601,6 +602,22 @@
     public static final int PROCESS_CAPABILITY_ALL = PROCESS_CAPABILITY_FOREGROUND_LOCATION
             | PROCESS_CAPABILITY_FOREGROUND_CAMERA
             | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
+    /**
+     * All explicit capabilities. These are capabilities that need to be specified from manifest
+     * file.
+     * @hide
+     */
+    @TestApi
+    public static final int PROCESS_CAPABILITY_ALL_EXPLICIT =
+            PROCESS_CAPABILITY_FOREGROUND_LOCATION;
+
+    /**
+     * All implicit capabilities. There are capabilities that process automatically have.
+     * @hide
+     */
+    @TestApi
+    public static final int PROCESS_CAPABILITY_ALL_IMPLICIT = PROCESS_CAPABILITY_FOREGROUND_CAMERA
+            | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
 
     // NOTE: If PROCESS_STATEs are added, then new fields must be added
     // to frameworks/base/core/proto/android/app/enums.proto and the following method must
@@ -1928,7 +1945,12 @@
         // Top activity in task when snapshot was taken
         private final ComponentName mTopActivityComponent;
         private final GraphicBuffer mSnapshot;
+        /** Indicates whether task was in landscape or portrait */
+        @Configuration.Orientation
         private final int mOrientation;
+        /** See {@link android.view.Surface.Rotation} */
+        @Surface.Rotation
+        private int mRotation;
         private final Rect mContentInsets;
         // Whether this snapshot is a down-sampled version of the full resolution, used mainly for
         // low-ram devices
@@ -1945,7 +1967,7 @@
 
         public TaskSnapshot(long id,
                 @NonNull ComponentName topActivityComponent, GraphicBuffer snapshot,
-                @NonNull ColorSpace colorSpace, int orientation, Rect contentInsets,
+                @NonNull ColorSpace colorSpace, int orientation, int rotation, Rect contentInsets,
                 boolean reducedResolution, float scale, boolean isRealSnapshot, int windowingMode,
                 int systemUiVisibility, boolean isTranslucent) {
             mId = id;
@@ -1954,6 +1976,7 @@
             mColorSpace = colorSpace.getId() < 0
                     ? ColorSpace.get(ColorSpace.Named.SRGB) : colorSpace;
             mOrientation = orientation;
+            mRotation = rotation;
             mContentInsets = new Rect(contentInsets);
             mReducedResolution = reducedResolution;
             mScale = scale;
@@ -1972,6 +1995,7 @@
                     ? ColorSpace.get(ColorSpace.Named.values()[colorSpaceId])
                     : ColorSpace.get(ColorSpace.Named.SRGB);
             mOrientation = source.readInt();
+            mRotation = source.readInt();
             mContentInsets = source.readParcelable(null /* classLoader */);
             mReducedResolution = source.readBoolean();
             mScale = source.readFloat();
@@ -2019,6 +2043,13 @@
         }
 
         /**
+         * @return The screen rotation the screenshot was taken in.
+         */
+        public int getRotation() {
+            return mRotation;
+        }
+
+        /**
          * @return The system/content insets on the snapshot. These can be clipped off in order to
          *         remove any areas behind system bars in the snapshot.
          */
@@ -2087,6 +2118,7 @@
             dest.writeParcelable(mSnapshot, 0);
             dest.writeInt(mColorSpace.getId());
             dest.writeInt(mOrientation);
+            dest.writeInt(mRotation);
             dest.writeParcelable(mContentInsets, 0);
             dest.writeBoolean(mReducedResolution);
             dest.writeFloat(mScale);
@@ -2106,6 +2138,7 @@
                     + " mSnapshot=" + mSnapshot + " (" + width + "x" + height + ")"
                     + " mColorSpace=" + mColorSpace.toString()
                     + " mOrientation=" + mOrientation
+                    + " mRotation=" + mRotation
                     + " mContentInsets=" + mContentInsets.toShortString()
                     + " mReducedResolution=" + mReducedResolution + " mScale=" + mScale
                     + " mIsRealSnapshot=" + mIsRealSnapshot + " mWindowingMode=" + mWindowingMode
@@ -2129,6 +2162,7 @@
             private GraphicBuffer mSnapshot;
             private ColorSpace mColorSpace;
             private int mOrientation;
+            private int mRotation;
             private Rect mContentInsets;
             private boolean mReducedResolution;
             private float mScaleFraction;
@@ -2163,6 +2197,11 @@
                 return this;
             }
 
+            public Builder setRotation(int rotation) {
+                mRotation = rotation;
+                return this;
+            }
+
             public Builder setContentInsets(Rect contentInsets) {
                 mContentInsets = contentInsets;
                 return this;
@@ -2218,6 +2257,7 @@
                         mSnapshot,
                         mColorSpace,
                         mOrientation,
+                        mRotation,
                         mContentInsets,
                         mReducedResolution,
                         mScaleFraction,
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 4f3e8ec..4e47594 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -367,4 +367,20 @@
      * Unregisters the specified {@code processObserver}.
      */
     public abstract void unregisterProcessObserver(IProcessObserver processObserver);
+
+    /**
+     * Checks if there is an unfinished instrumentation that targets the given uid.
+     *
+     * @param uid The uid to be checked for
+     *
+     * @return True, if there is an instrumentation whose target application uid matches the given
+     * uid, false otherwise
+     */
+    public abstract boolean isUidCurrentlyInstrumented(int uid);
+
+    /**
+     * Show a debug toast, asking user to file a bugreport.
+     */
+    // TODO: remove this toast after feature development is done
+    public abstract void showWhileInUseDebugToast(int uid, int op, int mode);
 }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 247ddb6..c901d2a 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -111,6 +111,8 @@
 import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.StatsFrameworkInitializer;
+import android.os.StatsServiceManager;
 import android.os.StrictMode;
 import android.os.SystemClock;
 import android.os.SystemProperties;
@@ -924,10 +926,6 @@
     private class ApplicationThread extends IApplicationThread.Stub {
         private static final String DB_INFO_FORMAT = "  %8s %8s %14s %14s  %s";
 
-        public final void scheduleSleeping(IBinder token, boolean sleeping) {
-            sendMessage(H.SLEEPING, token, sleeping ? 1 : 0);
-        }
-
         public final void scheduleReceiver(Intent intent, ActivityInfo info,
                 CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
                 boolean sync, int sendingUser, int processState) {
@@ -1855,7 +1853,6 @@
                     case SCHEDULE_CRASH: return "SCHEDULE_CRASH";
                     case DUMP_HEAP: return "DUMP_HEAP";
                     case DUMP_ACTIVITY: return "DUMP_ACTIVITY";
-                    case SLEEPING: return "SLEEPING";
                     case SET_CORE_SETTINGS: return "SET_CORE_SETTINGS";
                     case UPDATE_PACKAGE_COMPATIBILITY_INFO: return "UPDATE_PACKAGE_COMPATIBILITY_INFO";
                     case DUMP_PROVIDER: return "DUMP_PROVIDER";
@@ -1985,11 +1982,6 @@
                 case DUMP_PROVIDER:
                     handleDumpProvider((DumpComponentInfo)msg.obj);
                     break;
-                case SLEEPING:
-                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "sleeping");
-                    handleSleeping((IBinder)msg.obj, msg.arg1 != 0);
-                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
-                    break;
                 case SET_CORE_SETTINGS:
                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setCoreSettings");
                     handleSetCoreSettings((Bundle) msg.obj);
@@ -4855,41 +4847,6 @@
         }
     }
 
-    // TODO: This method should be changed to use {@link #performStopActivityInner} to perform to
-    // stop operation on the activity to reduce code duplication and the chance of fixing a bug in
-    // one place and missing the other.
-    private void handleSleeping(IBinder token, boolean sleeping) {
-        ActivityClientRecord r = mActivities.get(token);
-
-        if (r == null) {
-            Log.w(TAG, "handleSleeping: no activity for token " + token);
-            return;
-        }
-
-        if (sleeping) {
-            if (!r.stopped && !r.isPreHoneycomb()) {
-                callActivityOnStop(r, true /* saveState */, "sleeping");
-            }
-
-            // Make sure any pending writes are now committed.
-            if (!r.isPreHoneycomb()) {
-                QueuedWork.waitToFinish();
-            }
-
-            // Tell activity manager we slept.
-            try {
-                ActivityTaskManager.getService().activitySlept(r.token);
-            } catch (RemoteException ex) {
-                throw ex.rethrowFromSystemServer();
-            }
-        } else {
-            if (r.stopped && r.activity.mVisibleFromServer) {
-                r.activity.performRestart(true /* start */, "handleSleeping");
-                r.setState(ON_START);
-            }
-        }
-    }
-
     private void handleSetCoreSettings(Bundle coreSettings) {
         synchronized (mResourcesManager) {
             mCoreSettings = coreSettings;
@@ -7523,6 +7480,7 @@
      */
     public static void initializeMainlineModules() {
         TelephonyFrameworkInitializer.setTelephonyServiceManager(new TelephonyServiceManager());
+        StatsFrameworkInitializer.setStatsServiceManager(new StatsServiceManager());
     }
 
     private void purgePendingResources() {
diff --git a/core/java/android/app/AppOpsManagerInternal.java b/core/java/android/app/AppOpsManagerInternal.java
index 099037c..9958c6a 100644
--- a/core/java/android/app/AppOpsManagerInternal.java
+++ b/core/java/android/app/AppOpsManagerInternal.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.util.SparseArray;
 import android.util.SparseIntArray;
 
 import com.android.internal.util.function.HexFunction;
@@ -82,4 +83,12 @@
      * access to app ops for their user.
      */
     public abstract void setDeviceAndProfileOwners(SparseIntArray owners);
+
+    /**
+     * Update if the list of AppWidget becomes visible/invisible.
+     * @param uidPackageNames uid to packageName map.
+     * @param visible true for visible, false for invisible.
+     */
+    public abstract void updateAppWidgetVisibility(SparseArray<String> uidPackageNames,
+            boolean visible);
 }
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 4e6319d..c09aa1f 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -131,7 +131,7 @@
     private static final int DEFAULT_EPHEMERAL_COOKIE_MAX_SIZE_BYTES = 16384; // 16KB
 
     // Default flags to use with PackageManager when no flags are given.
-    private final static int sDefaultFlags = PackageManager.GET_SHARED_LIBRARY_FILES;
+    private static final int sDefaultFlags = GET_SHARED_LIBRARY_FILES;
 
     // Name of the resource which provides background permission button string
     public static final String APP_PERMISSION_BUTTON_ALLOW_ALWAYS =
@@ -907,7 +907,7 @@
 
     @Override
     public boolean hasSigningCertificate(
-            String packageName, byte[] certificate, @PackageManager.CertificateInputType int type) {
+            String packageName, byte[] certificate, @CertificateInputType int type) {
         try {
             return mPM.hasSigningCertificate(packageName, certificate, type);
         } catch (RemoteException e) {
@@ -917,7 +917,7 @@
 
     @Override
     public boolean hasSigningCertificate(
-            int uid, byte[] certificate, @PackageManager.CertificateInputType int type) {
+            int uid, byte[] certificate, @CertificateInputType int type) {
         try {
             return mPM.hasUidSigningCertificate(uid, certificate, type);
         } catch (RemoteException e) {
@@ -1464,8 +1464,7 @@
             return getActivityIcon(intent.getComponent());
         }
 
-        ResolveInfo info = resolveActivity(
-            intent, PackageManager.MATCH_DEFAULT_ONLY);
+        ResolveInfo info = resolveActivity(intent, MATCH_DEFAULT_ONLY);
         if (info != null) {
             return info.activityInfo.loadIcon(this);
         }
@@ -1500,7 +1499,7 @@
         }
 
         ResolveInfo info = resolveActivity(
-                intent, PackageManager.MATCH_DEFAULT_ONLY);
+                intent, MATCH_DEFAULT_ONLY);
         if (info != null) {
             return info.activityInfo.loadBanner(this);
         }
@@ -1532,8 +1531,7 @@
             return getActivityLogo(intent.getComponent());
         }
 
-        ResolveInfo info = resolveActivity(
-            intent, PackageManager.MATCH_DEFAULT_ONLY);
+        ResolveInfo info = resolveActivity(intent, MATCH_DEFAULT_ONLY);
         if (info != null) {
             return info.activityInfo.loadLogo(this);
         }
@@ -2017,7 +2015,7 @@
 
     @Override
     public int installExistingPackage(String packageName) throws NameNotFoundException {
-        return installExistingPackage(packageName, PackageManager.INSTALL_REASON_UNKNOWN);
+        return installExistingPackage(packageName, INSTALL_REASON_UNKNOWN);
     }
 
     @Override
@@ -2029,7 +2027,7 @@
     @Override
     public int installExistingPackageAsUser(String packageName, int userId)
             throws NameNotFoundException {
-        return installExistingPackageAsUser(packageName, PackageManager.INSTALL_REASON_UNKNOWN,
+        return installExistingPackageAsUser(packageName, INSTALL_REASON_UNKNOWN,
                 userId);
     }
 
@@ -2404,7 +2402,7 @@
     public void deletePackageAsUser(String packageName, IPackageDeleteObserver observer,
             int flags, int userId) {
         try {
-            mPM.deletePackageAsUser(packageName, PackageManager.VERSION_CODE_HIGHEST,
+            mPM.deletePackageAsUser(packageName, VERSION_CODE_HIGHEST,
                     observer, userId, flags);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -2651,11 +2649,11 @@
     public void setSyntheticAppDetailsActivityEnabled(String packageName, boolean enabled) {
         try {
             ComponentName componentName = new ComponentName(packageName,
-                    PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME);
+                    APP_DETAILS_ACTIVITY_CLASS_NAME);
             mPM.setComponentEnabledSetting(componentName, enabled
-                    ? PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
-                    : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
-                    PackageManager.DONT_KILL_APP, getUserId());
+                    ? COMPONENT_ENABLED_STATE_DEFAULT
+                    : COMPONENT_ENABLED_STATE_DISABLED,
+                    DONT_KILL_APP, getUserId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -2665,10 +2663,10 @@
     public boolean getSyntheticAppDetailsActivityEnabled(String packageName) {
         try {
             ComponentName componentName = new ComponentName(packageName,
-                    PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME);
+                    APP_DETAILS_ACTIVITY_CLASS_NAME);
             int state = mPM.getComponentEnabledSetting(componentName, getUserId());
-            return state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED
-                    || state == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
+            return state == COMPONENT_ENABLED_STATE_ENABLED
+                    || state == COMPONENT_ENABLED_STATE_DEFAULT;
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -2744,6 +2742,30 @@
 
     /** @hide */
     @Override
+    public void setSystemAppState(String packageName, @SystemAppState int state) {
+        try {
+            switch (state) {
+                case SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN:
+                    mPM.setSystemAppHiddenUntilInstalled(packageName, true);
+                    break;
+                case SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_VISIBLE:
+                    mPM.setSystemAppHiddenUntilInstalled(packageName, false);
+                    break;
+                case SYSTEM_APP_STATE_INSTALLED:
+                    mPM.setSystemAppInstallState(packageName, true, getUserId());
+                    break;
+                case SYSTEM_APP_STATE_UNINSTALLED:
+                    mPM.setSystemAppInstallState(packageName, false, getUserId());
+                    break;
+                default:
+            }
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /** @hide */
+    @Override
     public KeySet getKeySetByAlias(String packageName, String alias) {
         Objects.requireNonNull(packageName);
         Objects.requireNonNull(alias);
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 7d04ca0..3ffd7c7 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -53,6 +53,7 @@
 import android.content.pm.ProviderInfo;
 import android.content.pm.UserInfo;
 import android.content.res.Configuration;
+import android.content.LocusId;
 import android.graphics.Bitmap;
 import android.graphics.GraphicBuffer;
 import android.graphics.Point;
@@ -637,4 +638,13 @@
      * and the given process is imperceptible.
      */
     void killProcessesWhenImperceptible(in int[] pids, String reason);
+
+    /**
+     * Set locus context for a given activity.
+     * @param activity
+     * @param locusId a unique, stable id that identifies this activity instance from others.
+     * @param appToken ActivityRecord's appToken.
+     */
+    void setActivityLocusContext(in ComponentName activity, in LocusId locusId,
+            in IBinder appToken);
 }
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index e5c046c..85fa7c1 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -141,7 +141,6 @@
             in PersistableBundle persistentState, in CharSequence description);
     oneway void activityDestroyed(in IBinder token);
     void activityRelaunched(in IBinder token);
-    oneway void activitySlept(in IBinder token);
     int getFrontActivityScreenCompatMode();
     void setFrontActivityScreenCompatMode(int mode);
     String getCallingPackage(in IBinder token);
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index 51a64ff..c33c515 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -91,7 +91,6 @@
             int resultCode, in String data, in Bundle extras, boolean ordered,
             boolean sticky, int sendingUser, int processState);
     void scheduleLowMemory();
-    void scheduleSleeping(IBinder token, boolean sleeping);
     void profilerControl(boolean start, in ProfilerInfo profilerInfo, int profileType);
     void setSchedulingGroup(int group);
     void scheduleCreateBackupAgent(in ApplicationInfo app, in CompatibilityInfo compatInfo,
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index d665f33..4b1ba02 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -18,6 +18,7 @@
 package android.app;
 
 import android.app.ITransientNotification;
+import android.app.ITransientNotificationCallback;
 import android.app.Notification;
 import android.app.NotificationChannel;
 import android.app.NotificationChannelGroup;
@@ -45,8 +46,7 @@
     void cancelAllNotifications(String pkg, int userId);
 
     void clearData(String pkg, int uid, boolean fromApp);
-    // TODO: Replace parameter (ITransientNotification callback) with (CharSequence text)
-    void enqueueTextToast(String pkg, IBinder token, ITransientNotification callback, int duration, int displayId);
+    void enqueueTextToast(String pkg, IBinder token, CharSequence text, int duration, int displayId, @nullable ITransientNotificationCallback callback);
     void enqueueToast(String pkg, IBinder token, ITransientNotification callback, int duration, int displayId);
     void cancelToast(String pkg, IBinder token);
     void finishToken(String pkg, IBinder token);
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl b/core/java/android/app/ITransientNotificationCallback.aidl
similarity index 67%
copy from telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl
copy to core/java/android/app/ITransientNotificationCallback.aidl
index e9cbd9c..abe254f 100644
--- a/telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl
+++ b/core/java/android/app/ITransientNotificationCallback.aidl
@@ -1,6 +1,5 @@
 /*
- *
- * Copyright 2019, The Android Open Source Project
+ * 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.
@@ -15,6 +14,14 @@
  * limitations under the License.
  */
 
-package android.telephony.ims;
+package android.app;
 
-parcelable RcsMessageQueryParams;
+/**
+ * Callback object to be called when the associated toast is shown or hidden.
+ *
+ * @hide
+ */
+oneway interface ITransientNotificationCallback {
+    void onToastShown();
+    void onToastHidden();
+}
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index 6518652..4b0cadb 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -17,19 +17,21 @@
 package android.app;
 
 import android.Manifest;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.app.admin.DevicePolicyManager;
+import android.app.admin.PasswordMetrics;
 import android.app.trust.ITrustManager;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.hardware.biometrics.BiometricPrompt;
 import android.os.Binder;
 import android.os.Build;
 import android.os.IBinder;
@@ -46,7 +48,11 @@
 
 import com.android.internal.policy.IKeyguardDismissCallback;
 import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockPatternView;
+import com.android.internal.widget.LockscreenCredential;
 
+import java.nio.charset.Charset;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -134,7 +140,7 @@
      * {@link android.app.Activity#RESULT_OK} if the user successfully completes the challenge.
      *
      * @return the intent for launching the activity or null if no password is required.
-     * @deprecated see {@link BiometricPrompt.Builder#setDeviceCredentialAllowed(boolean)}
+     * @deprecated see BiometricPrompt.Builder#setDeviceCredentialAllowed(boolean)
      */
     @Deprecated
     @RequiresFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN)
@@ -655,4 +661,151 @@
 
         }
     }
+
+    private boolean checkInitialLockMethodUsage() {
+        if (mContext.checkCallingOrSelfPermission(Manifest.permission.SET_INITIAL_LOCK)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Requires SET_INITIAL_LOCK permission.");
+        }
+        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+    * Determine if a given password is valid based off its lock type and expected complexity level.
+    *
+    * @param isPin - whether this is a PIN-type password (only digits)
+    * @param password - password to validate
+    * @param complexity - complexity level imposed by the requester
+    *        as defined in {@code DevicePolicyManager.PasswordComplexity}
+    * @return true if the password is valid, false otherwise
+    * @hide
+    */
+    @RequiresPermission(Manifest.permission.SET_INITIAL_LOCK)
+    @SystemApi
+    public boolean validateLockPasswordComplexity(
+            boolean isPin, @NonNull byte[] password, int complexity) {
+        if (!checkInitialLockMethodUsage()) {
+            return false;
+        }
+        complexity = PasswordMetrics.sanitizeComplexityLevel(complexity);
+        // TODO: b/131755827 add devicePolicyManager support for Auto
+        DevicePolicyManager devicePolicyManager =
+                (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+        PasswordMetrics adminMetrics =
+                devicePolicyManager.getPasswordMinimumMetrics(mContext.getUserId());
+
+        return PasswordMetrics.validatePassword(
+                adminMetrics, complexity, isPin, password).size() == 0;
+    }
+
+    /**
+    * Determine the minimum allowable length for a lock type for a given complexity level.
+    *
+    * @param isPin - whether this is a PIN-type password (only digits)
+    * @param complexity - complexity level imposed by the requester
+    *        as defined in {@code DevicePolicyManager.PasswordComplexity}
+    * @return minimum allowable password length
+    * @hide
+    */
+    @RequiresPermission(Manifest.permission.SET_INITIAL_LOCK)
+    @SystemApi
+    public int getMinLockLength(boolean isPin, int complexity) {
+        if (!checkInitialLockMethodUsage()) {
+            return -1;
+        }
+        complexity = PasswordMetrics.sanitizeComplexityLevel(complexity);
+        // TODO: b/131755827 add devicePolicyManager support for Auto
+        DevicePolicyManager devicePolicyManager =
+                (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+        PasswordMetrics adminMetrics =
+                devicePolicyManager.getPasswordMinimumMetrics(mContext.getUserId());
+        PasswordMetrics minMetrics =
+                PasswordMetrics.applyComplexity(adminMetrics, isPin, complexity);
+        return minMetrics.length;
+    }
+
+    /**
+    * Set the lockscreen password after validating against its expected complexity level.
+    *
+    * @param lockType - type of lock as specified in {@link LockTypes}
+    * @param password - password to validate
+    * @param complexity - complexity level imposed by the requester
+    *        as defined in {@code DevicePolicyManager.PasswordComplexity}
+    * @return true if the lock is successfully set, false otherwise
+    * @hide
+    */
+    @RequiresPermission(Manifest.permission.SET_INITIAL_LOCK)
+    @SystemApi
+    public boolean setLock(@LockTypes int lockType, @NonNull byte[] password, int complexity) {
+        if (!checkInitialLockMethodUsage()) {
+            return false;
+        }
+
+        LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext);
+        int userId = mContext.getUserId();
+        if (isDeviceSecure(userId)) {
+            Log.e(TAG, "Password already set, rejecting call to setLock");
+            return false;
+        }
+        if (!validateLockPasswordComplexity(lockType != LockTypes.PASSWORD, password, complexity)) {
+            Log.e(TAG, "Password is not valid, rejecting call to setLock");
+            return false;
+        }
+        boolean success = false;
+        try {
+            switch (lockType) {
+                case LockTypes.PASSWORD:
+                    CharSequence passwordStr = new String(password, Charset.forName("UTF-8"));
+                    lockPatternUtils.setLockCredential(
+                            LockscreenCredential.createPassword(passwordStr),
+                            /* savedPassword= */ LockscreenCredential.createNone(),
+                            userId);
+                    success = true;
+                    break;
+                case LockTypes.PIN:
+                    CharSequence pinStr = new String(password);
+                    lockPatternUtils.setLockCredential(
+                            LockscreenCredential.createPin(pinStr),
+                            /* savedPassword= */ LockscreenCredential.createNone(),
+                            userId);
+                    success = true;
+                    break;
+                case LockTypes.PATTERN:
+                    List<LockPatternView.Cell> pattern =
+                            LockPatternUtils.byteArrayToPattern(password);
+                    lockPatternUtils.setLockCredential(
+                            LockscreenCredential.createPattern(pattern),
+                            /* savedPassword= */ LockscreenCredential.createNone(),
+                            userId);
+                    pattern.clear();
+                    success = true;
+                    break;
+                default:
+                    Log.e(TAG, "Unknown lock type, returning a failure");
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Save lock exception", e);
+            success = false;
+        } finally {
+            Arrays.fill(password, (byte) 0);
+        }
+        return success;
+    }
+
+    /**
+    * Available lock types
+    */
+    @IntDef({
+            LockTypes.PASSWORD,
+            LockTypes.PIN,
+            LockTypes.PATTERN
+    })
+    @interface LockTypes {
+        int PASSWORD = 0;
+        int PIN = 1;
+        int PATTERN = 2;
+    }
 }
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 1af275f..35d26ab 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -17,6 +17,8 @@
 package android.app;
 
 import static android.annotation.Dimension.DP;
+import static android.graphics.drawable.Icon.TYPE_URI;
+import static android.graphics.drawable.Icon.TYPE_URI_ADAPTIVE_BITMAP;
 
 import static com.android.internal.util.ContrastColorUtil.satisfiesTextContrast;
 
@@ -2504,6 +2506,14 @@
                 }
             }
         }
+
+        if (mBubbleMetadata != null && mBubbleMetadata.getBubbleIcon() != null) {
+            final Icon icon = mBubbleMetadata.getBubbleIcon();
+            final int iconType = icon.getType();
+            if (iconType == TYPE_URI_ADAPTIVE_BITMAP || iconType == TYPE_URI) {
+                visitor.accept(icon.getUri());
+            }
+        }
     }
 
     /**
@@ -3559,8 +3569,16 @@
          * This field will be ignored by Launchers that don't support badging, don't show
          * notification content, or don't show {@link android.content.pm.ShortcutManager shortcuts}.
          *
+         * If this notification has {@link BubbleMetadata} attached that was created with
+         * {@link BubbleMetadata.Builder#createShortcutBubble(String)} a check will be performed
+         * to ensure the shortcutId supplied to bubble metadata matches the shortcutId set here,
+         * if one was set. If the shortcutId's were specified but do not match, an exception
+         * is thrown.
+         *
          * @param shortcutId the {@link ShortcutInfo#getId() id} of the shortcut this notification
          *                   supersedes
+         *
+         * @see BubbleMetadata.Builder#createShortcutBubble(String)
          */
         @NonNull
         public Builder setShortcutId(String shortcutId) {
@@ -5916,9 +5934,29 @@
         /**
          * Combine all of the options that have been set and return a new {@link Notification}
          * object.
+         *
+         * If this notification has {@link BubbleMetadata} attached that was created with
+         * {@link BubbleMetadata.Builder#createShortcutBubble(String)} a check will be performed
+         * to ensure the shortcutId supplied to bubble metadata matches the shortcutId set on the
+         * notification builder, if one was set. If the shortcutId's were specified but do not
+         * match, an exception is thrown here.
+         *
+         * @see BubbleMetadata.Builder#createShortcutBubble(String)
+         * @see #setShortcutId(String)
          */
         @NonNull
         public Notification build() {
+            // Check shortcut id matches
+            if (mN.mShortcutId != null
+                    && mN.mBubbleMetadata != null
+                    && mN.mBubbleMetadata.getShortcutId() != null
+                    && !mN.mShortcutId.equals(mN.mBubbleMetadata.getShortcutId())) {
+                throw new IllegalArgumentException(
+                        "Notification and BubbleMetadata shortcut id's don't match,"
+                                + " notification: " + mN.mShortcutId
+                                + " vs bubble: " + mN.mBubbleMetadata.getShortcutId());
+            }
+
             // first, add any extras from the calling code
             if (mUserExtras != null) {
                 mN.extras = getAllExtras();
@@ -8634,17 +8672,23 @@
         public static final int FLAG_AUTO_EXPAND_BUBBLE = 0x00000001;
 
         /**
-         * If set and the app posting the bubble is in the foreground, the bubble will
-         * be posted <b>without</b> the associated notification in the notification shade.
+         * Indicates whether the notification associated with the bubble is being visually
+         * suppressed from the notification shade. When <code>true</code> the notification is
+         * hidden, when <code>false</code> the notification shows as normal.
          *
-         * <p>This flag has no effect if the app posting the bubble is not in the foreground.
-         * The app is considered foreground if it is visible and on the screen, note that
-         * a foreground service does not qualify.
-         * </p>
+         * <p>Apps sending bubbles may set this flag so that the bubble is posted <b>without</b>
+         * the associated notification in the notification shade.</p>
          *
-         * <p>Generally this flag should only be set if the user has performed an action to request
-         * or create a bubble, or if the user has seen the content in the notification and the
-         * notification is no longer relevant.</p>
+         * <p>Apps sending bubbles can only apply this flag when the app is in the foreground,
+         * otherwise the flag is not respected. The app is considered foreground if it is visible
+         * and on the screen, note that a foreground service does not qualify.</p>
+         *
+         * <p>Generally this flag should only be set by the app if the user has performed an
+         * action to request or create a bubble, or if the user has seen the content in the
+         * notification and the notification is no longer relevant. </p>
+         *
+         * <p>The system will also update this flag with <code>true</code> to hide the notification
+         * from the user once the bubble has been expanded. </p>
          *
          * @hide
          */
@@ -8762,6 +8806,24 @@
         }
 
         /**
+         * Indicates whether the notification associated with the bubble is being visually
+         * suppressed from the notification shade. When <code>true</code> the notification is
+         * hidden, when <code>false</code> the notification shows as normal.
+         *
+         * <p>Apps sending bubbles may set this flag so that the bubble is posted <b>without</b>
+         * the associated notification in the notification shade.</p>
+         *
+         * <p>Apps sending bubbles can only apply this flag when the app is in the foreground,
+         * otherwise the flag is not respected. The app is considered foreground if it is visible
+         * and on the screen, note that a foreground service does not qualify.</p>
+         *
+         * <p>Generally the app should only set this flag if the user has performed an
+         * action to request or create a bubble, or if the user has seen the content in the
+         * notification and the notification is no longer relevant. </p>
+         *
+         * <p>The system will update this flag with <code>true</code> to hide the notification
+         * from the user once the bubble has been expanded.</p>
+         *
          * @return whether this bubble should suppress the notification when it is posted.
          *
          * @see BubbleMetadata.Builder#setSuppressNotification(boolean)
@@ -8900,6 +8962,12 @@
                 if (icon == null) {
                     throw new IllegalArgumentException("Bubbles require non-null icon");
                 }
+                if (icon.getType() != TYPE_URI_ADAPTIVE_BITMAP
+                        && icon.getType() != TYPE_URI) {
+                    Log.w(TAG, "Bubbles work best with icons of TYPE_URI or "
+                            + "TYPE_URI_ADAPTIVE_BITMAP. "
+                            + "In the future, using an icon of this type will be required.");
+                }
                 mShortcutId = null;
                 mPendingIntent = intent;
                 mIcon = icon;
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 7f69865..f170b5d 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -122,6 +122,7 @@
 import android.net.NetworkWatchlistManager;
 import android.net.TestNetworkManager;
 import android.net.TetheringManager;
+import android.net.VpnManager;
 import android.net.lowpan.ILowpanManager;
 import android.net.lowpan.LowpanManager;
 import android.net.nsd.INsdManager;
@@ -150,6 +151,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.ServiceManager.ServiceNotFoundException;
+import android.os.StatsFrameworkInitializer;
 import android.os.SystemConfigManager;
 import android.os.SystemUpdateManager;
 import android.os.SystemVibrator;
@@ -378,6 +380,15 @@
                 return new IpSecManager(ctx, service);
             }});
 
+        registerService(Context.VPN_MANAGEMENT_SERVICE, VpnManager.class,
+                new CachedServiceFetcher<VpnManager>() {
+            @Override
+            public VpnManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
+                IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
+                return new VpnManager(ctx, service);
+            }});
+
         registerService(Context.CONNECTIVITY_DIAGNOSTICS_SERVICE,
                 ConnectivityDiagnosticsManager.class,
                 new CachedServiceFetcher<ConnectivityDiagnosticsManager>() {
@@ -601,13 +612,6 @@
                         return SensorPrivacyManager.getInstance(ctx);
                     }});
 
-        registerService(Context.STATS_MANAGER, StatsManager.class,
-                new CachedServiceFetcher<StatsManager>() {
-            @Override
-            public StatsManager createService(ContextImpl ctx) {
-                return new StatsManager(ctx.getOuterContext());
-            }});
-
         registerService(Context.STATUS_BAR_SERVICE, StatusBarManager.class,
                 new CachedServiceFetcher<StatusBarManager>() {
             @Override
@@ -1327,6 +1331,7 @@
             TelephonyFrameworkInitializer.registerServiceWrappers();
             AppSearchManagerFrameworkInitializer.initialize();
             WifiFrameworkInitializer.registerServiceWrappers();
+            StatsFrameworkInitializer.registerServiceWrappers();
         } finally {
             // If any of the above code throws, we're in a pretty bad shape and the process
             // will likely crash, but we'll reset it just in case there's an exception handler...
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index aeeabb7..d1b5a83 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2403,11 +2403,19 @@
     public static final int PERSONAL_APPS_SUSPENDED_EXPLICITLY = 1 << 0;
 
     /**
+     * Flag for {@link #getPersonalAppsSuspendedReasons} return value. Set when personal apps are
+     * suspended by framework because managed profile was off for longer than allowed by policy.
+     * @see #setManagedProfileMaximumTimeOff
+     */
+    public static final int PERSONAL_APPS_SUSPENDED_PROFILE_TIMEOUT = 1 << 1;
+
+    /**
      * @hide
      */
     @IntDef(flag = true, prefix = { "PERSONAL_APPS_" }, value = {
             PERSONAL_APPS_NOT_SUSPENDED,
-            PERSONAL_APPS_SUSPENDED_EXPLICITLY
+            PERSONAL_APPS_SUSPENDED_EXPLICITLY,
+            PERSONAL_APPS_SUSPENDED_PROFILE_TIMEOUT
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface PersonalAppSuspensionReason {}
@@ -8260,6 +8268,11 @@
      * actual package file remain. This function can be called by a device owner, profile owner, or
      * by a delegate given the {@link #DELEGATION_PACKAGE_ACCESS} scope via
      * {@link #setDelegatedScopes}.
+     * <p>
+     * This method can be called on the {@link DevicePolicyManager} instance, returned by
+     * {@link #getParentProfileInstance(ComponentName)}, where the caller must be the profile owner
+     * of an organization-owned managed profile and the package must be a system package. If called
+     * on the parent instance, then the package is hidden or unhidden in the personal profile.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
      *            {@code null} if the caller is a package access delegate.
@@ -8267,17 +8280,20 @@
      * @param hidden {@code true} if the package should be hidden, {@code false} if it should be
      *            unhidden.
      * @return boolean Whether the hidden setting of the package was successfully updated.
-     * @throws SecurityException if {@code admin} is not a device or profile owner.
+     * @throws SecurityException if {@code admin} is not a device or profile owner or if called on
+     *            the parent profile and the {@code admin} is not a profile owner of an
+     *            organization-owned managed profile.
+     * @throws IllegalArgumentException if called on the parent profile and the package provided
+     *            is not a system package.
      * @see #setDelegatedScopes
      * @see #DELEGATION_PACKAGE_ACCESS
      */
     public boolean setApplicationHidden(@NonNull ComponentName admin, String packageName,
             boolean hidden) {
-        throwIfParentInstance("setApplicationHidden");
         if (mService != null) {
             try {
                 return mService.setApplicationHidden(admin, mContext.getPackageName(), packageName,
-                        hidden);
+                        hidden, mParentInstance);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -8289,20 +8305,30 @@
      * Determine if a package is hidden. This function can be called by a device owner, profile
      * owner, or by a delegate given the {@link #DELEGATION_PACKAGE_ACCESS} scope via
      * {@link #setDelegatedScopes}.
+     * <p>
+     * This method can be called on the {@link DevicePolicyManager} instance, returned by
+     * {@link #getParentProfileInstance(ComponentName)}, where the caller must be the profile owner
+     * of an organization-owned managed profile and the package must be a system package. If called
+     * on the parent instance, this will determine whether the package is hidden or unhidden in the
+     * personal profile.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
      *            {@code null} if the caller is a package access delegate.
      * @param packageName The name of the package to retrieve the hidden status of.
      * @return boolean {@code true} if the package is hidden, {@code false} otherwise.
-     * @throws SecurityException if {@code admin} is not a device or profile owner.
+     * @throws SecurityException if {@code admin} is not a device or profile owner or if called on
+     *            the parent profile and the {@code admin} is not a profile owner of an
+     *            organization-owned managed profile.
+     * @throws IllegalArgumentException if called on the parent profile and the package provided
+     *            is not a system package.
      * @see #setDelegatedScopes
      * @see #DELEGATION_PACKAGE_ACCESS
      */
     public boolean isApplicationHidden(@NonNull ComponentName admin, String packageName) {
-        throwIfParentInstance("isApplicationHidden");
         if (mService != null) {
             try {
-                return mService.isApplicationHidden(admin, mContext.getPackageName(), packageName);
+                return mService.isApplicationHidden(admin, mContext.getPackageName(), packageName,
+                        mParentInstance);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -8829,6 +8855,49 @@
     }
 
     /**
+     * Called by device owners to request a location provider to change its allowed state. For a
+     * provider to be enabled requires both that the master location setting is enabled, and that
+     * the provider itself is allowed. Most location providers are always allowed. Some location
+     * providers may have user consents or terms and conditions that must be accepted, or some other
+     * type of blocker before they are allowed however. Every location provider is responsible for
+     * its own allowed state.
+     *
+     * <p>This method requests that a location provider change its allowed state. For providers that
+     * are always allowed and have no state to change, this will have no effect. If the provider
+     * does require some consent, terms and conditions, or other blocking state, using this API
+     * implies that the device owner is agreeing/disagreeing to any consents, terms and conditions,
+     * etc, and the provider should make a best effort to adjust it's allowed state accordingly.
+     *
+     * <p>Location providers are generally only responsible for the current user, and callers must
+     * assume that this method will only affect provider state for the current user. Callers are
+     * responsible for tracking current user changes and re-updating provider state as necessary.
+     *
+     * <p>While providers are expected to make a best effort to honor this request, it is not a
+     * given that all providers will support such a request. If a provider does change its state as
+     * a result of this request, that may happen asynchronously after some delay. Test location
+     * providers set through {@link android.location.LocationManager#addTestProvider} will respond
+     * to this request to aide in testing.
+     *
+     * @param admin          Which {@link DeviceAdminReceiver} this request is associated with
+     * @param provider       A location provider as listed by
+     *                       {@link android.location.LocationManager#getAllProviders()}
+     * @param providerAllowed Whether the location provider is being requested to enable or disable
+     *                       itself
+     * @throws SecurityException if {@code admin} is not a device owner.
+     */
+    public void requestSetLocationProviderAllowed(@NonNull ComponentName admin,
+            @NonNull String provider, boolean providerAllowed) {
+        throwIfParentInstance("requestSetLocationProviderAllowed");
+        if (mService != null) {
+            try {
+                mService.requestSetLocationProviderAllowed(admin, provider, providerAllowed);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
      * Called by profile or device owners to update {@link android.provider.Settings.Secure}
      * settings. Validation that the value of the setting is in the correct form for the setting
      * type should be performed by the caller.
@@ -9091,7 +9160,8 @@
     }
 
     /**
-     * Called by device owners to set a local system update policy. When a new policy is set,
+     * Called by device owners or profile owners of an organization-owned managed profile to to set
+     * a local system update policy. When a new policy is set,
      * {@link #ACTION_SYSTEM_UPDATE_POLICY_CHANGED} is broadcasted.
      * <p>
      * If the supplied system update policy has freeze periods set but the freeze periods do not
@@ -9109,7 +9179,8 @@
      *            components in the device owner package can set system update policies and the most
      *            recent policy takes effect.
      * @param policy the new policy, or {@code null} to clear the current policy.
-     * @throws SecurityException if {@code admin} is not a device owner.
+     * @throws SecurityException if {@code admin} is not a device owner or a profile owner of an
+     *      organization-owned managed profile.
      * @throws IllegalArgumentException if the policy type or maintenance window is not valid.
      * @throws SystemUpdatePolicy.ValidationFailedException if the policy's freeze period does not
      *             meet the requirement.
@@ -11194,7 +11265,8 @@
     }
 
     /**
-     * Called by device owner to install a system update from the given file. The device will be
+     * Called by device owner or profile owner of an organization-owned managed profile to install
+     * a system update from the given file. The device will be
      * rebooted in order to finish installing the update. Note that if the device is rebooted, this
      * doesn't necessarily mean that the update has been applied successfully. The caller should
      * additionally check the system version with {@link android.os.Build#FINGERPRINT} or {@link
@@ -11742,6 +11814,8 @@
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with
      * @param suspended Whether personal apps should be suspended.
+     * @throws IllegalStateException if the profile owner doesn't have an activity that handles
+     *        {@link #ACTION_CHECK_POLICY_COMPLIANCE}
      */
     public void setPersonalAppsSuspended(@NonNull ComponentName admin, boolean suspended) {
         throwIfParentInstance("setPersonalAppsSuspended");
@@ -11753,4 +11827,52 @@
             }
         }
     }
+
+    /**
+     * Called by a profile owner of an organization-owned managed profile to set maximum time
+     * the profile is allowed to be turned off. If the profile is turned off for longer, personal
+     * apps are suspended on the device.
+     *
+     * <p>When personal apps are suspended, an ongoing notification about that is shown to the user.
+     * When the user taps the notification, system invokes {@link #ACTION_CHECK_POLICY_COMPLIANCE}
+     * in the profile owner package. Profile owner implementation that uses personal apps suspension
+     * must handle this intent.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with
+     * @param timeoutMs Maximum time the profile is allowed to be off in milliseconds or 0 if
+     *        not limited.
+     * @throws IllegalStateException if the profile owner doesn't have an activity that handles
+     *        {@link #ACTION_CHECK_POLICY_COMPLIANCE}
+     * @see #setPersonalAppsSuspended
+     */
+    public void setManagedProfileMaximumTimeOff(@NonNull ComponentName admin, long timeoutMs) {
+        throwIfParentInstance("setManagedProfileMaximumTimeOff");
+        if (mService != null) {
+            try {
+                mService.setManagedProfileMaximumTimeOff(admin, timeoutMs);
+            } catch (RemoteException re) {
+                throw re.rethrowFromSystemServer();
+            }
+        }
+    }
+
+     /**
+     * Called by a profile owner of an organization-owned managed profile to get maximum time
+     * the profile is allowed to be turned off.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with
+     * @return Maximum time the profile is allowed to be off in milliseconds or 0 if not limited.
+     * @see #setPersonalAppsSuspended
+     */
+    public long getManagedProfileMaximumTimeOff(@NonNull ComponentName admin) {
+        throwIfParentInstance("getManagedProfileMaximumTimeOff");
+        if (mService != null) {
+            try {
+                return mService.getManagedProfileMaximumTimeOff(admin);
+            } catch (RemoteException re) {
+                throw re.rethrowFromSystemServer();
+            }
+        }
+        return 0;
+    }
 }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index b9ffc4e..e3dba31 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -233,8 +233,8 @@
     boolean isNotificationListenerServicePermitted(in String packageName, int userId);
 
     Intent createAdminSupportIntent(in String restriction);
-    boolean setApplicationHidden(in ComponentName admin, in String callerPackage, in String packageName, boolean hidden);
-    boolean isApplicationHidden(in ComponentName admin, in String callerPackage, in String packageName);
+    boolean setApplicationHidden(in ComponentName admin, in String callerPackage, in String packageName, boolean hidden, boolean parent);
+    boolean isApplicationHidden(in ComponentName admin, in String callerPackage, in String packageName, boolean parent);
 
     UserHandle createAndManageUser(in ComponentName who, in String name, in ComponentName profileOwner, in PersistableBundle adminExtras, in int flags);
     boolean removeUser(in ComponentName who, in UserHandle userHandle);
@@ -270,6 +270,7 @@
     boolean isLockdownAdminConfiguredNetworks(in ComponentName who);
 
     void setLocationEnabled(in ComponentName who, boolean locationEnabled);
+    void requestSetLocationProviderAllowed(in ComponentName who, in String provider, boolean providerAllowed);
 
     boolean setTime(in ComponentName who, long millis);
     boolean setTimeZone(in ComponentName who, String timeZone);
@@ -473,4 +474,7 @@
 
     int getPersonalAppsSuspendedReasons(in ComponentName admin);
     void setPersonalAppsSuspended(in ComponentName admin, boolean suspended);
+
+    long getManagedProfileMaximumTimeOff(in ComponentName admin);
+    void setManagedProfileMaximumTimeOff(in ComponentName admin, long timeoutMs);
 }
diff --git a/core/java/android/app/admin/PasswordMetrics.java b/core/java/android/app/admin/PasswordMetrics.java
index 0ecfca7..86ebb47 100644
--- a/core/java/android/app/admin/PasswordMetrics.java
+++ b/core/java/android/app/admin/PasswordMetrics.java
@@ -682,6 +682,11 @@
      *
      * TODO: move to PasswordPolicy
      */
+    public static PasswordMetrics applyComplexity(
+            PasswordMetrics adminMetrics, boolean isPin, int complexity) {
+        return applyComplexity(adminMetrics, isPin, ComplexityBucket.forComplexity(complexity));
+    }
+
     private static PasswordMetrics applyComplexity(
             PasswordMetrics adminMetrics, boolean isPin, ComplexityBucket bucket) {
         final PasswordMetrics minMetrics = new PasswordMetrics(adminMetrics);
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index 6ab880d..ab71e73 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -290,10 +290,16 @@
         public static final int USER_STOPPED = 29;
 
         /**
+         * An event type denoting that new locusId has been set for a given activity.
+         * @hide
+         */
+        public static final int LOCUS_ID_SET = 30;
+
+        /**
          * Keep in sync with the greatest event type value.
          * @hide
          */
-        public static final int MAX_EVENT_TYPE = 29;
+        public static final int MAX_EVENT_TYPE = 30;
 
         /** @hide */
         public static final int FLAG_IS_PACKAGE_INSTANT_APP = 1 << 0;
@@ -436,6 +442,18 @@
          */
         public int mNotificationChannelIdToken = UNASSIGNED_TOKEN;
 
+        /**
+         * LocusId.
+         * Currently LocusId only present for {@link #LOCUS_ID_SET} event types.
+         * {@hide}
+         */
+        public String mLocusId;
+
+        /**
+         * {@hide}
+         */
+        public int mLocusIdToken = UNASSIGNED_TOKEN;
+
         /** @hide */
         @EventFlags
         public int mFlags;
@@ -609,6 +627,16 @@
             return ret;
         }
 
+        /**
+         * Returns the locusId for this event if the event is of type {@link #LOCUS_ID_SET},
+         * otherwise it returns null.
+         * @hide
+         */
+        @Nullable
+        public String getLocusId() {
+            return mLocusId;
+        }
+
         private void copyFrom(Event orig) {
             mPackage = orig.mPackage;
             mClass = orig.mClass;
@@ -625,6 +653,7 @@
             mFlags = orig.mFlags;
             mBucketAndReason = orig.mBucketAndReason;
             mNotificationChannelId = orig.mNotificationChannelId;
+            mLocusId = orig.mLocusId;
         }
     }
 
@@ -823,6 +852,9 @@
             case Event.NOTIFICATION_INTERRUPTION:
                 p.writeString(event.mNotificationChannelId);
                 break;
+            case Event.LOCUS_ID_SET:
+                p.writeString(event.mLocusId);
+                break;
         }
         p.writeInt(event.mFlags);
     }
@@ -871,6 +903,7 @@
         eventOut.mContentType = null;
         eventOut.mContentAnnotations = null;
         eventOut.mNotificationChannelId = null;
+        eventOut.mLocusId = null;
 
         switch (eventOut.mEventType) {
             case Event.CONFIGURATION_CHANGE:
@@ -891,6 +924,9 @@
             case Event.NOTIFICATION_INTERRUPTION:
                 eventOut.mNotificationChannelId = p.readString();
                 break;
+            case Event.LOCUS_ID_SET:
+                eventOut.mLocusId = p.readString();
+                break;
         }
         eventOut.mFlags = p.readInt();
     }
diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java
index 8993de0..ee2cc6d 100755
--- a/core/java/android/bluetooth/BluetoothA2dpSink.java
+++ b/core/java/android/bluetooth/BluetoothA2dpSink.java
@@ -297,7 +297,8 @@
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
-    public boolean setConnectionPolicy(@Nullable BluetoothDevice device, int connectionPolicy) {
+    public boolean setConnectionPolicy(@Nullable BluetoothDevice device,
+            @ConnectionPolicy int connectionPolicy) {
         if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
         final IBluetoothA2dpSink service = getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
@@ -345,7 +346,7 @@
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public int getConnectionPolicy(@Nullable BluetoothDevice device) {
+    public @ConnectionPolicy int getConnectionPolicy(@Nullable BluetoothDevice device) {
         if (VDBG) log("getConnectionPolicy(" + device + ")");
         final IBluetoothA2dpSink service = getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index e751354..e24b040 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -3236,18 +3236,6 @@
     }
 
     /**
-     * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new
-     * API name, listenUsingL2capChannel.
-     * @hide
-     */
-    @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public BluetoothServerSocket listenUsingL2capCoc(int transport)
-            throws IOException {
-        Log.e(TAG, "listenUsingL2capCoc: PLEASE USE THE OFFICIAL API, listenUsingL2capChannel");
-        return listenUsingL2capChannel();
-    }
-
-    /**
      * Create an insecure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and
      * assign a dynamic PSM value. This socket can be used to listen for incoming connections. The
      * supported Bluetooth transport is LE only.
@@ -3294,19 +3282,6 @@
     }
 
     /**
-     * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new
-     * API name, listenUsingInsecureL2capChannel.
-     * @hide
-     */
-    @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public BluetoothServerSocket listenUsingInsecureL2capCoc(int transport)
-            throws IOException {
-        Log.e(TAG, "listenUsingInsecureL2capCoc: PLEASE USE THE OFFICIAL API, "
-                    + "listenUsingInsecureL2capChannel");
-        return listenUsingInsecureL2capChannel();
-    }
-
-    /**
      * Register a {@link #OnMetadataChangedListener} to receive update about metadata
      * changes for this {@link BluetoothDevice}.
      * Registration must be done when Bluetooth is ON and will last until
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 9fe4dd6..12dc814c 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -2172,17 +2172,6 @@
     }
 
     /**
-     * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new
-     * API name, createL2capChannel.
-     * @hide
-     */
-    @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public BluetoothSocket createL2capCocSocket(int transport, int psm) throws IOException {
-        Log.e(TAG, "createL2capCocSocket: PLEASE USE THE OFFICIAL API, createL2capChannel");
-        return createL2capChannel(psm);
-    }
-
-    /**
      * Create a Bluetooth L2CAP Connection-oriented Channel (CoC) {@link BluetoothSocket} that can
      * be used to start a secure outgoing connection to the remote device with the same dynamic
      * protocol/service multiplexer (PSM) value. The supported Bluetooth transport is LE only.
@@ -2213,17 +2202,6 @@
     }
 
     /**
-     * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new
-     * API name, createInsecureL2capChannel.
-     * @hide
-     */
-    @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public BluetoothSocket createInsecureL2capCocSocket(int transport, int psm) throws IOException {
-        Log.e(TAG, "createL2capCocSocket: PLEASE USE THE OFFICIAL API, createInsecureL2capChannel");
-        return createInsecureL2capChannel(psm);
-    }
-
-    /**
      * Set a keyed metadata of this {@link BluetoothDevice} to a
      * {@link String} value.
      * Only bonded devices's metadata will be persisted across Bluetooth
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java
index 6de1ffb..fbda9e9 100644
--- a/core/java/android/bluetooth/BluetoothHeadsetClient.java
+++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java
@@ -584,7 +584,8 @@
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
-    public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) {
+    public boolean setConnectionPolicy(BluetoothDevice device,
+            @ConnectionPolicy int connectionPolicy) {
         if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
         final IBluetoothHeadsetClient service =
                 getService();
@@ -633,7 +634,7 @@
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public int getConnectionPolicy(BluetoothDevice device) {
+    public @ConnectionPolicy int getConnectionPolicy(BluetoothDevice device) {
         if (VDBG) log("getConnectionPolicy(" + device + ")");
         final IBluetoothHeadsetClient service =
                 getService();
diff --git a/core/java/android/bluetooth/BluetoothHidHost.java b/core/java/android/bluetooth/BluetoothHidHost.java
index c1233b8..26e3e27 100644
--- a/core/java/android/bluetooth/BluetoothHidHost.java
+++ b/core/java/android/bluetooth/BluetoothHidHost.java
@@ -416,7 +416,8 @@
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
-    public boolean setConnectionPolicy(@Nullable BluetoothDevice device, int connectionPolicy) {
+    public boolean setConnectionPolicy(@Nullable BluetoothDevice device,
+            @ConnectionPolicy int connectionPolicy) {
         if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
         final IBluetoothHidHost service = getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
@@ -464,7 +465,7 @@
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public int getConnectionPolicy(@Nullable BluetoothDevice device) {
+    public @ConnectionPolicy int getConnectionPolicy(@Nullable BluetoothDevice device) {
         if (VDBG) log("getConnectionPolicy(" + device + ")");
         final IBluetoothHidHost service = getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
diff --git a/core/java/android/bluetooth/BluetoothMap.java b/core/java/android/bluetooth/BluetoothMap.java
index 4674706..1c62faa 100644
--- a/core/java/android/bluetooth/BluetoothMap.java
+++ b/core/java/android/bluetooth/BluetoothMap.java
@@ -340,7 +340,8 @@
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
-    public boolean setConnectionPolicy(@Nullable BluetoothDevice device, int connectionPolicy) {
+    public boolean setConnectionPolicy(@Nullable BluetoothDevice device,
+            @ConnectionPolicy int connectionPolicy) {
         if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
         final IBluetoothMap service = getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
@@ -388,7 +389,7 @@
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public int getConnectionPolicy(@Nullable BluetoothDevice device) {
+    public @ConnectionPolicy int getConnectionPolicy(@Nullable BluetoothDevice device) {
         if (VDBG) log("getConnectionPolicy(" + device + ")");
         final IBluetoothMap service = getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
diff --git a/core/java/android/bluetooth/BluetoothMapClient.java b/core/java/android/bluetooth/BluetoothMapClient.java
index 0aa5aac..8d2aadd 100644
--- a/core/java/android/bluetooth/BluetoothMapClient.java
+++ b/core/java/android/bluetooth/BluetoothMapClient.java
@@ -271,7 +271,8 @@
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
-    public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) {
+    public boolean setConnectionPolicy(BluetoothDevice device,
+            @ConnectionPolicy int connectionPolicy) {
         if (DBG) Log.d(TAG, "setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
         final IBluetoothMapClient service = getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
@@ -319,7 +320,7 @@
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public int getConnectionPolicy(BluetoothDevice device) {
+    public @ConnectionPolicy int getConnectionPolicy(BluetoothDevice device) {
         if (VDBG) Log.d(TAG, "getConnectionPolicy(" + device + ")");
         final IBluetoothMapClient service = getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
diff --git a/core/java/android/bluetooth/BluetoothPbapClient.java b/core/java/android/bluetooth/BluetoothPbapClient.java
index 9618ba0..9563c68 100644
--- a/core/java/android/bluetooth/BluetoothPbapClient.java
+++ b/core/java/android/bluetooth/BluetoothPbapClient.java
@@ -271,7 +271,8 @@
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
-    public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) {
+    public boolean setConnectionPolicy(BluetoothDevice device,
+            @ConnectionPolicy int connectionPolicy) {
         if (DBG) {
             log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
         }
@@ -323,7 +324,7 @@
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public int getConnectionPolicy(BluetoothDevice device) {
+    public @ConnectionPolicy int getConnectionPolicy(BluetoothDevice device) {
         if (VDBG) {
             log("getConnectionPolicy(" + device + ")");
         }
diff --git a/core/java/android/bluetooth/BluetoothSap.java b/core/java/android/bluetooth/BluetoothSap.java
index 8bf1b58..bfc3a4d 100644
--- a/core/java/android/bluetooth/BluetoothSap.java
+++ b/core/java/android/bluetooth/BluetoothSap.java
@@ -330,7 +330,8 @@
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
-    public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) {
+    public boolean setConnectionPolicy(BluetoothDevice device,
+            @ConnectionPolicy int connectionPolicy) {
         if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
         final IBluetoothSap service = getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
@@ -378,7 +379,7 @@
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public int getConnectionPolicy(BluetoothDevice device) {
+    public @ConnectionPolicy int getConnectionPolicy(BluetoothDevice device) {
         if (VDBG) log("getConnectionPolicy(" + device + ")");
         final IBluetoothSap service = getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index ebc5e0e..a0d5c10 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3394,6 +3394,7 @@
             CONNECTIVITY_SERVICE,
             //@hide: IP_MEMORY_STORE_SERVICE,
             IPSEC_SERVICE,
+            VPN_MANAGEMENT_SERVICE,
             TEST_NETWORK_SERVICE,
             //@hide: UPDATE_LOCK_SERVICE,
             //@hide: NETWORKMANAGEMENT_SERVICE,
@@ -3984,6 +3985,14 @@
     public static final String IPSEC_SERVICE = "ipsec";
 
     /**
+     * Use with {@link #getSystemService(String)} to retrieve a {@link android.net.VpnManager} to
+     * manage profiles for the platform built-in VPN.
+     *
+     * @see #getSystemService(String)
+     */
+    public static final String VPN_MANAGEMENT_SERVICE = "vpn_management";
+
+    /**
      * Use with {@link #getSystemService(String)} to retrieve a {@link
      * android.net.ConnectivityDiagnosticsManager} for performing network connectivity diagnostics
      * as well as receiving network connectivity information from the system.
@@ -4130,16 +4139,16 @@
     public static final String LOWPAN_SERVICE = "lowpan";
 
     /**
-     * Use with {@link #getSystemService(String)} to retrieve a {@link
-     * android.net.EthernetManager} for handling management of
-     * Ethernet access.
+     * Use with {@link #getSystemService(String)} to retrieve a {@link android.net.EthernetManager}
+     * for handling management of Ethernet access.
      *
      * @see #getSystemService(String)
      * @see android.net.EthernetManager
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
+    @TestApi
     public static final String ETHERNET_SERVICE = "ethernet";
 
     /**
@@ -5023,10 +5032,7 @@
     /**
      * Use with {@link #getSystemService(String)} to retrieve an
      * {@link android.telephony.ims.ImsManager}.
-     * @hide
      */
-    @SystemApi
-    @TestApi
     public static final String TELEPHONY_IMS_SERVICE = "telephony_ims";
 
     /**
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index c8c3102..acffec9 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -36,6 +36,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ShortcutInfo;
+import android.content.pm.SuspendDialogInfo;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Rect;
@@ -2667,6 +2668,34 @@
             "android.intent.action.SHOW_SUSPENDED_APP_DETAILS";
 
     /**
+     * Broadcast Action: Sent to indicate that the user unsuspended a package.
+     *
+     * <p>This can happen when the user taps on the neutral button of the
+     * {@linkplain SuspendDialogInfo suspend-dialog} which was created by using
+     * {@link SuspendDialogInfo#BUTTON_ACTION_UNSUSPEND}. This broadcast is only sent to the
+     * suspending app that originally specified this dialog while calling
+     * {@link PackageManager#setPackagesSuspended(String[], boolean, PersistableBundle,
+     * PersistableBundle, SuspendDialogInfo)}.
+     *
+     * <p>Includes an extra {@link #EXTRA_PACKAGE_NAME} which is the name of the package that just
+     * got unsuspended.
+     *
+     * <p class="note">This is a protected intent that can only be sent
+     * by the system. <em>This will be delivered to {@link BroadcastReceiver} components declared in
+     * the manifest.</em>
+     *
+     * @see PackageManager#setPackagesSuspended(String[], boolean, PersistableBundle,
+     * PersistableBundle, SuspendDialogInfo)
+     * @see PackageManager#isPackageSuspended()
+     * @see SuspendDialogInfo#BUTTON_ACTION_MORE_DETAILS
+     * @hide
+     */
+    @SystemApi
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_PACKAGE_UNSUSPENDED_MANUALLY =
+            "android.intent.action.PACKAGE_UNSUSPENDED_MANUALLY";
+
+    /**
      * Broadcast Action: Sent to a package that has been unsuspended.
      *
      * <p class="note">This is a protected intent that can only be sent
@@ -3629,7 +3658,9 @@
      * {@link android.Manifest.permission#MANAGE_USERS} to receive this broadcast.
      * @hide
      */
-    @UnsupportedAppUsage
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    @SystemApi
     public static final String ACTION_USER_SWITCHED =
             "android.intent.action.USER_SWITCHED";
 
@@ -4531,12 +4562,6 @@
     public static final String EXTRA_LTE_EARFCN_RSRP_BOOST = "LteEarfcnRsrpBoost";
 
     /**
-     * An parcelable extra used with {@link #ACTION_SERVICE_STATE} representing the service state.
-     * @hide
-     */
-    public static final String EXTRA_SERVICE_STATE = "android.intent.extra.SERVICE_STATE";
-
-    /**
      * The name of the extra used to define the text to be processed, as a
      * CharSequence. Note that this may be a styled CharSequence, so you must use
      * {@link Bundle#getCharSequence(String) Bundle.getCharSequence()} to retrieve it.
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl b/core/java/android/content/LocusId.aidl
similarity index 81%
copy from telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl
copy to core/java/android/content/LocusId.aidl
index e9cbd9c..eb98db0 100644
--- a/telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl
+++ b/core/java/android/content/LocusId.aidl
@@ -1,6 +1,5 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
+/**
+ * Copyright (c) 2020, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,6 +14,6 @@
  * limitations under the License.
  */
 
-package android.telephony.ims;
+package android.content;
 
-parcelable RcsMessageQueryParams;
+parcelable LocusId;
diff --git a/core/java/android/content/integrity/AppInstallMetadata.java b/core/java/android/content/integrity/AppInstallMetadata.java
index 85af881..351edc9 100644
--- a/core/java/android/content/integrity/AppInstallMetadata.java
+++ b/core/java/android/content/integrity/AppInstallMetadata.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,10 +17,6 @@
 package android.content.integrity;
 
 import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-
-import com.android.internal.annotations.VisibleForTesting;
 
 import java.util.Objects;
 
@@ -34,8 +30,6 @@
  *
  * @hide
  */
-@SystemApi
-@VisibleForTesting
 public final class AppInstallMetadata {
     private final String mPackageName;
     // Raw string encoding for the SHA-256 hash of the certificate of the app.
@@ -43,7 +37,7 @@
     private final String mInstallerName;
     // Raw string encoding for the SHA-256 hash of the certificate of the installer.
     private final String mInstallerCertificate;
-    private final int mVersionCode;
+    private final long mVersionCode;
     private final boolean mIsPreInstalled;
 
     private AppInstallMetadata(Builder builder) {
@@ -65,18 +59,18 @@
         return mAppCertificate;
     }
 
-    @Nullable
+    @NonNull
     public String getInstallerName() {
         return mInstallerName;
     }
 
-    @Nullable
+    @NonNull
     public String getInstallerCertificate() {
         return mInstallerCertificate;
     }
 
-    /** @see AppInstallMetadata.Builder#setVersionCode(int) */
-    public int getVersionCode() {
+    /** @see AppInstallMetadata.Builder#setVersionCode(long) */
+    public long getVersionCode() {
         return mVersionCode;
     }
 
@@ -104,7 +98,7 @@
         private String mAppCertificate;
         private String mInstallerName;
         private String mInstallerCertificate;
-        private int mVersionCode;
+        private long mVersionCode;
         private boolean mIsPreInstalled;
 
         /**
@@ -163,7 +157,7 @@
          * @see AppInstallMetadata#getVersionCode()
          */
         @NonNull
-        public Builder setVersionCode(int versionCode) {
+        public Builder setVersionCode(long versionCode) {
             this.mVersionCode = versionCode;
             return this;
         }
diff --git a/core/java/android/content/integrity/AtomicFormula.java b/core/java/android/content/integrity/AtomicFormula.java
index 574a93f..4c10a8f 100644
--- a/core/java/android/content/integrity/AtomicFormula.java
+++ b/core/java/android/content/integrity/AtomicFormula.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,15 +20,16 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
-import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
 import java.util.Objects;
 
 /**
@@ -38,29 +39,28 @@
  *
  * @hide
  */
-@SystemApi
 @VisibleForTesting
-public abstract class AtomicFormula implements Formula {
-
-    private static final String TAG = "AtomicFormula";
+public abstract class AtomicFormula extends IntegrityFormula {
 
     /** @hide */
     @IntDef(
             value = {
-                PACKAGE_NAME,
-                APP_CERTIFICATE,
-                INSTALLER_NAME,
-                INSTALLER_CERTIFICATE,
-                VERSION_CODE,
-                PRE_INSTALLED,
+                    PACKAGE_NAME,
+                    APP_CERTIFICATE,
+                    INSTALLER_NAME,
+                    INSTALLER_CERTIFICATE,
+                    VERSION_CODE,
+                    PRE_INSTALLED,
             })
     @Retention(RetentionPolicy.SOURCE)
-    public @interface Key {}
+    public @interface Key {
+    }
 
     /** @hide */
-    @IntDef(value = {EQ, LT, LE, GT, GE})
+    @IntDef(value = {EQ, GT, GTE})
     @Retention(RetentionPolicy.SOURCE)
-    public @interface Operator {}
+    public @interface Operator {
+    }
 
     /**
      * Package name of the app.
@@ -94,7 +94,7 @@
     /**
      * Version code of the app.
      *
-     * <p>Can only be used in {@link IntAtomicFormula}.
+     * <p>Can only be used in {@link LongAtomicFormula}.
      */
     public static final int VERSION_CODE = 4;
 
@@ -106,10 +106,8 @@
     public static final int PRE_INSTALLED = 5;
 
     public static final int EQ = 0;
-    public static final int LT = 1;
-    public static final int LE = 2;
-    public static final int GT = 3;
-    public static final int GE = 4;
+    public static final int GT = 1;
+    public static final int GTE = 2;
 
     private final @Key int mKey;
 
@@ -118,78 +116,99 @@
         mKey = key;
     }
 
-    /** An {@link AtomicFormula} with an key and int value. */
-    public static final class IntAtomicFormula extends AtomicFormula implements Parcelable {
-        private final int mValue;
-        private final @Operator int mOperator;
+    /** An {@link AtomicFormula} with an key and long value. */
+    public static final class LongAtomicFormula extends AtomicFormula implements Parcelable {
+        private final Long mValue;
+        private final @Operator Integer mOperator;
 
         /**
-         * Constructs a new {@link IntAtomicFormula}.
+         * Constructs an empty {@link LongAtomicFormula}. This should only be used as a base.
+         *
+         * <p>This formula will always return false.
+         *
+         * @throws IllegalArgumentException if {@code key} cannot be used with long value
+         */
+        public LongAtomicFormula(@Key int key) {
+            super(key);
+            checkArgument(
+                    key == VERSION_CODE,
+                    String.format(
+                            "Key %s cannot be used with LongAtomicFormula", keyToString(key)));
+            mValue = null;
+            mOperator = null;
+        }
+
+        /**
+         * Constructs a new {@link LongAtomicFormula}.
          *
          * <p>This formula will hold if and only if the corresponding information of an install
          * specified by {@code key} is of the correct relationship to {@code value} as specified by
          * {@code operator}.
          *
-         * @throws IllegalArgumentException if {@code key} cannot be used with integer value
+         * @throws IllegalArgumentException if {@code key} cannot be used with long value
          */
-        public IntAtomicFormula(@Key int key, @Operator int operator, int value) {
+        public LongAtomicFormula(@Key int key, @Operator int operator, long value) {
             super(key);
             checkArgument(
                     key == VERSION_CODE,
-                    String.format("Key %s cannot be used with IntAtomicFormula", keyToString(key)));
-            checkArgument(isValidOperator(operator),
-                    String.format("Unknown operator: %d", operator));
+                    String.format(
+                            "Key %s cannot be used with LongAtomicFormula", keyToString(key)));
+            checkArgument(
+                    isValidOperator(operator), String.format("Unknown operator: %d", operator));
             mOperator = operator;
             mValue = value;
         }
 
-        IntAtomicFormula(Parcel in) {
+        LongAtomicFormula(Parcel in) {
             super(in.readInt());
-            mValue = in.readInt();
+            mValue = in.readLong();
             mOperator = in.readInt();
         }
 
         @NonNull
-        public static final Creator<IntAtomicFormula> CREATOR =
-                new Creator<IntAtomicFormula>() {
+        public static final Creator<LongAtomicFormula> CREATOR =
+                new Creator<LongAtomicFormula>() {
                     @Override
-                    public IntAtomicFormula createFromParcel(Parcel in) {
-                        return new IntAtomicFormula(in);
+                    public LongAtomicFormula createFromParcel(Parcel in) {
+                        return new LongAtomicFormula(in);
                     }
 
                     @Override
-                    public IntAtomicFormula[] newArray(int size) {
-                        return new IntAtomicFormula[size];
+                    public LongAtomicFormula[] newArray(int size) {
+                        return new LongAtomicFormula[size];
                     }
                 };
 
         @Override
-        public boolean isSatisfied(@NonNull AppInstallMetadata appInstallMetadata) {
-            int metadataValue = getMetadataValueByKey(appInstallMetadata);
+        public int getTag() {
+            return IntegrityFormula.LONG_ATOMIC_FORMULA_TAG;
+        }
+
+        @Override
+        public boolean matches(AppInstallMetadata appInstallMetadata) {
+            if (mValue == null || mOperator == null) {
+                return false;
+            }
+
+            long metadataValue = getLongMetadataValue(appInstallMetadata, getKey());
             switch (mOperator) {
                 case EQ:
                     return metadataValue == mValue;
-                case LE:
-                    return metadataValue <= mValue;
-                case LT:
-                    return metadataValue < mValue;
-                case GE:
-                    return metadataValue >= mValue;
                 case GT:
                     return metadataValue > mValue;
+                case GTE:
+                    return metadataValue >= mValue;
                 default:
-                    Slog.i(TAG, String.format("Unexpected operator %d", mOperator));
-                    return false;
+                    throw new IllegalArgumentException(
+                            String.format("Unexpected operator %d", mOperator));
             }
         }
 
         @Override
-        public int getTag() {
-            return Formula.INT_ATOMIC_FORMULA_TAG;
-        }
-
-        @Override
         public String toString() {
+            if (mValue == null || mOperator == null) {
+                return String.format("(%s)", keyToString(getKey()));
+            }
             return String.format(
                     "(%s %s %s)", keyToString(getKey()), operatorToString(mOperator), mValue);
         }
@@ -202,7 +221,7 @@
             if (o == null || getClass() != o.getClass()) {
                 return false;
             }
-            IntAtomicFormula that = (IntAtomicFormula) o;
+            LongAtomicFormula that = (LongAtomicFormula) o;
             return getKey() == that.getKey()
                     && mValue == that.mValue
                     && mOperator == that.mOperator;
@@ -220,35 +239,35 @@
 
         @Override
         public void writeToParcel(@NonNull Parcel dest, int flags) {
+            if (mValue == null || mOperator == null) {
+                throw new IllegalStateException("Cannot write an empty LongAtomicFormula.");
+            }
             dest.writeInt(getKey());
-            dest.writeInt(mValue);
+            dest.writeLong(mValue);
             dest.writeInt(mOperator);
         }
 
-        public int getValue() {
+        public Long getValue() {
             return mValue;
         }
 
-        public int getOperator() {
+        public Integer getOperator() {
             return mOperator;
         }
 
-        private int getMetadataValueByKey(AppInstallMetadata appInstallMetadata) {
-            switch (getKey()) {
-                case VERSION_CODE:
-                    return appInstallMetadata.getVersionCode();
-                default:
-                    throw new IllegalStateException(
-                            "Unexpected key in IntAtomicFormula" + getKey());
-            }
-        }
-
         private static boolean isValidOperator(int operator) {
             return operator == EQ
-                    || operator == LT
-                    || operator == LE
                     || operator == GT
-                    || operator == GE;
+                    || operator == GTE;
+        }
+
+        private static long getLongMetadataValue(AppInstallMetadata appInstallMetadata, int key) {
+            switch (key) {
+                case AtomicFormula.VERSION_CODE:
+                    return appInstallMetadata.getVersionCode();
+                default:
+                    throw new IllegalStateException("Unexpected key in IntAtomicFormula" + key);
+            }
         }
     }
 
@@ -256,7 +275,27 @@
     public static final class StringAtomicFormula extends AtomicFormula implements Parcelable {
         private final String mValue;
         // Indicates whether the value is the actual value or the hashed value.
-        private final boolean mIsHashedValue;
+        private final Boolean mIsHashedValue;
+
+        /**
+         * Constructs an empty {@link StringAtomicFormula}. This should only be used as a base.
+         *
+         * <p>An empty formula will always match to false.
+         *
+         * @throws IllegalArgumentException if {@code key} cannot be used with string value
+         */
+        public StringAtomicFormula(@Key int key) {
+            super(key);
+            checkArgument(
+                    key == PACKAGE_NAME
+                            || key == APP_CERTIFICATE
+                            || key == INSTALLER_CERTIFICATE
+                            || key == INSTALLER_NAME,
+                    String.format(
+                            "Key %s cannot be used with StringAtomicFormula", keyToString(key)));
+            mValue = null;
+            mIsHashedValue = null;
+        }
 
         /**
          * Constructs a new {@link StringAtomicFormula}.
@@ -266,9 +305,8 @@
          *
          * @throws IllegalArgumentException if {@code key} cannot be used with string value
          */
-        public StringAtomicFormula(@Key int key, @NonNull String value, boolean isHashedValue) {
+        public StringAtomicFormula(@Key int key, @NonNull String value, boolean isHashed) {
             super(key);
-            mIsHashedValue = isHashedValue;
             checkArgument(
                     key == PACKAGE_NAME
                             || key == APP_CERTIFICATE
@@ -277,6 +315,30 @@
                     String.format(
                             "Key %s cannot be used with StringAtomicFormula", keyToString(key)));
             mValue = value;
+            mIsHashedValue = isHashed;
+        }
+
+        /**
+         * Constructs a new {@link StringAtomicFormula} together with handling the necessary
+         * hashing for the given key.
+         *
+         * <p> The value will be hashed with SHA256 and the hex digest will be computed; for
+         * all cases except when the key is PACKAGE_NAME or INSTALLER_NAME and the value
+         * is less than 33 characters.
+         *
+         * @throws IllegalArgumentException if {@code key} cannot be used with string value.
+         */
+        public StringAtomicFormula(@Key int key, @NonNull String value) {
+            super(key);
+            checkArgument(
+                    key == PACKAGE_NAME
+                            || key == APP_CERTIFICATE
+                            || key == INSTALLER_CERTIFICATE
+                            || key == INSTALLER_NAME,
+                    String.format(
+                            "Key %s cannot be used with StringAtomicFormula", keyToString(key)));
+            mValue = hashValue(key, value);
+            mIsHashedValue = !mValue.equals(value);
         }
 
         StringAtomicFormula(Parcel in) {
@@ -300,18 +362,23 @@
                 };
 
         @Override
-        public boolean isSatisfied(@NonNull AppInstallMetadata appInstallMetadata) {
-            String metadataValue = getMetadataValueByKey(appInstallMetadata);
-            return metadataValue.equals(mValue);
+        public int getTag() {
+            return IntegrityFormula.STRING_ATOMIC_FORMULA_TAG;
         }
 
         @Override
-        public int getTag() {
-            return Formula.STRING_ATOMIC_FORMULA_TAG;
+        public boolean matches(AppInstallMetadata appInstallMetadata) {
+            if (mValue == null || mIsHashedValue == null) {
+                return false;
+            }
+            return getStringMetadataValue(appInstallMetadata, getKey()).equals(mValue);
         }
 
         @Override
         public String toString() {
+            if (mValue == null || mIsHashedValue == null) {
+                return String.format("(%s)", keyToString(getKey()));
+            }
             return String.format("(%s %s %s)", keyToString(getKey()), operatorToString(EQ), mValue);
         }
 
@@ -339,40 +406,80 @@
 
         @Override
         public void writeToParcel(@NonNull Parcel dest, int flags) {
+            if (mValue == null || mIsHashedValue == null) {
+                throw new IllegalStateException("Cannot write an empty StringAtomicFormula.");
+            }
             dest.writeInt(getKey());
             dest.writeStringNoHelper(mValue);
             dest.writeByte((byte) (mIsHashedValue ? 1 : 0));
         }
 
-        @NonNull
         public String getValue() {
             return mValue;
         }
 
-        public boolean getIsHashedValue() {
+        public Boolean getIsHashedValue() {
             return mIsHashedValue;
         }
 
-        private String getMetadataValueByKey(AppInstallMetadata appInstallMetadata) {
-            switch (getKey()) {
-                case PACKAGE_NAME:
+        private static String getStringMetadataValue(
+                AppInstallMetadata appInstallMetadata, int key) {
+            switch (key) {
+                case AtomicFormula.PACKAGE_NAME:
                     return appInstallMetadata.getPackageName();
-                case APP_CERTIFICATE:
+                case AtomicFormula.APP_CERTIFICATE:
                     return appInstallMetadata.getAppCertificate();
-                case INSTALLER_CERTIFICATE:
+                case AtomicFormula.INSTALLER_CERTIFICATE:
                     return appInstallMetadata.getInstallerCertificate();
-                case INSTALLER_NAME:
+                case AtomicFormula.INSTALLER_NAME:
                     return appInstallMetadata.getInstallerName();
                 default:
                     throw new IllegalStateException(
-                            "Unexpected key in StringAtomicFormula: " + getKey());
+                            "Unexpected key in StringAtomicFormula: " + key);
+            }
+        }
+
+        private static String hashValue(@Key int key, String value) {
+            // Hash the string value unless it is a PACKAGE_NAME or INSTALLER_NAME and the value is
+            // less than 33 characters.
+            if (value.length() <= 32) {
+                if (key == PACKAGE_NAME || key == INSTALLER_NAME) {
+                    return value;
+                }
+            }
+            return hash(value);
+        }
+
+        private static String hash(String value) {
+            try {
+                MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
+                byte[] hashBytes = messageDigest.digest(value.getBytes(StandardCharsets.UTF_8));
+                return IntegrityUtils.getHexDigest(hashBytes);
+            } catch (NoSuchAlgorithmException e) {
+                throw new RuntimeException("SHA-256 algorithm not found", e);
             }
         }
     }
 
     /** An {@link AtomicFormula} with a key and boolean value. */
     public static final class BooleanAtomicFormula extends AtomicFormula implements Parcelable {
-        private final boolean mValue;
+        private final Boolean mValue;
+
+        /**
+         * Constructs an empty {@link BooleanAtomicFormula}. This should only be used as a base.
+         *
+         * <p>An empty formula will always match to false.
+         *
+         * @throws IllegalArgumentException if {@code key} cannot be used with boolean value
+         */
+        public BooleanAtomicFormula(@Key int key) {
+            super(key);
+            checkArgument(
+                    key == PRE_INSTALLED,
+                    String.format(
+                            "Key %s cannot be used with BooleanAtomicFormula", keyToString(key)));
+            mValue = null;
+        }
 
         /**
          * Constructs a new {@link BooleanAtomicFormula}.
@@ -411,18 +518,23 @@
                 };
 
         @Override
-        public boolean isSatisfied(@NonNull AppInstallMetadata appInstallMetadata) {
-            boolean metadataValue = getMetadataValueByKey(appInstallMetadata);
-            return metadataValue == mValue;
+        public int getTag() {
+            return IntegrityFormula.BOOLEAN_ATOMIC_FORMULA_TAG;
         }
 
         @Override
-        public int getTag() {
-            return Formula.BOOLEAN_ATOMIC_FORMULA_TAG;
+        public boolean matches(AppInstallMetadata appInstallMetadata) {
+            if (mValue == null) {
+                return false;
+            }
+            return getBooleanMetadataValue(appInstallMetadata, getKey()) == mValue;
         }
 
         @Override
         public String toString() {
+            if (mValue == null) {
+                return String.format("(%s)", keyToString(getKey()));
+            }
             return String.format("(%s %s %s)", keyToString(getKey()), operatorToString(EQ), mValue);
         }
 
@@ -450,21 +562,25 @@
 
         @Override
         public void writeToParcel(@NonNull Parcel dest, int flags) {
+            if (mValue == null) {
+                throw new IllegalStateException("Cannot write an empty BooleanAtomicFormula.");
+            }
             dest.writeInt(getKey());
             dest.writeByte((byte) (mValue ? 1 : 0));
         }
 
-        public boolean getValue() {
+        public Boolean getValue() {
             return mValue;
         }
 
-        private boolean getMetadataValueByKey(AppInstallMetadata appInstallMetadata) {
-            switch (getKey()) {
-                case PRE_INSTALLED:
+        private static boolean getBooleanMetadataValue(
+                AppInstallMetadata appInstallMetadata, int key) {
+            switch (key) {
+                case AtomicFormula.PRE_INSTALLED:
                     return appInstallMetadata.isPreInstalled();
                 default:
                     throw new IllegalStateException(
-                            "Unexpected key in BooleanAtomicFormula: " + getKey());
+                            "Unexpected key in BooleanAtomicFormula: " + key);
             }
         }
     }
@@ -496,14 +612,10 @@
         switch (op) {
             case EQ:
                 return "EQ";
-            case LT:
-                return "LT";
-            case LE:
-                return "LE";
             case GT:
                 return "GT";
-            case GE:
-                return "GE";
+            case GTE:
+                return "GTE";
             default:
                 throw new IllegalArgumentException("Unknown operator " + op);
         }
diff --git a/core/java/android/content/integrity/CompoundFormula.java b/core/java/android/content/integrity/CompoundFormula.java
index 2a651d9..56061df 100644
--- a/core/java/android/content/integrity/CompoundFormula.java
+++ b/core/java/android/content/integrity/CompoundFormula.java
@@ -20,10 +20,8 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
-import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
 
@@ -42,16 +40,11 @@
  *
  * @hide
  */
-@SystemApi
 @VisibleForTesting
-public final class CompoundFormula implements Formula, Parcelable {
-    private static final String TAG = "OpenFormula";
+public final class CompoundFormula extends IntegrityFormula implements Parcelable {
 
     /** @hide */
-    @IntDef(
-            value = {
-                AND, OR, NOT,
-            })
+    @IntDef(value = {AND, OR, NOT})
     @Retention(RetentionPolicy.SOURCE)
     public @interface Connector {}
 
@@ -65,7 +58,7 @@
     public static final int NOT = 2;
 
     private final @Connector int mConnector;
-    private final @NonNull List<Formula> mFormulas;
+    private final @NonNull List<IntegrityFormula> mFormulas;
 
     @NonNull
     public static final Creator<CompoundFormula> CREATOR =
@@ -85,9 +78,10 @@
      * Create a new formula from operator and operands.
      *
      * @throws IllegalArgumentException if the number of operands is not matching the requirements
-     *     for that operator (at least 2 for {@link #AND} and {@link #OR}, 1 for {@link #NOT}).
+     *                                  for that operator (at least 2 for {@link #AND} and {@link
+     *                                  #OR}, 1 for {@link #NOT}).
      */
-    public CompoundFormula(@Connector int connector, @NonNull List<Formula> formulas) {
+    public CompoundFormula(@Connector int connector, List<IntegrityFormula> formulas) {
         checkArgument(
                 isValidConnector(connector), String.format("Unknown connector: %d", connector));
         validateFormulas(connector, formulas);
@@ -101,7 +95,7 @@
         checkArgument(length >= 0, "Must have non-negative length. Got " + length);
         mFormulas = new ArrayList<>(length);
         for (int i = 0; i < length; i++) {
-            mFormulas.add(Formula.readFromParcel(in));
+            mFormulas.add(IntegrityFormula.readFromParcel(in));
         }
         validateFormulas(mConnector, mFormulas);
     }
@@ -111,30 +105,29 @@
     }
 
     @NonNull
-    public List<Formula> getFormulas() {
+    public List<IntegrityFormula> getFormulas() {
         return mFormulas;
     }
 
     @Override
-    public boolean isSatisfied(@NonNull AppInstallMetadata appInstallMetadata) {
-        switch (mConnector) {
-            case NOT:
-                return !mFormulas.get(0).isSatisfied(appInstallMetadata);
-            case AND:
-                return mFormulas.stream()
-                        .allMatch(formula -> formula.isSatisfied(appInstallMetadata));
-            case OR:
-                return mFormulas.stream()
-                        .anyMatch(formula -> formula.isSatisfied(appInstallMetadata));
-            default:
-                Slog.i(TAG, "Unknown connector " + mConnector);
-                return false;
-        }
+    public int getTag() {
+        return IntegrityFormula.COMPOUND_FORMULA_TAG;
     }
 
     @Override
-    public int getTag() {
-        return Formula.COMPOUND_FORMULA_TAG;
+    public boolean matches(AppInstallMetadata appInstallMetadata) {
+        switch (getConnector()) {
+            case NOT:
+                return !getFormulas().get(0).matches(appInstallMetadata);
+            case AND:
+                return getFormulas().stream()
+                        .allMatch(formula -> formula.matches(appInstallMetadata));
+            case OR:
+                return getFormulas().stream()
+                        .anyMatch(formula -> formula.matches(appInstallMetadata));
+            default:
+                throw new IllegalArgumentException("Unknown connector " + getConnector());
+        }
     }
 
     @Override
@@ -180,12 +173,13 @@
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeInt(mConnector);
         dest.writeInt(mFormulas.size());
-        for (Formula formula : mFormulas) {
-            Formula.writeToParcel(formula, dest, flags);
+        for (IntegrityFormula formula : mFormulas) {
+            IntegrityFormula.writeToParcel(formula, dest, flags);
         }
     }
 
-    private static void validateFormulas(@Connector int connector, List<Formula> formulas) {
+    private static void validateFormulas(
+            @Connector int connector, List<IntegrityFormula> formulas) {
         switch (connector) {
             case AND:
             case OR:
diff --git a/core/java/android/content/integrity/Formula.java b/core/java/android/content/integrity/Formula.java
deleted file mode 100644
index b092a22..0000000
--- a/core/java/android/content/integrity/Formula.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.integrity;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.content.integrity.AtomicFormula.BooleanAtomicFormula;
-import android.content.integrity.AtomicFormula.IntAtomicFormula;
-import android.content.integrity.AtomicFormula.StringAtomicFormula;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Represents a rule logic/content.
- *
- * @hide
- */
-@SystemApi
-@VisibleForTesting
-public interface Formula {
-    /** @hide */
-    @IntDef(
-            value = {
-                    COMPOUND_FORMULA_TAG,
-                    STRING_ATOMIC_FORMULA_TAG,
-                    INT_ATOMIC_FORMULA_TAG,
-                    BOOLEAN_ATOMIC_FORMULA_TAG
-            })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface Tag {}
-
-    int COMPOUND_FORMULA_TAG = 0;
-    int STRING_ATOMIC_FORMULA_TAG = 1;
-    int INT_ATOMIC_FORMULA_TAG = 2;
-    int BOOLEAN_ATOMIC_FORMULA_TAG = 3;
-
-    /**
-     * Returns if this formula can be satisfied by substituting the corresponding information of
-     * {@code appInstallMetadata} into the formula.
-     */
-    boolean isSatisfied(@NonNull AppInstallMetadata appInstallMetadata);
-
-    /** Returns the tag that identifies the current class. */
-    @Tag int getTag();
-
-    /**
-     * Write a {@link Formula} to {@link android.os.Parcel}.
-     *
-     * <p>This helper method is needed because non-final class/interface are not allowed to be
-     * {@link Parcelable}.
-     *
-     * @throws IllegalArgumentException if {@link Formula} is not a recognized subclass
-     */
-    static void writeToParcel(@NonNull Formula formula, @NonNull Parcel dest, int flags) {
-        dest.writeInt(formula.getTag());
-        ((Parcelable) formula).writeToParcel(dest, flags);
-    }
-
-    /**
-     * Read a {@link Formula} from a {@link android.os.Parcel}.
-     *
-     * <p>We need this (hacky) helper method because non-final class/interface cannot be {@link
-     * Parcelable} (api lint error).
-     *
-     * @throws IllegalArgumentException if the parcel cannot be parsed
-     */
-    @NonNull
-    static Formula readFromParcel(@NonNull Parcel in) {
-        int tag = in.readInt();
-        switch (tag) {
-            case COMPOUND_FORMULA_TAG:
-                return CompoundFormula.CREATOR.createFromParcel(in);
-            case STRING_ATOMIC_FORMULA_TAG:
-                return StringAtomicFormula.CREATOR.createFromParcel(in);
-            case INT_ATOMIC_FORMULA_TAG:
-                return IntAtomicFormula.CREATOR.createFromParcel(in);
-            case BOOLEAN_ATOMIC_FORMULA_TAG:
-                return BooleanAtomicFormula.CREATOR.createFromParcel(in);
-            default:
-                throw new IllegalArgumentException("Unknown formula tag " + tag);
-        }
-    }
-}
diff --git a/core/java/android/content/integrity/IntegrityFormula.java b/core/java/android/content/integrity/IntegrityFormula.java
new file mode 100644
index 0000000..0660f93
--- /dev/null
+++ b/core/java/android/content/integrity/IntegrityFormula.java
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.integrity;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.content.integrity.AtomicFormula.BooleanAtomicFormula;
+import android.content.integrity.AtomicFormula.LongAtomicFormula;
+import android.content.integrity.AtomicFormula.StringAtomicFormula;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+
+/**
+ * Represents a rule logic/content.
+ *
+ * @hide
+ */
+@SystemApi
+@VisibleForTesting
+public abstract class IntegrityFormula {
+
+    /**
+     * A static formula base for package name formulas.
+     *
+     * This formulation is incomplete and should always be used with {@code equals} formulation.
+     * Evaluates to false when used directly and cannot be written as a parcel.
+     */
+    @NonNull
+    public static final IntegrityFormula PACKAGE_NAME =
+            new StringAtomicFormula(AtomicFormula.PACKAGE_NAME);
+
+    /**
+     * A static formula base for app certificate formulas.
+     *
+     * This formulation is incomplete and should always be used with {@code equals} formulation.
+     * Evaluates to false when used directly and cannot be written as a parcel.
+     */
+    @NonNull
+    public static final IntegrityFormula APP_CERTIFICATE =
+            new StringAtomicFormula(AtomicFormula.APP_CERTIFICATE);
+
+    /**
+     * A static formula base for installer name formulas.
+     *
+     * This formulation is incomplete and should always be used with {@code equals} formulation.
+     * Evaluates to false when used directly and cannot be written as a parcel.
+     */
+    @NonNull
+    public static final IntegrityFormula INSTALLER_NAME =
+            new StringAtomicFormula(AtomicFormula.INSTALLER_NAME);
+
+    /**
+     * A static formula base for installer certificate formulas.
+     *
+     * This formulation is incomplete and should always be used with {@code equals} formulation.
+     * Evaluates to false when used directly and cannot be written as a parcel.
+     */
+    @NonNull
+    public static final IntegrityFormula INSTALLER_CERTIFICATE =
+            new StringAtomicFormula(AtomicFormula.INSTALLER_CERTIFICATE);
+
+    /**
+     * A static formula base for version code name formulas.
+     *
+     * This formulation is incomplete and should always be used with {@code equals},
+     * {@code greaterThan} and {@code greaterThanEquals} formulation. Evaluates to false when used
+     * directly and cannot be written as a parcel.
+     */
+    @NonNull
+    public static final IntegrityFormula VERSION_CODE =
+            new LongAtomicFormula(AtomicFormula.VERSION_CODE);
+
+    /**
+     * A static formula base for pre-installed status formulas.
+     *
+     * This formulation is incomplete and should always be used with {@code equals} formulation.
+     * Evaluates to false when used directly and cannot be written as a parcel.
+     */
+    @NonNull
+    public static final IntegrityFormula PRE_INSTALLED =
+            new BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED);
+
+    /** @hide */
+    @IntDef(
+            value = {
+                    COMPOUND_FORMULA_TAG,
+                    STRING_ATOMIC_FORMULA_TAG,
+                    LONG_ATOMIC_FORMULA_TAG,
+                    BOOLEAN_ATOMIC_FORMULA_TAG
+            })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface Tag {}
+
+    /** @hide */
+    public static final int COMPOUND_FORMULA_TAG = 0;
+    /** @hide */
+    public static final int STRING_ATOMIC_FORMULA_TAG = 1;
+    /** @hide */
+    public static final int LONG_ATOMIC_FORMULA_TAG = 2;
+    /** @hide */
+    public static final int BOOLEAN_ATOMIC_FORMULA_TAG = 3;
+
+    /**
+     * Returns the tag that identifies the current class.
+     *
+     * @hide
+     */
+    public abstract @Tag int getTag();
+
+    /**
+     * Returns true when the integrity formula is satisfied by the {@code appInstallMetadata}.
+     *
+     * @hide
+     */
+    public abstract @Tag boolean matches(AppInstallMetadata appInstallMetadata);
+
+    /**
+     * Write an {@link IntegrityFormula} to {@link android.os.Parcel}.
+     *
+     * <p>This helper method is needed because non-final class/interface are not allowed to be
+     * {@link Parcelable}.
+     *
+     * @throws IllegalArgumentException if {@link IntegrityFormula} is not a recognized subclass
+     *
+     * @hide
+     */
+    public static void writeToParcel(
+            @NonNull IntegrityFormula formula, @NonNull Parcel dest, int flags) {
+        dest.writeInt(formula.getTag());
+        ((Parcelable) formula).writeToParcel(dest, flags);
+    }
+
+    /**
+     * Read a {@link IntegrityFormula} from a {@link android.os.Parcel}.
+     *
+     * <p>We need this (hacky) helper method because non-final class/interface cannot be {@link
+     * Parcelable} (api lint error).
+     *
+     * @throws IllegalArgumentException if the parcel cannot be parsed
+     * @hide
+     */
+    @NonNull
+    public static IntegrityFormula readFromParcel(@NonNull Parcel in) {
+        int tag = in.readInt();
+        switch (tag) {
+            case COMPOUND_FORMULA_TAG:
+                return CompoundFormula.CREATOR.createFromParcel(in);
+            case STRING_ATOMIC_FORMULA_TAG:
+                return StringAtomicFormula.CREATOR.createFromParcel(in);
+            case LONG_ATOMIC_FORMULA_TAG:
+                return LongAtomicFormula.CREATOR.createFromParcel(in);
+            case BOOLEAN_ATOMIC_FORMULA_TAG:
+                return BooleanAtomicFormula.CREATOR.createFromParcel(in);
+            default:
+                throw new IllegalArgumentException("Unknown formula tag " + tag);
+        }
+    }
+
+    /**
+     * Returns an integrity formula that evaluates to true when value of the key matches to the
+     * provided string value.
+     *
+     * <p>The value will be hashed with SHA256 and the hex digest will be computed; for
+     * all cases except when the key is PACKAGE_NAME or INSTALLER_NAME and the value is less than
+     * 32 characters.
+     *
+     * <p>Throws an {@link IllegalArgumentException} if the key is not string typed.
+     */
+    @NonNull
+    public IntegrityFormula equalTo(@NonNull String value) {
+        AtomicFormula baseFormula = (AtomicFormula) this;
+        return new AtomicFormula.StringAtomicFormula(baseFormula.getKey(), value);
+    }
+
+    /**
+     * Returns an integrity formula that evaluates to true when the boolean value of the key matches
+     * the provided boolean value. It can only be used with the boolean comparison keys.
+     *
+     * <p>Throws an {@link IllegalArgumentException} if the key is not boolean typed.
+     */
+    @NonNull
+    public IntegrityFormula equalTo(boolean value) {
+        AtomicFormula baseFormula = (AtomicFormula) this;
+        return new AtomicFormula.BooleanAtomicFormula(baseFormula.getKey(), value);
+    }
+
+    /**
+     * Returns a formula that evaluates to true when the value of the key in the package being
+     * installed is equal to {@code value}.
+     *
+     * <p>Throws an {@link IllegalArgumentException} if the key is not long typed.
+     */
+    @NonNull
+    public IntegrityFormula equalTo(long value) {
+        AtomicFormula baseFormula = (AtomicFormula) this;
+        return new AtomicFormula.LongAtomicFormula(baseFormula.getKey(), AtomicFormula.EQ, value);
+    }
+
+    /**
+     * Returns a formula that evaluates to true when the value of the key in the package being
+     * installed is greater than {@code value}.
+     *
+     * <p>Throws an {@link IllegalArgumentException} if the key is not long typed.
+     */
+    @NonNull
+    public IntegrityFormula greaterThan(long value) {
+        AtomicFormula baseFormula = (AtomicFormula) this;
+        return new AtomicFormula.LongAtomicFormula(baseFormula.getKey(), AtomicFormula.GT, value);
+    }
+
+    /**
+     * Returns a formula that evaluates to true when the value of the key in the package being
+     * installed is greater than or equals to the {@code value}.
+     *
+     * <p>Throws an {@link IllegalArgumentException} if the key is not long typed.
+     */
+    @NonNull
+    public IntegrityFormula greaterThanOrEquals(long value) {
+        AtomicFormula baseFormula = (AtomicFormula) this;
+        return new AtomicFormula.LongAtomicFormula(baseFormula.getKey(), AtomicFormula.GTE, value);
+    }
+
+    /**
+     * Returns a formula that evaluates to true when any formula in {@code formulae} evaluates to
+     * true.
+     *
+     * <p>Throws an {@link IllegalArgumentException} if formulae has less than two elements.
+     */
+    @NonNull
+    public static IntegrityFormula any(@NonNull IntegrityFormula... formulae) {
+        return new CompoundFormula(CompoundFormula.OR, Arrays.asList(formulae));
+    }
+
+    /**
+     * Returns a formula that evaluates to true when all formula in {@code formulae} evaluates to
+     * true.
+     *
+     * <p>Throws an {@link IllegalArgumentException} if formulae has less than two elements.
+     */
+    @NonNull
+    public static IntegrityFormula all(@NonNull IntegrityFormula... formulae) {
+        return new CompoundFormula(CompoundFormula.AND, Arrays.asList(formulae));
+    }
+
+    /**
+     * Returns a formula that evaluates to true when {@code formula} evaluates to false.
+     */
+    @NonNull
+    public static IntegrityFormula not(@NonNull IntegrityFormula formula) {
+        return new CompoundFormula(CompoundFormula.NOT, Arrays.asList(formula));
+    }
+
+    // Constructor is package private so it cannot be inherited outside of this package.
+    IntegrityFormula() {
+    }
+}
diff --git a/services/core/java/com/android/server/integrity/IntegrityUtils.java b/core/java/android/content/integrity/IntegrityUtils.java
similarity index 95%
rename from services/core/java/com/android/server/integrity/IntegrityUtils.java
rename to core/java/android/content/integrity/IntegrityUtils.java
index f49c675..c3f7624 100644
--- a/services/core/java/com/android/server/integrity/IntegrityUtils.java
+++ b/core/java/android/content/integrity/IntegrityUtils.java
@@ -14,11 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.server.integrity;
+package android.content.integrity;
 
 import static com.android.internal.util.Preconditions.checkArgument;
 
-/** Utils class for simple operations used in integrity module. */
+/**
+ * Utils class for simple operations used in integrity module.
+ *
+ * @hide
+ */
 public class IntegrityUtils {
 
     private static final char[] HEX_CHARS = "0123456789ABCDEF".toCharArray();
diff --git a/core/java/android/content/integrity/Rule.java b/core/java/android/content/integrity/Rule.java
index 7758785..c421c40 100644
--- a/core/java/android/content/integrity/Rule.java
+++ b/core/java/android/content/integrity/Rule.java
@@ -59,17 +59,17 @@
      */
     public static final int FORCE_ALLOW = 1;
 
-    private final @NonNull Formula mFormula;
+    private final @NonNull IntegrityFormula mFormula;
     private final @Effect int mEffect;
 
-    public Rule(@NonNull Formula formula, @Effect int effect) {
+    public Rule(@NonNull IntegrityFormula formula, @Effect int effect) {
         checkArgument(isValidEffect(effect), String.format("Unknown effect: %d", effect));
         this.mFormula = Objects.requireNonNull(formula);
         this.mEffect = effect;
     }
 
     Rule(Parcel in) {
-        mFormula = Formula.readFromParcel(in);
+        mFormula = IntegrityFormula.readFromParcel(in);
         mEffect = in.readInt();
     }
 
@@ -94,12 +94,12 @@
 
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
-        Formula.writeToParcel(mFormula, dest, flags);
+        IntegrityFormula.writeToParcel(mFormula, dest, flags);
         dest.writeInt(mEffect);
     }
 
     @NonNull
-    public Formula getFormula() {
+    public IntegrityFormula getFormula() {
         return mFormula;
     }
 
@@ -141,7 +141,6 @@
     }
 
     private static boolean isValidEffect(int effect) {
-        return effect == DENY
-                || effect == FORCE_ALLOW;
+        return effect == DENY || effect == FORCE_ALLOW;
     }
 }
diff --git a/core/java/android/content/om/OverlayManager.java b/core/java/android/content/om/OverlayManager.java
index a2f8886..33d1776 100644
--- a/core/java/android/content/om/OverlayManager.java
+++ b/core/java/android/content/om/OverlayManager.java
@@ -22,7 +22,11 @@
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
+import android.compat.Compatibility;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
 import android.content.Context;
+import android.os.Build;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
@@ -40,6 +44,10 @@
     private final IOverlayManager mService;
     private final Context mContext;
 
+    @ChangeId
+    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
+    private static final long THROW_SECURITY_EXCEPTIONS = 147340954;
+
     /**
      * Creates a new instance.
      *
@@ -69,6 +77,9 @@
      * @param packageName the name of the overlay package to enable.
      * @param user The user for which to change the overlay.
      *
+     * @throws SecurityException when caller is not allowed to enable {@param packageName}
+     * @throws IllegalStateException when enabling fails otherwise
+     *
      * @hide
      */
     @SystemApi
@@ -77,11 +88,13 @@
             "android.permission.INTERACT_ACROSS_USERS_FULL"
     })
     public void setEnabledExclusiveInCategory(@NonNull final String packageName,
-            @NonNull UserHandle user) {
+            @NonNull UserHandle user) throws SecurityException, IllegalStateException {
         try {
             if (!mService.setEnabledExclusiveInCategory(packageName, user.getIdentifier())) {
                 throw new IllegalStateException("setEnabledExclusiveInCategory failed");
             }
+        } catch (SecurityException e) {
+            rethrowSecurityException(e);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -97,6 +110,9 @@
      * @param enable {@code false} if the overlay should be turned off.
      * @param user The user for which to change the overlay.
      *
+     * @throws SecurityException when caller is not allowed to enable/disable {@param packageName}
+     * @throws IllegalStateException when enabling/disabling fails otherwise
+     *
      * @hide
      */
     @SystemApi
@@ -105,15 +121,16 @@
             "android.permission.INTERACT_ACROSS_USERS_FULL"
     })
     public void setEnabled(@NonNull final String packageName, final boolean enable,
-            @NonNull UserHandle user) {
+            @NonNull UserHandle user) throws SecurityException, IllegalStateException {
         try {
             if (!mService.setEnabled(packageName, enable, user.getIdentifier())) {
                 throw new IllegalStateException("setEnabled failed");
             }
+        } catch (SecurityException e) {
+            rethrowSecurityException(e);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
-        return;
     }
 
     /**
@@ -187,4 +204,29 @@
             throw e.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Starting on R, actor enforcement and app visibility changes introduce additional failure
+     * cases, but the SecurityException thrown with these checks is unexpected for existing
+     * consumers of the API.
+     *
+     * The only prior case it would be thrown is with a permission failure, but the calling
+     * application would be able to verify that themselves, and so they may choose to ignore
+     * catching SecurityException when calling these APIs.
+     *
+     * For R, this no longer holds true, and SecurityExceptions can be thrown for any number of
+     * reasons, none of which are exposed to the caller. So for consumers targeting below R,
+     * transform these SecurityExceptions into IllegalStateExceptions, which are a little more
+     * expected to be thrown by the setEnabled APIs.
+     *
+     * This will mask the prior permission exception if it applies, but it's assumed that apps
+     * wouldn't call the APIs without the permission on prior versions, and so it's safe to ignore.
+     */
+    private void rethrowSecurityException(SecurityException e) {
+        if (!Compatibility.isChangeEnabled(THROW_SECURITY_EXCEPTIONS)) {
+            throw new IllegalStateException(e);
+        } else {
+            throw e;
+        }
+    }
 }
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 1aed977..b998539 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -133,6 +133,13 @@
     public int fullBackupContent = 0;
 
     /**
+     * <code>true</code> if the package is capable of presenting a unified interface representing
+     * multiple profiles.
+     * @hide
+     */
+    public boolean crossProfile;
+
+    /**
      * The default extra UI options for activities in this application.
      * Set from the {@link android.R.attr#uiOptions} attribute in the
      * activity's manifest.
@@ -1382,6 +1389,7 @@
                 pw.println(prefix + "fullBackupContent="
                         + (fullBackupContent < 0 ? "false" : "true"));
             }
+            pw.println("crossProfile=" + (crossProfile ? "true" : "false"));
             if (networkSecurityConfigRes != 0) {
                 pw.println(prefix + "networkSecurityConfigRes=0x"
                         + Integer.toHexString(networkSecurityConfigRes));
@@ -1586,6 +1594,7 @@
         uiOptions = orig.uiOptions;
         backupAgentName = orig.backupAgentName;
         fullBackupContent = orig.fullBackupContent;
+        crossProfile = orig.crossProfile;
         networkSecurityConfigRes = orig.networkSecurityConfigRes;
         category = orig.category;
         targetSandboxVersion = orig.targetSandboxVersion;
@@ -1665,6 +1674,7 @@
         dest.writeInt(descriptionRes);
         dest.writeInt(uiOptions);
         dest.writeInt(fullBackupContent);
+        dest.writeBoolean(crossProfile);
         dest.writeInt(networkSecurityConfigRes);
         dest.writeInt(category);
         dest.writeInt(targetSandboxVersion);
@@ -1741,6 +1751,7 @@
         descriptionRes = source.readInt();
         uiOptions = source.readInt();
         fullBackupContent = source.readInt();
+        crossProfile = source.readBoolean();
         networkSecurityConfigRes = source.readInt();
         category = source.readInt();
         targetSandboxVersion = source.readInt();
diff --git a/core/java/android/content/pm/IPackageInstallerSession.aidl b/core/java/android/content/pm/IPackageInstallerSession.aidl
index e86bb25..fc20263 100644
--- a/core/java/android/content/pm/IPackageInstallerSession.aidl
+++ b/core/java/android/content/pm/IPackageInstallerSession.aidl
@@ -16,6 +16,7 @@
 
 package android.content.pm;
 
+import android.content.pm.DataLoaderParamsParcel;
 import android.content.pm.IPackageInstallObserver2;
 import android.content.IntentSender;
 import android.os.ParcelFileDescriptor;
@@ -39,8 +40,9 @@
     void transfer(in String packageName);
     void abandon();
 
-    void addFile(String name, long lengthBytes, in byte[] metadata);
-    void removeFile(String name);
+    DataLoaderParamsParcel getDataLoaderParams();
+    void addFile(int location, String name, long lengthBytes, in byte[] metadata, in byte[] signature);
+    void removeFile(int location, String name);
 
     boolean isMultiPackage();
     int[] getChildSessionIds();
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index b3d8eb5..93126b8 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -230,7 +230,7 @@
      * @param versionedPackage The package to delete.
      * @param observer a callback to use to notify when the package deletion in finished.
      * @param userId the id of the user for whom to delete the package
-     * @param flags - possible values: {@link #DONT_DELETE_DATA}
+     * @param flags - possible values: {@link #DELETE_KEEP_DATA}
      */
     void deletePackageVersioned(in VersionedPackage versionedPackage,
             IPackageDeleteObserver2 observer, int userId, int flags);
diff --git a/core/java/android/content/pm/InstallationFile.java b/core/java/android/content/pm/InstallationFile.java
index ac5fd1e..111ad32 100644
--- a/core/java/android/content/pm/InstallationFile.java
+++ b/core/java/android/content/pm/InstallationFile.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -31,12 +32,14 @@
  *
  * @hide
  */
+@SystemApi
 public final class InstallationFile implements Parcelable {
     public static final int FILE_TYPE_UNKNOWN = -1;
     public static final int FILE_TYPE_APK = 0;
     public static final int FILE_TYPE_LIB = 1;
     public static final int FILE_TYPE_OBB = 2;
 
+    /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = {"FILE_TYPE_"}, value = {
             FILE_TYPE_APK,
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index fbcb2dd..b1b9454 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -365,6 +365,41 @@
     @SystemApi
     public static final int DATA_LOADER_TYPE_INCREMENTAL = DataLoaderType.INCREMENTAL;
 
+    /**
+     * Target location for the file in installation session is /data/app/<packageName>-<id>.
+     * This is the intended location for APKs.
+     * Requires permission to install packages.
+     * {@hide}
+     */
+    @SystemApi
+    public static final int LOCATION_DATA_APP = 0;
+
+    /**
+     * Target location for the file in installation session is
+     * /data/media/<userid>/Android/obb/<packageName>. This is the intended location for OBBs.
+     * {@hide}
+     */
+    @SystemApi
+    public static final int LOCATION_MEDIA_OBB = 1;
+
+    /**
+     * Target location for the file in installation session is
+     * /data/media/<userid>/Android/data/<packageName>.
+     * This is the intended location for application data.
+     * Can only be used by an app itself running under specific user.
+     * {@hide}
+     */
+    @SystemApi
+    public static final int LOCATION_MEDIA_DATA = 2;
+
+    /** @hide */
+    @IntDef(prefix = { "LOCATION_" }, value = {
+            LOCATION_DATA_APP,
+            LOCATION_MEDIA_OBB,
+            LOCATION_MEDIA_DATA})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface FileLocation{}
+
     private final IPackageInstaller mInstaller;
     private final int mUserId;
     private final String mInstallerPackageName;
@@ -1071,10 +1106,33 @@
             }
         }
 
+        /**
+         * @return data loader params or null if the session is not using one.
+         *
+         * WARNING: This is a system API to aid internal development.
+         * Use at your own risk. It will change or be removed without warning.
+         * {@hide}
+         */
+        @SystemApi
+        public @Nullable DataLoaderParams getDataLoaderParams() {
+            try {
+                DataLoaderParamsParcel data = mSession.getDataLoaderParams();
+                if (data == null) {
+                    return null;
+                }
+                return new DataLoaderParams(data);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
 
         /**
          * Adds a file to session. On commit this file will be pulled from dataLoader.
          *
+         * @param location target location for the file. Possible values:
+         *            {@link #LOCATION_DATA_APP},
+         *            {@link #LOCATION_MEDIA_OBB},
+         *            {@link #LOCATION_MEDIA_DATA}.
          * @param name arbitrary, unique name of your choosing to identify the
          *            APK being written. You can open a file again for
          *            additional writes (such as after a reboot) by using the
@@ -1084,6 +1142,8 @@
          *            The system may clear various caches as needed to allocate
          *            this space.
          * @param metadata additional info use by dataLoader to pull data for the file.
+         * @param signature additional file signature, e.g.
+         *                  <a href="https://source.android.com/security/apksigning/v4.html">APK Signature Scheme v4</a>
          * @throws SecurityException if called after the session has been
          *             sealed or abandoned
          * @throws IllegalStateException if called for non-callback session
@@ -1093,9 +1153,10 @@
          * {@hide}
          */
         @SystemApi
-        public void addFile(@NonNull String name, long lengthBytes, @NonNull byte[] metadata) {
+        public void addFile(@FileLocation int location, @NonNull String name, long lengthBytes,
+                @NonNull byte[] metadata, @Nullable byte[] signature) {
             try {
-                mSession.addFile(name, lengthBytes, metadata);
+                mSession.addFile(location, name, lengthBytes, metadata, signature);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -1104,15 +1165,20 @@
         /**
          * Removes a file.
          *
+         * @param location target location for the file. Possible values:
+         *            {@link #LOCATION_DATA_APP},
+         *            {@link #LOCATION_MEDIA_OBB},
+         *            {@link #LOCATION_MEDIA_DATA}.
          * @param name name of a file, e.g. split.
          * @throws SecurityException if called after the session has been
          *             sealed or abandoned
          * @throws IllegalStateException if called for non-callback session
          * {@hide}
          */
-        public void removeFile(@NonNull String name) {
+        @SystemApi
+        public void removeFile(@FileLocation int location, @NonNull String name) {
             try {
-                mSession.removeFile(name);
+                mSession.removeFile(location, name);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index a2d425b..b64c001 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -369,7 +369,7 @@
      * Flag parameter to retrieve some information about all applications (even
      * uninstalled ones) which have data directories. This state could have
      * resulted if applications have been deleted with flag
-     * {@code DONT_DELETE_DATA} with a possibility of being replaced or
+     * {@code DELETE_KEEP_DATA} with a possibility of being replaced or
      * reinstalled in future.
      * <p>
      * Note: this flag may cause less information about currently installed
@@ -549,9 +549,10 @@
     public static final int MATCH_DEBUG_TRIAGED_MISSING = MATCH_DIRECT_BOOT_AUTO;
 
     /**
-     * Internal flag used to indicate that a package is a hidden system app.
+     * Internal {@link PackageInfo} flag used to indicate that a package is a hidden system app.
      * @hide
      */
+    @SystemApi
     public static final int MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS =  0x20000000;
 
     /**
@@ -1959,6 +1960,15 @@
 
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
+     * {@link #hasSystemFeature}: The device's main front and back cameras can stream
+     * concurrently as described in  {@link
+     * android.hardware.camera2.CameraManager#getConcurrentStreamingCameraIds()}
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_CAMERA_CONCURRENT = "android.hardware.camera.concurrent";
+
+    /**
+     * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device is capable of communicating with
      * consumer IR devices.
      */
@@ -2325,6 +2335,13 @@
 
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
+     * {@link #hasSystemFeature}: The device includes a hinge angle sensor.
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_SENSOR_HINGE_ANGLE = "android.hardware.sensor.hinge_angle";
+
+    /**
+     * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device supports high fidelity sensor processing
      * capabilities.
      */
@@ -3328,6 +3345,15 @@
     public static final int FLAG_PERMISSION_ONE_TIME = 1 << 16;
 
     /**
+     * Permission flags: Reserved for use by the permission controller.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int FLAGS_PERMISSION_RESERVED_PERMISSIONCONTROLLER = 1 << 28 | 1 << 29
+            | 1 << 30 | 1 << 31;
+
+    /**
      * Permission flags: Bitwise or of all permission flags allowing an
      * exemption for a restricted permission.
      * @hide
@@ -3517,6 +3543,44 @@
     public static final long FILTER_APPLICATION_QUERY = 135549675L;
 
     /** {@hide} */
+    @IntDef(prefix = {"SYSTEM_APP_STATE_"}, value = {
+            SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN,
+            SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_VISIBLE,
+            SYSTEM_APP_STATE_INSTALLED,
+            SYSTEM_APP_STATE_UNINSTALLED
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SystemAppState {}
+
+    /**
+     * Constant for noting system app state as hidden before installation
+     * @hide
+     */
+    @SystemApi
+    public static final int SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN = 0;
+
+    /**
+     * Constant for noting system app state as visible before installation
+     * @hide
+     */
+    @SystemApi
+    public static final int SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_VISIBLE = 1;
+
+    /**
+     * Constant for noting system app state as installed
+     * @hide
+     */
+    @SystemApi
+    public static final int SYSTEM_APP_STATE_INSTALLED = 2;
+
+    /**
+     * Constant for noting system app state as not installed
+     * @hide
+     */
+    @SystemApi
+    public static final int SYSTEM_APP_STATE_UNINSTALLED = 3;
+
+    /** {@hide} */
     public int getUserId() {
         return UserHandle.myUserId();
     }
@@ -3534,7 +3598,7 @@
      *         information is retrieved from the list of uninstalled
      *         applications (which includes installed applications as well as
      *         applications with data directory i.e. applications which had been
-     *         deleted with {@code DONT_DELETE_DATA} flag set).
+     *         deleted with {@code DELETE_KEEP_DATA} flag set).
      * @throws NameNotFoundException if a package with the given name cannot be
      *             found on the system.
      */
@@ -3560,7 +3624,7 @@
      *         information is retrieved from the list of uninstalled
      *         applications (which includes installed applications as well as
      *         applications with data directory i.e. applications which had been
-     *         deleted with {@code DONT_DELETE_DATA} flag set).
+     *         deleted with {@code DELETE_KEEP_DATA} flag set).
      * @throws NameNotFoundException if a package with the given name cannot be
      *             found on the system.
      */
@@ -3581,7 +3645,7 @@
      *         information is retrieved from the list of uninstalled
      *         applications (which includes installed applications as well as
      *         applications with data directory i.e. applications which had been
-     *         deleted with {@code DONT_DELETE_DATA} flag set).
+     *         deleted with {@code DELETE_KEEP_DATA} flag set).
      * @throws NameNotFoundException if a package with the given name cannot be
      *             found on the system.
      * @hide
@@ -3828,7 +3892,7 @@
      *         the application information is retrieved from the list of
      *         uninstalled applications (which includes installed applications
      *         as well as applications with data directory i.e. applications
-     *         which had been deleted with {@code DONT_DELETE_DATA} flag set).
+     *         which had been deleted with {@code DELETE_KEEP_DATA} flag set).
      * @throws NameNotFoundException if a package with the given name cannot be
      *             found on the system.
      */
@@ -3855,7 +3919,7 @@
      *         the application information is retrieved from the list of
      *         uninstalled applications (which includes installed applications
      *         as well as applications with data directory i.e. applications
-     *         which had been deleted with {@code DONT_DELETE_DATA} flag set).
+     *         which had been deleted with {@code DELETE_KEEP_DATA} flag set).
      * @throws NameNotFoundException if a package with the given name cannot be
      *             found on the system.
      * @hide
@@ -3978,7 +4042,7 @@
      *         information is retrieved from the list of uninstalled
      *         applications (which includes installed applications as well as
      *         applications with data directory i.e. applications which had been
-     *         deleted with {@code DONT_DELETE_DATA} flag set).
+     *         deleted with {@code DELETE_KEEP_DATA} flag set).
      */
     @NonNull
     public abstract List<PackageInfo> getInstalledPackages(@PackageInfoFlags int flags);
@@ -3996,7 +4060,7 @@
      *         information is retrieved from the list of uninstalled
      *         applications (which includes installed applications as well as
      *         applications with data directory i.e. applications which had been
-     *         deleted with {@code DONT_DELETE_DATA} flag set).
+     *         deleted with {@code DELETE_KEEP_DATA} flag set).
      */
     @NonNull
     public abstract List<PackageInfo> getPackagesHoldingPermissions(
@@ -4015,7 +4079,7 @@
      *         information is retrieved from the list of uninstalled
      *         applications (which includes installed applications as well as
      *         applications with data directory i.e. applications which had been
-     *         deleted with {@code DONT_DELETE_DATA} flag set).
+     *         deleted with {@code DELETE_KEEP_DATA} flag set).
      * @hide
      */
     @NonNull
@@ -4561,7 +4625,7 @@
     /**
      * Return a List of all application packages that are installed for the
      * current user. If flag GET_UNINSTALLED_PACKAGES has been set, a list of all
-     * applications including those deleted with {@code DONT_DELETE_DATA}
+     * applications including those deleted with {@code DELETE_KEEP_DATA}
      * (partially installed apps with data directory) will be returned.
      *
      * @param flags Additional option flags to modify the data returned.
@@ -4572,7 +4636,7 @@
      *         information is retrieved from the list of uninstalled
      *         applications (which includes installed applications as well as
      *         applications with data directory i.e. applications which had been
-     *         deleted with {@code DONT_DELETE_DATA} flag set).
+     *         deleted with {@code DELETE_KEEP_DATA} flag set).
      */
     @NonNull
     public abstract List<ApplicationInfo> getInstalledApplications(@ApplicationInfoFlags int flags);
@@ -4581,7 +4645,7 @@
      * Return a List of all application packages that are installed on the
      * device, for a specific user. If flag GET_UNINSTALLED_PACKAGES has been
      * set, a list of all applications including those deleted with
-     * {@code DONT_DELETE_DATA} (partially installed apps with data directory)
+     * {@code DELETE_KEEP_DATA} (partially installed apps with data directory)
      * will be returned.
      *
      * @param flags Additional option flags to modify the data returned.
@@ -4594,7 +4658,7 @@
      *         information is retrieved from the list of uninstalled
      *         applications (which includes installed applications as well as
      *         applications with data directory i.e. applications which had been
-     *         deleted with {@code DONT_DELETE_DATA} flag set).
+     *         deleted with {@code DELETE_KEEP_DATA} flag set).
      * @hide
      */
     @NonNull
@@ -6620,6 +6684,17 @@
             @NonNull UserHandle userHandle);
 
     /**
+     * Sets system app state
+     * @param packageName Package name of the app.
+     * @param state State of the app.
+     * @hide
+     */
+    @SystemApi
+    public void setSystemAppState(@NonNull String packageName, @SystemAppState int state) {
+        throw new RuntimeException("Not implemented. Must override in a subclass");
+    }
+
+    /**
      * Return whether the device has been booted into safe mode.
      */
     public abstract boolean isSafeMode();
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 906ca10..430241a 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -41,6 +41,7 @@
 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
 
+import android.annotation.AnyThread;
 import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
@@ -1080,6 +1081,7 @@
      *
      * @see #parsePackage(File, int, boolean)
      */
+    @AnyThread
     public ParsedPackage parseParsedPackage(File packageFile, int flags, boolean useCaches)
             throws PackageParserException {
         ParsedPackage parsed = useCaches ? getCachedResult(packageFile, flags) : null;
diff --git a/core/java/android/content/pm/SuspendDialogInfo.java b/core/java/android/content/pm/SuspendDialogInfo.java
index 73b75df..851a081 100644
--- a/core/java/android/content/pm/SuspendDialogInfo.java
+++ b/core/java/android/content/pm/SuspendDialogInfo.java
@@ -19,6 +19,7 @@
 import static android.content.res.Resources.ID_NULL;
 
 import android.annotation.DrawableRes;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StringRes;
@@ -36,20 +37,21 @@
 import org.xmlpull.v1.XmlSerializer;
 
 import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Locale;
 import java.util.Objects;
 
 /**
  * A container to describe the dialog to be shown when the user tries to launch a suspended
- * application.
- * The suspending app can customize the dialog's following attributes:
+ * application. The suspending app can customize the dialog's following attributes:
  * <ul>
  * <li>The dialog icon, by providing a resource id.
  * <li>The title text, by providing a resource id.
  * <li>The text of the dialog's body, by providing a resource id or a string.
- * <li>The text on the neutral button which starts the
- * {@link android.content.Intent#ACTION_SHOW_SUSPENDED_APP_DETAILS SHOW_SUSPENDED_APP_DETAILS}
- * activity, by providing a resource id.
+ * <li>The text on the neutral button by providing a resource id.
+ * <li>The action performed on tapping the neutral button. Only {@link #BUTTON_ACTION_UNSUSPEND}
+ * and {@link #BUTTON_ACTION_MORE_DETAILS} are currently supported.
  * </ul>
  * System defaults are used whenever any of these are not provided, or any of the provided resource
  * ids cannot be resolved at the time of displaying the dialog.
@@ -67,12 +69,47 @@
     private static final String XML_ATTR_DIALOG_MESSAGE_RES_ID = "dialogMessageResId";
     private static final String XML_ATTR_DIALOG_MESSAGE = "dialogMessage";
     private static final String XML_ATTR_BUTTON_TEXT_RES_ID = "buttonTextResId";
+    private static final String XML_ATTR_BUTTON_ACTION = "buttonAction";
 
     private final int mIconResId;
     private final int mTitleResId;
     private final int mDialogMessageResId;
     private final String mDialogMessage;
     private final int mNeutralButtonTextResId;
+    private final int mNeutralButtonAction;
+
+    /**
+     * Used with {@link Builder#setNeutralButtonAction(int)} to create a neutral button that
+     * starts the {@link android.content.Intent#ACTION_SHOW_SUSPENDED_APP_DETAILS} activity.
+     * @see Builder#setNeutralButtonAction(int)
+     */
+    public static final int BUTTON_ACTION_MORE_DETAILS = 0;
+
+    /**
+     * Used with {@link Builder#setNeutralButtonAction(int)} to create a neutral button that
+     * unsuspends the app that the user was trying to launch and continues with the launch. The
+     * system also sends the broadcast
+     * {@link android.content.Intent#ACTION_PACKAGE_UNSUSPENDED_MANUALLY} to the suspending app
+     * when this happens.
+     * @see Builder#setNeutralButtonAction(int)
+     * @see android.content.Intent#ACTION_PACKAGE_UNSUSPENDED_MANUALLY
+     */
+    public static final int BUTTON_ACTION_UNSUSPEND = 1;
+
+    /**
+     * Button actions to specify what happens when the user taps on the neutral button.
+     * To be used with {@link Builder#setNeutralButtonAction(int)}.
+     *
+     * @hide
+     * @see Builder#setNeutralButtonAction(int)
+     */
+    @IntDef(flag = true, prefix = {"BUTTON_ACTION_"}, value = {
+            BUTTON_ACTION_MORE_DETAILS,
+            BUTTON_ACTION_UNSUSPEND
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ButtonAction {
+    }
 
     /**
      * @return the resource id of the icon to be used with the dialog
@@ -102,8 +139,8 @@
     }
 
     /**
-     * @return the text to be shown in the dialog's body. Returns {@code null} if
-     * {@link #getDialogMessageResId()} returns a valid resource id.
+     * @return the text to be shown in the dialog's body. Returns {@code null} if {@link
+     * #getDialogMessageResId()} returns a valid resource id
      * @hide
      */
     @Nullable
@@ -121,6 +158,15 @@
     }
 
     /**
+     * @return The {@link ButtonAction} that happens on tapping this button
+     * @hide
+     */
+    @ButtonAction
+    public int getNeutralButtonAction() {
+        return mNeutralButtonAction;
+    }
+
+    /**
      * @hide
      */
     public void saveToXml(XmlSerializer out) throws IOException {
@@ -138,6 +184,7 @@
         if (mNeutralButtonTextResId != ID_NULL) {
             XmlUtils.writeIntAttribute(out, XML_ATTR_BUTTON_TEXT_RES_ID, mNeutralButtonTextResId);
         }
+        XmlUtils.writeIntAttribute(out, XML_ATTR_BUTTON_ACTION, mNeutralButtonAction);
     }
 
     /**
@@ -150,6 +197,8 @@
             final int titleId = XmlUtils.readIntAttribute(in, XML_ATTR_TITLE_RES_ID, ID_NULL);
             final int buttonTextId = XmlUtils.readIntAttribute(in, XML_ATTR_BUTTON_TEXT_RES_ID,
                     ID_NULL);
+            final int buttonAction = XmlUtils.readIntAttribute(in, XML_ATTR_BUTTON_ACTION,
+                    BUTTON_ACTION_MORE_DETAILS);
             final int dialogMessageResId = XmlUtils.readIntAttribute(
                     in, XML_ATTR_DIALOG_MESSAGE_RES_ID, ID_NULL);
             final String dialogMessage = XmlUtils.readStringAttribute(in, XML_ATTR_DIALOG_MESSAGE);
@@ -168,6 +217,7 @@
             } else if (dialogMessage != null) {
                 dialogInfoBuilder.setMessage(dialogMessage);
             }
+            dialogInfoBuilder.setNeutralButtonAction(buttonAction);
         } catch (Exception e) {
             Slog.e(TAG, "Exception while parsing from xml. Some fields may default", e);
         }
@@ -181,6 +231,7 @@
         hashCode = 31 * hashCode + mNeutralButtonTextResId;
         hashCode = 31 * hashCode + mDialogMessageResId;
         hashCode = 31 * hashCode + Objects.hashCode(mDialogMessage);
+        hashCode = 31 * hashCode + mNeutralButtonAction;
         return hashCode;
     }
 
@@ -197,6 +248,7 @@
                 && mTitleResId == otherDialogInfo.mTitleResId
                 && mDialogMessageResId == otherDialogInfo.mDialogMessageResId
                 && mNeutralButtonTextResId == otherDialogInfo.mNeutralButtonTextResId
+                && mNeutralButtonAction == otherDialogInfo.mNeutralButtonAction
                 && Objects.equals(mDialogMessage, otherDialogInfo.mDialogMessage);
     }
 
@@ -228,6 +280,8 @@
             builder.append(mDialogMessage);
             builder.append("\" ");
         }
+        builder.append("mNeutralButtonAction = ");
+        builder.append(mNeutralButtonAction);
         builder.append("}");
         return builder.toString();
     }
@@ -244,6 +298,7 @@
         dest.writeInt(mDialogMessageResId);
         dest.writeString(mDialogMessage);
         dest.writeInt(mNeutralButtonTextResId);
+        dest.writeInt(mNeutralButtonAction);
     }
 
     private SuspendDialogInfo(Parcel source) {
@@ -252,6 +307,7 @@
         mDialogMessageResId = source.readInt();
         mDialogMessage = source.readString();
         mNeutralButtonTextResId = source.readInt();
+        mNeutralButtonAction = source.readInt();
     }
 
     SuspendDialogInfo(Builder b) {
@@ -260,9 +316,11 @@
         mDialogMessageResId = b.mDialogMessageResId;
         mDialogMessage = (mDialogMessageResId == ID_NULL) ? b.mDialogMessage : null;
         mNeutralButtonTextResId = b.mNeutralButtonTextResId;
+        mNeutralButtonAction = b.mNeutralButtonAction;
     }
 
-    public static final @android.annotation.NonNull Creator<SuspendDialogInfo> CREATOR = new Creator<SuspendDialogInfo>() {
+    public static final @NonNull Creator<SuspendDialogInfo> CREATOR =
+            new Creator<SuspendDialogInfo>() {
         @Override
         public SuspendDialogInfo createFromParcel(Parcel source) {
             return new SuspendDialogInfo(source);
@@ -283,6 +341,7 @@
         private int mTitleResId = ID_NULL;
         private int mIconResId = ID_NULL;
         private int mNeutralButtonTextResId = ID_NULL;
+        private int mNeutralButtonAction = BUTTON_ACTION_MORE_DETAILS;
 
         /**
          * Set the resource id of the icon to be used. If not provided, no icon will be shown.
@@ -333,8 +392,8 @@
 
         /**
          * Set the resource id of the dialog message to be shown. If no dialog message is provided
-         * via either this method or {@link #setMessage(String)}, the system will use a
-         * default message.
+         * via either this method or {@link #setMessage(String)}, the system will use a default
+         * message.
          * <p>
          * The system will use {@link android.content.res.Resources#getString(int, Object...)
          * getString} to insert the suspended app name into the message, so an example format string
@@ -353,9 +412,10 @@
         }
 
         /**
-         * Set the resource id of text to be shown on the neutral button. Tapping this button starts
-         * the {@link android.content.Intent#ACTION_SHOW_SUSPENDED_APP_DETAILS} activity. If this is
-         * not provided, the system will use a default text.
+         * Set the resource id of text to be shown on the neutral button. Tapping this button would
+         * perform the {@link ButtonAction action} specified through
+         * {@link #setNeutralButtonAction(int)}. If this is not provided, the system will use a
+         * default text.
          *
          * @param resId The resource id of the button text
          * @return this builder object.
@@ -368,6 +428,22 @@
         }
 
         /**
+         * Set the action expected to happen on neutral button tap. Defaults to
+         * {@link #BUTTON_ACTION_MORE_DETAILS} if this is not provided.
+         *
+         * @param buttonAction Either {@link #BUTTON_ACTION_MORE_DETAILS} or
+         *                     {@link #BUTTON_ACTION_UNSUSPEND}.
+         * @return this builder object
+         */
+        @NonNull
+        public Builder setNeutralButtonAction(@ButtonAction int buttonAction) {
+            Preconditions.checkArgument(buttonAction == BUTTON_ACTION_MORE_DETAILS
+                    || buttonAction == BUTTON_ACTION_UNSUSPEND, "Invalid button action");
+            mNeutralButtonAction = buttonAction;
+            return this;
+        }
+
+        /**
          * Build the final object based on given inputs.
          *
          * @return The {@link SuspendDialogInfo} object built using this builder.
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index 008cfa5..f150664 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -362,6 +362,10 @@
             // Don't support switching to an ephemeral user with removal in progress.
             return false;
         }
+        if (preCreated) {
+            // Don't support switching to pre-created users until they become "real" users.
+            return false;
+        }
         return !isProfile();
     }
 
diff --git a/core/java/android/content/pm/parsing/PackageImpl.java b/core/java/android/content/pm/parsing/PackageImpl.java
index 9baf325..fe8307c 100644
--- a/core/java/android/content/pm/parsing/PackageImpl.java
+++ b/core/java/android/content/pm/parsing/PackageImpl.java
@@ -2382,6 +2382,7 @@
         appInfo.uiOptions = uiOptions;
         appInfo.volumeUuid = volumeUuid;
         appInfo.zygotePreloadName = zygotePreloadName;
+        appInfo.crossProfile = isCrossProfile();
 
         appInfo.setBaseCodePath(baseCodePath);
         appInfo.setBaseResourcePath(baseCodePath);
diff --git a/core/java/android/hardware/CameraStatus.java b/core/java/android/hardware/CameraStatus.java
index 08b5b77..29802cb 100644
--- a/core/java/android/hardware/CameraStatus.java
+++ b/core/java/android/hardware/CameraStatus.java
@@ -30,6 +30,7 @@
 public class CameraStatus implements Parcelable {
     public String cameraId;
     public int status;
+    public String[] unavailablePhysicalCameras;
 
     @Override
     public int describeContents() {
@@ -40,11 +41,13 @@
     public void writeToParcel(Parcel out, int flags) {
         out.writeString(cameraId);
         out.writeInt(status);
+        out.writeStringArray(unavailablePhysicalCameras);
     }
 
     public void readFromParcel(Parcel in) {
         cameraId = in.readString();
         status = in.readInt();
+        unavailablePhysicalCameras = in.readStringArray();
     }
 
     public static final @android.annotation.NonNull Parcelable.Creator<CameraStatus> CREATOR =
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index a71a7b6..cc4c456 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -693,6 +693,22 @@
             "android.sensor.accelerometer_uncalibrated";
 
     /**
+     * A constant describing a hinge angle sensor.
+     *
+     * See {@link android.hardware.SensorEvent#values SensorEvent.values} for more details.
+     *
+     */
+    public static final int TYPE_HINGE_ANGLE = 36;
+
+    /**
+     * A constant string describing a hinge angle sensor.
+     *
+     * @see #TYPE_HINGE_ANGLE
+     *
+     */
+    public static final String STRING_TYPE_HINGE_ANGLE = "android.sensor.hinge_angle";
+
+    /**
      * A constant describing all sensor types.
      */
 
@@ -811,6 +827,7 @@
             16, // skip over additional sensor info type
             1, // SENSOR_TYPE_LOW_LATENCY_OFFBODY_DETECT
             6, // SENSOR_TYPE_ACCELEROMETER_UNCALIBRATED
+            1, // SENSOR_TYPE_HINGE_ANGLE
     };
 
     /**
@@ -1226,6 +1243,8 @@
             case TYPE_ACCELEROMETER_UNCALIBRATED:
                 mStringType = STRING_TYPE_ACCELEROMETER_UNCALIBRATED;
                 return true;
+            case TYPE_HINGE_ANGLE:
+                mStringType = STRING_TYPE_HINGE_ANGLE;
             default:
                 return false;
         }
diff --git a/core/java/android/hardware/SensorEvent.java b/core/java/android/hardware/SensorEvent.java
index 64c45bf..5fbf0da 100644
--- a/core/java/android/hardware/SensorEvent.java
+++ b/core/java/android/hardware/SensorEvent.java
@@ -630,6 +630,16 @@
      * x_bias, y_bias, z_bias are the estimated biases.
      * </p>
      *
+     * <h4>{@link android.hardware.Sensor#TYPE_HINGE_ANGLE Sensor.TYPE_HINGE_ANGLE}:</h4>
+     *
+     * A sensor of this type measures the angle, in degrees, between two integral parts of the
+     * device. Movement of a hinge measured by this sensor type is expected to alter the ways in
+     * which the user may interact with the device, for example by unfolding or revealing a display.
+     *
+     * <ul>
+     *  <li> values[0]: Measured hinge angle between 0 and 360 degrees inclusive</li>
+     * </ul>
+     *
      * @see GeomagneticField
      */
     public final float[] values;
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 7bddc1d..b3a1ee2 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -2860,6 +2860,44 @@
             new Key<android.hardware.camera2.params.MandatoryStreamCombination[]>("android.scaler.mandatoryStreamCombinations", android.hardware.camera2.params.MandatoryStreamCombination[].class);
 
     /**
+     * <p>List of rotate-and-crop modes for {@link CaptureRequest#SCALER_ROTATE_AND_CROP android.scaler.rotateAndCrop} that are supported by this camera device.</p>
+     * <p>This entry lists the valid modes for {@link CaptureRequest#SCALER_ROTATE_AND_CROP android.scaler.rotateAndCrop} for this camera device.</p>
+     * <p>Starting with API level 30, all devices will list at least <code>ROTATE_AND_CROP_NONE</code>.
+     * Devices with support for rotate-and-crop will additionally list at least
+     * <code>ROTATE_AND_CROP_AUTO</code> and <code>ROTATE_AND_CROP_90</code>.</p>
+     * <p><b>Range of valid values:</b><br>
+     * Any value listed in {@link CaptureRequest#SCALER_ROTATE_AND_CROP android.scaler.rotateAndCrop}</p>
+     * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
+     *
+     * @see CaptureRequest#SCALER_ROTATE_AND_CROP
+     */
+    @PublicKey
+    @NonNull
+    public static final Key<int[]> SCALER_AVAILABLE_ROTATE_AND_CROP_MODES =
+            new Key<int[]>("android.scaler.availableRotateAndCropModes", int[].class);
+    /**
+     * <p>An array of mandatory concurrent stream combinations.
+     * This is an app-readable conversion of the concurrent mandatory stream combination
+     * {@link android.hardware.camera2.CameraDevice#createCaptureSession tables}.</p>
+     * <p>The array of
+     * {@link android.hardware.camera2.params.MandatoryStreamCombination combinations} is
+     * generated according to the documented
+     * {@link android.hardware.camera2.CameraDevice#createCaptureSession guideline} for each device
+     * which has its Id present in the set returned by
+     * {@link android.hardware.camera2.CameraManager#getConcurrentStreamingCameraIds}.
+     * Clients can use the array as a quick reference to find an appropriate camera stream
+     * combination.
+     * The mandatory stream combination array will be {@code null} in case the device is not a part
+     * of at least one set of combinations returned by
+     * {@link android.hardware.camera2.CameraManager#getConcurrentStreamingCameraIds}.</p>
+     * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
+     */
+    @PublicKey
+    @NonNull
+    @SyntheticKey
+    public static final Key<android.hardware.camera2.params.MandatoryStreamCombination[]> SCALER_MANDATORY_CONCURRENT_STREAM_COMBINATIONS =
+            new Key<android.hardware.camera2.params.MandatoryStreamCombination[]>("android.scaler.mandatoryConcurrentStreamCombinations", android.hardware.camera2.params.MandatoryStreamCombination[].class);
+    /**
      * <p>The area of the image sensor which corresponds to active pixels after any geometric
      * distortion correction has been applied.</p>
      * <p>This is the rectangle representing the size of the active region of the sensor (i.e.
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index cc06681..24d9311 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -680,6 +680,25 @@
      * </table><br>
      * </p>
      *
+     *<p>Devices capable of streaming concurrently with other devices as described by
+     * {@link android.hardware.camera2.CameraManager#getConcurrentStreamingCameraIds} have the
+     * following guaranteed streams (when streaming concurrently with other devices)</p>
+     *
+     * <table>
+     * <tr><th colspan="5">Concurrent stream guaranteed configurations</th></tr>
+     * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th rowspan="2">Sample use case(s)</th> </tr>
+     * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
+     * <tr> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td>  <td colspan="2" id="rb"></td> <td>In-app video / image processing.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td>  <td colspan="2" id="rb"></td> <td>In-app viewfinder analysis.</td> </tr>
+     * <tr> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM}</td> <td>In-app video / processing with preview.</td> </tr>
+     * <tr> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV }</td><td id="rb">{@code MAXIMUM}</td> <td>In-app video / processing with preview.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV }</td><td id="rb">{@code MAXIMUM}</td> <td>Standard Recording.</td> </tr>
+     * </table><br>
+     * </p>
+     *
+     * <p> For guaranteed concurrent stream configurations, MAXIMUM refers to the camera device's
+     * resolution for that format from {@link StreamConfigurationMap#getOutputSizes} or
+     * 720p(1280X720) whichever is lower. </p>
      * <p>MONOCHROME-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES}
      * includes {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME MONOCHROME}) devices
      * supporting {@link android.graphics.ImageFormat#Y8 Y8} support substituting {@code YUV}
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 9b58578..9ee56a9 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -31,6 +31,9 @@
 import android.hardware.camera2.impl.CameraMetadataNative;
 import android.hardware.camera2.legacy.CameraDeviceUserShim;
 import android.hardware.camera2.legacy.LegacyMetadataMapper;
+import android.hardware.camera2.params.SessionConfiguration;
+import android.hardware.camera2.utils.CameraIdAndSessionConfiguration;
+import android.hardware.camera2.utils.ConcurrentCameraIdCombination;
 import android.os.Binder;
 import android.os.DeadObjectException;
 import android.os.Handler;
@@ -40,6 +43,7 @@
 import android.os.ServiceSpecificException;
 import android.os.SystemProperties;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.Log;
 import android.util.Size;
 import android.view.Display;
@@ -48,6 +52,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Comparator;
+import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
@@ -126,6 +131,66 @@
     }
 
     /**
+     * Return the list of combinations of currently connected camera devices identifiers, which
+     * support configuring camera device sessions concurrently.
+     *
+     * <p>The set of combinations may include camera devices that may be in use by other camera API
+     * clients.</p>
+     *
+     * <p>The set of combinations doesn't contain physical cameras that can only be used as
+     * part of a logical multi-camera device.</p>
+     *
+     * @return The set of combinations of currently connected camera devices, that may have
+     *         sessions configured concurrently. The set of combinations will be empty if no such
+     *         combinations are supported by the camera subsystem.
+     *
+     * @throws CameraAccessException if the camera device has been disconnected.
+     */
+    @NonNull
+    public Set<Set<String>> getConcurrentStreamingCameraIds() throws CameraAccessException {
+        return CameraManagerGlobal.get().getConcurrentStreamingCameraIds();
+    }
+
+    /**
+     * Checks whether the provided set of camera devices and their corresponding
+     * {@link SessionConfiguration} can be configured concurrently.
+     *
+     * <p>This method performs a runtime check of the given {@link SessionConfiguration} and camera
+     * id combinations. The result confirms whether or not the passed session configurations can be
+     * successfully used to create camera capture sessions concurrently, on the given camera
+     * devices using {@link CameraDevice#createCaptureSession(SessionConfiguration)}.
+     * </p>
+     *
+     * <p>The method can be called at any point before, during and after active capture sessions.
+     * It will not impact normal camera behavior in any way and must complete significantly
+     * faster than creating a regular or constrained capture session.</p>
+     *
+     * <p>Although this method is faster than creating a new capture session, it is not intended
+     * to be used for exploring the entire space of supported concurrent stream combinations. The
+     * available mandatory concurrent stream combinations may be obtained by querying
+     * {@link #getCameraCharacteristics} for the key
+     * SCALER_MANDATORY_CONCURRENT_STREAM_COMBINATIONS. </p>
+     *
+     * <p>Note that session parameters will be ignored and calls to
+     * {@link SessionConfiguration#setSessionParameters} are not required.</p>
+     *
+     * @return {@code true} if the given combination of session configurations and corresponding
+     *                      camera ids are concurrently supported by the camera sub-system,
+     *         {@code false} otherwise.
+     *
+     * @throws IllegalArgumentException if the set of camera devices provided is not a subset of
+     *                                  those returned by getConcurrentStreamingCameraIds()
+     * @throws CameraAccessException if one of the camera devices queried is no longer connected.
+     */
+    @RequiresPermission(android.Manifest.permission.CAMERA)
+    public boolean isConcurrentSessionConfigurationSupported(
+            @NonNull Map<String, SessionConfiguration> cameraIdAndSessionConfig)
+            throws CameraAccessException {
+        return CameraManagerGlobal.get().isConcurrentSessionConfigurationSupported(
+                cameraIdAndSessionConfig);
+    }
+
+    /**
      * Register a callback to be notified about camera device availability.
      *
      * <p>Registering the same callback again will replace the handler with the
@@ -336,8 +401,10 @@
                     } catch (NumberFormatException e) {
                         Log.e(TAG, "Failed to parse camera Id " + cameraId + " to integer");
                     }
+                    boolean hasConcurrentStreams =
+                            CameraManagerGlobal.get().cameraIdHasConcurrentStreamsLocked(cameraId);
+                    info.setHasMandatoryConcurrentStreams(hasConcurrentStreams);
                     info.setDisplaySize(displaySize);
-
                     characteristics = new CameraCharacteristics(info);
                 }
             } catch (ServiceSpecificException e) {
@@ -718,6 +785,52 @@
         public void onCameraAccessPrioritiesChanged() {
             // default empty implementation
         }
+
+        /**
+         * A physical camera has become available for use again.
+         *
+         * <p>By default, all of the physical cameras of a logical multi-camera are
+         * available, so {@link #onPhysicalCameraAvailable} is not called for any of the physical
+         * cameras of a logical multi-camera, when {@link #onCameraAvailable} for the logical
+         * multi-camera is invoked. However, if some specific physical cameras are unavailable
+         * to begin with, {@link #onPhysicalCameraUnavailable} may be invoked after
+         * {@link #onCameraAvailable}.</p>
+         *
+         * <p>The default implementation of this method does nothing.</p>
+         *
+         * @param cameraId The unique identifier of the logical multi-camera.
+         * @param physicalCameraId The unique identifier of the physical camera.
+         *
+         * @see #onCameraAvailable
+         * @see #onPhysicalCameraUnavailable
+         */
+        public void onPhysicalCameraAvailable(@NonNull String cameraId,
+                @NonNull String physicalCameraId) {
+            // default empty implementation
+        }
+
+        /**
+         * A previously-available physical camera has become unavailable for use.
+         *
+         * <p>By default, all of the physical cameras of a logical multi-camera are
+         * available, so {@link #onPhysicalCameraAvailable} is not called for any of the physical
+         * cameras of a logical multi-camera, when {@link #onCameraAvailable} for the logical
+         * multi-camera is invoked. If some specific physical cameras are unavailable
+         * to begin with, {@link #onPhysicalCameraUnavailable} may be invoked after
+         * {@link #onCameraAvailable}.</p>
+         *
+         * <p>The default implementation of this method does nothing.</p>
+         *
+         * @param cameraId The unique identifier of the logical multi-camera.
+         * @param physicalCameraId The unique identifier of the physical camera.
+         *
+         * @see #onCameraAvailable
+         * @see #onPhysicalCameraAvailable
+         */
+        public void onPhysicalCameraUnavailable(@NonNull String cameraId,
+                @NonNull String physicalCameraId) {
+            // default empty implementation
+        }
     }
 
     /**
@@ -914,6 +1027,12 @@
         private final ScheduledExecutorService mScheduler = Executors.newScheduledThreadPool(1);
         // Camera ID -> Status map
         private final ArrayMap<String, Integer> mDeviceStatus = new ArrayMap<String, Integer>();
+        // Camera ID -> (physical camera ID -> Status map)
+        private final ArrayMap<String, ArrayList<String>> mUnavailablePhysicalDevices =
+                new ArrayMap<String, ArrayList<String>>();
+
+        private final Set<Set<String>> mConcurrentCameraIdCombinations =
+                new ArraySet<Set<String>>();
 
         // Registered availablility callbacks and their executors
         private final ArrayMap<AvailabilityCallback, Executor> mCallbackMap =
@@ -1003,6 +1122,14 @@
                 CameraStatus[] cameraStatuses = cameraService.addListener(this);
                 for (CameraStatus c : cameraStatuses) {
                     onStatusChangedLocked(c.status, c.cameraId);
+
+                    if (c.unavailablePhysicalCameras != null) {
+                        for (String unavailPhysicalCamera : c.unavailablePhysicalCameras) {
+                            onPhysicalCameraStatusChangedLocked(
+                                    ICameraServiceListener.STATUS_NOT_PRESENT,
+                                    c.cameraId, unavailPhysicalCamera);
+                        }
+                    }
                 }
                 mCameraService = cameraService;
             } catch(ServiceSpecificException e) {
@@ -1011,7 +1138,22 @@
             } catch (RemoteException e) {
                 // Camera service is now down, leave mCameraService as null
             }
+
+            try {
+                ConcurrentCameraIdCombination[] cameraIdCombinations =
+                        cameraService.getConcurrentStreamingCameraIds();
+                for (ConcurrentCameraIdCombination comb : cameraIdCombinations) {
+                    mConcurrentCameraIdCombinations.add(comb.getConcurrentCameraIdCombination());
+                }
+            } catch (ServiceSpecificException e) {
+                // Unexpected failure
+                throw new IllegalStateException("Failed to get concurrent camera id combinations",
+                        e);
+            } catch (RemoteException e) {
+                // Camera service died in all probability
+            }
         }
+
         private String[] extractCameraIdListLocked() {
             String[] cameraIds = null;
             int idCount = 0;
@@ -1032,6 +1174,31 @@
             }
             return cameraIds;
         }
+
+        private Set<Set<String>> extractConcurrentCameraIdListLocked() {
+            Set<Set<String>> concurrentCameraIds = new ArraySet<Set<String>>();
+            for (Set<String> cameraIds : mConcurrentCameraIdCombinations) {
+                Set<String> extractedCameraIds = new ArraySet<String>();
+                for (String cameraId : cameraIds) {
+                    // if the camera id status is NOT_PRESENT or ENUMERATING; skip the device.
+                    // TODO: Would a device status NOT_PRESENT ever be in the map ? it gets removed
+                    // in the callback anyway.
+                    Integer status = mDeviceStatus.get(cameraId);
+                    if (status == null) {
+                        // camera id not present
+                        continue;
+                    }
+                    if (status == ICameraServiceListener.STATUS_ENUMERATING
+                            || status == ICameraServiceListener.STATUS_NOT_PRESENT) {
+                        continue;
+                    }
+                    extractedCameraIds.add(cameraId);
+                }
+                concurrentCameraIds.add(extractedCameraIds);
+            }
+            return concurrentCameraIds;
+        }
+
         private static void sortCameraIds(String[] cameraIds) {
             // The sort logic must match the logic in
             // libcameraservice/common/CameraProviderManager.cpp::getAPI1CompatibleCameraDeviceIds
@@ -1086,6 +1253,10 @@
                 public void onStatusChanged(int status, String id) throws RemoteException {
                 }
                 @Override
+                public void onPhysicalCameraStatusChanged(int status,
+                        String id, String physicalId) throws RemoteException {
+                }
+                @Override
                 public void onTorchStatusChanged(int status, String id) throws RemoteException {
                 }
                 @Override
@@ -1153,6 +1324,88 @@
             return cameraIds;
         }
 
+        public @NonNull Set<Set<String>> getConcurrentStreamingCameraIds() {
+            Set<Set<String>> concurrentStreamingCameraIds = null;
+            synchronized (mLock) {
+                // Try to make sure we have an up-to-date list of concurrent camera devices.
+                connectCameraServiceLocked();
+                concurrentStreamingCameraIds = extractConcurrentCameraIdListLocked();
+            }
+            // TODO: Some sort of sorting  ?
+            return concurrentStreamingCameraIds;
+        }
+
+        public boolean isConcurrentSessionConfigurationSupported(
+                @NonNull Map<String, SessionConfiguration> cameraIdsAndSessionConfigurations)
+                throws CameraAccessException {
+
+            if (cameraIdsAndSessionConfigurations == null) {
+                throw new IllegalArgumentException("cameraIdsAndSessionConfigurations was null");
+            }
+
+            int size = cameraIdsAndSessionConfigurations.size();
+            if (size == 0) {
+                throw new IllegalArgumentException("camera id and session combination is empty");
+            }
+
+            synchronized (mLock) {
+                // Go through all the elements and check if the camera ids are valid at least /
+                // belong to one of the combinations returned by getConcurrentStreamingCameraIds()
+                boolean subsetFound = false;
+                for (Set<String> combination : mConcurrentCameraIdCombinations) {
+                    if (combination.containsAll(cameraIdsAndSessionConfigurations.keySet())) {
+                        subsetFound = true;
+                    }
+                }
+                if (!subsetFound) {
+                    throw new IllegalArgumentException(
+                            "The set of camera ids provided is not a subset of"
+                            + "getConcurrentStreamingCameraIds");
+                }
+                CameraIdAndSessionConfiguration [] cameraIdsAndConfigs =
+                        new CameraIdAndSessionConfiguration[size];
+                int i = 0;
+                for (Map.Entry<String, SessionConfiguration> pair :
+                        cameraIdsAndSessionConfigurations.entrySet()) {
+                    cameraIdsAndConfigs[i] =
+                            new CameraIdAndSessionConfiguration(pair.getKey(), pair.getValue());
+                    i++;
+                }
+                try {
+                    return mCameraService.isConcurrentSessionConfigurationSupported(
+                            cameraIdsAndConfigs);
+                } catch (ServiceSpecificException e) {
+                   throwAsPublicException(e);
+                } catch (RemoteException e) {
+                  // Camera service died - act as if the camera was disconnected
+                  throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
+                          "Camera service is currently unavailable", e);
+                }
+            }
+
+            return false;
+        }
+
+      /**
+        * Helper function to find out if a camera id is in the set of combinations returned by
+        * getConcurrentStreamingCameraIds()
+        * @param cameraId the unique identifier of the camera device to query
+        * @return Whether the camera device was found in the set of combinations returned by
+        *         getConcurrentStreamingCameraIds
+        */
+        public boolean cameraIdHasConcurrentStreamsLocked(String cameraId) {
+            if (!mDeviceStatus.containsKey(cameraId)) {
+                Log.e(TAG, "cameraIdHasConcurrentStreamsLocked called on non existing camera id");
+                return false;
+            }
+            for (Set<String> comb : mConcurrentCameraIdCombinations) {
+                if (comb.contains(cameraId)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
         public void setTorchMode(String cameraId, boolean enabled) throws CameraAccessException {
             synchronized(mLock) {
 
@@ -1236,7 +1489,7 @@
         }
 
         private void postSingleUpdate(final AvailabilityCallback callback, final Executor executor,
-                final String id, final int status) {
+                final String id, final String physicalId, final int status) {
             if (isAvailable(status)) {
                 final long ident = Binder.clearCallingIdentity();
                 try {
@@ -1244,7 +1497,11 @@
                         new Runnable() {
                             @Override
                             public void run() {
-                                callback.onCameraAvailable(id);
+                                if (physicalId == null) {
+                                    callback.onCameraAvailable(id);
+                                } else {
+                                    callback.onPhysicalCameraAvailable(id, physicalId);
+                                }
                             }
                         });
                 } finally {
@@ -1257,7 +1514,11 @@
                         new Runnable() {
                             @Override
                             public void run() {
-                                callback.onCameraUnavailable(id);
+                                if (physicalId == null) {
+                                    callback.onCameraUnavailable(id);
+                                } else {
+                                    callback.onPhysicalCameraUnavailable(id, physicalId);
+                                }
                             }
                         });
                 } finally {
@@ -1304,7 +1565,16 @@
             for (int i = 0; i < mDeviceStatus.size(); i++) {
                 String id = mDeviceStatus.keyAt(i);
                 Integer status = mDeviceStatus.valueAt(i);
-                postSingleUpdate(callback, executor, id, status);
+                postSingleUpdate(callback, executor, id, null /*physicalId*/, status);
+
+                // Send the NOT_PRESENT state for unavailable physical cameras
+                if (isAvailable(status) && mUnavailablePhysicalDevices.containsKey(id)) {
+                    ArrayList<String> unavailableIds = mUnavailablePhysicalDevices.get(id);
+                    for (String unavailableId : unavailableIds) {
+                        postSingleUpdate(callback, executor, id, unavailableId,
+                                ICameraServiceListener.STATUS_NOT_PRESENT);
+                    }
+                }
             }
         }
 
@@ -1323,8 +1593,12 @@
             Integer oldStatus;
             if (status == ICameraServiceListener.STATUS_NOT_PRESENT) {
                 oldStatus = mDeviceStatus.remove(id);
+                mUnavailablePhysicalDevices.remove(id);
             } else {
                 oldStatus = mDeviceStatus.put(id, status);
+                if (oldStatus == null) {
+                    mUnavailablePhysicalDevices.put(id, new ArrayList<String>());
+                }
             }
 
             if (oldStatus != null && oldStatus == status) {
@@ -1366,10 +1640,62 @@
                 Executor executor = mCallbackMap.valueAt(i);
                 final AvailabilityCallback callback = mCallbackMap.keyAt(i);
 
-                postSingleUpdate(callback, executor, id, status);
+                postSingleUpdate(callback, executor, id, null /*physicalId*/, status);
             }
         } // onStatusChangedLocked
 
+        private void onPhysicalCameraStatusChangedLocked(int status,
+                String id, String physicalId) {
+            if (DEBUG) {
+                Log.v(TAG,
+                        String.format("Camera id %s physical camera id %s has status "
+                        + "changed to 0x%x", id, physicalId, status));
+            }
+
+            if (!validStatus(status)) {
+                Log.e(TAG, String.format(
+                        "Ignoring invalid device %s physical device %s status 0x%x", id,
+                        physicalId, status));
+                return;
+            }
+
+            //TODO: Do we need to treat this as error?
+            if (!mDeviceStatus.containsKey(id) || !isAvailable(mDeviceStatus.get(id))
+                    || !mUnavailablePhysicalDevices.containsKey(id)) {
+                Log.e(TAG, String.format("Camera %s is not available. Ignore physical camera "
+                        + "status change", id));
+                return;
+            }
+
+            ArrayList<String> unavailablePhysicalDevices = mUnavailablePhysicalDevices.get(id);
+            if (!isAvailable(status)
+                    && !unavailablePhysicalDevices.contains(physicalId)) {
+                unavailablePhysicalDevices.add(physicalId);
+            } else if (isAvailable(status)
+                    && unavailablePhysicalDevices.contains(physicalId)) {
+                unavailablePhysicalDevices.remove(physicalId);
+            } else {
+                if (DEBUG) {
+                    Log.v(TAG,
+                            String.format(
+                                "Physical camera device status was previously available (%b), "
+                                + " and is now again available (%b)"
+                                + "so no new client visible update will be sent",
+                                !unavailablePhysicalDevices.contains(physicalId),
+                                isAvailable(status)));
+                }
+                return;
+            }
+
+            final int callbackCount = mCallbackMap.size();
+            for (int i = 0; i < callbackCount; i++) {
+                Executor executor = mCallbackMap.valueAt(i);
+                final AvailabilityCallback callback = mCallbackMap.keyAt(i);
+
+                postSingleUpdate(callback, executor, id, physicalId, status);
+            }
+        } // onPhysicalCameraStatusChangedLocked
+
         private void updateTorchCallbackLocked(TorchCallback callback, Executor executor) {
             for (int i = 0; i < mTorchStatus.size(); i++) {
                 String id = mTorchStatus.keyAt(i);
@@ -1478,6 +1804,14 @@
         }
 
         @Override
+        public void onPhysicalCameraStatusChanged(int status, String cameraId,
+                String physicalCameraId) throws RemoteException {
+            synchronized (mLock) {
+                onPhysicalCameraStatusChangedLocked(status, cameraId, physicalCameraId);
+            }
+        }
+
+        @Override
         public void onTorchStatusChanged(int status, String cameraId) throws RemoteException {
             synchronized (mLock) {
                 onTorchStatusChangedLocked(status, cameraId);
@@ -1556,6 +1890,8 @@
                             cameraId);
                 }
 
+                mConcurrentCameraIdCombinations.clear();
+
                 scheduleCameraServiceReconnectionLocked();
             }
         }
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 89dac2a..9bef2e1 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -865,14 +865,20 @@
      * <p>The camera device is a logical camera backed by two or more physical cameras.</p>
      * <p>In API level 28, the physical cameras must also be exposed to the application via
      * {@link android.hardware.camera2.CameraManager#getCameraIdList }.</p>
-     * <p>Starting from API level 29, some or all physical cameras may not be independently
-     * exposed to the application, in which case the physical camera IDs will not be
-     * available in {@link android.hardware.camera2.CameraManager#getCameraIdList }. But the
+     * <p>Starting from API level 29:</p>
+     * <ul>
+     * <li>Some or all physical cameras may not be independently exposed to the application,
+     * in which case the physical camera IDs will not be available in
+     * {@link android.hardware.camera2.CameraManager#getCameraIdList }. But the
      * application can still query the physical cameras' characteristics by calling
-     * {@link android.hardware.camera2.CameraManager#getCameraCharacteristics }. Additionally,
-     * if a physical camera is hidden from camera ID list, the mandatory stream combinations
-     * for that physical camera must be supported through the logical camera using physical
-     * streams.</p>
+     * {@link android.hardware.camera2.CameraManager#getCameraCharacteristics }.</li>
+     * <li>If a physical camera is hidden from camera ID list, the mandatory stream
+     * combinations for that physical camera must be supported through the logical camera
+     * using physical streams. One exception is that in API level 30, a physical camera
+     * may become unavailable via
+     * {@link CameraManager.AvailabilityCallback#onPhysicalCameraUnavailable }
+     * callback.</li>
+     * </ul>
      * <p>Combinations of logical and physical streams, or physical streams from different
      * physical cameras are not guaranteed. However, if the camera device supports
      * {@link CameraDevice#isSessionConfigurationSupported },
@@ -2743,6 +2749,56 @@
     public static final int NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG = 4;
 
     //
+    // Enumeration values for CaptureRequest#SCALER_ROTATE_AND_CROP
+    //
+
+    /**
+     * <p>No rotate and crop is applied. Processed outputs are in the sensor orientation.</p>
+     * @see CaptureRequest#SCALER_ROTATE_AND_CROP
+     */
+    public static final int SCALER_ROTATE_AND_CROP_NONE = 0;
+
+    /**
+     * <p>Processed images are rotated by 90 degrees clockwise, and then cropped
+     * to the original aspect ratio.</p>
+     * @see CaptureRequest#SCALER_ROTATE_AND_CROP
+     */
+    public static final int SCALER_ROTATE_AND_CROP_90 = 1;
+
+    /**
+     * <p>Processed images are rotated by 180 degrees.  Since the aspect ratio does not
+     * change, no cropping is performed.</p>
+     * @see CaptureRequest#SCALER_ROTATE_AND_CROP
+     */
+    public static final int SCALER_ROTATE_AND_CROP_180 = 2;
+
+    /**
+     * <p>Processed images are rotated by 270 degrees clockwise, and then cropped
+     * to the original aspect ratio.</p>
+     * @see CaptureRequest#SCALER_ROTATE_AND_CROP
+     */
+    public static final int SCALER_ROTATE_AND_CROP_270 = 3;
+
+    /**
+     * <p>The camera API automatically selects the best concrete value for
+     * rotate-and-crop based on the application's support for resizability and the current
+     * multi-window mode.</p>
+     * <p>If the application does not support resizing but the display mode for its main
+     * Activity is not in a typical orientation, the camera API will set <code>ROTATE_AND_CROP_90</code>
+     * or some other supported rotation value, depending on device configuration,
+     * to ensure preview and captured images are correctly shown to the user. Otherwise,
+     * <code>ROTATE_AND_CROP_NONE</code> will be selected.</p>
+     * <p>When a value other than NONE is selected, several metadata fields will also be parsed
+     * differently to ensure that coordinates are correctly handled for features like drawing
+     * face detection boxes or passing in tap-to-focus coordinates.  The camera API will
+     * convert positions in the active array coordinate system to/from the cropped-and-rotated
+     * coordinate system to make the operation transparent for applications.</p>
+     * <p>No coordinate mapping will be done when the application selects a non-AUTO mode.</p>
+     * @see CaptureRequest#SCALER_ROTATE_AND_CROP
+     */
+    public static final int SCALER_ROTATE_AND_CROP_AUTO = 4;
+
+    //
     // Enumeration values for CaptureRequest#SENSOR_TEST_PATTERN_MODE
     //
 
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index b9af8f5..30fbde2 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -2845,6 +2845,99 @@
             new Key<android.graphics.Rect>("android.scaler.cropRegion", android.graphics.Rect.class);
 
     /**
+     * <p>Whether a rotation-and-crop operation is applied to processed
+     * outputs from the camera.</p>
+     * <p>This control is primarily intended to help camera applications with no support for
+     * multi-window modes to work correctly on devices where multi-window scenarios are
+     * unavoidable, such as foldables or other devices with variable display geometry or more
+     * free-form window placement (such as laptops, which often place portrait-orientation apps
+     * in landscape with pillarboxing).</p>
+     * <p>If supported, the default value is <code>ROTATE_AND_CROP_AUTO</code>, which allows the camera API
+     * to enable backwards-compatibility support for applications that do not support resizing
+     * / multi-window modes, when the device is in fact in a multi-window mode (such as inset
+     * portrait on laptops, or on a foldable device in some fold states).  In addition,
+     * <code>ROTATE_AND_CROP_NONE</code> and <code>ROTATE_AND_CROP_90</code> will always be available if this control
+     * is supported by the device.  If not supported, devices API level 30 or higher will always
+     * list only <code>ROTATE_AND_CROP_NONE</code>.</p>
+     * <p>When <code>CROP_AUTO</code> is in use, and the camera API activates backward-compatibility mode,
+     * several metadata fields will also be parsed differently to ensure that coordinates are
+     * correctly handled for features like drawing face detection boxes or passing in
+     * tap-to-focus coordinates.  The camera API will convert positions in the active array
+     * coordinate system to/from the cropped-and-rotated coordinate system to make the
+     * operation transparent for applications.  The following controls are affected:</p>
+     * <ul>
+     * <li>{@link CaptureRequest#CONTROL_AE_REGIONS android.control.aeRegions}</li>
+     * <li>{@link CaptureRequest#CONTROL_AF_REGIONS android.control.afRegions}</li>
+     * <li>{@link CaptureRequest#CONTROL_AWB_REGIONS android.control.awbRegions}</li>
+     * <li>{@link CaptureResult#STATISTICS_FACES android.statistics.faces}</li>
+     * </ul>
+     * <p>Capture results will contain the actual value selected by the API;
+     * <code>ROTATE_AND_CROP_AUTO</code> will never be seen in a capture result.</p>
+     * <p>Applications can also select their preferred cropping mode, either to opt out of the
+     * backwards-compatibility treatment, or to use the cropping feature themselves as needed.
+     * In this case, no coordinate translation will be done automatically, and all controls
+     * will continue to use the normal active array coordinates.</p>
+     * <p>Cropping and rotating is done after the application of digital zoom (via either
+     * {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} or {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio}), but before each individual
+     * output is further cropped and scaled. It only affects processed outputs such as
+     * YUV, PRIVATE, and JPEG.  It has no effect on RAW outputs.</p>
+     * <p>When <code>CROP_90</code> or <code>CROP_270</code> are selected, there is a significant loss to the field of
+     * view. For example, with a 4:3 aspect ratio output of 1600x1200, <code>CROP_90</code> will still
+     * produce 1600x1200 output, but these buffers are cropped from a vertical 3:4 slice at the
+     * center of the 4:3 area, then rotated to be 4:3, and then upscaled to 1600x1200.  Only
+     * 56.25% of the original FOV is still visible.  In general, for an aspect ratio of <code>w:h</code>,
+     * the crop and rotate operation leaves <code>(h/w)^2</code> of the field of view visible. For 16:9,
+     * this is ~31.6%.</p>
+     * <p>As a visual example, the figure below shows the effect of <code>ROTATE_AND_CROP_90</code> on the
+     * outputs for the following parameters:</p>
+     * <ul>
+     * <li>Sensor active array: <code>2000x1500</code></li>
+     * <li>Crop region: top-left: <code>(500, 375)</code>, size: <code>(1000, 750)</code> (4:3 aspect ratio)</li>
+     * <li>Output streams: YUV <code>640x480</code> and YUV <code>1280x720</code></li>
+     * <li><code>ROTATE_AND_CROP_90</code></li>
+     * </ul>
+     * <p><img alt="Effect of ROTATE_AND_CROP_90" src="/reference/images/camera2/metadata/android.scaler.rotateAndCrop/crop-region-rotate-90-43-ratio.png" /></p>
+     * <p>With these settings, the regions of the active array covered by the output streams are:</p>
+     * <ul>
+     * <li>640x480 stream crop: top-left: <code>(219, 375)</code>, size: <code>(562, 750)</code></li>
+     * <li>1280x720 stream crop: top-left: <code>(289, 375)</code>, size: <code>(422, 750)</code></li>
+     * </ul>
+     * <p>Since the buffers are rotated, the buffers as seen by the application are:</p>
+     * <ul>
+     * <li>640x480 stream: top-left: <code>(781, 375)</code> on active array, size: <code>(640, 480)</code>, downscaled 1.17x from sensor pixels</li>
+     * <li>1280x720 stream: top-left: <code>(711, 375)</code> on active array, size: <code>(1280, 720)</code>, upscaled 1.71x from sensor pixels</li>
+     * </ul>
+     * <p><b>Possible values:</b>
+     * <ul>
+     *   <li>{@link #SCALER_ROTATE_AND_CROP_NONE NONE}</li>
+     *   <li>{@link #SCALER_ROTATE_AND_CROP_90 90}</li>
+     *   <li>{@link #SCALER_ROTATE_AND_CROP_180 180}</li>
+     *   <li>{@link #SCALER_ROTATE_AND_CROP_270 270}</li>
+     *   <li>{@link #SCALER_ROTATE_AND_CROP_AUTO AUTO}</li>
+     * </ul></p>
+     * <p><b>Available values for this device:</b><br>
+     * {@link CameraCharacteristics#SCALER_AVAILABLE_ROTATE_AND_CROP_MODES android.scaler.availableRotateAndCropModes}</p>
+     * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
+     *
+     * @see CaptureRequest#CONTROL_AE_REGIONS
+     * @see CaptureRequest#CONTROL_AF_REGIONS
+     * @see CaptureRequest#CONTROL_AWB_REGIONS
+     * @see CaptureRequest#CONTROL_ZOOM_RATIO
+     * @see CameraCharacteristics#SCALER_AVAILABLE_ROTATE_AND_CROP_MODES
+     * @see CaptureRequest#SCALER_CROP_REGION
+     * @see CaptureResult#STATISTICS_FACES
+     * @see #SCALER_ROTATE_AND_CROP_NONE
+     * @see #SCALER_ROTATE_AND_CROP_90
+     * @see #SCALER_ROTATE_AND_CROP_180
+     * @see #SCALER_ROTATE_AND_CROP_270
+     * @see #SCALER_ROTATE_AND_CROP_AUTO
+     */
+    @PublicKey
+    @NonNull
+    public static final Key<Integer> SCALER_ROTATE_AND_CROP =
+            new Key<Integer>("android.scaler.rotateAndCrop", int.class);
+
+    /**
      * <p>Duration each pixel is exposed to
      * light.</p>
      * <p>If the sensor can't expose this exact duration, it will shorten the
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 6f0d135..641a3e1 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -3491,6 +3491,99 @@
             new Key<android.graphics.Rect>("android.scaler.cropRegion", android.graphics.Rect.class);
 
     /**
+     * <p>Whether a rotation-and-crop operation is applied to processed
+     * outputs from the camera.</p>
+     * <p>This control is primarily intended to help camera applications with no support for
+     * multi-window modes to work correctly on devices where multi-window scenarios are
+     * unavoidable, such as foldables or other devices with variable display geometry or more
+     * free-form window placement (such as laptops, which often place portrait-orientation apps
+     * in landscape with pillarboxing).</p>
+     * <p>If supported, the default value is <code>ROTATE_AND_CROP_AUTO</code>, which allows the camera API
+     * to enable backwards-compatibility support for applications that do not support resizing
+     * / multi-window modes, when the device is in fact in a multi-window mode (such as inset
+     * portrait on laptops, or on a foldable device in some fold states).  In addition,
+     * <code>ROTATE_AND_CROP_NONE</code> and <code>ROTATE_AND_CROP_90</code> will always be available if this control
+     * is supported by the device.  If not supported, devices API level 30 or higher will always
+     * list only <code>ROTATE_AND_CROP_NONE</code>.</p>
+     * <p>When <code>CROP_AUTO</code> is in use, and the camera API activates backward-compatibility mode,
+     * several metadata fields will also be parsed differently to ensure that coordinates are
+     * correctly handled for features like drawing face detection boxes or passing in
+     * tap-to-focus coordinates.  The camera API will convert positions in the active array
+     * coordinate system to/from the cropped-and-rotated coordinate system to make the
+     * operation transparent for applications.  The following controls are affected:</p>
+     * <ul>
+     * <li>{@link CaptureRequest#CONTROL_AE_REGIONS android.control.aeRegions}</li>
+     * <li>{@link CaptureRequest#CONTROL_AF_REGIONS android.control.afRegions}</li>
+     * <li>{@link CaptureRequest#CONTROL_AWB_REGIONS android.control.awbRegions}</li>
+     * <li>{@link CaptureResult#STATISTICS_FACES android.statistics.faces}</li>
+     * </ul>
+     * <p>Capture results will contain the actual value selected by the API;
+     * <code>ROTATE_AND_CROP_AUTO</code> will never be seen in a capture result.</p>
+     * <p>Applications can also select their preferred cropping mode, either to opt out of the
+     * backwards-compatibility treatment, or to use the cropping feature themselves as needed.
+     * In this case, no coordinate translation will be done automatically, and all controls
+     * will continue to use the normal active array coordinates.</p>
+     * <p>Cropping and rotating is done after the application of digital zoom (via either
+     * {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} or {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio}), but before each individual
+     * output is further cropped and scaled. It only affects processed outputs such as
+     * YUV, PRIVATE, and JPEG.  It has no effect on RAW outputs.</p>
+     * <p>When <code>CROP_90</code> or <code>CROP_270</code> are selected, there is a significant loss to the field of
+     * view. For example, with a 4:3 aspect ratio output of 1600x1200, <code>CROP_90</code> will still
+     * produce 1600x1200 output, but these buffers are cropped from a vertical 3:4 slice at the
+     * center of the 4:3 area, then rotated to be 4:3, and then upscaled to 1600x1200.  Only
+     * 56.25% of the original FOV is still visible.  In general, for an aspect ratio of <code>w:h</code>,
+     * the crop and rotate operation leaves <code>(h/w)^2</code> of the field of view visible. For 16:9,
+     * this is ~31.6%.</p>
+     * <p>As a visual example, the figure below shows the effect of <code>ROTATE_AND_CROP_90</code> on the
+     * outputs for the following parameters:</p>
+     * <ul>
+     * <li>Sensor active array: <code>2000x1500</code></li>
+     * <li>Crop region: top-left: <code>(500, 375)</code>, size: <code>(1000, 750)</code> (4:3 aspect ratio)</li>
+     * <li>Output streams: YUV <code>640x480</code> and YUV <code>1280x720</code></li>
+     * <li><code>ROTATE_AND_CROP_90</code></li>
+     * </ul>
+     * <p><img alt="Effect of ROTATE_AND_CROP_90" src="/reference/images/camera2/metadata/android.scaler.rotateAndCrop/crop-region-rotate-90-43-ratio.png" /></p>
+     * <p>With these settings, the regions of the active array covered by the output streams are:</p>
+     * <ul>
+     * <li>640x480 stream crop: top-left: <code>(219, 375)</code>, size: <code>(562, 750)</code></li>
+     * <li>1280x720 stream crop: top-left: <code>(289, 375)</code>, size: <code>(422, 750)</code></li>
+     * </ul>
+     * <p>Since the buffers are rotated, the buffers as seen by the application are:</p>
+     * <ul>
+     * <li>640x480 stream: top-left: <code>(781, 375)</code> on active array, size: <code>(640, 480)</code>, downscaled 1.17x from sensor pixels</li>
+     * <li>1280x720 stream: top-left: <code>(711, 375)</code> on active array, size: <code>(1280, 720)</code>, upscaled 1.71x from sensor pixels</li>
+     * </ul>
+     * <p><b>Possible values:</b>
+     * <ul>
+     *   <li>{@link #SCALER_ROTATE_AND_CROP_NONE NONE}</li>
+     *   <li>{@link #SCALER_ROTATE_AND_CROP_90 90}</li>
+     *   <li>{@link #SCALER_ROTATE_AND_CROP_180 180}</li>
+     *   <li>{@link #SCALER_ROTATE_AND_CROP_270 270}</li>
+     *   <li>{@link #SCALER_ROTATE_AND_CROP_AUTO AUTO}</li>
+     * </ul></p>
+     * <p><b>Available values for this device:</b><br>
+     * {@link CameraCharacteristics#SCALER_AVAILABLE_ROTATE_AND_CROP_MODES android.scaler.availableRotateAndCropModes}</p>
+     * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
+     *
+     * @see CaptureRequest#CONTROL_AE_REGIONS
+     * @see CaptureRequest#CONTROL_AF_REGIONS
+     * @see CaptureRequest#CONTROL_AWB_REGIONS
+     * @see CaptureRequest#CONTROL_ZOOM_RATIO
+     * @see CameraCharacteristics#SCALER_AVAILABLE_ROTATE_AND_CROP_MODES
+     * @see CaptureRequest#SCALER_CROP_REGION
+     * @see CaptureResult#STATISTICS_FACES
+     * @see #SCALER_ROTATE_AND_CROP_NONE
+     * @see #SCALER_ROTATE_AND_CROP_90
+     * @see #SCALER_ROTATE_AND_CROP_180
+     * @see #SCALER_ROTATE_AND_CROP_270
+     * @see #SCALER_ROTATE_AND_CROP_AUTO
+     */
+    @PublicKey
+    @NonNull
+    public static final Key<Integer> SCALER_ROTATE_AND_CROP =
+            new Key<Integer>("android.scaler.rotateAndCrop", int.class);
+
+    /**
      * <p>Duration each pixel is exposed to
      * light.</p>
      * <p>If the sensor can't expose this exact duration, it will shorten the
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 3ae3d78..aefe66f 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -621,6 +621,16 @@
                     }
                 });
         sGetCommandMap.put(
+                CameraCharacteristics.SCALER_MANDATORY_CONCURRENT_STREAM_COMBINATIONS.getNativeKey(),
+                        new GetCommand() {
+                    @Override
+                    @SuppressWarnings("unchecked")
+                    public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
+                        return (T) metadata.getMandatoryConcurrentStreamCombinations();
+                    }
+                });
+
+        sGetCommandMap.put(
                 CameraCharacteristics.CONTROL_MAX_REGIONS_AE.getNativeKey(), new GetCommand() {
                     @Override
                     @SuppressWarnings("unchecked")
@@ -1247,7 +1257,8 @@
         return ret;
     }
 
-    private MandatoryStreamCombination[] getMandatoryStreamCombinations() {
+    private MandatoryStreamCombination[] getMandatoryStreamCombinationsHelper(
+            boolean getConcurrent) {
         int[] capabilities = getBase(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
         ArrayList<Integer> caps = new ArrayList<Integer>();
         caps.ensureCapacity(capabilities.length);
@@ -1257,7 +1268,13 @@
         int hwLevel = getBase(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
         MandatoryStreamCombination.Builder build = new MandatoryStreamCombination.Builder(
                 mCameraId, hwLevel, mDisplaySize, caps, getStreamConfigurationMap());
-        List<MandatoryStreamCombination> combs = build.getAvailableMandatoryStreamCombinations();
+
+        List<MandatoryStreamCombination> combs = null;
+        if (getConcurrent) {
+            combs = build.getAvailableMandatoryConcurrentStreamCombinations();
+        } else {
+            combs = build.getAvailableMandatoryStreamCombinations();
+        }
         if ((combs != null) && (!combs.isEmpty())) {
             MandatoryStreamCombination[] combArray = new MandatoryStreamCombination[combs.size()];
             combArray = combs.toArray(combArray);
@@ -1267,6 +1284,17 @@
         return null;
     }
 
+    private MandatoryStreamCombination[] getMandatoryConcurrentStreamCombinations() {
+        if (!mHasMandatoryConcurrentStreams) {
+            return null;
+        }
+        return getMandatoryStreamCombinationsHelper(true);
+    }
+
+    private MandatoryStreamCombination[] getMandatoryStreamCombinations() {
+        return getMandatoryStreamCombinationsHelper(false);
+    }
+
     private StreamConfigurationMap getStreamConfigurationMap() {
         StreamConfiguration[] configurations = getBase(
                 CameraCharacteristics.SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
@@ -1614,6 +1642,7 @@
     }
 
     private int mCameraId = -1;
+    private boolean mHasMandatoryConcurrentStreams = false;
     private Size mDisplaySize = new Size(0, 0);
 
     /**
@@ -1628,6 +1657,18 @@
     }
 
     /**
+     * Set the current camera Id.
+     *
+     * @param hasMandatoryConcurrentStreams whether the metadata advertises mandatory concurrent
+     *        streams.
+     *
+     * @hide
+     */
+    public void setHasMandatoryConcurrentStreams(boolean hasMandatoryConcurrentStreams) {
+        mHasMandatoryConcurrentStreams = hasMandatoryConcurrentStreams;
+    }
+
+    /**
      * Set the current display size.
      *
      * @param displaySize The current display size.
@@ -1682,6 +1723,7 @@
     public void swap(CameraMetadataNative other) {
         nativeSwap(other);
         mCameraId = other.mCameraId;
+        mHasMandatoryConcurrentStreams = other.mHasMandatoryConcurrentStreams;
         mDisplaySize = other.mDisplaySize;
     }
 
diff --git a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java
index 23f18a8..41e1443 100644
--- a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java
+++ b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java
@@ -16,30 +16,27 @@
 
 package android.hardware.camera2.params;
 
-import static com.android.internal.util.Preconditions.*;
 import static android.hardware.camera2.params.StreamConfigurationMap.checkArgumentFormat;
 
-import android.annotation.IntRange;
+import static com.android.internal.util.Preconditions.*;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.content.Context;
 import android.graphics.ImageFormat;
 import android.graphics.ImageFormat.Format;
 import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.CameraCharacteristics.Key;
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CameraManager;
 import android.hardware.camera2.CameraMetadata;
 import android.hardware.camera2.params.StreamConfigurationMap;
 import android.hardware.camera2.utils.HashCodeHelpers;
-import android.graphics.PixelFormat;
 import android.media.CamcorderProfile;
-import android.util.Size;
 import android.util.Log;
 import android.util.Pair;
+import android.util.Size;
 
-import java.util.Arrays;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
@@ -200,7 +197,6 @@
         mDescription = description;
         mIsReprocessable = isReprocessable;
     }
-
     /**
      * Get the mandatory stream combination description.
      *
@@ -271,7 +267,7 @@
                 mStreamsInformation.hashCode());
     }
 
-    private static enum SizeThreshold { VGA, PREVIEW, RECORD, MAXIMUM }
+    private static enum SizeThreshold { VGA, PREVIEW, RECORD, MAXIMUM, s720p }
     private static enum ReprocessType { NONE, PRIVATE, YUV }
     private static final class StreamTemplate {
         public int mFormat;
@@ -653,6 +649,27 @@
                 /*reprocessType*/ ReprocessType.YUV),
     };
 
+    private static StreamCombinationTemplate sConcurrentStreamCombinations[] = {
+        new StreamCombinationTemplate(new StreamTemplate [] {
+                new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.s720p) },
+                "In-app video / image processing"),
+        new StreamCombinationTemplate(new StreamTemplate [] {
+                new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.s720p) },
+                "preview / preview to GPU"),
+        new StreamCombinationTemplate(new StreamTemplate [] {
+                new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.s720p),
+                new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.s720p)},
+                "In-app video / image processing with preview"),
+        new StreamCombinationTemplate(new StreamTemplate [] {
+                new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.s720p),
+                new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.s720p)},
+                "In-app video / image processing with preview"),
+        new StreamCombinationTemplate(new StreamTemplate [] {
+                new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.s720p),
+                new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.s720p)},
+                "Standard Recording"),
+    };
+
     /**
      * Helper builder class to generate a list of available mandatory stream combinations.
      * @hide
@@ -687,6 +704,64 @@
         }
 
         /**
+          * Retrieve a list of all available mandatory concurrent stream combinations.
+          * This method should only be called for devices which are listed in combinations returned
+          * by CameraManager.getConcurrentStreamingCameraIds.
+          *
+          * @return a non-modifiable list of supported mandatory concurrent stream combinations.
+          */
+        public @NonNull List<MandatoryStreamCombination>
+                getAvailableMandatoryConcurrentStreamCombinations() {
+            // Since concurrent streaming support is optional, we mandate these stream
+            // combinations regardless of camera device capabilities.
+            if (!isColorOutputSupported()) {
+                Log.v(TAG, "Device is not backward compatible!");
+                throw new IllegalArgumentException("Camera device which is not BACKWARD_COMPATIBLE"
+                         + " cannot have mandatory concurrent streams");
+            }
+            Size size720p = new Size(1280, 720);
+
+            ArrayList<MandatoryStreamCombination> availableConcurrentStreamCombinations =
+                    new ArrayList<MandatoryStreamCombination>();
+            availableConcurrentStreamCombinations.ensureCapacity(
+                    sConcurrentStreamCombinations.length);
+            for (StreamCombinationTemplate combTemplate : sConcurrentStreamCombinations) {
+                ArrayList<MandatoryStreamInformation> streamsInfo =
+                        new ArrayList<MandatoryStreamInformation>();
+                streamsInfo.ensureCapacity(combTemplate.mStreamTemplates.length);
+                for (StreamTemplate template : combTemplate.mStreamTemplates) {
+                    MandatoryStreamInformation streamInfo;
+                    List<Size> sizes = new ArrayList<Size>();
+                    Size sizeChosen =
+                            getMinSize(size720p,
+                                    getMaxSize(mStreamConfigMap.getOutputSizes(template.mFormat)));
+                    sizes.add(sizeChosen);
+                    try {
+                        streamInfo = new MandatoryStreamInformation(sizes, template.mFormat);
+                    } catch (IllegalArgumentException e) {
+                        String cause = "No available sizes found for format: " + template.mFormat
+                                + " size threshold: " + template.mSizeThreshold + " combination: "
+                                + combTemplate.mDescription;
+                        throw new RuntimeException(cause, e);
+                    }
+                    streamsInfo.add(streamInfo);
+                }
+
+                MandatoryStreamCombination streamCombination;
+                try {
+                    streamCombination = new MandatoryStreamCombination(streamsInfo,
+                            combTemplate.mDescription, /*isReprocess*/false);
+                } catch (IllegalArgumentException e) {
+                    String cause =  "No stream information for mandatory combination: "
+                            + combTemplate.mDescription;
+                    throw new RuntimeException(cause, e);
+                }
+                availableConcurrentStreamCombinations.add(streamCombination);
+            }
+            return Collections.unmodifiableList(availableConcurrentStreamCombinations);
+        }
+
+        /**
          * Retrieve a list of all available mandatory stream combinations.
          *
          * @return a non-modifiable list of supported mandatory stream combinations or
@@ -965,6 +1040,18 @@
         }
 
         /**
+         * Return the lower size
+         */
+        public static @Nullable Size getMinSize(Size a, Size b) {
+            if (a == null || b == null) {
+                throw new IllegalArgumentException("sizes was empty");
+            }
+            if (a.getWidth() * a.getHeight() < b.getHeight() * b.getWidth()) {
+                return a;
+            }
+            return b;
+        }
+        /**
          * Get the largest size by area.
          *
          * @param sizes an array of sizes, must have at least 1 element
diff --git a/core/java/android/hardware/camera2/utils/CameraIdAndSessionConfiguration.java b/core/java/android/hardware/camera2/utils/CameraIdAndSessionConfiguration.java
new file mode 100644
index 0000000..cdc037c
--- /dev/null
+++ b/core/java/android/hardware/camera2/utils/CameraIdAndSessionConfiguration.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.camera2.utils;
+
+import android.annotation.NonNull;
+import android.hardware.camera2.params.SessionConfiguration;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * CameraIdAndSessionConfiguration
+ *
+ * Includes the pair of a cameraId and its corresponding SessionConfiguration, to be used with
+ * ICameraService.isConcurrentSessionConfigurationSupported.
+ * @hide
+ */
+public class CameraIdAndSessionConfiguration implements Parcelable {
+
+    private String mCameraId;
+    private SessionConfiguration mSessionConfiguration;
+
+    public CameraIdAndSessionConfiguration(@NonNull String cameraId,
+            @NonNull SessionConfiguration sessionConfiguration) {
+        mCameraId = cameraId;
+        mSessionConfiguration = sessionConfiguration;
+    }
+
+    public static final @NonNull
+            Parcelable.Creator<CameraIdAndSessionConfiguration> CREATOR =
+            new Parcelable.Creator<CameraIdAndSessionConfiguration>() {
+        @Override
+        public CameraIdAndSessionConfiguration createFromParcel(Parcel in) {
+            return new CameraIdAndSessionConfiguration(in);
+        }
+
+        @Override
+        public CameraIdAndSessionConfiguration[] newArray(int size) {
+            return new CameraIdAndSessionConfiguration[size];
+        }
+    };
+
+    private CameraIdAndSessionConfiguration(Parcel in) {
+        readFromParcel(in);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mCameraId);
+        mSessionConfiguration.writeToParcel(dest, flags);
+    }
+
+    /**
+     * helper for CREATOR
+     */
+    public void readFromParcel(Parcel in) {
+        mCameraId = in.readString();
+        mSessionConfiguration = SessionConfiguration.CREATOR.createFromParcel(in);
+    }
+
+    public @NonNull String getCameraId() {
+        return mCameraId;
+    }
+
+    public @NonNull SessionConfiguration getSessionConfiguration() {
+        return mSessionConfiguration;
+    }
+}
diff --git a/core/java/android/hardware/camera2/utils/ConcurrentCameraIdCombination.java b/core/java/android/hardware/camera2/utils/ConcurrentCameraIdCombination.java
new file mode 100644
index 0000000..8f4d636
--- /dev/null
+++ b/core/java/android/hardware/camera2/utils/ConcurrentCameraIdCombination.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.camera2.utils;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * ConcurrentCameraIdCombination
+ *
+ * Includes a list of camera ids that may have sessions configured concurrently.
+ * @hide
+ */
+public class ConcurrentCameraIdCombination implements Parcelable {
+
+    private Set<String> mConcurrentCameraIds = new HashSet<>();
+
+    public static final @NonNull
+            Parcelable.Creator<ConcurrentCameraIdCombination> CREATOR =
+            new Parcelable.Creator<ConcurrentCameraIdCombination>() {
+        @Override
+        public ConcurrentCameraIdCombination createFromParcel(Parcel in) {
+            return new ConcurrentCameraIdCombination(in);
+        }
+
+        @Override
+        public ConcurrentCameraIdCombination[] newArray(int size) {
+            return new ConcurrentCameraIdCombination[size];
+        }
+    };
+
+    private ConcurrentCameraIdCombination(Parcel in) {
+        readFromParcel(in);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mConcurrentCameraIds.size());
+        for (String cameraId : mConcurrentCameraIds) {
+            dest.writeString(cameraId);
+        }
+    }
+
+    /**
+     * helper for CREATOR
+     */
+    public void readFromParcel(Parcel in) {
+        mConcurrentCameraIds.clear();
+        int cameraCombinationSize = in.readInt();
+        if (cameraCombinationSize < 0) {
+            throw new RuntimeException("cameraCombinationSize " + cameraCombinationSize
+                    + " should not be negative");
+        }
+        for (int i = 0; i < cameraCombinationSize; i++) {
+            String cameraId = in.readString();
+            if (cameraId == null) {
+                throw new RuntimeException("Failed to read camera id from Parcel");
+            }
+            mConcurrentCameraIds.add(cameraId);
+        }
+    }
+
+    /**
+     * Get this concurrent camera id combination.
+     */
+    public Set<String> getConcurrentCameraIdCombination() {
+        return mConcurrentCameraIds;
+    }
+}
diff --git a/core/java/android/hardware/display/BrightnessConfiguration.java b/core/java/android/hardware/display/BrightnessConfiguration.java
index 13122d2..6412a0c 100644
--- a/core/java/android/hardware/display/BrightnessConfiguration.java
+++ b/core/java/android/hardware/display/BrightnessConfiguration.java
@@ -61,7 +61,7 @@
     private static final String ATTR_MODEL_LOWER_BOUND = "model-lower-bound";
     private static final String ATTR_MODEL_UPPER_BOUND = "model-upper-bound";
     /**
-     * Returned from {@link #getShortTermModelTimeout()} if no timeout has been set.
+     * Returned from {@link #getShortTermModelTimeoutMillis()} if no timeout has been set.
      * In this case the device will use the default timeout available in the
      * {@link BrightnessConfiguration} returned from
      * {@link DisplayManager#getDefaultBrightnessConfiguration()}.
@@ -160,7 +160,7 @@
      * {@link #getShortTermModelUpperLuxMultiplier()} to decide whether to keep any adjustment
      * the user has made to adaptive brightness.
      */
-    public long getShortTermModelTimeout() {
+    public long getShortTermModelTimeoutMillis() {
         return mShortTermModelTimeout;
     }
 
@@ -326,7 +326,7 @@
             builder.setDescription(description);
             final boolean shouldCollectColorSamples = in.readBoolean();
             builder.setShouldCollectColorSamples(shouldCollectColorSamples);
-            builder.setShortTermModelTimeout(in.readLong());
+            builder.setShortTermModelTimeoutMillis(in.readLong());
             builder.setShortTermModelLowerLuxMultiplier(in.readFloat());
             builder.setShortTermModelUpperLuxMultiplier(in.readFloat());
             return builder.build();
@@ -487,7 +487,7 @@
             builder.addCorrectionByCategory(category, correction);
         }
         builder.setShouldCollectColorSamples(shouldCollectColorSamples);
-        builder.setShortTermModelTimeout(shortTermModelTimeout);
+        builder.setShortTermModelTimeoutMillis(shortTermModelTimeout);
         builder.setShortTermModelLowerLuxMultiplier(shortTermModelLowerLuxMultiplier);
         builder.setShortTermModelUpperLuxMultiplier(shortTermModelUpperLuxMultiplier);
         return builder.build();
@@ -673,8 +673,8 @@
          * adjustment the user has made to adaptive brightness.
          */
         @NonNull
-        public Builder setShortTermModelTimeout(long shortTermModelTimeout) {
-            mShortTermModelTimeout = shortTermModelTimeout;
+        public Builder setShortTermModelTimeoutMillis(long shortTermModelTimeoutMillis) {
+            mShortTermModelTimeout = shortTermModelTimeoutMillis;
             return this;
         }
 
diff --git a/core/java/android/hardware/location/ContextHubClient.java b/core/java/android/hardware/location/ContextHubClient.java
index c6a5dd0..43480ab 100644
--- a/core/java/android/hardware/location/ContextHubClient.java
+++ b/core/java/android/hardware/location/ContextHubClient.java
@@ -136,7 +136,10 @@
      * @see NanoAppMessage
      * @see ContextHubTransaction.Result
      */
-    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.LOCATION_HARDWARE,
+            android.Manifest.permission.ACCESS_CONTEXT_HUB
+    })
     @ContextHubTransaction.Result
     public int sendMessageToNanoApp(@NonNull NanoAppMessage message) {
         Objects.requireNonNull(message, "NanoAppMessage cannot be null");
diff --git a/core/java/android/hardware/location/ContextHubInfo.java b/core/java/android/hardware/location/ContextHubInfo.java
index a11f2e9..6d56d2d 100644
--- a/core/java/android/hardware/location/ContextHubInfo.java
+++ b/core/java/android/hardware/location/ContextHubInfo.java
@@ -21,6 +21,7 @@
 import android.hardware.contexthub.V1_0.ContextHub;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.proto.ProtoOutputStream;
 
 import java.util.Arrays;
 
@@ -270,6 +271,30 @@
         return retVal;
     }
 
+    /**
+     * Dump the internal state as a ContextHubInfoProto to the given ProtoOutputStream.
+     *
+     * If the output belongs to a sub message, the caller is responsible for wrapping this function
+     * between {@link ProtoOutputStream#start(long)} and {@link ProtoOutputStream#end(long)}.
+     *
+     * @hide
+     */
+    public void dump(ProtoOutputStream proto) {
+        proto.write(ContextHubInfoProto.ID, mId);
+        proto.write(ContextHubInfoProto.NAME, mName);
+        proto.write(ContextHubInfoProto.VENDOR, mVendor);
+        proto.write(ContextHubInfoProto.TOOLCHAIN, mToolchain);
+        proto.write(ContextHubInfoProto.PLATFORM_VERSION, mPlatformVersion);
+        proto.write(ContextHubInfoProto.STATIC_SW_VERSION, getStaticSwVersion());
+        proto.write(ContextHubInfoProto.TOOLCHAIN_VERSION, mToolchainVersion);
+        proto.write(ContextHubInfoProto.CHRE_PLATFORM_ID, mChrePlatformId);
+        proto.write(ContextHubInfoProto.PEAK_MIPS, mPeakMips);
+        proto.write(ContextHubInfoProto.STOPPED_POWER_DRAW_MW, mStoppedPowerDrawMw);
+        proto.write(ContextHubInfoProto.SLEEP_POWER_DRAW_MW, mSleepPowerDrawMw);
+        proto.write(ContextHubInfoProto.PEAK_POWER_DRAW_MW, mPeakPowerDrawMw);
+        proto.write(ContextHubInfoProto.MAX_PACKET_LENGTH_BYTES, mMaxPacketLengthBytes);
+    }
+
     @Override
     public boolean equals(@Nullable Object object) {
         if (object == this) {
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index a51d2c9..db16d24 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
@@ -26,6 +27,7 @@
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.os.Handler;
 import android.os.HandlerExecutor;
 import android.os.Looper;
@@ -44,12 +46,15 @@
  * A class that exposes the Context hubs on a device to applications.
  *
  * Please note that this class is not expected to be used by unbundled applications. Also, calling
- * applications are expected to have LOCATION_HARDWARE permissions to use this class.
+ * applications are expected to have LOCATION_HARDWARE or ACCESS_CONTEXT_HUB permissions to use this
+ * class. Use of LOCATION_HARDWARE to enable access to these APIs is deprecated and may be removed
+ * in the future - all applications are recommended to move to the ACCESS_CONTEXT_HUB permission.
  *
  * @hide
  */
 @SystemApi
 @SystemService(Context.CONTEXTHUB_SERVICE)
+@RequiresFeature(PackageManager.FEATURE_CONTEXTHUB)
 public final class ContextHubManager {
     private static final String TAG = "ContextHubManager";
 
@@ -196,7 +201,10 @@
      *             new APIs.
      */
     @Deprecated
-    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.LOCATION_HARDWARE,
+            android.Manifest.permission.ACCESS_CONTEXT_HUB
+    })
     public int[] getContextHubHandles() {
         try {
             return mService.getContextHubHandles();
@@ -217,7 +225,10 @@
      *             new APIs.
      */
     @Deprecated
-    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.LOCATION_HARDWARE,
+            android.Manifest.permission.ACCESS_CONTEXT_HUB
+    })
     public ContextHubInfo getContextHubInfo(int hubHandle) {
         try {
             return mService.getContextHubInfo(hubHandle);
@@ -248,7 +259,10 @@
      * @deprecated Use {@link #loadNanoApp(ContextHubInfo, NanoAppBinary)} instead.
      */
     @Deprecated
-    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.LOCATION_HARDWARE,
+            android.Manifest.permission.ACCESS_CONTEXT_HUB
+    })
     public int loadNanoApp(int hubHandle, @NonNull NanoApp app) {
         try {
             return mService.loadNanoApp(hubHandle, app);
@@ -275,7 +289,10 @@
      * @deprecated Use {@link #unloadNanoApp(ContextHubInfo, long)} instead.
      */
     @Deprecated
-    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.LOCATION_HARDWARE,
+            android.Manifest.permission.ACCESS_CONTEXT_HUB
+    })
     public int unloadNanoApp(int nanoAppHandle) {
         try {
             return mService.unloadNanoApp(nanoAppHandle);
@@ -315,7 +332,10 @@
      *             for loaded nanoapps.
      */
     @Deprecated
-    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.LOCATION_HARDWARE,
+            android.Manifest.permission.ACCESS_CONTEXT_HUB
+    })
     @Nullable public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppHandle) {
         try {
             return mService.getNanoAppInstanceInfo(nanoAppHandle);
@@ -338,7 +358,10 @@
      *             for loaded nanoapps.
      */
     @Deprecated
-    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.LOCATION_HARDWARE,
+            android.Manifest.permission.ACCESS_CONTEXT_HUB
+    })
     @NonNull public int[] findNanoAppOnHub(int hubHandle, @NonNull NanoAppFilter filter) {
         try {
             return mService.findNanoAppOnHub(hubHandle, filter);
@@ -373,7 +396,10 @@
      *             or {@link #createClient(ContextHubInfo, ContextHubClientCallback)}.
      */
     @Deprecated
-    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.LOCATION_HARDWARE,
+            android.Manifest.permission.ACCESS_CONTEXT_HUB
+    })
     public int sendMessage(int hubHandle, int nanoAppHandle, @NonNull ContextHubMessage message) {
         try {
             return mService.sendMessage(hubHandle, nanoAppHandle, message);
@@ -389,7 +415,10 @@
      *
      * @see ContextHubInfo
      */
-    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.LOCATION_HARDWARE,
+            android.Manifest.permission.ACCESS_CONTEXT_HUB
+    })
     @NonNull public List<ContextHubInfo> getContextHubs() {
         try {
             return mService.getContextHubs();
@@ -466,7 +495,10 @@
      *
      * @see NanoAppBinary
      */
-    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.LOCATION_HARDWARE,
+            android.Manifest.permission.ACCESS_CONTEXT_HUB
+    })
     @NonNull public ContextHubTransaction<Void> loadNanoApp(
             @NonNull ContextHubInfo hubInfo, @NonNull NanoAppBinary appBinary) {
         Objects.requireNonNull(hubInfo, "ContextHubInfo cannot be null");
@@ -495,7 +527,10 @@
      *
      * @throws NullPointerException if hubInfo is null
      */
-    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.LOCATION_HARDWARE,
+            android.Manifest.permission.ACCESS_CONTEXT_HUB
+    })
     @NonNull public ContextHubTransaction<Void> unloadNanoApp(
             @NonNull ContextHubInfo hubInfo, long nanoAppId) {
         Objects.requireNonNull(hubInfo, "ContextHubInfo cannot be null");
@@ -523,7 +558,10 @@
      *
      * @throws NullPointerException if hubInfo is null
      */
-    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.LOCATION_HARDWARE,
+            android.Manifest.permission.ACCESS_CONTEXT_HUB
+    })
     @NonNull public ContextHubTransaction<Void> enableNanoApp(
             @NonNull ContextHubInfo hubInfo, long nanoAppId) {
         Objects.requireNonNull(hubInfo, "ContextHubInfo cannot be null");
@@ -551,7 +589,10 @@
      *
      * @throws NullPointerException if hubInfo is null
      */
-    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.LOCATION_HARDWARE,
+            android.Manifest.permission.ACCESS_CONTEXT_HUB
+    })
     @NonNull public ContextHubTransaction<Void> disableNanoApp(
             @NonNull ContextHubInfo hubInfo, long nanoAppId) {
         Objects.requireNonNull(hubInfo, "ContextHubInfo cannot be null");
@@ -578,7 +619,10 @@
      *
      * @throws NullPointerException if hubInfo is null
      */
-    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.LOCATION_HARDWARE,
+            android.Manifest.permission.ACCESS_CONTEXT_HUB
+    })
     @NonNull public ContextHubTransaction<List<NanoAppState>> queryNanoApps(
             @NonNull ContextHubInfo hubInfo) {
         Objects.requireNonNull(hubInfo, "ContextHubInfo cannot be null");
@@ -724,7 +768,10 @@
      *
      * @see ContextHubClientCallback
      */
-    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.LOCATION_HARDWARE,
+            android.Manifest.permission.ACCESS_CONTEXT_HUB
+    })
     @NonNull public ContextHubClient createClient(
             @NonNull ContextHubInfo hubInfo, @NonNull ContextHubClientCallback callback,
             @NonNull @CallbackExecutor Executor executor) {
@@ -761,7 +808,10 @@
      *
      * @see ContextHubClientCallback
      */
-    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.LOCATION_HARDWARE,
+            android.Manifest.permission.ACCESS_CONTEXT_HUB
+    })
     @NonNull public ContextHubClient createClient(
             @NonNull ContextHubInfo hubInfo, @NonNull ContextHubClientCallback callback) {
         return createClient(hubInfo, callback, new HandlerExecutor(Handler.getMain()));
@@ -780,6 +830,9 @@
      * If a client is regenerated, the host endpoint identifier attached to messages sent to the
      * nanoapp remains consistent, even if the original process has exited.
      *
+     * To avoid unintentionally spreading data from the Context Hub to external applications, it is
+     * strongly recommended that the PendingIntent supplied to this API is an explicit intent.
+     *
      * If registered successfully, intents will be delivered regarding events or messages from the
      * specified nanoapp from the attached Context Hub. The intent will have an extra
      * {@link ContextHubManager.EXTRA_CONTEXT_HUB_INFO} of type {@link ContextHubInfo}, which
@@ -804,7 +857,10 @@
      * @throws IllegalStateException    if there were too many registered clients at the service
      * @throws NullPointerException     if pendingIntent or hubInfo is null
      */
-    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.LOCATION_HARDWARE,
+            android.Manifest.permission.ACCESS_CONTEXT_HUB
+    })
     @NonNull public ContextHubClient createClient(
             @NonNull ContextHubInfo hubInfo, @NonNull PendingIntent pendingIntent, long nanoAppId) {
         Objects.requireNonNull(pendingIntent);
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 827353b..086db10 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -262,6 +262,15 @@
     public static final String USB_FUNCTION_ACCESSORY = "accessory";
 
     /**
+     * Name of the NCM USB function.
+     * Used in extras for the {@link #ACTION_USB_STATE} broadcast
+     *
+     * {@hide}
+     */
+    @SystemApi
+    public static final String USB_FUNCTION_NCM = "ncm";
+
+    /**
      * Name of extra for {@link #ACTION_USB_PORT_CHANGED}
      * containing the {@link UsbPort} object for the port.
      *
@@ -367,8 +376,15 @@
      */
     public static final long FUNCTION_ADB = GadgetFunction.ADB;
 
+    /**
+     * Code for the ncm source usb function.
+     * {@hide}
+     */
+    @SystemApi
+    public static final long FUNCTION_NCM = 1 << 10;
+
     private static final long SETTABLE_FUNCTIONS = FUNCTION_MTP | FUNCTION_PTP | FUNCTION_RNDIS
-            | FUNCTION_MIDI;
+            | FUNCTION_MIDI | FUNCTION_NCM;
 
     private static final Map<String, Long> FUNCTION_NAME_TO_CODE = new HashMap<>();
 
@@ -380,6 +396,7 @@
         FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_ACCESSORY, FUNCTION_ACCESSORY);
         FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_AUDIO_SOURCE, FUNCTION_AUDIO_SOURCE);
         FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_ADB, FUNCTION_ADB);
+        FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_NCM, FUNCTION_NCM);
     }
 
     private final Context mContext;
@@ -954,6 +971,9 @@
         if ((functions & FUNCTION_AUDIO_SOURCE) != 0) {
             joiner.add(UsbManager.USB_FUNCTION_AUDIO_SOURCE);
         }
+        if ((functions & FUNCTION_NCM) != 0) {
+            joiner.add(UsbManager.USB_FUNCTION_NCM);
+        }
         if ((functions & FUNCTION_ADB) != 0) {
             joiner.add(UsbManager.USB_FUNCTION_ADB);
         }
diff --git a/core/java/android/net/ConnectivityDiagnosticsManager.java b/core/java/android/net/ConnectivityDiagnosticsManager.java
index a6f9b96..b13e4b7 100644
--- a/core/java/android/net/ConnectivityDiagnosticsManager.java
+++ b/core/java/android/net/ConnectivityDiagnosticsManager.java
@@ -19,7 +19,9 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.StringDef;
 import android.content.Context;
+import android.os.Binder;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.PersistableBundle;
@@ -79,6 +81,128 @@
 
     /** Class that includes connectivity information for a specific Network at a specific time. */
     public static final class ConnectivityReport implements Parcelable {
+        /**
+         * The overall status of the network is that it is invalid; it neither provides
+         * connectivity nor has been exempted from validation.
+         */
+        public static final int NETWORK_VALIDATION_RESULT_INVALID = 0;
+
+        /**
+         * The overall status of the network is that it is valid, this may be because it provides
+         * full Internet access (all probes succeeded), or because other properties of the network
+         * caused probes not to be run.
+         */
+        // TODO: link to INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID
+        public static final int NETWORK_VALIDATION_RESULT_VALID = 1;
+
+        /**
+         * The overall status of the network is that it provides partial connectivity; some
+         * probed services succeeded but others failed.
+         */
+        // TODO: link to INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
+        public static final int NETWORK_VALIDATION_RESULT_PARTIALLY_VALID = 2;
+
+        /**
+         * Due to the properties of the network, validation was not performed.
+         */
+        public static final int NETWORK_VALIDATION_RESULT_SKIPPED = 3;
+
+        /** @hide */
+        @IntDef(
+                prefix = {"NETWORK_VALIDATION_RESULT_"},
+                value = {
+                        NETWORK_VALIDATION_RESULT_INVALID,
+                        NETWORK_VALIDATION_RESULT_VALID,
+                        NETWORK_VALIDATION_RESULT_PARTIALLY_VALID,
+                        NETWORK_VALIDATION_RESULT_SKIPPED
+                })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface NetworkValidationResult {}
+
+        /**
+         * The overall validation result for the Network being reported on.
+         *
+         * <p>The possible values for this key are:
+         * {@link #NETWORK_VALIDATION_RESULT_INVALID},
+         * {@link #NETWORK_VALIDATION_RESULT_VALID},
+         * {@link #NETWORK_VALIDATION_RESULT_PARTIALLY_VALID},
+         * {@link #NETWORK_VALIDATION_RESULT_SKIPPED}.
+         *
+         * @see android.net.NetworkCapabilities#CAPABILITY_VALIDATED
+         */
+        @NetworkValidationResult
+        public static final String KEY_NETWORK_VALIDATION_RESULT = "networkValidationResult";
+
+        /** DNS probe. */
+        // TODO: link to INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS
+        public static final int NETWORK_PROBE_DNS = 0x04;
+
+        /** HTTP probe. */
+        // TODO: link to INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTP
+        public static final int NETWORK_PROBE_HTTP = 0x08;
+
+        /** HTTPS probe. */
+        // TODO: link to INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTPS;
+        public static final int NETWORK_PROBE_HTTPS = 0x10;
+
+        /** Captive portal fallback probe. */
+        // TODO: link to INetworkMonitor.NETWORK_VALIDATION_FALLBACK
+        public static final int NETWORK_PROBE_FALLBACK = 0x20;
+
+        /** Private DNS (DNS over TLS) probd. */
+        // TODO: link to INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS
+        public static final int NETWORK_PROBE_PRIVATE_DNS = 0x40;
+
+        /** @hide */
+        @IntDef(
+                prefix = {"NETWORK_PROBE_"},
+                value = {
+                        NETWORK_PROBE_DNS,
+                        NETWORK_PROBE_HTTP,
+                        NETWORK_PROBE_HTTPS,
+                        NETWORK_PROBE_FALLBACK,
+                        NETWORK_PROBE_PRIVATE_DNS
+                })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface NetworkProbe {}
+
+        /**
+         * A bitmask of network validation probes that succeeded.
+         *
+         * <p>The possible bits values reported by this key are:
+         * {@link #NETWORK_PROBE_DNS},
+         * {@link #NETWORK_PROBE_HTTP},
+         * {@link #NETWORK_PROBE_HTTPS},
+         * {@link #NETWORK_PROBE_FALLBACK},
+         * {@link #NETWORK_PROBE_PRIVATE_DNS}.
+         */
+        @NetworkProbe
+        public static final String KEY_NETWORK_PROBES_SUCCEEDED_BITMASK =
+                "networkProbesSucceeded";
+
+        /**
+         * A bitmask of network validation probes that were attempted.
+         *
+         * <p>These probes may have failed or may be incomplete at the time of this report.
+         *
+         * <p>The possible bits values reported by this key are:
+         * {@link #NETWORK_PROBE_DNS},
+         * {@link #NETWORK_PROBE_HTTP},
+         * {@link #NETWORK_PROBE_HTTPS},
+         * {@link #NETWORK_PROBE_FALLBACK},
+         * {@link #NETWORK_PROBE_PRIVATE_DNS}.
+         */
+        @NetworkProbe
+        public static final String KEY_NETWORK_PROBES_ATTEMPTED_BITMASK =
+                "networkProbesAttemped";
+
+        /** @hide */
+        @StringDef(prefix = {"KEY_"}, value = {
+                KEY_NETWORK_VALIDATION_RESULT, KEY_NETWORK_PROBES_SUCCEEDED_BITMASK,
+                KEY_NETWORK_PROBES_ATTEMPTED_BITMASK})
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface ConnectivityReportBundleKeys {}
+
         /** The Network for which this ConnectivityReport applied */
         @NonNull private final Network mNetwork;
 
@@ -218,7 +342,7 @@
 
         /** Implement the Parcelable interface */
         public static final @NonNull Creator<ConnectivityReport> CREATOR =
-                new Creator<>() {
+                new Creator<ConnectivityReport>() {
                     public ConnectivityReport createFromParcel(Parcel in) {
                         return new ConnectivityReport(
                                 in.readParcelable(null),
@@ -246,6 +370,49 @@
                 value = {DETECTION_METHOD_DNS_EVENTS, DETECTION_METHOD_TCP_METRICS})
         public @interface DetectionMethod {}
 
+        /**
+         * This key represents the period in milliseconds over which other included TCP metrics
+         * were measured.
+         *
+         * <p>This key will be included if the data stall detection method is
+         * {@link #DETECTION_METHOD_TCP_METRICS}.
+         *
+         * <p>This value is an int.
+         */
+        public static final String KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS =
+                "tcpMetricsCollectionPeriodMillis";
+
+        /**
+         * This key represents the fail rate of TCP packets when the suspected data stall was
+         * detected.
+         *
+         * <p>This key will be included if the data stall detection method is
+         * {@link #DETECTION_METHOD_TCP_METRICS}.
+         *
+         * <p>This value is an int percentage between 0 and 100.
+         */
+        public static final String KEY_TCP_PACKET_FAIL_RATE = "tcpPacketFailRate";
+
+        /**
+         * This key represents the consecutive number of DNS timeouts that have occurred.
+         *
+         * <p>The consecutive count will be reset any time a DNS response is received.
+         *
+         * <p>This key will be included if the data stall detection method is
+         * {@link #DETECTION_METHOD_DNS_EVENTS}.
+         *
+         * <p>This value is an int.
+         */
+        public static final String KEY_DNS_CONSECUTIVE_TIMEOUTS = "dnsConsecutiveTimeouts";
+
+        /** @hide */
+        @Retention(RetentionPolicy.SOURCE)
+        @StringDef(prefix = {"KEY_"}, value = {
+                KEY_TCP_PACKET_FAIL_RATE,
+                KEY_DNS_CONSECUTIVE_TIMEOUTS
+        })
+        public @interface DataStallReportBundleKeys {}
+
         /** The Network for which this DataStallReport applied */
         @NonNull private final Network mNetwork;
 
@@ -315,6 +482,9 @@
         /**
          * Returns a PersistableBundle with additional info for this report.
          *
+         * <p>Gets a bundle with details about the suspected data stall including information
+         * specific to the monitoring method that detected the data stall.
+         *
          * @return PersistableBundle that may contain additional information on the suspected data
          *     stall
          */
@@ -375,6 +545,53 @@
                 };
     }
 
+    /** @hide */
+    @VisibleForTesting
+    public static class ConnectivityDiagnosticsBinder
+            extends IConnectivityDiagnosticsCallback.Stub {
+        @NonNull private final ConnectivityDiagnosticsCallback mCb;
+        @NonNull private final Executor mExecutor;
+
+        /** @hide */
+        @VisibleForTesting
+        public ConnectivityDiagnosticsBinder(
+                @NonNull ConnectivityDiagnosticsCallback cb, @NonNull Executor executor) {
+            this.mCb = cb;
+            this.mExecutor = executor;
+        }
+
+        /** @hide */
+        @VisibleForTesting
+        public void onConnectivityReport(@NonNull ConnectivityReport report) {
+            Binder.withCleanCallingIdentity(() -> {
+                mExecutor.execute(() -> {
+                    mCb.onConnectivityReport(report);
+                });
+            });
+        }
+
+        /** @hide */
+        @VisibleForTesting
+        public void onDataStallSuspected(@NonNull DataStallReport report) {
+            Binder.withCleanCallingIdentity(() -> {
+                mExecutor.execute(() -> {
+                    mCb.onDataStallSuspected(report);
+                });
+            });
+        }
+
+        /** @hide */
+        @VisibleForTesting
+        public void onNetworkConnectivityReported(
+                @NonNull Network network, boolean hasConnectivity) {
+            Binder.withCleanCallingIdentity(() -> {
+                mExecutor.execute(() -> {
+                    mCb.onNetworkConnectivityReported(network, hasConnectivity);
+                });
+            });
+        }
+    }
+
     /**
      * Abstract base class for Connectivity Diagnostics callbacks. Used for notifications about
      * network connectivity events. Must be extended by applications wanting notifications.
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 753e754..ce9693d 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -33,7 +33,9 @@
 import android.content.Intent;
 import android.net.IpSecManager.UdpEncapsulationSocket;
 import android.net.SocketKeepalive.Callback;
+import android.net.TetheringManager.StartTetheringCallback;
 import android.net.TetheringManager.TetheringEventCallback;
+import android.net.TetheringManager.TetheringRequest;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Build.VERSION_CODES;
@@ -2452,10 +2454,12 @@
      *
      * @param iface the interface name to tether.
      * @return error a {@code TETHER_ERROR} value indicating success or failure type
+     * @deprecated Use {@link TetheringManager#startTethering} instead
      *
      * {@hide}
      */
     @UnsupportedAppUsage
+    @Deprecated
     public int tether(String iface) {
         return getTetheringManager().tether(iface);
     }
@@ -2512,9 +2516,12 @@
 
     /**
      * Callback for use with {@link #startTethering} to find out whether tethering succeeded.
+     *
+     * @deprecated Use {@link TetheringManager.StartTetheringCallback} instead.
      * @hide
      */
     @SystemApi
+    @Deprecated
     public static abstract class OnStartTetheringCallback {
         /**
          * Called when tethering has been successfully started.
@@ -2531,9 +2538,12 @@
      * Convenient overload for
      * {@link #startTethering(int, boolean, OnStartTetheringCallback, Handler)} which passes a null
      * handler to run on the current thread's {@link Looper}.
+     *
+     * @deprecated Use {@link TetheringManager#startTethering} instead.
      * @hide
      */
     @SystemApi
+    @Deprecated
     @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
     public void startTethering(int type, boolean showProvisioningUi,
             final OnStartTetheringCallback callback) {
@@ -2557,26 +2567,44 @@
      * @param callback an {@link OnStartTetheringCallback} which will be called to notify the caller
      *         of the result of trying to tether.
      * @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
+     *
+     * @deprecated Use {@link TetheringManager#startTethering} instead.
      * @hide
      */
     @SystemApi
+    @Deprecated
     @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
     public void startTethering(int type, boolean showProvisioningUi,
             final OnStartTetheringCallback callback, Handler handler) {
         Preconditions.checkNotNull(callback, "OnStartTetheringCallback cannot be null.");
 
-        ResultReceiver wrappedCallback = new ResultReceiver(handler) {
+        final Executor executor = new Executor() {
             @Override
-            protected void onReceiveResult(int resultCode, Bundle resultData) {
-                if (resultCode == TETHER_ERROR_NO_ERROR) {
-                    callback.onTetheringStarted();
+            public void execute(Runnable command) {
+                if (handler == null) {
+                    command.run();
                 } else {
-                    callback.onTetheringFailed();
+                    handler.post(command);
                 }
             }
         };
 
-        getTetheringManager().startTethering(type, wrappedCallback, showProvisioningUi);
+        final StartTetheringCallback tetheringCallback = new StartTetheringCallback() {
+            @Override
+            public void onTetheringStarted() {
+                callback.onTetheringStarted();
+            }
+
+            @Override
+            public void onTetheringFailed(final int resultCode) {
+                callback.onTetheringFailed();
+            }
+        };
+
+        final TetheringRequest request = new TetheringRequest.Builder(type)
+                .setSilentProvisioning(!showProvisioningUi).build();
+
+        getTetheringManager().startTethering(request, executor, tetheringCallback);
     }
 
     /**
@@ -2602,7 +2630,7 @@
      * Callback for use with {@link registerTetheringEventCallback} to find out tethering
      * upstream status.
      *
-     * @deprecated Use {@line TetheringManager#OnTetheringEventCallback} instead.
+     * @deprecated Use {@link TetheringManager#OnTetheringEventCallback} instead.
      * @hide
      */
     @SystemApi
@@ -2632,7 +2660,7 @@
      * @param executor the executor on which callback will be invoked.
      * @param callback the callback to be called when tethering has change events.
      *
-     * @deprecated Use {@line TetheringManager#registerTetheringEventCallback} instead.
+     * @deprecated Use {@link TetheringManager#registerTetheringEventCallback} instead.
      * @hide
      */
     @SystemApi
@@ -2749,10 +2777,12 @@
      *
      * @param enable a boolean - {@code true} to enable tethering
      * @return error a {@code TETHER_ERROR} value indicating success or failure type
+     * @deprecated Use {@link TetheringManager#startTethering} instead
      *
      * {@hide}
      */
     @UnsupportedAppUsage
+    @Deprecated
     public int setUsbTethering(boolean enable) {
         return getTetheringManager().setUsbTethering(enable);
     }
diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java
index fd015b4..a3899b7 100644
--- a/core/java/android/net/EthernetManager.java
+++ b/core/java/android/net/EthernetManager.java
@@ -16,7 +16,10 @@
 
 package android.net;
 
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Handler;
@@ -24,12 +27,15 @@
 import android.os.RemoteException;
 
 import java.util.ArrayList;
+import java.util.Objects;
 
 /**
  * A class representing the IP configuration of the Ethernet network.
  *
  * @hide
  */
+@SystemApi
+@TestApi
 @SystemService(Context.ETHERNET_SERVICE)
 public class EthernetManager {
     private static final String TAG = "EthernetManager";
@@ -37,7 +43,7 @@
 
     private final Context mContext;
     private final IEthernetManager mService;
-    private final Handler mHandler = new Handler() {
+    private final Handler mHandler = new Handler(ConnectivityThread.getInstanceLooper()) {
         @Override
         public void handleMessage(Message msg) {
             if (msg.what == MSG_AVAILABILITY_CHANGED) {
@@ -60,12 +66,14 @@
 
     /**
      * A listener interface to receive notification on changes in Ethernet.
+     * @hide
      */
     public interface Listener {
         /**
          * Called when Ethernet port's availability is changed.
          * @param iface Ethernet interface name
          * @param isAvailable {@code true} if Ethernet port exists.
+         * @hide
          */
         @UnsupportedAppUsage
         void onAvailabilityChanged(String iface, boolean isAvailable);
@@ -76,6 +84,7 @@
      * Applications will almost always want to use
      * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
      * the standard {@link android.content.Context#ETHERNET_SERVICE Context.ETHERNET_SERVICE}.
+     * @hide
      */
     public EthernetManager(Context context, IEthernetManager service) {
         mContext = context;
@@ -85,6 +94,7 @@
     /**
      * Get Ethernet configuration.
      * @return the Ethernet Configuration, contained in {@link IpConfiguration}.
+     * @hide
      */
     @UnsupportedAppUsage
     public IpConfiguration getConfiguration(String iface) {
@@ -97,6 +107,7 @@
 
     /**
      * Set Ethernet configuration.
+     * @hide
      */
     @UnsupportedAppUsage
     public void setConfiguration(String iface, IpConfiguration config) {
@@ -109,6 +120,7 @@
 
     /**
      * Indicates whether the system currently has one or more Ethernet interfaces.
+     * @hide
      */
     @UnsupportedAppUsage
     public boolean isAvailable() {
@@ -119,6 +131,7 @@
      * Indicates whether the system has given interface.
      *
      * @param iface Ethernet interface name
+     * @hide
      */
     @UnsupportedAppUsage
     public boolean isAvailable(String iface) {
@@ -133,6 +146,7 @@
      * Adds a listener.
      * @param listener A {@link Listener} to add.
      * @throws IllegalArgumentException If the listener is null.
+     * @hide
      */
     @UnsupportedAppUsage
     public void addListener(Listener listener) {
@@ -151,6 +165,7 @@
 
     /**
      * Returns an array of available Ethernet interface names.
+     * @hide
      */
     @UnsupportedAppUsage
     public String[] getAvailableInterfaces() {
@@ -165,6 +180,7 @@
      * Removes a listener.
      * @param listener A {@link Listener} to remove.
      * @throws IllegalArgumentException If the listener is null.
+     * @hide
      */
     @UnsupportedAppUsage
     public void removeListener(Listener listener) {
@@ -180,4 +196,78 @@
             }
         }
     }
+
+    /**
+     * A request for a tethered interface.
+     */
+    public static class TetheredInterfaceRequest {
+        private final IEthernetManager mService;
+        private final ITetheredInterfaceCallback mCb;
+
+        private TetheredInterfaceRequest(@NonNull IEthernetManager service,
+                @NonNull ITetheredInterfaceCallback cb) {
+            this.mService = service;
+            this.mCb = cb;
+        }
+
+        /**
+         * Release the request, causing the interface to revert back from tethering mode if there
+         * is no other requestor.
+         */
+        public void release() {
+            try {
+                mService.releaseTetheredInterface(mCb);
+            } catch (RemoteException e) {
+                e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
+     * Callback for {@link #requestTetheredInterface(TetheredInterfaceCallback)}.
+     */
+    public interface TetheredInterfaceCallback {
+        /**
+         * Called when the tethered interface is available.
+         * @param iface The name of the interface.
+         */
+        void onAvailable(@NonNull String iface);
+
+        /**
+         * Called when the tethered interface is now unavailable.
+         */
+        void onUnavailable();
+    }
+
+    /**
+     * Request a tethered interface in tethering mode.
+     *
+     * <p>When this method is called and there is at least one ethernet interface available, the
+     * system will designate one to act as a tethered interface. If there is already a tethered
+     * interface, the existing interface will be used.
+     * @param callback A callback to be called once the request has been fulfilled.
+     */
+    @NonNull
+    public TetheredInterfaceRequest requestTetheredInterface(
+            @NonNull TetheredInterfaceCallback callback) {
+        Objects.requireNonNull(callback, "Callback must be non-null");
+        final ITetheredInterfaceCallback cbInternal = new ITetheredInterfaceCallback.Stub() {
+            @Override
+            public void onAvailable(String iface) {
+                callback.onAvailable(iface);
+            }
+
+            @Override
+            public void onUnavailable() {
+                callback.onUnavailable();
+            }
+        };
+
+        try {
+            mService.requestTetheredInterface(cbInternal);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+        return new TetheredInterfaceRequest(mService, cbInternal);
+    }
 }
diff --git a/core/java/android/net/IConnectivityDiagnosticsCallback.aidl b/core/java/android/net/IConnectivityDiagnosticsCallback.aidl
new file mode 100644
index 0000000..3a161bf
--- /dev/null
+++ b/core/java/android/net/IConnectivityDiagnosticsCallback.aidl
@@ -0,0 +1,28 @@
+/**
+ *
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.net.ConnectivityDiagnosticsManager;
+import android.net.Network;
+
+/** @hide */
+oneway interface IConnectivityDiagnosticsCallback {
+    void onConnectivityReport(in ConnectivityDiagnosticsManager.ConnectivityReport report);
+    void onDataStallSuspected(in ConnectivityDiagnosticsManager.DataStallReport report);
+    void onNetworkConnectivityReported(in Network n, boolean hasConnectivity);
+}
\ No newline at end of file
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 186196bd..3e9e7fa 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -18,6 +18,7 @@
 
 import android.app.PendingIntent;
 import android.net.ConnectionInfo;
+import android.net.IConnectivityDiagnosticsCallback;
 import android.net.LinkProperties;
 import android.net.Network;
 import android.net.NetworkAgentConfig;
@@ -211,5 +212,9 @@
     boolean isCallerCurrentAlwaysOnVpnApp();
     boolean isCallerCurrentAlwaysOnVpnLockdownApp();
 
+    void registerConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback,
+            in NetworkRequest request);
+    void unregisterConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback);
+
     IBinder startOrGetTestNetworkService();
 }
diff --git a/core/java/android/net/IEthernetManager.aidl b/core/java/android/net/IEthernetManager.aidl
index 94960b5..ccc6e35 100644
--- a/core/java/android/net/IEthernetManager.aidl
+++ b/core/java/android/net/IEthernetManager.aidl
@@ -18,6 +18,7 @@
 
 import android.net.IpConfiguration;
 import android.net.IEthernetServiceListener;
+import android.net.ITetheredInterfaceCallback;
 
 /**
  * Interface that answers queries about, and allows changing
@@ -32,4 +33,6 @@
     boolean isAvailable(String iface);
     void addListener(in IEthernetServiceListener listener);
     void removeListener(in IEthernetServiceListener listener);
+    void requestTetheredInterface(in ITetheredInterfaceCallback callback);
+    void releaseTetheredInterface(in ITetheredInterfaceCallback callback);
 }
diff --git a/core/java/android/os/StatsLogEventWrapper.aidl b/core/java/android/net/ITetheredInterfaceCallback.aidl
similarity index 75%
rename from core/java/android/os/StatsLogEventWrapper.aidl
rename to core/java/android/net/ITetheredInterfaceCallback.aidl
index 766343e..e3d0759 100644
--- a/core/java/android/os/StatsLogEventWrapper.aidl
+++ b/core/java/android/net/ITetheredInterfaceCallback.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,10 @@
  * limitations under the License.
  */
 
-package android.os;
+package android.net;
 
 /** @hide */
-parcelable StatsLogEventWrapper cpp_header "android/os/StatsLogEventWrapper.h";
\ No newline at end of file
+interface ITetheredInterfaceCallback {
+    void onAvailable(in String iface);
+    void onUnavailable();
+}
\ No newline at end of file
diff --git a/core/java/android/net/Ikev2VpnProfile.java b/core/java/android/net/Ikev2VpnProfile.java
new file mode 100644
index 0000000..42b4da1
--- /dev/null
+++ b/core/java/android/net/Ikev2VpnProfile.java
@@ -0,0 +1,728 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import static android.net.PlatformVpnProfile.TYPE_IKEV2_IPSEC_PSK;
+import static android.net.PlatformVpnProfile.TYPE_IKEV2_IPSEC_RSA;
+import static android.net.PlatformVpnProfile.TYPE_IKEV2_IPSEC_USER_PASS;
+
+import static com.android.internal.annotations.VisibleForTesting.Visibility;
+import static com.android.internal.util.Preconditions.checkStringNotEmpty;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.security.Credentials;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.net.VpnProfile;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * The Ikev2VpnProfile is a configuration for the platform setup of IKEv2/IPsec VPNs.
+ *
+ * <p>Together with VpnManager, this allows apps to provision IKEv2/IPsec VPNs that do not require
+ * the VPN app to constantly run in the background.
+ *
+ * @see VpnManager
+ * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3.2">RFC 7296 - Internet Key
+ *     Exchange, Version 2 (IKEv2)</a>
+ */
+public final class Ikev2VpnProfile extends PlatformVpnProfile {
+    private static final String MISSING_PARAM_MSG_TMPL = "Required parameter was not provided: %s";
+    private static final String EMPTY_CERT = "";
+
+    @NonNull private final String mServerAddr;
+    @NonNull private final String mUserIdentity;
+
+    // PSK authentication
+    @Nullable private final byte[] mPresharedKey;
+
+    // Username/Password, RSA authentication
+    @Nullable private final X509Certificate mServerRootCaCert;
+
+    // Username/Password authentication
+    @Nullable private final String mUsername;
+    @Nullable private final String mPassword;
+
+    // RSA Certificate authentication
+    @Nullable private final PrivateKey mRsaPrivateKey;
+    @Nullable private final X509Certificate mUserCert;
+
+    @Nullable private final ProxyInfo mProxyInfo;
+    @NonNull private final List<String> mAllowedAlgorithms;
+    private final boolean mIsBypassable; // Defaults in builder
+    private final boolean mIsMetered; // Defaults in builder
+    private final int mMaxMtu; // Defaults in builder
+
+    private Ikev2VpnProfile(
+            int type,
+            @NonNull String serverAddr,
+            @NonNull String userIdentity,
+            @Nullable byte[] presharedKey,
+            @Nullable X509Certificate serverRootCaCert,
+            @Nullable String username,
+            @Nullable String password,
+            @Nullable PrivateKey rsaPrivateKey,
+            @Nullable X509Certificate userCert,
+            @Nullable ProxyInfo proxyInfo,
+            @NonNull List<String> allowedAlgorithms,
+            boolean isBypassable,
+            boolean isMetered,
+            int maxMtu) {
+        super(type);
+
+        checkNotNull(serverAddr, MISSING_PARAM_MSG_TMPL, "Server address");
+        checkNotNull(userIdentity, MISSING_PARAM_MSG_TMPL, "User Identity");
+        checkNotNull(allowedAlgorithms, MISSING_PARAM_MSG_TMPL, "Allowed Algorithms");
+
+        mServerAddr = serverAddr;
+        mUserIdentity = userIdentity;
+        mPresharedKey =
+                presharedKey == null ? null : Arrays.copyOf(presharedKey, presharedKey.length);
+        mServerRootCaCert = serverRootCaCert;
+        mUsername = username;
+        mPassword = password;
+        mRsaPrivateKey = rsaPrivateKey;
+        mUserCert = userCert;
+        mProxyInfo = new ProxyInfo(proxyInfo);
+
+        // UnmodifiableList doesn't make a defensive copy by default.
+        mAllowedAlgorithms = Collections.unmodifiableList(new ArrayList<>(allowedAlgorithms));
+
+        mIsBypassable = isBypassable;
+        mIsMetered = isMetered;
+        mMaxMtu = maxMtu;
+
+        validate();
+    }
+
+    private void validate() {
+        // Server Address not validated except to check an address was provided. This allows for
+        // dual-stack servers and hostname based addresses.
+        checkStringNotEmpty(mServerAddr, MISSING_PARAM_MSG_TMPL, "Server Address");
+        checkStringNotEmpty(mUserIdentity, MISSING_PARAM_MSG_TMPL, "User Identity");
+
+        // IPv6 MTU is greater; since profiles may be started by the system on IPv4 and IPv6
+        // networks, the VPN must provide a link fulfilling the stricter of the two conditions
+        // (at least that of the IPv6 MTU).
+        if (mMaxMtu < LinkProperties.MIN_MTU_V6) {
+            throw new IllegalArgumentException(
+                    "Max MTU must be at least" + LinkProperties.MIN_MTU_V6);
+        }
+
+        switch (mType) {
+            case TYPE_IKEV2_IPSEC_USER_PASS:
+                checkNotNull(mUsername, MISSING_PARAM_MSG_TMPL, "Username");
+                checkNotNull(mPassword, MISSING_PARAM_MSG_TMPL, "Password");
+
+                if (mServerRootCaCert != null) checkCert(mServerRootCaCert);
+
+                break;
+            case TYPE_IKEV2_IPSEC_PSK:
+                checkNotNull(mPresharedKey, MISSING_PARAM_MSG_TMPL, "Preshared Key");
+                break;
+            case TYPE_IKEV2_IPSEC_RSA:
+                checkNotNull(mUserCert, MISSING_PARAM_MSG_TMPL, "User cert");
+                checkNotNull(mRsaPrivateKey, MISSING_PARAM_MSG_TMPL, "RSA Private key");
+
+                checkCert(mUserCert);
+                if (mServerRootCaCert != null) checkCert(mServerRootCaCert);
+
+                break;
+            default:
+                throw new IllegalArgumentException("Invalid auth method set");
+        }
+
+        VpnProfile.validateAllowedAlgorithms(mAllowedAlgorithms);
+    }
+
+    /** Retrieves the server address string. */
+    @NonNull
+    public String getServerAddr() {
+        return mServerAddr;
+    }
+
+    /** Retrieves the user identity. */
+    @NonNull
+    public String getUserIdentity() {
+        return mUserIdentity;
+    }
+
+    /**
+     * Retrieves the pre-shared key.
+     *
+     * <p>May be null if the profile is not using Pre-shared key authentication.
+     */
+    @Nullable
+    public byte[] getPresharedKey() {
+        return mPresharedKey == null ? null : Arrays.copyOf(mPresharedKey, mPresharedKey.length);
+    }
+
+    /**
+     * Retrieves the certificate for the server's root CA.
+     *
+     * <p>May be null if the profile is not using RSA Digital Signature Authentication or
+     * Username/Password authentication
+     */
+    @Nullable
+    public X509Certificate getServerRootCaCert() {
+        return mServerRootCaCert;
+    }
+
+    /**
+     * Retrieves the username.
+     *
+     * <p>May be null if the profile is not using Username/Password authentication
+     */
+    @Nullable
+    public String getUsername() {
+        return mUsername;
+    }
+
+    /**
+     * Retrieves the password.
+     *
+     * <p>May be null if the profile is not using Username/Password authentication
+     */
+    @Nullable
+    public String getPassword() {
+        return mPassword;
+    }
+
+    /**
+     * Retrieves the RSA private key.
+     *
+     * <p>May be null if the profile is not using RSA Digital Signature authentication
+     */
+    @Nullable
+    public PrivateKey getRsaPrivateKey() {
+        return mRsaPrivateKey;
+    }
+
+    /** Retrieves the user certificate, if any was set. */
+    @Nullable
+    public X509Certificate getUserCert() {
+        return mUserCert;
+    }
+
+    /** Retrieves the proxy information if any was set */
+    @Nullable
+    public ProxyInfo getProxyInfo() {
+        return mProxyInfo;
+    }
+
+    /** Returns all the algorithms allowed by this VPN profile. */
+    @NonNull
+    public List<String> getAllowedAlgorithms() {
+        return mAllowedAlgorithms;
+    }
+
+    /** Returns whether or not the VPN profile should be bypassable. */
+    public boolean isBypassable() {
+        return mIsBypassable;
+    }
+
+    /** Returns whether or not the VPN profile should be always considered metered. */
+    public boolean isMetered() {
+        return mIsMetered;
+    }
+
+    /** Retrieves the maximum MTU set for this VPN profile. */
+    public int getMaxMtu() {
+        return mMaxMtu;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(
+                mType,
+                mServerAddr,
+                mUserIdentity,
+                Arrays.hashCode(mPresharedKey),
+                mServerRootCaCert,
+                mUsername,
+                mPassword,
+                mRsaPrivateKey,
+                mUserCert,
+                mProxyInfo,
+                mAllowedAlgorithms,
+                mIsBypassable,
+                mIsMetered,
+                mMaxMtu);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof Ikev2VpnProfile)) {
+            return false;
+        }
+
+        final Ikev2VpnProfile other = (Ikev2VpnProfile) obj;
+        return mType == other.mType
+                && Objects.equals(mServerAddr, other.mServerAddr)
+                && Objects.equals(mUserIdentity, other.mUserIdentity)
+                && Arrays.equals(mPresharedKey, other.mPresharedKey)
+                && Objects.equals(mServerRootCaCert, other.mServerRootCaCert)
+                && Objects.equals(mUsername, other.mUsername)
+                && Objects.equals(mPassword, other.mPassword)
+                && Objects.equals(mRsaPrivateKey, other.mRsaPrivateKey)
+                && Objects.equals(mUserCert, other.mUserCert)
+                && Objects.equals(mProxyInfo, other.mProxyInfo)
+                && Objects.equals(mAllowedAlgorithms, other.mAllowedAlgorithms)
+                && mIsBypassable == other.mIsBypassable
+                && mIsMetered == other.mIsMetered
+                && mMaxMtu == other.mMaxMtu;
+    }
+
+    /**
+     * Builds a VpnProfile instance for internal use, based on the stored IKEv2/IPsec parameters.
+     *
+     * <p>Redundant authentication information (from previous calls to other setAuth* methods) will
+     * be discarded.
+     *
+     * @hide
+     */
+    @NonNull
+    public VpnProfile toVpnProfile() throws IOException, GeneralSecurityException {
+        final VpnProfile profile = new VpnProfile("" /* Key; value unused by IKEv2VpnProfile(s) */);
+        profile.type = mType;
+        profile.server = mServerAddr;
+        profile.ipsecIdentifier = mUserIdentity;
+        profile.proxy = mProxyInfo;
+        profile.setAllowedAlgorithms(mAllowedAlgorithms);
+        profile.isBypassable = mIsBypassable;
+        profile.isMetered = mIsMetered;
+        profile.maxMtu = mMaxMtu;
+        profile.areAuthParamsInline = true;
+        profile.saveLogin = true;
+
+        switch (mType) {
+            case TYPE_IKEV2_IPSEC_USER_PASS:
+                profile.username = mUsername;
+                profile.password = mPassword;
+                profile.ipsecCaCert =
+                        mServerRootCaCert == null ? "" : certificateToPemString(mServerRootCaCert);
+                break;
+            case TYPE_IKEV2_IPSEC_PSK:
+                profile.ipsecSecret = encodeForIpsecSecret(mPresharedKey);
+                break;
+            case TYPE_IKEV2_IPSEC_RSA:
+                profile.ipsecUserCert = certificateToPemString(mUserCert);
+                profile.ipsecSecret = encodeForIpsecSecret(mRsaPrivateKey.getEncoded());
+                profile.ipsecCaCert =
+                        mServerRootCaCert == null ? "" : certificateToPemString(mServerRootCaCert);
+                break;
+            default:
+                throw new IllegalArgumentException("Invalid auth method set");
+        }
+
+        return profile;
+    }
+
+    /**
+     * Constructs a Ikev2VpnProfile from an internal-use VpnProfile instance.
+     *
+     * <p>Redundant authentication information (not related to profile type) will be discarded.
+     *
+     * @hide
+     */
+    @NonNull
+    public static Ikev2VpnProfile fromVpnProfile(@NonNull VpnProfile profile)
+            throws IOException, GeneralSecurityException {
+        final Builder builder = new Builder(profile.server, profile.ipsecIdentifier);
+        builder.setProxy(profile.proxy);
+        builder.setAllowedAlgorithms(profile.getAllowedAlgorithms());
+        builder.setBypassable(profile.isBypassable);
+        builder.setMetered(profile.isMetered);
+        builder.setMaxMtu(profile.maxMtu);
+
+        switch (profile.type) {
+            case TYPE_IKEV2_IPSEC_USER_PASS:
+                builder.setAuthUsernamePassword(
+                        profile.username,
+                        profile.password,
+                        certificateFromPemString(profile.ipsecCaCert));
+                break;
+            case TYPE_IKEV2_IPSEC_PSK:
+                builder.setAuthPsk(decodeFromIpsecSecret(profile.ipsecSecret));
+                break;
+            case TYPE_IKEV2_IPSEC_RSA:
+                final X509Certificate userCert = certificateFromPemString(profile.ipsecUserCert);
+                final PrivateKey key = getPrivateKey(profile.ipsecSecret);
+                final X509Certificate serverRootCa = certificateFromPemString(profile.ipsecCaCert);
+                builder.setAuthDigitalSignature(userCert, key, serverRootCa);
+                break;
+            default:
+                throw new IllegalArgumentException("Invalid auth method set");
+        }
+
+        return builder.build();
+    }
+
+    /**
+     * Converts a X509 Certificate to a PEM-formatted string.
+     *
+     * <p>Must be public due to runtime-package restrictions.
+     *
+     * @hide
+     */
+    @NonNull
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    public static String certificateToPemString(@Nullable X509Certificate cert)
+            throws IOException, CertificateEncodingException {
+        if (cert == null) {
+            return EMPTY_CERT;
+        }
+
+        // Credentials.convertToPem outputs ASCII bytes.
+        return new String(Credentials.convertToPem(cert), StandardCharsets.US_ASCII);
+    }
+
+    /**
+     * Decodes the provided Certificate(s).
+     *
+     * <p>Will use the first one if the certStr encodes more than one certificate.
+     */
+    @Nullable
+    private static X509Certificate certificateFromPemString(@Nullable String certStr)
+            throws CertificateException {
+        if (certStr == null || EMPTY_CERT.equals(certStr)) {
+            return null;
+        }
+
+        try {
+            final List<X509Certificate> certs =
+                    Credentials.convertFromPem(certStr.getBytes(StandardCharsets.US_ASCII));
+            return certs.isEmpty() ? null : certs.get(0);
+        } catch (IOException e) {
+            throw new CertificateException(e);
+        }
+    }
+
+    /** @hide */
+    @NonNull
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    public static String encodeForIpsecSecret(@NonNull byte[] secret) {
+        checkNotNull(secret, MISSING_PARAM_MSG_TMPL, "secret");
+
+        return Base64.getEncoder().encodeToString(secret);
+    }
+
+    @NonNull
+    private static byte[] decodeFromIpsecSecret(@NonNull String encoded) {
+        checkNotNull(encoded, MISSING_PARAM_MSG_TMPL, "encoded");
+
+        return Base64.getDecoder().decode(encoded);
+    }
+
+    @NonNull
+    private static PrivateKey getPrivateKey(@NonNull String keyStr)
+            throws InvalidKeySpecException, NoSuchAlgorithmException {
+        final PKCS8EncodedKeySpec privateKeySpec =
+                new PKCS8EncodedKeySpec(decodeFromIpsecSecret(keyStr));
+        final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+        return keyFactory.generatePrivate(privateKeySpec);
+    }
+
+    private static void checkCert(@NonNull X509Certificate cert) {
+        try {
+            certificateToPemString(cert);
+        } catch (GeneralSecurityException | IOException e) {
+            throw new IllegalArgumentException("Certificate could not be encoded");
+        }
+    }
+
+    private static @NonNull <T> T checkNotNull(
+            final T reference, final String messageTemplate, final Object... messageArgs) {
+        return Objects.requireNonNull(reference, String.format(messageTemplate, messageArgs));
+    }
+
+    /** A incremental builder for IKEv2 VPN profiles */
+    public static final class Builder {
+        private int mType = -1;
+        @NonNull private final String mServerAddr;
+        @NonNull private final String mUserIdentity;
+
+        // PSK authentication
+        @Nullable private byte[] mPresharedKey;
+
+        // Username/Password, RSA authentication
+        @Nullable private X509Certificate mServerRootCaCert;
+
+        // Username/Password authentication
+        @Nullable private String mUsername;
+        @Nullable private String mPassword;
+
+        // RSA Certificate authentication
+        @Nullable private PrivateKey mRsaPrivateKey;
+        @Nullable private X509Certificate mUserCert;
+
+        @Nullable private ProxyInfo mProxyInfo;
+        @NonNull private List<String> mAllowedAlgorithms = new ArrayList<>();
+        private boolean mIsBypassable = false;
+        private boolean mIsMetered = true;
+        private int mMaxMtu = 1360;
+
+        /**
+         * Creates a new builder with the basic parameters of an IKEv2/IPsec VPN.
+         *
+         * @param serverAddr the server that the VPN should connect to
+         * @param identity the identity string to be used for IKEv2 authentication
+         */
+        public Builder(@NonNull String serverAddr, @NonNull String identity) {
+            checkNotNull(serverAddr, MISSING_PARAM_MSG_TMPL, "serverAddr");
+            checkNotNull(identity, MISSING_PARAM_MSG_TMPL, "identity");
+
+            mServerAddr = serverAddr;
+            mUserIdentity = identity;
+        }
+
+        private void resetAuthParams() {
+            mPresharedKey = null;
+            mServerRootCaCert = null;
+            mUsername = null;
+            mPassword = null;
+            mRsaPrivateKey = null;
+            mUserCert = null;
+        }
+
+        /**
+         * Set the IKEv2 authentication to use the provided username/password.
+         *
+         * <p>Setting this will configure IKEv2 authentication using EAP-MSCHAPv2. Only one
+         * authentication method may be set. This method will overwrite any previously set
+         * authentication method.
+         *
+         * @param user the username to be used for EAP-MSCHAPv2 authentication
+         * @param pass the password to be used for EAP-MSCHAPv2 authentication
+         * @param serverRootCa the root certificate to be used for verifying the identity of the
+         *     server
+         * @return this {@link Builder} object to facilitate chaining of method calls
+         * @throws IllegalArgumentException if any of the certificates were invalid or of an
+         *     unrecognized format
+         */
+        @NonNull
+        public Builder setAuthUsernamePassword(
+                @NonNull String user,
+                @NonNull String pass,
+                @Nullable X509Certificate serverRootCa) {
+            checkNotNull(user, MISSING_PARAM_MSG_TMPL, "user");
+            checkNotNull(pass, MISSING_PARAM_MSG_TMPL, "pass");
+
+            // Test to make sure all auth params can be encoded safely.
+            if (serverRootCa != null) checkCert(serverRootCa);
+
+            resetAuthParams();
+            mUsername = user;
+            mPassword = pass;
+            mServerRootCaCert = serverRootCa;
+            mType = VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS;
+            return this;
+        }
+
+        /**
+         * Set the IKEv2 authentication to use Digital Signature Authentication with the given key.
+         *
+         * <p>Setting this will configure IKEv2 authentication using a Digital Signature scheme.
+         * Only one authentication method may be set. This method will overwrite any previously set
+         * authentication method.
+         *
+         * @param userCert the username to be used for RSA Digital signiture authentication
+         * @param key the PrivateKey instance associated with the user ceritificate, used for
+         *     constructing the signature
+         * @param serverRootCa the root certificate to be used for verifying the identity of the
+         *     server
+         * @return this {@link Builder} object to facilitate chaining of method calls
+         * @throws IllegalArgumentException if any of the certificates were invalid or of an
+         *     unrecognized format
+         */
+        @NonNull
+        public Builder setAuthDigitalSignature(
+                @NonNull X509Certificate userCert,
+                @NonNull PrivateKey key,
+                @Nullable X509Certificate serverRootCa) {
+            checkNotNull(userCert, MISSING_PARAM_MSG_TMPL, "userCert");
+            checkNotNull(key, MISSING_PARAM_MSG_TMPL, "key");
+
+            // Test to make sure all auth params can be encoded safely.
+            checkCert(userCert);
+            if (serverRootCa != null) checkCert(serverRootCa);
+
+            resetAuthParams();
+            mUserCert = userCert;
+            mRsaPrivateKey = key;
+            mServerRootCaCert = serverRootCa;
+            mType = VpnProfile.TYPE_IKEV2_IPSEC_RSA;
+            return this;
+        }
+
+        /**
+         * Set the IKEv2 authentication to use Preshared keys.
+         *
+         * <p>Setting this will configure IKEv2 authentication using a Preshared Key. Only one
+         * authentication method may be set. This method will overwrite any previously set
+         * authentication method.
+         *
+         * @param psk the key to be used for Pre-Shared Key authentication
+         * @return this {@link Builder} object to facilitate chaining of method calls
+         */
+        @NonNull
+        public Builder setAuthPsk(@NonNull byte[] psk) {
+            checkNotNull(psk, MISSING_PARAM_MSG_TMPL, "psk");
+
+            resetAuthParams();
+            mPresharedKey = psk;
+            mType = VpnProfile.TYPE_IKEV2_IPSEC_PSK;
+            return this;
+        }
+
+        /**
+         * Sets whether apps can bypass this VPN connection.
+         *
+         * <p>By default, all traffic from apps are forwarded through the VPN interface and it is
+         * not possible for unprivileged apps to side-step the VPN. If a VPN is set to bypassable,
+         * apps may use methods such as {@link Network#getSocketFactory} or {@link
+         * Network#openConnection} to instead send/receive directly over the underlying network or
+         * any other network they have permissions for.
+         *
+         * @param isBypassable Whether or not the VPN should be considered bypassable. Defaults to
+         *     {@code false}.
+         * @return this {@link Builder} object to facilitate chaining of method calls
+         */
+        @NonNull
+        public Builder setBypassable(boolean isBypassable) {
+            mIsBypassable = isBypassable;
+            return this;
+        }
+
+        /**
+         * Sets a proxy for the VPN network.
+         *
+         * <p>Note that this proxy is only a recommendation and it may be ignored by apps.
+         *
+         * @param proxy the ProxyInfo to be set for the VPN network
+         * @return this {@link Builder} object to facilitate chaining of method calls
+         */
+        @NonNull
+        public Builder setProxy(@Nullable ProxyInfo proxy) {
+            mProxyInfo = proxy;
+            return this;
+        }
+
+        /**
+         * Set the upper bound of the maximum transmission unit (MTU) of the VPN interface.
+         *
+         * <p>If it is not set, a safe value will be used. Additionally, the actual link MTU will be
+         * dynamically calculated/updated based on the underlying link's mtu.
+         *
+         * @param mtu the MTU (in bytes) of the VPN interface
+         * @return this {@link Builder} object to facilitate chaining of method calls
+         * @throws IllegalArgumentException if the value is not at least the minimum IPv6 MTU (1280)
+         */
+        @NonNull
+        public Builder setMaxMtu(int mtu) {
+            // IPv6 MTU is greater; since profiles may be started by the system on IPv4 and IPv6
+            // networks, the VPN must provide a link fulfilling the stricter of the two conditions
+            // (at least that of the IPv6 MTU).
+            if (mtu < LinkProperties.MIN_MTU_V6) {
+                throw new IllegalArgumentException(
+                        "Max MTU must be at least " + LinkProperties.MIN_MTU_V6);
+            }
+            mMaxMtu = mtu;
+            return this;
+        }
+
+        /**
+         * Marks the VPN network as metered.
+         *
+         * <p>A VPN network is classified as metered when the user is sensitive to heavy data usage
+         * due to monetary costs and/or data limitations. In such cases, you should set this to
+         * {@code true} so that apps on the system can avoid doing large data transfers. Otherwise,
+         * set this to {@code false}. Doing so would cause VPN network to inherit its meteredness
+         * from the underlying network.
+         *
+         * @param isMetered {@code true} if the VPN network should be treated as metered regardless
+         *     of underlying network meteredness. Defaults to {@code true}.
+         * @return this {@link Builder} object to facilitate chaining of method calls
+         * @see NetworkCapabilities.NET_CAPABILITY_NOT_METERED
+         */
+        @NonNull
+        public Builder setMetered(boolean isMetered) {
+            mIsMetered = isMetered;
+            return this;
+        }
+
+        /**
+         * Sets the allowable set of IPsec algorithms
+         *
+         * <p>A list of allowed IPsec algorithms as defined in {@link IpSecAlgorithm}
+         *
+         * @param algorithmNames the list of supported IPsec algorithms
+         * @return this {@link Builder} object to facilitate chaining of method calls
+         * @see IpSecAlgorithm
+         */
+        @NonNull
+        public Builder setAllowedAlgorithms(@NonNull List<String> algorithmNames) {
+            checkNotNull(algorithmNames, MISSING_PARAM_MSG_TMPL, "algorithmNames");
+            VpnProfile.validateAllowedAlgorithms(algorithmNames);
+
+            mAllowedAlgorithms = algorithmNames;
+            return this;
+        }
+
+        /**
+         * Validates, builds and provisions the VpnProfile.
+         *
+         * @throws IllegalArgumentException if any of the required keys or values were invalid
+         */
+        @NonNull
+        public Ikev2VpnProfile build() {
+            return new Ikev2VpnProfile(
+                    mType,
+                    mServerAddr,
+                    mUserIdentity,
+                    mPresharedKey,
+                    mServerRootCaCert,
+                    mUsername,
+                    mPassword,
+                    mRsaPrivateKey,
+                    mUserCert,
+                    mProxyInfo,
+                    mAllowedAlgorithms,
+                    mIsBypassable,
+                    mIsMetered,
+                    mMaxMtu);
+        }
+    }
+}
diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java
index bf8b38f..a9d7f17 100644
--- a/core/java/android/net/LinkAddress.java
+++ b/core/java/android/net/LinkAddress.java
@@ -19,6 +19,7 @@
 import static android.system.OsConstants.IFA_F_DADFAILED;
 import static android.system.OsConstants.IFA_F_DEPRECATED;
 import static android.system.OsConstants.IFA_F_OPTIMISTIC;
+import static android.system.OsConstants.IFA_F_PERMANENT;
 import static android.system.OsConstants.IFA_F_TENTATIVE;
 import static android.system.OsConstants.RT_SCOPE_HOST;
 import static android.system.OsConstants.RT_SCOPE_LINK;
@@ -34,6 +35,7 @@
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.SystemClock;
 import android.util.Pair;
 
 import java.net.Inet4Address;
@@ -41,6 +43,7 @@
 import java.net.InetAddress;
 import java.net.InterfaceAddress;
 import java.net.UnknownHostException;
+import java.util.Objects;
 
 /**
  * Identifies an IP address on a network link.
@@ -58,6 +61,21 @@
  * </ul>
  */
 public class LinkAddress implements Parcelable {
+
+    /**
+     * Indicates the deprecation or expiration time is unknown
+     * @hide
+     */
+    @SystemApi
+    public static final long LIFETIME_UNKNOWN = -1;
+
+    /**
+     * Indicates this address is permanent.
+     * @hide
+     */
+    @SystemApi
+    public static final long LIFETIME_PERMANENT = Long.MAX_VALUE;
+
     /**
      * IPv4 or IPv6 address.
      */
@@ -71,7 +89,9 @@
     private int prefixLength;
 
     /**
-     * Address flags. A bitmask of IFA_F_* values.
+     * Address flags. A bitmask of {@code IFA_F_*} values. Note that {@link #getFlags()} may not
+     * return these exact values. For example, it may set or clear the {@code IFA_F_DEPRECATED}
+     * flag depending on the current preferred lifetime.
      */
     private int flags;
 
@@ -81,6 +101,23 @@
     private int scope;
 
     /**
+     * The time, as reported by {@link SystemClock#elapsedRealtime}, when this LinkAddress will be
+     * or was deprecated. At the time existing connections can still use this address until it
+     * expires, but new connections should use the new address. {@link #LIFETIME_UNKNOWN} indicates
+     * this information is not available. {@link #LIFETIME_PERMANENT} indicates this
+     * {@link LinkAddress} will never be deprecated.
+     */
+    private long deprecationTime;
+
+    /**
+     * The time, as reported by {@link SystemClock#elapsedRealtime}, when this {@link LinkAddress}
+     * will expire and be removed from the interface. {@link #LIFETIME_UNKNOWN} indicates this
+     * information is not available. {@link #LIFETIME_PERMANENT} indicates this {@link LinkAddress}
+     * will never expire.
+     */
+    private long expirationTime;
+
+    /**
      * Utility function to determines the scope of a unicast address. Per RFC 4291 section 2.5 and
      * RFC 6724 section 3.2.
      * @hide
@@ -152,7 +189,8 @@
     /**
      * Utility function for the constructors.
      */
-    private void init(InetAddress address, int prefixLength, int flags, int scope) {
+    private void init(InetAddress address, int prefixLength, int flags, int scope,
+                      long deprecationTime, long expirationTime) {
         if (address == null ||
                 address.isMulticastAddress() ||
                 prefixLength < 0 ||
@@ -161,15 +199,42 @@
             throw new IllegalArgumentException("Bad LinkAddress params " + address +
                     "/" + prefixLength);
         }
+
+        // deprecation time and expiration time must be both provided, or neither.
+        if ((deprecationTime == LIFETIME_UNKNOWN) != (expirationTime == LIFETIME_UNKNOWN)) {
+            throw new IllegalArgumentException(
+                    "Must not specify only one of deprecation time and expiration time");
+        }
+
+        // deprecation time needs to be a positive value.
+        if (deprecationTime != LIFETIME_UNKNOWN && deprecationTime < 0) {
+            throw new IllegalArgumentException("invalid deprecation time " + deprecationTime);
+        }
+
+        // expiration time needs to be a positive value.
+        if (expirationTime != LIFETIME_UNKNOWN && expirationTime < 0) {
+            throw new IllegalArgumentException("invalid expiration time " + expirationTime);
+        }
+
+        // expiration time can't be earlier than deprecation time
+        if (deprecationTime != LIFETIME_UNKNOWN && expirationTime != LIFETIME_UNKNOWN
+                && expirationTime < deprecationTime) {
+            throw new IllegalArgumentException("expiration earlier than deprecation ("
+                    + deprecationTime + ", " + expirationTime + ")");
+        }
+
         this.address = address;
         this.prefixLength = prefixLength;
         this.flags = flags;
         this.scope = scope;
+        this.deprecationTime = deprecationTime;
+        this.expirationTime = expirationTime;
     }
 
     /**
      * Constructs a new {@code LinkAddress} from an {@code InetAddress} and prefix length, with
      * the specified flags and scope. Flags and scope are not checked for validity.
+     *
      * @param address The IP address.
      * @param prefixLength The prefix length. Must be &gt;= 0 and &lt;= (32 or 128) (IPv4 or IPv6).
      * @param flags A bitmask of {@code IFA_F_*} values representing properties of the address.
@@ -181,7 +246,39 @@
     @TestApi
     public LinkAddress(@NonNull InetAddress address, @IntRange(from = 0, to = 128) int prefixLength,
             int flags, int scope) {
-        init(address, prefixLength, flags, scope);
+        init(address, prefixLength, flags, scope, LIFETIME_UNKNOWN, LIFETIME_UNKNOWN);
+    }
+
+    /**
+     * Constructs a new {@code LinkAddress} from an {@code InetAddress}, prefix length, with
+     * the specified flags, scope, deprecation time, and expiration time. Flags and scope are not
+     * checked for validity. The value of the {@code IFA_F_DEPRECATED} and {@code IFA_F_PERMANENT}
+     * flag will be adjusted based on the passed-in lifetimes.
+     *
+     * @param address The IP address.
+     * @param prefixLength The prefix length. Must be &gt;= 0 and &lt;= (32 or 128) (IPv4 or IPv6).
+     * @param flags A bitmask of {@code IFA_F_*} values representing properties of the address.
+     * @param scope An integer defining the scope in which the address is unique (e.g.,
+     *              {@link OsConstants#RT_SCOPE_LINK} or {@link OsConstants#RT_SCOPE_SITE}).
+     * @param deprecationTime The time, as reported by {@link SystemClock#elapsedRealtime}, when
+     *                        this {@link LinkAddress} will be or was deprecated. At the time
+     *                        existing connections can still use this address until it expires, but
+     *                        new connections should use the new address. {@link #LIFETIME_UNKNOWN}
+     *                        indicates this information is not available.
+     *                        {@link #LIFETIME_PERMANENT} indicates this {@link LinkAddress} will
+     *                        never be deprecated.
+     * @param expirationTime The time, as reported by {@link SystemClock#elapsedRealtime}, when this
+     *                       {@link LinkAddress} will expire and be removed from the interface.
+     *                       {@link #LIFETIME_UNKNOWN} indicates this information is not available.
+     *                       {@link #LIFETIME_PERMANENT} indicates this {@link LinkAddress} will
+     *                       never expire.
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public LinkAddress(@NonNull InetAddress address, @IntRange(from = 0, to = 128) int prefixLength,
+                       int flags, int scope, long deprecationTime, long expirationTime) {
+        init(address, prefixLength, flags, scope, deprecationTime, expirationTime);
     }
 
     /**
@@ -237,7 +334,7 @@
         // This may throw an IllegalArgumentException; catching it is the caller's responsibility.
         // TODO: consider rejecting mapped IPv4 addresses such as "::ffff:192.0.2.5/24".
         Pair<InetAddress, Integer> ipAndMask = NetworkUtils.parseIpAndMask(address);
-        init(ipAndMask.first, ipAndMask.second, flags, scope);
+        init(ipAndMask.first, ipAndMask.second, flags, scope, LIFETIME_UNKNOWN, LIFETIME_UNKNOWN);
     }
 
     /**
@@ -265,10 +362,12 @@
             return false;
         }
         LinkAddress linkAddress = (LinkAddress) obj;
-        return this.address.equals(linkAddress.address) &&
-            this.prefixLength == linkAddress.prefixLength &&
-            this.flags == linkAddress.flags &&
-            this.scope == linkAddress.scope;
+        return this.address.equals(linkAddress.address)
+                && this.prefixLength == linkAddress.prefixLength
+                && this.flags == linkAddress.flags
+                && this.scope == linkAddress.scope
+                && this.deprecationTime == linkAddress.deprecationTime
+                && this.expirationTime == linkAddress.expirationTime;
     }
 
     /**
@@ -276,7 +375,7 @@
      */
     @Override
     public int hashCode() {
-        return address.hashCode() + 11 * prefixLength + 19 * flags + 43 * scope;
+        return Objects.hash(address, prefixLength, flags, scope, deprecationTime, expirationTime);
     }
 
     /**
@@ -329,6 +428,25 @@
      * Returns the flags of this {@code LinkAddress}.
      */
     public int getFlags() {
+        int flags = this.flags;
+        if (deprecationTime != LIFETIME_UNKNOWN) {
+            if (SystemClock.elapsedRealtime() >= deprecationTime) {
+                flags |= IFA_F_DEPRECATED;
+            } else {
+                // If deprecation time is in the future, or permanent.
+                flags &= ~IFA_F_DEPRECATED;
+            }
+        }
+
+        if (expirationTime == LIFETIME_PERMANENT) {
+            flags |= IFA_F_PERMANENT;
+        } else if (expirationTime != LIFETIME_UNKNOWN) {
+            // If we know this address expired or will expire in the future, then this address
+            // should not be permanent.
+            flags &= ~IFA_F_PERMANENT;
+        }
+
+        // Do no touch the original flags. Return the adjusted flags here.
         return flags;
     }
 
@@ -340,7 +458,42 @@
     }
 
     /**
-     * Returns true if this {@code LinkAddress} is global scope and preferred.
+     * Get the deprecation time, as reported by {@link SystemClock#elapsedRealtime}, when this
+     * {@link LinkAddress} will be or was deprecated. At the time existing connections can still use
+     * this address until it expires, but new connections should use the new address.
+     *
+     * @return The deprecation time in milliseconds. {@link #LIFETIME_UNKNOWN} indicates this
+     * information is not available. {@link #LIFETIME_PERMANENT} indicates this {@link LinkAddress}
+     * will never be deprecated.
+     *
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public long getDeprecationTime() {
+        return deprecationTime;
+    }
+
+    /**
+     * Get the expiration time, as reported by {@link SystemClock#elapsedRealtime}, when this
+     * {@link LinkAddress} will expire and be removed from the interface.
+     *
+     * @return The expiration time in milliseconds. {@link #LIFETIME_UNKNOWN} indicates this
+     * information is not available. {@link #LIFETIME_PERMANENT} indicates this {@link LinkAddress}
+     * will never expire.
+     *
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public long getExpirationTime() {
+        return expirationTime;
+    }
+
+    /**
+     * Returns true if this {@code LinkAddress} is global scope and preferred (i.e., not currently
+     * deprecated).
+     *
      * @hide
      */
     @TestApi
@@ -352,6 +505,7 @@
          * state has cleared either DAD has succeeded or failed, and both
          * flags are cleared regardless).
          */
+        int flags = getFlags();
         return (scope == RT_SCOPE_UNIVERSE
                 && !isIpv6ULA()
                 && (flags & (IFA_F_DADFAILED | IFA_F_DEPRECATED)) == 0L
@@ -373,6 +527,8 @@
         dest.writeInt(prefixLength);
         dest.writeInt(this.flags);
         dest.writeInt(scope);
+        dest.writeLong(deprecationTime);
+        dest.writeLong(expirationTime);
     }
 
     /**
@@ -392,7 +548,10 @@
                 int prefixLength = in.readInt();
                 int flags = in.readInt();
                 int scope = in.readInt();
-                return new LinkAddress(address, prefixLength, flags, scope);
+                long deprecationTime = in.readLong();
+                long expirationTime = in.readLong();
+                return new LinkAddress(address, prefixLength, flags, scope, deprecationTime,
+                        expirationTime);
             }
 
             public LinkAddress[] newArray(int size) {
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index e83f5e4..732ceb5 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -82,7 +82,8 @@
     private final transient boolean mParcelSensitiveFields;
 
     private static final int MIN_MTU    = 68;
-    private static final int MIN_MTU_V6 = 1280;
+    /* package-visibility - Used in other files (such as Ikev2VpnProfile) as minimum iface MTU. */
+    static final int MIN_MTU_V6 = 1280;
     private static final int MAX_MTU    = 10000;
 
     private static final int INET6_ADDR_LENGTH = 16;
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 738070b..4f4e27b 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -26,6 +26,7 @@
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.Process;
 import android.util.ArraySet;
 import android.util.proto.ProtoOutputStream;
 
@@ -35,6 +36,9 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 import java.util.Objects;
 import java.util.Set;
 import java.util.StringJoiner;
@@ -55,7 +59,6 @@
  */
 public final class NetworkCapabilities implements Parcelable {
     private static final String TAG = "NetworkCapabilities";
-    private static final int INVALID_UID = -1;
 
     // Set to true when private DNS is broken.
     private boolean mPrivateDnsBroken;
@@ -82,7 +85,8 @@
         mTransportInfo = null;
         mSignalStrength = SIGNAL_STRENGTH_UNSPECIFIED;
         mUids = null;
-        mEstablishingVpnAppUid = INVALID_UID;
+        mAdministratorUids.clear();
+        mOwnerUid = Process.INVALID_UID;
         mSSID = null;
         mPrivateDnsBroken = false;
     }
@@ -100,7 +104,8 @@
         mTransportInfo = nc.mTransportInfo;
         mSignalStrength = nc.mSignalStrength;
         setUids(nc.mUids); // Will make the defensive copy
-        mEstablishingVpnAppUid = nc.mEstablishingVpnAppUid;
+        setAdministratorUids(nc.mAdministratorUids);
+        mOwnerUid = nc.mOwnerUid;
         mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities;
         mSSID = nc.mSSID;
         mPrivateDnsBroken = nc.mPrivateDnsBroken;
@@ -805,31 +810,76 @@
     }
 
     /**
-     * UID of the app that manages this network, or INVALID_UID if none/unknown.
+     * UID of the app that owns this network, or INVALID_UID if none/unknown.
      *
-     * This field keeps track of the UID of the app that created this network and is in charge
-     * of managing it. In the practice, it is used to store the UID of VPN apps so it is named
-     * accordingly, but it may be renamed if other mechanisms are offered for third party apps
-     * to create networks.
-     *
-     * Because this field is only used in the services side (and to avoid apps being able to
-     * set this to whatever they want), this field is not parcelled and will not be conserved
-     * across the IPC boundary.
-     * @hide
+     * <p>This field keeps track of the UID of the app that created this network and is in charge of
+     * its lifecycle. This could be the UID of apps such as the Wifi network suggestor, the running
+     * VPN, or Carrier Service app managing a cellular data connection.
      */
-    private int mEstablishingVpnAppUid = INVALID_UID;
+    private int mOwnerUid = Process.INVALID_UID;
 
     /**
-     * Set the UID of the managing app.
-     * @hide
+     * Set the UID of the owner app.
      */
-    public void setEstablishingVpnAppUid(final int uid) {
-        mEstablishingVpnAppUid = uid;
+    public void setOwnerUid(final int uid) {
+        mOwnerUid = uid;
     }
 
-    /** @hide */
-    public int getEstablishingVpnAppUid() {
-        return mEstablishingVpnAppUid;
+    /**
+     * Retrieves the UID of the owner app.
+     */
+    public int getOwnerUid() {
+        return mOwnerUid;
+    }
+
+    /**
+     * UIDs of packages that are administrators of this network, or empty if none.
+     *
+     * <p>This field tracks the UIDs of packages that have permission to manage this network.
+     *
+     * <p>Network owners will also be listed as administrators.
+     *
+     * <p>For NetworkCapability instances being sent from the System Server, this value MUST be
+     * empty unless the destination is 1) the System Server, or 2) Telephony. In either case, the
+     * receiving entity must have the ACCESS_FINE_LOCATION permission and target R+.
+     */
+    private final List<Integer> mAdministratorUids = new ArrayList<>();
+
+    /**
+     * Sets the list of UIDs that are administrators of this network.
+     *
+     * <p>UIDs included in administratorUids gain administrator privileges over this Network.
+     * Examples of UIDs that should be included in administratorUids are:
+     * <ul>
+     *     <li>Carrier apps with privileges for the relevant subscription
+     *     <li>Active VPN apps
+     *     <li>Other application groups with a particular Network-related role
+     * </ul>
+     *
+     * <p>In general, user-supplied networks (such as WiFi networks) do not have an administrator.
+     *
+     * <p>An app is granted owner privileges over Networks that it supplies. Owner privileges
+     * implicitly include administrator privileges.
+     *
+     * @param administratorUids the UIDs to be set as administrators of this Network.
+     * @hide
+     */
+    @SystemApi
+    public void setAdministratorUids(@NonNull final List<Integer> administratorUids) {
+        mAdministratorUids.clear();
+        mAdministratorUids.addAll(administratorUids);
+    }
+
+    /**
+     * Retrieves the list of UIDs that are administrators of this Network.
+     *
+     * @return the List of UIDs that are administrators of this Network
+     * @hide
+     */
+    @NonNull
+    @SystemApi
+    public List<Integer> getAdministratorUids() {
+        return Collections.unmodifiableList(mAdministratorUids);
     }
 
     /**
@@ -1102,7 +1152,7 @@
      * member is null, then the network is not restricted by app UID. If it's an empty list, then
      * it means nobody can use it.
      * As a special exception, the app managing this network (as identified by its UID stored in
-     * mEstablishingVpnAppUid) can always see this network. This is embodied by a special check in
+     * mOwnerUid) can always see this network. This is embodied by a special check in
      * satisfiedByUids. That still does not mean the network necessarily <strong>applies</strong>
      * to the app that manages it as determined by #appliesToUid.
      * <p>
@@ -1209,7 +1259,7 @@
      * in the passed nc (representing the UIDs that this network is available to).
      * <p>
      * As a special exception, the UID that created the passed network (as represented by its
-     * mEstablishingVpnAppUid field) always satisfies a NetworkRequest requiring it (of LISTEN
+     * mOwnerUid field) always satisfies a NetworkRequest requiring it (of LISTEN
      * or REQUEST types alike), even if the network does not apply to it. That is so a VPN app
      * can see its own network when it listens for it.
      * <p>
@@ -1220,7 +1270,7 @@
     public boolean satisfiedByUids(@NonNull NetworkCapabilities nc) {
         if (null == nc.mUids || null == mUids) return true; // The network satisfies everything.
         for (UidRange requiredRange : mUids) {
-            if (requiredRange.contains(nc.mEstablishingVpnAppUid)) return true;
+            if (requiredRange.contains(nc.mOwnerUid)) return true;
             if (!nc.appliesToUidRange(requiredRange)) {
                 return false;
             }
@@ -1471,6 +1521,7 @@
     public int describeContents() {
         return 0;
     }
+
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeLong(mNetworkCapabilities);
@@ -1484,6 +1535,8 @@
         dest.writeArraySet(mUids);
         dest.writeString(mSSID);
         dest.writeBoolean(mPrivateDnsBroken);
+        dest.writeList(mAdministratorUids);
+        dest.writeInt(mOwnerUid);
     }
 
     public static final @android.annotation.NonNull Creator<NetworkCapabilities> CREATOR =
@@ -1504,6 +1557,8 @@
                         null /* ClassLoader, null for default */);
                 netCap.mSSID = in.readString();
                 netCap.mPrivateDnsBroken = in.readBoolean();
+                netCap.setAdministratorUids(in.readArrayList(null));
+                netCap.mOwnerUid = in.readInt();
                 return netCap;
             }
             @Override
@@ -1553,8 +1608,12 @@
                 sb.append(" Uids: <").append(mUids).append(">");
             }
         }
-        if (mEstablishingVpnAppUid != INVALID_UID) {
-            sb.append(" EstablishingAppUid: ").append(mEstablishingVpnAppUid);
+        if (mOwnerUid != Process.INVALID_UID) {
+            sb.append(" OwnerUid: ").append(mOwnerUid);
+        }
+
+        if (!mAdministratorUids.isEmpty()) {
+            sb.append(" AdministratorUids: ").append(mAdministratorUids);
         }
 
         if (null != mSSID) {
diff --git a/core/java/android/net/NetworkKey.java b/core/java/android/net/NetworkKey.java
index 4469d7d..5cd4eb5 100644
--- a/core/java/android/net/NetworkKey.java
+++ b/core/java/android/net/NetworkKey.java
@@ -75,13 +75,11 @@
      *
      * @return A new {@link NetworkKey} instance or <code>null</code> if the given
      *         {@link ScanResult} instance is malformed.
-     * @throws IllegalArgumentException
+     * @throws NullPointerException
      */
     @Nullable
     public static NetworkKey createFromScanResult(@NonNull ScanResult result) {
-        if (result == null) {
-            throw new IllegalArgumentException("ScanResult cannot be null");
-        }
+        Objects.requireNonNull(result);
         final String ssid = result.SSID;
         if (TextUtils.isEmpty(ssid) || ssid.equals(WifiManager.UNKNOWN_SSID)) {
             return null;
diff --git a/core/java/android/net/PlatformVpnProfile.java b/core/java/android/net/PlatformVpnProfile.java
new file mode 100644
index 0000000..fbae637
--- /dev/null
+++ b/core/java/android/net/PlatformVpnProfile.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import static android.net.PlatformVpnProfile.TYPE_IKEV2_IPSEC_PSK;
+import static android.net.PlatformVpnProfile.TYPE_IKEV2_IPSEC_RSA;
+import static android.net.PlatformVpnProfile.TYPE_IKEV2_IPSEC_USER_PASS;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+
+import com.android.internal.net.VpnProfile;
+
+import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.security.GeneralSecurityException;
+
+/**
+ * PlatformVpnProfile represents a configuration for a platform-based VPN implementation.
+ *
+ * <p>Platform-based VPNs allow VPN applications to provide configuration and authentication options
+ * to leverage the Android OS' implementations of well-defined control plane (authentication, key
+ * negotiation) and data plane (per-packet encryption) protocols to simplify the creation of VPN
+ * tunnels. In contrast, {@link VpnService} based VPNs must implement both the control and data
+ * planes on a per-app basis.
+ *
+ * @see Ikev2VpnProfile
+ */
+public abstract class PlatformVpnProfile {
+    /**
+     * Alias to platform VPN related types from VpnProfile, for API use.
+     *
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+        TYPE_IKEV2_IPSEC_USER_PASS,
+        TYPE_IKEV2_IPSEC_PSK,
+        TYPE_IKEV2_IPSEC_RSA,
+    })
+    public static @interface PlatformVpnType {}
+
+    public static final int TYPE_IKEV2_IPSEC_USER_PASS = VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS;
+    public static final int TYPE_IKEV2_IPSEC_PSK = VpnProfile.TYPE_IKEV2_IPSEC_PSK;
+    public static final int TYPE_IKEV2_IPSEC_RSA = VpnProfile.TYPE_IKEV2_IPSEC_RSA;
+
+    /** @hide */
+    @PlatformVpnType protected final int mType;
+
+    /** @hide */
+    PlatformVpnProfile(@PlatformVpnType int type) {
+        mType = type;
+    }
+    /** Returns the profile integer type. */
+    @PlatformVpnType
+    public final int getType() {
+        return mType;
+    }
+
+    /** Returns a type string describing the VPN profile type */
+    @NonNull
+    public final String getTypeString() {
+        switch (mType) {
+            case TYPE_IKEV2_IPSEC_USER_PASS:
+                return "IKEv2/IPsec Username/Password";
+            case TYPE_IKEV2_IPSEC_PSK:
+                return "IKEv2/IPsec Preshared key";
+            case TYPE_IKEV2_IPSEC_RSA:
+                return "IKEv2/IPsec RSA Digital Signature";
+            default:
+                return "Unknown VPN profile type";
+        }
+    }
+
+    /** @hide */
+    @NonNull
+    public abstract VpnProfile toVpnProfile() throws IOException, GeneralSecurityException;
+
+    /** @hide */
+    @NonNull
+    public static PlatformVpnProfile fromVpnProfile(@NonNull VpnProfile profile)
+            throws IOException, GeneralSecurityException {
+        switch (profile.type) {
+            case TYPE_IKEV2_IPSEC_USER_PASS: // fallthrough
+            case TYPE_IKEV2_IPSEC_PSK: // fallthrough
+            case TYPE_IKEV2_IPSEC_RSA:
+                return Ikev2VpnProfile.fromVpnProfile(profile);
+            default:
+                throw new IllegalArgumentException("Unknown VPN Profile type");
+        }
+    }
+}
diff --git a/core/java/android/net/VpnManager.java b/core/java/android/net/VpnManager.java
new file mode 100644
index 0000000..f95807a
--- /dev/null
+++ b/core/java/android/net/VpnManager.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * This class provides an interface for apps to manage platform VPN profiles
+ *
+ * <p>Apps can use this API to provide profiles with which the platform can set up a VPN without
+ * further app intermediation. When a VPN profile is present and the app is selected as an always-on
+ * VPN, the platform will directly trigger the negotiation of the VPN without starting or waking the
+ * app (unlike VpnService).
+ *
+ * <p>VPN apps using supported protocols should preferentially use this API over the {@link
+ * VpnService} API for ease-of-development and reduced maintainance burden. This also give the user
+ * the guarantee that VPN network traffic is not subjected to on-device packet interception.
+ *
+ * @see Ikev2VpnProfile
+ */
+public class VpnManager {
+    @NonNull private final Context mContext;
+    @NonNull private final IConnectivityManager mService;
+
+    /**
+     * Create an instance of the VpnManger with the given context.
+     *
+     * <p>Internal only. Applications are expected to obtain an instance of the VpnManager via the
+     * {@link Context.getSystemService()} method call.
+     *
+     * @hide
+     */
+    public VpnManager(@NonNull Context ctx, @NonNull IConnectivityManager service) {
+        mContext = checkNotNull(ctx, "missing Context");
+        mService = checkNotNull(service, "missing IConnectivityManager");
+    }
+
+    /**
+     * Install a VpnProfile configuration keyed on the calling app's package name.
+     *
+     * @param profile the PlatformVpnProfile provided by this package. Will override any previous
+     *     PlatformVpnProfile stored for this package.
+     * @return an intent to request user consent if needed (null otherwise).
+     */
+    @Nullable
+    public Intent provisionVpnProfile(@NonNull PlatformVpnProfile profile) {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    /** Delete the VPN profile configuration that was provisioned by the calling app */
+    public void deleteProvisionedVpnProfile() {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    /**
+     * Request the startup of a previously provisioned VPN.
+     *
+     * @throws SecurityException exception if user or device settings prevent this VPN from being
+     *     setup, or if user consent has not been granted
+     */
+    public void startProvisionedVpnProfile() {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    /** Tear down the VPN provided by the calling app (if any) */
+    public void stopProvisionedVpnProfile() {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+}
diff --git a/core/java/android/os/BatteryStatsManager.java b/core/java/android/os/BatteryStatsManager.java
index 0545666..f2e16b4 100644
--- a/core/java/android/os/BatteryStatsManager.java
+++ b/core/java/android/os/BatteryStatsManager.java
@@ -42,7 +42,7 @@
  */
 @SystemApi
 @SystemService(Context.BATTERY_STATS_SERVICE)
-public class BatteryStatsManager {
+public final class BatteryStatsManager {
     /**
      * Wifi states.
      *
@@ -166,7 +166,7 @@
      * @param newRssi The new RSSI value.
      */
     @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
-    public void noteWifiRssiChanged(@IntRange(from = -127, to = 0) int newRssi) {
+    public void reportWifiRssiChanged(@IntRange(from = -127, to = 0) int newRssi) {
         try {
             mBatteryStats.noteWifiRssiChanged(newRssi);
         } catch (RemoteException e) {
@@ -178,7 +178,7 @@
      * Indicates that wifi was toggled on.
      */
     @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
-    public void noteWifiOn() {
+    public void reportWifiOn() {
         try {
             mBatteryStats.noteWifiOn();
         } catch (RemoteException e) {
@@ -190,7 +190,7 @@
      * Indicates that wifi was toggled off.
      */
     @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
-    public void noteWifiOff() {
+    public void reportWifiOff() {
         try {
             mBatteryStats.noteWifiOff();
         } catch (RemoteException e) {
@@ -205,7 +205,7 @@
      * @param accessPoint SSID of the network if wifi is connected to STA, else null.
      */
     @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
-    public void noteWifiState(@WifiState int newWifiState,
+    public void reportWifiState(@WifiState int newWifiState,
             @Nullable String accessPoint) {
         try {
             mBatteryStats.noteWifiState(newWifiState, accessPoint);
@@ -220,7 +220,7 @@
      * @param ws Worksource (to be used for battery blaming).
      */
     @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
-    public void noteWifiScanStartedFromSource(@NonNull WorkSource ws) {
+    public void reportWifiScanStartedFromSource(@NonNull WorkSource ws) {
         try {
             mBatteryStats.noteWifiScanStartedFromSource(ws);
         } catch (RemoteException e) {
@@ -234,7 +234,7 @@
      * @param ws Worksource (to be used for battery blaming).
      */
     @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
-    public void noteWifiScanStoppedFromSource(@NonNull WorkSource ws) {
+    public void reportWifiScanStoppedFromSource(@NonNull WorkSource ws) {
         try {
             mBatteryStats.noteWifiScanStoppedFromSource(ws);
         } catch (RemoteException e) {
@@ -249,7 +249,7 @@
      * @param csph Channels scanned per hour.
      */
     @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
-    public void noteWifiBatchedScanStartedFromSource(@NonNull WorkSource ws,
+    public void reportWifiBatchedScanStartedFromSource(@NonNull WorkSource ws,
             @IntRange(from = 0) int csph) {
         try {
             mBatteryStats.noteWifiBatchedScanStartedFromSource(ws, csph);
@@ -264,7 +264,7 @@
      * @param ws Worksource (to be used for battery blaming).
      */
     @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
-    public void noteWifiBatchedScanStoppedFromSource(@NonNull WorkSource ws) {
+    public void reportWifiBatchedScanStoppedFromSource(@NonNull WorkSource ws) {
         try {
             mBatteryStats.noteWifiBatchedScanStoppedFromSource(ws);
         } catch (RemoteException e) {
@@ -308,7 +308,7 @@
      * @param ws Worksource (to be used for battery blaming).
      */
     @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
-    public void noteFullWifiLockAcquiredFromSource(@NonNull WorkSource ws) {
+    public void reportFullWifiLockAcquiredFromSource(@NonNull WorkSource ws) {
         try {
             mBatteryStats.noteFullWifiLockAcquiredFromSource(ws);
         } catch (RemoteException e) {
@@ -322,7 +322,7 @@
      * @param ws Worksource (to be used for battery blaming).
      */
     @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
-    public void noteFullWifiLockReleasedFromSource(@NonNull WorkSource ws) {
+    public void reportFullWifiLockReleasedFromSource(@NonNull WorkSource ws) {
         try {
             mBatteryStats.noteFullWifiLockReleasedFromSource(ws);
         } catch (RemoteException e) {
@@ -338,7 +338,7 @@
      *                   authentication failure.
      */
     @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
-    public void noteWifiSupplicantStateChanged(@WifiSupplState int newSupplState,
+    public void reportWifiSupplicantStateChanged(@WifiSupplState int newSupplState,
             boolean failedAuth) {
         try {
             mBatteryStats.noteWifiSupplicantStateChanged(newSupplState, failedAuth);
@@ -353,7 +353,7 @@
      * @param uid UID of the app that acquired the wifi lock (to be used for battery blaming).
      */
     @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
-    public void noteWifiMulticastEnabled(int uid) {
+    public void reportWifiMulticastEnabled(int uid) {
         try {
             mBatteryStats.noteWifiMulticastEnabled(uid);
         } catch (RemoteException e) {
@@ -367,7 +367,7 @@
      * @param uid UID of the app that released the wifi lock (to be used for battery blaming).
      */
     @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
-    public void noteWifiMulticastDisabled(int uid) {
+    public void reportWifiMulticastDisabled(int uid) {
         try {
             mBatteryStats.noteWifiMulticastDisabled(uid);
         } catch (RemoteException e) {
diff --git a/core/java/android/os/HwParcel.java b/core/java/android/os/HwParcel.java
index fb36e6f..228548a 100644
--- a/core/java/android/os/HwParcel.java
+++ b/core/java/android/os/HwParcel.java
@@ -38,6 +38,7 @@
 public class HwParcel {
     private static final String TAG = "HwParcel";
 
+    /** @hide */
     @IntDef(prefix = { "STATUS_" }, value = {
         STATUS_SUCCESS,
     })
diff --git a/core/java/android/os/IVibratorService.aidl b/core/java/android/os/IVibratorService.aidl
index 416d692..e201e43 100644
--- a/core/java/android/os/IVibratorService.aidl
+++ b/core/java/android/os/IVibratorService.aidl
@@ -24,6 +24,8 @@
 {
     boolean hasVibrator();
     boolean hasAmplitudeControl();
+    boolean[] areEffectsSupported(in int[] effectIds);
+    boolean[] arePrimitivesSupported(in int[] primitiveIds);
     boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, in VibrationEffect effect,
             in VibrationAttributes attributes);
     void vibrate(int uid, String opPkg, in VibrationEffect effect,
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 6a80788..f3d3837 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -1371,6 +1371,7 @@
      * @throws UnsupportedOperationException if userspace reboot was requested on a device that
      *                                       doesn't support it.
      */
+    @RequiresPermission(permission.REBOOT)
     public void reboot(@Nullable String reason) {
         if (REBOOT_USERSPACE.equals(reason) && !isRebootingUserspaceSupported()) {
             throw new UnsupportedOperationException(
@@ -1390,6 +1391,7 @@
      * </p>
      * @hide
      */
+    @RequiresPermission(permission.REBOOT)
     public void rebootSafeMode() {
         try {
             mService.rebootSafeMode(false, true);
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index c7a8474..8daf6e8 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -179,6 +179,12 @@
     public static final int OTA_UPDATE_UID = 1061;
 
     /**
+     * Defines the UID used for statsd
+     * @hide
+     */
+    public static final int STATSD_UID = 1066;
+
+    /**
      * Defines the UID used for incidentd.
      * @hide
      */
@@ -856,6 +862,17 @@
             throws IllegalArgumentException, SecurityException;
 
     /**
+     * Freeze or unfreeze the specified process.
+     *
+     * @param pid Identifier of the process to freeze or unfreeze.
+     * @param uid Identifier of the user the process is running under.
+     * @param frozen Specify whether to free (true) or unfreeze (false).
+     *
+     * @hide
+     */
+    public static final native void setProcessFrozen(int pid, int uid, boolean frozen);
+
+    /**
      * Return the scheduling group of requested process.
      *
      * @hide
diff --git a/core/java/android/os/StatsLogEventWrapper.java b/core/java/android/os/StatsLogEventWrapper.java
deleted file mode 100644
index 320fc13..0000000
--- a/core/java/android/os/StatsLogEventWrapper.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (C) 2017 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.os;
-
-import android.util.Slog;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Wrapper class for sending data from Android OS to StatsD.
- *
- * @hide
- */
-public final class StatsLogEventWrapper implements Parcelable {
-    static final boolean DEBUG = false;
-    static final String TAG = "StatsLogEventWrapper";
-
-    // Keep in sync with FieldValue.h enums
-    private static final int EVENT_TYPE_UNKNOWN = 0;
-    private static final int EVENT_TYPE_INT = 1; /* int32_t */
-    private static final int EVENT_TYPE_LONG = 2; /* int64_t */
-    private static final int EVENT_TYPE_FLOAT = 3;
-    private static final int EVENT_TYPE_DOUBLE = 4;
-    private static final int EVENT_TYPE_STRING = 5;
-    private static final int EVENT_TYPE_STORAGE = 6;
-
-    List<Integer> mTypes = new ArrayList<>();
-    List<Object> mValues = new ArrayList<>();
-    int mTag;
-    long mElapsedTimeNs;
-    long mWallClockTimeNs;
-    WorkSource mWorkSource = null;
-
-    public StatsLogEventWrapper(int tag, long elapsedTimeNs, long wallClockTimeNs) {
-        this.mTag = tag;
-        this.mElapsedTimeNs = elapsedTimeNs;
-        this.mWallClockTimeNs = wallClockTimeNs;
-    }
-
-    /**
-     * Boilerplate for Parcel.
-     */
-    public static final @android.annotation.NonNull Parcelable.Creator<StatsLogEventWrapper> CREATOR = new
-            Parcelable.Creator<StatsLogEventWrapper>() {
-                public StatsLogEventWrapper createFromParcel(Parcel in) {
-                    return new StatsLogEventWrapper(in);
-                }
-
-                public StatsLogEventWrapper[] newArray(int size) {
-                    return new StatsLogEventWrapper[size];
-                }
-            };
-
-    private StatsLogEventWrapper(Parcel in) {
-        readFromParcel(in);
-    }
-
-    /**
-     * Set work source if any.
-     */
-    public void setWorkSource(WorkSource ws) {
-        if (ws.getWorkChains() == null || ws.getWorkChains().size() == 0) {
-            Slog.w(TAG, "Empty worksource!");
-            return;
-        }
-        mWorkSource = ws;
-    }
-
-    /**
-     * Write a int value.
-     */
-    public void writeInt(int val) {
-        mTypes.add(EVENT_TYPE_INT);
-        mValues.add(val);
-    }
-
-    /**
-     * Write a long value.
-     */
-    public void writeLong(long val) {
-        mTypes.add(EVENT_TYPE_LONG);
-        mValues.add(val);
-    }
-
-    /**
-     * Write a string value.
-     */
-    public void writeString(String val) {
-        mTypes.add(EVENT_TYPE_STRING);
-        // use empty string for null
-        mValues.add(val == null ? "" : val);
-    }
-
-    /**
-     * Write a float value.
-     */
-    public void writeFloat(float val) {
-        mTypes.add(EVENT_TYPE_FLOAT);
-        mValues.add(val);
-    }
-
-    /**
-     * Write a storage value.
-     */
-    public void writeStorage(byte[] val) {
-        mTypes.add(EVENT_TYPE_STORAGE);
-        mValues.add(val);
-    }
-
-    /**
-     * Write a boolean value.
-     */
-    public void writeBoolean(boolean val) {
-        mTypes.add(EVENT_TYPE_INT);
-        mValues.add(val ? 1 : 0);
-    }
-
-    public void writeToParcel(Parcel out, int flags) {
-        if (DEBUG) {
-            Slog.d(TAG,
-                    "Writing " + mTag + " " + mElapsedTimeNs + " " + mWallClockTimeNs + " and "
-                            + mTypes.size() + " elements.");
-        }
-        out.writeInt(mTag);
-        out.writeLong(mElapsedTimeNs);
-        out.writeLong(mWallClockTimeNs);
-        if (mWorkSource != null) {
-            List<WorkSource.WorkChain> workChains = mWorkSource.getWorkChains();
-            // number of chains
-            out.writeInt(workChains.size());
-            for (int i = 0; i < workChains.size(); i++) {
-                android.os.WorkSource.WorkChain wc = workChains.get(i);
-                if (wc.getSize() == 0) {
-                    Slog.w(TAG, "Empty work chain.");
-                    out.writeInt(0);
-                    continue;
-                }
-                if (wc.getUids().length != wc.getTags().length
-                        || wc.getUids().length != wc.getSize()) {
-                    Slog.w(TAG, "Malformated work chain.");
-                    out.writeInt(0);
-                    continue;
-                }
-                // number of nodes
-                out.writeInt(wc.getSize());
-                for (int j = 0; j < wc.getSize(); j++) {
-                    out.writeInt(wc.getUids()[j]);
-                    out.writeString(wc.getTags()[j] == null ? "" : wc.getTags()[j]);
-                }
-            }
-        } else {
-            // no chains
-            out.writeInt(0);
-        }
-        out.writeInt(mTypes.size());
-        for (int i = 0; i < mTypes.size(); i++) {
-            out.writeInt(mTypes.get(i));
-            switch (mTypes.get(i)) {
-                case EVENT_TYPE_INT:
-                    out.writeInt((int) mValues.get(i));
-                    break;
-                case EVENT_TYPE_LONG:
-                    out.writeLong((long) mValues.get(i));
-                    break;
-                case EVENT_TYPE_FLOAT:
-                    out.writeFloat((float) mValues.get(i));
-                    break;
-                case EVENT_TYPE_DOUBLE:
-                    out.writeDouble((double) mValues.get(i));
-                    break;
-                case EVENT_TYPE_STRING:
-                    out.writeString((String) mValues.get(i));
-                    break;
-                case EVENT_TYPE_STORAGE:
-                    out.writeByteArray((byte[]) mValues.get(i));
-                    break;
-                default:
-                    break;
-            }
-        }
-    }
-
-    /**
-     * Reads from parcel and appropriately fills member fields.
-     */
-    public void readFromParcel(Parcel in) {
-        mTypes = new ArrayList<>();
-        mValues = new ArrayList<>();
-        mWorkSource = null;
-
-        mTag = in.readInt();
-        mElapsedTimeNs = in.readLong();
-        mWallClockTimeNs = in.readLong();
-
-        // Clear any data.
-        if (DEBUG) {
-            Slog.d(TAG, "Reading " + mTag + " " + mElapsedTimeNs + " " + mWallClockTimeNs);
-        }
-        // Set up worksource if present.
-        int numWorkChains = in.readInt();
-        if (numWorkChains > 0) {
-            mWorkSource = new WorkSource();
-            for (int i = 0; i < numWorkChains; i++) {
-                android.os.WorkSource.WorkChain workChain = mWorkSource.createWorkChain();
-                int workChainSize = in.readInt();
-                for (int j = 0; j < workChainSize; j++) {
-                    int uid = in.readInt();
-                    String tag = in.readString();
-                    workChain.addNode(uid, tag);
-                }
-            }
-        }
-
-        // Do the rest of the types.
-        int numTypes = in.readInt();
-        if (DEBUG) {
-            Slog.d(TAG, "Reading " + numTypes + " elements");
-        }
-        for (int i = 0; i < numTypes; i++) {
-            int type = in.readInt();
-            mTypes.add(type);
-            switch (type) {
-                case EVENT_TYPE_INT:
-                    mValues.add(in.readInt());
-                    break;
-                case EVENT_TYPE_LONG:
-                    mValues.add(in.readLong());
-                    break;
-                case EVENT_TYPE_FLOAT:
-                    mValues.add(in.readFloat());
-                    break;
-                case EVENT_TYPE_DOUBLE:
-                    mValues.add(in.readDouble());
-                    break;
-                case EVENT_TYPE_STRING:
-                    mValues.add(in.readString());
-                    break;
-                case EVENT_TYPE_STORAGE:
-                    mValues.add(in.createByteArray());
-                    break;
-                default:
-                    break;
-            }
-        }
-    }
-
-    /**
-     * Boilerplate for Parcel.
-     */
-    public int describeContents() {
-        return 0;
-    }
-}
diff --git a/core/java/android/os/StatsServiceManager.java b/core/java/android/os/StatsServiceManager.java
new file mode 100644
index 0000000..d032e98
--- /dev/null
+++ b/core/java/android/os/StatsServiceManager.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.os;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+
+/**
+ * Provides a way to register and obtain the system service binder objects managed by the stats
+ * service.
+ *
+ * <p> Only the statsd mainline module will be able to access an instance of this class.
+ *
+ * TODO(b/148225705) Change to @SystemApi(client=MODULE_LIBRARIES) when the build system is ready.
+ * @hide
+ */
+@SystemApi
+public class StatsServiceManager {
+    /**
+     * @hide
+     */
+    public StatsServiceManager() {}
+
+    /**
+     * A class that exposes the methods to register and obtain each system service.
+     */
+    public static final class ServiceRegisterer {
+        private final String mServiceName;
+
+        /**
+         * @hide
+         */
+        public ServiceRegisterer(String serviceName) {
+            mServiceName = serviceName;
+        }
+
+        /**
+         * Get the system server binding object for StatsManagerService.
+         *
+         * <p> This blocks until the service instance is ready.
+         * or a timeout happens, in which case it returns null.
+         */
+        @Nullable
+        public IBinder get() {
+            return ServiceManager.getService(mServiceName);
+        }
+
+        /**
+         * Get the system server binding object for a service.
+         *
+         * <p>This blocks until the service instance is ready,
+         * or a timeout happens, in which case it throws {@link ServiceNotFoundException}.
+         */
+        @Nullable
+        public IBinder getOrThrow() throws ServiceNotFoundException {
+            try {
+                return ServiceManager.getServiceOrThrow(mServiceName);
+            } catch (ServiceManager.ServiceNotFoundException e) {
+                throw new ServiceNotFoundException(mServiceName);
+            }
+        }
+
+        /**
+         * Get the system server binding object for a service. If the specified service is
+         * not available, it returns null.
+         */
+        @Nullable
+        private IBinder tryGet() {
+            return ServiceManager.checkService(mServiceName);
+        }
+    }
+
+    /**
+     * See {@link ServiceRegisterer#getOrThrow()}
+     */
+    public static class ServiceNotFoundException extends ServiceManager.ServiceNotFoundException {
+        /**
+         * Constructor
+         *
+         * @param name the name of the binder service that cannot be found.
+         */
+        public ServiceNotFoundException(@NonNull String name) {
+            super(name);
+        }
+    }
+
+    /**
+     * Returns {@link ServiceRegisterer} for the "statscompanion" service.
+     */
+    @NonNull
+    public ServiceRegisterer getStatsCompanionServiceRegisterer() {
+        return new ServiceRegisterer("statscompanion");
+    }
+
+    /**
+     * Returns {@link ServiceRegisterer} for the "statsmanager" service.
+     */
+    @NonNull
+    public ServiceRegisterer getStatsManagerServiceRegisterer() {
+        return new ServiceRegisterer("statsmanager");
+    }
+
+    /**
+     * Returns {@link ServiceRegisterer} for the "statsd" service.
+     */
+    @NonNull
+    public ServiceRegisterer getStatsdServiceRegisterer() {
+        return new ServiceRegisterer("stats");
+    }
+}
diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java
index 8050454..faf4a36 100644
--- a/core/java/android/os/SystemVibrator.java
+++ b/core/java/android/os/SystemVibrator.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import android.annotation.NonNull;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.media.AudioAttributes;
@@ -104,6 +105,28 @@
     }
 
     @Override
+    public boolean[] areEffectsSupported(@VibrationEffect.EffectType int... effectIds) {
+        try {
+            return mService.areEffectsSupported(effectIds);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to query effect support");
+        }
+        return new boolean[effectIds.length];
+    }
+
+    @Override
+    public boolean[] arePrimitivesSupported(
+            @NonNull @VibrationEffect.Composition.Primitive int... primitiveIds) {
+        try {
+            return mService.arePrimitivesSupported(primitiveIds);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to query effect support");
+        }
+        return new boolean[primitiveIds.length];
+    }
+
+
+    @Override
     public void cancel() {
         if (mService == null) {
             return;
diff --git a/core/java/android/os/TelephonyServiceManager.java b/core/java/android/os/TelephonyServiceManager.java
index 4f5f3d6..1128f4c 100644
--- a/core/java/android/os/TelephonyServiceManager.java
+++ b/core/java/android/os/TelephonyServiceManager.java
@@ -39,7 +39,7 @@
     /**
      * A class that exposes the methods to register and obtain each system service.
      */
-    public final class ServiceRegisterer {
+    public static final class ServiceRegisterer {
         private final String mServiceName;
 
         /**
@@ -119,14 +119,6 @@
     }
 
     /**
-     * Returns {@link ServiceRegisterer} for the telephony registry service.
-     */
-    @NonNull
-    public ServiceRegisterer getTelephonyRegistryServiceRegisterer() {
-        return new ServiceRegisterer("telephony.registry");
-    }
-
-    /**
      * Returns {@link ServiceRegisterer} for the telephony IMS service.
      */
     @NonNull
@@ -151,14 +143,6 @@
     }
 
     /**
-     * Returns {@link ServiceRegisterer} for the network policy service.
-     */
-    @NonNull
-    public ServiceRegisterer getNetworkPolicyServiceRegisterer() {
-        return new ServiceRegisterer(Context.NETWORK_POLICY_SERVICE);
-    }
-
-    /**
      * Returns {@link ServiceRegisterer} for the phone sub service.
      */
     @NonNull
@@ -198,28 +182,15 @@
         return new ServiceRegisterer("econtroller");
     }
 
+    /**
+     * Returns {@link ServiceRegisterer} for the eUICC card controller service.
+     */
     @NonNull
     public ServiceRegisterer getEuiccCardControllerServiceRegisterer() {
         return new ServiceRegisterer("euicc_card_controller");
     }
 
     /**
-     * Returns {@link ServiceRegisterer} for the package manager service.
-     */
-    @NonNull
-    public ServiceRegisterer getPackageManagerServiceRegisterer() {
-        return new ServiceRegisterer("package");
-    }
-
-    /**
-     * Returns {@link ServiceRegisterer} for the permission manager service.
-     */
-    @NonNull
-    public ServiceRegisterer getPermissionManagerServiceRegisterer() {
-        return new ServiceRegisterer("permissionmgr");
-    }
-
-    /**
      * Returns {@link ServiceRegisterer} for the ICC phone book service.
      */
     @NonNull
diff --git a/core/java/android/os/VibrationEffect.aidl b/core/java/android/os/VibrationEffect.aidl
index dcc79d7..89478fa 100644
--- a/core/java/android/os/VibrationEffect.aidl
+++ b/core/java/android/os/VibrationEffect.aidl
@@ -17,6 +17,4 @@
 package android.os;
 
 parcelable VibrationEffect;
-parcelable VibrationEffect.OneShotVibration;
-parcelable VibrationEffect.WaveformVibration;
-parcelable VibrationEffect.EffectVibration;
+parcelable VibrationEffect.Composition.PrimitiveEffect;
\ No newline at end of file
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index 75b4724..2d218f4 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -16,7 +16,9 @@
 
 package android.os;
 
+import android.annotation.FloatRange;
 import android.annotation.IntDef;
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
@@ -28,9 +30,14 @@
 import android.net.Uri;
 import android.util.MathUtils;
 
+import com.android.internal.util.Preconditions;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
 
 /**
  * A VibrationEffect describes a haptic effect to be performed by a {@link Vibrator}.
@@ -41,6 +48,8 @@
     private static final int PARCEL_TOKEN_ONE_SHOT = 1;
     private static final int PARCEL_TOKEN_WAVEFORM = 2;
     private static final int PARCEL_TOKEN_EFFECT = 3;
+    private static final int PARCEL_TOKEN_COMPOSITION = 4;
+
 
     /**
      * The default vibration strength of the device.
@@ -359,6 +368,16 @@
         return null;
     }
 
+    /**
+     * Start composing a haptic effect.
+     *
+     * @see VibrationEffect.Composition
+     */
+    @NonNull
+    public static VibrationEffect.Composition startComposition() {
+        return new VibrationEffect.Composition();
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -839,6 +858,331 @@
             };
     }
 
+    /** @hide */
+    public static final class Composed extends VibrationEffect implements Parcelable {
+        private final ArrayList<Composition.PrimitiveEffect> mPrimitiveEffects;
+
+        /**
+         * @hide
+         */
+        @SuppressWarnings("unchecked")
+        public Composed(@NonNull Parcel in) {
+            this(in.readArrayList(Composed.class.getClassLoader()));
+        }
+
+        /**
+         * @hide
+         */
+        public Composed(List<Composition.PrimitiveEffect> effects) {
+            mPrimitiveEffects = new ArrayList<>(Objects.requireNonNull(effects));
+        }
+
+        /**
+         * @hide
+         */
+        @NonNull
+        public List<Composition.PrimitiveEffect> getPrimitiveEffects() {
+            return mPrimitiveEffects;
+        }
+
+        @Override
+        public long getDuration() {
+            return -1;
+        }
+
+
+        /**
+         * @hide
+         */
+        @Override
+        public void validate() {
+            for (Composition.PrimitiveEffect effect : mPrimitiveEffects) {
+                Composition.checkPrimitive(effect.id);
+                Preconditions.checkArgumentInRange(
+                        effect.scale, 0.0f, 1.0f, "scale");
+            }
+        }
+
+        @Override
+        public void writeToParcel(@NonNull Parcel out, int flags) {
+            out.writeInt(PARCEL_TOKEN_COMPOSITION);
+            out.writeList(mPrimitiveEffects);
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            Composed composed = (Composed) o;
+            return mPrimitiveEffects.equals(composed.mPrimitiveEffects);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mPrimitiveEffects);
+        }
+
+        @Override
+        public String toString() {
+            return "Composed{mPrimitiveEffects=" + mPrimitiveEffects + '}';
+        }
+
+        public static final @NonNull Parcelable.Creator<Composed> CREATOR =
+                new Parcelable.Creator<Composed>() {
+                    @Override
+                    public Composed createFromParcel(@NonNull Parcel in) {
+                        // Skip the type token
+                        in.readInt();
+                        return new Composed(in);
+                    }
+
+                    @Override
+                    @NonNull
+                    public Composed[] newArray(int size) {
+                        return new Composed[size];
+                    }
+                };
+    }
+
+    /**
+     * A composition of haptic primitives that, when combined, create a single haptic effect.
+     *
+     * @see VibrationEffect#startComposition()
+     */
+    public static class Composition {
+        /** @hide */
+        @IntDef(prefix = { "PRIMITIVE_" }, value = {
+                PRIMITIVE_CLICK,
+                PRIMITIVE_THUD,
+                PRIMITIVE_SPIN,
+                PRIMITIVE_QUICK_RISE,
+                PRIMITIVE_SLOW_RISE,
+                PRIMITIVE_QUICK_FALL,
+                PRIMITIVE_LIGHT_TICK,
+        })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface Primitive {}
+
+        /**
+         * No haptic effect. Used to generate extended delays between primitives.
+         * @hide
+         */
+        public static final int PRIMITIVE_NOOP = 0;
+        /**
+         * This effect should produce a sharp, crisp click sensation.
+         */
+        public static final int PRIMITIVE_CLICK = 1;
+        /**
+         * A haptic effect that simulates downwards movement with gravity. Often
+         * followed by extra energy of hitting and reverberation to augment
+         * physicality.
+         */
+        public static final int PRIMITIVE_THUD = 2;
+        /**
+         * A haptic effect that simulates spinning momentum.
+         */
+        public static final int PRIMITIVE_SPIN = 3;
+        /**
+         * A haptic effect that simulates quick upward movement against gravity.
+         */
+        public static final int PRIMITIVE_QUICK_RISE = 4;
+        /**
+         * A haptic effect that simulates slow upward movement against gravity.
+         */
+        public static final int PRIMITIVE_SLOW_RISE = 5;
+        /**
+         * A haptic effect that simulates quick downwards movement with gravity.
+         */
+        public static final int PRIMITIVE_QUICK_FALL = 6;
+        /**
+         * This very short effect should produce a light crisp sensation intended
+         * to be used repetitively for dynamic feedback.
+         */
+        public static final int PRIMITIVE_LIGHT_TICK = 7;
+
+
+        private ArrayList<PrimitiveEffect> mEffects = new ArrayList<>();
+
+        /**
+         * Add a haptic primitive to the end of the current composition.
+         *
+         * Similar to {@link #addPrimitive(int, float, int)}, but with no delay and a
+         * default scale applied.
+         *
+         * @param primitiveId The primitive to add
+         *
+         * @return The {@link Composition} object to enable adding multiple primitives in one chain.
+         */
+        @Nullable
+        public Composition addPrimitive(@Primitive int primitiveId) {
+            addPrimitive(primitiveId, /*scale*/ 1.0f, /*delay*/ 0);
+            return this;
+        }
+
+        /**
+         * Add a haptic primitive to the end of the current composition.
+         *
+         * Similar to {@link #addPrimitive(int, float, int)}, but with no delay.
+         *
+         * @param primitiveId The primitive to add
+         * @param scale The scale to apply to the intensity of the primitive.
+         *
+         * @return The {@link Composition} object to enable adding multiple primitives in one chain.
+         */
+        @Nullable
+        public Composition addPrimitive(@Primitive int primitiveId,
+                @FloatRange(from = 0f, to = 1f) float scale) {
+            addPrimitive(primitiveId, scale, /*delay*/ 0);
+            return this;
+        }
+
+        /**
+         * Add a haptic primitive to the end of the current composition.
+         *
+         * @param primitiveId The primitive to add
+         * @param scale The scale to apply to the intensity of the primitive.
+         * @param delay The amount of time, in milliseconds, to wait before playing the prior
+         *              primitive and this one
+         * @return The {@link Composition} object to enable adding multiple primitives in one chain.
+         */
+        @Nullable
+        public Composition addPrimitive(@Primitive int primitiveId,
+                @FloatRange(from = 0f, to = 1f) float scale, @IntRange(from = 0) int delay) {
+            mEffects.add(new PrimitiveEffect(checkPrimitive(primitiveId), scale, delay));
+            return this;
+        }
+
+        /**
+         * Compose all of the added primitives together into a single {@link VibrationEffect}.
+         *
+         * The {@link Composition} object is still valid after this call, so you can continue adding
+         * more primitives to it and generating more {@link VibrationEffect}s by calling this method
+         * again.
+         *
+         * @return The {@link VibrationEffect} resulting from the composition of the primitives.
+         */
+        @NonNull
+        public VibrationEffect compose() {
+            if (mEffects.isEmpty()) {
+                throw new IllegalStateException(
+                        "Composition must have at least one element to compose.");
+            }
+            return new VibrationEffect.Composed(mEffects);
+        }
+
+        /**
+         * @throws IllegalArgumentException throws if the primitive ID is not within the valid range
+         * @hide
+         *
+         */
+        static int checkPrimitive(int primitiveId) {
+            Preconditions.checkArgumentInRange(primitiveId, PRIMITIVE_NOOP, PRIMITIVE_LIGHT_TICK,
+                    "primitiveId");
+            return primitiveId;
+        }
+
+        /**
+         * Convert the primitive ID to a human readable string for debugging
+         * @param id The ID to convert
+         * @return The ID in a human readable format.
+         * @hide
+         */
+        public static String primitiveToString(@Primitive int id) {
+            switch (id) {
+                case PRIMITIVE_NOOP:
+                    return "PRIMITIVE_NOOP";
+                case PRIMITIVE_CLICK:
+                    return "PRIMITIVE_CLICK";
+                case PRIMITIVE_THUD:
+                    return "PRIMITIVE_THUD";
+                case PRIMITIVE_SPIN:
+                    return "PRIMITIVE_SPIN";
+                case PRIMITIVE_QUICK_RISE:
+                    return "PRIMITIVE_QUICK_RISE";
+                case PRIMITIVE_SLOW_RISE:
+                    return "PRIMITIVE_SLOW_RISE";
+                case PRIMITIVE_QUICK_FALL:
+                    return "PRIMITIVE_QUICK_FALL";
+                case PRIMITIVE_LIGHT_TICK:
+                    return "PRIMITIVE_LIGHT_TICK";
+
+                default:
+                    return Integer.toString(id);
+
+            }
+        }
+
+
+        /**
+         * @hide
+         */
+        public static class PrimitiveEffect implements Parcelable {
+            public int id;
+            public float scale;
+            public int delay;
+
+            PrimitiveEffect(int id, float scale, int delay) {
+                this.id = id;
+                this.scale = scale;
+                this.delay = delay;
+            }
+
+            @Override
+            public void writeToParcel(Parcel dest, int flags) {
+                dest.writeInt(id);
+                dest.writeFloat(scale);
+                dest.writeInt(delay);
+            }
+
+            @Override
+            public int describeContents() {
+                return 0;
+            }
+
+            @Override
+            public String toString() {
+                return "PrimitiveEffect{"
+                        + "id=" + primitiveToString(id)
+                        + ", scale=" + scale
+                        + ", delay=" + delay
+                        + '}';
+            }
+
+            @Override
+            public boolean equals(Object o) {
+                if (this == o) return true;
+                if (o == null || getClass() != o.getClass()) return false;
+                PrimitiveEffect that = (PrimitiveEffect) o;
+                return id == that.id
+                        && Float.compare(that.scale, scale) == 0
+                        && delay == that.delay;
+            }
+
+            @Override
+            public int hashCode() {
+                return Objects.hash(id, scale, delay);
+            }
+
+
+            public static final @NonNull Parcelable.Creator<PrimitiveEffect> CREATOR =
+                    new Parcelable.Creator<PrimitiveEffect>() {
+                        @Override
+                        public PrimitiveEffect createFromParcel(Parcel in) {
+                            return new PrimitiveEffect(in.readInt(), in.readFloat(), in.readInt());
+                        }
+                        @Override
+                        public PrimitiveEffect[] newArray(int size) {
+                            return new PrimitiveEffect[size];
+                        }
+                    };
+        }
+    }
+
     public static final @NonNull Parcelable.Creator<VibrationEffect> CREATOR =
             new Parcelable.Creator<VibrationEffect>() {
                 @Override
@@ -850,6 +1194,8 @@
                         return new Waveform(in);
                     } else if (token == PARCEL_TOKEN_EFFECT) {
                         return new Prebaked(in);
+                    } else if (token == PARCEL_TOKEN_COMPOSITION) {
+                        return new Composed(in);
                     } else {
                         throw new IllegalStateException(
                                 "Unexpected vibration event type token in parcel.");
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index ae75f3d..f055c60 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -17,6 +17,7 @@
 package android.os;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemService;
@@ -41,37 +42,42 @@
 
     /**
      * Vibration intensity: no vibrations.
+     *
      * @hide
      */
     public static final int VIBRATION_INTENSITY_OFF = 0;
 
     /**
      * Vibration intensity: low.
+     *
      * @hide
      */
     public static final int VIBRATION_INTENSITY_LOW = 1;
 
     /**
      * Vibration intensity: medium.
+     *
      * @hide
      */
     public static final int VIBRATION_INTENSITY_MEDIUM = 2;
 
     /**
      * Vibration intensity: high.
+     *
      * @hide
      */
     public static final int VIBRATION_INTENSITY_HIGH = 3;
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = { "VIBRATION_INTENSITY_" }, value = {
-        VIBRATION_INTENSITY_OFF,
-        VIBRATION_INTENSITY_LOW,
-        VIBRATION_INTENSITY_MEDIUM,
-        VIBRATION_INTENSITY_HIGH
+    @IntDef(prefix = {"VIBRATION_INTENSITY_"}, value = {
+            VIBRATION_INTENSITY_OFF,
+            VIBRATION_INTENSITY_LOW,
+            VIBRATION_INTENSITY_MEDIUM,
+            VIBRATION_INTENSITY_HIGH
     })
-    public @interface VibrationIntensity{}
+    public @interface VibrationIntensity {
+    }
 
     private final String mPackageName;
     // The default vibration intensity level for haptic feedback.
@@ -117,6 +123,7 @@
 
     /**
      * Get the default vibration intensity for haptic feedback.
+     *
      * @hide
      */
     public int getDefaultHapticFeedbackIntensity() {
@@ -125,13 +132,16 @@
 
     /**
      * Get the default vibration intensity for notifications.
+     *
      * @hide
      */
     public int getDefaultNotificationVibrationIntensity() {
         return mDefaultNotificationVibrationIntensity;
     }
 
-    /** Get the default vibration intensity for ringtones.
+    /**
+     * Get the default vibration intensity for ringtones.
+     *
      * @hide
      */
     public int getDefaultRingVibrationIntensity() {
@@ -156,11 +166,12 @@
      * Configure an always-on haptics effect.
      *
      * @param alwaysOnId The board-specific always-on ID to configure.
-     * @param effect Vibration effect to assign to always-on id. Passing null will disable it.
+     * @param effect     Vibration effect to assign to always-on id. Passing null will disable it.
      * @param attributes {@link AudioAttributes} corresponding to the vibration. For example,
-     *        specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
-     *        {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
-     *        vibrations associated with incoming calls. May only be null when effect is null.
+     *                   specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
+     *                   {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
+     *                   vibrations associated with incoming calls. May only be null when effect is
+     *                   null.
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)
@@ -183,7 +194,6 @@
      * Vibrate constantly for the specified period of time.
      *
      * @param milliseconds The number of milliseconds to vibrate.
-     *
      * @deprecated Use {@link #vibrate(VibrationEffect)} instead.
      */
     @Deprecated
@@ -196,11 +206,10 @@
      * Vibrate constantly for the specified period of time.
      *
      * @param milliseconds The number of milliseconds to vibrate.
-     * @param attributes {@link AudioAttributes} corresponding to the vibration. For example,
-     *        specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
-     *        {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
-     *        vibrations associated with incoming calls.
-     *
+     * @param attributes   {@link AudioAttributes} corresponding to the vibration. For example,
+     *                     specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
+     *                     {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
+     *                     vibrations associated with incoming calls.
      * @deprecated Use {@link #vibrate(VibrationEffect, AudioAttributes)} instead.
      */
     @Deprecated
@@ -231,9 +240,8 @@
      * </p>
      *
      * @param pattern an array of longs of times for which to turn the vibrator on or off.
-     * @param repeat the index into pattern at which to repeat, or -1 if
-     *        you don't want to repeat.
-     *
+     * @param repeat  the index into pattern at which to repeat, or -1 if
+     *                you don't want to repeat.
      * @deprecated Use {@link #vibrate(VibrationEffect)} instead.
      */
     @Deprecated
@@ -256,14 +264,13 @@
      * to start the repeat, or -1 to disable repeating.
      * </p>
      *
-     * @param pattern an array of longs of times for which to turn the vibrator on or off.
-     * @param repeat the index into pattern at which to repeat, or -1 if
-     *        you don't want to repeat.
+     * @param pattern    an array of longs of times for which to turn the vibrator on or off.
+     * @param repeat     the index into pattern at which to repeat, or -1 if
+     *                   you don't want to repeat.
      * @param attributes {@link AudioAttributes} corresponding to the vibration. For example,
-     *        specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
-     *        {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
-     *        vibrations associated with incoming calls.
-     *
+     *                   specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
+     *                   {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
+     *                   vibrations associated with incoming calls.
      * @deprecated Use {@link #vibrate(VibrationEffect, AudioAttributes)} instead.
      */
     @Deprecated
@@ -295,8 +302,9 @@
     }
 
     /**
-     * Like {@link #vibrate(int, String, VibrationEffect, AudioAttributes)}, but allows the
+     * Like {@link #vibrate(VibrationEffect, AudioAttributes)}, but allows the
      * caller to specify the vibration is owned by someone else and set reason for vibration.
+     *
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.VIBRATE)
@@ -304,6 +312,85 @@
             String reason, AudioAttributes attributes);
 
     /**
+     * Query whether the vibrator supports the given effects.
+     *
+     * If the returned array is {@code null}, the hardware doesn't support querying its supported
+     * effects. It may support any or all effects, but there's no way to programmatically know
+     * whether a {@link #vibrate} call will be successful.
+     *
+     * If the returned array is non-null, then it will be the same length as the query array and
+     * the value at a given index will contain whether the effect at that same index in the
+     * querying array is supported or not.
+     *
+     * @param effectIds Which effects to query for.
+     * @return Whether the effects are supported. Null when the hardware doesn't tell us what it
+     *         supports.
+     */
+    @Nullable
+    public boolean[] areEffectsSupported(
+            @NonNull @VibrationEffect.EffectType int... effectIds) {
+        return new boolean[effectIds.length];
+    }
+
+    /**
+     * Query whether the vibrator supports all of the given effects.
+     *
+     * If the result is {@code null}, the hardware doesn't support querying its supported
+     * effects. It may support any or all effects, but there's no way to programmatically know
+     * whether a {@link #vibrate} call will be successful.
+     *
+     * If the returned array is non-null, then it will return whether all of the effects are
+     * supported by the hardware.
+     *
+     * @param effectIds Which effects to query for.
+     * @return Whether the effects are supported. {@code null} when the hardware doesn't tell us
+     *         what it supports.
+     */
+    @Nullable
+    public Boolean areAllEffectsSupported(
+            @NonNull @VibrationEffect.EffectType int... effectIds) {
+        for (boolean supported : areEffectsSupported(effectIds)) {
+            if (!supported) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+
+    /**
+     * Query whether the vibrator supports the given primitives.
+     *
+     * The returned array will be the same length as the query array and the value at a given index
+     * will contain whether the effect at that same index in the querying array is supported or
+     * not.
+     *
+     * @param primitiveIds Which primitives to query for.
+     * @return Whether the primitives are supported.
+     */
+    @NonNull
+    public boolean[] arePrimitivesSupported(
+            @NonNull @VibrationEffect.Composition.Primitive int... primitiveIds) {
+        return new boolean[primitiveIds.length];
+    }
+
+    /**
+     * Query whether the vibrator supports all of the given primitives.
+     *
+     * @param primitiveIds Which primitives to query for.
+     * @return Whether primitives effects are supported.
+     */
+    public boolean areAllPrimitivesSupported(
+            @NonNull @VibrationEffect.Composition.Primitive int... primitiveIds) {
+        for (boolean supported : arePrimitivesSupported(primitiveIds)) {
+            if (!supported) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
      * Turn the vibrator off.
      */
     @RequiresPermission(android.Manifest.permission.VIBRATE)
diff --git a/core/java/android/os/connectivity/WifiActivityEnergyInfo.java b/core/java/android/os/connectivity/WifiActivityEnergyInfo.java
index 664b6c8..016cc2f 100644
--- a/core/java/android/os/connectivity/WifiActivityEnergyInfo.java
+++ b/core/java/android/os/connectivity/WifiActivityEnergyInfo.java
@@ -16,7 +16,9 @@
 
 package android.os.connectivity;
 
+import android.annotation.ElapsedRealtimeLong;
 import android.annotation.IntDef;
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.app.ActivityThread;
@@ -37,14 +39,20 @@
  */
 @SystemApi
 public final class WifiActivityEnergyInfo implements Parcelable {
-    private long mTimeSinceBootMillis;
+    @ElapsedRealtimeLong
+    private final long mTimeSinceBootMillis;
     @StackState
-    private int mStackState;
-    private long mControllerTxDurationMillis;
-    private long mControllerRxDurationMillis;
-    private long mControllerScanDurationMillis;
-    private long mControllerIdleDurationMillis;
-    private long mControllerEnergyUsedMicroJoules;
+    private final int mStackState;
+    @IntRange(from = 0)
+    private final long mControllerTxDurationMillis;
+    @IntRange(from = 0)
+    private final long mControllerRxDurationMillis;
+    @IntRange(from = 0)
+    private final long mControllerScanDurationMillis;
+    @IntRange(from = 0)
+    private final long mControllerIdleDurationMillis;
+    @IntRange(from = 0)
+    private final long mControllerEnergyUsedMicroJoules;
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
@@ -67,7 +75,7 @@
     /**
      * Constructor.
      *
-     * @param timeSinceBootMillis the time since boot, in milliseconds.
+     * @param timeSinceBootMillis the elapsed real time since boot, in milliseconds.
      * @param stackState The current state of the Wifi Stack. One of {@link #STACK_STATE_INVALID},
      *                   {@link #STACK_STATE_STATE_ACTIVE}, {@link #STACK_STATE_STATE_SCANNING},
      *                   or {@link #STACK_STATE_STATE_IDLE}.
@@ -78,23 +86,27 @@
      *                       receiving.
      */
     public WifiActivityEnergyInfo(
-            long timeSinceBootMillis,
+            @ElapsedRealtimeLong long timeSinceBootMillis,
             @StackState int stackState,
-            long txDurationMillis,
-            long rxDurationMillis,
-            long scanDurationMillis,
-            long idleDurationMillis) {
-        mTimeSinceBootMillis = timeSinceBootMillis;
-        mStackState = stackState;
-        mControllerTxDurationMillis = txDurationMillis;
-        mControllerRxDurationMillis = rxDurationMillis;
-        mControllerScanDurationMillis = scanDurationMillis;
-        mControllerIdleDurationMillis = idleDurationMillis;
+            @IntRange(from = 0) long txDurationMillis,
+            @IntRange(from = 0) long rxDurationMillis,
+            @IntRange(from = 0) long scanDurationMillis,
+            @IntRange(from = 0) long idleDurationMillis) {
 
+        this(timeSinceBootMillis,
+                stackState,
+                txDurationMillis,
+                rxDurationMillis,
+                scanDurationMillis,
+                idleDurationMillis,
+                calculateEnergyMicroJoules(txDurationMillis, rxDurationMillis, idleDurationMillis));
+    }
+
+    private static long calculateEnergyMicroJoules(
+            long txDurationMillis, long rxDurationMillis, long idleDurationMillis) {
         final Context context = ActivityThread.currentActivityThread().getSystemContext();
         if (context == null) {
-            mControllerEnergyUsedMicroJoules = 0L;
-            return;
+            return 0L;
         }
         // Calculate energy used using PowerProfile.
         PowerProfile powerProfile = new PowerProfile(context);
@@ -106,10 +118,28 @@
                 PowerProfile.POWER_WIFI_CONTROLLER_TX);
         final double voltage = powerProfile.getAveragePower(
                 PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
-        final long energyUsedMicroJoules = (long) ((mControllerTxDurationMillis * txCurrent
-                + mControllerRxDurationMillis * rxCurrent
-                + mControllerIdleDurationMillis * rxIdleCurrent)
+
+        return (long) ((txDurationMillis * txCurrent
+                + rxDurationMillis * rxCurrent
+                + idleDurationMillis * rxIdleCurrent)
                 * voltage);
+    }
+
+    /** @hide */
+    public WifiActivityEnergyInfo(
+            @ElapsedRealtimeLong long timeSinceBootMillis,
+            @StackState int stackState,
+            @IntRange(from = 0) long txDurationMillis,
+            @IntRange(from = 0) long rxDurationMillis,
+            @IntRange(from = 0) long scanDurationMillis,
+            @IntRange(from = 0) long idleDurationMillis,
+            @IntRange(from = 0) long energyUsedMicroJoules) {
+        mTimeSinceBootMillis = timeSinceBootMillis;
+        mStackState = stackState;
+        mControllerTxDurationMillis = txDurationMillis;
+        mControllerRxDurationMillis = rxDurationMillis;
+        mControllerScanDurationMillis = scanDurationMillis;
+        mControllerIdleDurationMillis = idleDurationMillis;
         mControllerEnergyUsedMicroJoules = energyUsedMicroJoules;
     }
 
@@ -158,16 +188,12 @@
         return 0;
     }
 
-    /** Get the timestamp (milliseconds since boot) of record creation. */
+    /** Get the timestamp (elapsed real time milliseconds since boot) of record creation. */
+    @ElapsedRealtimeLong
     public long getTimeSinceBootMillis() {
         return mTimeSinceBootMillis;
     }
 
-    /** Set the timestamp (milliseconds since boot) of record creation. */
-    public void setTimeSinceBootMillis(long timeSinceBootMillis) {
-        mTimeSinceBootMillis = timeSinceBootMillis;
-    }
-
     /**
      * Get the Wifi stack reported state. One of {@link #STACK_STATE_INVALID},
      * {@link #STACK_STATE_STATE_ACTIVE}, {@link #STACK_STATE_STATE_SCANNING},
@@ -178,66 +204,40 @@
         return mStackState;
     }
 
-    /**
-     * Set the Wifi stack reported state. One of {@link #STACK_STATE_INVALID},
-     * {@link #STACK_STATE_STATE_ACTIVE}, {@link #STACK_STATE_STATE_SCANNING},
-     * {@link #STACK_STATE_STATE_IDLE}.
-     */
-    public void setStackState(@StackState int stackState) {
-        mStackState = stackState;
-    }
-
     /** Get the Wifi transmission duration, in milliseconds. */
+    @IntRange(from = 0)
     public long getControllerTxDurationMillis() {
         return mControllerTxDurationMillis;
     }
 
-    /** Set the Wifi transmission duration, in milliseconds. */
-    public void setControllerTxDurationMillis(long controllerTxDurationMillis) {
-        mControllerTxDurationMillis = controllerTxDurationMillis;
-    }
-
     /** Get the Wifi receive duration, in milliseconds. */
+    @IntRange(from = 0)
     public long getControllerRxDurationMillis() {
         return mControllerRxDurationMillis;
     }
 
-    /** Set the Wifi receive duration, in milliseconds. */
-    public void setControllerRxDurationMillis(long controllerRxDurationMillis) {
-        mControllerRxDurationMillis = controllerRxDurationMillis;
-    }
-
     /** Get the Wifi scan duration, in milliseconds. */
+    @IntRange(from = 0)
     public long getControllerScanDurationMillis() {
         return mControllerScanDurationMillis;
     }
 
-    /** Set the Wifi scan duration, in milliseconds. */
-    public void setControllerScanDurationMillis(long controllerScanDurationMillis) {
-        mControllerScanDurationMillis = controllerScanDurationMillis;
-    }
-
     /** Get the Wifi idle duration, in milliseconds. */
+    @IntRange(from = 0)
     public long getControllerIdleDurationMillis() {
         return mControllerIdleDurationMillis;
     }
 
-    /** Set the Wifi idle duration, in milliseconds. */
-    public void setControllerIdleDurationMillis(long controllerIdleDurationMillis) {
-        mControllerIdleDurationMillis = controllerIdleDurationMillis;
-    }
-
     /** Get the energy consumed by Wifi, in microjoules. */
+    @IntRange(from = 0)
     public long getControllerEnergyUsedMicroJoules() {
         return mControllerEnergyUsedMicroJoules;
     }
 
-    /** Set the energy consumed by Wifi, in microjoules. */
-    public void setControllerEnergyUsedMicroJoules(long controllerEnergyUsedMicroJoules) {
-        mControllerEnergyUsedMicroJoules = controllerEnergyUsedMicroJoules;
-    }
-
-    /** Returns true if the record is valid, false otherwise. */
+    /**
+     * Returns true if the record is valid, false otherwise.
+     * @hide
+     */
     public boolean isValid() {
         return mControllerTxDurationMillis >= 0
                 && mControllerRxDurationMillis >= 0
diff --git a/core/java/android/os/connectivity/WifiBatteryStats.java b/core/java/android/os/connectivity/WifiBatteryStats.java
index 895d837..3c30f63 100644
--- a/core/java/android/os/connectivity/WifiBatteryStats.java
+++ b/core/java/android/os/connectivity/WifiBatteryStats.java
@@ -15,11 +15,13 @@
  */
 package android.os.connectivity;
 
+import static android.os.BatteryStats.NUM_WIFI_SIGNAL_STRENGTH_BINS;
+import static android.os.BatteryStatsManager.NUM_WIFI_STATES;
+import static android.os.BatteryStatsManager.NUM_WIFI_SUPPL_STATES;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.os.BatteryStats;
-import android.os.BatteryStatsManager;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -33,31 +35,50 @@
  */
 @SystemApi
 public final class WifiBatteryStats implements Parcelable {
-    private long mLoggingDurationMillis = 0;
-    private long mKernelActiveTimeMillis = 0;
-    private long mNumPacketsTx = 0;
-    private long mNumBytesTx = 0;
-    private long mNumPacketsRx = 0;
-    private long mNumBytesRx = 0;
-    private long mSleepTimeMillis = 0;
-    private long mScanTimeMillis = 0;
-    private long mIdleTimeMillis = 0;
-    private long mRxTimeMillis = 0;
-    private long mTxTimeMillis = 0;
-    private long mEnergyConsumedMaMillis = 0;
-    private long mNumAppScanRequest = 0;
-    private long[] mTimeInStateMillis =
-        new long[BatteryStatsManager.NUM_WIFI_STATES];
-    private long[] mTimeInSupplicantStateMillis =
-        new long[BatteryStatsManager.NUM_WIFI_SUPPL_STATES];
-    private long[] mTimeInRxSignalStrengthLevelMillis =
-        new long[BatteryStats.NUM_WIFI_SIGNAL_STRENGTH_BINS];
-    private long mMonitoredRailChargeConsumedMaMillis = 0;
+    private final long mLoggingDurationMillis;
+    private final long mKernelActiveTimeMillis;
+    private final long mNumPacketsTx;
+    private final long mNumBytesTx;
+    private final long mNumPacketsRx;
+    private final long mNumBytesRx;
+    private final long mSleepTimeMillis;
+    private final long mScanTimeMillis;
+    private final long mIdleTimeMillis;
+    private final long mRxTimeMillis;
+    private final long mTxTimeMillis;
+    private final long mEnergyConsumedMaMillis;
+    private final long mAppScanRequestCount;
+    private final long[] mTimeInStateMillis;
+    private final long[] mTimeInSupplicantStateMillis;
+    private final long[] mTimeInRxSignalStrengthLevelMillis;
+    private final long mMonitoredRailChargeConsumedMaMillis;
 
     public static final @NonNull Parcelable.Creator<WifiBatteryStats> CREATOR =
             new Parcelable.Creator<WifiBatteryStats>() {
                 public WifiBatteryStats createFromParcel(Parcel in) {
-                    return new WifiBatteryStats(in);
+                    long loggingDurationMillis = in.readLong();
+                    long kernelActiveTimeMillis = in.readLong();
+                    long numPacketsTx = in.readLong();
+                    long numBytesTx = in.readLong();
+                    long numPacketsRx = in.readLong();
+                    long numBytesRx = in.readLong();
+                    long sleepTimeMillis = in.readLong();
+                    long scanTimeMillis = in.readLong();
+                    long idleTimeMillis = in.readLong();
+                    long rxTimeMillis = in.readLong();
+                    long txTimeMillis = in.readLong();
+                    long energyConsumedMaMillis = in.readLong();
+                    long appScanRequestCount = in.readLong();
+                    long[] timeInStateMillis = in.createLongArray();
+                    long[] timeInRxSignalStrengthLevelMillis = in.createLongArray();
+                    long[] timeInSupplicantStateMillis = in.createLongArray();
+                    long monitoredRailChargeConsumedMaMillis = in.readLong();
+                    return new WifiBatteryStats(loggingDurationMillis, kernelActiveTimeMillis,
+                            numPacketsTx, numBytesTx, numPacketsRx, numBytesRx, sleepTimeMillis,
+                            scanTimeMillis, idleTimeMillis, rxTimeMillis, txTimeMillis,
+                            energyConsumedMaMillis, appScanRequestCount, timeInStateMillis,
+                            timeInRxSignalStrengthLevelMillis, timeInSupplicantStateMillis,
+                            monitoredRailChargeConsumedMaMillis);
                 }
 
                 public WifiBatteryStats[] newArray(int size) {
@@ -84,7 +105,7 @@
         out.writeLong(mRxTimeMillis);
         out.writeLong(mTxTimeMillis);
         out.writeLong(mEnergyConsumedMaMillis);
-        out.writeLong(mNumAppScanRequest);
+        out.writeLong(mAppScanRequestCount);
         out.writeLongArray(mTimeInStateMillis);
         out.writeLongArray(mTimeInRxSignalStrengthLevelMillis);
         out.writeLongArray(mTimeInSupplicantStateMillis);
@@ -108,7 +129,7 @@
                 && this.mRxTimeMillis == otherStats.mRxTimeMillis
                 && this.mTxTimeMillis == otherStats.mTxTimeMillis
                 && this.mEnergyConsumedMaMillis == otherStats.mEnergyConsumedMaMillis
-                && this.mNumAppScanRequest == otherStats.mNumAppScanRequest
+                && this.mAppScanRequestCount == otherStats.mAppScanRequestCount
                 && Arrays.equals(this.mTimeInStateMillis, otherStats.mTimeInStateMillis)
                 && Arrays.equals(this.mTimeInSupplicantStateMillis,
                     otherStats.mTimeInSupplicantStateMillis)
@@ -123,33 +144,42 @@
         return Objects.hash(mLoggingDurationMillis, mKernelActiveTimeMillis, mNumPacketsTx,
                 mNumBytesTx, mNumPacketsRx, mNumBytesRx, mSleepTimeMillis, mScanTimeMillis,
                 mIdleTimeMillis, mRxTimeMillis, mTxTimeMillis, mEnergyConsumedMaMillis,
-                mNumAppScanRequest, Arrays.hashCode(mTimeInStateMillis),
+                mAppScanRequestCount, Arrays.hashCode(mTimeInStateMillis),
                 Arrays.hashCode(mTimeInSupplicantStateMillis),
                 Arrays.hashCode(mTimeInRxSignalStrengthLevelMillis),
                 mMonitoredRailChargeConsumedMaMillis);
     }
 
     /** @hide **/
-    public WifiBatteryStats() {}
-
-    private void readFromParcel(Parcel in) {
-        mLoggingDurationMillis = in.readLong();
-        mKernelActiveTimeMillis = in.readLong();
-        mNumPacketsTx = in.readLong();
-        mNumBytesTx = in.readLong();
-        mNumPacketsRx = in.readLong();
-        mNumBytesRx = in.readLong();
-        mSleepTimeMillis = in.readLong();
-        mScanTimeMillis = in.readLong();
-        mIdleTimeMillis = in.readLong();
-        mRxTimeMillis = in.readLong();
-        mTxTimeMillis = in.readLong();
-        mEnergyConsumedMaMillis = in.readLong();
-        mNumAppScanRequest = in.readLong();
-        in.readLongArray(mTimeInStateMillis);
-        in.readLongArray(mTimeInRxSignalStrengthLevelMillis);
-        in.readLongArray(mTimeInSupplicantStateMillis);
-        mMonitoredRailChargeConsumedMaMillis = in.readLong();
+    public WifiBatteryStats(long loggingDurationMillis, long kernelActiveTimeMillis,
+            long numPacketsTx, long numBytesTx, long numPacketsRx, long numBytesRx,
+            long sleepTimeMillis, long scanTimeMillis, long idleTimeMillis, long rxTimeMillis,
+            long txTimeMillis, long energyConsumedMaMillis, long appScanRequestCount,
+            @NonNull long[] timeInStateMillis, @NonNull long [] timeInRxSignalStrengthLevelMillis,
+            @NonNull long[] timeInSupplicantStateMillis, long monitoredRailChargeConsumedMaMillis) {
+        mLoggingDurationMillis = loggingDurationMillis;
+        mKernelActiveTimeMillis = kernelActiveTimeMillis;
+        mNumPacketsTx = numPacketsTx;
+        mNumBytesTx = numBytesTx;
+        mNumPacketsRx = numPacketsRx;
+        mNumBytesRx = numBytesRx;
+        mSleepTimeMillis = sleepTimeMillis;
+        mScanTimeMillis = scanTimeMillis;
+        mIdleTimeMillis = idleTimeMillis;
+        mRxTimeMillis = rxTimeMillis;
+        mTxTimeMillis = txTimeMillis;
+        mEnergyConsumedMaMillis = energyConsumedMaMillis;
+        mAppScanRequestCount = appScanRequestCount;
+        mTimeInStateMillis = Arrays.copyOfRange(
+                timeInStateMillis, 0,
+                Math.min(timeInStateMillis.length, NUM_WIFI_STATES));
+        mTimeInRxSignalStrengthLevelMillis = Arrays.copyOfRange(
+                timeInRxSignalStrengthLevelMillis, 0,
+                Math.min(timeInRxSignalStrengthLevelMillis.length, NUM_WIFI_SIGNAL_STRENGTH_BINS));
+        mTimeInSupplicantStateMillis = Arrays.copyOfRange(
+                timeInSupplicantStateMillis, 0,
+                Math.min(timeInSupplicantStateMillis.length, NUM_WIFI_SUPPL_STATES));
+        mMonitoredRailChargeConsumedMaMillis = monitoredRailChargeConsumedMaMillis;
     }
 
     /**
@@ -182,7 +212,7 @@
     }
 
     /**
-     * Returns the number of packets received over wifi within
+     * Returns the number of bytes transmitted over wifi within
      * {@link #getLoggingDurationMillis()}.
      *
      * @return Number of packets received.
@@ -192,7 +222,7 @@
     }
 
     /**
-     * Returns the number of bytes transmitted over wifi within
+     * Returns the number of packets received over wifi within
      * {@link #getLoggingDurationMillis()}.
      *
      * @return Number of bytes transmitted.
@@ -262,7 +292,7 @@
     }
 
     /**
-     * Returns an estimation of energy consumed by wifi chip within
+     * Returns an estimation of energy consumed in millis by wifi chip within
      * {@link #getLoggingDurationMillis()}.
      *
      * @return Energy consumed in millis.
@@ -276,8 +306,8 @@
      *
      * @return Number of app scans.
      */
-    public long getNumAppScanRequest() {
-        return mNumAppScanRequest;
+    public long getAppScanRequestCount() {
+        return mAppScanRequestCount;
     }
 
     /**
@@ -288,113 +318,4 @@
     public long getMonitoredRailChargeConsumedMaMillis() {
         return mMonitoredRailChargeConsumedMaMillis;
     }
-
-    /** @hide */
-    public void setLoggingDurationMillis(long t) {
-        mLoggingDurationMillis = t;
-        return;
-    }
-
-    /** @hide */
-    public void setKernelActiveTimeMillis(long t) {
-        mKernelActiveTimeMillis = t;
-        return;
-    }
-
-    /** @hide */
-    public void setNumPacketsTx(long n) {
-        mNumPacketsTx = n;
-        return;
-    }
-
-    /** @hide */
-    public void setNumBytesTx(long b) {
-        mNumBytesTx = b;
-        return;
-    }
-
-    /** @hide */
-    public void setNumPacketsRx(long n) {
-        mNumPacketsRx = n;
-        return;
-    }
-
-    /** @hide */
-    public void setNumBytesRx(long b) {
-        mNumBytesRx = b;
-        return;
-    }
-
-    /** @hide */
-    public void setSleepTimeMillis(long t) {
-        mSleepTimeMillis = t;
-        return;
-    }
-
-    /** @hide */
-    public void setScanTimeMillis(long t) {
-        mScanTimeMillis = t;
-        return;
-    }
-
-    /** @hide */
-    public void setIdleTimeMillis(long t) {
-        mIdleTimeMillis = t;
-        return;
-    }
-
-    /** @hide */
-    public void setRxTimeMillis(long t) {
-        mRxTimeMillis = t;
-        return;
-    }
-
-    /** @hide */
-    public void setTxTimeMillis(long t) {
-        mTxTimeMillis = t;
-        return;
-    }
-
-    /** @hide */
-    public void setEnergyConsumedMaMillis(long e) {
-        mEnergyConsumedMaMillis = e;
-        return;
-    }
-
-    /** @hide */
-    public void setNumAppScanRequest(long n) {
-        mNumAppScanRequest = n;
-        return;
-    }
-
-    /** @hide */
-    public void setTimeInStateMillis(long[] t) {
-        mTimeInStateMillis = Arrays.copyOfRange(t, 0,
-                Math.min(t.length, BatteryStatsManager.NUM_WIFI_STATES));
-        return;
-    }
-
-    /** @hide */
-    public void setTimeInRxSignalStrengthLevelMillis(long[] t) {
-        mTimeInRxSignalStrengthLevelMillis = Arrays.copyOfRange(t, 0,
-                Math.min(t.length, BatteryStats.NUM_WIFI_SIGNAL_STRENGTH_BINS));
-        return;
-    }
-
-    /** @hide */
-    public void setTimeInSupplicantStateMillis(long[] t) {
-        mTimeInSupplicantStateMillis = Arrays.copyOfRange(
-                t, 0, Math.min(t.length, BatteryStatsManager.NUM_WIFI_SUPPL_STATES));
-        return;
-    }
-
-    /** @hide */
-    public void setMonitoredRailChargeConsumedMaMillis(long monitoredRailEnergyConsumedMaMillis) {
-        mMonitoredRailChargeConsumedMaMillis = monitoredRailEnergyConsumedMaMillis;
-        return;
-    }
-
-    private WifiBatteryStats(Parcel in) {
-        readFromParcel(in);
-    }
 }
diff --git a/core/java/android/os/incremental/IIncrementalManager.aidl b/core/java/android/os/incremental/IIncrementalManager.aidl
index 17a310a..b415bc0 100644
--- a/core/java/android/os/incremental/IIncrementalManager.aidl
+++ b/core/java/android/os/incremental/IIncrementalManager.aidl
@@ -33,5 +33,7 @@
     boolean startDataLoader(int mountId);
     void showHealthBlockedUI(int mountId);
     void destroyDataLoader(int mountId);
-    void newFileForDataLoader(int mountId, long inode, in byte[] metadata);
+
+    // fileId is a 16 byte long identifier.
+    void newFileForDataLoader(int mountId, in byte[] fileId, in byte[] metadata);
 }
diff --git a/core/java/android/os/incremental/IIncrementalManagerNative.aidl b/core/java/android/os/incremental/IIncrementalManagerNative.aidl
index 14215b1..2b6cd14 100644
--- a/core/java/android/os/incremental/IIncrementalManagerNative.aidl
+++ b/core/java/android/os/incremental/IIncrementalManagerNative.aidl
@@ -17,6 +17,7 @@
 package android.os.incremental;
 
 import android.content.pm.DataLoaderParamsParcel;
+import android.os.incremental.IncrementalNewFileParams;
 
 /** @hide */
 interface IIncrementalManagerNative {
@@ -40,7 +41,7 @@
      */
     const int BIND_TEMPORARY = 0;
     const int BIND_PERMANENT = 1;
-    int makeBindMount(int storageId, in @utf8InCpp String pathUnderStorage, in @utf8InCpp String targetFullPath, int bindType);
+    int makeBindMount(int storageId, in @utf8InCpp String sourcePath, in @utf8InCpp String targetFullPath, int bindType);
 
     /**
      * Deletes an existing bind mount on a path under a storage. Returns 0 on success, and -errno on failure.
@@ -48,49 +49,50 @@
     int deleteBindMount(int storageId, in @utf8InCpp String targetFullPath);
 
     /**
-     * Creates a directory under a storage. The target directory is specified by its relative path under the storage.
+     * Creates a directory under a storage. The target directory is specified by its path.
      */
-    int makeDirectory(int storageId, in @utf8InCpp String pathUnderStorage);
+    int makeDirectory(int storageId, in @utf8InCpp String path);
 
     /**
-     * Recursively creates a directory under a storage. The target directory is specified by its relative path under the storage.
+     * Recursively creates a directory under a storage. The target directory is specified by its path.
      * All the parent directories of the target directory will be created if they do not exist already.
      */
-    int makeDirectories(int storageId, in @utf8InCpp String pathUnderStorage);
+    int makeDirectories(int storageId, in @utf8InCpp String path);
 
     /**
-     * Creates a file under a storage, specifying its name, size and metadata.
+     * Creates a file under a storage.
      */
-    int makeFile(int storageId, in @utf8InCpp String pathUnderStorage, long size, in byte[] metadata);
+    int makeFile(int storageId, in @utf8InCpp String path, in IncrementalNewFileParams params);
 
     /**
      * Creates a file under a storage. Content of the file is from a range inside another file.
-     * Both files are specified by relative paths under storage.
+     * Both files are specified by their paths.
      */
-    int makeFileFromRange(int storageId, in @utf8InCpp String targetPathUnderStorage, in @utf8InCpp String sourcePathUnderStorage, long start, long end);
+    int makeFileFromRange(int storageId, in @utf8InCpp String targetPath, in @utf8InCpp String sourcePath, long start, long end);
 
     /**
      * Creates a hard link between two files in two storage instances.
-     * Source and dest specified by parent storage IDs and their relative paths under the storage.
+     * Source and dest specified by parent storage IDs and their paths.
      * The source and dest storage instances should be in the same fs mount.
      * Note: destStorageId can be the same as sourceStorageId.
      */
-    int makeLink(int sourceStorageId, in @utf8InCpp String sourcePathUnderStorage, int destStorageId, in @utf8InCpp String destPathUnderStorage);
+    int makeLink(int sourceStorageId, in @utf8InCpp String sourcePath, int destStorageId, in @utf8InCpp String destPath);
 
     /**
-     * Deletes a hard link in a storage, specified by the relative path of the link target under storage.
+     * Deletes a hard link in a storage, specified by its path.
      */
-    int unlink(int storageId, in @utf8InCpp String pathUnderStorage);
+    int unlink(int storageId, in @utf8InCpp String path);
 
     /**
-     * Checks if a file's certain range is loaded. File is specified by relative file path under storage.
+     * Checks if a file's certain range is loaded. File is specified by its path.
      */
-    boolean isFileRangeLoaded(int storageId, in @utf8InCpp String pathUnderStorage, long start, long end);
+    boolean isFileRangeLoaded(int storageId, in @utf8InCpp String path, long start, long end);
 
     /**
-     * Reads the metadata of a file. File is specified by relative path under storage.
+     * Reads the metadata of a file. File is specified by either its path or 16 byte id.
      */
-    byte[] getFileMetadata(int storageId, in @utf8InCpp String pathUnderStorage);
+    byte[] getMetadataByPath(int storageId, in @utf8InCpp String path);
+    byte[] getMetadataById(int storageId, in byte[] fileId);
 
     /**
      * Starts loading data for a storage.
diff --git a/core/java/android/os/incremental/IncrementalFileStorages.java b/core/java/android/os/incremental/IncrementalFileStorages.java
index 63335a0..a0bfc1b 100644
--- a/core/java/android/os/incremental/IncrementalFileStorages.java
+++ b/core/java/android/os/incremental/IncrementalFileStorages.java
@@ -134,8 +134,8 @@
         }
 
         if (!new File(mDefaultDir, apk.getName()).exists()) {
-            mDefaultStorage.makeFile(apk.getName(), apk.getSize(),
-                    apk.getMetadata());
+            mDefaultStorage.makeFile(apk.getName(), apk.getSize(), null,
+                    apk.getMetadata(), 0, null, null, null);
         }
         // Assuming APK files are already named properly, e.g., "base.apk"
         mDefaultStorage.makeLink(apk.getName(), mApkStorage, apk.getName());
@@ -167,7 +167,8 @@
             current += '/';
         }
         String libFilePath = current + Paths.get(lib.getName()).getFileName();
-        mDefaultStorage.makeFile(libFilePath, lib.getSize(), lib.getMetadata());
+        mDefaultStorage.makeFile(libFilePath, lib.getSize(), null, lib.getMetadata(), 0, null, null,
+                                 null);
         mDefaultStorage.makeLink(libFilePath, mApkStorage, libFilePath);
     }
 
@@ -183,7 +184,8 @@
                     IncrementalManager.CREATE_MODE_CREATE
                             | IncrementalManager.CREATE_MODE_TEMPORARY_BIND);
         }
-        mDefaultStorage.makeFile(obb.getName(), obb.getSize(), obb.getMetadata());
+        mDefaultStorage.makeFile(obb.getName(), obb.getSize(), null, obb.getMetadata(), 0, null,
+                                 null, null);
         mDefaultStorage.makeLink(obb.getName(), mObbStorage, obb.getName());
     }
 
diff --git a/core/java/android/os/incremental/IncrementalFileSystemControlParcel.aidl b/core/java/android/os/incremental/IncrementalFileSystemControlParcel.aidl
index 0ae353d..6018ad1 100644
--- a/core/java/android/os/incremental/IncrementalFileSystemControlParcel.aidl
+++ b/core/java/android/os/incremental/IncrementalFileSystemControlParcel.aidl
@@ -17,11 +17,12 @@
 package android.os.incremental;
 
 /**
- * Wraps two file descriptors that Incremental Service uses to communicate
+ * Wraps the file descriptors Incremental Service uses to communicate
  * with Incremental FileSystem.
  * @hide
  */
 parcelable IncrementalFileSystemControlParcel {
-    @nullable ParcelFileDescriptor cmd;
-    @nullable ParcelFileDescriptor log;
+    ParcelFileDescriptor cmd;
+    ParcelFileDescriptor pendingReads;
+    ParcelFileDescriptor log;
 }
diff --git a/core/java/com/android/internal/car/ICarStatsService.aidl b/core/java/android/os/incremental/IncrementalNewFileParams.aidl
similarity index 60%
rename from core/java/com/android/internal/car/ICarStatsService.aidl
rename to core/java/android/os/incremental/IncrementalNewFileParams.aidl
index 170b448..182732c 100644
--- a/core/java/com/android/internal/car/ICarStatsService.aidl
+++ b/core/java/android/os/incremental/IncrementalNewFileParams.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,18 +14,18 @@
  * limitations under the License.
  */
 
-package com.android.internal.car;
+package android.os.incremental;
 
-import android.os.StatsLogEventWrapper;
+import android.os.incremental.IncrementalSignature;
 
 /**
- * Interface for pulling statsd atoms from automotive devices.
- *
+ * All the parameters to create a new file on IncFS
+ * FileId is a 16 byte-long identifier.
  * @hide
  */
-interface ICarStatsService {
-    /**
-     * Pull the specified atom. Results will be sent to statsd when complete.
-     */
-    StatsLogEventWrapper[] pullData(int atomId);
+parcelable IncrementalNewFileParams {
+    long size;
+    byte[] fileId;
+    byte[] metadata;
+    @nullable IncrementalSignature signature;
 }
diff --git a/core/java/android/os/incremental/IncrementalSignature.aidl b/core/java/android/os/incremental/IncrementalSignature.aidl
new file mode 100644
index 0000000..729e8e5
--- /dev/null
+++ b/core/java/android/os/incremental/IncrementalSignature.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.incremental;
+
+/** {@hide} */
+parcelable IncrementalSignature {
+    /*
+     * Stable AIDL doesn't support constants, but here's the possible values
+     *   const int HASH_ALGO_NONE = 0;
+     *   const int HASH_ALGO_SHA256 = 1;
+    */
+
+    int hashAlgorithm = 0;
+    byte[] rootHash;
+    byte[] additionalData;
+    byte[] signature;
+}
diff --git a/core/java/android/os/incremental/IncrementalStorage.java b/core/java/android/os/incremental/IncrementalStorage.java
index 2750868..91dda08 100644
--- a/core/java/android/os/incremental/IncrementalStorage.java
+++ b/core/java/android/os/incremental/IncrementalStorage.java
@@ -22,6 +22,8 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.UUID;
 
 /**
  * Provides operations on an Incremental File System directory, using IncrementalServiceNative.
@@ -64,14 +66,14 @@
      * Temporarily bind-mounts a subdir under the current storage directory to a target directory.
      * The bind-mount will NOT be preserved between device reboots.
      *
-     * @param sourcePathUnderStorage Source path as a relative path under current storage
-     *                               directory.
-     * @param targetPath             Absolute path to the target directory.
+     * @param sourcePath Source path as a relative path under current storage
+     *                   directory.
+     * @param targetPath Absolute path to the target directory.
      */
-    public void bind(@NonNull String sourcePathUnderStorage, @NonNull String targetPath)
+    public void bind(@NonNull String sourcePath, @NonNull String targetPath)
             throws IOException {
         try {
-            int res = mService.makeBindMount(mId, sourcePathUnderStorage, targetPath,
+            int res = mService.makeBindMount(mId, sourcePath, targetPath,
                     IIncrementalManagerNative.BIND_TEMPORARY);
             if (res < 0) {
                 throw new IOException("bind() failed with errno " + -res);
@@ -96,13 +98,13 @@
      * Permanently bind-mounts a subdir under the current storage directory to a target directory.
      * The bind-mount WILL be preserved between device reboots.
      *
-     * @param sourcePathUnderStorage Relative path under the current storage directory.
-     * @param targetPath             Absolute path to the target directory.
+     * @param sourcePath Relative path under the current storage directory.
+     * @param targetPath Absolute path to the target directory.
      */
-    public void bindPermanent(@NonNull String sourcePathUnderStorage, @NonNull String targetPath)
+    public void bindPermanent(@NonNull String sourcePath, @NonNull String targetPath)
             throws IOException {
         try {
-            int res = mService.makeBindMount(mId, sourcePathUnderStorage, targetPath,
+            int res = mService.makeBindMount(mId, sourcePath, targetPath,
                     IIncrementalManagerNative.BIND_PERMANENT);
             if (res < 0) {
                 throw new IOException("bind() permanent failed with errno " + -res);
@@ -131,11 +133,11 @@
     /**
      * Creates a sub-directory under the current storage directory.
      *
-     * @param pathUnderStorage Relative path of the sub-directory, e.g., "subdir"
+     * @param path Relative path of the sub-directory, e.g., "subdir"
      */
-    public void makeDirectory(@NonNull String pathUnderStorage) throws IOException {
+    public void makeDirectory(@NonNull String path) throws IOException {
         try {
-            int res = mService.makeDirectory(mId, pathUnderStorage);
+            int res = mService.makeDirectory(mId, path);
             if (res < 0) {
                 throw new IOException("makeDirectory() failed with errno " + -res);
             }
@@ -148,11 +150,11 @@
      * Creates a sub-directory under the current storage directory. If its parent dirs do not exist,
      * create the parent dirs as well.
      *
-     * @param pathUnderStorage Relative path of the sub-directory, e.g., "subdir/subsubdir"
+     * @param path Full path.
      */
-    public void makeDirectories(@NonNull String pathUnderStorage) throws IOException {
+    public void makeDirectories(@NonNull String path) throws IOException {
         try {
-            int res = mService.makeDirectories(mId, pathUnderStorage);
+            int res = mService.makeDirectories(mId, path);
             if (res < 0) {
                 throw new IOException("makeDirectory() failed with errno " + -res);
             }
@@ -164,15 +166,27 @@
     /**
      * Creates a file under the current storage directory.
      *
-     * @param pathUnderStorage Relative path of the new file.
+     * @param path             Relative path of the new file.
      * @param size             Size of the new file in bytes.
      * @param metadata         Metadata bytes.
      */
-    public void makeFile(@NonNull String pathUnderStorage, long size,
-            @Nullable byte[] metadata) throws IOException {
+    public void makeFile(@NonNull String path, long size, @Nullable UUID id,
+            @Nullable byte[] metadata, int hashAlgorithm, @Nullable byte[] rootHash,
+            @Nullable byte[] additionalData, @Nullable byte[] signature) throws IOException {
         try {
-            int res = mService.makeFile(mId, pathUnderStorage, size, metadata);
-            if (res < 0) {
+            final IncrementalNewFileParams params = new IncrementalNewFileParams();
+            params.size = size;
+            params.metadata = metadata;
+            params.fileId = idToBytes(id);
+            if (hashAlgorithm != 0 || signature != null) {
+                params.signature = new IncrementalSignature();
+                params.signature.hashAlgorithm = hashAlgorithm;
+                params.signature.rootHash = rootHash;
+                params.signature.additionalData = additionalData;
+                params.signature.signature = signature;
+            }
+            int res = mService.makeFile(mId, path, params);
+            if (res != 0) {
                 throw new IOException("makeFile() failed with errno " + -res);
             }
         } catch (RemoteException e) {
@@ -184,15 +198,15 @@
      * Creates a file in Incremental storage. The content of the file is mapped from a range inside
      * a source file in the same storage.
      *
-     * @param destRelativePath   Target relative path under storage.
-     * @param sourceRelativePath Source relative path under storage.
+     * @param destPath           Target full path.
+     * @param sourcePath         Source full path.
      * @param rangeStart         Starting offset (in bytes) in the source file.
      * @param rangeEnd           Ending offset (in bytes) in the source file.
      */
-    public void makeFileFromRange(@NonNull String destRelativePath,
-            @NonNull String sourceRelativePath, long rangeStart, long rangeEnd) throws IOException {
+    public void makeFileFromRange(@NonNull String destPath,
+            @NonNull String sourcePath, long rangeStart, long rangeEnd) throws IOException {
         try {
-            int res = mService.makeFileFromRange(mId, destRelativePath, sourceRelativePath,
+            int res = mService.makeFileFromRange(mId, destPath, sourcePath,
                     rangeStart, rangeEnd);
             if (res < 0) {
                 throw new IOException("makeFileFromRange() failed, errno " + -res);
@@ -206,15 +220,15 @@
      * Creates a hard-link between two paths, which can be under different storages but in the same
      * Incremental File System.
      *
-     * @param sourcePathUnderStorage The relative path of the source.
-     * @param destStorage            The target storage of the link target.
-     * @param destPathUnderStorage   The relative path of the target.
+     * @param sourcePath    The absolute path of the source.
+     * @param destStorage   The target storage of the link target.
+     * @param destPath      The absolute path of the target.
      */
-    public void makeLink(@NonNull String sourcePathUnderStorage, IncrementalStorage destStorage,
-            @NonNull String destPathUnderStorage) throws IOException {
+    public void makeLink(@NonNull String sourcePath, IncrementalStorage destStorage,
+            @NonNull String destPath) throws IOException {
         try {
-            int res = mService.makeLink(mId, sourcePathUnderStorage, destStorage.getId(),
-                    destPathUnderStorage);
+            int res = mService.makeLink(mId, sourcePath, destStorage.getId(),
+                    destPath);
             if (res < 0) {
                 throw new IOException("makeLink() failed with errno " + -res);
             }
@@ -226,11 +240,11 @@
     /**
      * Deletes a hard-link under the current storage directory.
      *
-     * @param pathUnderStorage The relative path of the target.
+     * @param path The absolute path of the target.
      */
-    public void unlink(@NonNull String pathUnderStorage) throws IOException {
+    public void unlink(@NonNull String path) throws IOException {
         try {
-            int res = mService.unlink(mId, pathUnderStorage);
+            int res = mService.unlink(mId, path);
             if (res < 0) {
                 throw new IOException("unlink() failed with errno " + -res);
             }
@@ -242,13 +256,14 @@
     /**
      * Rename an old file name to a new file name under the current storage directory.
      *
-     * @param sourcePathUnderStorage Old file path as a relative path to the storage directory.
-     * @param destPathUnderStorage   New file path as a relative path to the storage directory.
+     * @param sourcepath Old file path as a full path to the storage directory.
+     * @param destpath   New file path as a full path to the storage directory.
      */
-    public void moveFile(@NonNull String sourcePathUnderStorage,
-            @NonNull String destPathUnderStorage) throws IOException {
+    public void moveFile(@NonNull String sourcepath,
+            @NonNull String destpath) throws IOException {
+        //TODO(zyy): implement using rename(2) when confirmed that IncFS supports it.
         try {
-            int res = mService.makeLink(mId, sourcePathUnderStorage, mId, destPathUnderStorage);
+            int res = mService.makeLink(mId, sourcepath, mId, destpath);
             if (res < 0) {
                 throw new IOException("moveFile() failed at makeLink(), errno " + -res);
             }
@@ -256,7 +271,7 @@
             e.rethrowFromSystemServer();
         }
         try {
-            mService.unlink(mId, sourcePathUnderStorage);
+            mService.unlink(mId, sourcepath);
         } catch (RemoteException ignored) {
         }
     }
@@ -274,7 +289,7 @@
             throw new IOException("moveDir() requires that destination dir already exists.");
         }
         try {
-            int res = mService.makeBindMount(mId, "", destPath,
+            int res = mService.makeBindMount(mId, sourcePath, destPath,
                     IIncrementalManagerNative.BIND_PERMANENT);
             if (res < 0) {
                 throw new IOException("moveDir() failed at making bind mount, errno " + -res);
@@ -291,24 +306,24 @@
     /**
      * Checks whether a file under the current storage directory is fully loaded.
      *
-     * @param pathUnderStorage The relative path of the file.
+     * @param path The relative path of the file.
      * @return True if the file is fully loaded.
      */
-    public boolean isFileFullyLoaded(@NonNull String pathUnderStorage) {
-        return isFileRangeLoaded(pathUnderStorage, 0, -1);
+    public boolean isFileFullyLoaded(@NonNull String path) {
+        return isFileRangeLoaded(path, 0, -1);
     }
 
     /**
      * Checks whether a range in a file if loaded.
      *
-     * @param pathUnderStorage The relative path of the file.
+     * @param path The relative path of the file.
      * @param start            The starting offset of the range.
      * @param end              The ending offset of the range.
      * @return True if the file is fully loaded.
      */
-    public boolean isFileRangeLoaded(@NonNull String pathUnderStorage, long start, long end) {
+    public boolean isFileRangeLoaded(@NonNull String path, long start, long end) {
         try {
-            return mService.isFileRangeLoaded(mId, pathUnderStorage, start, end);
+            return mService.isFileRangeLoaded(mId, path, start, end);
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
             return false;
@@ -318,13 +333,65 @@
     /**
      * Returns the metadata object of an IncFs File.
      *
-     * @param pathUnderStorage The relative path of the file.
+     * @param path The relative path of the file.
      * @return Byte array that contains metadata bytes.
      */
     @Nullable
-    public byte[] getFileMetadata(@NonNull String pathUnderStorage) {
+    public byte[] getFileMetadata(@NonNull String path) {
         try {
-            return mService.getFileMetadata(mId, pathUnderStorage);
+            return mService.getMetadataByPath(mId, path);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+            return null;
+        }
+    }
+
+    private static final int UUID_BYTE_SIZE = 16;
+
+    /**
+     * Converts UUID to a byte array usable for Incremental API calls
+     *
+     * @param id The id to convert
+     * @return Byte array that contains the same ID.
+     */
+    public static byte[] idToBytes(UUID id) {
+        if (id == null) {
+            return null;
+        }
+        final ByteBuffer buf = ByteBuffer.wrap(new byte[UUID_BYTE_SIZE]);
+        buf.putLong(id.getMostSignificantBits());
+        buf.putLong(id.getLeastSignificantBits());
+        return buf.array();
+    }
+
+    /**
+     * Converts UUID from a byte array usable for Incremental API calls
+     *
+     * @param bytes The id in byte array format, 16 bytes long
+     * @return UUID constructed from the byte array.
+     */
+    public static UUID bytesToId(byte[] bytes) {
+        if (bytes.length != UUID_BYTE_SIZE) {
+            throw new IllegalArgumentException("Expected array of size " + UUID_BYTE_SIZE
+                                               + ", got " + bytes.length);
+        }
+        final ByteBuffer buf = ByteBuffer.wrap(bytes);
+        long msb = buf.getLong();
+        long lsb = buf.getLong();
+        return new UUID(msb, lsb);
+    }
+
+    /**
+     * Returns the metadata object of an IncFs File.
+     *
+     * @param id The file id.
+     * @return Byte array that contains metadata bytes.
+     */
+    @Nullable
+    public byte[] getFileMetadata(@NonNull UUID id) {
+        try {
+            final byte[] rawId = idToBytes(id);
+            return mService.getMetadataById(mId, rawId);
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
             return null;
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index 5a1ba7f..4812ea9 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -266,6 +266,28 @@
         }
     }
 
+    /**
+     * Grant default permissions to currently enabled carrier apps
+     * @param packageNames Package names of the apps to be granted permissions
+     * @param user The user handle
+     * @param executor The executor for the callback
+     * @param callback The callback provided by caller to be notified when grant completes
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS)
+    public void grantDefaultPermissionsToEnabledCarrierApps(@NonNull String[] packageNames,
+            @NonNull UserHandle user, @NonNull @CallbackExecutor Executor executor,
+            @NonNull Consumer<Boolean> callback) {
+        try {
+            mPermissionManager.grantDefaultPermissionsToEnabledCarrierApps(packageNames,
+                    user.getIdentifier());
+            executor.execute(() -> callback.accept(true));
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+    }
+
     private List<SplitPermissionInfo> splitPermissionInfoListToNonParcelableList(
             List<SplitPermissionInfoParcelable> parcelableList) {
         final int size = parcelableList.size();
@@ -416,4 +438,4 @@
             e.rethrowFromSystemServer();
         }
     }
-}
+}
\ No newline at end of file
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 00b2feb..3e0b46b 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2721,6 +2721,7 @@
                                                 }
                                             }
                                         });
+                                        currentGeneration = generation;
                                     }
                                 }
                                 if (mGenerationTracker != null && currentGeneration ==
@@ -2801,14 +2802,7 @@
                         }
                         mValues.clear();
                     } else {
-                        boolean prefixCached = false;
-                        int size = mValues.size();
-                        for (int i = 0; i < size; ++i) {
-                            if (mValues.keyAt(i).startsWith(prefix)) {
-                                prefixCached = true;
-                                break;
-                            }
-                        }
+                        boolean prefixCached = mValues.containsKey(prefix);
                         if (prefixCached) {
                             if (!names.isEmpty()) {
                                 for (String name : names) {
@@ -2817,9 +2811,11 @@
                                     }
                                 }
                             } else {
-                                for (int i = 0; i < size; ++i) {
+                                for (int i = 0; i < mValues.size(); ++i) {
                                     String key = mValues.keyAt(i);
-                                    if (key.startsWith(prefix)) {
+                                    // Explicitly exclude the prefix as it is only there to
+                                    // signal that the prefix has been cached.
+                                    if (key.startsWith(prefix) && !key.equals(prefix)) {
                                         keyValues.put(key, mValues.get(key));
                                     }
                                 }
@@ -2907,12 +2903,15 @@
                                     }
                                 }
                             });
+                            currentGeneration = generation;
                         }
                     }
                     if (mGenerationTracker != null && currentGeneration
                             == mGenerationTracker.getCurrentGeneration()) {
                         // cache the complete list of flags for the namespace
                         mValues.putAll(flagsToValues);
+                        // Adding the prefix as a signal that the prefix is cached.
+                        mValues.put(prefix, null);
                     }
                 }
                 return keyValues;
@@ -8402,6 +8401,7 @@
          *
          * @hide
          */
+        @SystemApi
         public static final String CARRIER_APPS_HANDLED = "carrier_apps_handled";
 
         /**
@@ -9361,6 +9361,16 @@
         public static final String DEVELOPMENT_ENABLE_SIZECOMPAT_FREEFORM =
                 "enable_sizecompat_freeform";
 
+        /**
+         * If true, shadows drawn around the window will be rendered by the system compositor. If
+         * false, shadows will be drawn by the client by setting an elevation on the root view and
+         * the contents will be inset by the surface insets.
+         * (0 = false, 1 = true)
+         * @hide
+         */
+        public static final String DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR =
+                "render_shadows_in_compositor";
+
        /**
         * Whether user has enabled development settings.
         */
@@ -9736,6 +9746,15 @@
         */
        public static final String PACKAGE_VERIFIER_INCLUDE_ADB = "verifier_verify_adb_installs";
 
+        /**
+         * Run integrity checks for integrity rule providers.
+         * 0 = bypass integrity verification on installs from rule providers (default)
+         * 1 = perform integrity verification on installs from rule providers
+         * @hide
+         */
+        public static final String INTEGRITY_CHECK_INCLUDES_RULE_PROVIDER =
+                "verify_integrity_for_rule_provider";
+
        /**
         * Time since last fstrim (milliseconds) after which we force one to happen
         * during device startup.  If unset, the default is 3 days.
@@ -11081,6 +11100,15 @@
                 = "activity_starts_logging_enabled";
 
         /**
+         * Feature flag to enable or disable the foreground service starts logging feature.
+         * Type: int (0 for false, 1 for true)
+         * Default: 1
+         * @hide
+         */
+        public static final String FOREGROUND_SERVICE_STARTS_LOGGING_ENABLED =
+                "foreground_service_starts_logging_enabled";
+
+        /**
          * @hide
          * @see com.android.server.appbinding.AppBindingConstants
          */
@@ -14075,7 +14103,7 @@
          * @hide
          */
         @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
-        static Map<String, String> getStrings(@NonNull ContentResolver resolver,
+        public static Map<String, String> getStrings(@NonNull ContentResolver resolver,
                 @NonNull String namespace, @NonNull List<String> names) {
             List<String> compositeNames = new ArrayList<>(names.size());
             for (String name : names) {
@@ -14134,8 +14162,9 @@
          * @hide
          */
         @RequiresPermission(Manifest.permission.WRITE_DEVICE_CONFIG)
-        static boolean setStrings(@NonNull ContentResolver resolver, @NonNull String namespace,
-                @NonNull Map<String, String> keyValues) throws DeviceConfig.BadConfigException {
+        public static boolean setStrings(@NonNull ContentResolver resolver,
+                @NonNull String namespace, @NonNull Map<String, String> keyValues)
+                throws DeviceConfig.BadConfigException {
             HashMap<String, String> compositeKeyValueMap = new HashMap<>(keyValues.keySet().size());
             for (Map.Entry<String, String> entry : keyValues.entrySet()) {
                 compositeKeyValueMap.put(
@@ -14212,6 +14241,12 @@
             }
         }
 
+        /** @hide */
+        public static void clearProviderForTest() {
+            sProviderHolder.clearProviderForTest();
+            sNameValueCache.clearGenerationTrackerForTest();
+        }
+
         private static String createCompositeName(@NonNull String namespace, @NonNull String name) {
             Preconditions.checkNotNull(namespace);
             Preconditions.checkNotNull(name);
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 4537281..b6f5138 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -37,7 +37,6 @@
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
-import android.os.Parcel;
 import android.telephony.CarrierConfigManager;
 import android.telephony.Rlog;
 import android.telephony.ServiceState;
@@ -1297,17 +1296,6 @@
                           "android.provider.action.EXTERNAL_PROVIDER_CHANGE";
 
             /**
-             * Same as {@link #ACTION_DEFAULT_SMS_PACKAGE_CHANGED} but it's implicit (e.g. sent to
-             * all apps) and requires
-             * {@link android.Manifest.permission#MONITOR_DEFAULT_SMS_PACKAGE} to receive.
-             *
-             * @hide
-             */
-            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-            public static final String ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL =
-                    "android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL";
-
-            /**
              * Broadcast action: When SMS-MMS db is being created. If file-based encryption is
              * supported, this broadcast indicates creation of the db in credential-encrypted
              * storage. A boolean is specified in {@link #EXTRA_IS_INITIAL_CREATE} to indicate if
@@ -3746,6 +3734,7 @@
          * @deprecated this column is no longer supported, use {@link #NETWORK_TYPE_BITMASK} instead
          */
         @Deprecated
+        @SystemApi
         public static final String BEARER_BITMASK = "bearer_bitmask";
 
         /**
@@ -3795,6 +3784,7 @@
          * <p>Type: INTEGER</p>
          *@hide
          */
+        @SystemApi
         public static final String PROFILE_ID = "profile_id";
 
         /**
@@ -3995,6 +3985,7 @@
          *
          * @hide
          */
+        @SystemApi
         public static final String SKIP_464XLAT = "skip_464xlat";
 
         /**
@@ -4003,6 +3994,7 @@
          *
          * @hide
          */
+        @SystemApi
         public static final int SKIP_464XLAT_DEFAULT = -1;
 
         /**
@@ -4011,6 +4003,7 @@
          *
          * @hide
          */
+        @SystemApi
         public static final int SKIP_464XLAT_DISABLE = 0;
 
         /**
@@ -4019,6 +4012,7 @@
          *
          * @hide
          */
+        @SystemApi
         public static final int SKIP_464XLAT_ENABLE = 1;
 
 
@@ -4033,15 +4027,6 @@
         @Retention(RetentionPolicy.SOURCE)
         public @interface EditStatus {}
 
-        /** @hide */
-        @IntDef({
-                SKIP_464XLAT_DEFAULT,
-                SKIP_464XLAT_DISABLE,
-                SKIP_464XLAT_ENABLE,
-        })
-        @Retention(RetentionPolicy.SOURCE)
-        public @interface Skip464XlatStatus {}
-
         /**
          * Compat framework change ID for the APN db read permission change.
          *
@@ -4292,6 +4277,15 @@
         public static final String LANGUAGE_CODE = "language";
 
         /**
+         * Dats coding scheme of the message.
+         * <p>
+         * The data coding scheme (dcs) value defined in 3GPP TS 23.038 section 4
+         * </p>
+         * <P>Type: INTEGER</P>
+         */
+        public static final String DATA_CODING_SCHEME = "dcs";
+
+        /**
          * Message body.
          * <P>Type: TEXT</P>
          */
@@ -4379,18 +4373,32 @@
         public static final String DEFAULT_SORT_ORDER = DELIVERY_TIME + " DESC";
 
         /**
-         * The timestamp in millisecond of when the device received the message.
+         * The timestamp in millisecond, reported by {@link System#currentTimeMillis()}, when the
+         * device received the message.
          * <P>Type: BIGINT</P>
          */
         public static final String RECEIVED_TIME = "received_time";
 
         /**
+         * The timestamp in millisecond, reported by {@link System#currentTimeMillis()}, when
+         * location was checked last time. Note this is only applicable to geo-targeting message.
+         * For non geo-targeting message. the field will be set to -1.
+         * <P>Type: BIGINT</P>
+         */
+        public static final String LOCATION_CHECK_TIME = "location_check_time";
+        /**
          * Indicates that whether the message has been broadcasted to the application.
          * <P>Type: BOOLEAN</P>
          */
         public static final String MESSAGE_BROADCASTED = "message_broadcasted";
 
         /**
+         * Indicates that whether the message has been displayed to the user.
+         * <P>Type: BOOLEAN</P>
+         */
+        public static final String MESSAGE_DISPLAYED = "message_displayed";
+
+        /**
          * The Warning Area Coordinates Elements. This element is used for geo-fencing purpose.
          *
          * The geometry and its coordinates are separated vertical bar, the first item is the
@@ -4559,32 +4567,6 @@
         }
 
         /**
-         * Used to insert a ServiceState into the ServiceStateProvider as a ContentValues instance.
-         *
-         * @param state the ServiceState to convert into ContentValues
-         * @return the convertedContentValues instance
-         * @hide
-         */
-        public static ContentValues getContentValuesForServiceState(ServiceState state) {
-            ContentValues values = new ContentValues();
-            final Parcel p = Parcel.obtain();
-            state.writeToParcel(p, 0);
-            // Turn the parcel to byte array. Safe to do this because the content values were never
-            // written into a persistent storage. ServiceStateProvider keeps values in the memory.
-            values.put(SERVICE_STATE, p.marshall());
-            return values;
-        }
-
-        /**
-         * The current service state.
-         *
-         * This is the entire {@link ServiceState} object in byte array.
-         *
-         * @hide
-         */
-        public static final String SERVICE_STATE = "service_state";
-
-        /**
          * An integer value indicating the current voice service state.
          * <p>
          * Valid values: {@link ServiceState#STATE_IN_SERVICE},
@@ -4596,53 +4578,6 @@
         public static final String VOICE_REG_STATE = "voice_reg_state";
 
         /**
-         * An integer value indicating the current data service state.
-         * <p>
-         * Valid values: {@link ServiceState#STATE_IN_SERVICE},
-         * {@link ServiceState#STATE_OUT_OF_SERVICE}, {@link ServiceState#STATE_EMERGENCY_ONLY},
-         * {@link ServiceState#STATE_POWER_OFF}.
-         * <p>
-         * This is the same as {@link ServiceState#getDataRegState()}.
-         * @hide
-         */
-        public static final String DATA_REG_STATE = "data_reg_state";
-
-        /**
-         * An integer value indicating the current voice roaming type.
-         * <p>
-         * This is the same as {@link ServiceState#getVoiceRoamingType()}.
-         * @hide
-         */
-        public static final String VOICE_ROAMING_TYPE = "voice_roaming_type";
-
-        /**
-         * An integer value indicating the current data roaming type.
-         * <p>
-         * This is the same as {@link ServiceState#getDataRoamingType()}.
-         * @hide
-         */
-        public static final String DATA_ROAMING_TYPE = "data_roaming_type";
-
-        /**
-         * The current registered voice network operator name in long alphanumeric format.
-         * <p>
-         * This is the same as {@link ServiceState#getOperatorAlphaLong()}.
-         * @hide
-         */
-        public static final String VOICE_OPERATOR_ALPHA_LONG = "voice_operator_alpha_long";
-
-        /**
-         * The current registered operator name in short alphanumeric format.
-         * <p>
-         * In GSM/UMTS, short format can be up to 8 characters long. The current registered voice
-         * network operator name in long alphanumeric format.
-         * <p>
-         * This is the same as {@link ServiceState#getOperatorAlphaShort()}.
-         * @hide
-         */
-        public static final String VOICE_OPERATOR_ALPHA_SHORT = "voice_operator_alpha_short";
-
-        /**
          * The current registered operator numeric id.
          * <p>
          * In GSM/UMTS, numeric format is 3 digit country code plus 2 or 3 digit
@@ -4653,125 +4588,11 @@
         public static final String VOICE_OPERATOR_NUMERIC = "voice_operator_numeric";
 
         /**
-         * The current registered data network operator name in long alphanumeric format.
-         * <p>
-         * This is the same as {@link ServiceState#getOperatorAlphaLong()}.
-         * @hide
-         */
-        public static final String DATA_OPERATOR_ALPHA_LONG = "data_operator_alpha_long";
-
-        /**
-         * The current registered data network operator name in short alphanumeric format.
-         * <p>
-         * This is the same as {@link ServiceState#getOperatorAlphaShort()}.
-         * @hide
-         */
-        public static final String DATA_OPERATOR_ALPHA_SHORT = "data_operator_alpha_short";
-
-        /**
-         * The current registered data network operator numeric id.
-         * <p>
-         * This is the same as {@link ServiceState#getOperatorNumeric()}.
-         * @hide
-         */
-        public static final String DATA_OPERATOR_NUMERIC = "data_operator_numeric";
-
-        /**
          * The current network selection mode.
          * <p>
          * This is the same as {@link ServiceState#getIsManualSelection()}.
          */
         public static final String IS_MANUAL_NETWORK_SELECTION = "is_manual_network_selection";
-
-        /**
-         * This is the same as {@link ServiceState#getRilVoiceRadioTechnology()}.
-         * @hide
-         */
-        public static final String RIL_VOICE_RADIO_TECHNOLOGY = "ril_voice_radio_technology";
-
-        /**
-         * This is the same as {@link ServiceState#getRilDataRadioTechnology()}.
-         * @hide
-         */
-        public static final String RIL_DATA_RADIO_TECHNOLOGY = "ril_data_radio_technology";
-
-        /**
-         * This is the same as {@link ServiceState#getCssIndicator()}.
-         * @hide
-         */
-        public static final String CSS_INDICATOR = "css_indicator";
-
-        /**
-         * This is the same as {@link ServiceState#getCdmaNetworkId()}.
-         * @hide
-         */
-        public static final String NETWORK_ID = "network_id";
-
-        /**
-         * This is the same as {@link ServiceState#getCdmaSystemId()}.
-         * @hide
-         */
-        public static final String SYSTEM_ID = "system_id";
-
-        /**
-         * This is the same as {@link ServiceState#getCdmaRoamingIndicator()}.
-         * @hide
-         */
-        public static final String CDMA_ROAMING_INDICATOR = "cdma_roaming_indicator";
-
-        /**
-         * This is the same as {@link ServiceState#getCdmaDefaultRoamingIndicator()}.
-         * @hide
-         */
-        public static final String CDMA_DEFAULT_ROAMING_INDICATOR =
-                "cdma_default_roaming_indicator";
-
-        /**
-         * This is the same as {@link ServiceState#getCdmaEriIconIndex()}.
-         * @hide
-         */
-        public static final String CDMA_ERI_ICON_INDEX = "cdma_eri_icon_index";
-
-        /**
-         * This is the same as {@link ServiceState#getCdmaEriIconMode()}.
-         * @hide
-         */
-        public static final String CDMA_ERI_ICON_MODE = "cdma_eri_icon_mode";
-
-        /**
-         * This is the same as {@link ServiceState#isEmergencyOnly()}.
-         * @hide
-         */
-        public static final String IS_EMERGENCY_ONLY = "is_emergency_only";
-
-        /**
-         * This is the same as {@link ServiceState#getDataRoamingFromRegistration()}.
-         * @hide
-         */
-        public static final String IS_DATA_ROAMING_FROM_REGISTRATION =
-                "is_data_roaming_from_registration";
-
-        /**
-         * This is the same as {@link ServiceState#isUsingCarrierAggregation()}.
-         * @hide
-         */
-        public static final String IS_USING_CARRIER_AGGREGATION = "is_using_carrier_aggregation";
-
-        /**
-         * The current registered raw data network operator name in long alphanumeric format.
-         * <p>
-         * This is the same as {@link ServiceState#getOperatorAlphaLongRaw()}.
-         * @hide
-         */
-        public static final String OPERATOR_ALPHA_LONG_RAW = "operator_alpha_long_raw";
-
-        /**
-         * The current registered raw data network operator name in short alphanumeric format.
-         * <p>
-         * This is the same as {@link ServiceState#getOperatorAlphaShortRaw()}.
-         * @hide
-         */
-        public static final String OPERATOR_ALPHA_SHORT_RAW = "operator_alpha_short_raw";
     }
 
     /**
@@ -5299,6 +5120,12 @@
         public static final String WFC_IMS_ROAMING_ENABLED = "wfc_ims_roaming_enabled";
 
         /**
+         * Determines if the user has enabled IMS RCS User Capability Exchange (UCE) for this
+         * subscription.
+         */
+        public static final String IMS_RCS_UCE_ENABLED = "ims_rcs_uce_enabled";
+
+        /**
          * TelephonyProvider column name for whether a subscription is opportunistic, that is,
          * whether the network it connects to is limited in functionality or coverage.
          * For example, CBRS.
diff --git a/core/java/android/se/omapi/ISecureElementReader.aidl b/core/java/android/se/omapi/ISecureElementReader.aidl
index a312c44..41244ab 100644
--- a/core/java/android/se/omapi/ISecureElementReader.aidl
+++ b/core/java/android/se/omapi/ISecureElementReader.aidl
@@ -48,4 +48,10 @@
      */
     void closeSessions();
 
+    /**
+     * Closes all the sessions opened on this reader and resets the reader.
+     * All the channels opened by all these sessions will be closed.
+     * @return true if the reset is successful, false otherwise.
+     */
+    boolean reset();
 }
diff --git a/core/java/android/se/omapi/Reader.java b/core/java/android/se/omapi/Reader.java
index 80262f7..7f68d91 100644
--- a/core/java/android/se/omapi/Reader.java
+++ b/core/java/android/se/omapi/Reader.java
@@ -23,6 +23,8 @@
 package android.se.omapi;
 
 import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.os.RemoteException;
 import android.os.ServiceSpecificException;
 import android.util.Log;
@@ -150,4 +152,25 @@
             } catch (RemoteException ignore) { }
         }
     }
+
+    /**
+     * Close all the sessions opened on this reader and reset the reader.
+     * All the channels opened by all these sessions will be closed.
+     * @return <code>true</code> if reset success, <code>false</code> otherwise.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.SECURE_ELEMENT_PRIVILEGED)
+    public boolean reset() {
+        if (!mService.isConnected()) {
+            Log.e(TAG, "service is not connected");
+            return false;
+        }
+        synchronized (mLock) {
+            try {
+                closeSessions();
+                return mReader.reset();
+            } catch (RemoteException ignore) {return false;}
+        }
+    }
 }
diff --git a/core/java/android/security/net/config/WfaCertificateSource.java b/core/java/android/security/net/config/WfaCertificateSource.java
index f212ef8..545e4b0 100644
--- a/core/java/android/security/net/config/WfaCertificateSource.java
+++ b/core/java/android/security/net/config/WfaCertificateSource.java
@@ -23,12 +23,15 @@
  * @hide
  */
 public final class WfaCertificateSource extends DirectoryCertificateSource {
+    private static final String CACERTS_WFA_PATH =
+            "/apex/com.android.wifi/etc/security/cacerts_wfa";
+
     private static class NoPreloadHolder {
         private static final WfaCertificateSource INSTANCE = new WfaCertificateSource();
     }
 
     private WfaCertificateSource() {
-        super(new File(System.getenv("ANDROID_ROOT") + "/etc/security/cacerts_wfa"));
+        super(new File(CACERTS_WFA_PATH));
     }
 
     public static WfaCertificateSource getInstance() {
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index dc0f562..36f3a78 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -87,6 +87,7 @@
     private final @Nullable UserData mUserData;
     private final @Nullable int[] mCancelIds;
     private final boolean mSupportsInlineSuggestions;
+    private final @Nullable ParceledListSlice<InlinePresentation> mInlineActions;
 
     private FillResponse(@NonNull Builder builder) {
         mDatasets = (builder.mDatasets != null) ? new ParceledListSlice<>(builder.mDatasets) : null;
@@ -105,6 +106,8 @@
         mUserData = builder.mUserData;
         mCancelIds = builder.mCancelIds;
         mSupportsInlineSuggestions = builder.mSupportsInlineSuggestions;
+        mInlineActions = (builder.mInlineActions != null) ? new ParceledListSlice<>(
+                builder.mInlineActions) : null;
     }
 
     /** @hide */
@@ -202,6 +205,11 @@
         return mSupportsInlineSuggestions;
     }
 
+    /** @hide */
+    public @Nullable List<InlinePresentation> getInlineActions() {
+        return (mInlineActions != null) ? mInlineActions.getList() : null;
+    }
+
     /**
      * Builder for {@link FillResponse} objects. You must to provide at least
      * one dataset or set an authentication intent with a presentation view.
@@ -223,6 +231,7 @@
         private UserData mUserData;
         private int[] mCancelIds;
         private boolean mSupportsInlineSuggestions;
+        private ArrayList<InlinePresentation> mInlineActions;
 
         /**
          * Triggers a custom UI before before autofilling the screen with any data set in this
@@ -578,6 +587,25 @@
         }
 
         /**
+         * Adds a new {@link InlinePresentation} to this response representing an action UI.
+         *
+         * <p> For example, the UI can be associated with an intent which can open an activity for
+         * the user to manage the Autofill provider settings.
+         *
+         * @return This builder.
+         */
+        @NonNull
+        public Builder addInlineAction(@NonNull InlinePresentation inlineAction) {
+            throwIfDestroyed();
+            throwIfAuthenticationCalled();
+            if (mInlineActions == null) {
+                mInlineActions = new ArrayList<>();
+            }
+            mInlineActions.add(inlineAction);
+            return this;
+        }
+
+        /**
          * Builds a new {@link FillResponse} instance.
          *
          * @throws IllegalStateException if any of the following conditions occur:
@@ -688,6 +716,10 @@
         if (mCancelIds != null) {
             builder.append(", mCancelIds=").append(mCancelIds.length);
         }
+        builder.append(", mSupportInlinePresentations=").append(mSupportsInlineSuggestions);
+        if (mInlineActions != null) {
+            builder.append(", mInlineActions=" + mInlineActions.getList());
+        }
         return builder.append("]").toString();
     }
 
@@ -716,6 +748,7 @@
         parcel.writeParcelableArray(mFieldClassificationIds, flags);
         parcel.writeInt(mFlags);
         parcel.writeIntArray(mCancelIds);
+        parcel.writeParcelable(mInlineActions, flags);
         parcel.writeInt(mRequestId);
     }
 
@@ -771,6 +804,15 @@
             final int[] cancelIds = parcel.createIntArray();
             builder.setPresentationCancelIds(cancelIds);
 
+            final ParceledListSlice<InlinePresentation> inlineActionsSlice = parcel.readParcelable(
+                    null);
+            final List<InlinePresentation> inlineActions =
+                    (inlineActionsSlice != null) ? inlineActionsSlice.getList() : null;
+            final int inlineActionsCount = (inlineActions != null) ? inlineActions.size() : 0;
+            for (int i = 0; i < inlineActionsCount; i++) {
+                builder.addInlineAction(inlineActions.get(i));
+            }
+
             final FillResponse response = builder.build();
             response.setRequestId(parcel.readInt());
 
diff --git a/core/java/android/service/autofill/IInlineSuggestionRenderService.aidl b/core/java/android/service/autofill/IInlineSuggestionRenderService.aidl
new file mode 100644
index 0000000..decdcf5
--- /dev/null
+++ b/core/java/android/service/autofill/IInlineSuggestionRenderService.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.autofill;
+
+import android.service.autofill.IInlineSuggestionUiCallback;
+import android.service.autofill.InlinePresentation;
+
+/**
+ * Interface from system to the inline suggestion render service.
+ *
+ * @hide
+ */
+oneway interface IInlineSuggestionRenderService {
+    void renderSuggestion(in IInlineSuggestionUiCallback callback, in InlinePresentation presentation,
+                     int width, int height);
+}
diff --git a/core/java/android/service/controls/actions/CommandAction.aidl b/core/java/android/service/autofill/IInlineSuggestionUiCallback.aidl
similarity index 63%
copy from core/java/android/service/controls/actions/CommandAction.aidl
copy to core/java/android/service/autofill/IInlineSuggestionUiCallback.aidl
index 7c1ee41..a55a2ce 100644
--- a/core/java/android/service/controls/actions/CommandAction.aidl
+++ b/core/java/android/service/autofill/IInlineSuggestionUiCallback.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,6 +13,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.service.controls.actions;
 
-parcelable CommandAction;
\ No newline at end of file
+package android.service.autofill;
+
+import android.view.SurfaceControl;
+
+/**
+ * Interface to receive events from inline suggestions.
+ *
+ * @hide
+ */
+oneway interface IInlineSuggestionUiCallback {
+    void autofill();
+    void onContent(in SurfaceControl surface);
+}
diff --git a/core/java/android/service/autofill/InlinePresentation.java b/core/java/android/service/autofill/InlinePresentation.java
index 1568fb3..fb8406e 100644
--- a/core/java/android/service/autofill/InlinePresentation.java
+++ b/core/java/android/service/autofill/InlinePresentation.java
@@ -34,10 +34,22 @@
         genEqualsHashCode = true)
 public final class InlinePresentation implements Parcelable {
 
+
+    /**
+     * Represents the UI content and the action for the inline suggestion.
+     */
     private final @NonNull Slice mSlice;
 
+    /**
+     * Specifies the UI specification for the inline suggestion.
+     */
     private final @NonNull InlinePresentationSpec mInlinePresentationSpec;
 
+    /**
+     * Indicates whether the UI should be pinned, hence non-scrollable, in the host.
+     */
+    private final boolean mPinned;
+
 
 
     // Code below generated by codegen v1.0.14.
@@ -53,30 +65,56 @@
     //@formatter:off
 
 
+    /**
+     * Creates a new InlinePresentation.
+     *
+     * @param slice
+     *   Represents the UI content and the action for the inline suggestion.
+     * @param inlinePresentationSpec
+     *   Specifies the UI specification for the inline suggestion.
+     * @param pinned
+     *   Indicates whether the UI should be pinned, hence non-scrollable, in the host.
+     */
     @DataClass.Generated.Member
     public InlinePresentation(
             @NonNull Slice slice,
-            @NonNull InlinePresentationSpec inlinePresentationSpec) {
+            @NonNull InlinePresentationSpec inlinePresentationSpec,
+            boolean pinned) {
         this.mSlice = slice;
         com.android.internal.util.AnnotationValidations.validate(
                 NonNull.class, null, mSlice);
         this.mInlinePresentationSpec = inlinePresentationSpec;
         com.android.internal.util.AnnotationValidations.validate(
                 NonNull.class, null, mInlinePresentationSpec);
+        this.mPinned = pinned;
 
         // onConstructed(); // You can define this method to get a callback
     }
 
+    /**
+     * Represents the UI content and the action for the inline suggestion.
+     */
     @DataClass.Generated.Member
     public @NonNull Slice getSlice() {
         return mSlice;
     }
 
+    /**
+     * Specifies the UI specification for the inline suggestion.
+     */
     @DataClass.Generated.Member
     public @NonNull InlinePresentationSpec getInlinePresentationSpec() {
         return mInlinePresentationSpec;
     }
 
+    /**
+     * Indicates whether the UI should be pinned, hence non-scrollable, in the host.
+     */
+    @DataClass.Generated.Member
+    public boolean isPinned() {
+        return mPinned;
+    }
+
     @Override
     @DataClass.Generated.Member
     public String toString() {
@@ -85,7 +123,8 @@
 
         return "InlinePresentation { " +
                 "slice = " + mSlice + ", " +
-                "inlinePresentationSpec = " + mInlinePresentationSpec +
+                "inlinePresentationSpec = " + mInlinePresentationSpec + ", " +
+                "pinned = " + mPinned +
         " }";
     }
 
@@ -103,7 +142,8 @@
         //noinspection PointlessBooleanExpression
         return true
                 && java.util.Objects.equals(mSlice, that.mSlice)
-                && java.util.Objects.equals(mInlinePresentationSpec, that.mInlinePresentationSpec);
+                && java.util.Objects.equals(mInlinePresentationSpec, that.mInlinePresentationSpec)
+                && mPinned == that.mPinned;
     }
 
     @Override
@@ -115,6 +155,7 @@
         int _hash = 1;
         _hash = 31 * _hash + java.util.Objects.hashCode(mSlice);
         _hash = 31 * _hash + java.util.Objects.hashCode(mInlinePresentationSpec);
+        _hash = 31 * _hash + Boolean.hashCode(mPinned);
         return _hash;
     }
 
@@ -124,6 +165,9 @@
         // You can override field parcelling by defining methods like:
         // void parcelFieldName(Parcel dest, int flags) { ... }
 
+        byte flg = 0;
+        if (mPinned) flg |= 0x4;
+        dest.writeByte(flg);
         dest.writeTypedObject(mSlice, flags);
         dest.writeTypedObject(mInlinePresentationSpec, flags);
     }
@@ -139,6 +183,8 @@
         // You can override field unparcelling by defining methods like:
         // static FieldType unparcelFieldName(Parcel in) { ... }
 
+        byte flg = in.readByte();
+        boolean pinned = (flg & 0x4) != 0;
         Slice slice = (Slice) in.readTypedObject(Slice.CREATOR);
         InlinePresentationSpec inlinePresentationSpec = (InlinePresentationSpec) in.readTypedObject(InlinePresentationSpec.CREATOR);
 
@@ -148,6 +194,7 @@
         this.mInlinePresentationSpec = inlinePresentationSpec;
         com.android.internal.util.AnnotationValidations.validate(
                 NonNull.class, null, mInlinePresentationSpec);
+        this.mPinned = pinned;
 
         // onConstructed(); // You can define this method to get a callback
     }
@@ -167,10 +214,10 @@
     };
 
     @DataClass.Generated(
-            time = 1578081082387L,
+            time = 1579726472535L,
             codegenVersion = "1.0.14",
             sourceFile = "frameworks/base/core/java/android/service/autofill/InlinePresentation.java",
-            inputSignatures = "private final @android.annotation.NonNull android.app.slice.Slice mSlice\nprivate final @android.annotation.NonNull android.view.inline.InlinePresentationSpec mInlinePresentationSpec\nclass InlinePresentation extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstDefs=true, genEqualsHashCode=true)")
+            inputSignatures = "private final @android.annotation.NonNull android.app.slice.Slice mSlice\nprivate final @android.annotation.NonNull android.view.inline.InlinePresentationSpec mInlinePresentationSpec\nprivate final  boolean mPinned\nclass InlinePresentation extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstDefs=true, genEqualsHashCode=true)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/android/service/autofill/InlineSuggestionRenderService.java b/core/java/android/service/autofill/InlineSuggestionRenderService.java
new file mode 100644
index 0000000..2593aab
--- /dev/null
+++ b/core/java/android/service/autofill/InlineSuggestionRenderService.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.service.autofill;
+
+import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.app.Service;
+import android.app.slice.Slice;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.util.Log;
+import android.view.View;
+
+/**
+ * A service that renders an inline presentation given the {@link InlinePresentation} containing
+ * a {@link Slice} built using the {@link androidx.autofill.AutofillSliceBuilder}.
+ *
+ * {@hide}
+ */
+@SystemApi
+@TestApi
+public abstract class InlineSuggestionRenderService extends Service {
+
+    private static final String TAG = "InlineSuggestionRenderService";
+
+    /**
+     * The {@link Intent} that must be declared as handled by the service.
+     *
+     * <p>To be supported, the service must also require the
+     * {@link android.Manifest.permission#BIND_INLINE_SUGGESTION_RENDER_SERVICE} permission so
+     * that other applications can not abuse it.
+     */
+    public static final String SERVICE_INTERFACE =
+            "android.service.autofill.InlineSuggestionRenderService";
+
+    private final Handler mHandler = new Handler(Looper.getMainLooper(), null, true);
+
+    private void handleRenderSuggestion(IInlineSuggestionUiCallback callback,
+            InlinePresentation presentation, int width, int height) {
+        //TODO(b/146453086): implementation in ExtService
+    }
+
+    @Override
+    @Nullable
+    public final IBinder onBind(@NonNull Intent intent) {
+        if (SERVICE_INTERFACE.equals(intent.getAction())) {
+            return new IInlineSuggestionRenderService.Stub() {
+                @Override
+                public void renderSuggestion(@NonNull IInlineSuggestionUiCallback callback,
+                        @NonNull InlinePresentation presentation, int width, int height) {
+                    mHandler.sendMessage(obtainMessage(
+                            InlineSuggestionRenderService::handleRenderSuggestion,
+                            InlineSuggestionRenderService.this, callback, presentation,
+                            width, height));
+                }
+            }.asBinder();
+        }
+
+        Log.w(TAG, "Tried to bind to wrong intent (should be " + SERVICE_INTERFACE + ": " + intent);
+        return null;
+    }
+
+    /**
+     * Renders the slice into a view.
+     */
+    @Nullable
+    public View onRenderSuggestion(@NonNull InlinePresentation presentation,
+            int width, int height) {
+        Log.e(TAG, "service implementation (" + getClass() + " does not implement "
+                + "onRenderSuggestion()");
+        return null;
+    }
+}
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index 3d82946..ac2532d 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -34,9 +34,12 @@
 import android.content.pm.ParceledListSlice;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.CancellationSignal;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.ICancellationSignal;
 import android.os.Looper;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.util.Log;
 import android.util.Slog;
@@ -49,15 +52,20 @@
 import android.view.contentcapture.ContentCaptureSession;
 import android.view.contentcapture.ContentCaptureSessionId;
 import android.view.contentcapture.DataRemovalRequest;
+import android.view.contentcapture.DataShareRequest;
 import android.view.contentcapture.IContentCaptureDirectManager;
 import android.view.contentcapture.MainContentCaptureSession;
 
 import com.android.internal.os.IResultReceiver;
+import com.android.internal.util.Preconditions;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
 
 /**
  * A service used to capture the content of the screen to provide contextual data in other areas of
@@ -166,6 +174,12 @@
         }
 
         @Override
+        public void onDataShared(DataShareRequest request, IDataShareCallback callback) {
+            mHandler.sendMessage(obtainMessage(ContentCaptureService::handleOnDataShared,
+                    ContentCaptureService.this, request, callback));
+        }
+
+        @Override
         public void onActivityEvent(ActivityEvent event) {
             mHandler.sendMessage(obtainMessage(ContentCaptureService::handleOnActivityEvent,
                     ContentCaptureService.this, event));
@@ -318,6 +332,21 @@
     }
 
     /**
+     * Notifies the service that data has been shared via a readable file.
+     *
+     * @param request request object containing information about data being shared
+     * @param callback callback to be fired with response on whether the request is "needed" and can
+     *                 be handled by the Content Capture service.
+     *
+     * @hide
+     */
+    @SystemApi
+    public void onDataShareRequest(@NonNull DataShareRequest request,
+            @NonNull DataShareCallback callback) {
+        if (sVerbose) Log.v(TAG, "onDataShareRequest()");
+    }
+
+    /**
      * Notifies the service of {@link SnapshotData snapshot data} associated with a session.
      *
      * @param sessionId the session's Id
@@ -505,6 +534,40 @@
         onDataRemovalRequest(request);
     }
 
+    private void handleOnDataShared(@NonNull DataShareRequest request,
+            IDataShareCallback callback) {
+        onDataShareRequest(request, new DataShareCallback() {
+
+            @Override
+            public void onAccept(@NonNull Executor executor,
+                    @NonNull DataShareReadAdapter adapter) {
+                Preconditions.checkNotNull(adapter);
+                Preconditions.checkNotNull(executor);
+
+                ICancellationSignal cancellationSignalTransport =
+                        CancellationSignal.createTransport();
+
+                DataShareReadAdapterDelegate delegate = new DataShareReadAdapterDelegate(
+                        executor, cancellationSignalTransport, adapter);
+
+                try {
+                    callback.accept(cancellationSignalTransport, delegate);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Failed to accept data sharing", e);
+                }
+            }
+
+            @Override
+            public void onReject() {
+                try {
+                    callback.reject();
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Failed to reject data sharing", e);
+                }
+            }
+        });
+    }
+
     private void handleOnActivityEvent(@NonNull ActivityEvent event) {
         onActivityEvent(event);
     }
@@ -589,4 +652,71 @@
             Log.e(TAG, "failed to write flush metrics: " + e);
         }
     }
+
+    private static class DataShareReadAdapterDelegate extends IDataShareReadAdapter.Stub {
+
+        private final Object mLock = new Object();
+        private final WeakReference<DataShareReadAdapter> mAdapterReference;
+        private final WeakReference<Executor> mExecutorReference;
+        private final WeakReference<ICancellationSignal> mCancellationSignalReference;
+
+        DataShareReadAdapterDelegate(Executor executor,
+                ICancellationSignal cancellationSignalTransport, DataShareReadAdapter adapter) {
+            Preconditions.checkNotNull(executor);
+            Preconditions.checkNotNull(cancellationSignalTransport);
+            Preconditions.checkNotNull(adapter);
+
+            mExecutorReference = new WeakReference<>(executor);
+            mCancellationSignalReference = new WeakReference<>(cancellationSignalTransport);
+            mAdapterReference = new WeakReference<>(adapter);
+        }
+
+        @Override
+        public void start(ParcelFileDescriptor fd, ICancellationSignal remoteCancellationSignal)
+                throws RemoteException {
+            synchronized (mLock) {
+                ICancellationSignal serverControlledCancellationSignal =
+                        mCancellationSignalReference.get();
+
+                if (serverControlledCancellationSignal == null) {
+                    Slog.w(TAG, "Can't execute onStart(), reference to cancellation signal has "
+                            + "been GC'ed");
+                    return;
+                }
+
+                CancellationSignal cancellationSignal =
+                        CancellationSignal.fromTransport(serverControlledCancellationSignal);
+                cancellationSignal.setRemote(remoteCancellationSignal);
+
+                executeAdapterMethodLocked(
+                        adapter -> adapter.onStart(fd, cancellationSignal), "onStart");
+            }
+        }
+
+        @Override
+        public void error(int errorCode) throws RemoteException {
+            synchronized (mLock) {
+                executeAdapterMethodLocked(
+                        adapter -> adapter.onError(errorCode), "onError");
+            }
+        }
+
+        private void executeAdapterMethodLocked(Consumer<DataShareReadAdapter> adapterFn,
+                String methodName) {
+            DataShareReadAdapter adapter = mAdapterReference.get();
+            Executor executor = mExecutorReference.get();
+
+            if (adapter == null || executor == null) {
+                Slog.w(TAG, "Can't execute " + methodName + "(), references have been GC'ed");
+                return;
+            }
+
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                executor.execute(() -> adapterFn.accept(adapter));
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+    }
 }
diff --git a/core/java/android/service/contentcapture/DataShareCallback.java b/core/java/android/service/contentcapture/DataShareCallback.java
new file mode 100644
index 0000000..e3c7bb3
--- /dev/null
+++ b/core/java/android/service/contentcapture/DataShareCallback.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.contentcapture;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Callback for the Content Capture Service to accept or reject the data share request from a client
+ * app.
+ *
+ * If the request is rejected, client app would receive a signal and the data share session wouldn't
+ * be started.
+ *
+ * @hide
+ **/
+@SystemApi
+public interface DataShareCallback {
+
+    /** Accept the data share.
+     *
+     * @param executor executor to be used for running the adapter in.
+     * @param adapter adapter to be used for the share operation
+     */
+    void onAccept(@NonNull @CallbackExecutor Executor executor,
+            @NonNull DataShareReadAdapter adapter);
+
+    /** Reject the data share. */
+    void onReject();
+}
diff --git a/core/java/android/service/contentcapture/DataShareReadAdapter.java b/core/java/android/service/contentcapture/DataShareReadAdapter.java
new file mode 100644
index 0000000..ca68201
--- /dev/null
+++ b/core/java/android/service/contentcapture/DataShareReadAdapter.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.contentcapture;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.CancellationSignal;
+import android.os.ParcelFileDescriptor;
+
+/**
+ * Adapter class to be used for the Content Capture Service app to propagate the status of the
+ * session
+ *
+ * @hide
+ **/
+@SystemApi
+public interface DataShareReadAdapter {
+
+    /**
+     * Signals the start of the data sharing session.
+     *
+     * @param fd file descriptor to use for reading data, that's being shared
+     * @param cancellationSignal cancellation signal to use if data is no longer needed and the
+     *                           session needs to be terminated.
+     **/
+    void onStart(@NonNull ParcelFileDescriptor fd, @NonNull CancellationSignal cancellationSignal);
+
+    /**
+     * Signals that the session failed to start or terminated unsuccessfully.
+     **/
+    void onError(int errorCode);
+}
diff --git a/core/java/android/service/contentcapture/IContentCaptureService.aidl b/core/java/android/service/contentcapture/IContentCaptureService.aidl
index a7578af9..277d82b 100644
--- a/core/java/android/service/contentcapture/IContentCaptureService.aidl
+++ b/core/java/android/service/contentcapture/IContentCaptureService.aidl
@@ -20,8 +20,10 @@
 import android.os.IBinder;
 import android.service.contentcapture.ActivityEvent;
 import android.service.contentcapture.SnapshotData;
+import android.service.contentcapture.IDataShareCallback;
 import android.view.contentcapture.ContentCaptureContext;
 import android.view.contentcapture.DataRemovalRequest;
+import android.view.contentcapture.DataShareRequest;
 
 import com.android.internal.os.IResultReceiver;
 
@@ -40,5 +42,6 @@
     void onSessionFinished(int sessionId);
     void onActivitySnapshot(int sessionId, in SnapshotData snapshotData);
     void onDataRemovalRequest(in DataRemovalRequest request);
+    void onDataShared(in DataShareRequest request, in IDataShareCallback callback);
     void onActivityEvent(in ActivityEvent event);
 }
diff --git a/core/java/android/os/StatsLogEventWrapper.aidl b/core/java/android/service/contentcapture/IDataShareCallback.aidl
similarity index 62%
copy from core/java/android/os/StatsLogEventWrapper.aidl
copy to core/java/android/service/contentcapture/IDataShareCallback.aidl
index 766343e..d972ada 100644
--- a/core/java/android/os/StatsLogEventWrapper.aidl
+++ b/core/java/android/service/contentcapture/IDataShareCallback.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,13 @@
  * limitations under the License.
  */
 
-package android.os;
+package android.service.contentcapture;
+
+import android.os.ICancellationSignal;
+import android.service.contentcapture.IDataShareReadAdapter;
 
 /** @hide */
-parcelable StatsLogEventWrapper cpp_header "android/os/StatsLogEventWrapper.h";
\ No newline at end of file
+oneway interface IDataShareCallback {
+    void accept(in ICancellationSignal cancellationSignal, in IDataShareReadAdapter adapter);
+    void reject();
+}
diff --git a/core/java/android/os/StatsLogEventWrapper.aidl b/core/java/android/service/contentcapture/IDataShareReadAdapter.aidl
similarity index 65%
copy from core/java/android/os/StatsLogEventWrapper.aidl
copy to core/java/android/service/contentcapture/IDataShareReadAdapter.aidl
index 766343e..73da5d5 100644
--- a/core/java/android/os/StatsLogEventWrapper.aidl
+++ b/core/java/android/service/contentcapture/IDataShareReadAdapter.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,12 @@
  * limitations under the License.
  */
 
-package android.os;
+package android.service.contentcapture;
+
+import android.os.ICancellationSignal;
 
 /** @hide */
-parcelable StatsLogEventWrapper cpp_header "android/os/StatsLogEventWrapper.h";
\ No newline at end of file
+oneway interface IDataShareReadAdapter {
+    void start(in ParcelFileDescriptor fd, in ICancellationSignal cancellationSignal);
+    void error(int errorCode);
+}
diff --git a/core/java/android/service/controls/Control.java b/core/java/android/service/controls/Control.java
index 43a308c..2d1d0ed 100644
--- a/core/java/android/service/controls/Control.java
+++ b/core/java/android/service/controls/Control.java
@@ -19,12 +19,16 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SuppressLint;
 import android.app.PendingIntent;
 import android.content.Intent;
+import android.content.res.ColorStateList;
+import android.graphics.drawable.Icon;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.service.controls.actions.ControlAction;
 import android.service.controls.templates.ControlTemplate;
+import android.service.controls.templates.ControlTemplateWrapper;
 import android.util.Log;
 
 import com.android.internal.util.Preconditions;
@@ -51,9 +55,8 @@
  * <p>
  * An {@link Intent} linking to the provider Activity that expands on this {@link Control} and
  * allows for further actions should be provided.
- * @hide
  */
-public class Control implements Parcelable {
+public final class Control implements Parcelable {
     private static final String TAG = "Control";
 
     private static final int NUM_STATUS = 5;
@@ -99,6 +102,10 @@
     private final @Nullable CharSequence mStructure;
     private final @Nullable CharSequence mZone;
     private final @NonNull PendingIntent mAppIntent;
+
+    private final @Nullable Icon mCustomIcon;
+    private final @Nullable ColorStateList mCustomColor;
+
     private final @Status int mStatus;
     private final @NonNull ControlTemplate mControlTemplate;
     private final @NonNull CharSequence mStatusText;
@@ -113,14 +120,21 @@
      * @param zone
      * @param appIntent a {@link PendingIntent} linking to a page to interact with the
      *                  corresponding device.
+     * @param customIcon
+     * @param customColor
+     * @param status
+     * @param controlTemplate
+     * @param statusText
      */
-    public Control(@NonNull String controlId,
+    Control(@NonNull String controlId,
             @DeviceTypes.DeviceType int deviceType,
             @NonNull CharSequence title,
             @NonNull CharSequence subtitle,
             @Nullable CharSequence structure,
             @Nullable CharSequence zone,
             @NonNull PendingIntent appIntent,
+            @Nullable Icon customIcon,
+            @Nullable ColorStateList customColor,
             @Status int status,
             @NonNull ControlTemplate controlTemplate,
             @NonNull CharSequence statusText) {
@@ -142,6 +156,10 @@
         mStructure = structure;
         mZone = zone;
         mAppIntent = appIntent;
+
+        mCustomColor = customColor;
+        mCustomIcon = customIcon;
+
         if (status < 0 || status >= NUM_STATUS) {
             mStatus = STATUS_UNKNOWN;
             Log.e(TAG, "Status unknown:" + status);
@@ -152,7 +170,11 @@
         mStatusText = statusText;
     }
 
-    public Control(Parcel in) {
+    /**
+     * @param in
+     * @hide
+     */
+    Control(Parcel in) {
         mControlId = in.readString();
         mDeviceType = in.readInt();
         mTitle = in.readCharSequence();
@@ -168,8 +190,22 @@
             mZone = null;
         }
         mAppIntent = PendingIntent.CREATOR.createFromParcel(in);
+
+        if (in.readByte() == (byte) 1) {
+            mCustomIcon = Icon.CREATOR.createFromParcel(in);
+        } else {
+            mCustomIcon = null;
+        }
+
+        if (in.readByte() == (byte) 1) {
+            mCustomColor = ColorStateList.CREATOR.createFromParcel(in);
+        } else {
+            mCustomColor = null;
+        }
+
         mStatus = in.readInt();
-        mControlTemplate = ControlTemplate.CREATOR.createFromParcel(in);
+        ControlTemplateWrapper wrapper = ControlTemplateWrapper.CREATOR.createFromParcel(in);
+        mControlTemplate = wrapper.getWrappedTemplate();
         mStatusText = in.readCharSequence();
     }
 
@@ -208,6 +244,16 @@
         return mAppIntent;
     }
 
+    @Nullable
+    public Icon getCustomIcon() {
+        return mCustomIcon;
+    }
+
+    @Nullable
+    public ColorStateList getCustomColor() {
+        return mCustomColor;
+    }
+
     @Status
     public int getStatus() {
         return mStatus;
@@ -229,7 +275,7 @@
     }
 
     @Override
-    public void writeToParcel(Parcel dest, int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeString(mControlId);
         dest.writeInt(mDeviceType);
         dest.writeCharSequence(mTitle);
@@ -247,14 +293,27 @@
             dest.writeByte((byte) 0);
         }
         mAppIntent.writeToParcel(dest, flags);
+        if (mCustomIcon != null) {
+            dest.writeByte((byte) 1);
+            mCustomIcon.writeToParcel(dest, flags);
+        } else {
+            dest.writeByte((byte) 0);
+        }
+        if (mCustomColor != null) {
+            dest.writeByte((byte) 1);
+            mCustomColor.writeToParcel(dest, flags);
+        } else {
+            dest.writeByte((byte) 0);
+        }
+
         dest.writeInt(mStatus);
-        mControlTemplate.writeToParcel(dest, flags);
+        new ControlTemplateWrapper(mControlTemplate).writeToParcel(dest, flags);
         dest.writeCharSequence(mStatusText);
     }
 
-    public static final Creator<Control> CREATOR = new Creator<Control>() {
+    public static final @NonNull Creator<Control> CREATOR = new Creator<Control>() {
         @Override
-        public Control createFromParcel(Parcel source) {
+        public Control createFromParcel(@NonNull Parcel source) {
             return new Control(source);
         }
 
@@ -275,25 +334,25 @@
      *     <li> Subtitle: {@code ""}
      * </ul>
      * This fixes the values relating to state of the {@link Control} as required by
-     * {@link ControlsProviderService#onLoad}:
+     * {@link ControlsProviderService#loadAvailableControls}:
      * <ul>
      *     <li> Status: {@link Status#STATUS_UNKNOWN}
      *     <li> Control template: {@link ControlTemplate#NO_TEMPLATE}
      *     <li> Status text: {@code ""}
      * </ul>
      */
-    public static class StatelessBuilder {
+    @SuppressLint("MutableBareField")
+    public static final class StatelessBuilder {
         private static final String TAG = "StatelessBuilder";
-        protected @NonNull String mControlId;
-        protected @DeviceTypes.DeviceType int mDeviceType = DeviceTypes.TYPE_UNKNOWN;
-        protected @NonNull CharSequence mTitle = "";
-        protected @NonNull CharSequence mSubtitle = "";
-        protected @Nullable CharSequence mStructure;
-        protected @Nullable CharSequence mZone;
-        protected @NonNull PendingIntent mAppIntent;
-        protected @Status int mStatus = STATUS_UNKNOWN;
-        protected @NonNull ControlTemplate mControlTemplate = ControlTemplate.NO_TEMPLATE;
-        protected @NonNull CharSequence mStatusText = "";
+        private @NonNull String mControlId;
+        private @DeviceTypes.DeviceType int mDeviceType = DeviceTypes.TYPE_UNKNOWN;
+        private @NonNull CharSequence mTitle = "";
+        private @NonNull CharSequence mSubtitle = "";
+        private @Nullable CharSequence mStructure;
+        private @Nullable CharSequence mZone;
+        private @NonNull PendingIntent mAppIntent;
+        private @Nullable Icon mCustomIcon;
+        private @Nullable ColorStateList mCustomColor;
 
         /**
          * @param controlId the identifier for the {@link Control}.
@@ -320,6 +379,8 @@
             mStructure = control.mStructure;
             mZone = control.mZone;
             mAppIntent = control.mAppIntent;
+            mCustomIcon = control.mCustomIcon;
+            mCustomColor = control.mCustomColor;
         }
 
         /**
@@ -385,6 +446,18 @@
             return this;
         }
 
+        @NonNull
+        public StatelessBuilder setCustomIcon(@Nullable Icon customIcon) {
+            mCustomIcon = customIcon;
+            return this;
+        }
+
+        @NonNull
+        public StatelessBuilder setCustomColor(@Nullable ColorStateList customColor) {
+            mCustomColor = customColor;
+            return this;
+        }
+
         /**
          * Build a {@link Control}
          * @return a valid {@link Control}
@@ -398,14 +471,42 @@
                     mStructure,
                     mZone,
                     mAppIntent,
-                    mStatus,
-                    mControlTemplate,
-                    mStatusText);
+                    mCustomIcon,
+                    mCustomColor,
+                    STATUS_UNKNOWN,
+                    ControlTemplate.NO_TEMPLATE,
+                    "");
         }
     }
 
-    public static class StatefulBuilder extends StatelessBuilder {
+    /**
+     * Builder class for {@link Control}.
+     *
+     * This class facilitates the creation of {@link Control}.
+     * It provides the following defaults for non-optional parameters:
+     * <ul>
+     *     <li> Device type: {@link DeviceTypes#TYPE_UNKNOWN}
+     *     <li> Title: {@code ""}
+     *     <li> Subtitle: {@code ""}
+     *     <li> Status: {@link Status#STATUS_UNKNOWN}
+     *     <li> Control template: {@link ControlTemplate#NO_TEMPLATE}
+     *     <li> Status text: {@code ""}
+     * </ul>
+     */
+    public static final class StatefulBuilder {
         private static final String TAG = "StatefulBuilder";
+        private @NonNull String mControlId;
+        private @DeviceTypes.DeviceType int mDeviceType = DeviceTypes.TYPE_UNKNOWN;
+        private @NonNull CharSequence mTitle = "";
+        private @NonNull CharSequence mSubtitle = "";
+        private @Nullable CharSequence mStructure;
+        private @Nullable CharSequence mZone;
+        private @NonNull PendingIntent mAppIntent;
+        private @Nullable Icon mCustomIcon;
+        private @Nullable ColorStateList mCustomColor;
+        private @Status int mStatus = STATUS_UNKNOWN;
+        private @NonNull ControlTemplate mControlTemplate = ControlTemplate.NO_TEMPLATE;
+        private @NonNull CharSequence mStatusText = "";
 
         /**
          * @param controlId the identifier for the {@link Control}.
@@ -413,11 +514,27 @@
          */
         public StatefulBuilder(@NonNull String controlId,
                 @NonNull PendingIntent appIntent) {
-            super(controlId, appIntent);
+            Preconditions.checkNotNull(controlId);
+            Preconditions.checkNotNull(appIntent);
+            mControlId = controlId;
+            mAppIntent = appIntent;
         }
 
+        /**
+         * Creates a {@link StatelessBuilder} using an existing {@link Control} as a base.
+         * @param control base for the builder.
+         */
         public StatefulBuilder(@NonNull Control control) {
-            super(control);
+            Preconditions.checkNotNull(control);
+            mControlId = control.mControlId;
+            mDeviceType = control.mDeviceType;
+            mTitle = control.mTitle;
+            mSubtitle = control.mSubtitle;
+            mStructure = control.mStructure;
+            mZone = control.mZone;
+            mAppIntent = control.mAppIntent;
+            mCustomIcon = control.mCustomIcon;
+            mCustomColor = control.mCustomColor;
             mStatus = control.mStatus;
             mControlTemplate = control.mControlTemplate;
             mStatusText = control.mStatusText;
@@ -429,13 +546,19 @@
          */
         @NonNull
         public StatefulBuilder setControlId(@NonNull String controlId) {
-            super.setControlId(controlId);
+            Preconditions.checkNotNull(controlId);
+            mControlId = controlId;
             return this;
         }
 
         @NonNull
         public StatefulBuilder setDeviceType(@DeviceTypes.DeviceType int deviceType) {
-            super.setDeviceType(deviceType);
+            if (!DeviceTypes.validDeviceType(deviceType)) {
+                Log.e(TAG, "Invalid device type:" + deviceType);
+                mDeviceType = DeviceTypes.TYPE_UNKNOWN;
+            } else {
+                mDeviceType = deviceType;
+            }
             return this;
         }
 
@@ -445,25 +568,27 @@
          */
         @NonNull
         public StatefulBuilder setTitle(@NonNull CharSequence title) {
-            super.setTitle(title);
+            Preconditions.checkNotNull(title);
+            mTitle = title;
             return this;
         }
 
         @NonNull
         public StatefulBuilder setSubtitle(@NonNull CharSequence subtitle) {
-            super.setSubtitle(subtitle);
+            Preconditions.checkNotNull(subtitle);
+            mSubtitle = subtitle;
             return this;
         }
 
         @NonNull
         public StatefulBuilder setStructure(@Nullable CharSequence structure) {
-            super.setStructure(structure);
+            mStructure = structure;
             return this;
         }
 
         @NonNull
         public StatefulBuilder setZone(@Nullable CharSequence zone) {
-            super.setZone(zone);
+            mZone = zone;
             return this;
         }
 
@@ -473,7 +598,20 @@
          */
         @NonNull
         public StatefulBuilder setAppIntent(@NonNull PendingIntent appIntent) {
-            super.setAppIntent(appIntent);
+            Preconditions.checkNotNull(appIntent);
+            mAppIntent = appIntent;
+            return this;
+        }
+
+        @NonNull
+        public StatefulBuilder setCustomIcon(@Nullable Icon customIcon) {
+            mCustomIcon = customIcon;
+            return this;
+        }
+
+        @NonNull
+        public StatefulBuilder setCustomColor(@Nullable ColorStateList customColor) {
+            mCustomColor = customColor;
             return this;
         }
 
@@ -501,5 +639,21 @@
             mStatusText = statusText;
             return this;
         }
+
+        @NonNull
+        public Control build() {
+            return new Control(mControlId,
+                    mDeviceType,
+                    mTitle,
+                    mSubtitle,
+                    mStructure,
+                    mZone,
+                    mAppIntent,
+                    mCustomIcon,
+                    mCustomColor,
+                    mStatus,
+                    mControlTemplate,
+                    mStatusText);
+        }
     }
 }
diff --git a/core/java/android/service/controls/ControlsProviderService.java b/core/java/android/service/controls/ControlsProviderService.java
index eca8541..bc65818 100644
--- a/core/java/android/service/controls/ControlsProviderService.java
+++ b/core/java/android/service/controls/ControlsProviderService.java
@@ -27,6 +27,7 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.service.controls.actions.ControlAction;
+import android.service.controls.actions.ControlActionWrapper;
 import android.service.controls.templates.ControlTemplate;
 import android.text.TextUtils;
 import android.util.Log;
@@ -35,150 +36,90 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.Flow.Publisher;
+import java.util.concurrent.Flow.Subscriber;
+import java.util.concurrent.Flow.Subscription;
+import java.util.function.Consumer;
 
 /**
  * Service implementation allowing applications to contribute controls to the
  * System UI.
- * @hide
  */
 public abstract class ControlsProviderService extends Service {
 
     @SdkConstant(SdkConstantType.SERVICE_ACTION)
-    public static final String CONTROLS_ACTION = "android.service.controls.ControlsProviderService";
+    public static final String SERVICE_CONTROLS =
+            "android.service.controls.ControlsProviderService";
+    /**
+     * @hide
+     */
     public static final String CALLBACK_BUNDLE = "CALLBACK_BUNDLE";
-    public static final String CALLBACK_BINDER = "CALLBACK_BINDER";
+
+    /**
+     * @hide
+     */
     public static final String CALLBACK_TOKEN = "CALLBACK_TOKEN";
 
-    public final String TAG = getClass().getSimpleName();
+    public static final @NonNull String TAG = "ControlsProviderService";
 
-    private IControlsProviderCallback mCallback;
     private IBinder mToken;
     private RequestHandler mHandler;
 
     /**
-     * Signal to retrieve all Controls. When complete, call
-     * {@link IControlsProviderCallback#onLoad} to inform the caller.
+     * Retrieve all available controls, using the stateless builder
+     * {@link Control.StatelessBuilder} to build each Control, then use the
+     * provided consumer to callback to the call originator.
      */
-    public abstract void load();
+    public abstract void loadAvailableControls(@NonNull Consumer<List<Control>> consumer);
 
     /**
-     * Informs the service that the caller is listening for updates to the given controlIds.
-     * {@link IControlsProviderCallback#onRefreshState} should be called any time
-     * there are Control updates to render.
+     * Return a valid Publisher for the given controlIds. This publisher will be asked
+     * to provide updates for the given list of controlIds as long as the Subscription
+     * is valid.
      */
-    public abstract void subscribe(@NonNull List<String> controlIds);
-
-    /**
-     * Informs the service that the caller is done listening for updates,
-     * and any calls to {@link IControlsProviderCallback#onRefreshState} will be ignored.
-     */
-    public abstract void unsubscribe();
+    @NonNull
+    public abstract Publisher<Control> publisherFor(@NonNull List<String> controlIds);
 
     /**
      * The user has interacted with a Control. The action is dictated by the type of
-     * {@link ControlAction} that was sent.
+     * {@link ControlAction} that was sent. A response can be sent via
+     * {@link Consumer#accept}, with the Integer argument being one of the provided
+     * {@link ControlAction.ResponseResult}. The Integer should indicate whether the action
+     * was received successfully, or if additional prompts should be presented to
+     * the user. Any visual control updates should be sent via the Publisher.
      */
-    public abstract void onAction(@NonNull String controlId, @NonNull ControlAction action);
-
-    /**
-     * Sends a list of the controls available from this service.
-     *
-     * The items in the list must not have state information (as created by
-     * {@link Control.StatelessBuilder}).
-     * @param controls
-     */
-    public final void onLoad(@NonNull List<Control> controls) {
-        Preconditions.checkNotNull(controls);
-        List<Control> list = new ArrayList<>();
-        for (Control control: controls) {
-            if (control == null) {
-                Log.e(TAG, "onLoad: null control.");
-            }
-            if (isStateless(control)) {
-                list.add(control);
-            } else {
-                Log.w(TAG, "onLoad: control is not stateless.");
-                list.add(new Control.StatelessBuilder(control).build());
-            }
-        }
-        try {
-            mCallback.onLoad(mToken, list);
-        } catch (RemoteException ex) {
-            ex.rethrowAsRuntimeException();
-        }
-    }
-
-    /**
-     * Sends a list of the controls requested by {@link ControlsProviderService#subscribe} with
-     * their state.
-     * @param statefulControls
-     */
-    public final void onRefreshState(@NonNull List<Control> statefulControls) {
-        Preconditions.checkNotNull(statefulControls);
-        try {
-            mCallback.onRefreshState(mToken, statefulControls);
-        } catch (RemoteException ex) {
-            ex.rethrowAsRuntimeException();
-        }
-    }
-
-    /**
-     * Sends the response of a command in the specified {@link Control}.
-     * @param controlId
-     * @param response
-     */
-    public final void onControlActionResponse(
-            @NonNull String controlId, @ControlAction.ResponseResult int response) {
-        Preconditions.checkNotNull(controlId);
-        if (!ControlAction.isValidResponse(response)) {
-            Log.e(TAG, "Not valid response result: " + response);
-            response = ControlAction.RESPONSE_UNKNOWN;
-        }
-        try {
-            mCallback.onControlActionResponse(mToken, controlId, response);
-        } catch (RemoteException ex) {
-            ex.rethrowAsRuntimeException();
-        }
-    }
-
-    private boolean isStateless(Control control) {
-        return (control.getStatus() == Control.STATUS_UNKNOWN
-                    && control.getControlTemplate().getTemplateType() == ControlTemplate.TYPE_NONE
-                    && TextUtils.isEmpty(control.getStatusText()));
-    }
+    public abstract void performControlAction(@NonNull String controlId,
+            @NonNull ControlAction action, @NonNull Consumer<Integer> consumer);
 
     @Override
-    public IBinder onBind(Intent intent) {
+    @NonNull
+    public final IBinder onBind(@NonNull Intent intent) {
         mHandler = new RequestHandler(Looper.getMainLooper());
 
         Bundle bundle = intent.getBundleExtra(CALLBACK_BUNDLE);
-        IBinder callbackBinder = bundle.getBinder(CALLBACK_BINDER);
         mToken = bundle.getBinder(CALLBACK_TOKEN);
-        mCallback = IControlsProviderCallback.Stub.asInterface(callbackBinder);
 
         return new IControlsProvider.Stub() {
-            public void load() {
-                mHandler.sendEmptyMessage(RequestHandler.MSG_LOAD);
+            public void load(IControlsLoadCallback cb) {
+                mHandler.obtainMessage(RequestHandler.MSG_LOAD, cb).sendToTarget();
             }
 
-            public void subscribe(List<String> ids) {
-                mHandler.obtainMessage(RequestHandler.MSG_SUBSCRIBE, ids).sendToTarget();
+            public void subscribe(List<String> controlIds,
+                    IControlsSubscriber subscriber) {
+                SubscribeMessage msg = new SubscribeMessage(controlIds, subscriber);
+                mHandler.obtainMessage(RequestHandler.MSG_SUBSCRIBE, msg).sendToTarget();
             }
 
-            public void unsubscribe() {
-                mHandler.sendEmptyMessage(RequestHandler.MSG_UNSUBSCRIBE);
-            }
-
-            public void onAction(String id, ControlAction action) {
-                ActionMessage msg = new ActionMessage(id, action);
-                mHandler.obtainMessage(RequestHandler.MSG_ON_ACTION, msg).sendToTarget();
+            public void action(String controlId, ControlActionWrapper action,
+                               IControlsActionCallback cb) {
+                ActionMessage msg = new ActionMessage(controlId, action.getWrappedAction(), cb);
+                mHandler.obtainMessage(RequestHandler.MSG_ACTION, msg).sendToTarget();
             }
         };
     }
 
     @Override
-    public boolean onUnbind(Intent intent) {
-        mCallback = null;
+    public boolean onUnbind(@NonNull Intent intent) {
         mHandler = null;
         return true;
     }
@@ -186,8 +127,7 @@
     private class RequestHandler extends Handler {
         private static final int MSG_LOAD = 1;
         private static final int MSG_SUBSCRIBE = 2;
-        private static final int MSG_UNSUBSCRIBE = 3;
-        private static final int MSG_ON_ACTION = 4;
+        private static final int MSG_ACTION = 3;
 
         RequestHandler(Looper looper) {
             super(looper);
@@ -196,30 +136,136 @@
         public void handleMessage(Message msg) {
             switch(msg.what) {
                 case MSG_LOAD:
-                    ControlsProviderService.this.load();
+                    final IControlsLoadCallback cb = (IControlsLoadCallback) msg.obj;
+                    ControlsProviderService.this.loadAvailableControls(consumerFor(cb));
                     break;
+
                 case MSG_SUBSCRIBE:
-                    List<String> ids = (List<String>) msg.obj;
-                    ControlsProviderService.this.subscribe(ids);
+                    final SubscribeMessage sMsg = (SubscribeMessage) msg.obj;
+                    final IControlsSubscriber cs = sMsg.mSubscriber;
+                    Subscriber<Control> s = new Subscriber<Control>() {
+                            public void onSubscribe(Subscription subscription) {
+                                try {
+                                    cs.onSubscribe(mToken, new SubscriptionAdapter(subscription));
+                                } catch (RemoteException ex) {
+                                    ex.rethrowAsRuntimeException();
+                                }
+                            }
+                            public void onNext(@NonNull Control statefulControl) {
+                                Preconditions.checkNotNull(statefulControl);
+                                try {
+                                    cs.onNext(mToken, statefulControl);
+                                } catch (RemoteException ex) {
+                                    ex.rethrowAsRuntimeException();
+                                }
+                            }
+                            public void onError(Throwable t) {
+                                try {
+                                    cs.onError(mToken, t.toString());
+                                } catch (RemoteException ex) {
+                                    ex.rethrowAsRuntimeException();
+                                }
+                            }
+                            public void onComplete() {
+                                try {
+                                    cs.onComplete(mToken);
+                                } catch (RemoteException ex) {
+                                    ex.rethrowAsRuntimeException();
+                                }
+                            }
+                        };
+                    ControlsProviderService.this.publisherFor(sMsg.mControlIds).subscribe(s);
                     break;
-                case MSG_UNSUBSCRIBE:
-                    ControlsProviderService.this.unsubscribe();
-                    break;
-                case MSG_ON_ACTION:
-                    ActionMessage aMsg = (ActionMessage) msg.obj;
-                    ControlsProviderService.this.onAction(aMsg.mId, aMsg.mAction);
+
+                case MSG_ACTION:
+                    final ActionMessage aMsg = (ActionMessage) msg.obj;
+                    ControlsProviderService.this.performControlAction(aMsg.mControlId,
+                            aMsg.mAction, consumerFor(aMsg.mControlId, aMsg.mCb));
                     break;
             }
         }
+
+        private Consumer<Integer> consumerFor(final String controlId,
+                final IControlsActionCallback cb) {
+            return (@NonNull Integer response) -> {
+                Preconditions.checkNotNull(response);
+                if (!ControlAction.isValidResponse(response)) {
+                    Log.e(TAG, "Not valid response result: " + response);
+                    response = ControlAction.RESPONSE_UNKNOWN;
+                }
+                try {
+                    cb.accept(mToken, controlId, response);
+                } catch (RemoteException ex) {
+                    ex.rethrowAsRuntimeException();
+                }
+            };
+        }
+
+        private Consumer<List<Control>> consumerFor(IControlsLoadCallback cb) {
+            return (@NonNull List<Control> controls) -> {
+                Preconditions.checkNotNull(controls);
+                List<Control> list = new ArrayList<>();
+                for (Control control: controls) {
+                    if (control == null) {
+                        Log.e(TAG, "onLoad: null control.");
+                    }
+                    if (isStatelessControl(control)) {
+                        list.add(control);
+                    } else {
+                        Log.w(TAG, "onLoad: control is not stateless.");
+                        list.add(new Control.StatelessBuilder(control).build());
+                    }
+                }
+                try {
+                    cb.accept(mToken, list);
+                } catch (RemoteException ex) {
+                    ex.rethrowAsRuntimeException();
+                }
+            };
+        }
+
+        private boolean isStatelessControl(Control control) {
+            return (control.getStatus() == Control.STATUS_UNKNOWN
+                    && control.getControlTemplate().getTemplateType() == ControlTemplate.TYPE_NONE
+                    && TextUtils.isEmpty(control.getStatusText()));
+        }
     }
 
-    private class ActionMessage {
-        final String mId;
-        final ControlAction mAction;
+    private static class SubscriptionAdapter extends IControlsSubscription.Stub {
+        final Subscription mSubscription;
 
-        ActionMessage(String id, ControlAction action) {
-            this.mId = id;
+        SubscriptionAdapter(Subscription s) {
+            this.mSubscription = s;
+        }
+
+        public void request(long n) {
+            mSubscription.request(n);
+        }
+
+        public void cancel() {
+            mSubscription.cancel();
+        }
+    }
+
+    private static class ActionMessage {
+        final String mControlId;
+        final ControlAction mAction;
+        final IControlsActionCallback mCb;
+
+        ActionMessage(String controlId, ControlAction action, IControlsActionCallback cb) {
+            this.mControlId = controlId;
             this.mAction = action;
+            this.mCb = cb;
+        }
+    }
+
+    private static class SubscribeMessage {
+        final List<String> mControlIds;
+        final IControlsSubscriber mSubscriber;
+
+        SubscribeMessage(List<String> controlIds, IControlsSubscriber subscriber) {
+            this.mControlIds = controlIds;
+            this.mSubscriber = subscriber;
         }
     }
 }
diff --git a/core/java/android/service/controls/DeviceTypes.java b/core/java/android/service/controls/DeviceTypes.java
index b2d1c08..8dbb9cf 100644
--- a/core/java/android/service/controls/DeviceTypes.java
+++ b/core/java/android/service/controls/DeviceTypes.java
@@ -21,9 +21,6 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
-/**
- * @hide
- */
 public class DeviceTypes {
 
     // Update this when adding new concrete types. Does not count TYPE_UNKNOWN
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl b/core/java/android/service/controls/IControlsActionCallback.aidl
similarity index 71%
copy from telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl
copy to core/java/android/service/controls/IControlsActionCallback.aidl
index e9cbd9c..eab4c89 100644
--- a/telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl
+++ b/core/java/android/service/controls/IControlsActionCallback.aidl
@@ -1,6 +1,5 @@
 /*
- *
- * Copyright 2019, The Android Open Source Project
+ * Copyright (c) 2020, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,6 +14,11 @@
  * limitations under the License.
  */
 
-package android.telephony.ims;
+package android.service.controls;
 
-parcelable RcsMessageQueryParams;
+/**
+ * @hide
+ */
+oneway interface IControlsActionCallback {
+    void accept(in IBinder token, in String controlId, int response);
+}
\ No newline at end of file
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl b/core/java/android/service/controls/IControlsLoadCallback.aidl
similarity index 68%
copy from telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl
copy to core/java/android/service/controls/IControlsLoadCallback.aidl
index e9cbd9c..bfc61cd 100644
--- a/telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl
+++ b/core/java/android/service/controls/IControlsLoadCallback.aidl
@@ -1,6 +1,5 @@
 /*
- *
- * Copyright 2019, The Android Open Source Project
+ * Copyright (c) 2020, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,6 +14,13 @@
  * limitations under the License.
  */
 
-package android.telephony.ims;
+package android.service.controls;
 
-parcelable RcsMessageQueryParams;
+import android.service.controls.Control;
+
+/**
+ * @hide
+ */
+oneway interface IControlsLoadCallback {
+    void accept(in IBinder token, in List<Control> controls);
+}
\ No newline at end of file
diff --git a/core/java/android/service/controls/IControlsProvider.aidl b/core/java/android/service/controls/IControlsProvider.aidl
index 6c105bb..4ce658e 100644
--- a/core/java/android/service/controls/IControlsProvider.aidl
+++ b/core/java/android/service/controls/IControlsProvider.aidl
@@ -16,15 +16,20 @@
 
 package android.service.controls;
 
-import android.service.controls.actions.ControlAction;
+import android.service.controls.IControlsActionCallback;
+import android.service.controls.IControlsLoadCallback;
+import android.service.controls.IControlsSubscriber;
+import android.service.controls.actions.ControlActionWrapper;
 
-/** @hide */
+/**
+ * @hide
+ */
 oneway interface IControlsProvider {
-    void load();
+    void load(IControlsLoadCallback cb);
 
-    void subscribe(in List<String> controlIds);
+    void subscribe(in List<String> controlIds,
+             IControlsSubscriber subscriber);
 
-    void unsubscribe();
-
-    void onAction(in String controlId, in ControlAction action);
+    void action(in String controlId, in ControlActionWrapper action,
+             IControlsActionCallback cb);
 }
\ No newline at end of file
diff --git a/core/java/android/service/controls/IControlsProviderCallback.aidl b/core/java/android/service/controls/IControlsSubscriber.aidl
similarity index 63%
rename from core/java/android/service/controls/IControlsProviderCallback.aidl
rename to core/java/android/service/controls/IControlsSubscriber.aidl
index 91f6a79..75ce584 100644
--- a/core/java/android/service/controls/IControlsProviderCallback.aidl
+++ b/core/java/android/service/controls/IControlsSubscriber.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, The Android Open Source Project
+ * Copyright (c) 2020, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,12 +17,14 @@
 package android.service.controls;
 
 import android.service.controls.Control;
+import android.service.controls.IControlsSubscription;
 
-/** @hide */
-oneway interface IControlsProviderCallback {
-    void onLoad(in IBinder token, in List<Control> controls);
-
-    void onRefreshState(in IBinder token, in List<Control> statefulControls);
-
-    void onControlActionResponse(in IBinder token, in String controlId, int response);
+/**
+ * @hide
+ */
+oneway interface IControlsSubscriber {
+    void onSubscribe(in IBinder token, in IControlsSubscription cs);
+    void onNext(in IBinder token, in Control c);
+    void onError(in IBinder token, in String s);
+    void onComplete(in IBinder token);
 }
\ No newline at end of file
diff --git a/core/java/android/service/controls/templates/ToggleTemplate.aidl b/core/java/android/service/controls/IControlsSubscription.aidl
similarity index 74%
rename from core/java/android/service/controls/templates/ToggleTemplate.aidl
rename to core/java/android/service/controls/IControlsSubscription.aidl
index 98a9e49..0af575e 100644
--- a/core/java/android/service/controls/templates/ToggleTemplate.aidl
+++ b/core/java/android/service/controls/IControlsSubscription.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, The Android Open Source Project
+ * Copyright (c) 2020, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,6 +14,12 @@
  * limitations under the License.
  */
 
-package android.service.controls.templates;
+package android.service.controls;
 
-parcelable ToggleTemplate;
\ No newline at end of file
+/**
+ * @hide
+ */
+oneway interface IControlsSubscription {
+    void request(long n);
+    void cancel();
+}
\ No newline at end of file
diff --git a/core/java/android/service/controls/TokenProvider.aidl b/core/java/android/service/controls/TokenProvider.aidl
new file mode 100644
index 0000000..8f4b795
--- /dev/null
+++ b/core/java/android/service/controls/TokenProvider.aidl
@@ -0,0 +1,7 @@
+package android.service.controls;
+
+/** @hide */
+interface TokenProvider {
+    void setAuthToken(String token);
+    String getAccountName();
+}
\ No newline at end of file
diff --git a/core/java/android/service/controls/actions/BooleanAction.aidl b/core/java/android/service/controls/actions/BooleanAction.aidl
deleted file mode 100644
index d1e7e02..0000000
--- a/core/java/android/service/controls/actions/BooleanAction.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.controls.actions;
-
-parcelable BooleanAction;
\ No newline at end of file
diff --git a/core/java/android/service/controls/actions/BooleanAction.java b/core/java/android/service/controls/actions/BooleanAction.java
index fb2c5ad..0259335 100644
--- a/core/java/android/service/controls/actions/BooleanAction.java
+++ b/core/java/android/service/controls/actions/BooleanAction.java
@@ -19,12 +19,10 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Bundle;
-import android.os.Parcel;
 import android.service.controls.templates.ToggleTemplate;
 
 /**
  * Action sent by a {@link ToggleTemplate}
- * @hide
  */
 public final class BooleanAction extends ControlAction {
 
@@ -54,6 +52,10 @@
         mNewState = newState;
     }
 
+    /**
+     * @param b
+     * @hide
+     */
     BooleanAction(Bundle b) {
         super(b);
         mNewState = b.getBoolean(KEY_NEW_STATE);
@@ -77,24 +79,15 @@
         return TYPE;
     }
 
+    /**
+     * @return
+     * @hide
+     */
     @Override
-    protected Bundle getDataBundle() {
+    @NonNull
+    Bundle getDataBundle() {
         Bundle b =  super.getDataBundle();
         b.putBoolean(KEY_NEW_STATE, mNewState);
         return b;
     }
-
-    public static final @NonNull Creator<BooleanAction> CREATOR = new Creator<BooleanAction>() {
-        @Override
-        public BooleanAction createFromParcel(Parcel source) {
-            int type = source.readInt();
-            verifyType(type, TYPE);
-            return new BooleanAction(source.readBundle());
-        }
-
-        @Override
-        public BooleanAction[] newArray(int size) {
-            return new BooleanAction[size];
-        }
-    };
 }
diff --git a/core/java/android/service/controls/actions/CommandAction.java b/core/java/android/service/controls/actions/CommandAction.java
index c69c539..84d6080 100644
--- a/core/java/android/service/controls/actions/CommandAction.java
+++ b/core/java/android/service/controls/actions/CommandAction.java
@@ -19,11 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Bundle;
-import android.os.Parcel;
 
-/**
- * @hide
- */
 public final class CommandAction extends ControlAction {
 
     private static final @ActionType int TYPE = TYPE_COMMAND;
@@ -36,7 +32,11 @@
         this(templateId, null);
     }
 
-    public CommandAction(Bundle b) {
+    /**
+     * @param b
+     * @hide
+     */
+    CommandAction(Bundle b) {
         super(b);
     }
 
@@ -44,18 +44,4 @@
     public int getActionType() {
         return TYPE;
     }
-
-    public static final Creator<CommandAction> CREATOR = new Creator<CommandAction>() {
-        @Override
-        public CommandAction createFromParcel(Parcel source) {
-            int type = source.readInt();
-            verifyType(type, TYPE);
-            return new CommandAction(source.readBundle());
-        }
-
-        @Override
-        public CommandAction[] newArray(int size) {
-            return new CommandAction[size];
-        }
-    };
 }
diff --git a/core/java/android/service/controls/actions/ControlAction.aidl b/core/java/android/service/controls/actions/ControlAction.aidl
deleted file mode 100644
index b012521..0000000
--- a/core/java/android/service/controls/actions/ControlAction.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.controls.actions;
-
-parcelable ControlAction;
\ No newline at end of file
diff --git a/core/java/android/service/controls/actions/ControlAction.java b/core/java/android/service/controls/actions/ControlAction.java
index 83d1cf8..4141da8 100644
--- a/core/java/android/service/controls/actions/ControlAction.java
+++ b/core/java/android/service/controls/actions/ControlAction.java
@@ -21,10 +21,9 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.service.controls.IControlsProviderCallback;
+import android.service.controls.IControlsActionCallback;
 import android.service.controls.templates.ControlTemplate;
+import android.util.Log;
 
 import com.android.internal.util.Preconditions;
 
@@ -36,20 +35,21 @@
  *
  * The action may have a value to authenticate the input, when the provider has requested it to
  * complete the action.
- * @hide
  */
-public abstract class ControlAction implements Parcelable {
+public abstract class ControlAction {
 
+    private static final String TAG = "ControlAction";
+
+    private static final String KEY_ACTION_TYPE = "key_action_type";
     private static final String KEY_TEMPLATE_ID = "key_template_id";
     private static final String KEY_CHALLENGE_VALUE = "key_challenge_value";
 
-
     /**
      * @hide
      */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({
-            TYPE_UNKNOWN,
+            TYPE_ERROR,
             TYPE_BOOLEAN,
             TYPE_FLOAT,
             TYPE_MULTI_FLOAT,
@@ -57,15 +57,16 @@
             TYPE_COMMAND
     })
     public @interface ActionType {};
-    public static final ControlAction UNKNOWN_ACTION = new ControlAction() {
 
+    public static final @NonNull ControlAction ERROR_ACTION = new ControlAction() {
         @Override
         public int getActionType() {
-            return TYPE_UNKNOWN;
+            return TYPE_ERROR;
         }
     };
 
-    public static final @ActionType int TYPE_UNKNOWN = 0;
+    public static final @ActionType int TYPE_ERROR = -1;
+
     /**
      * The identifier of {@link BooleanAction}.
      */
@@ -104,27 +105,27 @@
     public static final @ResponseResult int RESPONSE_UNKNOWN = 0;
 
     /**
-     * Response code for {@link IControlsProviderCallback#onControlActionResponse} indicating that
+     * Response code for {@link IControlsActionCallback#accept} indicating that
      * the action has been performed. The action may still fail later and the state may not change.
      */
     public static final @ResponseResult int RESPONSE_OK = 1;
     /**
-     * Response code for {@link IControlsProviderCallback#onControlActionResponse} indicating that
+     * Response code for {@link IControlsActionCallback#accept} indicating that
      * the action has failed.
      */
     public static final @ResponseResult int RESPONSE_FAIL = 2;
     /**
-     * Response code for {@link IControlsProviderCallback#onControlActionResponse} indicating that
+     * Response code for {@link IControlsActionCallback#accept} indicating that
      * in order for the action to be performed, acknowledgment from the user is required.
      */
     public static final @ResponseResult int RESPONSE_CHALLENGE_ACK = 3;
     /**
-     * Response code for {@link IControlsProviderCallback#onControlActionResponse} indicating that
+     * Response code for {@link IControlsActionCallback#accept} indicating that
      * in order for the action to be performed, a PIN is required.
      */
     public static final @ResponseResult int RESPONSE_CHALLENGE_PIN = 4;
     /**
-     * Response code for {@link IControlsProviderCallback#onControlActionResponse} indicating that
+     * Response code for {@link IControlsActionCallback#accept} indicating that
      * in order for the action to be performed, an alphanumeric passphrase is required.
      */
     public static final @ResponseResult int RESPONSE_CHALLENGE_PASSPHRASE = 5;
@@ -175,68 +176,55 @@
         return mChallengeValue;
     }
 
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public final void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(getActionType());
-        dest.writeBundle(getDataBundle());
-    }
-
     /**
      * Obtain a {@link Bundle} describing this object populated with data.
      *
      * Implementations in subclasses should populate the {@link Bundle} returned by
      * {@link ControlAction}.
      * @return a {@link Bundle} containing the data that represents this object.
+     * @hide
      */
     @CallSuper
-    protected Bundle getDataBundle() {
+    @NonNull
+    Bundle getDataBundle() {
         Bundle b = new Bundle();
+        b.putInt(KEY_ACTION_TYPE, getActionType());
         b.putString(KEY_TEMPLATE_ID, mTemplateId);
         b.putString(KEY_CHALLENGE_VALUE, mChallengeValue);
         return b;
     }
 
-    public static final @NonNull Creator<ControlAction> CREATOR = new Creator<ControlAction>() {
-        @Override
-        public ControlAction createFromParcel(Parcel source) {
-            int type = source.readInt();
-            return createActionFromType(type, source);
+    /**
+     * @param bundle
+     * @return
+     * @hide
+     */
+    @NonNull
+    static ControlAction createActionFromBundle(@NonNull Bundle bundle) {
+        if (bundle == null) {
+            Log.e(TAG, "Null bundle");
+            return ERROR_ACTION;
         }
-
-        @Override
-        public ControlAction[] newArray(int size) {
-            return new ControlAction[size];
-        }
-    };
-
-
-    private static ControlAction createActionFromType(@ActionType int type, Parcel source) {
-        switch(type) {
-            case TYPE_BOOLEAN:
-                return new BooleanAction(source.readBundle());
-            case TYPE_FLOAT:
-                return new FloatAction(source.readBundle());
-            case TYPE_MULTI_FLOAT:
-                return new MultiFloatAction(source.readBundle());
-            case TYPE_MODE:
-                return new ModeAction(source.readBundle());
-            case TYPE_COMMAND:
-                return new CommandAction(source.readBundle());
-            default:
-                source.readBundle();
-                return UNKNOWN_ACTION;
+        int type = bundle.getInt(KEY_ACTION_TYPE, TYPE_ERROR);
+        try {
+            switch (type) {
+                case TYPE_BOOLEAN:
+                    return new BooleanAction(bundle);
+                case TYPE_FLOAT:
+                    return new FloatAction(bundle);
+                case TYPE_MULTI_FLOAT:
+                    return new MultiFloatAction(bundle);
+                case TYPE_MODE:
+                    return new ModeAction(bundle);
+                case TYPE_COMMAND:
+                    return new CommandAction(bundle);
+                case TYPE_ERROR:
+                default:
+                    return ERROR_ACTION;
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Error creating action", e);
+            return ERROR_ACTION;
         }
     }
-
-    protected static void verifyType(@ActionType int type, @ActionType int thisType) {
-        if (type != thisType) {
-            throw new IllegalStateException("The type " + type + "does not match " + thisType);
-        }
-    }
-
 }
diff --git a/core/java/android/service/controls/actions/CommandAction.aidl b/core/java/android/service/controls/actions/ControlActionWrapper.aidl
similarity index 87%
rename from core/java/android/service/controls/actions/CommandAction.aidl
rename to core/java/android/service/controls/actions/ControlActionWrapper.aidl
index 7c1ee41..5ba962d 100644
--- a/core/java/android/service/controls/actions/CommandAction.aidl
+++ b/core/java/android/service/controls/actions/ControlActionWrapper.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.service.controls.actions;
 
-parcelable CommandAction;
\ No newline at end of file
+parcelable ControlActionWrapper;
\ No newline at end of file
diff --git a/core/java/android/service/controls/actions/ControlActionWrapper.java b/core/java/android/service/controls/actions/ControlActionWrapper.java
new file mode 100644
index 0000000..6a3ec86
--- /dev/null
+++ b/core/java/android/service/controls/actions/ControlActionWrapper.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.controls.actions;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * Wrapper for parceling/unparceling {@link ControlAction}.
+ * @hide
+ */
+public final class ControlActionWrapper implements Parcelable {
+
+    private final @NonNull ControlAction mControlAction;
+
+    public ControlActionWrapper(@NonNull ControlAction controlAction) {
+        Preconditions.checkNotNull(controlAction);
+
+        mControlAction = controlAction;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeBundle(mControlAction.getDataBundle());
+    }
+
+    @NonNull
+    public ControlAction getWrappedAction() {
+        return mControlAction;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    public static final @NonNull Creator<ControlActionWrapper> CREATOR =
+            new Creator<ControlActionWrapper>() {
+                @Override
+                public ControlActionWrapper createFromParcel(@NonNull Parcel in) {
+                    return new ControlActionWrapper(
+                            ControlAction.createActionFromBundle(in.readBundle()));
+                }
+
+                @Override
+                public ControlActionWrapper[] newArray(int size) {
+                    return new ControlActionWrapper[size];
+                }
+            };
+}
diff --git a/core/java/android/service/controls/actions/FloatAction.aidl b/core/java/android/service/controls/actions/FloatAction.aidl
deleted file mode 100644
index 2c1e76d..0000000
--- a/core/java/android/service/controls/actions/FloatAction.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.controls.actions;
-
-parcelable FloatAction;
\ No newline at end of file
diff --git a/core/java/android/service/controls/actions/FloatAction.java b/core/java/android/service/controls/actions/FloatAction.java
index 1c3fb4d..5b271ce 100644
--- a/core/java/android/service/controls/actions/FloatAction.java
+++ b/core/java/android/service/controls/actions/FloatAction.java
@@ -19,13 +19,11 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Bundle;
-import android.os.Parcel;
 import android.service.controls.templates.RangeTemplate;
 import android.service.controls.templates.ToggleRangeTemplate;
 
 /**
  * Action sent by a {@link RangeTemplate}, {@link ToggleRangeTemplate}.
- * @hide
  */
 public final class FloatAction extends ControlAction {
 
@@ -56,7 +54,11 @@
         mNewValue = newValue;
     }
 
-    public FloatAction(Bundle b) {
+    /**
+     * @param b
+     * @hide
+     */
+    FloatAction(Bundle b) {
         super(b);
         mNewValue = b.getFloat(KEY_NEW_VALUE);
     }
@@ -76,24 +78,15 @@
         return TYPE;
     }
 
+    /**
+     * @return
+     * @hide
+     */
     @Override
-    protected Bundle getDataBundle() {
+    @NonNull
+    Bundle getDataBundle() {
         Bundle b = super.getDataBundle();
         b.putFloat(KEY_NEW_VALUE, mNewValue);
         return b;
     }
-
-    public static final @NonNull Creator<FloatAction> CREATOR = new Creator<FloatAction>() {
-        @Override
-        public FloatAction createFromParcel(Parcel source) {
-            int type = source.readInt();
-            verifyType(type, TYPE);
-            return new FloatAction(source.readBundle());
-        }
-
-        @Override
-        public FloatAction[] newArray(int size) {
-            return new FloatAction[size];
-        }
-    };
 }
diff --git a/core/java/android/service/controls/actions/ModeAction.aidl b/core/java/android/service/controls/actions/ModeAction.aidl
deleted file mode 100644
index 3ef89e0..0000000
--- a/core/java/android/service/controls/actions/ModeAction.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.controls.actions;
-
-parcelable ModeAction;
\ No newline at end of file
diff --git a/core/java/android/service/controls/actions/ModeAction.java b/core/java/android/service/controls/actions/ModeAction.java
index 0bd1d24..ca40974 100644
--- a/core/java/android/service/controls/actions/ModeAction.java
+++ b/core/java/android/service/controls/actions/ModeAction.java
@@ -19,11 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Bundle;
-import android.os.Parcel;
 
-/**
- * @hide
- */
 public final class ModeAction extends ControlAction {
 
     private static final @ActionType int TYPE = TYPE_MODE;
@@ -45,13 +41,22 @@
         this(templateId, newMode, null);
     }
 
+    /**
+     * @param b
+     * @hide
+     */
     ModeAction(Bundle b) {
         super(b);
         mNewMode = b.getInt(KEY_MODE);
     }
 
+    /**
+     * @return
+     * @hide
+     */
     @Override
-    protected Bundle getDataBundle() {
+    @NonNull
+    Bundle getDataBundle() {
         Bundle b = super.getDataBundle();
         b.putInt(KEY_MODE, mNewMode);
         return b;
@@ -60,18 +65,4 @@
     public int getNewMode() {
         return mNewMode;
     }
-
-    public static final Creator<ModeAction> CREATOR = new Creator<ModeAction>() {
-        @Override
-        public ModeAction createFromParcel(Parcel source) {
-            int type = source.readInt();
-            verifyType(type, TYPE);
-            return new ModeAction(source.readBundle());
-        }
-
-        @Override
-        public ModeAction[] newArray(int size) {
-            return new ModeAction[size];
-        }
-    };
 }
diff --git a/core/java/android/service/controls/actions/MultiFloatAction.aidl b/core/java/android/service/controls/actions/MultiFloatAction.aidl
deleted file mode 100644
index bcba758..0000000
--- a/core/java/android/service/controls/actions/MultiFloatAction.aidl
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.service.controls.actions;
-
-parcelable MultiFloatAction;
\ No newline at end of file
diff --git a/core/java/android/service/controls/actions/MultiFloatAction.java b/core/java/android/service/controls/actions/MultiFloatAction.java
index aef8a78..e574079 100644
--- a/core/java/android/service/controls/actions/MultiFloatAction.java
+++ b/core/java/android/service/controls/actions/MultiFloatAction.java
@@ -19,14 +19,10 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Bundle;
-import android.os.Parcel;
 import android.util.Log;
 
 import com.android.internal.util.Preconditions;
 
-/**
- * @hide
- */
 public final class MultiFloatAction extends ControlAction {
 
     private static final String TAG = "MultiFloatAction";
@@ -58,6 +54,10 @@
         this(templateId, newValues, null);
     }
 
+    /**
+     * @param b
+     * @hide
+     */
     MultiFloatAction(Bundle b) {
         super(b);
         mNewValues = b.getFloatArray(KEY_VALUES);
@@ -68,24 +68,15 @@
         return mNewValues.clone();
     }
 
+    /**
+     * @return
+     * @hide
+     */
     @Override
-    protected Bundle getDataBundle() {
+    @NonNull
+    Bundle getDataBundle() {
         Bundle b = super.getDataBundle();
         b.putFloatArray(KEY_VALUES, mNewValues);
         return b;
     }
-
-    public static final Creator<MultiFloatAction> CREATOR = new Creator<MultiFloatAction>() {
-        @Override
-        public MultiFloatAction createFromParcel(Parcel source) {
-            int type = source.readInt();
-            verifyType(type, TYPE);
-            return new MultiFloatAction(source.readBundle());
-        }
-
-        @Override
-        public MultiFloatAction[] newArray(int size) {
-            return new MultiFloatAction[size];
-        }
-    };
 }
diff --git a/core/java/android/service/controls/templates/ControlButton.java b/core/java/android/service/controls/templates/ControlButton.java
index e03ac6f..157e231 100644
--- a/core/java/android/service/controls/templates/ControlButton.java
+++ b/core/java/android/service/controls/templates/ControlButton.java
@@ -24,7 +24,6 @@
 
 /**
  * Button element for {@link ControlTemplate}.
- * @hide
  */
 public final class ControlButton implements Parcelable {
 
@@ -64,7 +63,8 @@
     }
 
     @Override
-    public void writeToParcel(Parcel dest, int flags) {
+    @NonNull
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeByte(mChecked ? (byte) 1 : (byte) 0);
         dest.writeCharSequence(mActionDescription);
     }
@@ -74,7 +74,7 @@
         mActionDescription = in.readCharSequence();
     }
 
-    public static final Creator<ControlButton> CREATOR = new Creator<ControlButton>() {
+    public static final @NonNull Creator<ControlButton> CREATOR = new Creator<ControlButton>() {
         @Override
         public ControlButton createFromParcel(Parcel source) {
             return new ControlButton(source);
diff --git a/core/java/android/service/controls/templates/ControlTemplate.aidl b/core/java/android/service/controls/templates/ControlTemplate.aidl
deleted file mode 100644
index b6ab280..0000000
--- a/core/java/android/service/controls/templates/ControlTemplate.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.controls.templates;
-
-parcelable ControlTemplate;
\ No newline at end of file
diff --git a/core/java/android/service/controls/templates/ControlTemplate.java b/core/java/android/service/controls/templates/ControlTemplate.java
index bf194f8..d2c0f76 100644
--- a/core/java/android/service/controls/templates/ControlTemplate.java
+++ b/core/java/android/service/controls/templates/ControlTemplate.java
@@ -19,11 +19,11 @@
 import android.annotation.CallSuper;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
 import android.service.controls.Control;
 import android.service.controls.actions.ControlAction;
+import android.util.Log;
 
 import com.android.internal.util.Preconditions;
 
@@ -39,27 +39,37 @@
  * associated state. The actions available to a given {@link Control} are determined by its
  * {@link ControlTemplate}.
  * @see ControlAction
- * @hide
  */
-public abstract class ControlTemplate implements Parcelable {
+public abstract class ControlTemplate {
+
+    private static final String TAG = "ControlTemplate";
 
     private static final String KEY_TEMPLATE_ID = "key_template_id";
+    private static final String KEY_TEMPLATE_TYPE = "key_template_type";
 
     /**
      * Singleton representing a {@link Control} with no input.
      */
-    public static final ControlTemplate NO_TEMPLATE = new ControlTemplate("") {
+    public static final @NonNull ControlTemplate NO_TEMPLATE = new ControlTemplate("") {
         @Override
         public int getTemplateType() {
             return TYPE_NONE;
         }
     };
 
+    public static final @NonNull ControlTemplate ERROR_TEMPLATE = new ControlTemplate("") {
+        @Override
+        public int getTemplateType() {
+            return TYPE_ERROR;
+        }
+    };
+
     /**
      * @hide
      */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({
+            TYPE_ERROR,
             TYPE_NONE,
             TYPE_TOGGLE,
             TYPE_RANGE,
@@ -72,47 +82,50 @@
     })
     public @interface TemplateType {}
 
+    public static final @TemplateType int TYPE_ERROR = -1;
+
     /**
      * Type identifier of {@link ControlTemplate#NO_TEMPLATE}.
      */
-    public static final int TYPE_NONE = 0;
+    public static final @TemplateType int TYPE_NONE = 0;
 
     /**
      * Type identifier of {@link ToggleTemplate}.
      */
-    public static final int TYPE_TOGGLE = 1;
+    public static final @TemplateType int TYPE_TOGGLE = 1;
 
     /**
      * Type identifier of {@link RangeTemplate}.
      */
-    public static final int TYPE_RANGE = 2;
+    public static final @TemplateType int TYPE_RANGE = 2;
 
     /**
      * Type identifier of {@link ThumbnailTemplate}.
      */
-    public static final int TYPE_THUMBNAIL = 3;
+    public static final @TemplateType int TYPE_THUMBNAIL = 3;
 
     /**
      * Type identifier of {@link DiscreteToggleTemplate}.
      */
-    public static final int TYPE_DISCRETE_TOGGLE = 4;
+    public static final @TemplateType int TYPE_DISCRETE_TOGGLE = 4;
 
     /**
      * @hide
      */
-    public static final int TYPE_COORD_RANGE = 5;
+    public static final @TemplateType int TYPE_COORD_RANGE = 5;
 
-    public static final int TYPE_TOGGLE_RANGE = 6;
+    public static final @TemplateType int TYPE_TOGGLE_RANGE = 6;
 
-    public static final int TYPE_TEMPERATURE = 7;
+    public static final @TemplateType int TYPE_TEMPERATURE = 7;
 
-    public static final int TYPE_STATELESS = 8;
+    public static final @TemplateType int TYPE_STATELESS = 8;
 
     private @NonNull final String mTemplateId;
 
     /**
      * @return the identifier for this object.
      */
+    @NonNull
     public String getTemplateId() {
         return mTemplateId;
     }
@@ -122,24 +135,16 @@
      */
     public abstract @TemplateType int getTemplateType();
 
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public final void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(getTemplateType());
-        dest.writeBundle(getDataBundle());
-    }
-
     /**
      * Obtain a {@link Bundle} describing this object populated with data.
      * @return a {@link Bundle} containing the data that represents this object.
+     * @hide
      */
     @CallSuper
-    protected Bundle getDataBundle() {
+    @NonNull
+    Bundle getDataBundle() {
         Bundle b = new Bundle();
+        b.putInt(KEY_TEMPLATE_TYPE, getTemplateType());
         b.putString(KEY_TEMPLATE_ID, mTemplateId);
         return b;
     }
@@ -148,6 +153,10 @@
         mTemplateId = "";
     }
 
+    /**
+     * @param b
+     * @hide
+     */
     ControlTemplate(@NonNull Bundle b) {
         mTemplateId = b.getString(KEY_TEMPLATE_ID);
     }
@@ -160,48 +169,46 @@
         mTemplateId = templateId;
     }
 
-    public static final Creator<ControlTemplate> CREATOR = new Creator<ControlTemplate>() {
-        @Override
-        public ControlTemplate createFromParcel(Parcel source) {
-            int type = source.readInt();
-            return createTemplateFromType(type, source);
+    /**
+     *
+     * @param bundle
+     * @return
+     * @hide
+     */
+    @NonNull
+    static ControlTemplate createTemplateFromBundle(@Nullable Bundle bundle) {
+        if (bundle == null) {
+            Log.e(TAG, "Null bundle");
+            return ERROR_TEMPLATE;
         }
-
-        @Override
-        public ControlTemplate[] newArray(int size) {
-            return new ControlTemplate[size];
-        }
-    };
-
-
-    private static ControlTemplate createTemplateFromType(@TemplateType int type, Parcel source) {
-        switch(type) {
-            case TYPE_TOGGLE:
-                return new ToggleTemplate(source.readBundle());
-            case TYPE_RANGE:
-                return new RangeTemplate(source.readBundle());
-            case TYPE_THUMBNAIL:
-                return new ThumbnailTemplate(source.readBundle());
-            case TYPE_DISCRETE_TOGGLE:
-                return new DiscreteToggleTemplate(source.readBundle());
-            case TYPE_COORD_RANGE:
-                return new CoordinatedRangeTemplate(source.readBundle());
-            case TYPE_TOGGLE_RANGE:
-                return new ToggleRangeTemplate(source.readBundle());
-            case TYPE_TEMPERATURE:
-                return new TemperatureControlTemplate(source.readBundle());
-            case TYPE_STATELESS:
-                return new StatelessTemplate(source.readBundle());
-            case TYPE_NONE:
-            default:
-                source.readBundle();
-                return NO_TEMPLATE;
-        }
-    }
-
-    protected static void verifyType(@TemplateType int type, @TemplateType int thisType) {
-        if (type != thisType) {
-            throw new IllegalStateException("The type " + type + "does not match " + thisType);
+        int type = bundle.getInt(KEY_TEMPLATE_TYPE, TYPE_ERROR);
+        try {
+            switch (type) {
+                case TYPE_TOGGLE:
+                    return new ToggleTemplate(bundle);
+                case TYPE_RANGE:
+                    return new RangeTemplate(bundle);
+                case TYPE_THUMBNAIL:
+                    return new ThumbnailTemplate(bundle);
+                case TYPE_DISCRETE_TOGGLE:
+                    return new DiscreteToggleTemplate(bundle);
+                case TYPE_COORD_RANGE:
+                    return new CoordinatedRangeTemplate(bundle);
+                case TYPE_TOGGLE_RANGE:
+                    return new ToggleRangeTemplate(bundle);
+                case TYPE_TEMPERATURE:
+                    return new TemperatureControlTemplate(bundle);
+                case TYPE_STATELESS:
+                    return new StatelessTemplate(bundle);
+                case TYPE_NONE:
+                    return NO_TEMPLATE;
+                case TYPE_ERROR:
+                default:
+                    return ERROR_TEMPLATE;
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Error creating template", e);
+            return ERROR_TEMPLATE;
         }
     }
 }
diff --git a/core/java/android/service/controls/templates/ToggleRangeTemplate.aidl b/core/java/android/service/controls/templates/ControlTemplateWrapper.aidl
similarity index 87%
rename from core/java/android/service/controls/templates/ToggleRangeTemplate.aidl
rename to core/java/android/service/controls/templates/ControlTemplateWrapper.aidl
index 2611284..208ca4e 100644
--- a/core/java/android/service/controls/templates/ToggleRangeTemplate.aidl
+++ b/core/java/android/service/controls/templates/ControlTemplateWrapper.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,4 +16,4 @@
 
 package android.service.controls.templates;
 
-parcelable ToggleRangeTemplate;
\ No newline at end of file
+parcelable ControlTemplateWrapper;
\ No newline at end of file
diff --git a/core/java/android/service/controls/templates/ControlTemplateWrapper.java b/core/java/android/service/controls/templates/ControlTemplateWrapper.java
new file mode 100644
index 0000000..7957260
--- /dev/null
+++ b/core/java/android/service/controls/templates/ControlTemplateWrapper.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.controls.templates;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * Wrapper for parceling/unparceling {@link ControlTemplate}.
+ * @hide
+ */
+public final class ControlTemplateWrapper implements Parcelable {
+
+    private final @NonNull ControlTemplate mControlTemplate;
+
+    public ControlTemplateWrapper(@NonNull ControlTemplate template) {
+        Preconditions.checkNotNull(template);
+        mControlTemplate = template;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @NonNull
+    public ControlTemplate getWrappedTemplate() {
+        return mControlTemplate;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeBundle(mControlTemplate.getDataBundle());
+    }
+
+    public static final @NonNull Creator<ControlTemplateWrapper> CREATOR =
+            new Creator<ControlTemplateWrapper>() {
+        @Override
+        public ControlTemplateWrapper createFromParcel(@NonNull Parcel source) {
+            return new ControlTemplateWrapper(
+                    ControlTemplate.createTemplateFromBundle(source.readBundle()));
+        }
+
+        @Override
+        public ControlTemplateWrapper[] newArray(int size) {
+            return new ControlTemplateWrapper[size];
+        }
+    };
+}
diff --git a/core/java/android/service/controls/templates/CoordinatedRangeTemplate.aidl b/core/java/android/service/controls/templates/CoordinatedRangeTemplate.aidl
deleted file mode 100644
index 972142c..0000000
--- a/core/java/android/service/controls/templates/CoordinatedRangeTemplate.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.controls.templates;
-
-parcelable CoordinatedRangeTemplate;
\ No newline at end of file
diff --git a/core/java/android/service/controls/templates/CoordinatedRangeTemplate.java b/core/java/android/service/controls/templates/CoordinatedRangeTemplate.java
index 3d820c4..6aa5480 100644
--- a/core/java/android/service/controls/templates/CoordinatedRangeTemplate.java
+++ b/core/java/android/service/controls/templates/CoordinatedRangeTemplate.java
@@ -19,12 +19,8 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Bundle;
-import android.os.Parcel;
 import android.util.Log;
 
-/**
- * @hide
- */
 public final class CoordinatedRangeTemplate extends ControlTemplate {
 
     private static final String TAG = "CoordinatedRangeTemplate";
@@ -74,10 +70,14 @@
                 minValueHigh, maxValueHigh, currentValueHigh, stepValue, formatString));
     }
 
+    /**
+     * @param b
+     * @hide
+     */
     CoordinatedRangeTemplate(Bundle b) {
         super(b);
-        mRangeLow = b.getParcelable(KEY_RANGE_LOW);
-        mRangeHigh = b.getParcelable(KEY_RANGE_HIGH);
+        mRangeLow = new RangeTemplate(b.getBundle(KEY_RANGE_LOW));
+        mRangeHigh = new RangeTemplate(b.getBundle(KEY_RANGE_HIGH));
         mMinGap = b.getFloat(KEY_MIN_GAP);
         validateRanges();
     }
@@ -134,11 +134,16 @@
         return TYPE;
     }
 
+    /**
+     * @return
+     * @hide
+     */
     @Override
-    protected Bundle getDataBundle() {
+    @NonNull
+    Bundle getDataBundle() {
         Bundle b = super.getDataBundle();
-        b.putParcelable(KEY_RANGE_LOW, mRangeLow);
-        b.putParcelable(KEY_RANGE_HIGH, mRangeHigh);
+        b.putBundle(KEY_RANGE_LOW, mRangeLow.getDataBundle());
+        b.putBundle(KEY_RANGE_HIGH, mRangeHigh.getDataBundle());
         return b;
     }
 
@@ -160,18 +165,4 @@
         }
     }
 
-    public static final Creator<CoordinatedRangeTemplate> CREATOR =
-            new Creator<CoordinatedRangeTemplate>() {
-        @Override
-        public CoordinatedRangeTemplate createFromParcel(Parcel source) {
-            int type = source.readInt();
-            verifyType(type, TYPE);
-            return new CoordinatedRangeTemplate(source.readBundle());
-        }
-
-        @Override
-        public CoordinatedRangeTemplate[] newArray(int size) {
-            return new CoordinatedRangeTemplate[size];
-        }
-    };
 }
diff --git a/core/java/android/service/controls/templates/DiscreteToggleTemplate.aidl b/core/java/android/service/controls/templates/DiscreteToggleTemplate.aidl
deleted file mode 100644
index d22e375..0000000
--- a/core/java/android/service/controls/templates/DiscreteToggleTemplate.aidl
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.service.controls.templates;
-
-parcelable DiscreteToggleTemplate;
\ No newline at end of file
diff --git a/core/java/android/service/controls/templates/DiscreteToggleTemplate.java b/core/java/android/service/controls/templates/DiscreteToggleTemplate.java
index a8c193c..7a1331a 100644
--- a/core/java/android/service/controls/templates/DiscreteToggleTemplate.java
+++ b/core/java/android/service/controls/templates/DiscreteToggleTemplate.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.os.Bundle;
-import android.os.Parcel;
 import android.service.controls.Control;
 import android.service.controls.actions.BooleanAction;
 
@@ -33,9 +32,8 @@
  * {@link BooleanAction#getNewState} will be {@code false} if the button was
  * {@link DiscreteToggleTemplate#getNegativeButton} and {@code true} if the button was
  * {@link DiscreteToggleTemplate#getPositiveButton}.
- * @hide
  */
-public class DiscreteToggleTemplate extends ControlTemplate {
+public final class DiscreteToggleTemplate extends ControlTemplate {
 
     private static final @TemplateType int TYPE = TYPE_DISCRETE_TOGGLE;
     private static final String KEY_NEGATIVE_BUTTON = "key_negative_button";
@@ -46,8 +44,8 @@
 
     /**
      * @param templateId the identifier for this template object
-     * @param negativeButton a {@ControlButton} for the <i>Negative</i> input
-     * @param positiveButton a {@ControlButton} for the <i>Positive</i> input
+     * @param negativeButton a {@link ControlButton} for the <i>Negative</i> input
+     * @param positiveButton a {@link ControlButton} for the <i>Positive</i> input
      */
     public DiscreteToggleTemplate(@NonNull String templateId,
             @NonNull ControlButton negativeButton,
@@ -59,6 +57,10 @@
         mPositiveButton = positiveButton;
     }
 
+    /**
+     * @param b
+     * @hide
+     */
     DiscreteToggleTemplate(Bundle b) {
         super(b);
         mNegativeButton = b.getParcelable(KEY_NEGATIVE_BUTTON);
@@ -89,32 +91,17 @@
         return TYPE;
     }
 
-
+    /**
+     * @return
+     * @hide
+     */
     @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    protected Bundle getDataBundle() {
+    @NonNull
+    Bundle getDataBundle() {
         Bundle b = super.getDataBundle();
         b.putParcelable(KEY_NEGATIVE_BUTTON, mNegativeButton);
         b.putParcelable(KEY_POSITIVE_BUTTON, mPositiveButton);
         return b;
     }
 
-    public static final Creator<DiscreteToggleTemplate> CREATOR =
-            new Creator<DiscreteToggleTemplate>() {
-                @Override
-                public DiscreteToggleTemplate createFromParcel(Parcel source) {
-                    int type = source.readInt();
-                    verifyType(type, TYPE);
-                    return new DiscreteToggleTemplate(source.readBundle());
-                }
-
-                @Override
-                public DiscreteToggleTemplate[] newArray(int size) {
-                    return new DiscreteToggleTemplate[size];
-                }
-            };
 }
diff --git a/core/java/android/service/controls/templates/RangeTemplate.aidl b/core/java/android/service/controls/templates/RangeTemplate.aidl
deleted file mode 100644
index 9928815..0000000
--- a/core/java/android/service/controls/templates/RangeTemplate.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.controls.templates;
-
-parcelable RangeTemplate;
\ No newline at end of file
diff --git a/core/java/android/service/controls/templates/RangeTemplate.java b/core/java/android/service/controls/templates/RangeTemplate.java
index bb79d83..fe0d167 100644
--- a/core/java/android/service/controls/templates/RangeTemplate.java
+++ b/core/java/android/service/controls/templates/RangeTemplate.java
@@ -27,7 +27,6 @@
  * A template for a {@link Control} with inputs in a "continuous" range of values.
  *
  * @see FloatAction
- * @hide
  */
 public final class RangeTemplate extends ControlTemplate {
 
@@ -148,8 +147,13 @@
         return TYPE;
     }
 
+    /**
+     * @return
+     * @hide
+     */
     @Override
-    protected Bundle getDataBundle() {
+    @NonNull
+    Bundle getDataBundle() {
         Bundle b = super.getDataBundle();
         b.putFloat(KEY_MIN_VALUE, mMinValue);
         b.putFloat(KEY_MAX_VALUE, mMaxValue);
@@ -181,18 +185,4 @@
             throw new IllegalArgumentException(String.format("stepValue=%f <= 0", mStepValue));
         }
     }
-
-    public static final Creator<RangeTemplate> CREATOR = new Creator<RangeTemplate>() {
-        @Override
-        public RangeTemplate createFromParcel(Parcel source) {
-            int type = source.readInt();
-            verifyType(type, TYPE);
-            return new RangeTemplate(source.readBundle());
-        }
-
-        @Override
-        public RangeTemplate[] newArray(int size) {
-            return new RangeTemplate[size];
-        }
-    };
 }
diff --git a/core/java/android/service/controls/templates/StatelessTemplate.aidl b/core/java/android/service/controls/templates/StatelessTemplate.aidl
deleted file mode 100644
index 02e18d9..0000000
--- a/core/java/android/service/controls/templates/StatelessTemplate.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.controls.templates;
-
-parcelable StatelessTemplate;
\ No newline at end of file
diff --git a/core/java/android/service/controls/templates/StatelessTemplate.java b/core/java/android/service/controls/templates/StatelessTemplate.java
index 12ab9bc..3f98bea 100644
--- a/core/java/android/service/controls/templates/StatelessTemplate.java
+++ b/core/java/android/service/controls/templates/StatelessTemplate.java
@@ -18,11 +18,7 @@
 
 import android.annotation.NonNull;
 import android.os.Bundle;
-import android.os.Parcel;
 
-/**
- * @hide
- */
 public final class StatelessTemplate extends ControlTemplate {
 
     @Override
@@ -30,23 +26,15 @@
         return TYPE_STATELESS;
     }
 
-    public StatelessTemplate(@NonNull Bundle b) {
+    /**
+     * @param b
+     * @hide
+     */
+    StatelessTemplate(@NonNull Bundle b) {
         super(b);
     }
 
     public StatelessTemplate(@NonNull String templateId) {
         super(templateId);
     }
-
-    public static final Creator<StatelessTemplate> CREATOR = new Creator<StatelessTemplate>() {
-        @Override
-        public StatelessTemplate createFromParcel(Parcel source) {
-            return new StatelessTemplate(source.readBundle());
-        }
-
-        @Override
-        public StatelessTemplate[] newArray(int size) {
-            return new StatelessTemplate[size];
-        }
-    };
 }
diff --git a/core/java/android/service/controls/templates/TemperatureControlTemplate.aidl b/core/java/android/service/controls/templates/TemperatureControlTemplate.aidl
deleted file mode 100644
index 7994d26..0000000
--- a/core/java/android/service/controls/templates/TemperatureControlTemplate.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.controls.templates;
-
-parcelable TemperatureControlTemplate;
\ No newline at end of file
diff --git a/core/java/android/service/controls/templates/TemperatureControlTemplate.java b/core/java/android/service/controls/templates/TemperatureControlTemplate.java
index 987621e..9d8dca62 100644
--- a/core/java/android/service/controls/templates/TemperatureControlTemplate.java
+++ b/core/java/android/service/controls/templates/TemperatureControlTemplate.java
@@ -19,7 +19,6 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.os.Bundle;
-import android.os.Parcel;
 import android.util.Log;
 
 import com.android.internal.util.Preconditions;
@@ -27,9 +26,6 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
-/**
- * @hide
- */
 public final class TemperatureControlTemplate extends ControlTemplate {
 
     private static final String TAG = "ThermostatTemplate";
@@ -67,6 +63,9 @@
 
     public static final @Mode int MODE_ECO = 5;
 
+    /**
+     * @hide
+     */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(flag = true, value = {
             FLAG_MODE_OFF,
@@ -136,18 +135,27 @@
         }
     }
 
+    /**
+     * @param b
+     * @hide
+     */
     TemperatureControlTemplate(@NonNull Bundle b) {
         super(b);
-        mTemplate = b.getParcelable(KEY_TEMPLATE);
+        mTemplate = ControlTemplate.createTemplateFromBundle(b.getBundle(KEY_TEMPLATE));
         mCurrentMode = b.getInt(KEY_CURRENT_MODE);
         mCurrentActiveMode = b.getInt(KEY_CURRENT_ACTIVE_MODE);
         mModes = b.getInt(KEY_MODES);
     }
 
+    /**
+     * @return
+     * @hide
+     */
     @Override
-    protected Bundle getDataBundle() {
+    @NonNull
+    Bundle getDataBundle() {
         Bundle b = super.getDataBundle();
-        b.putParcelable(KEY_TEMPLATE, mTemplate);
+        b.putBundle(KEY_TEMPLATE, mTemplate.getDataBundle());
         b.putInt(KEY_CURRENT_MODE, mCurrentMode);
         b.putInt(KEY_CURRENT_ACTIVE_MODE, mCurrentActiveMode);
         b.putInt(KEY_MODES, mModes);
@@ -175,18 +183,4 @@
     public int getTemplateType() {
         return TYPE;
     }
-
-    public static final Creator<TemperatureControlTemplate> CREATOR = new Creator<TemperatureControlTemplate>() {
-        @Override
-        public TemperatureControlTemplate createFromParcel(Parcel source) {
-            int type = source.readInt();
-            verifyType(type, TYPE);
-            return new TemperatureControlTemplate(source.readBundle());
-        }
-
-        @Override
-        public TemperatureControlTemplate[] newArray(int size) {
-            return new TemperatureControlTemplate[size];
-        }
-    };
 }
diff --git a/core/java/android/service/controls/templates/ThumbnailTemplate.aidl b/core/java/android/service/controls/templates/ThumbnailTemplate.aidl
deleted file mode 100644
index 81c879b..0000000
--- a/core/java/android/service/controls/templates/ThumbnailTemplate.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.controls.templates;
-
-parcelable ThumbnailTemplate;
\ No newline at end of file
diff --git a/core/java/android/service/controls/templates/ThumbnailTemplate.java b/core/java/android/service/controls/templates/ThumbnailTemplate.java
index 111d60d..72179f4 100644
--- a/core/java/android/service/controls/templates/ThumbnailTemplate.java
+++ b/core/java/android/service/controls/templates/ThumbnailTemplate.java
@@ -19,15 +19,12 @@
 import android.annotation.NonNull;
 import android.graphics.drawable.Icon;
 import android.os.Bundle;
-import android.os.Parcel;
 import android.service.controls.Control;
 
 import com.android.internal.util.Preconditions;
 
 /**
  * A template for a {@link Control} that displays an image.
- *
- * @hide
  */
 public final class ThumbnailTemplate extends ControlTemplate {
 
@@ -52,6 +49,10 @@
         mContentDescription = contentDescription;
     }
 
+    /**
+     * @param b
+     * @hide
+     */
     ThumbnailTemplate(Bundle b) {
         super(b);
         mThumbnail = b.getParcelable(KEY_ICON);
@@ -82,25 +83,16 @@
         return TYPE;
     }
 
+    /**
+     * @return
+     * @hide
+     */
     @Override
-    protected Bundle getDataBundle() {
+    @NonNull
+    Bundle getDataBundle() {
         Bundle b = super.getDataBundle();
         b.putObject(KEY_ICON, mThumbnail);
         b.putObject(KEY_CONTENT_DESCRIPTION, mContentDescription);
         return b;
     }
-
-    public static final Creator<ThumbnailTemplate> CREATOR = new Creator<ThumbnailTemplate>() {
-        @Override
-        public ThumbnailTemplate createFromParcel(Parcel source) {
-            int type = source.readInt();
-            verifyType(type, TYPE);
-            return new ThumbnailTemplate(source.readBundle());
-        }
-
-        @Override
-        public ThumbnailTemplate[] newArray(int size) {
-            return new ThumbnailTemplate[size];
-        }
-    };
 }
diff --git a/core/java/android/service/controls/templates/ToggleRangeTemplate.java b/core/java/android/service/controls/templates/ToggleRangeTemplate.java
index aa6f6fb..af43b94 100644
--- a/core/java/android/service/controls/templates/ToggleRangeTemplate.java
+++ b/core/java/android/service/controls/templates/ToggleRangeTemplate.java
@@ -18,13 +18,9 @@
 
 import android.annotation.NonNull;
 import android.os.Bundle;
-import android.os.Parcel;
 
 import com.android.internal.util.Preconditions;
 
-/**
- * @hide
- */
 public final class ToggleRangeTemplate extends ControlTemplate {
 
     private static final @TemplateType int TYPE = TYPE_TOGGLE_RANGE;
@@ -34,11 +30,14 @@
     private @NonNull final ControlButton mControlButton;
     private @NonNull final RangeTemplate mRangeTemplate;
 
-
+    /**
+     * @param b
+     * @hide
+     */
     ToggleRangeTemplate(@NonNull Bundle b) {
         super(b);
         mControlButton = b.getParcelable(KEY_BUTTON);
-        mRangeTemplate = b.getParcelable(KEY_RANGE);
+        mRangeTemplate = new RangeTemplate(b.getBundle(KEY_RANGE));
     }
 
     public ToggleRangeTemplate(@NonNull String templateId,
@@ -60,11 +59,16 @@
                 range);
     }
 
+    /**
+     * @return
+     * @hide
+     */
     @Override
-    protected Bundle getDataBundle() {
+    @NonNull
+    Bundle getDataBundle() {
         Bundle b = super.getDataBundle();
         b.putParcelable(KEY_BUTTON, mControlButton);
-        b.putParcelable(KEY_RANGE, mRangeTemplate);
+        b.putBundle(KEY_RANGE, mRangeTemplate.getDataBundle());
         return b;
     }
 
@@ -86,19 +90,4 @@
     public int getTemplateType() {
         return TYPE;
     }
-
-    public static final Creator<ToggleRangeTemplate> CREATOR = new Creator<ToggleRangeTemplate>() {
-
-        @Override
-        public ToggleRangeTemplate createFromParcel(Parcel source) {
-            int type = source.readInt();
-            verifyType(type, TYPE);
-            return new ToggleRangeTemplate(source.readBundle());
-        }
-
-        @Override
-        public ToggleRangeTemplate[] newArray(int size) {
-            return new ToggleRangeTemplate[size];
-        }
-    };
 }
diff --git a/core/java/android/service/controls/templates/ToggleTemplate.java b/core/java/android/service/controls/templates/ToggleTemplate.java
index 0e5fd33..e4aa6b0 100644
--- a/core/java/android/service/controls/templates/ToggleTemplate.java
+++ b/core/java/android/service/controls/templates/ToggleTemplate.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.os.Bundle;
-import android.os.Parcel;
 import android.service.controls.Control;
 import android.service.controls.actions.BooleanAction;
 
@@ -31,7 +30,6 @@
  * An action on this template will originate a {@link BooleanAction} to change that state.
  *
  * @see BooleanAction
- * @hide
  */
 public final class ToggleTemplate extends ControlTemplate {
 
@@ -41,7 +39,7 @@
 
     /**
      * @param templateId the identifier for this template object
-     * @param button a {@ControlButton} that can show the current state and toggle it
+     * @param button a {@link ControlButton} that can show the current state and toggle it
      */
     public ToggleTemplate(@NonNull String templateId, @NonNull ControlButton button) {
         super(templateId);
@@ -49,6 +47,10 @@
         mButton = button;
     }
 
+    /**
+     * @param b
+     * @hide
+     */
     ToggleTemplate(Bundle b) {
         super(b);
         mButton = b.getParcelable(KEY_BUTTON);
@@ -58,6 +60,7 @@
         return mButton.isChecked();
     }
 
+    @NonNull
     public CharSequence getContentDescription() {
         return mButton.getActionDescription();
     }
@@ -70,25 +73,15 @@
         return TYPE;
     }
 
+    /**
+     * @return
+     * @hide
+     */
     @Override
-    protected Bundle getDataBundle() {
+    @NonNull
+    Bundle getDataBundle() {
         Bundle b =  super.getDataBundle();
         b.putParcelable(KEY_BUTTON, mButton);
         return b;
     }
-
-    public static final Creator<ToggleTemplate> CREATOR = new Creator<ToggleTemplate>() {
-        @Override
-        public ToggleTemplate createFromParcel(Parcel source) {
-            int type = source.readInt();
-            verifyType(type, TYPE);
-            return new ToggleTemplate(source.readBundle());
-        }
-
-        @Override
-        public ToggleTemplate[] newArray(int size) {
-            return new ToggleTemplate[size];
-        }
-    };
-
 }
diff --git a/core/java/android/service/dataloader/DataLoaderService.java b/core/java/android/service/dataloader/DataLoaderService.java
index 75f252e..c215778 100644
--- a/core/java/android/service/dataloader/DataLoaderService.java
+++ b/core/java/android/service/dataloader/DataLoaderService.java
@@ -58,6 +58,7 @@
      * Managed DataLoader interface. Each instance corresponds to a single installation session.
      * @hide
      */
+    @SystemApi
     public interface DataLoader {
         /**
          * A virtual constructor.
@@ -78,8 +79,8 @@
          * @param removedFiles list of files removed in this installation session.
          * @return false if unable to create and populate all addedFiles.
          */
-        boolean onPrepareImage(Collection<InstallationFile> addedFiles,
-                Collection<String> removedFiles);
+        boolean onPrepareImage(@NonNull Collection<InstallationFile> addedFiles,
+                @NonNull Collection<String> removedFiles);
     }
 
     /**
@@ -88,6 +89,7 @@
      * @return An instance of a DataLoader.
      * @hide
      */
+    @SystemApi
     public @Nullable DataLoader onCreateDataLoader() {
         return null;
     }
@@ -188,6 +190,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final class FileSystemConnector {
         /**
          * Create a wrapper for a native instance.
@@ -211,8 +214,8 @@
          * @throws IOException if trouble opening the file for writing, such as lack of disk space
          *                     or unavailable media.
          */
-        public void writeData(String name, long offsetBytes, long lengthBytes,
-                ParcelFileDescriptor incomingFd) throws IOException {
+        public void writeData(@NonNull String name, long offsetBytes, long lengthBytes,
+                @NonNull ParcelFileDescriptor incomingFd) throws IOException {
             try {
                 nativeWriteData(mNativeInstance, name, offsetBytes, lengthBytes, incomingFd);
             } catch (RuntimeException e) {
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index 4f400a8..c5d97b7 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -17,7 +17,8 @@
 package android.service.notification;
 
 import static android.app.NotificationChannel.PLACEHOLDER_CONVERSATION_ID;
-import static android.util.FeatureFlagUtils.*;
+import static android.util.FeatureFlagUtils.NOTIF_CONVO_BYPASS_SHORTCUT_REQ;
+import static android.util.FeatureFlagUtils.isEnabled;
 
 import android.annotation.NonNull;
 import android.app.Notification;
@@ -33,7 +34,6 @@
 import android.os.Parcelable;
 import android.os.UserHandle;
 import android.text.TextUtils;
-import android.util.FeatureFlagUtils;
 
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -454,11 +454,23 @@
         return conversationId;
     }
 
-    private String getGroupLogTag() {
+    /**
+     *  Returns a probably-unique string based on the notification's group name,
+     *  with no more than MAX_LOG_TAG_LENGTH characters.
+     * @return String based on group name of notification.
+     * @hide
+     */
+    public String getGroupLogTag() {
         return shortenTag(getGroup());
     }
 
-    private String getChannelIdLogTag() {
+    /**
+     *  Returns a probably-unique string based on the notification's channel ID,
+     *  with no more than MAX_LOG_TAG_LENGTH characters.
+     * @return String based on channel ID of notification.
+     * @hide
+     */
+    public String getChannelIdLogTag() {
         if (notification.getChannelId() == null) {
             return null;
         }
diff --git a/core/java/android/service/quicksettings/Tile.java b/core/java/android/service/quicksettings/Tile.java
index 79c2152..40c0ac0 100644
--- a/core/java/android/service/quicksettings/Tile.java
+++ b/core/java/android/service/quicksettings/Tile.java
@@ -65,6 +65,7 @@
     private CharSequence mLabel;
     private CharSequence mSubtitle;
     private CharSequence mContentDescription;
+    private CharSequence mStateDescription;
     // Default to inactive until clients of the new API can update.
     private int mState = STATE_INACTIVE;
 
@@ -177,6 +178,14 @@
     }
 
     /**
+     * Gets the current state description for the tile.
+     */
+    @Nullable
+    public CharSequence getStateDescription() {
+        return mStateDescription;
+    }
+
+    /**
      * Sets the current content description for the tile.
      *
      * Does not take effect until {@link #updateTile()} is called.
@@ -187,6 +196,17 @@
         this.mContentDescription = contentDescription;
     }
 
+    /**
+     * Sets the current state description for the tile.
+     *
+     * Does not take effect until {@link #updateTile()} is called.
+     *
+     * @param stateDescription New state description to use.
+     */
+    public void setStateDescription(@Nullable CharSequence stateDescription) {
+        this.mStateDescription = stateDescription;
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -215,6 +235,7 @@
         TextUtils.writeToParcel(mLabel, dest, flags);
         TextUtils.writeToParcel(mSubtitle, dest, flags);
         TextUtils.writeToParcel(mContentDescription, dest, flags);
+        TextUtils.writeToParcel(mStateDescription, dest, flags);
     }
 
     private void readFromParcel(Parcel source) {
@@ -227,6 +248,7 @@
         mLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
         mSubtitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
         mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
+        mStateDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
     }
 
     public static final @android.annotation.NonNull Creator<Tile> CREATOR = new Creator<Tile>() {
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index dd78c78..e9285cc 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -223,6 +223,9 @@
 
         SurfaceControl mSurfaceControl = new SurfaceControl();
 
+        // Unused relayout out-param
+        SurfaceControl mTmpSurfaceControl = new SurfaceControl();
+
         final BaseSurfaceHolder mSurfaceHolder = new BaseSurfaceHolder() {
             {
                 mRequestedFormat = PixelFormat.RGBX_8888;
@@ -902,7 +905,7 @@
                             View.VISIBLE, 0, -1, mWinFrame, mContentInsets,
                             mVisibleInsets, mStableInsets, mBackdropFrame,
                             mDisplayCutout, mMergedConfiguration, mSurfaceControl,
-                            mInsetsState, mSurfaceSize);
+                            mInsetsState, mSurfaceSize, mTmpSurfaceControl);
                     if (mSurfaceControl.isValid()) {
                         mSurfaceHolder.mSurface.copyFrom(mSurfaceControl);
                         mSurfaceControl.release();
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index 7815864..26c8314 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -1259,6 +1259,7 @@
     @Override
     public IBinder onBind(Intent intent) {
         if (TextToSpeech.Engine.INTENT_ACTION_TTS_SERVICE.equals(intent.getAction())) {
+            Binder.allowBlocking(mBinder.asBinder());
             return mBinder;
         }
         return null;
diff --git a/core/java/android/telephony/CellBroadcastIntents.java b/core/java/android/telephony/CellBroadcastIntents.java
index 8446253..2e08108 100644
--- a/core/java/android/telephony/CellBroadcastIntents.java
+++ b/core/java/android/telephony/CellBroadcastIntents.java
@@ -16,22 +16,23 @@
 
 package android.telephony;
 
+import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.app.AppOpsManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
 import android.os.Handler;
 import android.os.UserHandle;
+import android.provider.Telephony;
 
 /**
  * A static helper class used to send Intents with prepopulated flags.
  * <p>
- * This is intended to be used by the CellBroadcastService and will throw a security exception if
- * used from a UID besides the network stack UID.
+ * This is intended to be used by the CellBroadcastService and does nothing if the caller does not
+ * have permission to broadcast {@link Telephony.Sms.Intents.SMS_CB_RECEIVED_ACTION}.
  *
  * @hide
  */
@@ -39,6 +40,8 @@
 public class CellBroadcastIntents {
     private static final String LOG_TAG = "CellBroadcastIntents";
 
+    private static final String EXTRA_MESSAGE = "message";
+
     /**
      * @hide
      */
@@ -46,50 +49,71 @@
     }
 
     /**
-     * Returns an intent which can be received by background BroadcastReceivers. This is only
-     * intended to be used by the CellBroadcastService and will throw a security exception if called
-     * from another UID.
+     * Broadcasts an SMS_CB_RECEIVED_ACTION intent which can be received by background
+     * BroadcastReceivers. This is only intended to be used by the CellBroadcastService and will
+     * do nothing if the caller does not have permission to broadcast
+     * {@link Telephony.Sms.Intents.SMS_CB_RECEIVED_ACTION}.
      *
      * @param context            The context from which to send the broadcast
      * @param user               The user from which to send the broadcast
-     * @param intent             The Intent to broadcast; all receivers matching this Intent will
-     *                           receive the broadcast.
-     * @param receiverPermission String naming a permissions that a receiver must hold in order to
-     *                           receive your broadcast. If null, no permission is required.
-     * @param receiverAppOp      The app op associated with the broadcast. If null, no appOp is
-     *                           required. If both receiverAppOp and receiverPermission are
-     *                           non-null, a receiver must have both of them to receive the
-     *                           broadcast
+     * @param smsCbMessage       The SmsCbMessage to include with the intent
      * @param resultReceiver     Your own BroadcastReceiver to treat as the final receiver of the
      *                           broadcast.
      * @param scheduler          A custom Handler with which to schedule the resultReceiver
      *                           callback; if null it will be scheduled in the Context's main
      *                           thread.
      * @param initialCode        An initial value for the result code.  Often Activity.RESULT_OK.
-     * @param initialData        An initial value for the result data.  Often null.
-     * @param initialExtras      An initial value for the result extras.  Often null.
+     * @param slotIndex          The slot index to include in the intent
      */
-    public static void sendOrderedBroadcastForBackgroundReceivers(@NonNull Context context,
-            @Nullable UserHandle user, @NonNull Intent intent, @Nullable String receiverPermission,
-            @Nullable String receiverAppOp, @Nullable BroadcastReceiver resultReceiver,
-            @Nullable Handler scheduler, int initialCode, @Nullable String initialData,
-            @Nullable Bundle initialExtras) {
-        int status = context.checkCallingOrSelfPermission(
-                "android.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS");
-        if (status == PackageManager.PERMISSION_DENIED) {
-            throw new SecurityException(
-                    "Caller does not have permission to send broadcast for background receivers");
-        }
-        Intent backgroundIntent = new Intent(intent);
+    public static void sendSmsCbReceivedBroadcast(@NonNull Context context,
+            @Nullable UserHandle user, @NonNull SmsCbMessage smsCbMessage,
+            @Nullable BroadcastReceiver resultReceiver, @Nullable Handler scheduler,
+            int initialCode, int slotIndex) {
+        Intent backgroundIntent = new Intent(Telephony.Sms.Intents.SMS_CB_RECEIVED_ACTION);
+        backgroundIntent.putExtra(EXTRA_MESSAGE, smsCbMessage);
         backgroundIntent.setFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+        putPhoneIdAndSubIdExtra(context, backgroundIntent, slotIndex);
+
+        String receiverPermission = Manifest.permission.RECEIVE_SMS;
+        String receiverAppOp = AppOpsManager.OPSTR_RECEIVE_SMS;
         if (user != null) {
             context.createContextAsUser(user, 0).sendOrderedBroadcast(backgroundIntent,
                     receiverPermission, receiverAppOp, resultReceiver, scheduler, initialCode,
-                    initialData, initialExtras);
+                    null, null);
         } else {
             context.sendOrderedBroadcast(backgroundIntent, receiverPermission,
-                    receiverAppOp, resultReceiver, scheduler, initialCode, initialData,
-                    initialExtras);
+                    receiverAppOp, resultReceiver, scheduler, initialCode, null, null);
+        }
+    }
+
+    /**
+     * Put the phone ID and sub ID into an intent as extras.
+     */
+    private static void putPhoneIdAndSubIdExtra(Context context, Intent intent, int phoneId) {
+        int subId = getSubIdForPhone(context, phoneId);
+        if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            intent.putExtra("subscription", subId);
+            intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
+        }
+        intent.putExtra("phone", phoneId);
+        intent.putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, phoneId);
+    }
+
+    /**
+     * Get the subscription ID for a phone ID, or INVALID_SUBSCRIPTION_ID if the phone does not
+     * have an active sub
+     * @param phoneId the phoneId to use
+     * @return the associated sub id
+     */
+    private static int getSubIdForPhone(Context context, int phoneId) {
+        SubscriptionManager subMan =
+                (SubscriptionManager) context.getSystemService(
+                        Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+        int[] subIds = subMan.getSubscriptionIds(phoneId);
+        if (subIds != null) {
+            return subIds[0];
+        } else {
+            return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
         }
     }
 }
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index 5737591..4024db1 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -20,8 +20,12 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.compat.Compatibility;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
 import android.content.Context;
 import android.os.Binder;
+import android.os.Build;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.telephony.Annotation.ApnType;
@@ -36,6 +40,7 @@
 import android.telephony.Annotation.SimActivationState;
 import android.telephony.Annotation.SrvccState;
 import android.telephony.data.ApnSetting;
+import android.telephony.emergency.EmergencyNumber;
 import android.telephony.ims.ImsReasonInfo;
 import android.util.Log;
 
@@ -198,6 +203,42 @@
     }
 
     /**
+     * To check the SDK version for {@link #listenForSubscriber}.
+     */
+    @ChangeId
+    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.P)
+    private static final long LISTEN_CODE_CHANGE = 147600208L;
+
+    /**
+     * Listen for incoming subscriptions
+     * @param subId Subscription ID
+     * @param pkg Package name
+     * @param featureId Feature ID
+     * @param listener Listener providing callback
+     * @param events Events
+     * @param notifyNow Whether to notify instantly
+     */
+    public void listenForSubscriber(int subId, @NonNull String pkg, @NonNull String featureId,
+            @NonNull PhoneStateListener listener, int events, boolean notifyNow) {
+        try {
+            // subId from PhoneStateListener is deprecated Q on forward, use the subId from
+            // TelephonyManager instance. Keep using subId from PhoneStateListener for pre-Q.
+            if (Compatibility.isChangeEnabled(LISTEN_CODE_CHANGE)) {
+                // Since mSubId in PhoneStateListener is deprecated from Q on forward, this is
+                // the only place to set mSubId and its for "informational" only.
+                listener.mSubId = (events == PhoneStateListener.LISTEN_NONE)
+                        ? SubscriptionManager.INVALID_SUBSCRIPTION_ID : subId;
+            } else if (listener.mSubId != null) {
+                subId = listener.mSubId;
+            }
+            sRegistry.listenForSubscriber(
+                    subId, pkg, featureId, listener.callback, events, notifyNow);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Informs the system of an intentional upcoming carrier network change by a carrier app.
      * This call only used to allow the system to provide alternative UI while telephony is
      * performing an action that may result in intentional, temporary network lack of connectivity.
@@ -258,6 +299,32 @@
     }
 
     /**
+     * Notify {@link SubscriptionInfo} change.
+     * @hide
+     */
+    @SystemApi
+    public void notifySubscriptionInfoChanged() {
+        try {
+            sRegistry.notifySubscriptionInfoChanged();
+        } catch (RemoteException ex) {
+            // system server crash
+        }
+    }
+
+    /**
+     * Notify opportunistic {@link SubscriptionInfo} change.
+     * @hide
+     */
+    @SystemApi
+    public void notifyOpportunisticSubscriptionInfoChanged() {
+        try {
+            sRegistry.notifyOpportunisticSubscriptionInfoChanged();
+        } catch (RemoteException ex) {
+            // system server crash
+        }
+    }
+
+    /**
      * Notify {@link ServiceState} update on certain subscription.
      *
      * @param subId for which the service state changed.
@@ -394,6 +461,36 @@
     }
 
     /**
+     * Notify outgoing emergency call.
+     * @param phoneId Sender phone ID.
+     * @param subId Sender subscription ID.
+     * @param emergencyNumber Emergency number.
+     */
+    public void notifyOutgoingEmergencyCall(int phoneId, int subId,
+            @NonNull EmergencyNumber emergencyNumber) {
+        try {
+            sRegistry.notifyOutgoingEmergencyCall(phoneId, subId, emergencyNumber);
+        } catch (RemoteException ex) {
+            // system process is dead
+        }
+    }
+
+    /**
+     * Notify outgoing emergency SMS.
+     * @param phoneId Sender phone ID.
+     * @param subId Sender subscription ID.
+     * @param emergencyNumber Emergency number.
+     */
+    public void notifyOutgoingEmergencySms(int phoneId, int subId,
+            @NonNull EmergencyNumber emergencyNumber) {
+        try {
+            sRegistry.notifyOutgoingEmergencySms(phoneId, subId, emergencyNumber);
+        } catch (RemoteException ex) {
+            // system process is dead
+        }
+    }
+
+    /**
      * Notify radio power state changed on certain subscription.
      *
      * @param subId for which radio power state changed.
diff --git a/core/java/android/util/CloseGuard.java b/core/java/android/util/CloseGuard.java
index 6ac7696..ba504a3 100644
--- a/core/java/android/util/CloseGuard.java
+++ b/core/java/android/util/CloseGuard.java
@@ -26,7 +26,7 @@
  * A simple example: <pre>   {@code
  *   class Foo {
  *
- *       private final CloseGuard guard = CloseGuard.get();
+ *       private final CloseGuard guard = new CloseGuard();
  *
  *       ...
  *
@@ -64,7 +64,7 @@
  * be deferred. For example: <pre>   {@code
  *   class Bar {
  *
- *       private final CloseGuard guard = CloseGuard.get();
+ *       private final CloseGuard guard = new CloseGuard();
  *
  *       ...
  *
diff --git a/core/java/android/view/IPinnedStackController.aidl b/core/java/android/view/IPinnedStackController.aidl
index 00edb3a..cb82f16 100644
--- a/core/java/android/view/IPinnedStackController.aidl
+++ b/core/java/android/view/IPinnedStackController.aidl
@@ -53,9 +53,4 @@
      * {@param bounds} here is the final destination bounds.
      */
     void resetBoundsAnimation(in Rect bounds);
-
-    /**
-     * Reports the current default and movement bounds to controller.
-     */
-    void reportBounds(in Rect defaultBounds, in Rect movementBounds);
 }
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index d9c502e..e1f1581 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -558,12 +558,6 @@
     boolean isWindowTraceEnabled();
 
     /**
-     * Requests that the WindowManager sends
-     * WindowManagerPolicyConstants#ACTION_USER_ACTIVITY_NOTIFICATION on the next user activity.
-     */
-    void requestUserActivityNotification();
-
-    /**
      * Notify WindowManager that it should not override the info in DisplayManager for the specified
      * display. This can disable letter- or pillar-boxing applied in DisplayManager when the metrics
      * of the logical display reported from WindowManager do not correspond to the metrics of the
@@ -748,4 +742,9 @@
     void getWindowInsets(in WindowManager.LayoutParams attrs, int displayId,
             out Rect outContentInsets, out Rect outStableInsets,
             out DisplayCutout.ParcelableWrapper displayCutout);
+
+    /**
+     * Called to show global actions.
+     */
+    void showGlobalActions();
 }
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index e3446e1..1677357d 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -92,6 +92,9 @@
      * @param outSurface Object in which is placed the new display surface.
      * @param insetsState The current insets state in the system.
      * @param outSurfaceSize The width and height of the surface control
+     * @param outBlastSurfaceControl A BLAST SurfaceControl allocated by the WindowManager
+     * the SurfaceControl willl be managed by the client side, but the WindowManager
+     * may use it as a deferTransaction barrier.
      *
      * @return int Result flags: {@link WindowManagerGlobal#RELAYOUT_SHOW_FOCUS},
      * {@link WindowManagerGlobal#RELAYOUT_FIRST_TIME}.
@@ -103,7 +106,8 @@
             out Rect outBackdropFrame,
             out DisplayCutout.ParcelableWrapper displayCutout,
             out MergedConfiguration outMergedConfiguration, out SurfaceControl outSurfaceControl,
-            out InsetsState insetsState, out Point outSurfaceSize);
+            out InsetsState insetsState, out Point outSurfaceSize,
+            out SurfaceControl outBlastSurfaceControl);
 
     /*
      * Notify the window manager that an application is relaunching and
diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java
index d069437..2e37751 100644
--- a/core/java/android/view/ImeInsetsSourceConsumer.java
+++ b/core/java/android/view/ImeInsetsSourceConsumer.java
@@ -87,7 +87,7 @@
      * @return @see {@link android.view.InsetsSourceConsumer.ShowResult}.
      */
     @Override
-    @ShowResult int requestShow(boolean fromIme) {
+    public @ShowResult int requestShow(boolean fromIme) {
         // TODO: ResultReceiver for IME.
         // TODO: Set mShowOnNextImeRender to automatically show IME and guard it with a flag.
         if (fromIme) {
@@ -95,7 +95,7 @@
         }
 
         return getImm().requestImeShow(null /* resultReceiver */)
-                ? ShowResult.SHOW_DELAYED : ShowResult.SHOW_FAILED;
+                ? ShowResult.IME_SHOW_DELAYED : ShowResult.IME_SHOW_FAILED;
     }
 
     /**
diff --git a/core/java/android/view/InsetsAnimationControlCallbacks.java b/core/java/android/view/InsetsAnimationControlCallbacks.java
index 27edb0b..0645c98 100644
--- a/core/java/android/view/InsetsAnimationControlCallbacks.java
+++ b/core/java/android/view/InsetsAnimationControlCallbacks.java
@@ -52,12 +52,6 @@
     void notifyFinished(InsetsAnimationControlImpl controller, boolean shown);
 
     /**
-     * Get the description of the insets state.
-     * @return {@link InsetsState} for adjusting corresponding {@link InsetsSource}.
-     */
-    InsetsState getState();
-
-    /**
      * Apply the new params to the surface.
      * @param params The {@link android.view.SyncRtSurfaceTransactionApplier.SurfaceParams} to
      *               apply.
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index 405eccd..e863aa0 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -191,13 +191,7 @@
         if (mCancelled) {
             return;
         }
-        InsetsState state = new InsetsState(mController.getState());
-        for (int i = mControls.size() - 1; i >= 0; i--) {
-            InsetsSourceControl control = mControls.valueAt(i);
-            state.getSource(control.getType()).setVisible(shown);
-        }
-        Insets insets = getInsetsFromState(state, mFrame, null /* typeSideMap */);
-        setInsetsAndAlpha(insets, 1f /* alpha */, 1f /* fraction */);
+        setInsetsAndAlpha(shown ? mShownInsets : mHiddenInsets, 1f /* alpha */, 1f /* fraction */);
         mFinished = true;
         mShownOnFinish = shown;
     }
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index c6e3835..6f76497 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -19,6 +19,7 @@
 import static android.view.InsetsState.ITYPE_IME;
 import static android.view.InsetsState.toPublicType;
 import static android.view.WindowInsets.Type.all;
+import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_APPEARANCE_CONTROLLED;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
 
@@ -31,6 +32,7 @@
 import android.annotation.Nullable;
 import android.graphics.Insets;
 import android.graphics.Rect;
+import android.os.Handler;
 import android.os.RemoteException;
 import android.util.ArraySet;
 import android.util.Log;
@@ -55,6 +57,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.function.BiFunction;
 
 /**
  * Implements {@link WindowInsetsController} on the client.
@@ -64,6 +67,7 @@
 
     private static final int ANIMATION_DURATION_SHOW_MS = 275;
     private static final int ANIMATION_DURATION_HIDE_MS = 340;
+    private static final int PENDING_CONTROL_TIMEOUT_MS = 2000;
 
     static final Interpolator INTERPOLATOR = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
 
@@ -235,12 +239,36 @@
         DefaultAnimationControlListener(boolean show) {
             super(show);
         }
-
+        
         @Override
         protected void setStartingAnimation(boolean startingAnimation) {
             mStartingAnimation = startingAnimation;
         }
     }
+    /**
+     * Represents a control request that we had to defer because we are waiting for the IME to
+     * process our show request.
+     */
+    private static class PendingControlRequest {
+
+        PendingControlRequest(@InsetsType int types, WindowInsetsAnimationControlListener listener,
+                long durationMs, Interpolator interpolator, @AnimationType int animationType,
+                @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation) {
+            this.types = types;
+            this.listener = listener;
+            this.durationMs = durationMs;
+            this.interpolator = interpolator;
+            this.animationType = animationType;
+            this.layoutInsetsDuringAnimation = layoutInsetsDuringAnimation;
+        }
+
+        final @InsetsType int types;
+        final WindowInsetsAnimationControlListener listener;
+        final long durationMs;
+        final Interpolator interpolator;
+        final @AnimationType int animationType;
+        final @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation;
+    }
 
     private final String TAG = "InsetsControllerImpl";
 
@@ -248,8 +276,10 @@
     private final InsetsState mTmpState = new InsetsState();
 
     private final Rect mFrame = new Rect();
+    private final BiFunction<InsetsController, Integer, InsetsSourceConsumer> mConsumerCreator;
     private final SparseArray<InsetsSourceConsumer> mSourceConsumers = new SparseArray<>();
     private final ViewRootImpl mViewRoot;
+    private final Handler mHandler;
 
     private final SparseArray<InsetsSourceControl> mTmpControlArray = new SparseArray<>();
     private final ArrayList<RunningAnimation> mRunningAnimations = new ArrayList<>();
@@ -263,7 +293,8 @@
     private final Rect mLastLegacyContentInsets = new Rect();
     private final Rect mLastLegacyStableInsets = new Rect();
 
-    private int mPendingTypesToShow;
+    /** Pending control request that is waiting on IME to be ready to be shown */
+    private PendingControlRequest mPendingImeControlRequest;
 
     private int mLastLegacySoftInputMode;
     private int mLastLegacySystemUiFlags;
@@ -271,8 +302,26 @@
 
     private SyncRtSurfaceTransactionApplier mApplier;
 
+    private Runnable mPendingControlTimeout = this::abortPendingImeControlRequest;
+
     public InsetsController(ViewRootImpl viewRoot) {
+        this(viewRoot, (controller, type) -> {
+            if (type == ITYPE_IME) {
+                return new ImeInsetsSourceConsumer(controller.mState, Transaction::new, controller);
+            } else {
+                return new InsetsSourceConsumer(type, controller.mState, Transaction::new,
+                        controller);
+            }
+        }, viewRoot.mHandler);
+    }
+
+    @VisibleForTesting
+    public InsetsController(ViewRootImpl viewRoot,
+            BiFunction<InsetsController, Integer, InsetsSourceConsumer> consumerCreator,
+            Handler handler) {
         mViewRoot = viewRoot;
+        mConsumerCreator = consumerCreator;
+        mHandler = handler;
         mAnimCallback = () -> {
             mAnimCallbackScheduled = false;
             if (mRunningAnimations.isEmpty()) {
@@ -393,7 +442,21 @@
         show(types, false /* fromIme */);
     }
 
-    void show(@InsetsType int types, boolean fromIme) {
+    @VisibleForTesting
+    public void show(@InsetsType int types, boolean fromIme) {
+
+        // Handle pending request ready in case there was one set.
+        if (fromIme && mPendingImeControlRequest != null) {
+            PendingControlRequest pendingRequest = mPendingImeControlRequest;
+            mPendingImeControlRequest = null;
+            mHandler.removeCallbacks(mPendingControlTimeout);
+            controlAnimationUnchecked(pendingRequest.types, pendingRequest.listener, mFrame,
+                    true /* fromIme */, pendingRequest.durationMs, pendingRequest.interpolator,
+                    false /* fade */, pendingRequest.animationType,
+                    pendingRequest.layoutInsetsDuringAnimation);
+            return;
+        }
+
         // TODO: Support a ResultReceiver for IME.
         // TODO(b/123718661): Make show() work for multi-session IME.
         int typesReady = 0;
@@ -463,6 +526,7 @@
             @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation) {
         if (types == 0) {
             // nothing to animate.
+            listener.onCancelled();
             return;
         }
         cancelExistingControllers(types);
@@ -471,19 +535,18 @@
         final SparseArray<InsetsSourceControl> controls = new SparseArray<>();
 
         Pair<Integer, Boolean> typesReadyPair = collectSourceControls(
-                fromIme, internalTypes, controls, listener);
+                fromIme, internalTypes, controls);
         int typesReady = typesReadyPair.first;
-        boolean isReady = typesReadyPair.second;
-        if (!isReady) {
-            // IME isn't ready, all requested types would be shown once IME is ready.
-            mPendingTypesToShow = typesReady;
-            // TODO: listener for pending types.
+        boolean imeReady = typesReadyPair.second;
+        if (!imeReady) {
+            // IME isn't ready, all requested types will be animated once IME is ready
+            abortPendingImeControlRequest();
+            mPendingImeControlRequest = new PendingControlRequest(types, listener, durationMs,
+                    interpolator, animationType, layoutInsetsDuringAnimation);
+            mHandler.postDelayed(mPendingControlTimeout, PENDING_CONTROL_TIMEOUT_MS);
             return;
         }
 
-        // pending types from previous request.
-        typesReady = collectPendingTypes(typesReady);
-
         if (typesReady == 0) {
             listener.onCancelled();
             return;
@@ -496,13 +559,12 @@
     }
 
     /**
-     * @return Pair of (types ready to animate, is ready to animate).
+     * @return Pair of (types ready to animate, IME ready to animate).
      */
     private Pair<Integer, Boolean> collectSourceControls(boolean fromIme,
-            ArraySet<Integer> internalTypes, SparseArray<InsetsSourceControl> controls,
-            WindowInsetsAnimationControlListener listener) {
+            ArraySet<Integer> internalTypes, SparseArray<InsetsSourceControl> controls) {
         int typesReady = 0;
-        boolean isReady = true;
+        boolean imeReady = true;
         for (int i = internalTypes.size() - 1; i >= 0; i--) {
             InsetsSourceConsumer consumer = getSourceConsumer(internalTypes.valueAt(i));
             boolean setVisible = !consumer.isRequestedVisible();
@@ -512,16 +574,12 @@
                     case ShowResult.SHOW_IMMEDIATELY:
                         typesReady |= InsetsState.toPublicType(consumer.getType());
                         break;
-                    case ShowResult.SHOW_DELAYED:
-                        isReady = false;
+                    case ShowResult.IME_SHOW_DELAYED:
+                        imeReady = false;
                         break;
-                    case ShowResult.SHOW_FAILED:
+                    case ShowResult.IME_SHOW_FAILED:
                         // IME cannot be shown (since it didn't have focus), proceed
                         // with animation of other types.
-                        if (mPendingTypesToShow != 0) {
-                            // remove IME from pending because view no longer has focus.
-                            mPendingTypesToShow &= ~InsetsState.toPublicType(ITYPE_IME);
-                        }
                         break;
                 }
             } else {
@@ -538,13 +596,7 @@
                 controls.put(consumer.getType(), control);
             }
         }
-        return new Pair<>(typesReady, isReady);
-    }
-
-    private int collectPendingTypes(@InsetsType int typesReady) {
-        typesReady |= mPendingTypesToShow;
-        mPendingTypesToShow = 0;
-        return typesReady;
+        return new Pair<>(typesReady, imeReady);
     }
 
     private @LayoutInsetsDuringAnimation int getLayoutInsetsDuringAnimationMode(
@@ -577,6 +629,17 @@
                 cancelAnimation(control, true /* invokeCallback */);
             }
         }
+        if ((types & ime()) != 0) {
+            abortPendingImeControlRequest();
+        }
+    }
+
+    private void abortPendingImeControlRequest() {
+        if (mPendingImeControlRequest != null) {
+            mPendingImeControlRequest.listener.onCancelled();
+            mPendingImeControlRequest = null;
+            mHandler.removeCallbacks(mPendingControlTimeout);
+        }
     }
 
     @VisibleForTesting
@@ -608,6 +671,9 @@
                 cancelAnimation(control, true /* invokeCallback */);
             }
         }
+        if (consumer.getType() == ITYPE_IME) {
+            abortPendingImeControlRequest();
+        }
     }
 
     private void cancelAnimation(InsetsAnimationControlImpl control, boolean invokeCallback) {
@@ -635,7 +701,7 @@
         if (controller != null) {
             return controller;
         }
-        controller = createConsumerOfType(type);
+        controller = mConsumerCreator.apply(this, type);
         mSourceConsumers.put(type, controller);
         return controller;
     }
@@ -696,14 +762,6 @@
         return ANIMATION_TYPE_NONE;
     }
 
-    private InsetsSourceConsumer createConsumerOfType(int type) {
-        if (type == ITYPE_IME) {
-            return new ImeInsetsSourceConsumer(mState, Transaction::new, this);
-        } else {
-            return new InsetsSourceConsumer(type, mState, Transaction::new, this);
-        }
-    }
-
     /**
      * Sends the local visibility state back to window manager.
      */
diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java
index 35a82b8..ddfd38c 100644
--- a/core/java/android/view/InsetsSourceConsumer.java
+++ b/core/java/android/view/InsetsSourceConsumer.java
@@ -36,7 +36,7 @@
 public class InsetsSourceConsumer {
 
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef(value = {ShowResult.SHOW_IMMEDIATELY, ShowResult.SHOW_DELAYED, ShowResult.SHOW_FAILED})
+    @IntDef(value = {ShowResult.SHOW_IMMEDIATELY, ShowResult.IME_SHOW_DELAYED, ShowResult.IME_SHOW_FAILED})
     @interface ShowResult {
         /**
          * Window type is ready to be shown, will be shown immidiately.
@@ -46,12 +46,12 @@
          * Result will be delayed. Window needs to be prepared or request is not from controller.
          * Request will be delegated to controller and may or may not be shown.
          */
-        int SHOW_DELAYED = 1;
+        int IME_SHOW_DELAYED = 1;
         /**
          * Window will not be shown because one of the conditions couldn't be met.
          * (e.g. in IME's case, when no editor is focused.)
          */
-        int SHOW_FAILED = 2;
+        int IME_SHOW_FAILED = 2;
     }
 
     protected final InsetsController mController;
@@ -155,7 +155,8 @@
      *                       {@link android.inputmethodservice.InputMethodService}).
      * @return @see {@link ShowResult}.
      */
-    @ShowResult int requestShow(boolean fromController) {
+    @VisibleForTesting
+    public @ShowResult int requestShow(boolean fromController) {
         return ShowResult.SHOW_IMMEDIATELY;
     }
 
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index c638717..c91096e 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -19,6 +19,7 @@
 import static android.view.Display.INVALID_DISPLAY;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Build;
@@ -1269,6 +1270,7 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private int mSource;
     private int mDisplayId;
+    private @Nullable byte[] mHmac;
     @UnsupportedAppUsage
     private int mMetaState;
     @UnsupportedAppUsage
@@ -1546,6 +1548,7 @@
         mDeviceId = origEvent.mDeviceId;
         mSource = origEvent.mSource;
         mDisplayId = origEvent.mDisplayId;
+        mHmac = origEvent.mHmac == null ? null : origEvent.mHmac.clone();
         mScanCode = origEvent.mScanCode;
         mFlags = origEvent.mFlags;
         mCharacters = origEvent.mCharacters;
@@ -1573,6 +1576,7 @@
         mDeviceId = origEvent.mDeviceId;
         mSource = origEvent.mSource;
         mDisplayId = origEvent.mDisplayId;
+        mHmac = null; // Don't copy HMAC, it will be invalid because eventTime is changing
         mScanCode = origEvent.mScanCode;
         mFlags = origEvent.mFlags;
         mCharacters = origEvent.mCharacters;
@@ -1600,7 +1604,8 @@
      */
     public static KeyEvent obtain(long downTime, long eventTime, int action,
             int code, int repeat, int metaState,
-            int deviceId, int scancode, int flags, int source, int displayId, String characters) {
+            int deviceId, int scancode, int flags, int source, int displayId, @Nullable byte[] hmac,
+            String characters) {
         KeyEvent ev = obtain();
         ev.mDownTime = downTime;
         ev.mEventTime = eventTime;
@@ -1613,6 +1618,7 @@
         ev.mFlags = flags;
         ev.mSource = source;
         ev.mDisplayId = displayId;
+        ev.mHmac = hmac;
         ev.mCharacters = characters;
         return ev;
     }
@@ -1627,7 +1633,7 @@
             int code, int repeat, int metaState,
             int deviceId, int scancode, int flags, int source, String characters) {
         return obtain(downTime, eventTime, action, code, repeat, metaState, deviceId, scancode,
-                flags, source, INVALID_DISPLAY, characters);
+                flags, source, INVALID_DISPLAY, null /* hmac */, characters);
     }
 
     /**
@@ -1650,6 +1656,7 @@
         ev.mFlags = other.mFlags;
         ev.mSource = other.mSource;
         ev.mDisplayId = other.mDisplayId;
+        ev.mHmac = other.mHmac == null ? null : other.mHmac.clone();
         ev.mCharacters = other.mCharacters;
         return ev;
     }
@@ -1738,6 +1745,7 @@
         mDeviceId = origEvent.mDeviceId;
         mSource = origEvent.mSource;
         mDisplayId = origEvent.mDisplayId;
+        mHmac = null; // Don't copy the hmac, it will be invalid since action is changing
         mScanCode = origEvent.mScanCode;
         mFlags = origEvent.mFlags;
         // Don't copy mCharacters, since one way or the other we'll lose it
@@ -3091,6 +3099,7 @@
         mDeviceId = in.readInt();
         mSource = in.readInt();
         mDisplayId = in.readInt();
+        mHmac = in.createByteArray();
         mAction = in.readInt();
         mKeyCode = in.readInt();
         mRepeatCount = in.readInt();
@@ -3109,6 +3118,7 @@
         out.writeInt(mDeviceId);
         out.writeInt(mSource);
         out.writeInt(mDisplayId);
+        out.writeByteArray(mHmac);
         out.writeInt(mAction);
         out.writeInt(mKeyCode);
         out.writeInt(mRepeatCount);
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 7707ad1..78a080d 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.FloatRange;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -88,6 +89,8 @@
     private static native int nativeSetSharedBufferModeEnabled(long nativeObject, boolean enabled);
     private static native int nativeSetAutoRefreshEnabled(long nativeObject, boolean enabled);
 
+    private static native int nativeSetFrameRate(long nativeObject, float frameRate);
+
     public static final @android.annotation.NonNull Parcelable.Creator<Surface> CREATOR =
             new Parcelable.Creator<Surface>() {
         @Override
@@ -841,6 +844,35 @@
     }
 
     /**
+     * Sets the intended frame rate for this surface.
+     *
+     * On devices that are capable of running the display at different refresh rates, the
+     * system may choose a display refresh rate to better match this surface's frame
+     * rate. Usage of this API won't introduce frame rate throttling, or affect other
+     * aspects of the application's frame production pipeline. However, because the system
+     * may change the display refresh rate, calls to this function may result in changes
+     * to Choreographer callback timings, and changes to the time interval at which the
+     * system releases buffers back to the application.
+     *
+     * Note that this only has an effect for surfaces presented on the display. If this
+     * surface is consumed by something other than the system compositor, e.g. a media
+     * codec, this call has no effect.
+     *
+     * @param frameRate The intended frame rate of this surface, in frames per second. 0
+     * is a special value that indicates the app will accept the system's choice for the
+     * display frame rate, which is the default behavior if this function isn't
+     * called. The frameRate param does *not* need to be a valid refresh rate for this
+     * device's display - e.g., it's fine to pass 30fps to a device that can only run the
+     * display at 60fps.
+     */
+    public void setFrameRate(@FloatRange(from = 0.0) float frameRate) {
+        int error = nativeSetFrameRate(mNativeObject, frameRate);
+        if (error != 0) {
+            throw new RuntimeException("Failed to set frame rate on Surface");
+        }
+    }
+
+    /**
      * Exception thrown when a Canvas couldn't be locked with {@link Surface#lockCanvas}, or
      * when a SurfaceTexture could not successfully be allocated.
      */
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index bcc9e41..bee05a9 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -211,6 +211,9 @@
     private static native void nativeSetGlobalShadowSettings(@Size(4) float[] ambientColor,
             @Size(4) float[] spotColor, float lightPosY, float lightPosZ, float lightRadius);
 
+    private static native void nativeSetFrameRate(
+            long transactionObj, long nativeObject, float frameRate);
+
     private final CloseGuard mCloseGuard = CloseGuard.get();
     private String mName;
     /**
@@ -2548,6 +2551,7 @@
         /**
          * @hide
          */
+        @Deprecated
         @UnsupportedAppUsage
         public Transaction deferTransactionUntilSurface(SurfaceControl sc, Surface barrierSurface,
                 long frameNumber) {
@@ -2787,6 +2791,33 @@
         }
 
         /**
+         * Sets the intended frame rate for the surface {@link SurfaceControl}.
+         *
+         * On devices that are capable of running the display at different refresh rates, the system
+         * may choose a display refresh rate to better match this surface's frame rate. Usage of
+         * this API won't directly affect the application's frame production pipeline. However,
+         * because the system may change the display refresh rate, calls to this function may result
+         * in changes to Choreographer callback timings, and changes to the time interval at which
+         * the system releases buffers back to the application.
+         *
+         * @param sc The SurfaceControl to specify the frame rate of.
+         * @param frameRate The intended frame rate for this surface, in frames per second. 0 is a
+         *                  special value that indicates the app will accept the system's choice for
+         *                  the display frame rate, which is the default behavior if this function
+         *                  isn't called. The frameRate param does *not* need to be a valid refresh
+         *                  rate for this device's display - e.g., it's fine to pass 30fps to a
+         *                  device that can only run the display at 60fps.
+         * @return This transaction object.
+         */
+        @NonNull
+        public Transaction setFrameRate(
+                @NonNull SurfaceControl sc, @FloatRange(from = 0.0) float frameRate) {
+            checkPreconditions(sc);
+            nativeSetFrameRate(mNativeObject, sc.mNativeObject, frameRate);
+            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/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 1981bdd..75d5538 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -414,7 +414,8 @@
                             }
                             t.setAlpha(mSurfaceControl, alpha);
                             if (!useBLAST) {
-                                t.deferTransactionUntilSurface(mSurfaceControl, parent, frame);
+                                t.deferTransactionUntil(mSurfaceControl,
+                                        viewRoot.getRenderSurfaceControl(), frame);
                             }
                         }
                         // It's possible that mSurfaceControl is released in the UI thread before
@@ -1122,7 +1123,7 @@
         if (frameNumber > 0 && !WindowManagerGlobal.USE_BLAST_ADAPTER) {
             final ViewRootImpl viewRoot = getViewRootImpl();
 
-            t.deferTransactionUntilSurface(surface, viewRoot.mSurface,
+            t.deferTransactionUntil(surface, viewRoot.getRenderSurfaceControl(),
                     frameNumber);
         }
 
@@ -1217,8 +1218,8 @@
 
             if (frameNumber > 0 && viewRoot !=  null && !useBLAST) {
                 if (viewRoot.mSurface.isValid()) {
-                    mRtTransaction.deferTransactionUntilSurface(mSurfaceControl, viewRoot.mSurface,
-                            frameNumber);
+                    mRtTransaction.deferTransactionUntil(mSurfaceControl,
+                            viewRoot.getRenderSurfaceControl(), frameNumber);
                 }
             }
             t.hide(mSurfaceControl);
diff --git a/core/java/android/view/SyncRtSurfaceTransactionApplier.java b/core/java/android/view/SyncRtSurfaceTransactionApplier.java
index a6536f5d..abe44f4 100644
--- a/core/java/android/view/SyncRtSurfaceTransactionApplier.java
+++ b/core/java/android/view/SyncRtSurfaceTransactionApplier.java
@@ -38,7 +38,7 @@
     public static final int FLAG_CORNER_RADIUS = 1 << 4;
     public static final int FLAG_VISIBILITY = 1 << 5;
 
-    private final Surface mTargetSurface;
+    private SurfaceControl mTargetSc;
     private final ViewRootImpl mTargetViewRootImpl;
     private final float[] mTmpFloat9 = new float[9];
 
@@ -47,7 +47,6 @@
      */
     public SyncRtSurfaceTransactionApplier(View targetView) {
         mTargetViewRootImpl = targetView != null ? targetView.getViewRootImpl() : null;
-        mTargetSurface = mTargetViewRootImpl != null ? mTargetViewRootImpl.mSurface : null;
     }
 
     /**
@@ -60,15 +59,16 @@
         if (mTargetViewRootImpl == null) {
             return;
         }
+        mTargetSc = mTargetViewRootImpl.getRenderSurfaceControl();
         mTargetViewRootImpl.registerRtFrameCallback(frame -> {
-            if (mTargetSurface == null || !mTargetSurface.isValid()) {
+            if (mTargetSc == null || !mTargetSc.isValid()) {
                 return;
             }
             Transaction t = new Transaction();
             for (int i = params.length - 1; i >= 0; i--) {
                 SurfaceParams surfaceParams = params[i];
                 SurfaceControl surface = surfaceParams.surface;
-                t.deferTransactionUntilSurface(surface, mTargetSurface, frame);
+                t.deferTransactionUntil(surface, mTargetSc, frame);
                 applyParams(t, surfaceParams, mTmpFloat9);
             }
             t.setEarlyWakeup();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 0f2d2c2..5e59143 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -22,10 +22,6 @@
 import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP;
 import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION;
 import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
-import static android.view.WindowInsets.Type.ime;
-import static android.view.WindowInsets.Type.systemBars;
-import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
-import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
 import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
 
 import static java.lang.Math.max;
@@ -146,7 +142,6 @@
 import android.widget.ScrollBarDrawable;
 
 import com.android.internal.R;
-import com.android.internal.policy.DecorView;
 import com.android.internal.view.TooltipPopup;
 import com.android.internal.view.menu.MenuBuilder;
 import com.android.internal.widget.ScrollBarUtils;
@@ -3659,8 +3654,8 @@
      *
      * @deprecated For floating windows, use {@link LayoutParams#setFitInsetsTypes(int)} with
      * {@link Type#navigationBars()}. For non-floating windows that fill the screen, call
-     * {@link Window#setOnContentApplyWindowInsets} with {@code null} or a listener that doesn't
-     * fit the navigation bar on the window content level.
+     * {@link Window#setOnContentApplyWindowInsetsListener} with {@code null} or a listener that
+     * doesn't fit the navigation bar on the window content level.
      */
     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
 
@@ -3688,8 +3683,8 @@
      *
      * @deprecated For floating windows, use {@link LayoutParams#setFitInsetsTypes(int)} with
      * {@link Type#statusBars()} ()}. For non-floating windows that fill the screen, call
-     * {@link Window#setOnContentApplyWindowInsets} with {@code null} or a listener that doesn't
-     * fit the status bar on the window content level.
+     * {@link Window#setOnContentApplyWindowInsetsListener} with {@code null} or a listener that
+     * doesn't fit the status bar on the window content level.
      */
     @Deprecated
     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
@@ -21856,7 +21851,7 @@
         if (!concatMatrix &&
                 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
                         ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
-                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
+                canvas.quickReject(mLeft, mTop, mRight, mBottom) &&
                 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
             mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
             return more;
@@ -22140,6 +22135,7 @@
          *      4. Draw children
          *      5. If necessary, draw the fading edges and restore layers
          *      6. Draw decorations (scrollbars for instance)
+         *      7. If necessary, draw the default focus highlight
          */
 
         // Step 1, draw the background, if needed
@@ -22346,6 +22342,9 @@
         // Step 6, draw decorations (foreground, scrollbars)
         onDrawForeground(canvas);
 
+        // Step 7, draw the default focus highlight
+        drawDefaultFocusHighlight(canvas);
+
         if (isShowingLayoutBounds()) {
             debugDrawFocus(canvas);
         }
@@ -23241,11 +23240,11 @@
     }
 
     /**
-     * Draw the default focus highlight onto the canvas.
+     * Draw the default focus highlight onto the canvas if there is one and this view is focused.
      * @param canvas the canvas where we're drawing the highlight.
      */
     private void drawDefaultFocusHighlight(Canvas canvas) {
-        if (mDefaultFocusHighlight != null) {
+        if (mDefaultFocusHighlight != null && isFocused()) {
             if (mDefaultFocusHighlightSizeChanged) {
                 mDefaultFocusHighlightSizeChanged = false;
                 final int l = mScrollX;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f5cfbec..841c43f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -507,7 +507,7 @@
     @UnsupportedAppUsage
     public final Surface mSurface = new Surface();
     private final SurfaceControl mSurfaceControl = new SurfaceControl();
-    private SurfaceControl mBlastSurfaceControl;
+    private SurfaceControl mBlastSurfaceControl = new SurfaceControl();
 
     private BLASTBufferQueue mBlastBufferQueue;
 
@@ -636,6 +636,7 @@
             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
                     new InputEventConsistencyVerifier(this, 0) : null;
 
+    private final InsetsController mInsetsController;
     private final ImeFocusController mImeFocusController;
 
     /**
@@ -646,7 +647,6 @@
         return mImeFocusController;
     }
 
-    private final InsetsController mInsetsController = new InsetsController(this);
 
     private final GestureExclusionTracker mGestureExclusionTracker = new GestureExclusionTracker();
 
@@ -705,6 +705,7 @@
         mFallbackEventHandler = new PhoneFallbackEventHandler(context);
         mChoreographer = Choreographer.getInstance();
         mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
+        mInsetsController = new InsetsController(this);
 
         String processorOverrideName = context.getResources().getString(
                                     R.string.config_inputEventCompatProcessorOverrideClassName);
@@ -1690,23 +1691,17 @@
                     .build();
             setBoundsLayerCrop();
             mTransaction.show(mBoundsLayer).apply();
-        }
-        return mBoundsLayer;
+        } 
+       return mBoundsLayer;
     }
 
     Surface getOrCreateBLASTSurface(int width, int height) {
         if (mSurfaceControl == null || !mSurfaceControl.isValid()) {
             return null;
         }
-        if (mBlastSurfaceControl == null) {
-            mBlastSurfaceControl = new SurfaceControl.Builder(mSurfaceSession)
-            .setParent(mSurfaceControl)
-            .setName("BLAST")
-            .setBLASTLayer()
-            .build();
+        if ((mBlastBufferQueue != null) && mBlastSurfaceControl.isValid()) {
             mBlastBufferQueue = new BLASTBufferQueue(
                 mBlastSurfaceControl, width, height);
-
         }
         mBlastBufferQueue.update(mBlastSurfaceControl, width, height);
 
@@ -1733,8 +1728,8 @@
     private void updateBoundsLayer() {
         if (mBoundsLayer != null) {
             setBoundsLayerCrop();
-            mTransaction.deferTransactionUntilSurface(mBoundsLayer,
-                    mSurface, mSurface.getNextFrameNumber())
+            mTransaction.deferTransactionUntil(mBoundsLayer,
+                    getRenderSurfaceControl(), mSurface.getNextFrameNumber())
                     .apply();
         }
     }
@@ -3683,32 +3678,29 @@
         Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw");
 
         boolean usingAsyncReport = false;
+        boolean reportNextDraw = mReportNextDraw; // Capture the original value
         if (mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled()) {
             ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver
                     .captureFrameCommitCallbacks();
-            if (mReportNextDraw) {
-                usingAsyncReport = true;
+            final boolean needFrameCompleteCallback = mNextDrawUseBLASTSyncTransaction ||
+                (commitCallbacks != null && commitCallbacks.size() > 0) ||
+                mReportNextDraw;
+            usingAsyncReport = mReportNextDraw;
+            if (needFrameCompleteCallback) {
                 final Handler handler = mAttachInfo.mHandler;
                 mAttachInfo.mThreadedRenderer.setFrameCompleteCallback((long frameNr) ->
                         handler.postAtFrontOfQueue(() -> {
                             finishBLASTSync();
-                            // TODO: Use the frame number
-                            pendingDrawFinished();
+                            if (reportNextDraw) {
+                                // TODO: Use the frame number
+                                pendingDrawFinished();
+                            }
                             if (commitCallbacks != null) {
                                 for (int i = 0; i < commitCallbacks.size(); i++) {
                                     commitCallbacks.get(i).run();
                                 }
                             }
                         }));
-            } else if (commitCallbacks != null && commitCallbacks.size() > 0) {
-                final Handler handler = mAttachInfo.mHandler;
-                mAttachInfo.mThreadedRenderer.setFrameCompleteCallback((long frameNr) ->
-                        handler.postAtFrontOfQueue(() -> {
-                            finishBLASTSync();
-                            for (int i = 0; i < commitCallbacks.size(); i++) {
-                                commitCallbacks.get(i).run();
-                            }
-                        }));
             }
         }
 
@@ -7344,7 +7336,8 @@
                 insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, frameNumber,
                 mTmpFrame, mPendingContentInsets, mPendingVisibleInsets,
                 mPendingStableInsets, mPendingBackDropFrame, mPendingDisplayCutout,
-                mPendingMergedConfiguration, mSurfaceControl, mTempInsets, mSurfaceSize);
+                mPendingMergedConfiguration, mSurfaceControl, mTempInsets, mSurfaceSize,
+                mBlastSurfaceControl);
         if (mSurfaceControl.isValid()) {
             if (!WindowManagerGlobal.USE_BLAST_ADAPTER) {
                 mSurface.copyFrom(mSurfaceControl);
@@ -9539,4 +9532,12 @@
     SurfaceControl.Transaction getBLASTSyncTransaction() {
         return mRtBLASTSyncTransaction;
     }
+
+    SurfaceControl getRenderSurfaceControl() {
+        if (WindowManagerGlobal.USE_BLAST_ADAPTER) {
+            return mBlastSurfaceControl;
+        } else {
+            return mSurfaceControl;
+        }
+    }
 }
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index c8dea43..a6450a1 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -497,13 +497,48 @@
      * Message for taking fullscreen screenshot
      * @hide
      */
-    final int TAKE_SCREENSHOT_FULLSCREEN = 1;
+    int TAKE_SCREENSHOT_FULLSCREEN = 1;
 
     /**
      * Message for taking screenshot of selected region.
      * @hide
      */
-    final int TAKE_SCREENSHOT_SELECTED_REGION = 2;
+    int TAKE_SCREENSHOT_SELECTED_REGION = 2;
+
+    /**
+     * Message for handling a screenshot flow with an image provided by the caller.
+     * @hide
+     */
+    int TAKE_SCREENSHOT_PROVIDED_IMAGE = 3;
+
+    /**
+     * Parcel key for the screen shot bitmap sent with messages of type
+     * {@link #TAKE_SCREENSHOT_PROVIDED_IMAGE}, type {@link android.graphics.Bitmap}
+     * @hide
+     */
+    String PARCEL_KEY_SCREENSHOT_BITMAP = "screenshot_screen_bitmap";
+
+    /**
+     * Parcel key for the screen bounds of the image sent with messages of type
+     * [@link {@link #TAKE_SCREENSHOT_PROVIDED_IMAGE}], type {@link Rect} in screen coordinates.
+     * @hide
+     */
+    String PARCEL_KEY_SCREENSHOT_BOUNDS = "screenshot_screen_bounds";
+
+    /**
+     * Parcel key for the task id of the task that the screen shot was taken of, sent with messages
+     * of type [@link {@link #TAKE_SCREENSHOT_PROVIDED_IMAGE}], type int.
+     * @hide
+     */
+    String PARCEL_KEY_SCREENSHOT_TASK_ID = "screenshot_task_id";
+
+    /**
+     * Parcel key for the visible insets of the image sent with messages of type
+     * [@link {@link #TAKE_SCREENSHOT_PROVIDED_IMAGE}], type {@link android.graphics.Insets} in
+     * screen coordinates.
+     * @hide
+     */
+    String PARCEL_KEY_SCREENSHOT_INSETS = "screenshot_insets";
 
     /**
      * @hide
@@ -2424,6 +2459,7 @@
          * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED}
          * will be used.
          */
+        @ActivityInfo.ScreenOrientation
         public int screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 
         /**
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index d39c3c0..f03c4e7 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -29,7 +29,6 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
-import android.provider.DeviceConfig;
 import android.util.AndroidRuntimeException;
 import android.util.ArraySet;
 import android.util.Log;
@@ -63,10 +62,7 @@
      * This flag controls whether ViewRootImpl will utilize the Blast Adapter
      * to send buffer updates to SurfaceFlinger
      */
-    public static final boolean USE_BLAST_ADAPTER =
-            SystemProperties.getBoolean(String.join(".", "persist.device_config",
-                  DeviceConfig.NAMESPACE_WINDOW_MANAGER_NATIVE_BOOT,
-                  WM_USE_BLAST_ADAPTER_FLAG), false);
+    public static final boolean USE_BLAST_ADAPTER = false;
 
     /**
      * The user is navigating with keys (not the touch screen), so
diff --git a/core/java/android/view/WindowManagerPolicyConstants.java b/core/java/android/view/WindowManagerPolicyConstants.java
index a22f5a5..492ab6f 100644
--- a/core/java/android/view/WindowManagerPolicyConstants.java
+++ b/core/java/android/view/WindowManagerPolicyConstants.java
@@ -66,12 +66,6 @@
     String NAV_BAR_MODE_GESTURAL_OVERLAY = "com.android.internal.systemui.navbar.gestural";
 
     /**
-     * Broadcast sent when a user activity is detected.
-     */
-    String ACTION_USER_ACTIVITY_NOTIFICATION =
-            "android.intent.action.USER_ACTIVITY_NOTIFICATION";
-
-    /**
      * Sticky broadcast of the current HDMI plugged state.
      */
     String ACTION_HDMI_PLUGGED = "android.intent.action.HDMI_PLUGGED";
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 9f27848..91778aa 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -161,7 +161,7 @@
             Rect outStableInsets, Rect outBackdropFrame,
             DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,
             SurfaceControl outSurfaceControl, InsetsState outInsetsState,
-            Point outSurfaceSize) {
+            Point outSurfaceSize, SurfaceControl outBLASTSurfaceControl) {
         State state = null;
         synchronized (this) {
             state = mStateForWindow.get(window.asBinder());
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 9cbba87..02b098b 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -102,6 +102,12 @@
     public static final int STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED = 0x00000004;
 
     /** @hide */
+    public static final int STATE_FLAG_DISPATCH_DOUBLE_TAP = 0x00000008;
+
+    /** @hide */
+    public static final int STATE_FLAG_REQUEST_MULTI_FINGER_GESTURES = 0x00000010;
+
+    /** @hide */
     public static final int DALTONIZER_DISABLED = -1;
 
     /** @hide */
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 6040abd..cede3b5 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -19,6 +19,7 @@
 import static android.view.contentcapture.ContentCaptureHelper.sVerbose;
 import static android.view.contentcapture.ContentCaptureHelper.toSet;
 
+import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -30,12 +31,17 @@
 import android.content.ContentCaptureOptions;
 import android.content.Context;
 import android.graphics.Canvas;
+import android.os.Binder;
+import android.os.CancellationSignal;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.ICancellationSignal;
 import android.os.Looper;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.util.Log;
+import android.util.Slog;
 import android.view.View;
 import android.view.ViewStructure;
 import android.view.WindowManager;
@@ -48,8 +54,11 @@
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
 
 /**
  * <p>The {@link ContentCaptureManager} provides additional ways for for apps to
@@ -629,6 +638,36 @@
     }
 
     /**
+     * Called by the app to request data sharing via writing to a file.
+     *
+     * <p>The ContentCaptureService app will receive a read-only file descriptor pointing to the
+     * same file and will be able to read data being shared from it.
+     *
+     * <p>Note: using this API doesn't guarantee the app staying alive and is "best-effort".
+     * Starting a foreground service would minimize the chances of the app getting killed during the
+     * file sharing session.
+     *
+     * @param request object specifying details of the data being shared.
+     */
+    public void shareData(@NonNull DataShareRequest request,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull DataShareWriteAdapter dataShareWriteAdapter) {
+        Preconditions.checkNotNull(request);
+        Preconditions.checkNotNull(dataShareWriteAdapter);
+        Preconditions.checkNotNull(executor);
+
+        ICancellationSignal cancellationSignalTransport = CancellationSignal.createTransport();
+
+        try {
+            mService.shareData(request, cancellationSignalTransport,
+                    new DataShareAdapterDelegate(executor,
+                            cancellationSignalTransport, dataShareWriteAdapter));
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Runs a sync method in the service, properly handling exceptions.
      *
      * @throws SecurityException if caller is not allowed to execute the method.
@@ -675,4 +714,65 @@
     private interface MyRunnable {
         void run(@NonNull SyncResultReceiver receiver) throws RemoteException;
     }
+
+    private static class DataShareAdapterDelegate extends IDataShareWriteAdapter.Stub {
+
+        private final WeakReference<DataShareWriteAdapter> mAdapterReference;
+        private final WeakReference<Executor> mExecutorReference;
+        private final WeakReference<ICancellationSignal> mCancellationSignal;
+
+        private DataShareAdapterDelegate(Executor executor,
+                ICancellationSignal cancellationSignalTransport, DataShareWriteAdapter adapter) {
+            Preconditions.checkNotNull(executor);
+            Preconditions.checkNotNull(cancellationSignalTransport);
+            Preconditions.checkNotNull(adapter);
+
+            mExecutorReference = new WeakReference<>(executor);
+            mAdapterReference = new WeakReference<>(adapter);
+            mCancellationSignal = new WeakReference<>(cancellationSignalTransport);
+        }
+
+        @Override
+        public void write(ParcelFileDescriptor destination)
+                throws RemoteException {
+            ICancellationSignal cancellationSignalTransport = mCancellationSignal.get();
+            if (cancellationSignalTransport == null) {
+                Slog.w(TAG, "Can't execute write(), reference to cancellation signal has been "
+                        + "GC'ed");
+            }
+            CancellationSignal cancellationSignal =
+                    CancellationSignal.fromTransport(cancellationSignalTransport);
+
+            executeAdapterMethodLocked(adapter -> adapter.onWrite(destination, cancellationSignal),
+                    "onWrite");
+        }
+
+        @Override
+        public void error(int errorCode) throws RemoteException {
+            executeAdapterMethodLocked(adapter -> adapter.onError(errorCode), "onError");
+        }
+
+        @Override
+        public void rejected() throws RemoteException {
+            executeAdapterMethodLocked(DataShareWriteAdapter::onRejected, "onRejected");
+        }
+
+        private void executeAdapterMethodLocked(Consumer<DataShareWriteAdapter> adapterFn,
+                String methodName) {
+            DataShareWriteAdapter adapter = mAdapterReference.get();
+            Executor executor = mExecutorReference.get();
+
+            if (adapter == null || executor == null) {
+                Slog.w(TAG, "Can't execute " + methodName + "(), references have been GC'ed");
+                return;
+            }
+
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                executor.execute(() -> adapterFn.accept(adapter));
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+    }
 }
diff --git a/core/java/android/service/controls/actions/CommandAction.aidl b/core/java/android/view/contentcapture/DataShareRequest.aidl
similarity index 81%
copy from core/java/android/service/controls/actions/CommandAction.aidl
copy to core/java/android/view/contentcapture/DataShareRequest.aidl
index 7c1ee41..75073e4 100644
--- a/core/java/android/service/controls/actions/CommandAction.aidl
+++ b/core/java/android/view/contentcapture/DataShareRequest.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,6 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.service.controls.actions;
+package android.view.contentcapture;
 
-parcelable CommandAction;
\ No newline at end of file
+parcelable DataShareRequest;
diff --git a/core/java/android/view/contentcapture/DataShareRequest.java b/core/java/android/view/contentcapture/DataShareRequest.java
new file mode 100644
index 0000000..78c0ef9
--- /dev/null
+++ b/core/java/android/view/contentcapture/DataShareRequest.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.contentcapture;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.ActivityThread;
+import android.content.LocusId;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+import com.android.internal.util.Preconditions;
+
+/** Container class representing a request to share data with Content Capture service. */
+@DataClass(
+        genConstructor = false,
+        genEqualsHashCode = true,
+        genHiddenConstDefs = true,
+        genParcelable = true,
+        genToString = true
+)
+public final class DataShareRequest implements Parcelable {
+
+    /** Name of the package making the request. */
+    @NonNull private final String mPackageName;
+
+    /** Locus id helping to identify what data is being shared. */
+    @Nullable private final LocusId mLocusId;
+
+    /** MIME type of the data being shared. */
+    @NonNull private final String mMimeType;
+
+    /** Constructs a request to share data with the Content Capture Service. */
+    public DataShareRequest(@Nullable LocusId locusId, @NonNull String mimeType) {
+        Preconditions.checkNotNull(mimeType);
+
+        mPackageName = ActivityThread.currentActivityThread().getApplication().getPackageName();
+        mLocusId = locusId;
+        mMimeType = mimeType;
+    }
+
+
+
+    // Code below generated by codegen v1.0.14.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/view/contentcapture/DataShareRequest.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    /**
+     * Name of the package making the request.
+     */
+    @DataClass.Generated.Member
+    public @NonNull String getPackageName() {
+        return mPackageName;
+    }
+
+    /**
+     * Locus id helping to identify what data is being shared.
+     */
+    @DataClass.Generated.Member
+    public @Nullable LocusId getLocusId() {
+        return mLocusId;
+    }
+
+    /**
+     * MIME type of the data being shared.
+     */
+    @DataClass.Generated.Member
+    public @NonNull String getMimeType() {
+        return mMimeType;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public String toString() {
+        // You can override field toString logic by defining methods like:
+        // String fieldNameToString() { ... }
+
+        return "DataShareRequest { " +
+                "packageName = " + mPackageName + ", " +
+                "locusId = " + mLocusId + ", " +
+                "mimeType = " + mMimeType +
+        " }";
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public boolean equals(@Nullable Object o) {
+        // You can override field equality logic by defining either of the methods like:
+        // boolean fieldNameEquals(DataShareRequest other) { ... }
+        // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        @SuppressWarnings("unchecked")
+        DataShareRequest that = (DataShareRequest) o;
+        //noinspection PointlessBooleanExpression
+        return true
+                && java.util.Objects.equals(mPackageName, that.mPackageName)
+                && java.util.Objects.equals(mLocusId, that.mLocusId)
+                && java.util.Objects.equals(mMimeType, that.mMimeType);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int hashCode() {
+        // You can override field hashCode logic by defining methods like:
+        // int fieldNameHashCode() { ... }
+
+        int _hash = 1;
+        _hash = 31 * _hash + java.util.Objects.hashCode(mPackageName);
+        _hash = 31 * _hash + java.util.Objects.hashCode(mLocusId);
+        _hash = 31 * _hash + java.util.Objects.hashCode(mMimeType);
+        return _hash;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        byte flg = 0;
+        if (mLocusId != null) flg |= 0x2;
+        dest.writeByte(flg);
+        dest.writeString(mPackageName);
+        if (mLocusId != null) dest.writeTypedObject(mLocusId, flags);
+        dest.writeString(mMimeType);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ DataShareRequest(@NonNull Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        byte flg = in.readByte();
+        String packageName = in.readString();
+        LocusId locusId = (flg & 0x2) == 0 ? null : (LocusId) in.readTypedObject(LocusId.CREATOR);
+        String mimeType = in.readString();
+
+        this.mPackageName = packageName;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mPackageName);
+        this.mLocusId = locusId;
+        this.mMimeType = mimeType;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mMimeType);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<DataShareRequest> CREATOR
+            = new Parcelable.Creator<DataShareRequest>() {
+        @Override
+        public DataShareRequest[] newArray(int size) {
+            return new DataShareRequest[size];
+        }
+
+        @Override
+        public DataShareRequest createFromParcel(@NonNull Parcel in) {
+            return new DataShareRequest(in);
+        }
+    };
+
+    @DataClass.Generated(
+            time = 1579870254459L,
+            codegenVersion = "1.0.14",
+            sourceFile = "frameworks/base/core/java/android/view/contentcapture/DataShareRequest.java",
+            inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.Nullable android.content.LocusId mLocusId\nprivate final @android.annotation.NonNull java.lang.String mMimeType\nclass DataShareRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/view/contentcapture/DataShareWriteAdapter.java b/core/java/android/view/contentcapture/DataShareWriteAdapter.java
new file mode 100644
index 0000000..f791fea
--- /dev/null
+++ b/core/java/android/view/contentcapture/DataShareWriteAdapter.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.contentcapture;
+
+import android.annotation.NonNull;
+import android.os.CancellationSignal;
+import android.os.ParcelFileDescriptor;
+
+/** Adapter class used by apps to share data with the Content Capture service. */
+public interface DataShareWriteAdapter {
+
+    /** Request has been rejected, because a concurrent data share sessions is in progress. */
+    int ERROR_CONCURRENT_REQUEST = 1;
+
+    /** Data share session timed out. */
+    int ERROR_UNKNOWN = 2;
+
+    /**
+     * Method invoked when the data share session has been started and the app needs to start
+     * writing into the file used for sharing.
+     *
+     * <p>App needs to handle explicitly cases when the file descriptor is closed and handle
+     * gracefully if IOExceptions happen.
+     *
+     * @param destination file descriptor used to write data into
+     * @param cancellationSignal cancellation signal that the app can use to subscribe to cancel
+     *                           operations.
+     */
+    void onWrite(@NonNull ParcelFileDescriptor destination,
+            @NonNull CancellationSignal cancellationSignal);
+
+    /** Data share sessions has been rejected by the Content Capture service. */
+    void onRejected();
+
+    /**
+     * Method invoked when an error occurred, for example sessions has not been started or
+     * terminated unsuccessfully.
+     *
+     * @param errorCode the error code corresponding to an ERROR_* value.
+     */
+    default void onError(int errorCode) {
+        /* do nothing - stub */
+    }
+}
diff --git a/core/java/android/view/contentcapture/IContentCaptureManager.aidl b/core/java/android/view/contentcapture/IContentCaptureManager.aidl
index 7850b67..5217e68 100644
--- a/core/java/android/view/contentcapture/IContentCaptureManager.aidl
+++ b/core/java/android/view/contentcapture/IContentCaptureManager.aidl
@@ -20,7 +20,10 @@
 import android.view.contentcapture.ContentCaptureContext;
 import android.view.contentcapture.ContentCaptureEvent;
 import android.view.contentcapture.DataRemovalRequest;
+import android.view.contentcapture.DataShareRequest;
+import android.view.contentcapture.IDataShareWriteAdapter;
 import android.os.IBinder;
+import android.os.ICancellationSignal;
 
 import com.android.internal.os.IResultReceiver;
 
@@ -64,6 +67,12 @@
     void removeData(in DataRemovalRequest request);
 
     /**
+    * Requests sharing of a binary data with the content capture service.
+    */
+    void shareData(in DataShareRequest request, in ICancellationSignal cancellationSignal,
+                   in IDataShareWriteAdapter adapter);
+
+    /**
      * Returns whether the content capture feature is enabled for the calling user.
      */
     void isContentCaptureFeatureEnabled(in IResultReceiver result);
diff --git a/core/java/android/service/controls/actions/CommandAction.aidl b/core/java/android/view/contentcapture/IDataShareWriteAdapter.aidl
similarity index 65%
copy from core/java/android/service/controls/actions/CommandAction.aidl
copy to core/java/android/view/contentcapture/IDataShareWriteAdapter.aidl
index 7c1ee41..80924ef 100644
--- a/core/java/android/service/controls/actions/CommandAction.aidl
+++ b/core/java/android/view/contentcapture/IDataShareWriteAdapter.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,6 +13,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.service.controls.actions;
 
-parcelable CommandAction;
\ No newline at end of file
+package android.view.contentcapture;
+
+import android.os.ICancellationSignal;
+
+/**
+ * @hide
+ */
+oneway interface IDataShareWriteAdapter {
+    void write(in ParcelFileDescriptor destination);
+    void error(int errorCode);
+    void rejected();
+}
diff --git a/core/java/android/view/inputmethod/InlineSuggestionInfo.java b/core/java/android/view/inputmethod/InlineSuggestionInfo.java
index 195b63a..703b64f 100644
--- a/core/java/android/view/inputmethod/InlineSuggestionInfo.java
+++ b/core/java/android/view/inputmethod/InlineSuggestionInfo.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SuppressLint;
 import android.annotation.TestApi;
 import android.os.Parcelable;
 import android.view.inline.InlinePresentationSpec;
@@ -45,6 +46,17 @@
      */
     public static final @Source String SOURCE_PLATFORM = "android:platform";
 
+    /**
+     * UI type: the UI contains an Autofill suggestion that will autofill the fields when tapped.
+     */
+    public static final @Type String TYPE_SUGGESTION = "android:autofill:suggestion";
+
+    /**
+     * UI type: the UI contains an widget that will launch an intent when tapped.
+     */
+    @SuppressLint({"IntentName"})
+    public static final @Type String TYPE_ACTION = "android:autofill:action";
+
     /** The presentation spec to which the inflated suggestion view abides. */
     private final @NonNull InlinePresentationSpec mPresentationSpec;
 
@@ -54,6 +66,9 @@
     /** Hints for the type of data being suggested. */
     private final @Nullable String[] mAutofillHints;
 
+    /** The type of the UI. */
+    private final @NonNull @Type String mType;
+
     /**
      * Creates a new {@link InlineSuggestionInfo}, for testing purpose.
      *
@@ -65,7 +80,8 @@
             @NonNull InlinePresentationSpec presentationSpec,
             @NonNull @Source String source,
             @Nullable String[] autofillHints) {
-        return new InlineSuggestionInfo(presentationSpec, source, autofillHints);
+        // TODO(b/147394280): Add CTS test for the type field.
+        return new InlineSuggestionInfo(presentationSpec, source, autofillHints, TYPE_SUGGESTION);
     }
 
 
@@ -92,6 +108,15 @@
     @DataClass.Generated.Member
     public @interface Source {}
 
+    /** @hide */
+    @android.annotation.StringDef(prefix = "TYPE_", value = {
+        TYPE_SUGGESTION,
+        TYPE_ACTION
+    })
+    @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE)
+    @DataClass.Generated.Member
+    public @interface Type {}
+
     /**
      * Creates a new InlineSuggestionInfo.
      *
@@ -101,13 +126,16 @@
      *   The source from which the suggestion is provided.
      * @param autofillHints
      *   Hints for the type of data being suggested.
+     * @param type
+     *   The type of the UI.
      * @hide
      */
     @DataClass.Generated.Member
     public InlineSuggestionInfo(
             @NonNull InlinePresentationSpec presentationSpec,
             @NonNull @Source String source,
-            @Nullable String[] autofillHints) {
+            @Nullable String[] autofillHints,
+            @NonNull @Type String type) {
         this.mPresentationSpec = presentationSpec;
         com.android.internal.util.AnnotationValidations.validate(
                 NonNull.class, null, mPresentationSpec);
@@ -124,6 +152,18 @@
         com.android.internal.util.AnnotationValidations.validate(
                 NonNull.class, null, mSource);
         this.mAutofillHints = autofillHints;
+        this.mType = type;
+
+        if (!(java.util.Objects.equals(mType, TYPE_SUGGESTION))
+                && !(java.util.Objects.equals(mType, TYPE_ACTION))) {
+            throw new java.lang.IllegalArgumentException(
+                    "type was " + mType + " but must be one of: "
+                            + "TYPE_SUGGESTION(" + TYPE_SUGGESTION + "), "
+                            + "TYPE_ACTION(" + TYPE_ACTION + ")");
+        }
+
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mType);
 
         // onConstructed(); // You can define this method to get a callback
     }
@@ -152,6 +192,14 @@
         return mAutofillHints;
     }
 
+    /**
+     * The type of the UI.
+     */
+    @DataClass.Generated.Member
+    public @NonNull @Type String getType() {
+        return mType;
+    }
+
     @Override
     @DataClass.Generated.Member
     public String toString() {
@@ -161,7 +209,8 @@
         return "InlineSuggestionInfo { " +
                 "presentationSpec = " + mPresentationSpec + ", " +
                 "source = " + mSource + ", " +
-                "autofillHints = " + java.util.Arrays.toString(mAutofillHints) +
+                "autofillHints = " + java.util.Arrays.toString(mAutofillHints) + ", " +
+                "type = " + mType +
         " }";
     }
 
@@ -180,7 +229,8 @@
         return true
                 && java.util.Objects.equals(mPresentationSpec, that.mPresentationSpec)
                 && java.util.Objects.equals(mSource, that.mSource)
-                && java.util.Arrays.equals(mAutofillHints, that.mAutofillHints);
+                && java.util.Arrays.equals(mAutofillHints, that.mAutofillHints)
+                && java.util.Objects.equals(mType, that.mType);
     }
 
     @Override
@@ -193,6 +243,7 @@
         _hash = 31 * _hash + java.util.Objects.hashCode(mPresentationSpec);
         _hash = 31 * _hash + java.util.Objects.hashCode(mSource);
         _hash = 31 * _hash + java.util.Arrays.hashCode(mAutofillHints);
+        _hash = 31 * _hash + java.util.Objects.hashCode(mType);
         return _hash;
     }
 
@@ -208,6 +259,7 @@
         dest.writeTypedObject(mPresentationSpec, flags);
         dest.writeString(mSource);
         if (mAutofillHints != null) dest.writeStringArray(mAutofillHints);
+        dest.writeString(mType);
     }
 
     @Override
@@ -225,6 +277,7 @@
         InlinePresentationSpec presentationSpec = (InlinePresentationSpec) in.readTypedObject(InlinePresentationSpec.CREATOR);
         String source = in.readString();
         String[] autofillHints = (flg & 0x4) == 0 ? null : in.createStringArray();
+        String type = in.readString();
 
         this.mPresentationSpec = presentationSpec;
         com.android.internal.util.AnnotationValidations.validate(
@@ -242,6 +295,18 @@
         com.android.internal.util.AnnotationValidations.validate(
                 NonNull.class, null, mSource);
         this.mAutofillHints = autofillHints;
+        this.mType = type;
+
+        if (!(java.util.Objects.equals(mType, TYPE_SUGGESTION))
+                && !(java.util.Objects.equals(mType, TYPE_ACTION))) {
+            throw new java.lang.IllegalArgumentException(
+                    "type was " + mType + " but must be one of: "
+                            + "TYPE_SUGGESTION(" + TYPE_SUGGESTION + "), "
+                            + "TYPE_ACTION(" + TYPE_ACTION + ")");
+        }
+
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mType);
 
         // onConstructed(); // You can define this method to get a callback
     }
@@ -261,10 +326,10 @@
     };
 
     @DataClass.Generated(
-            time = 1578972121865L,
+            time = 1579806757327L,
             codegenVersion = "1.0.14",
             sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestionInfo.java",
-            inputSignatures = "public static final @android.view.inputmethod.InlineSuggestionInfo.Source java.lang.String SOURCE_AUTOFILL\npublic static final @android.view.inputmethod.InlineSuggestionInfo.Source java.lang.String SOURCE_PLATFORM\nprivate final @android.annotation.NonNull android.view.inline.InlinePresentationSpec mPresentationSpec\nprivate final @android.annotation.NonNull @android.view.inputmethod.InlineSuggestionInfo.Source java.lang.String mSource\nprivate final @android.annotation.Nullable java.lang.String[] mAutofillHints\npublic static @android.annotation.TestApi @android.annotation.NonNull android.view.inputmethod.InlineSuggestionInfo newInlineSuggestionInfo(android.view.inline.InlinePresentationSpec,java.lang.String,java.lang.String[])\nclass InlineSuggestionInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstDefs=true, genHiddenConstructor=true)")
+            inputSignatures = "public static final @android.view.inputmethod.InlineSuggestionInfo.Source java.lang.String SOURCE_AUTOFILL\npublic static final @android.view.inputmethod.InlineSuggestionInfo.Source java.lang.String SOURCE_PLATFORM\npublic static final @android.view.inputmethod.InlineSuggestionInfo.Type java.lang.String TYPE_SUGGESTION\npublic static final @android.annotation.SuppressLint({\"IntentName\"}) @android.view.inputmethod.InlineSuggestionInfo.Type java.lang.String TYPE_ACTION\nprivate final @android.annotation.NonNull android.view.inline.InlinePresentationSpec mPresentationSpec\nprivate final @android.annotation.NonNull @android.view.inputmethod.InlineSuggestionInfo.Source java.lang.String mSource\nprivate final @android.annotation.Nullable java.lang.String[] mAutofillHints\nprivate final @android.annotation.NonNull @android.view.inputmethod.InlineSuggestionInfo.Type java.lang.String mType\npublic static @android.annotation.TestApi @android.annotation.NonNull android.view.inputmethod.InlineSuggestionInfo newInlineSuggestionInfo(android.view.inline.InlinePresentationSpec,java.lang.String,java.lang.String[])\nclass InlineSuggestionInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstDefs=true, genHiddenConstructor=true)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index cdf8c68..7fd4150 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -5107,7 +5107,7 @@
                     int lineLeft = (int) layout.getLineLeft(line);
                     lineLeft += mTextView.getTotalPaddingLeft() - mTextView.getScrollX();
                     int lineRight = (int) layout.getLineRight(line);
-                    lineRight -= mTextView.getTotalPaddingRight() + mTextView.getScrollX();
+                    lineRight += mTextView.getTotalPaddingLeft() - mTextView.getScrollX();
                     mMagnifierAnimator.mMagnifier.setSourceHorizontalBounds(lineLeft, lineRight);
                 }
                 mMagnifierAnimator.show(showPosInView.x, showPosInView.y);
diff --git a/core/java/android/widget/ScrollBarDrawable.java b/core/java/android/widget/ScrollBarDrawable.java
index 80e17b5..c2d4596 100644
--- a/core/java/android/widget/ScrollBarDrawable.java
+++ b/core/java/android/widget/ScrollBarDrawable.java
@@ -138,7 +138,7 @@
         }
 
         final Rect r = getBounds();
-        if (canvas.quickReject(r.left, r.top, r.right, r.bottom, Canvas.EdgeType.AA)) {
+        if (canvas.quickReject(r.left, r.top, r.right, r.bottom)) {
             return;
         }
 
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index 42d7892..c8a7c07 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import static com.android.internal.util.Preconditions.checkNotNull;
+import static com.android.internal.util.Preconditions.checkState;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -24,6 +25,9 @@
 import android.annotation.StringRes;
 import android.app.INotificationManager;
 import android.app.ITransientNotification;
+import android.app.ITransientNotificationCallback;
+import android.compat.Compatibility;
+import android.compat.annotation.ChangeId;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -105,15 +109,45 @@
      */
     public static final int LENGTH_LONG = 1;
 
+    /**
+     * Text toasts will be rendered by SystemUI instead of in-app, so apps can't circumvent
+     * background custom toast restrictions.
+     *
+     * TODO(b/144152069): Add @EnabledAfter(Q) to target R+ after assessing impact on dogfood
+     */
+    @ChangeId
+    // @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
+    private static final long CHANGE_TEXT_TOASTS_IN_THE_SYSTEM = 147798919L;
+
+
     private final Binder mToken;
     private final Context mContext;
+    private final Handler mHandler;
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     final TN mTN;
     @UnsupportedAppUsage
     int mDuration;
-    View mNextView;
-    // TODO(b/128611929): Remove this and check for null view when toast creation is in the system
-    boolean mIsCustomToast = false;
+
+    /**
+     * This is also passed to {@link TN} object, where it's also accessed with itself as its own
+     * lock.
+     */
+    @GuardedBy("mCallbacks")
+    private final List<Callback> mCallbacks;
+
+    /**
+     * View to be displayed, in case this is a custom toast (e.g. not created with {@link
+     * #makeText(Context, int, int)} or its variants).
+     */
+    @Nullable
+    private View mNextView;
+
+    /**
+     * Text to be shown, in case this is NOT a custom toast (e.g. created with {@link
+     * #makeText(Context, int, int)} or its variants).
+     */
+    @Nullable
+    private CharSequence mText;
 
     /**
      * Construct an empty Toast object.  You must call {@link #setView} before you
@@ -133,19 +167,34 @@
     public Toast(@NonNull Context context, @Nullable Looper looper) {
         mContext = context;
         mToken = new Binder();
-        mTN = new TN(context.getPackageName(), mToken, looper);
+        looper = getLooper(looper);
+        mHandler = new Handler(looper);
+        mCallbacks = new ArrayList<>();
+        mTN = new TN(context.getPackageName(), mToken, mCallbacks, looper);
         mTN.mY = context.getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.toast_y_offset);
         mTN.mGravity = context.getResources().getInteger(
                 com.android.internal.R.integer.config_toastDefaultGravity);
     }
 
+    private Looper getLooper(@Nullable Looper looper) {
+        if (looper != null) {
+            return looper;
+        }
+        return checkNotNull(Looper.myLooper(),
+                "Can't toast on a thread that has not called Looper.prepare()");
+    }
+
     /**
      * Show the view for the specified duration.
      */
     public void show() {
-        if (mNextView == null) {
-            throw new RuntimeException("setView must have been called");
+        if (Compatibility.isChangeEnabled(CHANGE_TEXT_TOASTS_IN_THE_SYSTEM)) {
+            checkState(mNextView != null || mText != null, "You must either set a text or a view");
+        } else {
+            if (mNextView == null) {
+                throw new RuntimeException("setView must have been called");
+            }
         }
 
         INotificationManager service = getService();
@@ -155,10 +204,18 @@
         final int displayId = mContext.getDisplayId();
 
         try {
-            if (mIsCustomToast) {
-                service.enqueueToast(pkg, mToken, tn, mDuration, displayId);
+            if (Compatibility.isChangeEnabled(CHANGE_TEXT_TOASTS_IN_THE_SYSTEM)) {
+                if (mNextView != null) {
+                    // It's a custom toast
+                    service.enqueueToast(pkg, mToken, tn, mDuration, displayId);
+                } else {
+                    // It's a text toast
+                    ITransientNotificationCallback callback =
+                            new CallbackBinder(mCallbacks, mHandler);
+                    service.enqueueTextToast(pkg, mToken, mText, mDuration, displayId, callback);
+                }
             } else {
-                service.enqueueTextToast(pkg, mToken, tn, mDuration, displayId);
+                service.enqueueToast(pkg, mToken, tn, mDuration, displayId);
             }
         } catch (RemoteException e) {
             // Empty
@@ -171,7 +228,16 @@
      * after the appropriate duration.
      */
     public void cancel() {
-        mTN.cancel();
+        if (Compatibility.isChangeEnabled(CHANGE_TEXT_TOASTS_IN_THE_SYSTEM)
+                && mNextView == null) {
+            try {
+                getService().cancelToast(mContext.getOpPackageName(), mToken);
+            } catch (RemoteException e) {
+                // Empty
+            }
+        } else {
+            mTN.cancel();
+        }
     }
 
     /**
@@ -187,7 +253,6 @@
      */
     @Deprecated
     public void setView(View view) {
-        mIsCustomToast = true;
         mNextView = view;
     }
 
@@ -203,7 +268,6 @@
      *      will not have custom toast views displayed.
      */
     public View getView() {
-        mIsCustomToast = true;
         return mNextView;
     }
 
@@ -298,8 +362,8 @@
      */
     public void addCallback(@NonNull Callback callback) {
         checkNotNull(callback);
-        synchronized (mTN.mCallbacks) {
-            mTN.mCallbacks.add(callback);
+        synchronized (mCallbacks) {
+            mCallbacks.add(callback);
         }
     }
 
@@ -307,8 +371,8 @@
      * Removes a callback previously added with {@link #addCallback(Callback)}.
      */
     public void removeCallback(@NonNull Callback callback) {
-        synchronized (mTN.mCallbacks) {
-            mTN.mCallbacks.remove(callback);
+        synchronized (mCallbacks) {
+            mCallbacks.remove(callback);
         }
     }
 
@@ -338,22 +402,30 @@
     /**
      * Make a standard toast to display using the specified looper.
      * If looper is null, Looper.myLooper() is used.
+     *
      * @hide
      */
     public static Toast makeText(@NonNull Context context, @Nullable Looper looper,
             @NonNull CharSequence text, @Duration int duration) {
-        Toast result = new Toast(context, looper);
+        if (Compatibility.isChangeEnabled(CHANGE_TEXT_TOASTS_IN_THE_SYSTEM)) {
+            Toast result = new Toast(context, looper);
+            result.mText = text;
+            result.mDuration = duration;
+            return result;
+        } else {
+            Toast result = new Toast(context, looper);
 
-        LayoutInflater inflate = (LayoutInflater)
-                context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        View v = inflate.inflate(com.android.internal.R.layout.transient_notification, null);
-        TextView tv = (TextView)v.findViewById(com.android.internal.R.id.message);
-        tv.setText(text);
+            LayoutInflater inflate = (LayoutInflater)
+                    context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+            View v = inflate.inflate(com.android.internal.R.layout.transient_notification, null);
+            TextView tv = (TextView) v.findViewById(com.android.internal.R.id.message);
+            tv.setText(text);
 
-        result.mNextView = v;
-        result.mDuration = duration;
+            result.mNextView = v;
+            result.mDuration = duration;
 
-        return result;
+            return result;
+        }
     }
 
     /**
@@ -385,14 +457,23 @@
      * @param s The new text for the Toast.
      */
     public void setText(CharSequence s) {
-        if (mNextView == null) {
-            throw new RuntimeException("This Toast was not created with Toast.makeText()");
+        if (Compatibility.isChangeEnabled(CHANGE_TEXT_TOASTS_IN_THE_SYSTEM)) {
+            if (mNextView != null) {
+                throw new IllegalStateException(
+                        "Text provided for custom toast, remove previous setView() calls if you "
+                                + "want a text toast instead.");
+            }
+            mText = s;
+        } else {
+            if (mNextView == null) {
+                throw new RuntimeException("This Toast was not created with Toast.makeText()");
+            }
+            TextView tv = mNextView.findViewById(com.android.internal.R.id.message);
+            if (tv == null) {
+                throw new RuntimeException("This Toast was not created with Toast.makeText()");
+            }
+            tv.setText(s);
         }
-        TextView tv = mNextView.findViewById(com.android.internal.R.id.message);
-        if (tv == null) {
-            throw new RuntimeException("This Toast was not created with Toast.makeText()");
-        }
-        tv.setText(s);
     }
 
     // =======================================================================================
@@ -442,12 +523,18 @@
         final Binder mToken;
 
         @GuardedBy("mCallbacks")
-        private final List<Callback> mCallbacks = new ArrayList<>();
+        private final List<Callback> mCallbacks;
 
         static final long SHORT_DURATION_TIMEOUT = 4000;
         static final long LONG_DURATION_TIMEOUT = 7000;
 
-        TN(String packageName, Binder token, @Nullable Looper looper) {
+        /**
+         * Creates a {@link ITransientNotification} object.
+         *
+         * The parameter {@code callbacks} is not copied and is accessed with itself as its own
+         * lock.
+         */
+        TN(String packageName, Binder token, List<Callback> callbacks, @Nullable Looper looper) {
             // XXX This should be changed to use a Dialog, with a Theme.Toast
             // defined that sets up the layout params appropriately.
             final WindowManager.LayoutParams params = mParams;
@@ -464,15 +551,8 @@
 
             mPackageName = packageName;
             mToken = token;
+            mCallbacks = callbacks;
 
-            if (looper == null) {
-                // Use Looper.myLooper() if looper is not specified.
-                looper = Looper.myLooper();
-                if (looper == null) {
-                    throw new RuntimeException(
-                            "Can't toast on a thread that has not called Looper.prepare()");
-                }
-            }
             mHandler = new Handler(looper, null) {
                 @Override
                 public void handleMessage(Message msg) {
@@ -655,4 +735,46 @@
          */
         public void onToastHidden() {}
     }
+
+    private static class CallbackBinder extends ITransientNotificationCallback.Stub {
+        private final Handler mHandler;
+
+        @GuardedBy("mCallbacks")
+        private final List<Callback> mCallbacks;
+
+        /**
+         * Creates a {@link ITransientNotificationCallback} object.
+         *
+         * The parameter {@code callbacks} is not copied and is accessed with itself as its own
+         * lock.
+         */
+        private CallbackBinder(List<Callback> callbacks, Handler handler) {
+            mCallbacks = callbacks;
+            mHandler = handler;
+        }
+
+        @Override
+        public void onToastShown() {
+            mHandler.post(() -> {
+                for (Callback callback : getCallbacks()) {
+                    callback.onToastShown();
+                }
+            });
+        }
+
+        @Override
+        public void onToastHidden() {
+            mHandler.post(() -> {
+                for (Callback callback : getCallbacks()) {
+                    callback.onToastHidden();
+                }
+            });
+        }
+
+        private List<Callback> getCallbacks() {
+            synchronized (mCallbacks) {
+                return new ArrayList<>(mCallbacks);
+            }
+        }
+    }
 }
diff --git a/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
index b2aa043..77d8e02 100644
--- a/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
+++ b/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
@@ -156,14 +156,32 @@
     @VisibleForTesting
     public abstract Object getAdapterForIndex(int pageIndex);
 
+    /**
+     * Returns the {@link ResolverListAdapter} instance of the profile that represents
+     * <code>userHandle</code>. If there is no such adapter for the specified
+     * <code>userHandle</code>, returns {@code null}.
+     * <p>For example, if there is a work profile on the device with user id 10, calling this method
+     * with <code>UserHandle.of(10)</code> returns the work profile {@link ResolverListAdapter}.
+     */
+    @Nullable
+    abstract ResolverListAdapter getListAdapterForUserHandle(UserHandle userHandle);
+
+    /**
+     * Returns the {@link ResolverListAdapter} instance of the profile that is currently visible
+     * to the user.
+     * <p>For example, if the user is viewing the work tab in the share sheet, this method returns
+     * the work profile {@link ResolverListAdapter}.
+     * @see #getInactiveListAdapter()
+     */
     @VisibleForTesting
     public abstract ResolverListAdapter getActiveListAdapter();
 
     /**
      * If this is a device with a work profile, returns the {@link ResolverListAdapter} instance
-     * of the profile that is not the active one. Otherwise returns {@code null}. For example,
-     * if the share sheet is launched in the work profile, this method returns the personal
-     * profile {@link ResolverListAdapter}.
+     * of the profile that is <b><i>not</i></b> currently visible to the user. Otherwise returns
+     * {@code null}.
+     * <p>For example, if the user is viewing the work tab in the share sheet, this method returns
+     * the personal profile {@link ResolverListAdapter}.
      * @see #getActiveListAdapter()
      */
     @VisibleForTesting
diff --git a/core/java/com/android/internal/app/BlockedAppActivity.java b/core/java/com/android/internal/app/BlockedAppActivity.java
deleted file mode 100644
index fbdbbfb..0000000
--- a/core/java/com/android/internal/app/BlockedAppActivity.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.app;
-
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.text.TextUtils;
-import android.util.Slog;
-
-import com.android.internal.R;
-
-/**
- * A dialog shown to the user when they try to launch an app that is not allowed in lock task
- * mode. The intent to start this activity must be created with the static factory method provided
- * below.
- */
-public class BlockedAppActivity extends AlertActivity {
-
-    private static final String TAG = "BlockedAppActivity";
-    private static final String PACKAGE_NAME = "com.android.internal.app";
-    private static final String EXTRA_BLOCKED_PACKAGE = PACKAGE_NAME + ".extra.BLOCKED_PACKAGE";
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        Intent intent = getIntent();
-        int userId = intent.getIntExtra(Intent.EXTRA_USER_ID, /* defaultValue= */ -1);
-        if (userId < 0) {
-            Slog.wtf(TAG, "Invalid user: " + userId);
-            finish();
-            return;
-        }
-
-        String packageName = intent.getStringExtra(EXTRA_BLOCKED_PACKAGE);
-        if (TextUtils.isEmpty(packageName)) {
-            Slog.wtf(TAG, "Invalid package: " + packageName);
-            finish();
-            return;
-        }
-
-        CharSequence appLabel = getAppLabel(userId, packageName);
-
-        mAlertParams.mTitle = getString(R.string.app_blocked_title);
-        mAlertParams.mMessage = getString(R.string.app_blocked_message, appLabel);
-        mAlertParams.mPositiveButtonText = getString(android.R.string.ok);
-        setupAlert();
-    }
-
-    private CharSequence getAppLabel(int userId, String packageName) {
-        PackageManager pm = getPackageManager();
-        try {
-            ApplicationInfo aInfo =
-                    pm.getApplicationInfoAsUser(packageName, /* flags= */ 0, userId);
-            return aInfo.loadLabel(pm);
-        } catch (PackageManager.NameNotFoundException ne) {
-            Slog.e(TAG, "Package " + packageName + " not found", ne);
-        }
-        return packageName;
-    }
-
-
-    /** Creates an intent that launches {@link BlockedAppActivity}. */
-    public static Intent createIntent(int userId, String packageName) {
-        return new Intent()
-                .setClassName("android", BlockedAppActivity.class.getName())
-                .putExtra(Intent.EXTRA_USER_ID, userId)
-                .putExtra(EXTRA_BLOCKED_PACKAGE, packageName);
-    }
-}
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 8bbc343..65128e4 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -72,7 +72,6 @@
 import android.os.Message;
 import android.os.Parcelable;
 import android.os.PatternMatcher;
-import android.os.Process;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.UserHandle;
@@ -90,6 +89,7 @@
 import android.util.AttributeSet;
 import android.util.HashedStringCache;
 import android.util.Log;
+import android.util.Pair;
 import android.util.Size;
 import android.util.Slog;
 import android.view.LayoutInflater;
@@ -150,6 +150,8 @@
         ChooserListAdapter.ChooserListCommunicator,
         SelectableTargetInfoCommunicator {
     private static final String TAG = "ChooserActivity";
+    private AppPredictor mPersonalAppPredictor;
+    private AppPredictor mWorkAppPredictor;
 
     @UnsupportedAppUsage
     public ChooserActivity() {
@@ -164,7 +166,7 @@
 
     private static final String PREF_NUM_SHEET_EXPANSIONS = "pref_num_sheet_expansions";
 
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = true;
 
     private static final boolean USE_PREDICTION_MANAGER_FOR_SHARE_ACTIVITIES = true;
     // TODO(b/123088566) Share these in a better way.
@@ -177,9 +179,8 @@
     public static final int LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS = 250;
 
     private boolean mIsAppPredictorComponentAvailable;
-    private AppPredictor mAppPredictor;
-    private AppPredictor.Callback mAppPredictorCallback;
     private Map<ChooserTarget, AppTarget> mDirectShareAppTargetCache;
+    private Map<ChooserTarget, ShortcutInfo> mDirectShareShortcutInfoCache;
 
     public static final int TARGET_TYPE_DEFAULT = 0;
     public static final int TARGET_TYPE_CHOOSER_TARGET = 1;
@@ -239,7 +240,7 @@
     private static final int MAX_RANKED_TARGETS = 4;
 
     private final List<ChooserTargetServiceConnection> mServiceConnections = new ArrayList<>();
-    private final Set<ComponentName> mServicesRequested = new HashSet<>();
+    private final Set<Pair<ComponentName, UserHandle>> mServicesRequested = new HashSet<>();
 
     private static final int MAX_LOG_RANK_POSITION = 12;
 
@@ -422,6 +423,7 @@
                     WATCHDOG_TIMEOUT_MIN_MILLIS);
             sendEmptyMessageDelayed(CHOOSER_TARGET_SERVICE_WATCHDOG_MAX_TIMEOUT,
                     WATCHDOG_TIMEOUT_MAX_MILLIS);
+
         }
 
         private void maybeStopServiceRequestTimer() {
@@ -454,10 +456,14 @@
                         break;
                     }
                     if (sri.resultTargets != null) {
-                        // TODO(arangelov): Instead of using getCurrentListAdapter(), pass the
-                        // profileId as part of the message.
-                        mChooserMultiProfilePagerAdapter.getActiveListAdapter().addServiceResults(
-                                sri.originalTarget, sri.resultTargets, TARGET_TYPE_CHOOSER_TARGET);
+                        ChooserListAdapter adapterForUserHandle =
+                                mChooserMultiProfilePagerAdapter.getListAdapterForUserHandle(
+                                        sri.userHandle);
+                        if (adapterForUserHandle != null) {
+                            adapterForUserHandle.addServiceResults(sri.originalTarget,
+                                    sri.resultTargets, TARGET_TYPE_CHOOSER_TARGET,
+                                    /* directShareShortcutInfoCache */ null);
+                        }
                     }
                     unbindService(sri.connection);
                     sri.connection.destroy();
@@ -480,15 +486,23 @@
                         Log.d(TAG, "LIST_VIEW_UPDATE_MESSAGE; ");
                     }
 
-                    mChooserMultiProfilePagerAdapter.getActiveListAdapter().refreshListView();
+                    UserHandle userHandle = (UserHandle) msg.obj;
+                    mChooserMultiProfilePagerAdapter.getListAdapterForUserHandle(userHandle)
+                            .refreshListView();
                     break;
 
                 case SHORTCUT_MANAGER_SHARE_TARGET_RESULT:
                     if (DEBUG) Log.d(TAG, "SHORTCUT_MANAGER_SHARE_TARGET_RESULT");
                     final ServiceResultInfo resultInfo = (ServiceResultInfo) msg.obj;
                     if (resultInfo.resultTargets != null) {
-                        mChooserMultiProfilePagerAdapter.getActiveListAdapter().addServiceResults(
-                                resultInfo.originalTarget, resultInfo.resultTargets, msg.arg1);
+                        ChooserListAdapter adapterForUserHandle =
+                                mChooserMultiProfilePagerAdapter.getListAdapterForUserHandle(
+                                        resultInfo.userHandle);
+                        if (adapterForUserHandle != null) {
+                            adapterForUserHandle.addServiceResults(
+                                    resultInfo.originalTarget, resultInfo.resultTargets, msg.arg1,
+                                    mDirectShareShortcutInfoCache);
+                        }
                     }
                     break;
 
@@ -638,45 +652,6 @@
                 .addTaggedData(MetricsEvent.FIELD_SHARESHEET_MIMETYPE, target.getType())
                 .addTaggedData(MetricsEvent.FIELD_TIME_TO_APP_TARGETS, systemCost));
 
-        AppPredictor appPredictor = getAppPredictorForDirectShareIfEnabled();
-        if (appPredictor != null) {
-            mDirectShareAppTargetCache = new HashMap<>();
-            mAppPredictorCallback = resultList -> {
-                //TODO(arangelov) Take care of edge case when callback called after swiping tabs
-                if (isFinishing() || isDestroyed()) {
-                    return;
-                }
-                if (mChooserMultiProfilePagerAdapter.getActiveListAdapter().getCount() == 0) {
-                    return;
-                }
-                if (resultList.isEmpty()) {
-                    // APS may be disabled, so try querying targets ourselves.
-                    //TODO(arangelov) queryDirectShareTargets indirectly uses mIntents.
-                    // Investigate implications for work tab.
-                    queryDirectShareTargets(
-                            mChooserMultiProfilePagerAdapter.getActiveListAdapter(), true);
-                    return;
-                }
-                final List<DisplayResolveInfo> driList =
-                        getDisplayResolveInfos(
-                                mChooserMultiProfilePagerAdapter.getActiveListAdapter());
-                final List<ShortcutManager.ShareShortcutInfo> shareShortcutInfos =
-                        new ArrayList<>();
-                for (AppTarget appTarget : resultList) {
-                    if (appTarget.getShortcutInfo() == null) {
-                        continue;
-                    }
-                    shareShortcutInfos.add(new ShortcutManager.ShareShortcutInfo(
-                            appTarget.getShortcutInfo(),
-                            new ComponentName(
-                                appTarget.getPackageName(), appTarget.getClassName())));
-                }
-                sendShareShortcutInfoList(shareShortcutInfos, driList, resultList);
-            };
-            appPredictor
-                .registerPredictionUpdates(this.getMainExecutor(), mAppPredictorCallback);
-        }
-
         mChooserRowServiceSpacing = getResources()
                                         .getDimensionPixelSize(R.dimen.chooser_service_spacing);
 
@@ -707,6 +682,54 @@
         if (DEBUG) {
             Log.d(TAG, "System Time Cost is " + systemCost);
         }
+
+        mDirectShareShortcutInfoCache = new HashMap<>();
+    }
+
+    private AppPredictor setupAppPredictorForUser(UserHandle userHandle,
+            AppPredictor.Callback appPredictorCallback) {
+        AppPredictor appPredictor = getAppPredictorForDirectShareIfEnabled(userHandle);
+        if (appPredictor == null) {
+            return null;
+        }
+        mDirectShareAppTargetCache = new HashMap<>();
+        appPredictor.registerPredictionUpdates(this.getMainExecutor(), appPredictorCallback);
+        return appPredictor;
+    }
+
+    private AppPredictor.Callback createAppPredictorCallback(
+            ChooserListAdapter chooserListAdapter) {
+        return resultList -> {
+            //TODO(arangelov) Take care of edge case when callback called after swiping tabs
+            if (isFinishing() || isDestroyed()) {
+                return;
+            }
+            if (chooserListAdapter.getCount() == 0) {
+                return;
+            }
+            if (resultList.isEmpty()) {
+                // APS may be disabled, so try querying targets ourselves.
+                //TODO(arangelov) queryDirectShareTargets indirectly uses mIntents.
+                // Investigate implications for work tab.
+                queryDirectShareTargets(chooserListAdapter, true);
+                return;
+            }
+            final List<DisplayResolveInfo> driList =
+                    getDisplayResolveInfos(chooserListAdapter);
+            final List<ShortcutManager.ShareShortcutInfo> shareShortcutInfos =
+                    new ArrayList<>();
+            for (AppTarget appTarget : resultList) {
+                if (appTarget.getShortcutInfo() == null) {
+                    continue;
+                }
+                shareShortcutInfos.add(new ShortcutManager.ShareShortcutInfo(
+                        appTarget.getShortcutInfo(),
+                        new ComponentName(
+                                appTarget.getPackageName(), appTarget.getClassName())));
+            }
+            sendShareShortcutInfoList(shareShortcutInfos, driList, resultList,
+                    chooserListAdapter.getUserHandle());
+        };
     }
 
     static SharedPreferences getPinnedSharedPrefs(Context context) {
@@ -1260,9 +1283,9 @@
 
         if (mPreviewCoord != null) mPreviewCoord.cancelLoads();
 
-        if (mAppPredictor != null) {
-            mAppPredictor.unregisterPredictionUpdates(mAppPredictorCallback);
-            mAppPredictor.destroy();
+        mChooserMultiProfilePagerAdapter.getActiveListAdapter().destroyAppPredictor();
+        if (mChooserMultiProfilePagerAdapter.getInactiveListAdapter() != null) {
+            mChooserMultiProfilePagerAdapter.getInactiveListAdapter().destroyAppPredictor();
         }
     }
 
@@ -1312,7 +1335,8 @@
             mChooserMultiProfilePagerAdapter.getActiveListAdapter().addServiceResults(
                     /* origTarget */ null,
                     Lists.newArrayList(mCallerChooserTargets),
-                    TARGET_TYPE_DEFAULT);
+                    TARGET_TYPE_DEFAULT,
+                    /* directShareShortcutInfoCache */ null);
         }
     }
 
@@ -1541,8 +1565,10 @@
     void queryTargetServices(ChooserListAdapter adapter) {
         mQueriedTargetServicesTimeMs = System.currentTimeMillis();
 
-        final PackageManager pm = getPackageManager();
-        ShortcutManager sm = (ShortcutManager) getSystemService(ShortcutManager.class);
+        Context selectedProfileContext = createContextAsUser(
+                adapter.getUserHandle(), 0 /* flags */);
+        final PackageManager pm = selectedProfileContext.getPackageManager();
+        ShortcutManager sm = selectedProfileContext.getSystemService(ShortcutManager.class);
         int targetsToQuery = 0;
 
         for (int i = 0, N = adapter.getDisplayResolveInfoCount(); i < N; i++) {
@@ -1565,10 +1591,13 @@
                 final ComponentName serviceComponent = new ComponentName(
                         ai.packageName, serviceName);
 
-                if (mServicesRequested.contains(serviceComponent)) {
+                UserHandle userHandle = adapter.getUserHandle();
+                Pair<ComponentName, UserHandle> requestedItem =
+                        new Pair<>(serviceComponent, userHandle);
+                if (mServicesRequested.contains(requestedItem)) {
                     continue;
                 }
-                mServicesRequested.add(serviceComponent);
+                mServicesRequested.add(requestedItem);
 
                 final Intent serviceIntent = new Intent(ChooserTargetService.SERVICE_INTERFACE)
                         .setComponent(serviceComponent);
@@ -1596,13 +1625,14 @@
                 }
 
                 final ChooserTargetServiceConnection conn =
-                        new ChooserTargetServiceConnection(this, dri);
+                        new ChooserTargetServiceConnection(this, dri,
+                                adapter.getUserHandle());
 
-                // Explicitly specify Process.myUserHandle instead of calling bindService
+                // Explicitly specify the user handle instead of calling bindService
                 // to avoid the warning from calling from the system process without an explicit
                 // user handle
                 if (bindServiceAsUser(serviceIntent, conn, BIND_AUTO_CREATE | BIND_NOT_FOREGROUND,
-                        Process.myUserHandle())) {
+                        adapter.getUserHandle())) {
                     if (DEBUG) {
                         Log.d(TAG, "Binding service connection for target " + dri
                                 + " intent " + serviceIntent);
@@ -1684,8 +1714,9 @@
     private void queryDirectShareTargets(
                 ChooserListAdapter adapter, boolean skipAppPredictionService) {
         mQueriedSharingShortcutsTimeMs = System.currentTimeMillis();
+        UserHandle userHandle = adapter.getUserHandle();
         if (!skipAppPredictionService) {
-            AppPredictor appPredictor = getAppPredictorForDirectShareIfEnabled();
+            AppPredictor appPredictor = getAppPredictorForDirectShareIfEnabled(userHandle);
             if (appPredictor != null) {
                 appPredictor.requestPredictionUpdate();
                 return;
@@ -1700,17 +1731,18 @@
         final List<DisplayResolveInfo> driList = getDisplayResolveInfos(adapter);
 
         AsyncTask.execute(() -> {
-            //TODO(arangelov) use the selected probile tab's ShortcutManager
-            ShortcutManager sm = (ShortcutManager) getSystemService(Context.SHORTCUT_SERVICE);
+            Context selectedProfileContext = createContextAsUser(userHandle, 0 /* flags */);
+            ShortcutManager sm = (ShortcutManager) selectedProfileContext
+                    .getSystemService(Context.SHORTCUT_SERVICE);
             List<ShortcutManager.ShareShortcutInfo> resultList = sm.getShareTargets(filter);
-            sendShareShortcutInfoList(resultList, driList, null);
+            sendShareShortcutInfoList(resultList, driList, null, userHandle);
         });
     }
 
     private void sendShareShortcutInfoList(
                 List<ShortcutManager.ShareShortcutInfo> resultList,
                 List<DisplayResolveInfo> driList,
-                @Nullable List<AppTarget> appTargets) {
+                @Nullable List<AppTarget> appTargets, UserHandle userHandle) {
         if (appTargets != null && appTargets.size() != resultList.size()) {
             throw new RuntimeException("resultList and appTargets must have the same size."
                     + " resultList.size()=" + resultList.size()
@@ -1749,9 +1781,11 @@
             List<ChooserTarget> chooserTargets = convertToChooserTarget(
                     matchingShortcuts, resultList, appTargets, shortcutType);
 
+
+
             final Message msg = Message.obtain();
             msg.what = ChooserHandler.SHORTCUT_MANAGER_SHARE_TARGET_RESULT;
-            msg.obj = new ServiceResultInfo(driList.get(i), chooserTargets, null);
+            msg.obj = new ServiceResultInfo(driList.get(i), chooserTargets, null, userHandle);
             msg.arg1 = shortcutType;
             mChooserHandler.sendMessage(msg);
             resultMessageSent = true;
@@ -1842,6 +1876,9 @@
                 mDirectShareAppTargetCache.put(chooserTarget,
                         allAppTargets.get(indexInAllShortcuts));
             }
+            if (mDirectShareShortcutInfoCache != null) {
+                mDirectShareShortcutInfoCache.put(chooserTarget, shortcutInfo);
+            }
         }
         // Sort ChooserTargets by score in descending order
         Comparator<ChooserTarget> byScore =
@@ -1915,7 +1952,8 @@
     }
 
     private void sendClickToAppPredictor(TargetInfo targetInfo) {
-        AppPredictor directShareAppPredictor = getAppPredictorForDirectShareIfEnabled();
+        AppPredictor directShareAppPredictor = getAppPredictorForDirectShareIfEnabled(
+                mChooserMultiProfilePagerAdapter.getCurrentUserHandle());
         if (directShareAppPredictor == null) {
             return;
         }
@@ -1937,34 +1975,54 @@
     }
 
     @Nullable
-    private AppPredictor getAppPredictor() {
+    private AppPredictor createAppPredictor(UserHandle userHandle) {
         if (!mIsAppPredictorComponentAvailable) {
             return null;
         }
-        if (mAppPredictor == null) {
-            final IntentFilter filter = getTargetIntentFilter();
-            Bundle extras = new Bundle();
-            extras.putParcelable(APP_PREDICTION_INTENT_FILTER_KEY, filter);
-            AppPredictionContext appPredictionContext = new AppPredictionContext.Builder(this)
-                .setUiSurface(APP_PREDICTION_SHARE_UI_SURFACE)
-                .setPredictedTargetCount(APP_PREDICTION_SHARE_TARGET_QUERY_PACKAGE_LIMIT)
-                .setExtras(extras)
-                .build();
-            AppPredictionManager appPredictionManager
-                    = getSystemService(AppPredictionManager.class);
-            mAppPredictor = appPredictionManager.createAppPredictionSession(appPredictionContext);
+
+        if (getPersonalProfileUserHandle() == userHandle) {
+            if (mPersonalAppPredictor != null) {
+                return mPersonalAppPredictor;
+            }
+        } else {
+            if (mWorkAppPredictor != null) {
+                return mWorkAppPredictor;
+            }
         }
-        return mAppPredictor;
+
+        // TODO(b/148230574): Currently AppPredictor fetches only the same-profile app targets.
+        // Make AppPredictor work cross-profile.
+        Context contextAsUser = createContextAsUser(userHandle, 0 /* flags */);
+        final IntentFilter filter = getTargetIntentFilter();
+        Bundle extras = new Bundle();
+        extras.putParcelable(APP_PREDICTION_INTENT_FILTER_KEY, filter);
+        AppPredictionContext appPredictionContext = new AppPredictionContext.Builder(contextAsUser)
+            .setUiSurface(APP_PREDICTION_SHARE_UI_SURFACE)
+            .setPredictedTargetCount(APP_PREDICTION_SHARE_TARGET_QUERY_PACKAGE_LIMIT)
+            .setExtras(extras)
+            .build();
+        AppPredictionManager appPredictionManager =
+                contextAsUser
+                        .getSystemService(AppPredictionManager.class);
+        AppPredictor appPredictionSession = appPredictionManager.createAppPredictionSession(
+                appPredictionContext);
+        if (getPersonalProfileUserHandle() == userHandle) {
+            mPersonalAppPredictor = appPredictionSession;
+        } else {
+            mWorkAppPredictor = appPredictionSession;
+        }
+        return appPredictionSession;
     }
 
     /**
      * This will return an app predictor if it is enabled for direct share sorting
      * and if one exists. Otherwise, it returns null.
+     * @param userHandle
      */
     @Nullable
-    private AppPredictor getAppPredictorForDirectShareIfEnabled() {
+    private AppPredictor getAppPredictorForDirectShareIfEnabled(UserHandle userHandle) {
         return ChooserFlags.USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS
-                && !ActivityManager.isLowRamDeviceStatic() ? getAppPredictor() : null;
+                && !ActivityManager.isLowRamDeviceStatic() ? createAppPredictor(userHandle) : null;
     }
 
     /**
@@ -1972,8 +2030,8 @@
      * and if one exists. Otherwise, it returns null.
      */
     @Nullable
-    private AppPredictor getAppPredictorForShareActivitesIfEnabled() {
-        return USE_PREDICTION_MANAGER_FOR_SHARE_ACTIVITIES ? getAppPredictor() : null;
+    private AppPredictor getAppPredictorForShareActivitiesIfEnabled(UserHandle userHandle) {
+        return USE_PREDICTION_MANAGER_FOR_SHARE_ACTIVITIES ? createAppPredictor(userHandle) : null;
     }
 
     void onRefinementResult(TargetInfo selectedTarget, Intent matchingIntent) {
@@ -2016,12 +2074,13 @@
         return false;
     }
 
-    void filterServiceTargets(String packageName, List<ChooserTarget> targets) {
+    void filterServiceTargets(Context contextAsUser, String packageName,
+            List<ChooserTarget> targets) {
         if (targets == null) {
             return;
         }
 
-        final PackageManager pm = getPackageManager();
+        final PackageManager pm = contextAsUser.getPackageManager();
         for (int i = targets.size() - 1; i >= 0; i--) {
             final ChooserTarget target = targets.get(i);
             final ComponentName targetName = target.getComponentName();
@@ -2104,19 +2163,24 @@
     public ChooserGridAdapter createChooserGridAdapter(Context context,
             List<Intent> payloadIntents, Intent[] initialIntents, List<ResolveInfo> rList,
             boolean filterLastUsed, boolean useLayoutForBrowsables, UserHandle userHandle) {
-        return new ChooserGridAdapter(
-                new ChooserListAdapter(context, payloadIntents, initialIntents, rList,
-                        filterLastUsed, createListController(userHandle), useLayoutForBrowsables,
-                        this, this));
+        ChooserListAdapter chooserListAdapter = new ChooserListAdapter(context, payloadIntents,
+                initialIntents, rList,
+                filterLastUsed, createListController(userHandle), useLayoutForBrowsables,
+                this, this);
+        AppPredictor.Callback appPredictorCallback = createAppPredictorCallback(chooserListAdapter);
+        AppPredictor appPredictor = setupAppPredictorForUser(userHandle, appPredictorCallback);
+        chooserListAdapter.setAppPredictor(appPredictor);
+        chooserListAdapter.setAppPredictorCallback(appPredictorCallback);
+        return new ChooserGridAdapter(chooserListAdapter);
     }
 
     @VisibleForTesting
     protected ResolverListController createListController(UserHandle userHandle) {
-        AppPredictor appPredictor = getAppPredictorForShareActivitesIfEnabled();
+        AppPredictor appPredictor = getAppPredictorForShareActivitiesIfEnabled(userHandle);
         AbstractResolverComparator resolverComparator;
         if (appPredictor != null) {
             resolverComparator = new AppPredictionServiceResolverComparator(this, getTargetIntent(),
-                    getReferrerPackageName(), appPredictor, getUser());
+                    getReferrerPackageName(), appPredictor, userHandle);
         } else {
             resolverComparator =
                     new ResolverRankerServiceResolverComparator(this, getTargetIntent(),
@@ -2297,9 +2361,11 @@
     }
 
     @Override // ChooserListCommunicator
-    public void sendListViewUpdateMessage() {
-        mChooserHandler.sendEmptyMessageDelayed(ChooserHandler.LIST_VIEW_UPDATE_MESSAGE,
-                LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);
+    public void sendListViewUpdateMessage(UserHandle userHandle) {
+        Message msg = Message.obtain();
+        msg.what = ChooserHandler.LIST_VIEW_UPDATE_MESSAGE;
+        msg.obj = userHandle;
+        mChooserHandler.sendMessageDelayed(msg, LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);
     }
 
     @Override
@@ -3158,6 +3224,7 @@
         private DisplayResolveInfo mOriginalTarget;
         private ComponentName mConnectedComponent;
         private ChooserActivity mChooserActivity;
+        private final UserHandle mUserHandle;
         private final Object mLock = new Object();
 
         private final IChooserTargetResult mChooserTargetResult = new IChooserTargetResult.Stub() {
@@ -3169,21 +3236,24 @@
                                 + mConnectedComponent + "; ignoring...");
                         return;
                     }
-                    mChooserActivity.filterServiceTargets(
+                    Context contextAsUser =
+                            mChooserActivity.createContextAsUser(mUserHandle, 0 /* flags */);
+                    mChooserActivity.filterServiceTargets(contextAsUser,
                             mOriginalTarget.getResolveInfo().activityInfo.packageName, targets);
                     final Message msg = Message.obtain();
                     msg.what = ChooserHandler.CHOOSER_TARGET_SERVICE_RESULT;
                     msg.obj = new ServiceResultInfo(mOriginalTarget, targets,
-                            ChooserTargetServiceConnection.this);
+                            ChooserTargetServiceConnection.this, mUserHandle);
                     mChooserActivity.mChooserHandler.sendMessage(msg);
                 }
             }
         };
 
         public ChooserTargetServiceConnection(ChooserActivity chooserActivity,
-                DisplayResolveInfo dri) {
+                DisplayResolveInfo dri, UserHandle userHandle) {
             mChooserActivity = chooserActivity;
             mOriginalTarget = dri;
+            mUserHandle = userHandle;
         }
 
         @Override
@@ -3249,12 +3319,14 @@
         public final DisplayResolveInfo originalTarget;
         public final List<ChooserTarget> resultTargets;
         public final ChooserTargetServiceConnection connection;
+        public final UserHandle userHandle;
 
         public ServiceResultInfo(DisplayResolveInfo ot, List<ChooserTarget> rt,
-                ChooserTargetServiceConnection c) {
+                ChooserTargetServiceConnection c, UserHandle userHandle) {
             originalTarget = ot;
             resultTargets = rt;
             connection = c;
+            this.userHandle = userHandle;
         }
     }
 
diff --git a/core/java/com/android/internal/app/ChooserListAdapter.java b/core/java/com/android/internal/app/ChooserListAdapter.java
index 6ff844a..ca3b7e7 100644
--- a/core/java/com/android/internal/app/ChooserListAdapter.java
+++ b/core/java/com/android/internal/app/ChooserListAdapter.java
@@ -19,7 +19,9 @@
 import static com.android.internal.app.ChooserActivity.TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE;
 import static com.android.internal.app.ChooserActivity.TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER;
 
+import android.annotation.Nullable;
 import android.app.ActivityManager;
+import android.app.prediction.AppPredictor;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -27,7 +29,9 @@
 import android.content.pm.LabeledIntent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.content.pm.ShortcutInfo;
 import android.os.AsyncTask;
+import android.os.UserHandle;
 import android.os.UserManager;
 import android.service.chooser.ChooserTarget;
 import android.util.Log;
@@ -90,6 +94,8 @@
 
     // Sorted list of DisplayResolveInfos for the alphabetical app section.
     private List<DisplayResolveInfo> mSortedList = new ArrayList<>();
+    private AppPredictor mAppPredictor;
+    private AppPredictor.Callback mAppPredictorCallback;
 
     public ChooserListAdapter(Context context, List<Intent> payloadIntents,
             Intent[] initialIntents, List<ResolveInfo> rList,
@@ -160,6 +166,10 @@
         }
     }
 
+    AppPredictor getAppPredictor() {
+        return mAppPredictor;
+    }
+
     @Override
     public void handlePackagesChanged() {
         if (DEBUG) {
@@ -173,7 +183,7 @@
     @Override
     public void notifyDataSetChanged() {
         if (!mListViewDataChanged) {
-            mChooserListCommunicator.sendListViewUpdateMessage();
+            mChooserListCommunicator.sendListViewUpdateMessage(getUserHandle());
             mListViewDataChanged = true;
         }
     }
@@ -383,7 +393,8 @@
      * if score is too low.
      */
     public void addServiceResults(DisplayResolveInfo origTarget, List<ChooserTarget> targets,
-            @ChooserActivity.ShareTargetType int targetType) {
+            @ChooserActivity.ShareTargetType int targetType,
+            Map<ChooserTarget, ShortcutInfo> directShareToShortcutInfos) {
         if (DEBUG) {
             Log.d(TAG, "addServiceResults " + origTarget + ", " + targets.size()
                     + " targets");
@@ -412,8 +423,11 @@
                 // This incents ChooserTargetServices to define what's truly better.
                 targetScore = lastScore * 0.95f;
             }
-            boolean isInserted = insertServiceTarget(new SelectableTargetInfo(
-                    mContext, origTarget, target, targetScore, mSelectableTargetInfoComunicator));
+            UserHandle userHandle = getUserHandle();
+            Context contextAsUser = mContext.createContextAsUser(userHandle, 0 /* flags */);
+            boolean isInserted = insertServiceTarget(new SelectableTargetInfo(contextAsUser,
+                    origTarget, target, targetScore, mSelectableTargetInfoComunicator,
+                    (isShortcutResult ? directShareToShortcutInfos.get(target) : null)));
 
             if (isInserted && isShortcutResult) {
                 mNumShortcutResults++;
@@ -547,6 +561,21 @@
         };
     }
 
+    public void setAppPredictor(AppPredictor appPredictor) {
+        mAppPredictor = appPredictor;
+    }
+
+    public void setAppPredictorCallback(AppPredictor.Callback appPredictorCallback) {
+        mAppPredictorCallback = appPredictorCallback;
+    }
+
+    public void destroyAppPredictor() {
+        if (getAppPredictor() != null) {
+            getAppPredictor().unregisterPredictionUpdates(mAppPredictorCallback);
+            getAppPredictor().destroy();
+        }
+    }
+
     /**
      * Necessary methods to communicate between {@link ChooserListAdapter}
      * and {@link ChooserActivity}.
@@ -555,7 +584,7 @@
 
         int getMaxRankedTargets();
 
-        void sendListViewUpdateMessage();
+        void sendListViewUpdateMessage(UserHandle userHandle);
 
         boolean isSendAction(Intent targetIntent);
     }
diff --git a/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java
index 1c52d0e..663e025 100644
--- a/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java
+++ b/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java
@@ -18,6 +18,7 @@
 
 import android.annotation.Nullable;
 import android.content.Context;
+import android.os.UserHandle;
 import android.view.LayoutInflater;
 import android.view.ViewGroup;
 
@@ -84,6 +85,18 @@
     }
 
     @Override
+    @Nullable
+    ChooserListAdapter getListAdapterForUserHandle(UserHandle userHandle) {
+        if (getActiveListAdapter().getUserHandle() == userHandle) {
+            return getActiveListAdapter();
+        } else if (getInactiveListAdapter() != null
+                && getInactiveListAdapter().getUserHandle() == userHandle) {
+            return getInactiveListAdapter();
+        }
+        return null;
+    }
+
+    @Override
     void setupListAdapter(int pageIndex) {
         final RecyclerView recyclerView = getItem(pageIndex).recyclerView;
         ChooserActivity.ChooserGridAdapter chooserGridAdapter =
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 68d6e03..30a41d3 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -543,6 +543,9 @@
     public void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
         mMultiProfilePagerAdapter.getActiveListAdapter().handlePackagesChanged();
+        if (mMultiProfilePagerAdapter.getInactiveListAdapter() != null) {
+            mMultiProfilePagerAdapter.getInactiveListAdapter().handlePackagesChanged();
+        }
 
         if (mSystemWindowInsets != null) {
             mResolverDrawerLayout.setPadding(mSystemWindowInsets.left, mSystemWindowInsets.top,
@@ -1101,6 +1104,9 @@
         }
 
         if (target != null) {
+            if (intent != null) {
+                intent.fixUris(UserHandle.myUserId());
+            }
             safelyStartActivity(target);
 
             // Rely on the ActivityManager to pop up a dialog regarding app suspension
diff --git a/core/java/com/android/internal/app/ResolverListAdapter.java b/core/java/com/android/internal/app/ResolverListAdapter.java
index d227ec5..405112d 100644
--- a/core/java/com/android/internal/app/ResolverListAdapter.java
+++ b/core/java/com/android/internal/app/ResolverListAdapter.java
@@ -407,6 +407,7 @@
     // We assume that at this point we've already filtered out the only intent for a different
     // targetUserId which we're going to use.
     private void addResolveInfo(DisplayResolveInfo dri) {
+        // TODO(arangelov): Is that UserHandle.USER_CURRENT check okay?
         if (dri != null && dri.getResolveInfo() != null
                 && dri.getResolveInfo().targetUserId == UserHandle.USER_CURRENT) {
             // Checks if this info is already listed in display.
@@ -575,7 +576,7 @@
 
     Drawable loadIconForResolveInfo(ResolveInfo ri) {
         // Load icons based on the current process. If in work profile icons should be badged.
-        return makePresentationGetter(ri).getIcon(mResolverListController.getUserHandle());
+        return makePresentationGetter(ri).getIcon(getUserHandle());
     }
 
     void loadFilteredItemIconTaskAsync(@NonNull ImageView iconView) {
@@ -585,6 +586,10 @@
         }
     }
 
+    UserHandle getUserHandle() {
+        return mResolverListController.getUserHandle();
+    }
+
     /**
      * Necessary methods to communicate between {@link ResolverListAdapter}
      * and {@link ResolverActivity}.
diff --git a/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java
index 567ed74..9d3c6c9 100644
--- a/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java
+++ b/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java
@@ -18,6 +18,7 @@
 
 import android.annotation.Nullable;
 import android.content.Context;
+import android.os.UserHandle;
 import android.view.LayoutInflater;
 import android.view.ViewGroup;
 import android.widget.ListView;
@@ -88,6 +89,18 @@
     }
 
     @Override
+    @Nullable
+    ResolverListAdapter getListAdapterForUserHandle(UserHandle userHandle) {
+        if (getActiveListAdapter().getUserHandle() == userHandle) {
+            return getActiveListAdapter();
+        } else if (getInactiveListAdapter() != null
+                && getInactiveListAdapter().getUserHandle() == userHandle) {
+            return getInactiveListAdapter();
+        }
+        return null;
+    }
+
+    @Override
     @VisibleForTesting
     public ResolverListAdapter getActiveListAdapter() {
         return getAdapterForIndex(getCurrentPage());
diff --git a/core/java/com/android/internal/app/SuspendedAppActivity.java b/core/java/com/android/internal/app/SuspendedAppActivity.java
index c610ac4..0589baa 100644
--- a/core/java/com/android/internal/app/SuspendedAppActivity.java
+++ b/core/java/com/android/internal/app/SuspendedAppActivity.java
@@ -18,23 +18,31 @@
 
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
+import static android.content.pm.SuspendDialogInfo.BUTTON_ACTION_MORE_DETAILS;
+import static android.content.pm.SuspendDialogInfo.BUTTON_ACTION_UNSUSPEND;
 import static android.content.res.Resources.ID_NULL;
 
 import android.Manifest;
+import android.annotation.Nullable;
 import android.app.AlertDialog;
+import android.app.AppGlobals;
 import android.content.DialogInterface;
 import android.content.Intent;
+import android.content.IntentSender;
+import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.SuspendDialogInfo;
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
+import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.Slog;
 import android.view.WindowManager;
 
 import com.android.internal.R;
+import com.android.internal.util.ArrayUtils;
 
 public class SuspendedAppActivity extends AlertActivity
         implements DialogInterface.OnClickListener {
@@ -46,8 +54,13 @@
             PACKAGE_NAME + ".extra.SUSPENDING_PACKAGE";
     public static final String EXTRA_DIALOG_INFO = PACKAGE_NAME + ".extra.DIALOG_INFO";
     public static final String EXTRA_ACTIVITY_OPTIONS = PACKAGE_NAME + ".extra.ACTIVITY_OPTIONS";
+    public static final String EXTRA_UNSUSPEND_INTENT = PACKAGE_NAME + ".extra.UNSUSPEND_INTENT";
 
     private Intent mMoreDetailsIntent;
+    private IntentSender mOnUnsuspend;
+    private String mSuspendedPackage;
+    private String mSuspendingPackage;
+    private int mNeutralButtonAction;
     private int mUserId;
     private PackageManager mPm;
     private Resources mSuspendingAppResources;
@@ -63,16 +76,15 @@
         return packageName;
     }
 
-    private Intent getMoreDetailsActivity(String suspendingPackage, String suspendedPackage,
-            int userId) {
+    private Intent getMoreDetailsActivity() {
         final Intent moreDetailsIntent = new Intent(Intent.ACTION_SHOW_SUSPENDED_APP_DETAILS)
-                .setPackage(suspendingPackage);
+                .setPackage(mSuspendingPackage);
         final String requiredPermission = Manifest.permission.SEND_SHOW_SUSPENDED_APP_DETAILS;
         final ResolveInfo resolvedInfo = mPm.resolveActivityAsUser(moreDetailsIntent,
-                MATCH_DIRECT_BOOT_UNAWARE | MATCH_DIRECT_BOOT_AWARE, userId);
+                MATCH_DIRECT_BOOT_UNAWARE | MATCH_DIRECT_BOOT_AWARE, mUserId);
         if (resolvedInfo != null && resolvedInfo.activityInfo != null
                 && requiredPermission.equals(resolvedInfo.activityInfo.permission)) {
-            moreDetailsIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, suspendedPackage)
+            moreDetailsIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, mSuspendedPackage)
                     .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
             return moreDetailsIntent;
         }
@@ -105,8 +117,8 @@
         return getString(R.string.app_suspended_title);
     }
 
-    private String resolveDialogMessage(String suspendingPkg, String suspendedPkg) {
-        final CharSequence suspendedAppLabel = getAppLabel(suspendedPkg);
+    private String resolveDialogMessage() {
+        final CharSequence suspendedAppLabel = getAppLabel(mSuspendedPackage);
         if (mSuppliedDialogInfo != null) {
             final int messageId = mSuppliedDialogInfo.getDialogMessageResId();
             final String message = mSuppliedDialogInfo.getDialogMessage();
@@ -122,10 +134,30 @@
             }
         }
         return getString(R.string.app_suspended_default_message, suspendedAppLabel,
-                getAppLabel(suspendingPkg));
+                getAppLabel(mSuspendingPackage));
     }
 
+    /**
+     * Returns a text to be displayed on the neutral button or {@code null} if the button should
+     * not be shown.
+     */
+    @Nullable
     private String resolveNeutralButtonText() {
+        final int defaultButtonTextId;
+        switch (mNeutralButtonAction) {
+            case BUTTON_ACTION_MORE_DETAILS:
+                if (mMoreDetailsIntent == null) {
+                    return null;
+                }
+                defaultButtonTextId = R.string.app_suspended_more_details;
+                break;
+            case BUTTON_ACTION_UNSUSPEND:
+                defaultButtonTextId = R.string.app_suspended_unsuspend_message;
+                break;
+            default:
+                Slog.w(TAG, "Unknown neutral button action: " + mNeutralButtonAction);
+                return null;
+        }
         final int buttonTextId = (mSuppliedDialogInfo != null)
                 ? mSuppliedDialogInfo.getNeutralButtonTextResId() : ID_NULL;
         if (buttonTextId != ID_NULL && mSuspendingAppResources != null) {
@@ -135,7 +167,7 @@
                 Slog.e(TAG, "Could not resolve string resource id " + buttonTextId);
             }
         }
-        return getString(R.string.app_suspended_more_details);
+        return getString(defaultButtonTextId);
     }
 
     @Override
@@ -152,27 +184,29 @@
             finish();
             return;
         }
-        final String suspendedPackage = intent.getStringExtra(EXTRA_SUSPENDED_PACKAGE);
-        final String suspendingPackage = intent.getStringExtra(EXTRA_SUSPENDING_PACKAGE);
+        mSuspendedPackage = intent.getStringExtra(EXTRA_SUSPENDED_PACKAGE);
+        mSuspendingPackage = intent.getStringExtra(EXTRA_SUSPENDING_PACKAGE);
         mSuppliedDialogInfo = intent.getParcelableExtra(EXTRA_DIALOG_INFO);
+        mOnUnsuspend = intent.getParcelableExtra(EXTRA_UNSUSPEND_INTENT);
         if (mSuppliedDialogInfo != null) {
             try {
-                mSuspendingAppResources = mPm.getResourcesForApplicationAsUser(suspendingPackage,
+                mSuspendingAppResources = mPm.getResourcesForApplicationAsUser(mSuspendingPackage,
                         mUserId);
             } catch (PackageManager.NameNotFoundException ne) {
-                Slog.e(TAG, "Could not find resources for " + suspendingPackage, ne);
+                Slog.e(TAG, "Could not find resources for " + mSuspendingPackage, ne);
             }
         }
+        mNeutralButtonAction = (mSuppliedDialogInfo != null)
+                ? mSuppliedDialogInfo.getNeutralButtonAction() : BUTTON_ACTION_MORE_DETAILS;
+        mMoreDetailsIntent = (mNeutralButtonAction == BUTTON_ACTION_MORE_DETAILS)
+                ? getMoreDetailsActivity() : null;
 
         final AlertController.AlertParams ap = mAlertParams;
         ap.mIcon = resolveIcon();
         ap.mTitle = resolveTitle();
-        ap.mMessage = resolveDialogMessage(suspendingPackage, suspendedPackage);
+        ap.mMessage = resolveDialogMessage();
         ap.mPositiveButtonText = getString(android.R.string.ok);
-        mMoreDetailsIntent = getMoreDetailsActivity(suspendingPackage, suspendedPackage, mUserId);
-        if (mMoreDetailsIntent != null) {
-            ap.mNeutralButtonText = resolveNeutralButtonText();
-        }
+        ap.mNeutralButtonText = resolveNeutralButtonText();
         ap.mPositiveButtonListener = ap.mNeutralButtonListener = this;
         setupAlert();
     }
@@ -181,21 +215,62 @@
     public void onClick(DialogInterface dialog, int which) {
         switch (which) {
             case AlertDialog.BUTTON_NEUTRAL:
-                startActivityAsUser(mMoreDetailsIntent, mOptions, UserHandle.of(mUserId));
-                Slog.i(TAG, "Started activity: " + mMoreDetailsIntent.getAction()
-                        + " in user " + mUserId);
+                switch (mNeutralButtonAction) {
+                    case BUTTON_ACTION_MORE_DETAILS:
+                        if (mMoreDetailsIntent != null) {
+                            startActivityAsUser(mMoreDetailsIntent, mOptions,
+                                    UserHandle.of(mUserId));
+                        } else {
+                            Slog.wtf(TAG, "Neutral button should not have existed!");
+                        }
+                        break;
+                    case BUTTON_ACTION_UNSUSPEND:
+                        final IPackageManager ipm = AppGlobals.getPackageManager();
+                        try {
+                            final String[] errored = ipm.setPackagesSuspendedAsUser(
+                                    new String[]{mSuspendedPackage}, false, null, null, null,
+                                    mSuspendingPackage, mUserId);
+                            if (ArrayUtils.contains(errored, mSuspendedPackage)) {
+                                Slog.e(TAG, "Could not unsuspend " + mSuspendedPackage);
+                                break;
+                            }
+                        } catch (RemoteException re) {
+                            Slog.e(TAG, "Can't talk to system process", re);
+                            break;
+                        }
+                        final Intent reportUnsuspend = new Intent()
+                                .setAction(Intent.ACTION_PACKAGE_UNSUSPENDED_MANUALLY)
+                                .putExtra(Intent.EXTRA_PACKAGE_NAME, mSuspendedPackage)
+                                .setPackage(mSuspendingPackage)
+                                .addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+                        sendBroadcastAsUser(reportUnsuspend, UserHandle.of(mUserId));
+
+                        if (mOnUnsuspend != null) {
+                            try {
+                                mOnUnsuspend.sendIntent(this, 0, null, null, null);
+                            } catch (IntentSender.SendIntentException e) {
+                                Slog.e(TAG, "Error while starting intent " + mOnUnsuspend, e);
+                            }
+                        }
+                        break;
+                    default:
+                        Slog.e(TAG, "Unexpected action on neutral button: " + mNeutralButtonAction);
+                        break;
+                }
                 break;
         }
         finish();
     }
 
     public static Intent createSuspendedAppInterceptIntent(String suspendedPackage,
-            String suspendingPackage, SuspendDialogInfo dialogInfo, Bundle options, int userId) {
+            String suspendingPackage, SuspendDialogInfo dialogInfo, Bundle options,
+            IntentSender onUnsuspend, int userId) {
         return new Intent()
                 .setClassName("android", SuspendedAppActivity.class.getName())
                 .putExtra(EXTRA_SUSPENDED_PACKAGE, suspendedPackage)
                 .putExtra(EXTRA_DIALOG_INFO, dialogInfo)
                 .putExtra(EXTRA_SUSPENDING_PACKAGE, suspendingPackage)
+                .putExtra(EXTRA_UNSUSPEND_INTENT, onUnsuspend)
                 .putExtra(EXTRA_ACTIVITY_OPTIONS, options)
                 .putExtra(Intent.EXTRA_USER_ID, userId)
                 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
diff --git a/core/java/com/android/internal/app/chooser/SelectableTargetInfo.java b/core/java/com/android/internal/app/chooser/SelectableTargetInfo.java
index 86a0d10..246a07d 100644
--- a/core/java/com/android/internal/app/chooser/SelectableTargetInfo.java
+++ b/core/java/com/android/internal/app/chooser/SelectableTargetInfo.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.app.chooser;
 
+import android.annotation.Nullable;
 import android.app.Activity;
 import android.content.ComponentName;
 import android.content.Context;
@@ -70,7 +71,8 @@
 
     public SelectableTargetInfo(Context context, DisplayResolveInfo sourceInfo,
             ChooserTarget chooserTarget,
-            float modifiedScore, SelectableTargetInfoCommunicator selectableTargetInfoComunicator) {
+            float modifiedScore, SelectableTargetInfoCommunicator selectableTargetInfoComunicator,
+            @Nullable ShortcutInfo shortcutInfo) {
         mContext = context;
         mSourceInfo = sourceInfo;
         mChooserTarget = chooserTarget;
@@ -91,7 +93,7 @@
             }
         }
         // TODO(b/121287224): do this in the background thread, and only for selected targets
-        mDisplayIcon = getChooserTargetIconDrawable(chooserTarget);
+        mDisplayIcon = getChooserTargetIconDrawable(chooserTarget, shortcutInfo);
 
         if (sourceInfo != null) {
             mBackupResolveInfo = null;
@@ -134,34 +136,18 @@
         return mIsSuspended;
     }
 
-    /**
-     * Since ShortcutInfos are returned by ShortcutManager, we can cache the shortcuts and skip
-     * the call to LauncherApps#getShortcuts(ShortcutQuery).
-     */
-    // TODO(121287224): Refactor code to apply the suggestion above
-    private Drawable getChooserTargetIconDrawable(ChooserTarget target) {
+    private Drawable getChooserTargetIconDrawable(ChooserTarget target,
+            @Nullable ShortcutInfo shortcutInfo) {
         Drawable directShareIcon = null;
 
         // First get the target drawable and associated activity info
         final Icon icon = target.getIcon();
         if (icon != null) {
             directShareIcon = icon.loadDrawable(mContext);
-        } else if (ChooserFlags.USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS) {
-            Bundle extras = target.getIntentExtras();
-            if (extras != null && extras.containsKey(Intent.EXTRA_SHORTCUT_ID)) {
-                CharSequence shortcutId = extras.getCharSequence(Intent.EXTRA_SHORTCUT_ID);
-                LauncherApps launcherApps = (LauncherApps) mContext.getSystemService(
-                        Context.LAUNCHER_APPS_SERVICE);
-                final LauncherApps.ShortcutQuery q = new LauncherApps.ShortcutQuery();
-                q.setPackage(target.getComponentName().getPackageName());
-                q.setShortcutIds(Arrays.asList(shortcutId.toString()));
-                q.setQueryFlags(LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC);
-                final List<ShortcutInfo> shortcuts =
-                        launcherApps.getShortcuts(q, mContext.getUser());
-                if (shortcuts != null && shortcuts.size() > 0) {
-                    directShareIcon = launcherApps.getShortcutIconDrawable(shortcuts.get(0), 0);
-                }
-            }
+        } else if (ChooserFlags.USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS && shortcutInfo != null) {
+            LauncherApps launcherApps = (LauncherApps) mContext.getSystemService(
+                    Context.LAUNCHER_APPS_SERVICE);
+            directShareIcon = launcherApps.getShortcutIconDrawable(shortcutInfo, 0);
         }
 
         if (directShareIcon == null) return null;
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index de64573..b232efc 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -364,6 +364,12 @@
      */
     public static final String NAV_BAR_HANDLE_FORCE_OPAQUE = "nav_bar_handle_force_opaque";
 
+    /**
+     * (boolean) Whether to force the Nav Bar handle to remain visible over the lockscreen.
+     */
+    public static final String NAV_BAR_HANDLE_SHOW_OVER_LOCKSCREEN =
+            "nav_bar_handle_show_over_lockscreen";
+
     private SystemUiDeviceConfigFlags() {
     }
 }
diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java
index 4bb012a..bbae027 100644
--- a/core/java/com/android/internal/net/VpnProfile.java
+++ b/core/java/com/android/internal/net/VpnProfile.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.net;
 
+import android.annotation.NonNull;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.net.ProxyInfo;
 import android.os.Build;
@@ -23,21 +24,34 @@
 import android.os.Parcelable;
 import android.text.TextUtils;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.net.InetAddress;
 import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
 
 /**
- * Parcel-like entity class for VPN profiles. To keep things simple, all
- * fields are package private. Methods are provided for serialization, so
- * storage can be implemented easily. Two rules are set for this class.
- * First, all fields must be kept non-null. Second, always make a copy
- * using clone() before modifying.
+ * Profile storage class for a platform VPN.
+ *
+ * <p>This class supports both the Legacy VPN, as well as application-configurable platform VPNs
+ * (such as IKEv2/IPsec).
+ *
+ * <p>This class is serialized and deserialized via the {@link #encode()} and {@link #decode()}
+ * functions for persistent storage in the Android Keystore. The encoding is entirely custom, but
+ * must be kept for backward compatibility for devices upgrading between Android versions.
  *
  * @hide
  */
-public class VpnProfile implements Cloneable, Parcelable {
+public final class VpnProfile implements Cloneable, Parcelable {
     private static final String TAG = "VpnProfile";
 
+    @VisibleForTesting static final String VALUE_DELIMITER = "\0";
+    @VisibleForTesting static final String LIST_DELIMITER = ",";
+
     // Match these constants with R.array.vpn_types.
     public static final int TYPE_PPTP = 0;
     public static final int TYPE_L2TP_IPSEC_PSK = 1;
@@ -45,39 +59,85 @@
     public static final int TYPE_IPSEC_XAUTH_PSK = 3;
     public static final int TYPE_IPSEC_XAUTH_RSA = 4;
     public static final int TYPE_IPSEC_HYBRID_RSA = 5;
-    public static final int TYPE_MAX = 5;
+    public static final int TYPE_IKEV2_IPSEC_USER_PASS = 6;
+    public static final int TYPE_IKEV2_IPSEC_PSK = 7;
+    public static final int TYPE_IKEV2_IPSEC_RSA = 8;
+    public static final int TYPE_MAX = 8;
 
     // Match these constants with R.array.vpn_proxy_settings.
     public static final int PROXY_NONE = 0;
     public static final int PROXY_MANUAL = 1;
 
+    private static final String ENCODED_NULL_PROXY_INFO = "\0\0\0\0";
+
     // Entity fields.
     @UnsupportedAppUsage
-    public final String key;           // -1
+    public final String key;                                   // -1
+
     @UnsupportedAppUsage
-    public String name = "";           // 0
+    public String name = "";                                   // 0
+
     @UnsupportedAppUsage
-    public int type = TYPE_PPTP;       // 1
+    public int type = TYPE_PPTP;                               // 1
+
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
-    public String server = "";         // 2
+    public String server = "";                                 // 2
+
     @UnsupportedAppUsage
-    public String username = "";       // 3
-    public String password = "";       // 4
-    public String dnsServers = "";     // 5
-    public String searchDomains = "";  // 6
-    public String routes = "";         // 7
-    public boolean mppe = true;        // 8
-    public String l2tpSecret = "";     // 9
-    public String ipsecIdentifier = "";// 10
-    public String ipsecSecret = "";    // 11
-    public String ipsecUserCert = "";  // 12
-    public String ipsecCaCert = "";    // 13
-    public String ipsecServerCert = "";// 14
-    public ProxyInfo proxy = null;     // 15~18
+    public String username = "";                               // 3
+    public String password = "";                               // 4
+    public String dnsServers = "";                             // 5
+    public String searchDomains = "";                          // 6
+    public String routes = "";                                 // 7
+    public boolean mppe = true;                                // 8
+    public String l2tpSecret = "";                             // 9
+    public String ipsecIdentifier = "";                        // 10
+
+    /**
+     * The RSA private key or pre-shared key used for authentication.
+     *
+     * <p>If areAuthParamsInline is {@code true}, this String will be either:
+     *
+     * <ul>
+     *   <li>If this is an IKEv2 RSA profile: a PKCS#8 encoded {@link java.security.PrivateKey}
+     *   <li>If this is an IKEv2 PSK profile: a string value representing the PSK.
+     * </ul>
+     */
+    public String ipsecSecret = "";                            // 11
+
+    /**
+     * The RSA certificate to be used for digital signature authentication.
+     *
+     * <p>If areAuthParamsInline is {@code true}, this String will be a pem-encoded {@link
+     * java.security.X509Certificate}
+     */
+    public String ipsecUserCert = "";                          // 12
+
+    /**
+     * The RSA certificate that should be used to verify the server's end/target certificate.
+     *
+     * <p>If areAuthParamsInline is {@code true}, this String will be a pem-encoded {@link
+     * java.security.X509Certificate}
+     */
+    public String ipsecCaCert = "";                            // 13
+    public String ipsecServerCert = "";                        // 14
+    public ProxyInfo proxy = null;                             // 15~18
+
+    /**
+     * The list of allowable algorithms.
+     *
+     * <p>This list is validated in the setter to ensure that encoding characters (list, value
+     * delimiters) are not present in the algorithm names. See {@link #validateAllowedAlgorithms()}
+     */
+    private List<String> mAllowedAlgorithms = new ArrayList<>(); // 19
+    public boolean isBypassable = false;                       // 20
+    public boolean isMetered = false;                          // 21
+    public int maxMtu = 1400;                                  // 22
+    public boolean areAuthParamsInline = false;                   // 23
 
     // Helper fields.
     @UnsupportedAppUsage
-    public boolean saveLogin = false;
+    public transient boolean saveLogin = false;
 
     public VpnProfile(String key) {
         this.key = key;
@@ -103,6 +163,34 @@
         ipsecServerCert = in.readString();
         saveLogin = in.readInt() != 0;
         proxy = in.readParcelable(null);
+        mAllowedAlgorithms = new ArrayList<>();
+        in.readList(mAllowedAlgorithms, null);
+        isBypassable = in.readBoolean();
+        isMetered = in.readBoolean();
+        maxMtu = in.readInt();
+        areAuthParamsInline = in.readBoolean();
+    }
+
+    /**
+     * Retrieves the list of allowed algorithms.
+     *
+     * <p>The contained elements are as listed in {@link IpSecAlgorithm}
+     */
+    public List<String> getAllowedAlgorithms() {
+        return Collections.unmodifiableList(mAllowedAlgorithms);
+    }
+
+    /**
+     * Validates and sets the list of algorithms that can be used for the IPsec transforms.
+     *
+     * @param allowedAlgorithms the list of allowable algorithms, as listed in {@link
+     *     IpSecAlgorithm}.
+     * @throws IllegalArgumentException if any delimiters are used in algorithm names. See {@link
+     *     #VALUE_DELIMITER} and {@link LIST_DELIMITER}.
+     */
+    public void setAllowedAlgorithms(List<String> allowedAlgorithms) {
+        validateAllowedAlgorithms(allowedAlgorithms);
+        mAllowedAlgorithms = allowedAlgorithms;
     }
 
     @Override
@@ -125,8 +213,18 @@
         out.writeString(ipsecServerCert);
         out.writeInt(saveLogin ? 1 : 0);
         out.writeParcelable(proxy, flags);
+        out.writeList(mAllowedAlgorithms);
+        out.writeBoolean(isBypassable);
+        out.writeBoolean(isMetered);
+        out.writeInt(maxMtu);
+        out.writeBoolean(areAuthParamsInline);
     }
 
+    /**
+     * Decodes a VpnProfile instance from the encoded byte array.
+     *
+     * <p>See {@link #encode()}
+     */
     @UnsupportedAppUsage
     public static VpnProfile decode(String key, byte[] value) {
         try {
@@ -134,9 +232,11 @@
                 return null;
             }
 
-            String[] values = new String(value, StandardCharsets.UTF_8).split("\0", -1);
-            // There can be 14 - 19 Bytes in values.length.
-            if (values.length < 14 || values.length > 19) {
+            String[] values = new String(value, StandardCharsets.UTF_8).split(VALUE_DELIMITER, -1);
+            // Acceptable numbers of values are:
+            // 14-19: Standard profile, with option for serverCert, proxy
+            // 24: Standard profile with serverCert, proxy and platform-VPN parameters.
+            if ((values.length < 14 || values.length > 19) && values.length != 24) {
                 return null;
             }
 
@@ -164,13 +264,23 @@
                 String port = (values.length > 16) ? values[16] : "";
                 String exclList = (values.length > 17) ? values[17] : "";
                 String pacFileUrl = (values.length > 18) ? values[18] : "";
-                if (pacFileUrl.isEmpty()) {
+                if (!host.isEmpty() || !port.isEmpty() || !exclList.isEmpty()) {
                     profile.proxy = new ProxyInfo(host, port.isEmpty() ?
                             0 : Integer.parseInt(port), exclList);
-                } else {
+                } else if (!pacFileUrl.isEmpty()) {
                     profile.proxy = new ProxyInfo(pacFileUrl);
                 }
-            } // else profle.proxy = null
+            } // else profile.proxy = null
+
+            // Either all must be present, or none must be.
+            if (values.length >= 24) {
+                profile.mAllowedAlgorithms = Arrays.asList(values[19].split(LIST_DELIMITER));
+                profile.isBypassable = Boolean.parseBoolean(values[20]);
+                profile.isMetered = Boolean.parseBoolean(values[21]);
+                profile.maxMtu = Integer.parseInt(values[22]);
+                profile.areAuthParamsInline = Boolean.parseBoolean(values[23]);
+            }
+
             profile.saveLogin = !profile.username.isEmpty() || !profile.password.isEmpty();
             return profile;
         } catch (Exception e) {
@@ -179,36 +289,52 @@
         return null;
     }
 
+    /**
+     * Encodes a VpnProfile instance to a byte array for storage.
+     *
+     * <p>See {@link #decode(String, byte[])}
+     */
     public byte[] encode() {
         StringBuilder builder = new StringBuilder(name);
-        builder.append('\0').append(type);
-        builder.append('\0').append(server);
-        builder.append('\0').append(saveLogin ? username : "");
-        builder.append('\0').append(saveLogin ? password : "");
-        builder.append('\0').append(dnsServers);
-        builder.append('\0').append(searchDomains);
-        builder.append('\0').append(routes);
-        builder.append('\0').append(mppe);
-        builder.append('\0').append(l2tpSecret);
-        builder.append('\0').append(ipsecIdentifier);
-        builder.append('\0').append(ipsecSecret);
-        builder.append('\0').append(ipsecUserCert);
-        builder.append('\0').append(ipsecCaCert);
-        builder.append('\0').append(ipsecServerCert);
+        builder.append(VALUE_DELIMITER).append(type);
+        builder.append(VALUE_DELIMITER).append(server);
+        builder.append(VALUE_DELIMITER).append(saveLogin ? username : "");
+        builder.append(VALUE_DELIMITER).append(saveLogin ? password : "");
+        builder.append(VALUE_DELIMITER).append(dnsServers);
+        builder.append(VALUE_DELIMITER).append(searchDomains);
+        builder.append(VALUE_DELIMITER).append(routes);
+        builder.append(VALUE_DELIMITER).append(mppe);
+        builder.append(VALUE_DELIMITER).append(l2tpSecret);
+        builder.append(VALUE_DELIMITER).append(ipsecIdentifier);
+        builder.append(VALUE_DELIMITER).append(ipsecSecret);
+        builder.append(VALUE_DELIMITER).append(ipsecUserCert);
+        builder.append(VALUE_DELIMITER).append(ipsecCaCert);
+        builder.append(VALUE_DELIMITER).append(ipsecServerCert);
         if (proxy != null) {
-            builder.append('\0').append(proxy.getHost() != null ? proxy.getHost() : "");
-            builder.append('\0').append(proxy.getPort());
-            builder.append('\0').append(proxy.getExclusionListAsString() != null ?
-                    proxy.getExclusionListAsString() : "");
-            builder.append('\0').append(proxy.getPacFileUrl().toString());
+            builder.append(VALUE_DELIMITER).append(proxy.getHost() != null ? proxy.getHost() : "");
+            builder.append(VALUE_DELIMITER).append(proxy.getPort());
+            builder.append(VALUE_DELIMITER)
+                    .append(
+                            proxy.getExclusionListAsString() != null
+                                    ? proxy.getExclusionListAsString()
+                                    : "");
+            builder.append(VALUE_DELIMITER).append(proxy.getPacFileUrl().toString());
+        } else {
+            builder.append(ENCODED_NULL_PROXY_INFO);
         }
+
+        builder.append(VALUE_DELIMITER).append(String.join(LIST_DELIMITER, mAllowedAlgorithms));
+        builder.append(VALUE_DELIMITER).append(isBypassable);
+        builder.append(VALUE_DELIMITER).append(isMetered);
+        builder.append(VALUE_DELIMITER).append(maxMtu);
+        builder.append(VALUE_DELIMITER).append(areAuthParamsInline);
+
         return builder.toString().getBytes(StandardCharsets.UTF_8);
     }
 
     /**
-     * Tests if profile is valid for lockdown, which requires IPv4 address for
-     * both server and DNS. Server hostnames would require using DNS before
-     * connection.
+     * Tests if profile is valid for lockdown, which requires IPv4 address for both server and DNS.
+     * Server hostnames would require using DNS before connection.
      */
     public boolean isValidLockdownProfile() {
         return isTypeValidForLockdown()
@@ -238,10 +364,7 @@
         return !TextUtils.isEmpty(dnsServers);
     }
 
-    /**
-     * Returns {@code true} if all DNS servers have numeric addresses,
-     * e.g. 8.8.8.8
-     */
+    /** Returns {@code true} if all DNS servers have numeric addresses, e.g. 8.8.8.8 */
     public boolean areDnsAddressesNumeric() {
         try {
             for (String dnsServer : dnsServers.split(" +")) {
@@ -253,6 +376,62 @@
         return true;
     }
 
+    /**
+     * Validates that the provided list of algorithms does not contain illegal characters.
+     *
+     * @param allowedAlgorithms The list to be validated
+     */
+    public static void validateAllowedAlgorithms(List<String> allowedAlgorithms) {
+        for (final String alg : allowedAlgorithms) {
+            if (alg.contains(VALUE_DELIMITER) || alg.contains(LIST_DELIMITER)) {
+                throw new IllegalArgumentException(
+                        "Algorithm contained illegal ('\0' or ',') character");
+            }
+        }
+    }
+
+    /** Generates a hashcode over the VpnProfile. */
+    @Override
+    public int hashCode() {
+        return Objects.hash(
+            key, type, server, username, password, dnsServers, searchDomains, routes, mppe,
+            l2tpSecret, ipsecIdentifier, ipsecSecret, ipsecUserCert, ipsecCaCert, ipsecServerCert,
+            proxy, mAllowedAlgorithms, isBypassable, isMetered, maxMtu, areAuthParamsInline);
+    }
+
+    /** Checks VPN profiles for interior equality. */
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof VpnProfile)) {
+            return false;
+        }
+
+        final VpnProfile other = (VpnProfile) obj;
+        return Objects.equals(key, other.key)
+                && Objects.equals(name, other.name)
+                && type == other.type
+                && Objects.equals(server, other.server)
+                && Objects.equals(username, other.username)
+                && Objects.equals(password, other.password)
+                && Objects.equals(dnsServers, other.dnsServers)
+                && Objects.equals(searchDomains, other.searchDomains)
+                && Objects.equals(routes, other.routes)
+                && mppe == other.mppe
+                && Objects.equals(l2tpSecret, other.l2tpSecret)
+                && Objects.equals(ipsecIdentifier, other.ipsecIdentifier)
+                && Objects.equals(ipsecSecret, other.ipsecSecret)
+                && Objects.equals(ipsecUserCert, other.ipsecUserCert)
+                && Objects.equals(ipsecCaCert, other.ipsecCaCert)
+                && Objects.equals(ipsecServerCert, other.ipsecServerCert)
+                && Objects.equals(proxy, other.proxy)
+                && Objects.equals(mAllowedAlgorithms, other.mAllowedAlgorithms)
+                && isBypassable == other.isBypassable
+                && isMetered == other.isMetered
+                && maxMtu == other.maxMtu
+                && areAuthParamsInline == other.areAuthParamsInline;
+    }
+
+    @NonNull
     public static final Creator<VpnProfile> CREATOR = new Creator<VpnProfile>() {
         @Override
         public VpnProfile createFromParcel(Parcel in) {
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index b3548b8..580c1f0 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -12644,7 +12644,6 @@
 
     /*@hide */
     public WifiBatteryStats getWifiBatteryStats() {
-        WifiBatteryStats s = new WifiBatteryStats();
         final int which = STATS_SINCE_CHARGED;
         final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
         final ControllerActivityCounter counter = getWifiControllerActivity();
@@ -12675,24 +12674,16 @@
         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
             timeSignalStrengthTimeMs[i] = getWifiSignalStrengthTime(i, rawRealTime, which) / 1000;
         }
-        s.setLoggingDurationMillis(computeBatteryRealtime(rawRealTime, which) / 1000);
-        s.setKernelActiveTimeMillis(getWifiActiveTime(rawRealTime, which) / 1000);
-        s.setNumPacketsTx(getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which));
-        s.setNumBytesTx(getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which));
-        s.setNumPacketsRx(getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which));
-        s.setNumBytesRx(getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which));
-        s.setSleepTimeMillis(sleepTimeMs);
-        s.setIdleTimeMillis(idleTimeMs);
-        s.setRxTimeMillis(rxTimeMs);
-        s.setTxTimeMillis(txTimeMs);
-        s.setScanTimeMillis(scanTimeMs);
-        s.setEnergyConsumedMaMillis(energyConsumedMaMs);
-        s.setNumAppScanRequest(numAppScanRequest);
-        s.setTimeInStateMillis(timeInStateMs);
-        s.setTimeInSupplicantStateMillis(timeInSupplStateMs);
-        s.setTimeInRxSignalStrengthLevelMillis(timeSignalStrengthTimeMs);
-        s.setMonitoredRailChargeConsumedMaMillis(monitoredRailChargeConsumedMaMs);
-        return s;
+        return new WifiBatteryStats(
+                computeBatteryRealtime(rawRealTime, which) / 1000,
+                getWifiActiveTime(rawRealTime, which) / 1000,
+                getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which),
+                getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which),
+                getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which),
+                getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which),
+                sleepTimeMs, scanTimeMs, idleTimeMs, rxTimeMs, txTimeMs, energyConsumedMaMs,
+                numAppScanRequest, timeInStateMs, timeSignalStrengthTimeMs, timeInSupplStateMs,
+                monitoredRailChargeConsumedMaMs);
     }
 
     /*@hide */
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index 13d0c5c..7adb27c 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -19,6 +19,8 @@
 import android.app.ActivityManager;
 import android.app.ActivityThread;
 import android.app.ApplicationErrorReport;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.type.DefaultMimeMapFactory;
 import android.os.Build;
@@ -34,6 +36,7 @@
 import com.android.internal.logging.AndroidConfig;
 import com.android.server.NetworkManagementSocketTagger;
 
+import dalvik.annotation.compat.VersionCodes;
 import dalvik.system.RuntimeHooks;
 import dalvik.system.ThreadPrioritySetter;
 import dalvik.system.VMRuntime;
@@ -64,8 +67,17 @@
 
     private static volatile boolean mCrashing = false;
 
+    /*
+     * Native heap allocations will now have a non-zero tag in the most significant byte.
+     * See {@linktourl https://source.android.com/devices/tech/debug/tagged-pointers}.
+     */
+    @ChangeId
+    @EnabledAfter(targetSdkVersion = VersionCodes.Q)
+    private static final long NATIVE_HEAP_POINTER_TAGGING = 135754954; // This is a bug id.
+
     private static final native void nativeFinishInit();
     private static final native void nativeSetExitWithoutCleanup(boolean exitWithoutCleanup);
+    private static native void nativeDisableHeapPointerTagging();
 
     private static int Clog_e(String tag, String msg, Throwable tr) {
         return Log.printlns(Log.LOG_ID_CRASH, Log.ERROR, tag, msg, tr);
@@ -398,6 +410,20 @@
         if (DEBUG) Slog.d(TAG, "Leaving RuntimeInit!");
     }
 
+    private static void maybeDisableHeapPointerTagging(long[] disabledCompatChanges) {
+        // Heap tagging needs to be disabled before any additional threads are created, but the
+        // AppCompat framework is not initialized enough at this point.
+        // Check if the change is enabled manually.
+        if (disabledCompatChanges != null) {
+            for (int i = 0; i < disabledCompatChanges.length; i++) {
+                if (disabledCompatChanges[i] == NATIVE_HEAP_POINTER_TAGGING) {
+                    nativeDisableHeapPointerTagging();
+                    break;
+                }
+            }
+        }
+    }
+
     protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
             String[] argv, ClassLoader classLoader) {
         // If the application calls System.exit(), terminate the process
@@ -410,6 +436,8 @@
         VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
         VMRuntime.getRuntime().setDisabledCompatChanges(disabledCompatChanges);
 
+        maybeDisableHeapPointerTagging(disabledCompatChanges);
+
         final Arguments args = new Arguments(argv);
 
         // The end of of the RuntimeInit event (see #zygoteInit).
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 8412b84..adb4036 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -95,8 +95,6 @@
 import android.view.Window;
 import android.view.WindowCallbacks;
 import android.view.WindowInsets;
-import android.view.WindowInsets.Side;
-import android.view.WindowInsets.Type;
 import android.view.WindowInsetsController;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
@@ -131,9 +129,9 @@
     private static final boolean SWEEP_OPEN_MENU = false;
 
     // The height of a window which has focus in DIP.
-    private final static int DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP = 20;
+    public static final int DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP = 20;
     // The height of a window which has not in DIP.
-    private final static int DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP = 5;
+    public static final int DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP = 5;
 
     private static final int SCRIM_LIGHT = 0xe6ffffff; // 90% white
 
@@ -1629,7 +1627,9 @@
 
         int opacity = PixelFormat.OPAQUE;
         final WindowConfiguration winConfig = getResources().getConfiguration().windowConfiguration;
-        if (winConfig.hasWindowShadow()) {
+        // If we draw shadows in the compositor we don't need to force the surface to be
+        // translucent.
+        if (winConfig.hasWindowShadow() && !mWindow.mRenderShadowsInCompositor) {
             // If the window has a shadow, it must be translucent.
             opacity = PixelFormat.TRANSLUCENT;
         } else{
@@ -2414,6 +2414,10 @@
     }
 
     private void updateElevation() {
+        // If rendering shadows in the compositor, don't set an elevation on the view
+        if (mWindow.mRenderShadowsInCompositor) {
+            return;
+        }
         float elevation = 0;
         final boolean wasAdjustedForStack = mElevationAdjustedForStack;
         // Do not use a shadow when we are in resizing mode (mBackdropFrameRenderer not null)
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 95558c3..f13a638 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -17,6 +17,7 @@
 package com.android.internal.policy;
 
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES;
+import static android.provider.Settings.Global.DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR;
 import static android.view.View.SYSTEM_UI_LAYOUT_FLAGS;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
@@ -134,6 +135,11 @@
 
     private final static String TAG = "PhoneWindow";
 
+    /* If true, shadows drawn around the window will be rendered by the system compositor. If
+     * false, shadows will be drawn by the client by setting an elevation on the root view and
+     * the contents will be inset by the shadow radius. */
+    public final boolean mRenderShadowsInCompositor;
+
     private static final boolean DEBUG = false;
 
     private final static int DEFAULT_BACKGROUND_FADE_DURATION_MS = 300;
@@ -327,6 +333,8 @@
     public PhoneWindow(Context context) {
         super(context);
         mLayoutInflater = LayoutInflater.from(context);
+        mRenderShadowsInCompositor = Settings.Global.getInt(context.getContentResolver(),
+                DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR, 0) != 0;
     }
 
     /**
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index aa0ac37..2106712 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -16,6 +16,7 @@
 
 package com.android.internal.statusbar;
 
+import android.app.ITransientNotificationCallback;
 import android.content.ComponentName;
 import android.graphics.Rect;
 import android.hardware.biometrics.IBiometricServiceReceiverInternal;
@@ -198,4 +199,25 @@
      * Dismiss the warning that the device is about to go to sleep due to user inactivity.
      */
     void dismissInattentiveSleepWarning(boolean animated);
+
+    /**
+     * Displays a text toast.
+     */
+    void showToast(String packageName, IBinder token, CharSequence text, IBinder windowToken,
+            int duration, @nullable ITransientNotificationCallback callback);
+
+    /**
+     * Cancels toast with token {@code token} in {@code packageName}.
+     */
+    void hideToast(String packageName, IBinder token);
+
+    /**
+     * Notifies SystemUI to start tracing.
+     */
+    void startTracing();
+
+    /**
+     * Notifies SystemUI to stop tracing.
+     */
+    void stopTracing();
 }
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index a9f7b84..5ce83c2 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -78,6 +78,7 @@
             in int notificationLocation, boolean modifiedBeforeSending);
     void onNotificationSettingsViewed(String key);
     void onNotificationBubbleChanged(String key, boolean isBubble);
+    void onBubbleNotificationSuppressionChanged(String key, boolean isSuppressed);
     void grantInlineReplyUriPermission(String key, in Uri uri, in UserHandle user, String packageName);
     void clearInlineReplyUriPermissions(String key);
 
@@ -123,4 +124,19 @@
      * Dismiss the warning that the device is about to go to sleep due to user inactivity.
      */
     void dismissInattentiveSleepWarning(boolean animated);
+
+    /**
+     * Notifies SystemUI to start tracing.
+     */
+    void startTracing();
+
+    /**
+     * Notifies SystemUI to stop tracing.
+     */
+    void stopTracing();
+
+    /**
+     * Returns whether SystemUI tracing is enabled.
+     */
+    boolean isTracing();
 }
diff --git a/core/java/com/android/internal/util/ConnectivityUtil.java b/core/java/com/android/internal/util/LocationPermissionChecker.java
similarity index 71%
rename from core/java/com/android/internal/util/ConnectivityUtil.java
rename to core/java/com/android/internal/util/LocationPermissionChecker.java
index 799352b..2db0e99 100644
--- a/core/java/com/android/internal/util/ConnectivityUtil.java
+++ b/core/java/com/android/internal/util/LocationPermissionChecker.java
@@ -33,28 +33,59 @@
 
 
 /**
- * Utility methods for common functionality using by different networks.
+ * The methods used for location permission and location mode checking.
  *
  * @hide
  */
-public class ConnectivityUtil {
+public class LocationPermissionChecker {
 
-    private static final String TAG = "ConnectivityUtil";
+    private static final String TAG = "LocationPermissionChecker";
 
     private final Context mContext;
-    private final AppOpsManager mAppOps;
+    private final AppOpsManager mAppOpsManager;
     private final UserManager mUserManager;
+    private final LocationManager mLocationManager;
 
-    public ConnectivityUtil(Context context) {
+    public LocationPermissionChecker(Context context) {
         mContext = context;
-        mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
+        mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        mLocationManager =
+            (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
     }
 
     /**
-     * API to determine if the caller has fine/coarse location permission (depending on
-     * config/targetSDK level) and the location mode is enabled for the user. SecurityException is
-     * thrown if the caller has no permission or the location mode is disabled.
+     * Check location permission granted by the caller.
+     *
+     * This API check if the location mode enabled for the caller and the caller has
+     * ACCESS_COARSE_LOCATION permission is targetSDK<29, otherwise, has ACCESS_FINE_LOCATION.
+     *
+     * @param pkgName package name of the application requesting access
+     * @param featureId The feature in the package
+     * @param uid The uid of the package
+     * @param message A message describing why the permission was checked. Only needed if this is
+     *                not inside of a two-way binder call from the data receiver
+     *
+     * @return {@code true} returns if the caller has location permission and the location mode is
+     *         enabled.
+     */
+    public boolean checkLocationPermission(String pkgName, @Nullable String featureId,
+            int uid, @Nullable String message) {
+        try {
+            enforceLocationPermission(pkgName, featureId, uid, message);
+            return true;
+        } catch (SecurityException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Enforce the caller has location permission.
+     *
+     * This API determines if the location mode enabled for the caller and the caller has
+     * ACCESS_COARSE_LOCATION permission is targetSDK<29, otherwise, has ACCESS_FINE_LOCATION.
+     * SecurityException is thrown if the caller has no permission or the location mode is disabled.
+     *
      * @param pkgName package name of the application requesting access
      * @param featureId The feature in the package
      * @param uid The uid of the package
@@ -62,31 +93,21 @@
      *                not inside of a two-way binder call from the data receiver
      */
     public void enforceLocationPermission(String pkgName, @Nullable String featureId, int uid,
-            @Nullable String message)
-            throws SecurityException {
+            @Nullable String message) throws SecurityException {
+
         checkPackage(uid, pkgName);
 
         // Location mode must be enabled
         if (!isLocationModeEnabled()) {
-            // Location mode is disabled, scan results cannot be returned
             throw new SecurityException("Location mode is disabled for the device");
         }
 
         // LocationAccess by App: caller must have Coarse/Fine Location permission to have access to
         // location information.
-        boolean canAppPackageUseLocation = checkCallersLocationPermission(pkgName, featureId,
-                uid, /* coarseForTargetSdkLessThanQ */ true, message);
-
-        // If neither caller or app has location access, there is no need to check
-        // any other permissions. Deny access to scan results.
-        if (!canAppPackageUseLocation) {
+        if (!checkCallersLocationPermission(pkgName, featureId,
+                uid, /* coarseForTargetSdkLessThanQ */ true, message)) {
             throw new SecurityException("UID " + uid + " has no location permission");
         }
-        // If the User or profile is current, permission is granted
-        // Otherwise, uid must have INTERACT_ACROSS_USERS_FULL permission.
-        if (!isCurrentProfile(uid) && !checkInteractAcrossUsersFull(uid)) {
-            throw new SecurityException("UID " + uid + " profile not permitted");
-        }
     }
 
     /**
@@ -104,6 +125,7 @@
      */
     public boolean checkCallersLocationPermission(String pkgName, @Nullable String featureId,
             int uid, boolean coarseForTargetSdkLessThanQ, @Nullable String message) {
+
         boolean isTargetSdkLessThanQ = isTargetSdkLessThan(pkgName, Build.VERSION_CODES.Q, uid);
 
         String permissionType = Manifest.permission.ACCESS_FINE_LOCATION;
@@ -111,8 +133,7 @@
             // Having FINE permission implies having COARSE permission (but not the reverse)
             permissionType = Manifest.permission.ACCESS_COARSE_LOCATION;
         }
-        if (getUidPermission(permissionType, uid)
-                == PackageManager.PERMISSION_DENIED) {
+        if (getUidPermission(permissionType, uid) == PackageManager.PERMISSION_DENIED) {
             return false;
         }
 
@@ -134,10 +155,8 @@
      * Retrieves a handle to LocationManager (if not already done) and check if location is enabled.
      */
     public boolean isLocationModeEnabled() {
-        LocationManager locationManager =
-                (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
         try {
-            return locationManager.isLocationEnabledForUser(UserHandle.of(
+            return mLocationManager.isLocationEnabledForUser(UserHandle.of(
                     getCurrentUser()));
         } catch (Exception e) {
             Log.e(TAG, "Failure to get location mode via API, falling back to settings", e);
@@ -166,27 +185,16 @@
 
     private boolean noteAppOpAllowed(String op, String pkgName, @Nullable String featureId,
             int uid, @Nullable String message) {
-        return mAppOps.noteOp(op, uid, pkgName, featureId, message) == AppOpsManager.MODE_ALLOWED;
+        return mAppOpsManager.noteOp(op, uid, pkgName, featureId, message)
+                == AppOpsManager.MODE_ALLOWED;
     }
 
-    private void checkPackage(int uid, String pkgName) throws SecurityException {
+    private void checkPackage(int uid, String pkgName)
+            throws SecurityException {
         if (pkgName == null) {
             throw new SecurityException("Checking UID " + uid + " but Package Name is Null");
         }
-        mAppOps.checkPackage(uid, pkgName);
-    }
-
-    private boolean isCurrentProfile(int uid) {
-        UserHandle currentUser = UserHandle.of(getCurrentUser());
-        UserHandle callingUser = UserHandle.getUserHandleForUid(uid);
-        return currentUser.equals(callingUser)
-                || mUserManager.isSameProfileGroup(currentUser, callingUser);
-    }
-
-    private boolean checkInteractAcrossUsersFull(int uid) {
-        return getUidPermission(
-                android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, uid)
-                == PackageManager.PERMISSION_GRANTED;
+        mAppOpsManager.checkPackage(uid, pkgName);
     }
 
     @VisibleForTesting
diff --git a/core/java/com/android/internal/util/ScreenshotHelper.java b/core/java/com/android/internal/util/ScreenshotHelper.java
index 8cad5a0..7cff90b 100644
--- a/core/java/com/android/internal/util/ScreenshotHelper.java
+++ b/core/java/com/android/internal/util/ScreenshotHelper.java
@@ -6,7 +6,11 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.graphics.Bitmap;
+import android.graphics.Insets;
+import android.graphics.Rect;
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
@@ -14,6 +18,7 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.Log;
+import android.view.WindowManager;
 
 import java.util.function.Consumer;
 
@@ -38,9 +43,9 @@
      * is recommended for general use.
      *
      * @param screenshotType     The type of screenshot, for example either
-     *                           {@link android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN}
+     *                           {@link android.view.WindowManager#TAKE_SCREENSHOT_FULLSCREEN}
      *                           or
-     *                           {@link android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION}
+     *                           {@link android.view.WindowManager#TAKE_SCREENSHOT_SELECTED_REGION}
      * @param hasStatus          {@code true} if the status bar is currently showing. {@code false}
      *                           if
      *                           not.
@@ -65,9 +70,9 @@
      * is recommended for general use.
      *
      * @param screenshotType     The type of screenshot, for example either
-     *                           {@link android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN}
+     *                           {@link android.view.WindowManager#TAKE_SCREENSHOT_FULLSCREEN}
      *                           or
-     *                           {@link android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION}
+     *                           {@link android.view.WindowManager#TAKE_SCREENSHOT_SELECTED_REGION}
      * @param hasStatus          {@code true} if the status bar is currently showing. {@code false}
      *                           if
      *                           not.
@@ -84,6 +89,40 @@
     public void takeScreenshot(final int screenshotType, final boolean hasStatus,
             final boolean hasNav, long timeoutMs, @NonNull Handler handler,
             @Nullable Consumer<Uri> completionConsumer) {
+        takeScreenshot(screenshotType, hasStatus, hasNav, timeoutMs, handler, null,
+                completionConsumer
+        );
+    }
+
+    /**
+     * Request that provided image be handled as if it was a screenshot.
+     *
+     * @param screenshot         The bitmap to treat as the screen shot.
+     * @param boundsInScreen     The bounds in screen coordinates that the bitmap orginated from.
+     * @param insets             The insets that the image was shown with, inside the screenbounds.
+     * @param taskId             The taskId of the task that the screen shot was taken of.
+     * @param handler            A handler used in case the screenshot times out
+     * @param completionConsumer Consumes `false` if a screenshot was not taken, and `true` if the
+     *                           screenshot was taken.
+     */
+    public void provideScreenshot(@NonNull Bitmap screenshot, @NonNull Rect boundsInScreen,
+            @NonNull Insets insets, int taskId, @NonNull Handler handler,
+            @Nullable Consumer<Uri> completionConsumer) {
+        Bundle imageBundle = new Bundle();
+        imageBundle.putParcelable(WindowManager.PARCEL_KEY_SCREENSHOT_BITMAP, screenshot);
+        imageBundle.putParcelable(WindowManager.PARCEL_KEY_SCREENSHOT_BOUNDS, boundsInScreen);
+        imageBundle.putParcelable(WindowManager.PARCEL_KEY_SCREENSHOT_INSETS, insets);
+        imageBundle.putInt(WindowManager.PARCEL_KEY_SCREENSHOT_TASK_ID, taskId);
+
+        takeScreenshot(
+                WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE,
+                false, false, // ignored when image bundle is set
+                SCREENSHOT_TIMEOUT_MS, handler, imageBundle, completionConsumer);
+    }
+
+    private void takeScreenshot(final int screenshotType, final boolean hasStatus,
+            final boolean hasNav, long timeoutMs, @NonNull Handler handler,
+            @Nullable Bundle providedImage, @Nullable Consumer<Uri> completionConsumer) {
         synchronized (mScreenshotLock) {
             if (mScreenshotConnection != null) {
                 return;
@@ -139,6 +178,10 @@
                         msg.arg1 = hasStatus ? 1 : 0;
                         msg.arg2 = hasNav ? 1 : 0;
 
+                        if (screenshotType == WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE) {
+                            msg.setData(providedImage);
+                        }
+
                         try {
                             messenger.send(msg);
                         } catch (RemoteException e) {
diff --git a/core/java/com/android/internal/util/TraceBuffer.java b/core/java/com/android/internal/util/TraceBuffer.java
new file mode 100644
index 0000000..fe8a59e
--- /dev/null
+++ b/core/java/com/android/internal/util/TraceBuffer.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+import android.util.proto.ProtoOutputStream;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayDeque;
+import java.util.Arrays;
+import java.util.Queue;
+import java.util.function.Consumer;
+
+/**
+ * Buffer used for tracing and logging.
+ *
+ * @param <P> The class type of the proto provider
+ * @param <S> The proto class type of the encapsulating proto
+ * @param <T> The proto class type of the individual entry protos in the buffer
+ *
+ * {@hide}
+ */
+public class TraceBuffer<P, S extends P, T extends P> {
+    private final Object mBufferLock = new Object();
+
+    private final ProtoProvider<P, S, T> mProtoProvider;
+    private final Queue<T> mBuffer = new ArrayDeque<>();
+    private final Consumer mProtoDequeuedCallback;
+    private int mBufferUsedSize;
+    private int mBufferCapacity;
+
+    /**
+     * An interface to get protos from different sources (ie. fw-proto/proto-lite/nano-proto) for
+     * the trace buffer.
+     *
+     * @param <P> The class type of the proto provider
+     * @param <S> The proto class type of the encapsulating proto
+     * @param <T> The proto class type of the individual protos in the buffer
+     */
+    public interface ProtoProvider<P, S extends P, T extends P> {
+        /**
+         * @return The size of the given proto.
+         */
+        int getItemSize(P proto);
+
+        /**
+         * @return The bytes of the given proto.
+         */
+        byte[] getBytes(P proto);
+
+        /**
+         * Writes the given encapsulating proto and buffer of protos to the given output
+         * stream.
+         */
+        void write(S encapsulatingProto, Queue<T> buffer, OutputStream os) throws IOException;
+    }
+
+    /**
+     * An implementation of the ProtoProvider that uses only the framework ProtoOutputStream.
+     */
+    private static class ProtoOutputStreamProvider implements
+            ProtoProvider<ProtoOutputStream, ProtoOutputStream, ProtoOutputStream> {
+        @Override
+        public int getItemSize(ProtoOutputStream proto) {
+            return proto.getRawSize();
+        }
+
+        @Override
+        public byte[] getBytes(ProtoOutputStream proto) {
+            return proto.getBytes();
+        }
+
+        @Override
+        public void write(ProtoOutputStream encapsulatingProto, Queue<ProtoOutputStream> buffer,
+                OutputStream os) throws IOException {
+            os.write(encapsulatingProto.getBytes());
+            for (ProtoOutputStream protoOutputStream : buffer) {
+                byte[] protoBytes = protoOutputStream.getBytes();
+                os.write(protoBytes);
+            }
+        }
+    }
+
+    public TraceBuffer(int bufferCapacity) {
+        this(bufferCapacity, new ProtoOutputStreamProvider(), null);
+    }
+
+    public TraceBuffer(int bufferCapacity, ProtoProvider protoProvider,
+            Consumer<T> protoDequeuedCallback) {
+        mBufferCapacity = bufferCapacity;
+        mProtoProvider = protoProvider;
+        mProtoDequeuedCallback = protoDequeuedCallback;
+        resetBuffer();
+    }
+
+    public int getAvailableSpace() {
+        return mBufferCapacity - mBufferUsedSize;
+    }
+
+    /**
+     * Returns buffer size.
+     */
+    public int size() {
+        return mBuffer.size();
+    }
+
+    public void setCapacity(int capacity) {
+        mBufferCapacity = capacity;
+    }
+
+    /**
+     * Inserts the specified element into this buffer.
+     *
+     * @param proto the element to add
+     * @throws IllegalStateException if the element cannot be added because it is larger
+     *                               than the buffer size.
+     */
+    public void add(T proto) {
+        int protoLength = mProtoProvider.getItemSize(proto);
+        if (protoLength > mBufferCapacity) {
+            throw new IllegalStateException("Trace object too large for the buffer. Buffer size:"
+                    + mBufferCapacity + " Object size: " + protoLength);
+        }
+        synchronized (mBufferLock) {
+            discardOldest(protoLength);
+            mBuffer.add(proto);
+            mBufferUsedSize += protoLength;
+            mBufferLock.notify();
+        }
+    }
+
+    @VisibleForTesting
+    public boolean contains(byte[] other) {
+        return mBuffer.stream()
+                .anyMatch(p -> Arrays.equals(mProtoProvider.getBytes(p), other));
+    }
+
+    /**
+     * Writes the trace buffer to disk inside the encapsulatingProto.
+     */
+    public void writeTraceToFile(File traceFile, S encapsulatingProto)
+            throws IOException {
+        synchronized (mBufferLock) {
+            traceFile.delete();
+            try (OutputStream os = new FileOutputStream(traceFile)) {
+                traceFile.setReadable(true /* readable */, false /* ownerOnly */);
+                mProtoProvider.write(encapsulatingProto, mBuffer, os);
+                os.flush();
+            }
+        }
+    }
+
+    /**
+     * Checks if the element can be added to the buffer. The element is already certain to be
+     * smaller than the overall buffer size.
+     *
+     * @param protoLength byte array representation of the Proto object to add
+     */
+    private void discardOldest(int protoLength) {
+        long availableSpace = getAvailableSpace();
+
+        while (availableSpace < protoLength) {
+
+            P item = mBuffer.poll();
+            if (item == null) {
+                throw new IllegalStateException("No element to discard from buffer");
+            }
+            mBufferUsedSize -= mProtoProvider.getItemSize(item);
+            availableSpace = getAvailableSpace();
+
+            if (mProtoDequeuedCallback != null) {
+                mProtoDequeuedCallback.accept(item);
+            }
+        }
+    }
+
+    /**
+     * Removes all elements form the buffer
+     */
+    public void resetBuffer() {
+        synchronized (mBufferLock) {
+            if (mProtoDequeuedCallback != null) {
+                for (T item : mBuffer) {
+                    mProtoDequeuedCallback.accept(item);
+                }
+            }
+            mBuffer.clear();
+            mBufferUsedSize = 0;
+        }
+    }
+
+    @VisibleForTesting
+    public int getBufferSize() {
+        return mBufferUsedSize;
+    }
+
+    /**
+     * Returns the buffer status in human-readable form.
+     */
+    public String getStatus() {
+        synchronized (mBufferLock) {
+            return "Buffer size: " + mBufferCapacity + " bytes" + "\n"
+                    + "Buffer usage: " + mBufferUsedSize + " bytes" + "\n"
+                    + "Elements in the buffer: " + mBuffer.size();
+        }
+    }
+}
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index c41b19e..9783b65 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -46,6 +46,7 @@
 #include <signal.h>
 #include <dirent.h>
 #include <assert.h>
+#include <bionic/malloc.h>
 
 #include <string>
 #include <vector>
@@ -237,6 +238,14 @@
     gCurRuntime->setExitWithoutCleanup(exitWithoutCleanup);
 }
 
+static void com_android_internal_os_RuntimeInit_nativeDisableHeapPointerTagging(
+        JNIEnv* env, jobject clazz) {
+    HeapTaggingLevel tag_level = M_HEAP_TAGGING_LEVEL_NONE;
+    if (!android_mallopt(M_SET_HEAP_TAGGING_LEVEL, &tag_level, sizeof(tag_level))) {
+        ALOGE("ERROR: could not disable heap pointer tagging\n");
+    }
+}
+
 /*
  * JNI registration.
  */
@@ -244,10 +253,12 @@
 int register_com_android_internal_os_RuntimeInit(JNIEnv* env)
 {
     const JNINativeMethod methods[] = {
-        { "nativeFinishInit", "()V",
-            (void*) com_android_internal_os_RuntimeInit_nativeFinishInit },
-        { "nativeSetExitWithoutCleanup", "(Z)V",
-            (void*) com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup },
+            {"nativeFinishInit", "()V",
+             (void*)com_android_internal_os_RuntimeInit_nativeFinishInit},
+            {"nativeSetExitWithoutCleanup", "(Z)V",
+             (void*)com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup},
+            {"nativeDisableHeapPointerTagging", "()V",
+             (void*)com_android_internal_os_RuntimeInit_nativeDisableHeapPointerTagging},
     };
     return jniRegisterNativeMethods(env, "com/android/internal/os/RuntimeInit",
         methods, NELEM(methods));
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 32a7cf3..30e914d 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -34,7 +34,6 @@
 #include <string>
 
 #define DEBUG_PARCEL 0
-#define ASHMEM_BITMAP_MIN_SIZE (128 * (1 << 10))
 
 static jclass   gBitmap_class;
 static jfieldID gBitmap_nativePtr;
@@ -475,8 +474,7 @@
     }
 
     auto fm = static_cast<Bitmap::JavaCompressFormat>(format);
-    auto result = bitmap->bitmap().compress(fm, quality, strm.get());
-    return result == Bitmap::CompressResult::Success ? JNI_TRUE : JNI_FALSE;
+    return bitmap->bitmap().compress(fm, quality, strm.get()) ? JNI_TRUE : JNI_FALSE;
 }
 
 static inline void bitmapErase(SkBitmap bitmap, const SkColor4f& color,
@@ -588,7 +586,6 @@
 
     android::Parcel* p = android::parcelForJavaObject(env, parcel);
 
-    const bool        isMutable = p->readInt32() != 0;
     const SkColorType colorType = (SkColorType)p->readInt32();
     const SkAlphaType alphaType = (SkAlphaType)p->readInt32();
     const uint32_t    colorSpaceSize = p->readUint32();
@@ -637,11 +634,10 @@
 
     // Map the bitmap in place from the ashmem region if possible otherwise copy.
     sk_sp<Bitmap> nativeBitmap;
-    if (blob.fd() >= 0 && (blob.isMutable() || !isMutable) && (size >= ASHMEM_BITMAP_MIN_SIZE)) {
+    if (blob.fd() >= 0 && !blob.isMutable()) {
 #if DEBUG_PARCEL
-        ALOGD("Bitmap.createFromParcel: mapped contents of %s bitmap from %s blob "
+        ALOGD("Bitmap.createFromParcel: mapped contents of bitmap from %s blob "
                 "(fds %s)",
-                isMutable ? "mutable" : "immutable",
                 blob.isMutable() ? "mutable" : "immutable",
                 p->allowFds() ? "allowed" : "forbidden");
 #endif
@@ -658,7 +654,7 @@
         // Map the pixels in place and take ownership of the ashmem region. We must also respect the
         // rowBytes value already set on the bitmap instead of attempting to compute our own.
         nativeBitmap = Bitmap::createFrom(bitmap->info(), bitmap->rowBytes(), dupFd,
-                                          const_cast<void*>(blob.data()), size, !isMutable);
+                                          const_cast<void*>(blob.data()), size, true);
         if (!nativeBitmap) {
             close(dupFd);
             blob.release();
@@ -696,7 +692,7 @@
     }
 
     return createBitmap(env, nativeBitmap.release(),
-            getPremulBitmapCreateFlags(isMutable), NULL, NULL, density);
+            getPremulBitmapCreateFlags(false), NULL, NULL, density);
 #else
     doThrowRE(env, "Cannot use parcels outside of Android");
     return NULL;
@@ -704,9 +700,7 @@
 }
 
 static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
-                                     jlong bitmapHandle,
-                                     jboolean isMutable, jint density,
-                                     jobject parcel) {
+                                     jlong bitmapHandle, jint density, jobject parcel) {
 #ifdef __ANDROID__ // Layoutlib does not support parcel
     if (parcel == NULL) {
         SkDebugf("------- writeToParcel null parcel\n");
@@ -719,7 +713,6 @@
     auto bitmapWrapper = reinterpret_cast<BitmapWrapper*>(bitmapHandle);
     bitmapWrapper->getSkBitmap(&bitmap);
 
-    p->writeInt32(isMutable);
     p->writeInt32(bitmap.colorType());
     p->writeInt32(bitmap.alphaType());
     SkColorSpace* colorSpace = bitmap.colorSpace();
@@ -746,7 +739,7 @@
     // Transfer the underlying ashmem region if we have one and it's immutable.
     android::status_t status;
     int fd = bitmapWrapper->bitmap().getAshmemFd();
-    if (fd >= 0 && !isMutable && p->allowFds()) {
+    if (fd >= 0 && p->allowFds()) {
 #if DEBUG_PARCEL
         ALOGD("Bitmap.writeToParcel: transferring immutable bitmap's ashmem fd as "
                 "immutable blob (fds %s)",
@@ -762,17 +755,14 @@
     }
 
     // Copy the bitmap to a new blob.
-    bool mutableCopy = isMutable;
 #if DEBUG_PARCEL
-    ALOGD("Bitmap.writeToParcel: copying %s bitmap into new %s blob (fds %s)",
-            isMutable ? "mutable" : "immutable",
-            mutableCopy ? "mutable" : "immutable",
+    ALOGD("Bitmap.writeToParcel: copying bitmap into new blob (fds %s)",
             p->allowFds() ? "allowed" : "forbidden");
 #endif
 
     size_t size = bitmap.computeByteSize();
     android::Parcel::WritableBlob blob;
-    status = p->writeBlob(size, mutableCopy, &blob);
+    status = p->writeBlob(size, false, &blob);
     if (status) {
         doThrowRE(env, "Could not copy bitmap to parcel blob.");
         return JNI_FALSE;
@@ -1110,7 +1100,7 @@
     {   "nativeCreateFromParcel",
         "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",
         (void*)Bitmap_createFromParcel },
-    {   "nativeWriteToParcel",      "(JZILandroid/os/Parcel;)Z",
+    {   "nativeWriteToParcel",      "(JILandroid/os/Parcel;)Z",
         (void*)Bitmap_writeToParcel },
     {   "nativeExtractAlpha",       "(JJ[I)Landroid/graphics/Bitmap;",
         (void*)Bitmap_extractAlpha },
diff --git a/core/jni/android/graphics/apex/android_bitmap.cpp b/core/jni/android/graphics/apex/android_bitmap.cpp
index 6628529..decd190 100644
--- a/core/jni/android/graphics/apex/android_bitmap.cpp
+++ b/core/jni/android/graphics/apex/android_bitmap.cpp
@@ -290,14 +290,8 @@
     }
 
     CompressWriter stream(userContext, fn);
-    switch (Bitmap::compress(bitmap, format, quality, &stream)) {
-        case Bitmap::CompressResult::Success:
-            return ANDROID_BITMAP_RESULT_SUCCESS;
-        case Bitmap::CompressResult::AllocationFailed:
-            return ANDROID_BITMAP_RESULT_ALLOCATION_FAILED;
-        case Bitmap::CompressResult::Error:
-            return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
-    }
+    return Bitmap::compress(bitmap, format, quality, &stream) ? ANDROID_BITMAP_RESULT_SUCCESS
+                                                              : ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
 }
 
 AHardwareBuffer* ABitmap_getHardwareBuffer(ABitmap* bitmapHandle) {
diff --git a/core/jni/android_content_res_ApkAssets.cpp b/core/jni/android_content_res_ApkAssets.cpp
index 5d13cf8..b55dc68 100644
--- a/core/jni/android_content_res_ApkAssets.cpp
+++ b/core/jni/android_content_res_ApkAssets.cpp
@@ -221,7 +221,7 @@
     return nullptr;
   }
 
-  jstring actor_string = env->NewStringUTF(actor->first.c_str());
+  jstring actor_string = env->NewStringUTF(actor->second.c_str());
   if (env->ExceptionCheck() || actor_string == nullptr) {
     jniThrowException(env, "java/io/IOException", "Error reading overlayable from APK");
     return 0;
diff --git a/core/jni/android_media_AudioEffectDescriptor.cpp b/core/jni/android_media_AudioEffectDescriptor.cpp
index 5175a05..37d8114 100644
--- a/core/jni/android_media_AudioEffectDescriptor.cpp
+++ b/core/jni/android_media_AudioEffectDescriptor.cpp
@@ -39,17 +39,21 @@
     jstring jImplementor;
     char str[EFFECT_STRING_LEN_MAX];
 
-    if ((nDescriptor->flags & EFFECT_FLAG_TYPE_MASK)
-        == EFFECT_FLAG_TYPE_AUXILIARY) {
-        jConnect = env->NewStringUTF("Auxiliary");
-    } else if ((nDescriptor->flags & EFFECT_FLAG_TYPE_MASK)
-        == EFFECT_FLAG_TYPE_INSERT) {
-        jConnect = env->NewStringUTF("Insert");
-    } else if ((nDescriptor->flags & EFFECT_FLAG_TYPE_MASK)
-        == EFFECT_FLAG_TYPE_PRE_PROC) {
-        jConnect = env->NewStringUTF("Pre Processing");
-    } else {
-        return (jint) AUDIO_JAVA_BAD_VALUE;
+    switch (nDescriptor->flags & EFFECT_FLAG_TYPE_MASK) {
+        case EFFECT_FLAG_TYPE_AUXILIARY:
+            jConnect = env->NewStringUTF("Auxiliary");
+            break;
+        case EFFECT_FLAG_TYPE_INSERT:
+            jConnect = env->NewStringUTF("Insert");
+            break;
+        case EFFECT_FLAG_TYPE_PRE_PROC:
+            jConnect = env->NewStringUTF("Pre Processing");
+            break;
+        case EFFECT_FLAG_TYPE_POST_PROC:
+            jConnect = env->NewStringUTF("Post Processing");
+            break;
+        default:
+            return (jint)AUDIO_JAVA_BAD_VALUE;
     }
 
     AudioEffect::guidToString(&nDescriptor->type, str, EFFECT_STRING_LEN_MAX);
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index fb8e633..e77c25e 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -537,9 +537,10 @@
         LOGDEATH("Receiving binderDied() on JavaDeathRecipient %p\n", this);
         if (mObject != NULL) {
             JNIEnv* env = javavm_to_jnienv(mVM);
-            jobject jBinderProxy = javaObjectForIBinder(env, who.promote());
+            ScopedLocalRef<jobject> jBinderProxy(env, javaObjectForIBinder(env, who.promote()));
             env->CallStaticVoidMethod(gBinderProxyOffsets.mClass,
-                                      gBinderProxyOffsets.mSendDeathNotice, mObject, jBinderProxy);
+                                      gBinderProxyOffsets.mSendDeathNotice, mObject,
+                                      jBinderProxy.get());
             if (env->ExceptionCheck()) {
                 jthrowable excep = env->ExceptionOccurred();
                 report_exception(env, excep,
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 89dbca8..0eb364d 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -330,6 +330,22 @@
     closedir(d);
 }
 
+void android_os_Process_setProcessFrozen(
+        JNIEnv *env, jobject clazz, jint pid, jint uid, jboolean freeze)
+{
+    bool success = true;
+
+    if (freeze) {
+        success = SetProcessProfiles(uid, pid, {"Frozen"});
+    } else {
+        success = SetProcessProfiles(uid, pid, {"Unfrozen"});
+    }
+
+    if (!success) {
+        signalExceptionForGroupError(env, EINVAL, pid);
+    }
+}
+
 jint android_os_Process_getProcessGroup(JNIEnv* env, jobject clazz, jint pid)
 {
     SchedPolicy sp;
@@ -1327,6 +1343,7 @@
         {"setGid", "(I)I", (void*)android_os_Process_setGid},
         {"sendSignal", "(II)V", (void*)android_os_Process_sendSignal},
         {"sendSignalQuiet", "(II)V", (void*)android_os_Process_sendSignalQuiet},
+        {"setProcessFrozen", "(IIZ)V", (void*)android_os_Process_setProcessFrozen},
         {"getFreeMemory", "()J", (void*)android_os_Process_getFreeMemory},
         {"getTotalMemory", "()J", (void*)android_os_Process_getTotalMemory},
         {"readProcLines", "(Ljava/lang/String;[Ljava/lang/String;[J)V",
diff --git a/core/jni/android_view_InputEventSender.cpp b/core/jni/android_view_InputEventSender.cpp
index f90d1cf..84acf9a 100644
--- a/core/jni/android_view_InputEventSender.cpp
+++ b/core/jni/android_view_InputEventSender.cpp
@@ -113,10 +113,13 @@
     }
 
     uint32_t publishedSeq = mNextPublishedSeq++;
-    status_t status = mInputPublisher.publishKeyEvent(publishedSeq,
-            event->getDeviceId(), event->getSource(), event->getDisplayId(), event->getAction(),
-            event->getFlags(), event->getKeyCode(), event->getScanCode(), event->getMetaState(),
-            event->getRepeatCount(), event->getDownTime(), event->getEventTime());
+    status_t status =
+            mInputPublisher.publishKeyEvent(publishedSeq, event->getDeviceId(), event->getSource(),
+                                            event->getDisplayId(), event->getHmac(),
+                                            event->getAction(), event->getFlags(),
+                                            event->getKeyCode(), event->getScanCode(),
+                                            event->getMetaState(), event->getRepeatCount(),
+                                            event->getDownTime(), event->getEventTime());
     if (status) {
         ALOGW("Failed to send key event on channel '%s'.  status=%d",
                 getInputChannelName().c_str(), status);
@@ -134,17 +137,24 @@
     uint32_t publishedSeq;
     for (size_t i = 0; i <= event->getHistorySize(); i++) {
         publishedSeq = mNextPublishedSeq++;
-        status_t status = mInputPublisher.publishMotionEvent(publishedSeq,
-                event->getDeviceId(), event->getSource(), event->getDisplayId(),
-                event->getAction(), event->getActionButton(), event->getFlags(),
-                event->getEdgeFlags(), event->getMetaState(), event->getButtonState(),
-                event->getClassification(),
-                event->getXOffset(), event->getYOffset(),
-                event->getXPrecision(), event->getYPrecision(),
-                event->getRawXCursorPosition(), event->getRawYCursorPosition(),
-                event->getDownTime(), event->getHistoricalEventTime(i),
-                event->getPointerCount(), event->getPointerProperties(),
-                event->getHistoricalRawPointerCoords(0, i));
+        status_t status =
+                mInputPublisher.publishMotionEvent(publishedSeq, event->getDeviceId(),
+                                                   event->getSource(), event->getDisplayId(),
+                                                   event->getHmac(), event->getAction(),
+                                                   event->getActionButton(), event->getFlags(),
+                                                   event->getEdgeFlags(), event->getMetaState(),
+                                                   event->getButtonState(),
+                                                   event->getClassification(), event->getXScale(),
+                                                   event->getYScale(), event->getXOffset(),
+                                                   event->getYOffset(), event->getXPrecision(),
+                                                   event->getYPrecision(),
+                                                   event->getRawXCursorPosition(),
+                                                   event->getRawYCursorPosition(),
+                                                   event->getDownTime(),
+                                                   event->getHistoricalEventTime(i),
+                                                   event->getPointerCount(),
+                                                   event->getPointerProperties(),
+                                                   event->getHistoricalRawPointerCoords(0, i));
         if (status) {
             ALOGW("Failed to send motion event sample on channel '%s'.  status=%d",
                     getInputChannelName().c_str(), status);
diff --git a/core/jni/android_view_KeyEvent.cpp b/core/jni/android_view_KeyEvent.cpp
index f010772..57979bd 100644
--- a/core/jni/android_view_KeyEvent.cpp
+++ b/core/jni/android_view_KeyEvent.cpp
@@ -20,15 +20,53 @@
 
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/Log.h>
-#include <utils/Log.h>
 #include <input/Input.h>
+#include <nativehelper/ScopedPrimitiveArray.h>
 #include <nativehelper/ScopedUtfChars.h>
+#include <utils/Log.h>
+#include <optional>
 #include "android_view_KeyEvent.h"
 
 #include "core_jni_helpers.h"
 
 namespace android {
 
+/**
+ * Convert an std::array of bytes into a Java object.
+ */
+template <size_t N>
+static ScopedLocalRef<jbyteArray> toJbyteArray(JNIEnv* env, const std::array<uint8_t, N>& data) {
+    ScopedLocalRef<jbyteArray> array(env, env->NewByteArray(N));
+    if (array.get() == nullptr) {
+        jniThrowException(env, "java/lang/OutOfMemoryError", nullptr);
+        return array;
+    }
+    static_assert(sizeof(char) == sizeof(uint8_t));
+    env->SetByteArrayRegion(array.get(), 0, N, reinterpret_cast<const signed char*>(data.data()));
+    return array;
+}
+
+/**
+ * Convert a Java object into an std::array of bytes of size N.
+ * If the object is null,  or the length is unexpected, return std::nullopt.
+ */
+template <size_t N>
+static std::optional<std::array<uint8_t, N>> fromJobject(JNIEnv* env, jobject object) {
+    if (object == nullptr) {
+        return std::nullopt;
+    }
+    jbyteArray javaArray = reinterpret_cast<jbyteArray>(object);
+    ScopedByteArrayRO bytes(env, javaArray);
+    if (bytes.size() != N) {
+        ALOGE("Could not initialize array from java object, expected length %zu but got %zu", N,
+              bytes.size());
+        return std::nullopt;
+    }
+    std::array<uint8_t, N> array;
+    std::move(bytes.get(), bytes.get() + N, array.begin());
+    return array;
+}
+
 // ----------------------------------------------------------------------------
 
 static struct {
@@ -40,6 +78,7 @@
     jfieldID mDeviceId;
     jfieldID mSource;
     jfieldID mDisplayId;
+    jfieldID mHmac;
     jfieldID mMetaState;
     jfieldID mAction;
     jfieldID mKeyCode;
@@ -54,20 +93,16 @@
 // ----------------------------------------------------------------------------
 
 jobject android_view_KeyEvent_fromNative(JNIEnv* env, const KeyEvent* event) {
-    jobject eventObj = env->CallStaticObjectMethod(gKeyEventClassInfo.clazz,
-            gKeyEventClassInfo.obtain,
-            nanoseconds_to_milliseconds(event->getDownTime()),
-            nanoseconds_to_milliseconds(event->getEventTime()),
-            event->getAction(),
-            event->getKeyCode(),
-            event->getRepeatCount(),
-            event->getMetaState(),
-            event->getDeviceId(),
-            event->getScanCode(),
-            event->getFlags(),
-            event->getSource(),
-            event->getDisplayId(),
-            NULL);
+    ScopedLocalRef<jbyteArray> hmac = toJbyteArray(env, event->getHmac());
+    jobject eventObj =
+            env->CallStaticObjectMethod(gKeyEventClassInfo.clazz, gKeyEventClassInfo.obtain,
+                                        nanoseconds_to_milliseconds(event->getDownTime()),
+                                        nanoseconds_to_milliseconds(event->getEventTime()),
+                                        event->getAction(), event->getKeyCode(),
+                                        event->getRepeatCount(), event->getMetaState(),
+                                        event->getDeviceId(), event->getScanCode(),
+                                        event->getFlags(), event->getSource(),
+                                        event->getDisplayId(), hmac.get(), NULL);
     if (env->ExceptionCheck()) {
         ALOGE("An exception occurred while obtaining a key event.");
         LOGE_EX(env);
@@ -82,6 +117,11 @@
     jint deviceId = env->GetIntField(eventObj, gKeyEventClassInfo.mDeviceId);
     jint source = env->GetIntField(eventObj, gKeyEventClassInfo.mSource);
     jint displayId = env->GetIntField(eventObj, gKeyEventClassInfo.mDisplayId);
+    jobject hmacObj = env->GetObjectField(eventObj, gKeyEventClassInfo.mHmac);
+    std::optional<std::array<uint8_t, 32>> hmac = fromJobject<32>(env, hmacObj);
+    if (!hmac) {
+        hmac = INVALID_HMAC;
+    }
     jint metaState = env->GetIntField(eventObj, gKeyEventClassInfo.mMetaState);
     jint action = env->GetIntField(eventObj, gKeyEventClassInfo.mAction);
     jint keyCode = env->GetIntField(eventObj, gKeyEventClassInfo.mKeyCode);
@@ -91,10 +131,9 @@
     jlong downTime = env->GetLongField(eventObj, gKeyEventClassInfo.mDownTime);
     jlong eventTime = env->GetLongField(eventObj, gKeyEventClassInfo.mEventTime);
 
-    event->initialize(deviceId, source, displayId, action, flags, keyCode, scanCode, metaState,
-            repeatCount,
-            milliseconds_to_nanoseconds(downTime),
-            milliseconds_to_nanoseconds(eventTime));
+    event->initialize(deviceId, source, displayId, *hmac, action, flags, keyCode, scanCode,
+                      metaState, repeatCount, milliseconds_to_nanoseconds(downTime),
+                      milliseconds_to_nanoseconds(eventTime));
     return OK;
 }
 
@@ -134,8 +173,9 @@
     jclass clazz = FindClassOrDie(env, "android/view/KeyEvent");
     gKeyEventClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
 
-    gKeyEventClassInfo.obtain = GetStaticMethodIDOrDie(env, gKeyEventClassInfo.clazz,
-            "obtain", "(JJIIIIIIIIILjava/lang/String;)Landroid/view/KeyEvent;");
+    gKeyEventClassInfo.obtain =
+            GetStaticMethodIDOrDie(env, gKeyEventClassInfo.clazz, "obtain",
+                                   "(JJIIIIIIIII[BLjava/lang/String;)Landroid/view/KeyEvent;");
     gKeyEventClassInfo.recycle = GetMethodIDOrDie(env, gKeyEventClassInfo.clazz,
             "recycle", "()V");
 
@@ -143,6 +183,7 @@
     gKeyEventClassInfo.mSource = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mSource", "I");
     gKeyEventClassInfo.mDisplayId = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mDisplayId",
                                                     "I");
+    gKeyEventClassInfo.mHmac = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mHmac", "[B");
     gKeyEventClassInfo.mMetaState = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mMetaState",
                                                     "I");
     gKeyEventClassInfo.mAction = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mAction", "I");
diff --git a/core/jni/android_view_KeyEvent.h b/core/jni/android_view_KeyEvent.h
index 586eb2f..dab6bb7 100644
--- a/core/jni/android_view_KeyEvent.h
+++ b/core/jni/android_view_KeyEvent.h
@@ -42,4 +42,4 @@
 
 } // namespace android
 
-#endif // _ANDROID_OS_KEYEVENT_H
+#endif // _ANDROID_VIEW_KEYEVENT_H
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index feb9fe3..3335fb2 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -330,14 +330,12 @@
 
 // ----------------------------------------------------------------------------
 
-static jlong android_view_MotionEvent_nativeInitialize(JNIEnv* env, jclass clazz,
-        jlong nativePtr,
-        jint deviceId, jint source, jint displayId, jint action, jint flags, jint edgeFlags,
-        jint metaState, jint buttonState, jint classification,
-        jfloat xOffset, jfloat yOffset, jfloat xPrecision, jfloat yPrecision,
-        jlong downTimeNanos, jlong eventTimeNanos,
-        jint pointerCount, jobjectArray pointerPropertiesObjArray,
-        jobjectArray pointerCoordsObjArray) {
+static jlong android_view_MotionEvent_nativeInitialize(
+        JNIEnv* env, jclass clazz, jlong nativePtr, jint deviceId, jint source, jint displayId,
+        jint action, jint flags, jint edgeFlags, jint metaState, jint buttonState,
+        jint classification, jfloat xOffset, jfloat yOffset, jfloat xPrecision, jfloat yPrecision,
+        jlong downTimeNanos, jlong eventTimeNanos, jint pointerCount,
+        jobjectArray pointerPropertiesObjArray, jobjectArray pointerCoordsObjArray) {
     if (!validatePointerCount(env, pointerCount)
             || !validatePointerPropertiesArray(env, pointerPropertiesObjArray, pointerCount)
             || !validatePointerCoordsObjArray(env, pointerCoordsObjArray, pointerCount)) {
@@ -371,11 +369,12 @@
         env->DeleteLocalRef(pointerCoordsObj);
     }
 
-    event->initialize(deviceId, source, displayId, action, 0, flags, edgeFlags, metaState,
-            buttonState, static_cast<MotionClassification>(classification),
-            xOffset, yOffset, xPrecision, yPrecision,
-            AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
-            downTimeNanos, eventTimeNanos, pointerCount, pointerProperties, rawPointerCoords);
+    event->initialize(deviceId, source, displayId, INVALID_HMAC, action, 0, flags, edgeFlags,
+                      metaState, buttonState, static_cast<MotionClassification>(classification),
+                      1 /*xScale*/, 1 /*yScale*/, xOffset, yOffset, xPrecision, yPrecision,
+                      AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                      downTimeNanos, eventTimeNanos, pointerCount, pointerProperties,
+                      rawPointerCoords);
 
     return reinterpret_cast<jlong>(event);
 
@@ -757,155 +756,76 @@
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod gMotionEventMethods[] = {
-    /* name, signature, funcPtr */
-    { "nativeInitialize",
-            "(JIIIIIIIIIFFFFJJI[Landroid/view/MotionEvent$PointerProperties;"
-                    "[Landroid/view/MotionEvent$PointerCoords;)J",
-            (void*)android_view_MotionEvent_nativeInitialize },
-    { "nativeDispose",
-            "(J)V",
-            (void*)android_view_MotionEvent_nativeDispose },
-    { "nativeAddBatch",
-            "(JJ[Landroid/view/MotionEvent$PointerCoords;I)V",
-            (void*)android_view_MotionEvent_nativeAddBatch },
-    { "nativeReadFromParcel",
-            "(JLandroid/os/Parcel;)J",
-            (void*)android_view_MotionEvent_nativeReadFromParcel },
-    { "nativeWriteToParcel",
-            "(JLandroid/os/Parcel;)V",
-            (void*)android_view_MotionEvent_nativeWriteToParcel },
-    { "nativeAxisToString", "(I)Ljava/lang/String;",
-            (void*)android_view_MotionEvent_nativeAxisToString },
-    { "nativeAxisFromString", "(Ljava/lang/String;)I",
-            (void*)android_view_MotionEvent_nativeAxisFromString },
-    { "nativeGetPointerProperties",
-            "(JILandroid/view/MotionEvent$PointerProperties;)V",
-            (void*)android_view_MotionEvent_nativeGetPointerProperties },
-    { "nativeGetPointerCoords",
-            "(JIILandroid/view/MotionEvent$PointerCoords;)V",
-            (void*)android_view_MotionEvent_nativeGetPointerCoords },
+        /* name, signature, funcPtr */
+        {"nativeInitialize",
+         "(JIIIIIIIIIFFFFJJI[Landroid/view/MotionEvent$PointerProperties;"
+         "[Landroid/view/MotionEvent$PointerCoords;)J",
+         (void*)android_view_MotionEvent_nativeInitialize},
+        {"nativeDispose", "(J)V", (void*)android_view_MotionEvent_nativeDispose},
+        {"nativeAddBatch", "(JJ[Landroid/view/MotionEvent$PointerCoords;I)V",
+         (void*)android_view_MotionEvent_nativeAddBatch},
+        {"nativeReadFromParcel", "(JLandroid/os/Parcel;)J",
+         (void*)android_view_MotionEvent_nativeReadFromParcel},
+        {"nativeWriteToParcel", "(JLandroid/os/Parcel;)V",
+         (void*)android_view_MotionEvent_nativeWriteToParcel},
+        {"nativeAxisToString", "(I)Ljava/lang/String;",
+         (void*)android_view_MotionEvent_nativeAxisToString},
+        {"nativeAxisFromString", "(Ljava/lang/String;)I",
+         (void*)android_view_MotionEvent_nativeAxisFromString},
+        {"nativeGetPointerProperties", "(JILandroid/view/MotionEvent$PointerProperties;)V",
+         (void*)android_view_MotionEvent_nativeGetPointerProperties},
+        {"nativeGetPointerCoords", "(JIILandroid/view/MotionEvent$PointerCoords;)V",
+         (void*)android_view_MotionEvent_nativeGetPointerCoords},
 
-    // --------------- @FastNative ----------------------
-    { "nativeGetPointerId",
-            "(JI)I",
-            (void*)android_view_MotionEvent_nativeGetPointerId },
-    { "nativeGetToolType",
-            "(JI)I",
-            (void*)android_view_MotionEvent_nativeGetToolType },
-    { "nativeGetEventTimeNanos",
-            "(JI)J",
-            (void*)android_view_MotionEvent_nativeGetEventTimeNanos },
-    { "nativeGetRawAxisValue",
-            "(JIII)F",
-            (void*)android_view_MotionEvent_nativeGetRawAxisValue },
-    { "nativeGetAxisValue",
-            "(JIII)F",
-            (void*)android_view_MotionEvent_nativeGetAxisValue },
-    { "nativeTransform",
-            "(JLandroid/graphics/Matrix;)V",
-            (void*)android_view_MotionEvent_nativeTransform },
+        // --------------- @FastNative ----------------------
+        {"nativeGetPointerId", "(JI)I", (void*)android_view_MotionEvent_nativeGetPointerId},
+        {"nativeGetToolType", "(JI)I", (void*)android_view_MotionEvent_nativeGetToolType},
+        {"nativeGetEventTimeNanos", "(JI)J",
+         (void*)android_view_MotionEvent_nativeGetEventTimeNanos},
+        {"nativeGetRawAxisValue", "(JIII)F", (void*)android_view_MotionEvent_nativeGetRawAxisValue},
+        {"nativeGetAxisValue", "(JIII)F", (void*)android_view_MotionEvent_nativeGetAxisValue},
+        {"nativeTransform", "(JLandroid/graphics/Matrix;)V",
+         (void*)android_view_MotionEvent_nativeTransform},
 
-    // --------------- @CriticalNative ------------------
+        // --------------- @CriticalNative ------------------
 
-    { "nativeCopy",
-            "(JJZ)J",
-            (void*)android_view_MotionEvent_nativeCopy },
-    { "nativeGetDeviceId",
-            "(J)I",
-            (void*)android_view_MotionEvent_nativeGetDeviceId },
-    { "nativeGetSource",
-            "(J)I",
-            (void*)android_view_MotionEvent_nativeGetSource },
-    { "nativeSetSource",
-            "(JI)V",
-            (void*)android_view_MotionEvent_nativeSetSource },
-    { "nativeGetDisplayId",
-            "(J)I",
-            (void*)android_view_MotionEvent_nativeGetDisplayId },
-    { "nativeSetDisplayId",
-            "(JI)V",
-            (void*)android_view_MotionEvent_nativeSetDisplayId },
-    { "nativeGetAction",
-            "(J)I",
-            (void*)android_view_MotionEvent_nativeGetAction },
-    { "nativeSetAction",
-            "(JI)V",
-            (void*)android_view_MotionEvent_nativeSetAction },
-    { "nativeGetActionButton",
-            "(J)I",
-            (void*)android_view_MotionEvent_nativeGetActionButton},
-    { "nativeSetActionButton",
-            "(JI)V",
-            (void*)android_view_MotionEvent_nativeSetActionButton},
-    { "nativeIsTouchEvent",
-            "(J)Z",
-            (void*)android_view_MotionEvent_nativeIsTouchEvent },
-    { "nativeGetFlags",
-            "(J)I",
-            (void*)android_view_MotionEvent_nativeGetFlags },
-    { "nativeSetFlags",
-            "(JI)V",
-            (void*)android_view_MotionEvent_nativeSetFlags },
-    { "nativeGetEdgeFlags",
-            "(J)I",
-            (void*)android_view_MotionEvent_nativeGetEdgeFlags },
-    { "nativeSetEdgeFlags",
-            "(JI)V",
-            (void*)android_view_MotionEvent_nativeSetEdgeFlags },
-    { "nativeGetMetaState",
-            "(J)I",
-            (void*)android_view_MotionEvent_nativeGetMetaState },
-    { "nativeGetButtonState",
-            "(J)I",
-            (void*)android_view_MotionEvent_nativeGetButtonState },
-    { "nativeSetButtonState",
-            "(JI)V",
-            (void*)android_view_MotionEvent_nativeSetButtonState },
-    { "nativeGetClassification",
-            "(J)I",
-            (void*)android_view_MotionEvent_nativeGetClassification },
-    { "nativeOffsetLocation",
-            "(JFF)V",
-            (void*)android_view_MotionEvent_nativeOffsetLocation },
-    { "nativeGetXOffset",
-            "(J)F",
-            (void*)android_view_MotionEvent_nativeGetXOffset },
-    { "nativeGetYOffset",
-            "(J)F",
-            (void*)android_view_MotionEvent_nativeGetYOffset },
-    { "nativeGetXPrecision",
-            "(J)F",
-            (void*)android_view_MotionEvent_nativeGetXPrecision },
-    { "nativeGetYPrecision",
-            "(J)F",
-            (void*)android_view_MotionEvent_nativeGetYPrecision },
-    { "nativeGetXCursorPosition",
-            "(J)F",
-            (void*)android_view_MotionEvent_nativeGetXCursorPosition },
-    { "nativeGetYCursorPosition",
-            "(J)F",
-            (void*)android_view_MotionEvent_nativeGetYCursorPosition },
-    { "nativeSetCursorPosition",
-            "(JFF)V",
-            (void*)android_view_MotionEvent_nativeSetCursorPosition },
-    { "nativeGetDownTimeNanos",
-            "(J)J",
-            (void*)android_view_MotionEvent_nativeGetDownTimeNanos },
-    { "nativeSetDownTimeNanos",
-            "(JJ)V",
-            (void*)android_view_MotionEvent_nativeSetDownTimeNanos },
-    { "nativeGetPointerCount",
-            "(J)I",
-            (void*)android_view_MotionEvent_nativeGetPointerCount },
-    { "nativeFindPointerIndex",
-            "(JI)I",
-            (void*)android_view_MotionEvent_nativeFindPointerIndex },
-    { "nativeGetHistorySize",
-            "(J)I",
-            (void*)android_view_MotionEvent_nativeGetHistorySize },
-    { "nativeScale",
-            "(JF)V",
-            (void*)android_view_MotionEvent_nativeScale },
+        {"nativeCopy", "(JJZ)J", (void*)android_view_MotionEvent_nativeCopy},
+        {"nativeGetDeviceId", "(J)I", (void*)android_view_MotionEvent_nativeGetDeviceId},
+        {"nativeGetSource", "(J)I", (void*)android_view_MotionEvent_nativeGetSource},
+        {"nativeSetSource", "(JI)V", (void*)android_view_MotionEvent_nativeSetSource},
+        {"nativeGetDisplayId", "(J)I", (void*)android_view_MotionEvent_nativeGetDisplayId},
+        {"nativeSetDisplayId", "(JI)V", (void*)android_view_MotionEvent_nativeSetDisplayId},
+        {"nativeGetAction", "(J)I", (void*)android_view_MotionEvent_nativeGetAction},
+        {"nativeSetAction", "(JI)V", (void*)android_view_MotionEvent_nativeSetAction},
+        {"nativeGetActionButton", "(J)I", (void*)android_view_MotionEvent_nativeGetActionButton},
+        {"nativeSetActionButton", "(JI)V", (void*)android_view_MotionEvent_nativeSetActionButton},
+        {"nativeIsTouchEvent", "(J)Z", (void*)android_view_MotionEvent_nativeIsTouchEvent},
+        {"nativeGetFlags", "(J)I", (void*)android_view_MotionEvent_nativeGetFlags},
+        {"nativeSetFlags", "(JI)V", (void*)android_view_MotionEvent_nativeSetFlags},
+        {"nativeGetEdgeFlags", "(J)I", (void*)android_view_MotionEvent_nativeGetEdgeFlags},
+        {"nativeSetEdgeFlags", "(JI)V", (void*)android_view_MotionEvent_nativeSetEdgeFlags},
+        {"nativeGetMetaState", "(J)I", (void*)android_view_MotionEvent_nativeGetMetaState},
+        {"nativeGetButtonState", "(J)I", (void*)android_view_MotionEvent_nativeGetButtonState},
+        {"nativeSetButtonState", "(JI)V", (void*)android_view_MotionEvent_nativeSetButtonState},
+        {"nativeGetClassification", "(J)I",
+         (void*)android_view_MotionEvent_nativeGetClassification},
+        {"nativeOffsetLocation", "(JFF)V", (void*)android_view_MotionEvent_nativeOffsetLocation},
+        {"nativeGetXOffset", "(J)F", (void*)android_view_MotionEvent_nativeGetXOffset},
+        {"nativeGetYOffset", "(J)F", (void*)android_view_MotionEvent_nativeGetYOffset},
+        {"nativeGetXPrecision", "(J)F", (void*)android_view_MotionEvent_nativeGetXPrecision},
+        {"nativeGetYPrecision", "(J)F", (void*)android_view_MotionEvent_nativeGetYPrecision},
+        {"nativeGetXCursorPosition", "(J)F",
+         (void*)android_view_MotionEvent_nativeGetXCursorPosition},
+        {"nativeGetYCursorPosition", "(J)F",
+         (void*)android_view_MotionEvent_nativeGetYCursorPosition},
+        {"nativeSetCursorPosition", "(JFF)V",
+         (void*)android_view_MotionEvent_nativeSetCursorPosition},
+        {"nativeGetDownTimeNanos", "(J)J", (void*)android_view_MotionEvent_nativeGetDownTimeNanos},
+        {"nativeSetDownTimeNanos", "(JJ)V", (void*)android_view_MotionEvent_nativeSetDownTimeNanos},
+        {"nativeGetPointerCount", "(J)I", (void*)android_view_MotionEvent_nativeGetPointerCount},
+        {"nativeFindPointerIndex", "(JI)I", (void*)android_view_MotionEvent_nativeFindPointerIndex},
+        {"nativeGetHistorySize", "(J)I", (void*)android_view_MotionEvent_nativeGetHistorySize},
+        {"nativeScale", "(JF)V", (void*)android_view_MotionEvent_nativeScale},
 };
 
 int register_android_view_MotionEvent(JNIEnv* env) {
diff --git a/core/jni/android_view_MotionEvent.h b/core/jni/android_view_MotionEvent.h
index 0cf1fb2..9ce4bf3 100644
--- a/core/jni/android_view_MotionEvent.h
+++ b/core/jni/android_view_MotionEvent.h
@@ -38,4 +38,4 @@
 
 } // namespace android
 
-#endif // _ANDROID_OS_KEYEVENT_H
+#endif // _ANDROID_VIEW_MOTIONEVENT_H
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 01b5920..b01083b 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -413,6 +413,12 @@
     return anw->perform(surface, NATIVE_WINDOW_SET_AUTO_REFRESH, int(enabled));
 }
 
+static jint nativeSetFrameRate(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat frameRate) {
+    Surface* surface = reinterpret_cast<Surface*>(nativeObject);
+    ANativeWindow* anw = static_cast<ANativeWindow*>(surface);
+    return anw->perform(surface, NATIVE_WINDOW_SET_FRAME_RATE, float(frameRate));
+}
+
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod gSurfaceMethods[] = {
@@ -447,6 +453,7 @@
             (void*)nativeAttachAndQueueBufferWithColorSpace},
     {"nativeSetSharedBufferModeEnabled", "(JZ)I", (void*)nativeSetSharedBufferModeEnabled},
     {"nativeSetAutoRefreshEnabled", "(JZ)I", (void*)nativeSetAutoRefreshEnabled},
+    {"nativeSetFrameRate", "(JF)I", (void*)nativeSetFrameRate},
 };
 
 int register_android_view_Surface(JNIEnv* env)
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index e0f9571..2b9d454 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -584,6 +584,14 @@
     transaction->setShadowRadius(ctrl, shadowRadius);
 }
 
+static void nativeSetFrameRate(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject,
+                               jfloat frameRate) {
+    auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+
+    const auto ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);
+    transaction->setFrameRate(ctrl, frameRate);
+}
+
 static jlongArray nativeGetPhysicalDisplayIds(JNIEnv* env, jclass clazz) {
     const auto displayIds = SurfaceComposerClient::getPhysicalDisplayIds();
     jlongArray array = env->NewLongArray(displayIds.size());
@@ -1383,6 +1391,8 @@
             (void*)nativeSetLayerStack },
     {"nativeSetShadowRadius", "(JJF)V",
             (void*)nativeSetShadowRadius },
+    {"nativeSetFrameRate", "(JJF)V",
+            (void*)nativeSetFrameRate },
     {"nativeGetPhysicalDisplayIds", "()[J",
             (void*)nativeGetPhysicalDisplayIds },
     {"nativeGetPhysicalDisplayToken", "(J)Landroid/os/IBinder;",
diff --git a/core/proto/OWNERS b/core/proto/OWNERS
index 74ced89..4892faa 100644
--- a/core/proto/OWNERS
+++ b/core/proto/OWNERS
@@ -14,6 +14,7 @@
 # Frameworks
 ogunwale@google.com
 jjaggi@google.com
+per-file usagestatsservice.proto, usagestatsservice_v2.proto = mwachens@google.com
 
 # Launcher
 hyunyoungs@google.com
diff --git a/core/proto/android/hardware/location/context_hub_info.proto b/core/proto/android/hardware/location/context_hub_info.proto
new file mode 100644
index 0000000..de5cd55
--- /dev/null
+++ b/core/proto/android/hardware/location/context_hub_info.proto
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+package android.hardware.location;
+
+import "frameworks/base/core/proto/android/privacy.proto";
+
+option java_multiple_files = true;
+
+message ContextHubInfoProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+    // Context hub unique identifier
+    optional int32 id = 1;
+    // A name for the hub
+    optional string name = 2;
+    // A name for the vendor
+    optional string vendor = 3;
+    // Description of the tool chain
+    optional string toolchain = 4;
+    optional int32 platform_version = 5;
+    optional int32 static_sw_version = 6;
+    optional int32 toolchain_version = 7;
+    // The CHRE platform ID as defined in chre/version.h
+    optional int64 chre_platform_id = 8;
+    // Peak MIPS that this hub can deliver
+    optional float peak_mips = 9;
+    // Power draw in stopped state in milli watts
+    optional float stopped_power_draw_mw = 10;
+    // Power draw in sleep state in milli watts
+    optional float sleep_power_draw_mw = 11;
+    // Peak power draw in milli watts
+    optional float peak_power_draw_mw = 12;
+    // The maximum number of bytes that can be sent per message to the hub
+    optional int32 max_packet_length_bytes = 13;
+}
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index d08cbed..8adcc9e 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -36,6 +36,7 @@
 import "frameworks/base/core/proto/android/server/alarmmanagerservice.proto";
 import "frameworks/base/core/proto/android/server/fingerprint.proto";
 import "frameworks/base/core/proto/android/server/jobscheduler.proto";
+import "frameworks/base/core/proto/android/server/location/context_hub.proto";
 import "frameworks/base/core/proto/android/server/powermanagerservice.proto";
 import "frameworks/base/core/proto/android/server/rolemanagerservice.proto";
 import "frameworks/base/core/proto/android/server/windowmanagerservice.proto";
@@ -486,6 +487,11 @@
         (section).args = "connmetrics --proto"
     ];
 
+    optional com.android.server.location.ContextHubServiceProto context_hub = 3051 [
+        (section).type = SECTION_DUMPSYS,
+        (section).args = "contexthub --proto"
+    ];
+
     // Reserved for OEMs.
     extensions 50000 to 100000;
 }
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index 126d445..1426932 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -109,7 +109,7 @@
     // To be removed soon.
     optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1 [deprecated=true];
     optional int32 id = 2;
-    repeated ActivityRecordProto activities = 3;
+    repeated .com.android.server.wm.ActivityRecordProto activities = 3;
     optional int32 stack_id = 4;
     optional .android.graphics.RectProto last_non_fullscreen_bounds = 5;
     optional string real_activity = 6;
@@ -123,21 +123,6 @@
     optional .com.android.server.wm.TaskProto task = 14;
 }
 
-message ActivityRecordProto {
-    option (.android.msg_privacy).dest = DEST_AUTOMATIC;
-
-    // To be removed soon.
-    optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1 [deprecated=true];
-    optional .com.android.server.wm.IdentifierProto identifier = 2;
-    optional string state = 3;
-    optional bool visible_requested = 4;
-    optional bool front_of_task = 5;
-    optional int32 proc_id = 6;
-    optional bool translucent = 7;
-    optional .com.android.server.wm.AppWindowTokenProto app_window_token = 8;
-    optional bool visible = 9;
-}
-
 message KeyguardControllerProto {
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
@@ -589,7 +574,8 @@
     repeated IntentBindRecordProto bindings = 25;
     repeated ConnectionRecordProto connections = 26;
 
-    // Next Tag: 27
+    optional bool allow_while_in_use_permission_in_fgs = 27;
+    // Next Tag: 28
 }
 
 message ConnectionRecordProto {
diff --git a/core/proto/android/server/location/context_hub.proto b/core/proto/android/server/location/context_hub.proto
new file mode 100644
index 0000000..c87f791
--- /dev/null
+++ b/core/proto/android/server/location/context_hub.proto
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+package com.android.server.location;
+
+import "frameworks/base/core/proto/android/hardware/location/context_hub_info.proto";
+import "frameworks/base/core/proto/android/privacy.proto";
+
+option java_multiple_files = true;
+
+message ContextHubServiceProto {
+    option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    repeated .android.hardware.location.ContextHubInfoProto context_hub_info = 1;
+    optional ClientManagerProto client_manager = 2;
+}
+
+message ClientManagerProto {
+    option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    message RegistrationRecord {
+        option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+        optional int64 timestamp_ms = 1;
+        optional int32 action = 2;
+        // ClientBroker endpoint id, contexthub id and package name
+        optional string broker = 3;
+    }
+
+    repeated ClientBrokerProto client_brokers = 1;
+    repeated RegistrationRecord registration_records = 2;
+}
+
+message ClientBrokerProto {
+    option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional int32 endpoint_id = 1;
+    optional int32 attached_context_hub_id = 2;
+    optional string package = 3;
+    optional int64 nano_app_id = 4;
+    optional bool pending_intent_request_valid = 5;
+    optional bool has_pending_intent = 6;
+    optional bool pending_intent_cancelled = 7;
+    optional bool registered = 8;
+
+}
diff --git a/core/proto/android/server/usagestatsservice_v2.proto b/core/proto/android/server/usagestatsservice_v2.proto
index a28fcf3..24b0728 100644
--- a/core/proto/android/server/usagestatsservice_v2.proto
+++ b/core/proto/android/server/usagestatsservice_v2.proto
@@ -99,6 +99,7 @@
   optional int32 instance_id = 10;
   optional int32 task_root_package_token = 11;
   optional int32 task_root_class_token = 12;
+  optional int32 locus_id_token = 13;
 }
 
 /**
@@ -117,6 +118,7 @@
   optional int32 instance_id = 10;
   optional string task_root_package = 11;
   optional string task_root_class = 12;
+  optional string locus_id = 13;
 }
 
 /**
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index 0c74842..c0743e5 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -147,7 +147,8 @@
     optional int32 id = 2;
     repeated StackProto stacks = 3;
     optional DockedStackDividerControllerProto docked_stack_divider_controller = 4;
-    optional PinnedStackControllerProto pinned_stack_controller = 5;
+    // Will be removed soon.
+    optional PinnedStackControllerProto pinned_stack_controller = 5 [deprecated=true];
     /* non app windows */
     repeated WindowTokenProto above_app_windows = 6;
     repeated WindowTokenProto below_app_windows = 7;
@@ -184,8 +185,8 @@
 message PinnedStackControllerProto {
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
-    optional .android.graphics.RectProto default_bounds = 1;
-    optional .android.graphics.RectProto movement_bounds = 2;
+    optional .android.graphics.RectProto default_bounds = 1 [deprecated=true];
+    optional .android.graphics.RectProto movement_bounds = 2 [deprecated=true];
 }
 
 /* represents TaskStack */
@@ -213,7 +214,7 @@
 
     optional WindowContainerProto window_container = 1;
     optional int32 id = 2;
-    repeated AppWindowTokenProto app_window_tokens = 3;
+    repeated ActivityRecordProto activity = 3;
     optional bool fills_parent = 4;
     optional .android.graphics.RectProto bounds = 5;
     optional .android.graphics.RectProto displayed_bounds = 6;
@@ -223,12 +224,12 @@
     optional int32 surface_height = 9;
 }
 
-/* represents AppWindowToken */
-message AppWindowTokenProto {
+/* represents ActivityRecordProto */
+message ActivityRecordProto {
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
-    /* obtained from ActivityRecord */
     optional string name = 1 [ (.android.privacy).dest = DEST_EXPLICIT ];
+
     optional WindowTokenProto window_token = 2;
     optional bool last_surface_showing = 3;
     optional bool is_waiting_for_transition_start = 4;
@@ -253,6 +254,13 @@
     optional bool visible_set_from_transferred_starting_window = 22;
     repeated .android.graphics.RectProto frozen_bounds = 23;
     optional bool visible = 24;
+    // To be removed soon.
+    optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 25 [deprecated=true];
+    optional .com.android.server.wm.IdentifierProto identifier = 26;
+    optional string state = 27;
+    optional bool front_of_task = 28;
+    optional int32 proc_id = 29;
+    optional bool translucent = 30;
 }
 
 /* represents WindowToken */
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 4595bab..4d319df 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -53,6 +53,7 @@
     <protected-broadcast android:name="android.intent.action.PACKAGE_VERIFIED" />
     <protected-broadcast android:name="android.intent.action.PACKAGES_SUSPENDED" />
     <protected-broadcast android:name="android.intent.action.PACKAGES_UNSUSPENDED" />
+    <protected-broadcast android:name="android.intent.action.PACKAGE_UNSUSPENDED_MANUALLY" />
     <protected-broadcast android:name="android.intent.action.DISTRACTING_PACKAGES_CHANGED" />
     <protected-broadcast android:name="android.intent.action.ACTION_PREFERRED_ACTIVITY_CHANGED" />
     <protected-broadcast android:name="android.intent.action.UID_REMOVED" />
@@ -93,7 +94,6 @@
     <protected-broadcast android:name="android.intent.action.OVERLAY_CHANGED" />
     <protected-broadcast android:name="android.intent.action.OVERLAY_REMOVED" />
     <protected-broadcast android:name="android.intent.action.OVERLAY_PRIORITY_CHANGED" />
-    <protected-broadcast android:name="android.intent.action.USER_ACTIVITY_NOTIFICATION" />
     <protected-broadcast android:name="android.intent.action.MY_PACKAGE_SUSPENDED" />
     <protected-broadcast android:name="android.intent.action.MY_PACKAGE_UNSUSPENDED" />
 
@@ -1528,6 +1528,14 @@
         android:protectionLevel="signature|privileged" />
     <uses-permission android:name="android.permission.LOCATION_HARDWARE"/>
 
+    <!-- @SystemApi Allows an application to use the Context Hub.
+         <p>Not for use by third-party applications.
+         @hide
+    -->
+    <permission android:name="android.permission.ACCESS_CONTEXT_HUB"
+        android:protectionLevel="signature" />
+    <uses-permission android:name="android.permission.ACCESS_CONTEXT_HUB"/>
+
     <!-- @SystemApi Allows an application to create mock location providers for testing.
          <p>Protection level: signature
          @hide
@@ -3331,6 +3339,13 @@
     <permission android:name="android.permission.BIND_AUTOFILL_FIELD_CLASSIFICATION_SERVICE"
                 android:protectionLevel="signature" />
 
+    <!-- Must be required by an {@link android.service.autofill.InlineSuggestionRenderService}
+         to ensure that only the system can bind to it.
+         @hide This is not a third-party API (intended for OEMs and system apps).
+    -->
+    <permission android:name="android.permission.BIND_INLINE_SUGGESTION_RENDER_SERVICE"
+                android:protectionLevel="signature" />
+
     <!-- Must be required by a android.service.textclassifier.TextClassifierService,
          to ensure that only the system can bind to it.
          @SystemApi @hide This is not a third-party API (intended for OEMs and system apps).
@@ -4298,6 +4313,11 @@
     <permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE"
         android:protectionLevel="signature" />
 
+    <!-- Allows applications to set the initial lockscreen state.
+         <p>Not for use by third-party applications. @hide -->
+    <permission android:name="android.permission.SET_INITIAL_LOCK"
+        android:protectionLevel="signature|setup"/>
+
     <!-- Allows managing (adding, removing) fingerprint templates. Reserved for the system. @hide -->
     <permission android:name="android.permission.MANAGE_FINGERPRINT"
         android:protectionLevel="signature|privileged" />
@@ -4836,6 +4856,19 @@
     <permission android:name="android.permission.ACCESS_SHARED_LIBRARIES"
                 android:protectionLevel="signature|installer" />
 
+    <!-- Allows an app to log compat change usage.
+         @hide  <p>Not for use by third-party applications.</p> -->
+    <permission android:name="android.permission.LOG_COMPAT_CHANGE"
+                android:protectionLevel="signature" />
+    <!-- Allows an app to read compat change config.
+         @hide  <p>Not for use by third-party applications.</p> -->
+    <permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"
+                android:protectionLevel="signature" />
+    <!-- Allows an app to override compat change config.
+         @hide  <p>Not for use by third-party applications.</p> -->
+    <permission android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG"
+                android:protectionLevel="signature" />
+
     <!-- Allows input events to be monitored. Very dangerous!  @hide -->
     <permission android:name="android.permission.MONITOR_INPUT"
                 android:protectionLevel="signature" />
@@ -5046,12 +5079,6 @@
                 android:process=":ui">
         </activity>
 
-        <activity android:name="com.android.internal.app.BlockedAppActivity"
-                android:theme="@style/Theme.Dialog.Confirmation"
-                android:excludeFromRecents="true"
-                android:process=":ui">
-        </activity>
-
         <activity android:name="com.android.settings.notification.NotificationAccessConfirmationActivity"
                   android:theme="@style/Theme.Dialog.Confirmation"
                   android:excludeFromRecents="true">
diff --git a/core/res/res/layout/autofill_inline_suggestion.xml b/core/res/res/layout/autofill_inline_suggestion.xml
index f7ac164..27faea4 100644
--- a/core/res/res/layout/autofill_inline_suggestion.xml
+++ b/core/res/res/layout/autofill_inline_suggestion.xml
@@ -16,19 +16,20 @@
 
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
+    style="?android:attr/autofillInlineSuggestionChip"
     android:layout_width="wrap_content"
-    android:layout_height="56dp"
-    android:background="@color/white"
-    android:orientation="horizontal"
-    android:paddingStart="12dp"
-    android:paddingEnd="12dp">
+    android:layout_height="wrap_content"
+    android:gravity="center"
+    android:paddingTop="4dp"
+    android:paddingBottom="4dp"
+    android:orientation="horizontal">
 
     <ImageView
         android:id="@+id/autofill_inline_suggestion_start_icon"
-        android:layout_width="24dp"
-        android:layout_height="24dp"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
         android:layout_gravity="center"
+        android:scaleType="fitCenter"
         android:contentDescription="autofill_inline_suggestion_start_icon" />
 
     <LinearLayout
@@ -36,32 +37,33 @@
         android:layout_height="match_parent"
         android:layout_gravity="center"
         android:layout_weight="1"
-        android:layout_marginStart="12dp"
-        android:layout_marginEnd="12dp"
+        android:paddingStart="4dp"
+        android:paddingEnd="4dp"
         android:orientation="vertical"
-        android:gravity="center_vertical">
+        android:gravity="center">
 
         <TextView
+            style="?android:attr/autofillInlineSuggestionTitle"
             android:id="@+id/autofill_inline_suggestion_title"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:ellipsize="end"
-            android:maxLines="1"
-            tools:text="username1"/>
+            android:maxLines="1"/>
 
         <TextView
+            style="?android:attr/autofillInlineSuggestionSubtitle"
             android:id="@+id/autofill_inline_suggestion_subtitle"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:ellipsize="end"
-            android:maxLines="1"
-            tools:text="inline fill service"/>
+            android:maxLines="1"/>
     </LinearLayout>
 
     <ImageView
         android:id="@+id/autofill_inline_suggestion_end_icon"
-        android:layout_width="24dp"
-        android:layout_height="24dp"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
         android:layout_gravity="center"
+        android:scaleType="fitCenter"
         android:contentDescription="autofill_inline_suggestion_end_icon" />
 </LinearLayout>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index be0e588..c34a485 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Jou toestel sal uitgevee word"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Die administrasieprogram kan nie gebruik word nie. Jou toestel sal nou uitgevee word.\n\nKontak jou organisasie se administrateur as jy vrae het."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Druk is gedeaktiveer deur <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Ek"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tablet-opsies"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV-opsies"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"by jou kalender in te gaan"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS-boodskappe te stuur en te bekyk"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Lêers en media"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"toegang te verkry tot foto\'s, media en lêers op jou toestel"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofoon"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"oudio op te neem"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Kan tik, swiep, knyp en ander gebare uitvoer."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Vingerafdrukgebare"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Kan gebare vasvang wat op die toestel se vingerafdruksensor uitgevoer word."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Neem skermkiekie"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan \'n skermkiekie neem."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"deaktiveer of verander statusbalk"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Laat die program toe om die statusbalk te deaktiveer en stelselikone by te voeg of te verwyder."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"wees die statusbalk"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Jy het jou ontsluitpatroon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer verkeerdelik geteken. Na nog <xliff:g id="NUMBER_1">%2$d</xliff:g> onsuksesvolle pogings, sal jy gevra word om jou foon te ontsluit deur middel van \'n e-posrekening.\n\n Probeer weer oor <xliff:g id="NUMBER_2">%3$d</xliff:g> sekondes."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Verwyder"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Verhoog volume bo aanbevole vlak?\n\nOm lang tydperke teen hoë volume te luister, kan jou gehoor beskadig."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Gebruik toeganklikheidkortpad?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Wanneer die kortpad aan is, sal \'n toeganklikheidkenmerk begin word as albei volumeknoppies 3 sekondes lank gedruk word.\n\n Bestaande toeganklikheidkenmerk:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Jy kan die kenmerk in Instellings &gt; Toeganklikheid verander."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Maak leeg"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Wysig kortpaaie"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Kanselleer"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Skakel kortpad af"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Program is nie beskikbaar nie"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> is nie nou onmiddellik beskikbaar nie. Dit word bestuur deur <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Kom meer te wete"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Skakel werkprofiel aan?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Jou werkprogramme, kennisgewings, data en ander werkprofielkenmerke sal aangeskakel word"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Skakel aan"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Hierdie program is vir \'n ouer weergawe van Android gebou en sal dalk nie behoorlik werk nie. Probeer kyk vir opdaterings, of kontak die ontwikkelaar."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Kyk vir opdatering"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Jy het nuwe boodskappe"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Battery kan afloop voordat dit normaalweg gelaai word"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Batterybespaarder is geaktiveer om batterylewe te verleng"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Batterybespaarder"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Batterybespaarder is afgeskakel"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Foon se battery het genoeg krag. Kenmerke is nie meer beperk nie."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Tablet se battery het genoeg krag. Kenmerke is nie meer beperk nie."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Toestel se battery het genoeg krag. Kenmerke is nie meer beperk nie."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"Vouer"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android-program"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Lêer"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g>-sigblad"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Aanbieding"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g>-aanbieding"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth sal tydens vliegtuigmodus aan bly"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Laai tans"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> lêers</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Wissel verdeelde skerm"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Sluitskerm"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Skermkiekie"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> se onderskrifbalk."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> is in die BEPERK-groep geplaas"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index c92d3b0..23e6ccd 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"የእርስዎ መሣሪያ ይደመሰሳል"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"የአስተዳዳሪ መተግበሪያ ስራ ላይ ሊውል አይችልም። የእርስዎን መሣሪያ አሁን ይደመሰሳል።\n\nጥያቄዎች ካለዎት የድርጅትዎን አስተዳዳሪ ያነጋግሩ።"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"ማተም በ<xliff:g id="OWNER_APP">%s</xliff:g> ተሰናክሏል።"</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"እኔ"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"የጡባዊ አማራጮች"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV አማራጮች"</string>
@@ -1609,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"የመክፈቻ ስርዓተ ጥለቱን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ በትክክል አልሳሉትም። ከ<xliff:g id="NUMBER_1">%2$d</xliff:g> ተጨማሪ ያልተሳኩ ሙከራዎች በኋላ የኢሜይል መለያ ተጠቅመው ስልክዎን እንዲከፍቱ ይጠየቃሉ።\n\nእባክዎ ከ<xliff:g id="NUMBER_2">%3$d</xliff:g> ሰከንዶች በኋላ እንደገና ይሞክሩ።"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"አስወግድ"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ድምጹ ከሚመከረው መጠን በላይ ከፍ ይበል?\n\nበከፍተኛ ድምጽ ለረጅም ጊዜ ማዳመጥ ጆሮዎን ሊጎዳው ይችላል።"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"የተደራሽነት አቋራጭ ጥቅም ላይ ይዋል?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"አቋራጩ ሲበራ ሁለቱንም የድምፅ አዝራሮች ለ3 ሰከንዶች ተጭኖ መቆየት የተደራሽነት ባህሪን ያስጀምረዋል።\n\n አሁን ያለ የተደራሽነት ባህሪ፦\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n ባህሪውን በቅንብሮች &gt; ተደራሽነት ውስጥ ሊለውጡት ይችላሉ።"</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"ባዶ"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"አቋራጮችን አርትዕ ያድርጉ"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"ይቅር"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"አቋራጩን አጥፋ"</string>
@@ -1847,11 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"መተግበሪያ አይገኝም"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> አሁን ላይ አይገኝም። በ<xliff:g id="APP_NAME_1">%2$s</xliff:g> የሚተዳደር ነው።"</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"የበለጠ ለመረዳት"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"የስራ መገለጫ ይብራ?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"የእርስዎ የስራ መተግበሪያዎች፣ ማሳወቂያዎች፣ ውሂብ እና ሌሎች የስራ መገለጫ ባህሪያት ይበራሉ"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"አብራ"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"መተግበሪያ አይገኝም"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> አሁን አይገኝም።"</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ይህ መተግበሪያ ለቆየ የAndroid ስሪት ነው የተገነባው፣ እና በአግባቡ ላይሰራ ይችላል። ዝማኔዎች ካሉ ለመመልከት ይሞክሩ፣ ወይም ደግሞ ገንቢውን ያነጋግሩ።"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"ዝማኔ ካለ አረጋግጥ"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"አዲስ መልዕክቶች አለዎት"</string>
@@ -1984,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"የ<xliff:g id="EXTENSION">%1$s</xliff:g> ተመን ሉህ"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"የዝግጅት አቀራረብ"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"የ<xliff:g id="EXTENSION">%1$s</xliff:g> ዝግጅት አቀራረብ"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"ብሉቱዝ በአውሮፕላን ሁነታ ጊዜ እንደበራ ይቆያል"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"በመጫን ላይ"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ፋይሎች</item>
@@ -2001,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"የተከፈለ ማያን ቀያይር"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"የማያ ገጽ ቁልፍ"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"ቅጽበታዊ ገጽ እይታ"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"የ<xliff:g id="APP_NAME">%1$s</xliff:g> የሥዕል ገላጭ ጽሑፍ አሞሌ።"</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> ወደ የRESTRICTED ባልዲ ተከትቷል"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 1a6bbd8..80c04eb 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -49,7 +49,7 @@
     <string name="invalidPuk" msgid="8831151490931907083">"‏اكتب رمز PUK مكونًا من ٨ أرقام أو أكثر."</string>
     <string name="needPuk" msgid="7321876090152422918">"‏شريحة SIM مؤمّنة برمز PUK. اكتب رمز PUK لإلغاء تأمينها."</string>
     <string name="needPuk2" msgid="7032612093451537186">"‏اكتب PUK2 لإلغاء تأمين شريحة SIM."</string>
-    <string name="enablePin" msgid="2543771964137091212">"‏محاولة غير ناجحة، مكّن قفل SIM/RUIM."</string>
+    <string name="enablePin" msgid="2543771964137091212">"‏محاولة غير ناجحة، فعّل قفل SIM/RUIM."</string>
     <plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584">
       <item quantity="zero">‏لم يتبق لديك أي محاولات (<xliff:g id="NUMBER_1">%d</xliff:g>) يتم بعدها قفل شريحة SIM.</item>
       <item quantity="two">‏يتبقى لديك محاولتان (<xliff:g id="NUMBER_1">%d</xliff:g>) يتم بعدهما قفل شريحة SIM.</item>
@@ -202,6 +202,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"سيتم محو بيانات جهازك."</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"تعذّر استخدام تطبيق المشرف. سيتم محو بيانات جهازك الآن.\n\nإذا كانت لديك أسئلة، اتصل بمشرف مؤسستك."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"تم إيقاف الطباعة بواسطة <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"أنا"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"خيارات الجهاز اللوحي"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"‏خيارات Android TV"</string>
@@ -218,7 +222,7 @@
     <string name="reboot_to_update_prepare" msgid="6978842143587422365">"جارٍ الإعداد للتحديث…"</string>
     <string name="reboot_to_update_package" msgid="4644104795527534811">"جارٍ معالجة حزمة التحديث…"</string>
     <string name="reboot_to_update_reboot" msgid="4474726009984452312">"جارٍ إعادة التشغيل…"</string>
-    <string name="reboot_to_reset_title" msgid="2226229680017882787">"إعادة الضبط بحسب بيانات المصنع"</string>
+    <string name="reboot_to_reset_title" msgid="2226229680017882787">"إعادة الضبط على الإعدادات الأصلية"</string>
     <string name="reboot_to_reset_message" msgid="3347690497972074356">"جارٍ إعادة التشغيل…"</string>
     <string name="shutdown_progress" msgid="5017145516412657345">"جارٍ إيقاف التشغيل..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="2872769463279602432">"سيتم إيقاف تشغيل الجهاز اللوحي."</string>
@@ -299,8 +303,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"الوصول تقويمك"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"‏إرسال رسائل قصيرة SMS وعرضها"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"الملفات والوسائط"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"الوصول إلى الصور والوسائط والملفات على جهازك"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"الميكروفون"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"تسجيل الصوت"</string>
@@ -317,7 +320,7 @@
     <string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"استرداد محتوى النافذة"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"فحص محتوى نافذة يتم التفاعل معها"</string>
     <string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"تشغيل الاستكشاف باللمس"</string>
-    <string name="capability_desc_canRequestTouchExploration" msgid="4394677060796752976">"سيتم نطق العناصر التي تم النقر عليها بصوت عال ويمكن استكشاف الشاشة باستخدام الإيماءات."</string>
+    <string name="capability_desc_canRequestTouchExploration" msgid="4394677060796752976">"سيتم قول العناصر التي تم النقر عليها بصوت عال ويمكن استكشاف الشاشة باستخدام الإيماءات."</string>
     <string name="capability_title_canRequestFilterKeyEvents" msgid="2772371671541753254">"ملاحظة النص الذي تكتبه"</string>
     <string name="capability_desc_canRequestFilterKeyEvents" msgid="2381315802405773092">"يتضمن بيانات شخصية مثل أرقام بطاقات الائتمان وكلمات المرور."</string>
     <string name="capability_title_canControlMagnification" msgid="7701572187333415795">"التحكم في تكبير الشاشة"</string>
@@ -326,10 +329,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"يمكن النقر والتمرير بسرعة والتصغير أو التكبير بإصبعين وتنفيذ إيماءات أخرى."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"إيماءات بصمات الإصبع"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"يمكن أن تلتقط الإيماءات التي تم تنفيذها على جهاز استشعار بصمات الإصبع في الجهاز."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"أخذ لقطة شاشة"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"يمكن أخذ لقطة شاشة."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"إيقاف شريط الحالة أو تعديله"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"للسماح للتطبيق بإيقاف شريط الحالة أو إضافة رموز نظام وإزالتها."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"العمل كشريط للحالة"</string>
@@ -606,7 +607,7 @@
     <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>
@@ -675,8 +676,8 @@
     <string name="policylab_forceLock" msgid="7360335502968476434">"قفل الشاشة"</string>
     <string name="policydesc_forceLock" msgid="1008844760853899693">"التحكّم في طريقة ووقت قفل الشاشة"</string>
     <string name="policylab_wipeData" msgid="1359485247727537311">"محو جميع البيانات"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"يمكنك محو بيانات الجهاز اللوحي بدون تحذير، وذلك عبر إجراء إعادة الضبط بحسب بيانات المصنع."</string>
-    <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"‏يمكنك محو بيانات جهاز Android TV بدون تحذير عن طريق تنفيذ إعادة الضبط بحسب بيانات المصنع."</string>
+    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"يمكنك محو بيانات الجهاز اللوحي بدون تحذير، وذلك عبر إجراء إعادة الضبط على الإعدادات الأصلية."</string>
+    <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"‏يمكنك محو بيانات جهاز Android TV بدون تحذير عن طريق تنفيذ إعادة الضبط على الإعدادات الأصلية."</string>
     <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"محو بيانات الهاتف بدون تحذير، وذلك من خلال إعادة ضبط البيانات على الإعدادات الأصلية"</string>
     <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"محو بيانات المستخدم"</string>
     <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"لمحو بيانات هذا المستخدم على هذا الجهاز اللوحي بدون تحذير."</string>
@@ -1700,10 +1701,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"لقد رسمت نقش فتح القفل بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%2$d</xliff:g> من المحاولات غير الناجحة الأخرى، ستُطالب بإلغاء تأمين الهاتف باستخدام حساب بريد إلكتروني لإلغاء تأمين الهاتف.\n\n أعد المحاولة خلال <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانية."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"إزالة"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"هل تريد رفع مستوى الصوت فوق المستوى الموصى به؟\n\nقد يضر سماع صوت عالٍ لفترات طويلة بسمعك."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"هل تريد استخدام اختصار \"سهولة الاستخدام\"؟"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"عند تشغيل الاختصار، يؤدي الضغط على زرّي مستوى الصوت لمدة 3 ثوانٍ إلى تفعيل ميزة \"سهولة الاستخدام\".\n\n ميزة \"سهولة الاستخدام\" الحالية:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n يمكنك تغيير الميزة من \"الإعدادات\" &gt; \"سهولة الاستخدام\"."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"فارغ"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"تعديل الاختصارات"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"إلغاء"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"إيقاف الاختصار"</string>
@@ -1932,7 +1934,7 @@
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"حدث"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"النوم"</string>
     <string name="muted_by" msgid="91464083490094950">"يعمل <xliff:g id="THIRD_PARTY">%1$s</xliff:g> على كتم بعض الأصوات."</string>
-    <string name="system_error_wipe_data" msgid="5910572292172208493">"حدثت مشكلة داخلية في جهازك، وقد لا يستقر وضعه حتى إجراء إعادة الضبط بحسب بيانات المصنع."</string>
+    <string name="system_error_wipe_data" msgid="5910572292172208493">"حدثت مشكلة داخلية في جهازك، وقد لا يستقر وضعه حتى إجراء إعادة الضبط على الإعدادات الأصلية."</string>
     <string name="system_error_manufacturer" msgid="703545241070116315">"حدثت مشكلة داخلية في جهازك. يمكنك الاتصال بالمصنِّع للحصول على تفاصيل."</string>
     <string name="stk_cc_ussd_to_dial" msgid="3139884150741157610">"‏تم تغيير طلب USSD إلى مكالمة عادية."</string>
     <string name="stk_cc_ussd_to_ss" msgid="4826846653052609738">"‏تم تغيير طلب USSD إلى طلب SS."</string>
@@ -1978,13 +1980,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"التطبيق غير متاح"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"التطبيق <xliff:g id="APP_NAME_0">%1$s</xliff:g> غير متاح الآن، وهو مُدار بواسطة <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"مزيد من المعلومات"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"تفعيل الملف الشخصي للعمل؟"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"سيتم تفعيل تطبيقات العمل التي تستخدمها والإشعارات والبيانات وغيرها من ميزات الملف الشخصي للعمل"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"تشغيل"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"‏تمّ إنشاء هذا التطبيق لإصدار قديم من Android وقد لا يعمل بشكل صحيح. جرِّب البحث عن تحديثات أو الاتصال بمطوّر البرامج."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"البحث عن تحديث"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"لديك رسائل جديدة"</string>
@@ -2099,14 +2099,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"قد تنفد طاقة البطارية قبل الشحن المعتاد"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"تم تفعيل \"توفير شحن البطارية\" لإطالة عمرها."</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"توفير شحن البطارية"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"تم تفعيل ميزة \"توفير شحن البطارية\""</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"تم شحن الهاتف بدرجة كافية وتفعيل الميزات مرة أخرى"</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"تم شحن الجهاز اللوحي بدرجة كافية وتفعيل الميزات مرة أخرى"</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"تم شحن الجهاز بدرجة كافية وتفعيل الميزات مرة أخرى"</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"مجلّد"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"‏تطبيق Android"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"ملف"</string>
@@ -2125,6 +2121,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"جدول بيانات: <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"عرض تقديمي"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"عرض تقديمي: <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"سيظل البلوتوث مفعَّلاً أثناء تفعيل \"وضع الطائرة\"."</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"جارٍ التحميل"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="zero"><xliff:g id="FILE_NAME_2">%s</xliff:g> و<xliff:g id="COUNT_3">%d</xliff:g> ملف</item>
@@ -2146,5 +2143,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"تبديل \"تقسيم الشاشة\""</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"شاشة القفل"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"لقطة شاشة"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"شريط الشرح لتطبيق <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"تم وضع <xliff:g id="PACKAGE_NAME">%1$s</xliff:g> في الحزمة \"محظورة\"."</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index faa99a2..73e32b8 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"আপোনাৰ ডিভাইচৰ ডেটা মচা হ\'ব"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"এই প্ৰশাসক এপটো ব্যৱহাৰ কৰিব নোৱাৰি। এতিয়া আপোনাৰ ডিভাইচটোৰ ডেটা মচা হ\'ব।\n\nআপোনাৰ কিবা প্ৰশ্ন থাকিলে আপোনাৰ প্ৰতিষ্ঠানৰ প্ৰশাসকৰ সৈতে যোগাযোগ কৰক।"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"প্ৰিণ্ট কৰা কাৰ্য <xliff:g id="OWNER_APP">%s</xliff:g>এ অক্ষম কৰি ৰাখিছে।"</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"মই"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"টে\'বলেটৰ বিকল্পসমূহ"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TVৰ বিকল্পসমূহ"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"আপোনাৰ কেলেণ্ডাৰ ব্যৱহাৰ কৰিব পাৰে"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"এছএমএছ"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"এছএমএছ বার্তা পঠিয়াব আৰু চাব পাৰে"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"ফাইল আৰু মিডিয়াবোৰ"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"আপোনাৰ ডিভাইচৰ ফট\', মিডিয়া আৰু ফাইলসমূহ ব্যৱহাৰ কৰিব পাৰে"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"মাইক্ৰ\'ফ\'ন"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"অডিঅ\' ৰেকর্ড কৰিব পাৰে"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"টেপ কৰা, ছোৱাইপ কৰা, পিঞ্চ কৰা আৰু আঙুলিৰ স্পৰ্শেৰে নিৰ্দেশ কৰা অন্যান্য কাৰ্যসমূহ কৰিব পাৰে।"</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"ফিংগাৰপ্ৰিণ্ট নিৰ্দেশ"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ডিভাইচটোৰ ফিংগাৰপ্ৰিণ্ট ছেন্সৰত দিয়া নিৰ্দেশ বুজিব পাৰে।"</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"স্ক্ৰীনশ্বট লওক"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ডিছপ্লে’খনৰ এটা স্ক্ৰীনশ্বট ল\'ব পাৰে।"</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"স্থিতি দণ্ড অক্ষম কৰক বা সলনি কৰক"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"স্থিতি দণ্ড অক্ষম কৰিবলৈ বা ছিষ্টেম আইকন আঁতৰাবলৈ এপটোক অনুমতি দিয়ে।"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"স্থিতি দণ্ড হ\'ব পাৰে"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"আপুনি আপোনাৰ ল\'ক খোলাৰ আৰ্হিটো <xliff:g id="NUMBER_0">%1$d</xliff:g>বাৰ ভুলকৈ আঁকিছে। <xliff:g id="NUMBER_1">%2$d</xliff:g>তকৈ বেছি বাৰ ভুল আৰ্হি আঁকিলে আপোনাৰ ফ\'নটো কোনো একাউণ্টৰ জৰিয়তে আনলক কৰিবলৈ কোৱা হ\'ব।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ছেকেণ্ডৰ পিছত আকৌ চেষ্টা কৰক।"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"আঁতৰাওক"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"অনুমোদিত স্তৰতকৈ ওপৰলৈ ভলিউম বঢ়াব নেকি?\n\nদীৰ্ঘ সময়ৰ বাবে উচ্চ ভলিউমত শুনাৰ ফলত শ্ৰৱণ ক্ষমতাৰ ক্ষতি হ\'ব পাৰে।"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"দিব্যাংগসকলৰ সুবিধাৰ শ্বৰ্টকাট ব্যৱহাৰ কৰেনে?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"শ্বৰ্টকাট অন হৈ থকাৰ সময়ত দুয়োটা ভলিউম বুটামত ৩ ছেকেণ্ডৰ বাবে ছাপ দি থাকিলে দিব্যাংগসকলৰ বাবে থকা সুবিধা এটা আৰম্ভ হ\'ব। \n\n চলিত দিব্যাংগসকলৰ সুবিধা:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n আপুনি এই সুবিধাটো ছেটিংসমূহ &gt; দিব্যাংগসকলৰ বাবে সুবিধা-লৈ গৈ সলনি কৰিব পাৰে।"</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"খালী কৰক"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"শ্বৰ্টকাটসমূহ সম্পাদনা কৰক"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"বাতিল কৰক"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"শ্বৰ্টকাট অফ কৰক"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"এপটো নাই"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"এই মুহূৰ্তত <xliff:g id="APP_NAME_0">%1$s</xliff:g> উপলব্ধ নহয়। ইয়াক <xliff:g id="APP_NAME_1">%2$s</xliff:g>এ পৰিচালনা কৰে।"</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"অধিক জানক"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"কৰ্মস্থানৰ প্ৰ\'ফাইল অন কৰিবনে?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"আপোনাৰ কৰ্মস্থানৰ এপসমূহ, জাননীসমূহ, ডেটা আৰু কৰ্মস্থানৰ প্ৰ\'ফাইলৰ অইন সুবিধাসমূহ অন কৰা হ\'ব"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"অন কৰক"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"এই এপটো Androidৰ এটা পুৰণা সংস্কৰণৰ বাবে প্ৰস্তুত কৰা হৈছিল, আৰু ই বিচৰাধৰণে কাম নকৰিবও পাৰে। ইয়াৰ আপডে’ট আছে নেকি চাওক, বা বিকাশকৰ্তাৰ সৈতে যোগাযোগ কৰক।"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"আপডে’ট আছে নেকি চাওক"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"আপুনি নতুন বার্তা লাভ কৰিছে"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"চ্চাৰ্জ কৰাৰ সচৰাচৰ সময়ৰ আগতেই বেটাৰি শেষ হ’ব পাৰে"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"বেটাৰিৰ খৰচ কমাবলৈ বেটাৰি সঞ্চয়কাৰী অন কৰা হৈছে"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"বেটাৰি সঞ্চয়কাৰী"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"বেটাৰি সঞ্চয়কাৰী অফ কৰা হ’ল"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ফ\'নটোত পর্যাপ্ত পৰিমাণে চার্জ আছে। সুবিধাবোৰ আৰু সীমাবদ্ধ কৰা নাই।"</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"টেবলেটটোত পর্যাপ্ত পৰিমাণে চার্জ আছে। সুবিধাবোৰ আৰু সীমাবদ্ধ কৰা নাই।"</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"ডিভাইচটোত পর্যাপ্ত পৰিমাণে চার্জ আছে। সুবিধাবোৰ আৰু সীমাবদ্ধ কৰা নাই।"</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"ফ’ল্ডাৰ"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android এপ্লিকেশ্বন"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"ফাইল"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> স্প্ৰেডশ্বীট"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"উপস্থাপন"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> উপস্থাপন"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"এয়াৰপ্লেন ম\'ডৰ সময়ত ব্লুটুথ অন হৈ থাকিব"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"ল’ড হৈ আছে"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g>টা ফাইল</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"বিভাজিত স্ক্ৰীন ট’গল কৰক"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"লক স্ক্ৰীন"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"স্ক্ৰীণশ্বট"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ কেপশ্বন বাৰ।"</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g>ক সীমাবদ্ধ বাকেটটোত ৰখা হৈছে"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index d97b73f..c894c29 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Cihazınız təmizlənəcəkdir"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Admin tətbiqini istifadə etmək mümkün deyil. Cihaz indi təmizlənəcək.\n\nSualınız varsa, təşkilatın admini ilə əlaqə saxlayın."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Çap <xliff:g id="OWNER_APP">%s</xliff:g> tərəfindən deaktiv edildi."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Mən"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Planşet seçimləri"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV seçimləri"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"təqvimə daxil olun"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"göndərin və SMS mesajlarına baxın"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Fayllar və media"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"cihazınızda foto, media və fayllara daxil olun"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"səsi qeydə alın"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Digər jestlərə tıklaya, sürüşdürə və əməliyyat apara bilərsiniz."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Barmaq izi işarələri"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Cihazların barmaq izi sensorunda olan işarələri əldə edə bilər."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ekran şəkli çəkin"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Ekran şəkli çəkilə bilər."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"status panelini deaktivləşdir və ya dəyişdir"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Tətbiqə status panelini deaktiv etməyə və ya sistem ikonalarını əlavə etmək və ya silmək imkanı verir."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"status paneli edin"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Siz artıq modeli <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış daxil etmisiniz.<xliff:g id="NUMBER_1">%2$d</xliff:g> dəfə də yanlış daxil etsəniz, telefonun kilidinin açılması üçün elektron poçt ünvanınız tələb olunacaq.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> saniyə ərzində yenidən cəhd edin."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" - "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Yığışdır"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Səsin həcmi tövsiyə olunan səviyyədən artıq olsun?\n\nYüksək səsi uzun zaman dinləmək eşitmə qabiliyyətinizə zərər vura bilər."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Əlçatımlılıq Qısayolu istifadə edilsin?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Qısayol aktiv olduqda hər iki səs düyməsinə 3 saniyə basıb saxlamaqla əlçatımlılıq funksiyası işə başlayacaq.\n\n Cari əlçatımlılıq funksiyası:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Funksiyanı Ayarlar və Əçatımlılıq bölməsində dəyişə bilərsiniz."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Boşaldın"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Qısayolları redaktə edin"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Ləğv edin"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Qısayolu Deaktiv edin"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Tətbiq əlçatmazdır"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> hazırda əlçatan deyil. Bunu <xliff:g id="APP_NAME_1">%2$s</xliff:g> idarə edir."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Ətraflı məlumat"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"İş profili aktiv edilsin?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"İş tətbiqləri, bildirişləri, data və digər iş profili funksiyaları aktiv ediləcək"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Aktivləşdirin"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Bu tətbiq köhnə Android versiyası üçün hazırlanıb və düzgün işləməyə bilər. Güncəlləməni yoxlayın və ya developer ilə əlaqə saxlayın."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Güncəlləməni yoxlayın"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Yeni mesajlarınız var"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Batareya həmişəki vaxtdan əvvəl bitə bilər"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Enerjiyə Qənaət rejimi batareya istifadəsinin müddətini artırmaq üçün aktiv edilir"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Enerjiyə qənaət"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Enerjiyə qənaət deaktivdir"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefonun kifayət qədər enerjisi var. Funksiyalar artıq məhdud deyil."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Planşetin kifayət qədər enerjisi var. Funksiyalar artıq məhdud deyil."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Cihazın kifayət qədər enerjisi var. Funksiyalar artıq məhdud deyil."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"Qovluq"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android tətbiqi"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Fayl"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> cədvəl"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Təqdimat"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> təqdimat"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth təyyarə rejimində aktiv olacaq"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Yüklənir"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> fayl</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Bölünmüş Ekrana keçid"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Kilid Ekranı"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Ekran şəkli"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> başlıq paneli."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> MƏHDUDLAŞDIRILMIŞ səbətinə yerləşdirilib"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index c37e2b4..909c315 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -196,6 +196,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Uređaj će biti obrisan"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Ne možete da koristite ovu aplikaciju za administratore. Uređaj će sada biti obrisan.\n\nAko imate pitanja, kontaktirajte administratora organizacije."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Štampanje je onemogućila aplikacija <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Ja"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opcije za tablet"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Opcije Android TV-a"</string>
@@ -1631,10 +1635,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Nacrtali ste šablon za otključavanje netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Posle još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja, od vas će biti zatraženo da otključate telefon pomoću naloga e-pošte.\n\nProbajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunde/i."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Ukloni"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Želite da pojačate zvuk iznad preporučenog nivoa?\n\nSlušanje glasne muzike duže vreme može da vam ošteti sluh."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Želite li da koristite prečicu za pristupačnost?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Kada je prečica uključena, pritisnite oba dugmeta za jačinu zvuka da biste pokrenuli funkciju pristupačnosti.\n\n Aktuelna funkcija pristupačnosti:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Možete da promenite funkciju u odeljku Podešavanja &gt; Pristupačnost."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Prazno"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Izmenite prečice"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Otkaži"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Isključi prečicu"</string>
@@ -1879,11 +1884,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Aplikacija nije dostupna"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"Aplikacija <xliff:g id="APP_NAME_0">%1$s</xliff:g> trenutno nije dostupna. <xliff:g id="APP_NAME_1">%2$s</xliff:g> upravlja dostupnošću."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Saznajte više"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Da uključimo profil za Work?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Uključiće se poslovne aplikacije, obaveštenja, podaci i druge funkcije profila za Work"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Uključi"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"Aplikacija nije dostupna"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> trenutno nije dostupna."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ova aplikacija je napravljena za stariju verziju Android-a, pa možda neće raditi ispravno. Potražite ažuriranja ili kontaktirajte programera."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Potraži ažuriranje"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Imate nove poruke"</string>
@@ -2017,6 +2022,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> tabela"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Prezentacija"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> prezentacija"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth ostaje uključen tokom režima rada u avionu"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Učitava se"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> i još <xliff:g id="COUNT_3">%d</xliff:g> datoteka</item>
@@ -2035,5 +2041,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Uključite/isključite podeljeni ekran"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Zaključani ekran"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Snimak ekrana"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Traka sa naslovima aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Paket <xliff:g id="PACKAGE_NAME">%1$s</xliff:g> je dodat u segment OGRANIČENO"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 855ce25..19dcf92 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -198,6 +198,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Даныя вашай прылады будуць сцерты"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Немагчыма выкарыстоўваць праграму адміністравання. Звесткі на вашай прыладзе будуць выдалены.\n\nКалі ў вас ёсць пытанні, звярніцеся да адміністратара арганізацыі."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Друк адключаны ўладальнікам праграмы <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Я"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Параметры планшэта"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Параметры Android TV"</string>
@@ -293,8 +297,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"атрымліваць доступ да вашага календара"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"адпраўляць і праглядаць SMS-паведамленні"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Файлы і мультымедыя"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"атрымліваць доступ да фатаграфій, медыяфайлаў і файлаў на вашай прыладзе"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Мікрафон"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"запісваць аўдыя"</string>
@@ -320,10 +323,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Можна кранаць, праводзіць пальцам, маштабаваць шчыпком, а таксама выконваць іншыя жэсты."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Жэсты на сканеры адбіткаў пальцаў"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Можа распазнаваць жэсты на сканеры адбіткаў пальцаў прылады."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Зрабіць здымак экрана"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Можна зрабіць здымак экрана."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"адключаць ці змяняць радок стану"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Дазваляе прыкладанням адключаць радок стану або дадаваць і выдаляць сістэмныя значкі."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"быць панэллю стану"</string>
@@ -1656,10 +1657,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Вы няправільна ўвялі графічны ключ разблакiроўкi пэўную колькасць разоў: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Пасля яшчэ некалькiх няўдалых спроб (<xliff:g id="NUMBER_1">%2$d</xliff:g>) вам будзе прапанавана разблакiраваць тэлефон, увайшоўшы ў Google.\n\n Паўтарыце спробу праз <xliff:g id="NUMBER_2">%3$d</xliff:g> с."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Выдалiць"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Павялiчыць гук вышэй рэкамендаванага ўзроўню?\n\nДоўгае праслухоўванне музыкi на вялiкай гучнасцi можа пашкодзiць ваш слых."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Выкарыстоўваць камбінацыю хуткага доступу для спецыяльных магчымасцей?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Калі камбінацыя хуткага доступу ўключана, вы можаце націснуць абедзве кнопкі гучнасці і ўтрымліваць іх 3 секунды, каб уключыць функцыю спецыяльных магчымасцей.\n\n Бягучая функцыя спецыяльных магчымасцей:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Вы можаце змяніць гэту функцыю ў меню \"Налады &gt; Спецыяльныя магчымасці\"."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Пуста"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Змяніць ярлыкі"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Скасаваць"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Дэактываваць камбінацыю хуткага доступу"</string>
@@ -1914,13 +1916,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Праграма недаступная"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"Праграма \"<xliff:g id="APP_NAME_0">%1$s</xliff:g>\" цяпер недаступная. Яна кіруецца праграмай \"<xliff:g id="APP_NAME_1">%2$s</xliff:g>\"."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Даведацца больш"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Уключыць працоўны профіль?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Будуць уключаны вашы рабочыя праграмы, апавяшчэнні, даныя і іншыя функцыі працоўнага профілю"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Уключыць"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Гэта праграма была створана для больш старой версіі Android і можа не працаваць належным чынам. Праверце наяўнасць абнаўленняў або звярніцеся да распрацоўшчыка."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Праверыць на наяўнасць абнаўленняў"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"У вас ёсць новыя паведамленні"</string>
@@ -2033,14 +2033,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Акумулятар можа разрадзіцца хутчэй, чым прыйдзе час звычайнай зарадкі"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Каб павялічыць тэрмін работы акумулятара, уключаны рэжым эканоміі зараду"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Эканомія зараду"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Рэжым эканоміі зараду выключаны"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"У тэлефона дастатковы ўзровень зараду. Функцыі больш не абмежаваны."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"У планшэта дастатковы ўзровень зараду. Функцыі больш не абмежаваны."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"У прылады дастатковы ўзровень зараду. Функцыі больш не абмежаваны."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"Папка"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Праграма Android"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Файл"</string>
@@ -2059,6 +2055,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"Табліца <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Прэзентацыя"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Прэзентацыя <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth застанецца ўключаным у рэжыме палёту"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Загрузка"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> файл</item>
@@ -2078,5 +2075,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Пераключальнік падзеленага экрана"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Экран блакіроўкі"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Здымак экрана"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Панэль субцітраў праграмы \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Пакет \"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g>\" дададзены ў АБМЕЖАВАНУЮ групу"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 40e20d3..8a68766 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Данните на устройството ви ще бъдат изтрити"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Приложението за администриране не може да се използва. Сега данните на устройството ви ще бъдат изтрити.\n\nАко имате въпроси, свържете се с администратора на организацията си."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Отпечатването е деактивиранo от <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Аз"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Опции за таблета"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Опции за Android TV"</string>
@@ -1609,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Начертахте неправилно фигурата си за отключване <xliff:g id="NUMBER_0">%1$d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни опита ще бъдете помолени да отключите телефона посредством имейл адрес.\n\n Опитайте отново след <xliff:g id="NUMBER_2">%3$d</xliff:g> секунди."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Премахване"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Да се увеличи ли силата на звука над препоръчителното ниво?\n\nПродължителното слушане при висока сила на звука може да увреди слуха ви."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Искате ли да използвате пряк път към функцията за достъпност?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Когато прекият път е включен, можете да стартирате дадена функция за достъпност, като натиснете двата бутона за промяна на силата на звука и ги задържите 3 секунди.\n\n Текущата функция за достъпност е:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Можете да промените функцията от „Настройки“ &gt; „Достъпност“."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Празно"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Редактиране на преките пътища"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Отказ"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Изключване на прекия път"</string>
@@ -1847,11 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Няма достъп до приложението"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"В момента няма достъп до <xliff:g id="APP_NAME_0">%1$s</xliff:g>. Това се управлява от <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Научете повече"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Вкл. на служ. потр. профил?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Служебните ви приложения, известия и данни, както и другите функции на служебния потребителски профил ще бъдат включени"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Включване"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"Приложението не е достъпно"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"В момента няма достъп до <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Това приложение бе създадено за по-стара версия на Android и може да не работи правилно. Опитайте да проверите за актуализации или се свържете с програмиста."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Проверка за актуализация"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Имате нови съобщения"</string>
@@ -1984,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"Електронна таблица във формат <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Презентация"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Презентация във формат <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Функцията за Bluetooth ще остане включена по време на самолетния режим"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Зарежда се"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> файла</item>
@@ -2001,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Превключване на разделения екран"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Заключен екран"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Екранна снимка"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Лента за надписи на <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Пакетът <xliff:g id="PACKAGE_NAME">%1$s</xliff:g> е поставен в ОГРАНИЧЕНИЯ контейнер"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 3164bb6..9ca383d 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"আপনার ডিভাইসটি মুছে ফেলা হবে"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"অ্যাডমিন অ্যাপটি ব্যবহার করা যাবে না। আপনার ডিভাইসে থাকা সবকিছু এখন মুছে ফেলা হবে।\n\nকোনও প্রশ্ন থাকলে আপনার প্রতিষ্ঠানের অ্যাডমিনের সাথে যোগাযোগ করুন।"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> প্রিন্টিং বন্ধ রেখেছে।"</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"আমাকে"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"ট্যাবলেট বিকল্পগুলি"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV-র বিকল্প"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"আপনার ক্যালেন্ডারে অ্যাক্সেস"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"এসএমএসগুলি পাঠাতে এবং দেখতে"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"ফাইল এবং মিডিয়া"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"আপনার ডিভাইসে ফটো, মিডিয়া এবং ফাইলগুলিতে অ্যাক্সেস"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"মাইক্রোফোন"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"অডিও রেকর্ড"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"আলতো চাপ দেওয়া, সোয়াইপ, পিঞ্চ করা এবং অন্যান্য ইঙ্গিতের কাজগুলি সম্পাদন করতে পারবেন৷"</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"আঙ্গুলের ছাপ সেন্সরের উপর করা জেসচার"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ডিভাইসের আঙ্গুলের ছাপের সেন্সরের উপরে ইঙ্গিত করলে বুঝতে পারে।"</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"স্ক্রিনশট নিন"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ডিসপ্লের একটি স্ক্রিনশট নিতে পারেন।"</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"স্ট্যাটাস বার নিষ্ক্রিয় অথবা সংশোধন করে"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"অ্যাপ্লিকেশনকে স্ট্যাটাস বার অক্ষম করতে এবং সিস্টেম আইকনগুলি সরাতে দেয়৷"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"স্থিতি দন্ডে থাকুন"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"আপনি আপনার আনলকের প্যাটার্ন আঁকার ক্ষেত্রে <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল করেছেন৷ আর <xliff:g id="NUMBER_1">%2$d</xliff:g> বার অসফল প্রচেষ্টা করা হলে আপনাকে একটি ইমেল অ্যাকাউন্ট মারফত আপনার ফোন আনলক করতে বলা হবে৷\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন৷"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"সরান"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"প্রস্তাবিত স্তরের চেয়ে বেশি উঁচুতে ভলিউম বাড়াবেন?\n\nউঁচু ভলিউমে বেশি সময় ধরে কিছু শুনলে আপনার শ্রবনশক্তির ক্ষতি হতে পারে।"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"অ্যাক্সেসযোগ্যতা শর্টকাট ব্যবহার করবেন?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"শর্টকাটটি চালু থাকলে দুটি ভলিউম বোতাম একসাথে ৩ সেকেন্ড টিপে ধরে রাখলে একটি অ্যাকসেসিবিলিটি বৈশিষ্ট্য চালু হবে।\n\n বর্তমান অ্যাকসেসিবিলিটি বৈশিষ্ট্য:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n আপনি এই বৈশিষ্ট্যটি সেটিংস &gt; অ্যাকসেসিবিলিটিতে গিয়ে পরিবর্তন করতে পারবেন।"</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"খালি"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"শর্টকাট এডিট করুন"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"বাতিল করুন"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"শর্টকাট বন্ধ করুন"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"অ্যাপটি উপলভ্য নয়"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> এখন উপলভ্য নয়। এই অ্যাপটিকে <xliff:g id="APP_NAME_1">%2$s</xliff:g> অ্যাপ ম্যানেজ করে।"</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"আরও জানুন"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"কাজের প্রোফাইল চালু করবেন?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"আপনার কাজের অ্যাপ, বিজ্ঞপ্তি, ডেটা এবং কাজের প্রোফাইলের অন্যান্য বৈশিষ্ট্য চালু করা হবে"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"চালু করুন"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"এই অ্যাপটি Android এর একটি পুরনো ভার্সনের জন্য তৈরি করা হয়েছিল, তাই এখানে সেটি ঠিকমতো কাজ নাও করতে পারে। আপডেট পাওয়া যাচ্ছে কিনা দেখুন বা ডেভেলপারের সাথে যোগাযোগ করুন।"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"আপডেট পাওয়া যাচ্ছে কিনা দেখুন"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"আপনার নতুন মেসেজ আছে"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"সাধারণত যখন চার্জ দেন, তার আগে চার্জ শেষ হয়ে যেতে পারে"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"ডিভাইস বেশিক্ষণ চালু রাখতে ব্যাটারি সেভার চালু করা হয়েছে"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ব্যাটারি সেভার"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"ব্যাটারি সেভার বন্ধ করা আছে"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ফোনের ব্যাটারিতে যথেষ্ট চার্জ আছে। ফিচারগুলির উপর আর বিধিনিষেধ নেই।"</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"ট্যাবলেটের ব্যাটারিতে যথেষ্ট চার্জ আছে। ফিচারগুলির উপর আর বিধিনিষেধ নেই।"</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"ডিভাইসের ব্যাটারিতে যথেষ্ট পরিমাণে চার্জ আছে। ফিচারগুলির উপর আর বিধিনিষেধ নেই।"</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"ফোল্ডার"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android অ্যাপ্লিকেশন"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"ফাইল"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> স্প্রেডশীট"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"উপস্থাপনা"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> উপস্থাপনা"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"ব্লুটুথ বিমান মোডে চালু থাকবে"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"লোড হচ্ছে"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> এবং আরও <xliff:g id="COUNT_3">%d</xliff:g>টি ফাইল</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"স্প্লিট স্ক্রিন টগল করুন"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"লক স্ক্রিন"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"স্ক্রিনশট"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এর ক্যাপশন বার।"</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> সীমাবদ্ধ গ্রুপে অন্তর্ভুক্ত করা হয়েছে"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index e0a4886..5f83aa4 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -196,6 +196,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Uređaj će biti izbrisan"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Nije moguće koristiti aplikaciju administratora. Potpuno će se izbrisati podaci na vašem uređaju.\n\nAko imate pitanja, obratite se administratoru svoje organizacije."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Štampanje je onemogućila aplikacija <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Ja"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opcije tableta"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Opcije Android TV uređaja"</string>
@@ -1633,10 +1637,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Pogrešno ste nacrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Ako napravite još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, od vas će se tražiti da otključate telefon pomoću e-pošte. \n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Ukloni"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Želite li pojačati zvuk iznad preporučenog nivoa?\n\nDužim slušanjem glasnog zvuka možete oštetiti sluh."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Želite li koristiti Prečicu za pristupačnost?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Kada je prečica uključena, pritiskom na oba dugmeta za podešavanje jačine zvuka u trajanju od 3 sekunde pokrenut će se funkcija za pristupačnost.\n\n Trenutna funkcija za pristupačnost je:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Funkciju možete promijeniti ako odete u Postavke &gt; Pristupačnost."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Prazno"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Uredi prečice"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Otkaži"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Isključi prečicu"</string>
@@ -1881,11 +1886,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Aplikacija nije dostupna"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"Aplikacija <xliff:g id="APP_NAME_0">%1$s</xliff:g> trenutno nije dostupna. Ovim upravlja aplikacija <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Saznajte više"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Uključiti radni profil?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Uključit će se poslovne aplikacije, obavještenja, podaci i druge funkcije radnog profila"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Uključi"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"Aplikacija nije dostupna"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> trenutno nije dostupna."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ova aplikacija je pravljena za stariju verziju Androida i možda neće ispravno raditi. Provjerite jesu li dostupna ažuriranja ili kontaktirajte programera."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Provjeri je li dostupno ažuriranje"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Imate nove poruke"</string>
@@ -2019,6 +2024,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> tabela"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Prezentacija"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> prezentacija"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth će ostati uključen i u načinu rada u avionu"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Učitavanje"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> fajl</item>
@@ -2037,5 +2043,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Uključi/isključi podijeljeni ekran"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Zaključavanje ekrana"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Snimak ekrana"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Traka za natpis aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Paket <xliff:g id="PACKAGE_NAME">%1$s</xliff:g> je stavljen u odjeljak OGRANIČENO"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 93a60d8..930065b 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"El contingut del dispositiu s\'esborrarà"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"No es pot utilitzar l\'aplicació d\'administració. S\'esborraran les dades del dispositiu.\n\nSi tens cap dubte, contacta amb l\'administrador de la teva organització."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ha desactivat la impressió."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Mi"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opcions de la tauleta"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Opcions d\'Android TV"</string>
@@ -1609,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Has dibuixat el patró de desbloqueig <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, se\'t demanarà que desbloquegis el telèfon amb un compte de correu electrònic.\n\n Torna-ho a provar d\'aquí a <xliff:g id="NUMBER_2">%3$d</xliff:g> segons."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Elimina"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vols apujar el volum per sobre del nivell recomanat?\n\nSi escoltes música a un volum alt durant períodes llargs, pots danyar-te l\'oïda."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Vols fer servir la drecera d\'accessibilitat?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Si la drecera està activada, prem els dos botons de volum durant 3 segons, per iniciar una funció d\'accessibilitat.\n\n Funció d\'accessibilitat actual:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Pots canviar la funció a Configuració &gt; Accessibilitat."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Buida"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edita les dreceres"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Cancel·la"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Desactiva la drecera"</string>
@@ -1847,11 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"L\'aplicació no està disponible"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> no està disponible en aquests moments. Aquesta opció es gestiona a <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Més informació"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Activar el perfil professional?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"S\'activaran les teves aplicacions per a la feina, les notificacions, les dades i altres funcions del perfil professional"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Activa"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"L\'aplicació no està disponible"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"Ara mateix, <xliff:g id="APP_NAME">%1$s</xliff:g> no està disponible."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Aquesta aplicació es va crear per a una versió antiga d\'Android i pot ser que no funcioni correctament. Prova de cercar actualitzacions o contacta amb el desenvolupador."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Cerca actualitzacions"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Tens missatges nous"</string>
@@ -1984,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"Full de càlcul <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Presentació"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Presentació <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"El Bluetooth es mantindrà activat durant el mode d\'avió"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"S\'està carregant"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> i <xliff:g id="COUNT_3">%d</xliff:g> fitxers més</item>
@@ -2001,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Commuta Pantalla dividida"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Pantalla de bloqueig"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Captura de pantalla"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Barra de títol de l\'aplicació <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> s\'ha transferit al segment RESTRINGIT"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 81b1ebb..2c017dd 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -198,6 +198,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Zařízení bude vymazáno"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Aplikaci pro správu nelze použít. Zařízení teď bude vymazáno.\n\nV případě dotazů vám pomůže administrátor organizace."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Aplikace <xliff:g id="OWNER_APP">%s</xliff:g> tisk zakazuje."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Já"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Možnosti tabletu"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Možnosti zařízení Android TV"</string>
@@ -1653,10 +1657,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Již <xliff:g id="NUMBER_0">%1$d</xliff:g>krát jste nesprávně nakreslili své heslo odemknutí. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> dalších neúspěšných pokusech budete požádáni o odemčení telefonu pomocí e-mailového účtu.\n\n Zkuste to znovu za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Odebrat"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Zvýšit hlasitost nad doporučenou úroveň?\n\nDlouhodobý poslech hlasitého zvuku může poškodit sluch."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Použít zkratku přístupnosti?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Když je tato zkratka zapnutá, můžete funkci přístupnosti spustit tím, že na tři sekundy podržíte obě tlačítka hlasitosti.\n\n Aktuální funkce přístupnosti:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Funkci můžete změnit v Nastavení &gt; Přístupnost."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Prázdné"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Upravit zkratky"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Zrušit"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Vypnout zkratku"</string>
@@ -1911,11 +1916,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Aplikace není k dispozici"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"Aplikace <xliff:g id="APP_NAME_0">%1$s</xliff:g> momentálně není dostupná. Tato předvolba se spravuje v aplikaci <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Další informace"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Zapnout pracovní profil?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Vaše pracovní aplikace, oznámení, data a ostatní funkce pracovního účtu budou zapnuty"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Zapnout"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"Aplikace není k dispozici"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> v tuto chvíli není k dispozici."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Tato aplikace byla vytvořena pro starší verzi systému Android a nemusí fungovat správně. Zkuste vyhledat aktualizace, případně kontaktujte vývojáře."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Zkontrolovat aktualizace"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Máte nové zprávy"</string>
@@ -2050,6 +2055,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"Tabulka <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Prezentace"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Prezentace <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth v režimu Letadlo zůstane zapnuté"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Načítání"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="few"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> soubory</item>
@@ -2069,5 +2075,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Přepnout rozdělenou obrazovku"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Obrazovka uzamčení"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Snímek obrazovky"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Popisek aplikace <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Balíček <xliff:g id="PACKAGE_NAME">%1$s</xliff:g> byl vložen do sekce OMEZENO"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 4374b22..4ebea89 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Enheden slettes"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Administrationsappen kan ikke bruges. Enheden vil nu blive ryddet. \n\nKontakt din organisations administrator, hvis du har spørgsmål."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Udskrivning er deaktiveret af <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Mig"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Valgmuligheder for tabletcomputeren"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Valgmuligheder for Android TV"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"have adgang til din kalender"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"Sms"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"sende og se sms-beskeder"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Filer og medier"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"få adgang til billeder, medier og filer på din enhed"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"optage lyd"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Kan trykke, stryge, knibe sammen og udføre andre bevægelser."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Fingeraftryksbevægelser"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Kan registrere bevægelser, der foretages på enhedens fingeraftrykslæser."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Tag screenshot"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan tage et screenshot af skærmen."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"deaktivere eller redigere statuslinje"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Tillader, at appen kan deaktivere statusbjælken eller tilføje og fjerne systemikoner."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"vær statusbjælken"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter <xliff:g id="NUMBER_1">%2$d</xliff:g> yderligere mislykkede forsøg til vil du blive bedt om at låse din telefon op ved hjælp af en mailkonto.\n\n Prøv igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Fjern"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vil du skrue højere op end det anbefalede lydstyrkeniveau?\n\nDu kan skade hørelsen ved at lytte til meget høj musik over længere tid."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Vil du bruge genvejen til Hjælpefunktioner?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Når genvejen er slået til, kan du starte en hjælpefunktion ved at trykke på begge lydstyrkeknapper i tre sekunder.\n\n Nuværende hjælpefunktion:\n<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Du kan skifte funktion i Indstillinger &gt; Hjælpefunktioner."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Tom"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Rediger genveje"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Annuller"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Deaktiver genvej"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Appen er ikke tilgængelig"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> er ikke tilgængelig lige nu. Dette administreres af <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Få flere oplysninger"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Skal arbejdsprofilen slås til?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Dine arbejdsapps, notifikationer, data og andre funktioner til din arbejdsprofil deaktiveres"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Slå til"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Denne app er lavet til en ældre version af Android og fungerer muligvis ikke korrekt. Prøv at søge efter opdateringer, eller kontakt udvikleren."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Søg efter opdatering"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Du har nye beskeder"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Enheden løber muligvis tør for batteri, inden du normalt oplader den"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Batterisparefunktion er aktiveret for at forlænge batteritiden"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Batterisparefunktion"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Batterisparefunktion blev slået fra"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefonen har tilstrækkeligt batteri. Funktionerne er ikke længere begrænsede."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Tabletten har tilstrækkeligt batteri. Funktionerne er ikke længere begrænsede."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Enheden har tilstrækkeligt batteri. Funktionerne er ikke længere begrænsede."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"Mappe"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android-app"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Fil"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g>-regneark"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Præsentation"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g>-præsentation"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth forbliver aktiveret i flytilstand"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Indlæser"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> fil</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Slå Opdelt skærm til eller fra"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Låseskærm"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Screenshot"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Titellinje for <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> er blevet placeret i samlingen BEGRÆNSET"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 7804e9e..6fa0ac1 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Die Daten auf deinem Gerät werden gelöscht."</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Die Admin-App kann nicht verwendet werden. Die Daten auf deinem Gerät werden nun gelöscht.\n\nBitte wende dich bei Fragen an den Administrator deiner Organisation."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Drucken wurde von <xliff:g id="OWNER_APP">%s</xliff:g> deaktiviert."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Eigene"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tablet-Optionen"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV-Optionen"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"auf deinen Kalender zugreifen"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS senden und abrufen"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Dateien und Medien"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"auf Fotos, Medien und Dateien auf deinem Gerät zugreifen"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"Audio aufnehmen"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Tippen, Wischen, Zusammenziehen und andere Touch-Gesten möglich."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Fingerabdrucksensor-Gesten"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Erfasst Touch-Gesten auf dem Fingerabdrucksensor des Geräts."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Screenshot erstellen"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Es kann ein Screenshot des Displays erstellt werden."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"Statusleiste deaktivieren oder ändern"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Ermöglicht der App, die Statusleiste zu deaktivieren oder Systemsymbole hinzuzufügen oder zu entfernen"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"Statusleiste darstellen"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Du hast dein Entsperrungsmuster <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch gezeichnet. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wirst du aufgefordert, dein Telefon mithilfe eines E-Mail-Kontos zu entsperren.\n\n Versuche es in <xliff:g id="NUMBER_2">%3$d</xliff:g> Sekunden erneut."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Entfernen"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Lautstärke über den Schwellenwert anheben?\n\nWenn du über einen längeren Zeitraum Musik in hoher Lautstärke hörst, kann dies dein Gehör schädigen."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Verknüpfung für Bedienungshilfen verwenden?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Wenn die Verknüpfung aktiviert ist, kannst du die beiden Lautstärketasten drei Sekunden lang gedrückt halten, um eine Bedienungshilfe zu starten.\n\n Aktuelle Bedienungshilfe:\n<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Du kannst die Bedienungshilfe unter \"Einstellungen\" &gt; \"Bedienungshilfen\" ändern."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Leeren"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Verknüpfungen bearbeiten"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Abbrechen"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Verknüpfung deaktivieren"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"App nicht verfügbar"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ist momentan nicht verfügbar. Dies wird über die App \"<xliff:g id="APP_NAME_1">%2$s</xliff:g>\" verwaltet."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Weitere Informationen"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Arbeitsprofil aktivieren?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Deine geschäftlichen Apps, Benachrichtigungen, Daten und andere Funktionen des Arbeitsprofils werden aktiviert"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Aktivieren"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Diese App wurde für eine ältere Android-Version entwickelt und funktioniert möglicherweise nicht mehr richtig. Prüfe, ob Updates verfügbar sind oder kontaktiere den Entwickler."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Auf Updates prüfen"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Du hast neue Nachrichten"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Dein Akku könnte vor der gewöhnlichen Ladezeit leer sein"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Energiesparmodus aktiviert, um die Akkulaufzeit zu verlängern"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Energiesparmodus"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Energiesparmodus deaktiviert"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Das Smartphone ist ausreichend geladen. Es sind keine Funktionen mehr beschränkt."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Das Tablet ist ausreichend geladen. Es sind keine Funktionen mehr beschränkt."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Das Gerät ist ausreichend geladen. Es sind keine Funktionen mehr beschränkt."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"Ordner"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android-App"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Datei"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"Tabelle (<xliff:g id="EXTENSION">%1$s</xliff:g>)"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Präsentation"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Präsentation (<xliff:g id="EXTENSION">%1$s</xliff:g>)"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth bleibt im Flugmodus aktiviert"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Wird geladen"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> und <xliff:g id="COUNT_3">%d</xliff:g> Dateien</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"\"Bildschirm teilen\" ein-/ausschalten"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Sperrbildschirm"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Screenshot"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Untertitelleiste von <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> wurde in den BESCHRÄNKT-Bucket gelegt"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index a5977ee..81a16f2 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Η συσκευή σας θα διαγραφεί"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Δεν είναι δυνατή η χρήση της εφαρμογής διαχειριστή. Η συσκευή σας θα διαγραφεί.\n\nΕάν έχετε ερωτήσεις, επικοινωνήστε με τον διαχειριστή του οργανισμού σας."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Η εκτύπωση απενεργοποιήθηκε από τον χρήστη <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Για εμένα"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Επιλογές tablet"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Επιλογές Android TV"</string>
@@ -1609,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Σχεδιάσατε το μοτίβο ξεκλειδώματος εσφαλμένα <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές. Μετά από <xliff:g id="NUMBER_1">%2$d</xliff:g> ανεπιτυχείς προσπάθειες ακόμη, θα σας ζητηθεί να ξεκλειδώσετε το τηλέφωνό σας με τη χρήση ενός λογαριασμού ηλεκτρονικού ταχυδρομείου.\n\n Δοκιμάστε ξανά σε <xliff:g id="NUMBER_2">%3$d</xliff:g> δευτερόλεπτα."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Κατάργηση"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Αυξάνετε την ένταση ήχου πάνω από το επίπεδο ασφαλείας;\n\nΑν ακούτε μουσική σε υψηλή ένταση για μεγάλο χρονικό διάστημα ενδέχεται να προκληθεί βλάβη στην ακοή σας."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Να χρησιμοποιείται η συντόμευση προσβασιμότητας;"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Όταν η συντόμευση είναι ενεργοποιημένη, το πάτημα και των δύο κουμπιών έντασης ήχου για 3 δευτερόλεπτα θα ξεκινήσει μια λειτουργία προσβασιμότητας.\n\n Τρέχουσα λειτουργία προσβασιμότητας:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Μπορείτε να αλλάξετε τη λειτουργία από τις Ρυθμίσεις &gt; Προσβασιμότητα."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Κενό"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Επεξεργασία συντομεύσεων"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Άκυρο"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Απενεργοποίηση συντόμευσης"</string>
@@ -1847,11 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Η εφαρμογή δεν είναι διαθέσιμη"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"Η εφαρμογή <xliff:g id="APP_NAME_0">%1$s</xliff:g> δεν είναι διαθέσιμη αυτήν τη στιγμή. Η διαχείριση πραγματοποιείται από την εφαρμογή <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Μάθετε περισσότερα"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Ενεργοποίηση προφίλ εργασίας;"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Οι εφαρμογές, οι ειδοποιήσεις και τα δεδομένα εργασίας σας, καθώς και άλλες λειτουργίες του προφίλ εργασίας, θα ενεργοποιηθούν"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Ενεργοποίηση"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"Η εφαρμογή δεν είναι διαθέσιμη"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> δεν είναι διαθέσιμη αυτήν τη στιγμή."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Αυτή η εφαρμογή δημιουργήθηκε για παλαιότερη έκδοση του Android και μπορεί να μην λειτουργεί σωστά. Δοκιμάστε να ελέγξετε εάν υπάρχουν ενημερώσεις ή επικοινωνήστε με τον προγραμματιστή."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Έλεγχος για ενημέρωση"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Έχετε νέα μηνύματα"</string>
@@ -1984,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"Υπολογιστικό φύλλο <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Παρουσίαση"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Παρουσίαση <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Το Bluetooth θα παραμείνει ενεργό κατά τη λειτουργία πτήσης."</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Φόρτωση"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> αρχεία</item>
@@ -2001,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Εναλλαγή διαχωρισμού οθόνης"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Οθόνη κλειδώματος"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Στιγμιότυπο οθόνης"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Γραμμή υποτίτλων για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Το πακέτο <xliff:g id="PACKAGE_NAME">%1$s</xliff:g> τοποθετήθηκε στον κάδο ΠΕΡΙΟΡΙΣΜΕΝΗΣ ΠΡΟΣΒΑΣΗΣ."</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index da89793..87e0c90 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Your device will be erased"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"The admin app can\'t be used. Your device will now be erased.\n\nIf you have questions, contact your organisation\'s admin."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Printing disabled by <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Me"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tablet options"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV options"</string>
@@ -1609,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remove"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Raise volume above recommended level?\n\nListening at high volume for long periods may damage your hearing."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Use Accessibility Shortcut?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"When the shortcut is on, pressing both volume buttons for 3 seconds will start an accessibility feature.\n\n Current accessibility feature:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n You can change the feature in Settings &gt; Accessibility."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Empty"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit shortcuts"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Cancel"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Turn off Shortcut"</string>
@@ -1847,11 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"App isn’t available"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> isn’t available at the moment. This is managed by <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Learn more"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Turn on work profile?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Your work apps, notifications, data and other work profile features will be turned on"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Turn on"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"App is not available"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not available right now."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"This app was built for an older version of Android and may not work properly. Try checking for updates or contact the developer."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Check for update"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"You have new messages"</string>
@@ -1984,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> spreadsheet"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Presentation"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> presentation"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth will stay on during aeroplane mode"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Loading"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> files</item>
@@ -2001,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Toggle Split Screen"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Lock Screen"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Screenshot"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Caption bar of <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> has been put into the RESTRICTED bucket"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 560c4cd..008ad8a 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Your device will be erased"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"The admin app can\'t be used. Your device will now be erased.\n\nIf you have questions, contact your organisation\'s admin."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Printing disabled by <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Me"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tablet options"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV options"</string>
@@ -1609,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remove"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Raise volume above recommended level?\n\nListening at high volume for long periods may damage your hearing."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Use Accessibility Shortcut?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"When the shortcut is on, pressing both volume buttons for 3 seconds will start an accessibility feature.\n\n Current accessibility feature:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n You can change the feature in Settings &gt; Accessibility."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Empty"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit shortcuts"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Cancel"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Turn off Shortcut"</string>
@@ -1847,11 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"App isn’t available"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> isn’t available at the moment. This is managed by <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Learn more"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Turn on work profile?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Your work apps, notifications, data and other work profile features will be turned on"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Turn on"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"App is not available"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not available right now."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"This app was built for an older version of Android and may not work properly. Try checking for updates or contact the developer."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Check for update"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"You have new messages"</string>
@@ -1984,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> spreadsheet"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Presentation"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> presentation"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth will stay on during aeroplane mode"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Loading"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> files</item>
@@ -2001,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Toggle Split Screen"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Lock Screen"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Screenshot"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Caption bar of <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> has been put into the RESTRICTED bucket"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index da89793..87e0c90 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Your device will be erased"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"The admin app can\'t be used. Your device will now be erased.\n\nIf you have questions, contact your organisation\'s admin."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Printing disabled by <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Me"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tablet options"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV options"</string>
@@ -1609,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remove"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Raise volume above recommended level?\n\nListening at high volume for long periods may damage your hearing."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Use Accessibility Shortcut?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"When the shortcut is on, pressing both volume buttons for 3 seconds will start an accessibility feature.\n\n Current accessibility feature:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n You can change the feature in Settings &gt; Accessibility."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Empty"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit shortcuts"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Cancel"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Turn off Shortcut"</string>
@@ -1847,11 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"App isn’t available"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> isn’t available at the moment. This is managed by <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Learn more"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Turn on work profile?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Your work apps, notifications, data and other work profile features will be turned on"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Turn on"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"App is not available"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not available right now."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"This app was built for an older version of Android and may not work properly. Try checking for updates or contact the developer."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Check for update"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"You have new messages"</string>
@@ -1984,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> spreadsheet"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Presentation"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> presentation"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth will stay on during aeroplane mode"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Loading"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> files</item>
@@ -2001,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Toggle Split Screen"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Lock Screen"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Screenshot"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Caption bar of <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> has been put into the RESTRICTED bucket"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index da89793..87e0c90 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Your device will be erased"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"The admin app can\'t be used. Your device will now be erased.\n\nIf you have questions, contact your organisation\'s admin."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Printing disabled by <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Me"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tablet options"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV options"</string>
@@ -1609,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remove"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Raise volume above recommended level?\n\nListening at high volume for long periods may damage your hearing."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Use Accessibility Shortcut?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"When the shortcut is on, pressing both volume buttons for 3 seconds will start an accessibility feature.\n\n Current accessibility feature:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n You can change the feature in Settings &gt; Accessibility."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Empty"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit shortcuts"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Cancel"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Turn off Shortcut"</string>
@@ -1847,11 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"App isn’t available"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> isn’t available at the moment. This is managed by <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Learn more"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Turn on work profile?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Your work apps, notifications, data and other work profile features will be turned on"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Turn on"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"App is not available"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not available right now."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"This app was built for an older version of Android and may not work properly. Try checking for updates or contact the developer."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Check for update"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"You have new messages"</string>
@@ -1984,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> spreadsheet"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Presentation"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> presentation"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth will stay on during aeroplane mode"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Loading"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> files</item>
@@ -2001,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Toggle Split Screen"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Lock Screen"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Screenshot"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Caption bar of <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> has been put into the RESTRICTED bucket"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index f7da05e..777107a 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‎‏‏‏‏‎‎‎‎‎‏‎‎‎‏‎‏‎‏‏‎‏‎‏‎‏‎‏‏‎‏‏‎‏‎‎‏‎‎‏‎‎‏‎‎‎‏‎‎‎‎‎‏‎Your device will be erased‎‏‎‎‏‎"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‏‏‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‎‎‎‏‏‏‎‏‏‏‎‏‎‏‏‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‎‏‎‏‎‏‎The admin app can\'t be used. Your device will now be erased.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎If you have questions, contact your organization\'s admin.‎‏‎‎‏‎"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‏‎‎‎‎‏‎‏‎‏‎‏‏‎‏‏‏‎‎‎‎‎‎‎‎‎‎‎‏‏‎‏‎‏‎‎‎‏‎‎‎‎‎‎‏‎‏‏‏‏‎‎‏‎Printing disabled by ‎‏‎‎‏‏‎<xliff:g id="OWNER_APP">%s</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‎‏‏‏‏‏‎‏‎‏‏‏‎‏‏‏‏‏‎‎‏‎‏‎‎‎Me‎‏‎‎‏‎"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‎‏‎‏‏‎‎‎‎‎‎‎‎‏‎‎‏‏‏‏‏‏‎‎‏‎‎‎‎‏‎‏‏‏‏‏‎‎‎‏‎‏‎‏‏‎‏‎‏‏‎‏‎Tablet options‎‏‎‎‏‎"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‎‏‎‏‏‎‏‏‏‎‎‏‏‏‎‎‏‎‎‏‏‏‎‎‏‏‏‎‏‎‏‎‎‏‎‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‏‎Android TV options‎‏‎‎‏‎"</string>
@@ -1609,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‎‎‏‎‏‏‏‎‏‏‏‎‎‏‏‏‏‎‎‏‎‏‏‏‏‎‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‎‎‎‎‎‏‏‎‏‏‎‎‎You have incorrectly drawn your unlock pattern ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ times. After ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ more unsuccessful attempts, you will be asked to unlock your phone using an email account.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎ Try again in ‎‏‎‎‏‏‎<xliff:g id="NUMBER_2">%3$d</xliff:g>‎‏‎‎‏‏‏‎ seconds.‎‏‎‎‏‎"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" ‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‎‎‎‎‎‎‏‏‎‎‎‏‏‎‏‎‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‎‏‎‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‎‎‏‎‎ — ‎‏‎‎‏‎ "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‎‎‏‏‏‎‏‏‎‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‎‎‎‎‎‏‏‏‎‎‎‎‏‏‎‏‏‏‎‏‏‎‎‎‎‎‎‎‎‎‏‎‎Remove‎‏‎‎‏‎"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‏‎‎‎‎‏‎‏‎‎‎‏‎‎‎‏‏‎‎‎‏‏‏‎‎‏‏‏‏‏‏‎‎‏‏‎‏‎‎‏‎‏‎‏‏‎‎‎‎‏‎‏‎‎Raise volume above recommended level?‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Listening at high volume for long periods may damage your hearing.‎‏‎‎‏‎"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‎‎‎‎‏‎‏‏‎‎‏‎‎‏‏‏‏‎‏‏‎‏‎‎‎‏‎‏‏‎‏‎‏‎‏‎‏‎‏‎‏‏‏‎‎‎‎‏‎‏‎‏‎‏‎Use Accessibility Shortcut?‎‏‎‎‏‎"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‎‏‎‏‏‎‏‏‎‎‎‎‏‏‎‏‏‏‎‏‎‎‎‏‏‎‎‏‎‏‎‎‎‎‏‏‏‎‎‏‎‏‎‏‎‎‏‎‏‏‎‎‎When the shortcut is on, pressing both volume buttons for 3 seconds will start an accessibility feature.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎ Current accessibility feature:‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎<xliff:g id="SERVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎ You can change the feature in Settings &gt; Accessibility.‎‏‎‎‏‎"</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‏‎‎‏‏‎‏‏‎‏‎‎‎‎‎‎‏‎‏‎‎‏‎‎‎‎‏‎‏‎‏‏‎‎‏‎‏‏‏‎‏‏‏‏‏‎‎‎‎‏‎‏‎‎‎Empty‎‏‎‎‏‎"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎‎‏‎‎‎‏‎‎‏‎‎‎‎‏‎‎‏‏‎‎‎‎‎‏‎‎‎‏‎‏‏‏‎‎‏‎‏‎‎‎‎‏‎‎‎‎‏‏‏‎Edit shortcuts‎‏‎‎‏‎"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‎‎‏‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎‎‎‎‏‏‏‎‏‏‏‏‎‎‎‎‎‎‏‎‏‏‎‏‎‎‏‏‏‎‏‎‎Cancel‎‏‎‎‏‎"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‏‎‎‏‏‎‏‏‎‎‎‎‏‎‏‎‏‏‎‎‎‏‏‎‏‎‎‏‏‏‎‎‏‎‎‎‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎Turn off Shortcut‎‏‎‎‏‎"</string>
@@ -1847,11 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‏‎‏‎‏‎‏‏‏‏‎‏‎‎‏‏‎‏‏‎‎‎‎‎‏‎‏‎‏‎‎‎‎‎‏‏‏‏‎‎‎‏‏‎‏‎‎‏‏‎‏‏‎‏‎‎App isn’t available‎‏‎‎‏‎"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‎‎‏‏‏‎‏‎‏‎‎‏‎‎‏‏‏‏‎‏‎‏‏‎‎‏‎‎‏‏‎‎‎‎‏‎‏‏‏‎‏‎‏‏‎‎‏‎‎‏‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎ isn’t available right now. This is managed by ‎‏‎‎‏‏‎<xliff:g id="APP_NAME_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‏‏‏‎‏‏‏‎‏‎‎‎‏‏‎‎‏‎‏‏‎‏‎‏‎‏‎‎‏‏‎‎‎‏‏‎‎‏‎‎‎‎‎‎‏‏‏‎‏‏‎‎‎‏‏‎‎Learn more‎‏‎‎‏‎"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‏‎‏‏‏‏‏‏‎‎‏‏‏‏‎‏‏‏‎‎‏‎‏‎‎‏‎‎‎‏‏‎‏‎‏‏‏‎‎‎‎‏‎‎‏‏‎‎‏‏‏‎‎‎‎‎Turn on work profile?‎‏‎‎‏‎"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‎‎‎‎‏‏‏‎‏‎‎‏‎‏‏‏‏‎‏‏‏‎‏‏‎‏‎‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‎‎‏‏‎‏‏‎‏‏‎Your work apps, notifications, data, and other work profile features will be turned on‎‏‎‎‏‎"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‏‎‏‎‏‎‎‎‎‎‎‏‎‎‎‎‏‏‎‏‏‎‏‎‏‎‎‏‎‏‏‏‏‎‏‏‎‎‎‎‎‎‎‎‏‏‏‏‎‏‎‏‏‎‏‎Turn on‎‏‎‎‏‎"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‎‎‏‏‎‎‎‎‎‎‏‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‎‏‏‎‎‎‏‏‏‏‏‎‎‏‎‎‏‏‎‏‏‏‎‎‎‎‎‎‎App is not available‎‏‎‎‏‎"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‎‎‎‏‎‎‏‎‎‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‎‎‎‏‏‎‎‏‎‏‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is not available right now.‎‏‎‎‏‎"</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‏‏‎‏‎‏‏‎‎‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‏‎‎‎‏‎‏‎‏‏‎‏‏‏‏‎‏‏‎‏‏‎‎‎‏‎This app was built for an older version of Android and may not work properly. Try checking for updates, or contact the developer.‎‏‎‎‏‎"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‏‎‎‏‎‎‎‏‎‎‎‎‏‎‎‏‎‎‏‎‏‎‎‎‏‎‎‏‎‎‎‏‎‎‏‏‎‎‏‏‏‏‏‎‏‎‎‏‏‎‏‎Check for update‎‏‎‎‏‎"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‎‏‏‎‏‎‏‏‎‎‏‏‏‏‎‎‎‎‎‎‏‎‏‏‏‎‏‏‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‏‎‏‎‏‎‎‎‎‏‏‎You have new messages‎‏‎‎‏‎"</string>
@@ -1984,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‏‎‎‎‏‎‎‎‏‏‏‎‏‎‎‏‏‏‎‏‎‎‎‏‎‎‏‏‎‎‏‎‎‏‎‏‏‏‏‏‎‎‎‎‎‎‎‏‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="EXTENSION">%1$s</xliff:g>‎‏‎‎‏‏‏‎ spreadsheet‎‏‎‎‏‎"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‏‏‎‎‎‏‏‏‎‎‏‎‏‎‎‎‏‎‏‎‏‎‎‎‏‏‎‎‎‎‏‎‏‎‏‏‎‏‎‎‏‏‎‏‏‎Presentation‎‏‎‎‏‎"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‎‏‎‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‎‎‎‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‏‎‎‎‎‎‏‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="EXTENSION">%1$s</xliff:g>‎‏‎‎‏‏‏‎ presentation‎‏‎‎‏‎"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‎‏‏‎‏‎‏‎‏‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‎‎‏‎‎‏‎‎‏‎‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‏‎‏‎‎Bluetooth will stay on during airplane mode‎‏‎‎‏‎"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‎‎‏‏‎‎‏‏‏‎‏‎‏‏‎‎‏‎‎‏‎‏‎‏‎‎‎‎‏‎‎‏‏‏‏‏‎‏‏‎‎‏‎‏‎‎‏‎‎‏‏‎‎Loading‎‏‎‎‏‎"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‎‎‎‏‏‎‏‎‏‎‎‏‎‎‎‏‏‎‏‎‎‎‏‎‎‏‏‎‎‎‏‏‎‎‏‏‎‏‏‏‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="FILE_NAME_2">%s</xliff:g>‎‏‎‎‏‏‏‎ + ‎‏‎‎‏‏‎<xliff:g id="COUNT_3">%d</xliff:g>‎‏‎‎‏‏‏‎ files‎‏‎‎‏‎</item>
@@ -2001,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‏‎‎‏‎‎‎‎‎‏‏‎‎‎‎‎‎‏‏‎‎‎‎‎‏‏‎‎‎‏‎‎‏‏‏‎‏‏‏‎‎‏‎‎‎Toggle Split Screen‎‏‎‎‏‎"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‎‎‏‏‎‏‏‏‏‎‎‎‎‏‎‎‏‏‎‎‎‎‎‏‎‏‏‏‎‎‏‏‏‏‎‏‎‏‏‎‏‎‎‎‏‏‎‏‎‏‏‏‏‏‎‎Lock Screen‎‏‎‎‏‎"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‏‎‏‎‎‎‏‎‎‎‏‏‏‏‏‎‎‎‏‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‎‏‎‏‏‎‎‎Screenshot‎‏‎‎‏‎"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‎‎‎‏‎‏‏‏‎‏‏‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‏‎‏‎‎‏‎‏‎‎Caption bar of ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‎‏‎‎‏‎‎‏‎‏‏‎‎‏‎‏‎‎‎‎‎‎‎‏‎‎‎‎‎‎‏‏‏‎‏‎‎‎‎‎‏‎‏‏‏‏‎‏‎‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="PACKAGE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ has been put into the RESTRICTED bucket‎‏‎‎‏‎"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index aeec9f8..4335c2b 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Se borrarán los datos del dispositivo"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"No se puede usar la app de administrador. Ahora se borrará tu dispositivo.\n\nSi tienes preguntas, comunícate con el administrador de tu organización."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> inhabilitó la impresión."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Yo"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opciones de tablet"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Opciones de Android TV"</string>
@@ -1609,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Dibujaste incorrectamente tu patrón de desbloqueo <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. Luego de <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se te solicitará que desbloquees tu dispositivo mediante el uso de una cuenta de correo.\n\n Vuelve a intentarlo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Eliminar"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"¿Quieres subir el volumen por encima del nivel recomendado?\n\nEscuchar a un alto volumen durante largos períodos puede dañar tu audición."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"¿Usar acceso directo de accesibilidad?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Cuando el acceso directo está activado, puedes presionar los botones de volumen durante 3 segundos para iniciar una función de accesibilidad.\n\n Función de accesibilidad actual:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Puedes cambiar la función en Configuración &gt; Accesibilidad."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Vacío"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar accesos directos"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Cancelar"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Desactivar acceso directo"</string>
@@ -1847,11 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"La app no está disponible"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> no está disponible en este momento. Esta opción se administra en <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Más información"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"¿Activar el perfil de trabajo?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Se activaran las apps de trabajo, los datos, las notificaciones y otras funciones del perfil de trabajo"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Activar"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"La app no está disponible"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> no está disponible en este momento."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Esta app se creó para una versión anterior de Android y es posible que no funcione correctamente. Busca actualizaciones o comunícate con el programador."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Buscar actualización"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Tienes mensajes nuevos"</string>
@@ -1984,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"Hoja de cálculo <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Presentación"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Presentación <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"La conexión Bluetooth permanecerá activa durante el modo de avión"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Cargando"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> y <xliff:g id="COUNT_3">%d</xliff:g> archivos más</item>
@@ -2001,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Activar o desactivar pantalla dividida"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Bloquear pantalla"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Captura de pantalla"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Barra de subtítulos de <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Se colocó <xliff:g id="PACKAGE_NAME">%1$s</xliff:g> en el depósito RESTRICTED"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 1ef891a..8d750ca 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Tu dispositivo se borrará"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"No se puede utilizar la aplicación de administración. Se borrarán todos los datos del dispositivo.\n\nSi tienes alguna pregunta, ponte en contacto con el administrador de tu organización."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ha inhabilitado la impresión."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Yo"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opciones del tablet"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Opciones de Android TV"</string>
@@ -1609,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Has fallado <xliff:g id="NUMBER_0">%1$d</xliff:g> veces al dibujar el patrón de desbloqueo. Si fallas otras <xliff:g id="NUMBER_1">%2$d</xliff:g> veces, deberás usar una cuenta de correo electrónico para desbloquear el teléfono.\n\n Inténtalo de nuevo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Quitar"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"¿Quieres subir el volumen por encima del nivel recomendado?\n\nEscuchar sonidos fuertes durante mucho tiempo puede dañar los oídos."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"¿Utilizar acceso directo de accesibilidad?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Si el acceso directo está activado, pulsa los dos botones de volumen durante tres segundos para iniciar una función de accesibilidad.\n\n Función de accesibilidad actual:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Puedes cambiar la función en Ajustes &gt; Accesibilidad."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Vacío"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar accesos directos"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Cancelar"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Desactivar acceso directo"</string>
@@ -1847,11 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"La aplicación no está disponible"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> no está disponible en este momento. Esta opción se administra en <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Más información"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"¿Activar el perfil de trabajo?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Tus aplicaciones, notificaciones, datos y otras funciones del perfil de trabajo se activarán"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Activar"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"La aplicación no está disponible"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"En estos momentos, <xliff:g id="APP_NAME">%1$s</xliff:g> no está disponible."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Esta aplicación se ha diseñado para una versión anterior de Android y es posible que no funcione correctamente. Busca actualizaciones o ponte en contacto con el desarrollador."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Buscar actualizaciones"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Tienes mensajes nuevos"</string>
@@ -1984,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"Hoja de cálculo <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Presentación"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Presentación <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"El Bluetooth seguirá activado en el modo avión"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Cargando"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> y <xliff:g id="COUNT_3">%d</xliff:g> archivos</item>
@@ -2001,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Activar o desactivar la pantalla dividida"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Pantalla de bloqueo"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Captura de pantalla"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Barra de subtítulos de <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> se ha incluido en el grupo de restringidos"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 9a4b6d3..7f423e9 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Seade kustutatakse"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Administraatori rakendust ei saa kasutada. Teie seade tühjendatakse nüüd.\n\nKui teil on küsimusi, võtke ühendust organisatsiooni administraatoriga."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Rakendus <xliff:g id="OWNER_APP">%s</xliff:g> on printimise keelanud."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Mina"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tahvelarvuti valikud"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV valikud"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"juurdepääs kalendrile"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"saata ja vaadata SMS-sõnumeid"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Failid ja meedia"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"juurdepääs seadmesse salvestatud fotodele, meediasisule ja failidele"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"heli salvestamine"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Saate puudutada, pühkida, sõrmi kokku-lahku liigutada ja teisi liigutusi teha."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Sõrmejälje liigutused"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Teil on võimalik jäädvustada seadme sõrmejäljeanduril tehtud liigutused."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Jäädvusta ekraanipilt"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Saab jäädvustada ekraanipildi."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"keela või muuda olekuriba"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Võimaldab rakendusel keelata olekuriba või lisada ja eemaldada süsteemiikoone."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"olekuribana kuvamine"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Joonistasite oma avamismustri <xliff:g id="NUMBER_0">%1$d</xliff:g> korda valesti. Pärast veel <xliff:g id="NUMBER_1">%2$d</xliff:g> ebaõnnestunud katset palutakse teil telefon avada meilikontoga.\n\n Proovige uuesti <xliff:g id="NUMBER_2">%3$d</xliff:g> sekundi pärast."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Eemalda"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Kas suurendada helitugevuse taset üle soovitatud taseme?\n\nPikaajaline valju helitugevusega kuulamine võib kuulmist kahjustada."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Kas kasutada juurdepääsetavuse otseteed?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Kui otsetee on sisse lülitatud, käivitab mõlema helitugevuse nupu kolm sekundit all hoidmine juurdepääsetavuse funktsiooni.\n\n Praegune juurdepääsetavuse funktsioon:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Saate seda funktsiooni muuta valikutega Seaded &gt; Juurdepääsetavus."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Tühi"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Muuda otseteid"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Tühista"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Lülita otsetee välja"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Rakendus pole saadaval"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> pole praegu saadaval. Seda haldab rakendus <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Lisateave"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Kas lülitada tööprofiil sisse?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Teie töörakendused, märguanded, andmed ja muud tööprofiili funktsioonid lülitatakse sisse"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Lülita sisse"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"See rakendus on loodud Androidi vanema versiooni jaoks ega pruugi õigesti töötada. Otsige värskendusi või võtke ühendust arendajaga."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Otsi värskendust"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Teile on uusi sõnumeid"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Aku võib enne tavapärast laadimist tühjaks saada"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Akusäästja aktiveeriti aku tööea pikendamiseks"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Akusäästja"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Akusäästja on välja lülitatud"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefon on piisavalt laetud. Funktsioonid ei ole enam piiratud."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Tahvelarvuti on piisavalt laetud. Funktsioonid ei ole enam piiratud."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Seade on piisavalt laetud. Funktsioonid ei ole enam piiratud."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"Kaust"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Androidi rakendus"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Fail"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g>-arvutustabelifail"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Esitlus"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g>-esitlusefail"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth jääb lennukirežiimi ajal sisselülitatuks"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Laadimine"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> faili</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Vaheta jagatud ekraanikuva"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Lukustuskuva"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Ekraanipilt"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> pealkirjariba."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> on lisatud salve PIIRANGUTEGA"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index f0a0010c..9d014a3 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Gailuko datuak ezabatu egingo dira"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Ezin da erabili administratzeko aplikazioa. Ezabatu egingo da gailuko eduki guztia.\n\nZalantzarik baduzu, jarri erakundeko administratzailearekin harremanetan."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> aplikazioak desgaitu egin du inprimatzeko aukera."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Ni"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tabletaren aukerak"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV gailuaren aukerak"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"atzitu egutegia"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS mezuak"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"bidali eta ikusi SMS mezuak"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Fitxategiak eta multimedia-edukia"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"atzitu gailuko argazkiak, multimedia-edukia eta fitxategiak"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofonoa"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"grabatu audioa"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Sakatu, lerratu, atximurkatu eta beste hainbat keinu egin ditzake."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Hatz-marken keinuak"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Gailuaren hatz-marken sentsorean egindako keinuak atzeman ditzake."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Atera pantaila-argazki bat"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pantaila-argazkiak atera ditzake."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"desgaitu edo aldatu egoera-barra"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Egoera-barra desgaitzea edo sistema-ikonoak gehitzea edo kentzea baimentzen die aplikazioei."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"bihurtu egoera-barra"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Desblokeatzeko eredua oker marraztu duzu <xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz oker marrazten baduzu, telefonoa posta-kontu baten bidez desblokeatzeko eskatuko dizugu.\n\n Saiatu berriro <xliff:g id="NUMBER_2">%3$d</xliff:g> segundo barru."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Kendu"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Bolumena gomendatutako mailatik gora igo nahi duzu?\n\nMusika bolumen handian eta denbora luzez entzuteak entzumena kalte diezazuke."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Erabilerraztasun-lasterbidea erabili nahi duzu?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Lasterbidea aktibatuta dagoenean, bi bolumen-botoiak hiru segundoz sakatuta abiaraziko da erabilerraztasun-eginbidea.\n\n Uneko erabilerraztasun-eginbidea:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Eginbidea aldatzeko, joan Ezarpenak &gt; Erabilerraztasuna atalera."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Hustu"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editatu lasterbideak"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Utzi"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Desaktibatu lasterbidea"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Aplikazioa ez dago erabilgarri"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ez dago erabilgarri une honetan. Haren erabilgarritasuna <xliff:g id="APP_NAME_1">%2$s</xliff:g> aplikazioak kudeatzen du."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Lortu informazio gehiago"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Laneko profila aktibatu?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Laneko aplikazioak, jakinarazpenak, datuak eta laneko profileko bestelako eginbideak aktibatuko dira"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Aktibatu"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Aplikazioa Android-en bertsio zaharrago baterako sortu zenez, baliteke behar bezala ez funtzionatzea. Bilatu eguneratzerik baden, edo jarri garatzailearekin harremanetan."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Bilatu eguneratzeak"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Mezu berriak dituzu"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Baliteke bateria ohi baino lehenago agortzea"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Bateria-aurrezlea aktibatuta dago bateriaren iraupena luzatzeko"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Bateria-aurrezlea"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Desaktibatu egin da bateria-aurrezlea"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Behar adina bateria dauka telefonoak. Jada ez dago eginbiderik murriztuta."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Behar adina bateria dauka tabletak. Jada ez dago eginbiderik murriztuta."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Behar adina bateria dauka gailuak. Jada ez dago eginbiderik murriztuta."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"Karpeta"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android-erako aplikazioa"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Fitxategia"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> kalkulu-orria"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Aurkezpena"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> aurkezpena"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth konexioak aktibatuta jarraituko du hegaldi moduan"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Kargatzen"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> fitxategi</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Aktibatu/Desaktibatu pantaila zatitua"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Pantaila blokeatua"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Pantaila-argazkia"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioko azpitituluen barra."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Murriztuen edukiontzian ezarri da <xliff:g id="PACKAGE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 7d12221..58ce7a7 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"دستگاهتان پاک خواهد شد"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"برنامه سرپرست سیستم را نمی‌توان استفاده کرد. دستگاه شما در این لحظه پاک می‌شود.\n\nاگر سؤالی دارید، با سرپرست سیستم سازمانتان تماس بگیرید."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> چاپ کردن را غیرفعال کرده است."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"من"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"گزینه‌های رایانهٔ لوحی"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"‏گزینه‌های Android TV"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"دسترسی به تقویم شما"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"پیامک"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"ارسال و مشاهده پیامک‌ها"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"فایل‌ها و رسانه‌ها"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"دسترسی به عکس‌ها، رسانه‌ها و فایل‌های روی دستگاهتان"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"میکروفن"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ضبط صدا"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"می‌توانید ضربه بزنید، انگشتتان را تند بکشید، انگشتانتان را به هم نزدیک یا از هم دور کنید و اشاره‌های دیگری اجرا کنید."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"اشاره‌های اثر انگشت"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"می‌تواند اشاره‌های اجرا‌شده روی حسگر اثرانگشت دستگاه را ثبت کند."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"گرفتن نماگرفت"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"می‌تواند از نمایشگر نماگرفت بگیرد."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"غیرفعال کردن یا تغییر نوار وضعیت"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"‏به برنامه اجازه می‎دهد تا نوار وضعیت را غیرفعال کند یا نمادهای سیستم را اضافه یا حذف کند."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"نوار وضعیت باشد"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"‏شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه کشیده‌اید. پس از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق، از شما خواسته می‎شود که با استفاده از یک حساب ایمیل قفل تلفن خود را باز کنید.\n\n لطفاً پس از <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"حذف"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"میزان صدا را به بالاتر از حد توصیه شده افزایش می‌دهید؟\n\nگوش دادن به صداهای بلند برای مدت طولانی می‌تواند به شنوایی‌تان آسیب وارد کند."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"از میان‌بر دسترس‌پذیری استفاده شود؟"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"وقتی میان‌بر روشن است،‌ اگر هر دو دکمه صدا را ۳ ثانیه فشار دهید یکی از قابلیت‌های دسترس‌پذیری شروع می‌شود.\n\n قابلیت دسترس‌پذیری کنونی:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n می‌توانید در «تنظیمات &gt; دسترس‌پذیری»، قابلیت را تغییر دهید."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"خالی"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ویرایش میان‌برها"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"لغو"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"خاموش کردن میان‌بر"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"برنامه در دسترس نیست"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> درحال‌حاضر در دسترس نیست. <xliff:g id="APP_NAME_1">%2$s</xliff:g> آن را مدیریت می‌کند."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"بیشتر بدانید"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"نمایه کاری روشن شود؟"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"برنامه‌ها، اعلان‌ها، داده‌ها و سایر قابلیت‌های نمایه کاری شما روشن خواهد شد"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"روشن کردن"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"‏این برنامه برای نسخه قدیمی‌تری از Android ساخته شده است و ممکن است درست کار نکند. وجود به‌روزرسانی را بررسی کنید یا با برنامه‌نویس تماس بگیرید."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"بررسی وجود به‌روزرسانی"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"پیام‌های جدیدی دارید"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"ممکن است شارژ باتری قبل از شارژ معمول تمام شود"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"جهت افزایش عمر باتری، «بهینه‌سازی باتری» فعال شد"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"بهینه‌سازی باتری"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"«بهینه‌سازی باتری» خاموش شد"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"تلفن به‌اندازه کافی شارژ دارد. ویژگی‌ها دیگر محدود نمی‌شوند."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"رایانه لوحی به‌اندازه کافی شارژ دارد. ویژگی‌ها دیگر محدود نمی‌شوند."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"دستگاه به‌اندازه کافی شارژ دارد. ویژگی‌ها دیگر محدود نمی‌شوند."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"پوشه"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"‏برنامه Android"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"فایل"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> صفحه‌گسترده"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"ارائه"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> ارائه"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"بلوتوث درطول حالت هواپیما روشن خواهد بود"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"درحال بارگیری"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> فایل</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"تغییر وضعیت صفحهٔ دونیمه"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"صفحه قفل"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"عکس صفحه‌نمایش"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"نوار شرح <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> در سطل «محدودشده» قرار گرفت"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index ba39b8c..e0f4ed4 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Laitteen tiedot poistetaan"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Hallintasovellusta ei voi käyttää. Laitteen tiedot pyyhitään.\n\nPyydä ohjeita järjestelmänvalvojaltasi."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> on poistanut tulostuksen käytöstä."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Minä"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tablet-laitteen asetukset"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV ‑vaihtoehdot"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"käyttää kalenteria"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"Tekstiviestit"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"lähettää ja tarkastella tekstiviestejä"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Tiedostot ja media"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"käyttää laitteellesi tallennettuja valokuvia, mediatiedostoja ja muita tiedostoja"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofoni"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"tallentaa ääntä"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Lupa napauttaa, pyyhkäistä, nipistää ja käyttää muita eleitä."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Sormenjälkieleet"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Voi tallentaa laitteen sormenjälkitunnistimelle tehtyjä eleitä."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ota kuvakaappaus"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Voi ottaa kuvakaappauksen näytöstä."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"poista tilapalkki käytöstä tai muokkaa tilapalkkia"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Antaa sovelluksen poistaa tilapalkin käytöstä ja lisätä tai poistaa järjestelmäkuvakkeita."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"sijaita tilapalkissa"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Piirsit lukituksenpoistokuvion väärin <xliff:g id="NUMBER_0">%1$d</xliff:g> kertaa. Jos piirrät kuvion väärin vielä <xliff:g id="NUMBER_1">%2$d</xliff:g> kertaa, sinua pyydetään poistamaan puhelimesi lukitus sähköpostitilin avulla.\n\n Yritä uudelleen <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunnin kuluttua."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Poista"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Nostetaanko äänenvoimakkuus suositellun tason yläpuolelle?\n\nPitkäkestoinen kova äänenvoimakkuus saattaa heikentää kuuloa."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Käytetäänkö esteettömyyden pikanäppäintä?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Kun pikanäppäin on käytössä, voit käynnistää esteettömyystoiminnon pitämällä molempia äänenvoimakkuuspainikkeita painettuna kolmen sekunnin ajan.\n\n Tällä hetkellä valittu esteettömyystoiminto:\n<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Voit vaihtaa toimintoa valitsemalla Asetukset &gt; Esteettömyys."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Tyhjennä"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Muokkaa pikakuvakkeita"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Peruuta"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Poista pikanäppäin käytöstä"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Sovellus ei käytettävissä"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ei ole juuri nyt saatavilla. Tästä vastaa <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Lue lisää"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Otetaanko työprofiili käyttöön?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Työsovellukset, ‑ilmoitukset, ‑tiedot ja muut työprofiiliominaisuudet otetaan käyttöön"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Ota käyttöön"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Tämä sovellus on suunniteltu vanhemmalle Android-versiolle eikä välttämättä toimi oikein. Kokeile tarkistaa päivitykset tai ottaa yhteyttä kehittäjään."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Tarkista päivitykset"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Sinulle on uusia viestejä"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Akku saattaa loppua ennen normaalia latausaikaa"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Virransäästö otettu käyttöön akunkeston pidentämiseksi"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Virransäästö"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Virransäästö laitettiin pois päältä"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Puhelimessa on tarpeeksi virtaa. Ominaisuuksia ei enää rajoiteta."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Tabletissa on tarpeeksi virtaa. Ominaisuuksia ei enää rajoiteta."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Laitteessa on tarpeeksi virtaa. Ominaisuuksia ei enää rajoiteta."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"Kansio"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android-sovellus"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Tiedosto"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g>-laskentataulukko"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Esitys"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g>-esitys"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth pysyy päällä myös lentokonetilassa"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Ladataan"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> tiedostoa</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Jaettu näyttö päälle/pois"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Lukitusnäyttö"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Kuvakaappaus"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Tekstityspalkki: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> on nyt rajoitettujen ryhmässä"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 8df6ad6..5d99db1 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Le contenu de votre appareil sera effacé"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Impossible d\'utiliser l\'application d\'administration. Les données de votre appareil vont maintenant être effacées.\n\nSi vous avez des questions, communiquez avec l\'administrateur de votre organisation."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Impression désactivée par <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Moi"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Options de la tablette"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Options d\'Android TV"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"accéder à votre agenda"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"Messagerie texte"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"envoyer et afficher des messages texte"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Fichiers et contenu multimédia"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"accéder aux photos, aux contenus multimédias et aux fichiers sur votre appareil"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Microphone"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"enregistrer des fichiers audio"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Peut toucher, balayer, pincer et effectuer d\'autres gestes."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gestes sur le capteur d\'empreintes digitales"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Peut capturer des gestes effectués sur le capteur d\'empreintes digitales de l\'appareil."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Prendre une capture d\'écran"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Peut prendre une capture de l\'écran."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"désactiver ou modifier la barre d\'état"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Permet à l\'application de désactiver la barre d\'état, ou d\'ajouter et de supprimer des icônes système."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"servir de barre d\'état"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, vous devrez déverrouiller votre téléphone à l\'aide d\'un compte de messagerie électronique.\n\n Veuillez réessayer dans <xliff:g id="NUMBER_2">%3$d</xliff:g> secondes."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Supprimer"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Augmenter le volume au-dessus du niveau recommandé?\n\nL\'écoute prolongée à un volume élevé peut endommager vos facultés auditives."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Utiliser le raccourci d\'accessibilité?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Quand le raccourci est activé, appuyez sur les deux boutons de volume pendant trois secondes pour lancer une fonctionnalité d\'accessibilité.\n\n Fonctionnalité d\'accessibilité utilisée actuellement :\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Vous pouvez changer de fonctionnalité sous Paramètres &gt; Accessibilité."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Vide"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Modifier les raccourcis"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Annuler"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Désactiver le raccourci"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"L\'application n\'est pas accessible"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"L\'application <xliff:g id="APP_NAME_0">%1$s</xliff:g> n\'est pas accessible pour le moment. Ceci est géré par <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"En savoir plus"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Activer le profil professionnel?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Vos applications professionnelles, vos notifications, vos données et les autres fonctionnalités de profil professionnel seront activées"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Activer"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Cette application a été conçue pour une ancienne version d\'Android et pourrait ne pas fonctionner correctement. Essayez de vérifier les mises à jour ou communiquez avec son concepteur."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Vérifier la présence de mises à jour"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Vous avez de nouveaux messages"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"La pile pourrait s\'épuiser avant la charge habituelle"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Le mode Économiseur de pile est activé afin de prolonger l\'autonomie"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Économiseur de pile"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Le mode Économiseur de pile est désactivé"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Le téléphone est suffisamment chargé. Ces fonctionnalités ne sont plus restreintes."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"La tablette est suffisamment chargée. Ces fonctionnalités ne sont plus restreintes."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"L\'appareil est suffisamment chargé. Ces fonctionnalités ne sont plus restreintes."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"Dossier"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Application Android"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Fichier"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"Feuille de calcul <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Présentation"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Présentation <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Le Bluetooth restera activé en mode Avion"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Chargement en cours…"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> fichier</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Basculer l\'écran partagé"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Écran de verrouillage"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Capture d\'écran"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Barre de légende de l\'application <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> a été placé dans le compartiment RESTREINT"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index a64066a..3f4f3e6 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Les données de votre appareil vont être effacées"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Impossible d\'utiliser l\'application d\'administration. Les données de votre appareil vont maintenant être effacées.\n\nSi vous avez des questions, contactez l\'administrateur de votre organisation."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Impression désactivée par <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Moi"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Options de la tablette"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Options Android TV"</string>
@@ -1609,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, vous devrez déverrouiller votre téléphone à l\'aide d\'un compte de messagerie électronique.\n\n Veuillez réessayer dans <xliff:g id="NUMBER_2">%3$d</xliff:g> secondes."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Supprimer"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Augmenter le volume au dessus du niveau recommandé ?\n\nL\'écoute prolongée à un volume élevé peut endommager vos facultés auditives."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Utiliser le raccourci d\'accessibilité ?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Quand le raccourci est activé, appuyez sur les deux boutons de volume pendant trois secondes pour lancer une fonctionnalité d\'accessibilité.\n\n Fonctionnalité d\'accessibilité utilisée actuellement :\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Vous pouvez changer de fonctionnalité dans Paramètres &gt; Accessibilité."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Vider"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Modifier les raccourcis"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Annuler"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Désactiver le raccourci"</string>
@@ -1847,11 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Application indisponible"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"L\'application <xliff:g id="APP_NAME_0">%1$s</xliff:g> n\'est pas disponible pour le moment. Cette suspension est gérée par l\'application <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"En savoir plus"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Activer profil professionnel ?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Vos applications professionnelles, notifications, données et d\'autres fonctionnalités de votre profil professionnel seront activées"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Activer"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"Application non disponible"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> n\'est pas disponible pour le moment."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Cette application a été conçue pour une ancienne version d\'Android et risque de ne pas fonctionner correctement. Recherchez des mises à jour ou contactez le développeur."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Rechercher une mise à jour"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Vous avez de nouveaux messages"</string>
@@ -1984,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"Feuille de calcul <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Présentation"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Présentation <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Le Bluetooth restera activé en mode Avion"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Chargement…"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> fichier</item>
@@ -2001,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Activer/Désactiver l\'écran partagé"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Verrouiller l\'écran"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Capture d\'écran"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Barre de légende de l\'application <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> a été placé dans le bucket RESTRICTED"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index df08abc..2e5052c 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Borrarase o teu dispositivo"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Non se pode utilizar a aplicación de administración. Borrarase o teu dispositivo.\n\nSe tes preguntas, contacta co administrador da organización."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> desactivou a impresión."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Eu"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opcións da tableta"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Opcións de Android TV"</string>
@@ -1609,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Debuxaches o padrón de desbloqueo incorrectamente <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. Se realizas <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos máis, terás que desbloquear o teléfono a través dunha conta de correo electrónico.\n\n Téntao de novo dentro de <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Eliminar"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Queres subir o volume máis do nivel recomendado?\n\nA reprodución de son a un volume elevado durante moito tempo pode provocar danos nos oídos."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Queres utilizar o atallo de accesibilidade?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Cando o atallo está activado, podes premer os dous botóns de volume durante 3 segundos para iniciar unha función de accesibilidade.\n\n Función de accesibilidade actual:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Podes cambiar a función en Configuración &gt; Accesibilidade."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Baleirar"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar atallos"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Cancelar"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Desactivar atallo"</string>
@@ -1847,11 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"A aplicación non está dispoñible"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"A aplicación <xliff:g id="APP_NAME_0">%1$s</xliff:g> non está dispoñible neste momento. A dispoñibilidade está xestionada por <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Máis información"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Activar o perfil de traballo?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Activaranse as túas aplicacións de traballo, as notificacións, os datos e outras funcións do perfil de traballo"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Activar"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"A aplicación non está dispoñible"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"A aplicación <xliff:g id="APP_NAME">%1$s</xliff:g> non está dispoñible neste momento."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Esta aplicación deseñouse para unha versión anterior de Android e quizais non funcione correctamente. Proba a buscar actualizacións ou contacta co programador."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Buscar actualización"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Tes mensaxes novas"</string>
@@ -1984,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"Folla de cálculo <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Presentación"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Presentación <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"O Bluetooth permanecerá activado mentres se utilice o modo avión"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Cargando"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ficheiros</item>
@@ -2001,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Activar/desactivar pantalla dividida"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Pantalla de bloqueo"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Captura de pantalla"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Barra de subtítulos de <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> incluíuse no grupo RESTRINXIDO"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index f663b87..8081ef2 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"તમારું ઉપકરણ કાઢી નાખવામાં આવશે"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"વ્યવસ્થાપક ઍપનો ઉપયોગ કરી શકાશે નહીં. તમારું ઉપકરણ હવે કાઢી નાખવામાં આવશે.\n\nજો તમને પ્રશ્નો હોય, તો તમારી સંસ્થાના વ્યવસ્થાપકનો સંપર્ક કરો."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> દ્વારા પ્રિન્ટ કરવાનું બંધ કરાયું છે."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"હું"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"ટેબ્લેટ વિકલ્પો"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TVના વિકલ્પો"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"તમારા કેલેન્ડરને ઍક્સેસ કરવાની"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS સંદેશા મોકલવાની અને જોવાની"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"ફાઇલો અને મીડિયા"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"તમારા ઉપકરણ પર ફોટો, મીડિયા અને ફાઇલો ઍક્સેસ કરવાની"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"માઇક્રોફોન"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ઑડિઓ રેકોર્ડ કરવાની"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"ટૅપ, સ્વાઇપ, પિંચ કરી અને અન્ય હાવભાવ કરી શકે છે."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"ફિંગરપ્રિન્ટ સંકેતો"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ડિવાઇસના ફિંગરપ્રિન્ટ સેન્સર પર કરવામાં આવેલા સંકેતો કૅપ્ચર કરી શકે છે."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"સ્ક્રીનશૉટ લો"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ડિસ્પ્લેનો સ્ક્રીનશૉટ લઈ શકે છે."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"સ્ટેટસ બારને અક્ષમ કરો અથવા તેમાં ફેરફાર કરો"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"ઍપ્લિકેશનને સ્ટેટસ બાર અક્ષમ કરવાની અથવા સિસ્ટમ આયકન્સ ઉમેરવા અને દૂર કરવાની મંજૂરી આપે છે."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"સ્ટેટસ બારમાં બતાવો"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"તમે તમારી અનલૉક પૅટર્ન <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે દોરી. હજી <xliff:g id="NUMBER_1">%2$d</xliff:g> અસફળ પ્રયાસ પછી, તમને ઇમેઇલ એકાઉન્ટનો ઉપયોગ કરીને ફોનને અનલૉક કરવાનું કહેવામાં આવશે.\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> સેકન્ડમાં ફરીથી પ્રયાસ કરો."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"દૂર કરો"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ભલામણ કરેલ સ્તરની ઉપર વૉલ્યૂમ વધાર્યો?\n\nલાંબા સમય સુધી ઊંચા અવાજે સાંભળવું તમારી શ્રવણક્ષમતાને નુકસાન પહોંચાડી શકે છે."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ઍક્સેસિબિલિટી શૉર્ટકટનો ઉપયોગ કરીએ?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"જ્યારે શૉર્ટકટ ચાલુ હોય, ત્યારે બન્ને વૉલ્યૂમ બટનને 3 સેકન્ડ સુધી દબાવી રાખવાથી ઍક્સેસિબિલિટી સુવિધા શરૂ થઈ જશે.\n\n વર્તમાન ઍક્સેસિબિલિટી સુવિધા:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n તમે સેટિંગ્સ &gt; ઍક્સેસિબિલિટીમાં જઈને આ સુવિધા બદલી શકો છો."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"ખાલી કરો"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"શૉર્ટકટમાં ફેરફાર કરો"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"રદ કરો"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"શૉર્ટકટ બંધ કરો"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"ઍપ ઉપલબ્ધ નથી"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> હમણાં ઉપલબ્ધ નથી. આને <xliff:g id="APP_NAME_1">%2$s</xliff:g> દ્વારા મેનેજ કરવામાં આવે છે."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"વધુ જાણો"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"કાર્યાલયની પ્રોફાઇલ ચાલુ કરીએ?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"તમારી કાર્યાલયની ઍપ, નોટિફિકેશન, ડેટા અને અન્ય કાર્યાલયની પ્રોફાઇલ સુવિધાઓ ચાલુ કરવામાં આવશે"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"ચાલુ કરો"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"આ ઍપ Androidના જૂના વર્ઝન માટે બનાવવામાં આવ્યું હતું અને તે કદાચ તે યોગ્ય રીતે કાર્ય કરી શકશે નહીં. અપડેટ માટે તપાસવાનો પ્રયાસ કરો અથવા ડેવલપરનો સંપર્ક કરો."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"અપડેટ માટે તપાસો"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"તમારી પાસે નવા સંદેશા છે"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"સામાન્ય રીતે ચાર્જ કરવાના સમય પહેલાં બૅટરી સમાપ્ત થઈ શકે છે"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"બૅટરી આવરદા વધારવા માટે બૅટરી સેવર ચાલુ કર્યું"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"બૅટરી સેવર"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"બૅટરી સેવર બંધ કર્યું"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ફોનમાં પૂરતો ચાર્જ છે. સુવિધાઓ હવે મર્યાદિત નથી."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"ટૅબ્લેટમાં પૂરતો ચાર્જ છે. સુવિધાઓ હવે મર્યાદિત નથી."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"ડિવાઇસમાં પૂરતો ચાર્જ છે. સુવિધાઓ હવે મર્યાદિત નથી."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"ફોલ્ડર"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android ઍપ"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"ફાઇલ"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> સ્પ્રેડશીટ"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"પ્રસ્તુતિ"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> પ્રસ્તુતિ"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"એરપ્લેન મોડ દરમિયાન બ્લૂટૂથ ચાલુ રહેશે"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"લોડિંગ"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ફાઇલ</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"સ્ક્રીનને વિભાજિત કરવાની ક્રિયા ટૉગલ કરો"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"લૉક સ્ક્રીન"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"સ્ક્રીનશૉટ"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g>નું કૅપ્શન બાર."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g>ને પ્રતિબંધિત સમૂહમાં મૂકવામાં આવ્યું છે"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 8105441..05efcd8 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"आपके डिवाइस को मिटा दिया जाएगा"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"एडमिन ऐप्लिकेशन का इस्तेमाल नहीं किया जा सकता. आपके डिवाइस पर मौजूद डेटा अब मिटा दिया जाएगा.\n\nअगर आप कुछ पूछना चाहते हैं तो, अपने संगठन के एडमिन से संपर्क करें."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ने प्रिंटिंग सुविधा बंद कर दी है."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"मैं"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"टैबलेट विकल्‍प"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV डिवाइस में फ़ोन से जुड़े विकल्प"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"अपने कैलेंडर को ऐक्सेस करने"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"मैसेज (एसएमएस)"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"मैसेज (एसएमएस) भेजें और देखें"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"फ़ाइलें और मीडिया"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"अपने डिवाइस पर मौजूद फ़ोटो, मीडिया और फ़ाइलें ऐक्सेस करने की"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"माइक्रोफ़ोन"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ऑडियो रिकॉर्ड करें"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"इस सेवा के ज़रिए टैप, स्वाइप, पिंच और बाकी जेस्चर किए जा सकते हैं."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"फ़िंगरप्रिंट जेस्चर"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"डिवाइस के फ़िंगरप्रिंट सेंसर पर किए गए हाथ के जेस्चर (स्पर्श) कैप्चर किए जा सकते हैं."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"स्क्रीनशॉट लें"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"डिसप्ले का स्क्रीनशॉट लिया जा सकता है."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"स्टेटस बार को अक्षम करें या बदलें"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"ऐप को, स्टेटस बार को बंद करने या सिस्‍टम आइकॉन को जोड़ने और निकालने की अनुमति देता है."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"स्टेटस बार को रहने दें"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"आपने अपने अनलॉक आकार को <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से आरेखित किया है. <xliff:g id="NUMBER_1">%2$d</xliff:g> और असफल प्रयासों के बाद, आपसे अपने फ़ोन को किसी ईमेल खाते का उपयोग करके अनलॉक करने के लिए कहा जाएगा.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंड में फिर से प्रयास करें."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"निकालें"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"वॉल्यूम को सुझाए गए स्तर से ऊपर बढ़ाएं?\n\nअत्यधिक वॉल्यूम पर ज़्यादा समय तक सुनने से आपकी सुनने की क्षमता को नुकसान हो सकता है."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"सुलभता शॉर्टकट का इस्तेमाल करना चाहते हैं?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"इस शॉर्टकट के चालू होने पर, दोनों वॉल्यूम बटनों को 3 सेकंड तक दबाने से सुलभता सुविधा शुरू हो जाएगी.\n\n मौजूदा सुलभता सुविधा:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n आप इस सुविधा को सेटिंग &gt; सुलभता पर जाकर बदल सकते हैं."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"खाली करें"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"शॉर्टकट में बदलाव करें"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"अभी नहीं"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"शॉर्टकट बंद करें"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"यह ऐप्लिकेशन उपलब्ध नहीं है"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"फ़िलहाल <xliff:g id="APP_NAME_0">%1$s</xliff:g> उपलब्ध नहीं है. इसे <xliff:g id="APP_NAME_1">%2$s</xliff:g> के ज़रिए प्रबंधित किया जाता है."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"ज़्यादा जानें"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"वर्क प्रोफ़ाइल चालू करें?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"आपके काम से जुड़े ऐप्लिकेशन, सूचनाएं, डेटा और वर्क प्रोफ़ाइल से जुड़ी दूसरी सुविधाएं चालू हो जाएंगी"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"चालू करें"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"यह ऐप्लिकेशन Android के पुराने वर्शन के लिए बनाया गया था, इसलिए हो सकता है कि यह सही से काम न करे. देखें कि अपडेट मौजूद हैं या नहीं, या फिर डेवलपर से संपर्क करें."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"देखें कि अपडेट मौजूद है या नहीं"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"आपके पास नए संदेश हैं"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"बैटरी आम तौर पर जितने समय चलती है, उससे पहले खत्म हो सकती है"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"बैटरी लाइफ़ बढ़ाने के लिए \'बैटरी सेवर\' चालू हो गया है"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"बैटरी सेवर"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"बैटरी सेवर बंद कर दिया गया है"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"फ़ोन में काफ़ी बैटरी बची है. सुविधाओं पर अब पाबंदी नहीं है."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"टैबलेट में काफ़ी बैटरी बची है. सुविधाओं पर अब पाबंदी नहीं है."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"डिवाइस में काफ़ी बैटरी बची है. सुविधाओं पर अब पाबंदी नहीं है."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"फ़ोल्डर"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android ऐप्लिकेशन"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"फ़ाइल"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> स्प्रेडशीट"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"प्रज़ेंटेशन"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> प्रज़ेंटेशन"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"हवाई जहाज़ मोड के दौरान ब्लूटूथ चालू रहेगा"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"प्राेफ़ाइल लोड हो रही है"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> फ़ाइलें</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"स्प्लिट स्क्रीन पर टॉगल करें"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"स्क्रीन लॉक करें"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"स्क्रीनशॉट लें"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> का कैप्शन बार."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> को प्रतिबंधित बकेट में रखा गया है"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 9737187..e4cefe8 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -196,6 +196,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Uređaj će se izbrisati"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Administratorska aplikacija ne može se upotrebljavati. Uređaj će se izbrisati.\n\nAko imate pitanja, obratite se administratoru organizacije."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Ispis je onemogućila aplikacija <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Ja"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opcije tabletnog uređaja"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Opcije Android TV-a"</string>
@@ -1631,10 +1635,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Netočno ste iscrtali obrazac za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Nakon još ovoliko neuspješnih pokušaja: <xliff:g id="NUMBER_1">%2$d</xliff:g> morat ćete otključati telefon pomoću računa e-pošte.\n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Ukloni"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Želite li pojačati zvuk iznad preporučene razine?\n\nDugotrajno slušanje glasne glazbe može vam oštetiti sluh."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Želite li upotrebljavati prečac za pristupačnost?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Kada je taj prečac uključen, pritiskom na obje tipke za glasnoću na 3 sekunde pokrenut će se značajka pristupačnosti.\n\n Trenutačna značajka pristupačnosti:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Značajku možete promijeniti u Postavkama &gt; Pristupačnost."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Prazno"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Uredi prečace"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Otkaži"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Isključi prečac"</string>
@@ -1879,11 +1884,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Aplikacija nije dostupna"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"Aplikacija <xliff:g id="APP_NAME_0">%1$s</xliff:g> trenutačno nije dostupna. Ovime upravlja aplikacija <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Saznajte više"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Želite uključiti radni profil?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Uključit će se vaše radne aplikacije, obavijesti, podaci i druge značajke radnog profila"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Uključi"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"Aplikacija nije dostupna"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> trenutačno nije dostupna."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ova je aplikacija razvijena za stariju verziju Androida i možda neće funkcionirati pravilno. Potražite ažuriranja ili se obratite razvojnom programeru."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Provjeri ažuriranja"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Imate nove poruke"</string>
@@ -2017,6 +2022,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> proračunska tablica"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Prezentacija"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> prezentacija"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth će ostati uključen tijekom načina rada u zrakoplovu"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Učitavanje"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> i još <xliff:g id="COUNT_3">%d</xliff:g> datoteka</item>
@@ -2035,5 +2041,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Uključite ili isključite podijeljeni zaslon"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Zaključajte zaslon"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Snimka zaslona"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Traka naslova aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Paket <xliff:g id="PACKAGE_NAME">%1$s</xliff:g> premješten je u spremnik OGRANIČENO"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 4884cf7..08cb1c7 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"A rendszer törölni fogja eszközét"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"A rendszergazdai alkalmazás nem használható. A rendszer most törli az eszközt.\n\nKérdéseivel forduljon szervezete rendszergazdájához."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"A(z) <xliff:g id="OWNER_APP">%s</xliff:g> letiltotta a nyomtatást."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Saját"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Táblagép beállításai"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV beállításai"</string>
@@ -1609,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"<xliff:g id="NUMBER_0">%1$d</xliff:g> alkalommal helytelenül rajzolta le a feloldási mintát. További <xliff:g id="NUMBER_1">%2$d</xliff:g> sikertelen kísérlet után egy e-mail fiók használatával kell feloldania a telefonját.\n\n Kérjük, próbálja újra <xliff:g id="NUMBER_2">%3$d</xliff:g> másodperc múlva."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Eltávolítás"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Az ajánlott szint fölé szeretné emelni a hangerőt?\n\nHa hosszú időn át teszi ki magát nagy hangerőnek, azzal károsíthatja a hallását."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Szeretné használni a Kisegítő lehetőségek billentyűparancsot?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Ha be van kapcsolva a billentyűparancs, a két hangerőgomb 3 másodpercig tartó lenyomásával elindíthatja a kisegítő lehetőségek egyik funkcióját.\n\n A kisegítő lehetőségek jelenleg beállított funkciója:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n A funkciót a Beállítások &gt; Kisegítő lehetőségek menüpontban módosíthatja."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Üres"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Gyorsparancsszerkesztés"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Mégse"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Billentyűparancs kikapcsolása"</string>
@@ -1847,11 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Az alkalmazás nem áll rendelkezésre"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"A(z) <xliff:g id="APP_NAME_0">%1$s</xliff:g> alkalmazás jelenleg nem áll rendelkezésre. Ezt a(z) <xliff:g id="APP_NAME_1">%2$s</xliff:g> kezeli."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"További információ"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Bekapcsolja a munkaprofilt?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"A munkahelyi alkalmazások, értesítések, adatok és a munkaprofilhoz tartozó egyéb funkciók be lesznek kapcsolva"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Bekapcsolás"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"Az alkalmazás nem hozzáférhető"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> jelenleg nem hozzáférhető."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ez az alkalmazás az Android egyik korábbi verziójához készült, így elképzelhető, hogy nem működik majd megfelelően ezen a rendszeren. Keressen frissítéseket, vagy vegye fel a kapcsolatot a fejlesztővel."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Frissítés keresése"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Új üzenetei érkeztek"</string>
@@ -1984,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g>-táblázat"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Prezentáció"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g>-prezentáció"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"A Bluetooth repülős üzemmódban is bekapcsolva marad"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Betöltés"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> fájl</item>
@@ -2001,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Osztott képernyő be- vagy kikapcsolása"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Lezárási képernyő"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Képernyőkép"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazás címsora."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"A következő csomag a KORLÁTOZOTT csoportba került: <xliff:g id="PACKAGE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 7491539..9d33f6b 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Ձեր սարքը ջնջվելու է"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Հնարավոր չէ օգտագործել ադմինիստրատորի հավելվածը։ Ձեր սարքից բոլոր տվյալները կջնջվեն։\n\nՀարցեր ունենալու դեպքում դիմեք ձեր կազմակերպության ադմինիստրատորին։"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Տպումն անջատված է <xliff:g id="OWNER_APP">%s</xliff:g> հավելվածի կողմից։"</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Իմ"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Պլանշետի ընտրանքները"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV-ի կարգավորումներ"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"օգտագործել օրացույցը"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"ուղարկել և դիտել SMS-ները"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Ֆայլեր և մեդիա"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"օգտագործել լուսանկարները, մեդիա ֆայլերը և ձեր սարքում պահվող մյուս ֆայլերը"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Խոսափող"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ձայնագրել"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Կարող է հպել, թերթել, պտղունցել և կատարել այլ ժեստեր:"</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Մատնահետքերի սկաների ժեստեր"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Կարող է արձանագրել մատնահետքերի սկաների վրա կատարվող ժեստերը"</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Սքրինշոթի ստեղծում"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Կարող է ստեղծել էկրանի սքրինշոթ։"</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"անջատել կամ փոփոխել կարգավիճակի գոտին"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Թույլ է տալիս հավելվածին անջատել կարգավիճակի գոտին կամ ավելացնել ու հեռացնել համակարգի պատկերակները:"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"լինել կարգավիճակի գոտի"</string>
@@ -641,7 +642,7 @@
     <string name="permdesc_handoverStatus" msgid="3842269451732571070">"Ծրագրին թույլ է տալիս ստանալ Android Beam-ով ընթացիկ փոխանցումների մասին տեղեկատվություն:"</string>
     <string name="permlab_removeDrmCertificates" msgid="710576248717404416">"հեռացնել DRM վկայագրեր"</string>
     <string name="permdesc_removeDrmCertificates" msgid="4068445390318355716">"Ծրագրին թույլ է տալիս հեռացնել DRM վկայագրեր: Սովորական ծրագրերի համար երբեք պետք չի գալիս:"</string>
-    <string name="permlab_bindCarrierMessagingService" msgid="3363450860593096967">"Կապակցում օպերատորի հաղորդագրությունների ծառայության հետ"</string>
+    <string name="permlab_bindCarrierMessagingService" msgid="3363450860593096967">"Միացում օպերատորի հաղորդագրությունների ծառայության հետ"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="6316457028173478345">"Թույլ է տալիս տիրոջը կապվել օպերատորի հաղորդագրությունների ծառայության վերին մակարդակի միջերեսի հետ: Սա երբեք չի պահանջվում սովորական հավելվածների համար:"</string>
     <string name="permlab_bindCarrierServices" msgid="2395596978626237474">"կապվել օպերատորի ծառայություններին"</string>
     <string name="permdesc_bindCarrierServices" msgid="9185614481967262900">"Թույլ է տալիս սեփականատիրոջը կապվել օպերատորի ծառայություններին: Սովորական հավելվածների դեպքում չի պահանջվում:"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Դուք <xliff:g id="NUMBER_0">%1$d</xliff:g> անգամ սխալ եք հավաքել ձեր ապակողպման նմուշը: <xliff:g id="NUMBER_1">%2$d</xliff:g> անգամից ավել անհաջող փորձերից հետո ձեզ կառաջարկվի ապակողպել ձեր հեռախոսը` օգտագործելով էլփոստի հաշիվ:\n\n Փորձեք կրկին <xliff:g id="NUMBER_2">%3$d</xliff:g> վայրկյանից:"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Հեռացնել"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Ձայնը բարձրացնե՞լ խորհուրդ տրվող մակարդակից ավել:\n\nԵրկարատև բարձրաձայն լսելը կարող է վնասել ձեր լսողությունը:"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Օգտագործե՞լ Մատչելիության դյուրանցումը։"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Հատուկ գործառույթն օգտագործելու համար սեղմեք և 3 վայրկյան սեղմած պահեք ձայնի ուժգնության երկու կոճակները, երբ գործառույթը միացված է։\n\n Մատչելիության ակտիվ գործառույթը՝\n<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Գործառույթը կարող եք փոփոխել՝ անցնելով Կարգավորումներ &gt; Հատուկ գործառույթներ։"</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Դատարկ"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Փոփոխել դյուրանցումները"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Չեղարկել"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Անջատել դյուրանցումը"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Հավելվածը հասանելի չէ"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> հավելվածը հասանելի չէ։ Դրա աշխատանքը սահմանափակում է <xliff:g id="APP_NAME_1">%2$s</xliff:g> հավելվածը։"</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Մանրամասն"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Միացնե՞լ աշխատանքային պրոֆիլը"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Ձեր աշխատանքային հավելվածները, ծանուցումները, տվյալները և աշխատանքային պրոֆիլի մյուս գործառույթները կմիանան"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Միացնել"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Այս հավելվածը ստեղծվել է Android-ի ավելի հին տարբերակի համար և կարող է պատշաճ չաշխատել: Ստուգեք թարմացումների առկայությունը կամ դիմեք մշակողին:"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Ստուգել նոր տարբերակի առկայությունը"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Դուք ունեք նոր հաղորդագրություններ"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Մարտկոցի լիցքը կարող է սովորականից շուտ սպառվել"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Մարտկոցի կյանքը երկարացնելու համար ակտիվացվել է մարտկոցի տնտեսման ռեժիմը"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Մարտկոցի տնտեսում"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Մարտկոցի տնտեսումն անջատված է"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Հեռախոսի լիցքը բավարար է։ Գործառույթներն այլևս չեն սահմանափակվում։"</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Պլանշետի լիցքը բավարար է։ Գործառույթներն այլևս չեն սահմանափակվում։"</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Սարքի լիցքը բավարար է։ Գործառույթներն այլևս չեն սահմանափակվում։"</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"Պանակ"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android հավելված"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Ֆայլ"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> աղյուսակ"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Ներկայացում"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> ներկայացում"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Ավիառեժիմի ժամանակ Bluetooth-ը չի անջատվի"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Բեռնում"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ֆայլ</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Միացնել/անջատել էկրանի տրոհումը"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Կողպէկրան"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Սքրինշոթ"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի ենթագրերի գոտին։"</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> փաթեթը գցվեց ՍԱՀՄԱՆԱՓԱԿՎԱԾ զամբյուղի մեջ"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 9cfe6d9..4813610 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Perangkat akan dihapus"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Aplikasi admin tidak dapat digunakan. Perangkat Anda kini akan dihapus.\n\nJika ada pertanyaan, hubungi admin organisasi."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Fitur pencetakan dinonaktifkan oleh <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Saya"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opsi tablet"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Opsi Android TV"</string>
@@ -1609,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali salah menggambar pola pembuka kunci. Setelah <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi upaya gagal, Anda akan diminta membuka kunci ponsel menggunakan akun email.\n\nCoba lagi dalam <xliff:g id="NUMBER_2">%3$d</xliff:g> detik."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Hapus"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Mengeraskan volume di atas tingkat yang disarankan?\n\nMendengarkan dengan volume keras dalam waktu yang lama dapat merusak pendengaran Anda."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Gunakan Pintasan Aksesibilitas?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Saat pintasan aktif, menekan kedua tombol volume selama 3 detik akan memulai fitur aksesibilitas.\n\n Fitur aksesibilitas saat ini:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Anda dapat mengubah fitur di Setelan &gt; Aksesibilitas."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Kosong"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit pintasan"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Batal"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Nonaktifkan Pintasan"</string>
@@ -1847,11 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Aplikasi tidak tersedia"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> saat ini tidak tersedia. Aplikasi ini dikelola oleh <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Pelajari lebih lanjut"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Aktifkan profil kerja?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Aplikasi kerja, notifikasi, data, dan fitur profil kerja lainnya akan diaktifkan"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Aktifkan"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"Aplikasi tidak tersedia"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak tersedia saat ini."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Aplikasi ini dibuat untuk Android versi lama dan mungkin tidak berfungsi sebagaimana mestinya. Coba periksa apakah ada update, atau hubungi developer."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Periksa apakah ada update"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Ada pesan baru"</string>
@@ -1984,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"Spreadsheet <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Presentasi"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Presentasi <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth akan tetap aktif selama mode pesawat"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Memuat"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> file</item>
@@ -2001,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Aktifkan/Nonaktifkan Layar Terpisah"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Layar Kunci"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Screenshot"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Kolom teks <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> telah dimasukkan ke dalam bucket DIBATASI"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index f7c3b5c..bf3fe87 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Tækið verður hreinsað"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Ekki er hægt að nota stjórnunarforritið. Tækinu verður eytt.\n\nEf spurningar vakna skaltu hafa samband við kerfisstjóra fyrirtækisins."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> lokaði á prentun."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Ég"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Valkostir spjaldtölvu"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Valkostir Android TV"</string>
@@ -1609,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Þú hefur teiknað rangt opnunarmynstur <xliff:g id="NUMBER_0">%1$d</xliff:g> sinnum. Eftir <xliff:g id="NUMBER_1">%2$d</xliff:g> árangurslausar tilraunir í viðbót verður þú beðin(n) um að opna símann með tölvupóstreikningi.\n\n Reyndu aftur eftir <xliff:g id="NUMBER_2">%3$d</xliff:g> sekúndur."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Fjarlægja"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Hækka hljóðstyrk umfram ráðlagðan styrk?\n\nEf hlustað er á háum hljóðstyrk í langan tíma kann það að skaða heyrnina."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Viltu nota aðgengisflýtileið?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Þegar flýtileiðin er virk er kveikt á aðgengiseiginleikanum með því að halda báðum hljóðstyrkshnöppunum inni í þrjár sekúndur.\n\n Virkur aðgengiseiginleiki:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Hægt er að skipta um eiginleika í Stillingar &gt; Aðgengi."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Autt"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Breyta flýtileiðum"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Hætta við"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Slökkva á flýtileið"</string>
@@ -1847,11 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Forritið er ekki í boði"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> er ekki í boði eins og er. Þessu er stjórnað með <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Nánari upplýsingar"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Kveikja á vinnusniði?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Kveikt verður á vinnuforritum, tilkynningum, gögnum og öðrum eiginleikum vinnusniðsins"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Kveikja"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"Forrit er ekki tiltækt"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> er ekki tiltækt núna."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Þetta forrit var hannað fyrir eldri útgáfu af Android og ekki er víst að það virki eðlilega. Athugaðu hvort uppfærslur séu í boði eða hafðu samband við þróunaraðilann."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Leita að uppfærslu"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Þú ert með ný skilaboð"</string>
@@ -1984,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g>-töflureiknir"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Kynning"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g>-kynning"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Áfram verður kveikt á Bluetooth í flugstillingu"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Hleður"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> skrá</item>
@@ -2001,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Breyta skjáskiptingu"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Lásskjár"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Skjámynd"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Skjátextastika <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> var sett í flokkinn TAKMARKAÐ"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 387d52e..72ca138 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Il dispositivo verrà resettato"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Impossibile usare l\'app di amministrazione. Il dispositivo verrà resettato.\n\nPer eventuali domande, contatta l\'amministratore della tua organizzazione."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Stampa disattivata da <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Io"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opzioni tablet"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Opzioni Android TV"</string>
@@ -1609,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"<xliff:g id="NUMBER_0">%1$d</xliff:g> tentativi errati di inserimento della sequenza di sblocco. Dopo altri <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativi falliti, ti verrà chiesto di sbloccare il telefono con un account email.\n\n Riprova tra <xliff:g id="NUMBER_2">%3$d</xliff:g> secondi."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Rimuovi"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vuoi aumentare il volume oltre il livello consigliato?\n\nL\'ascolto ad alto volume per lunghi periodi di tempo potrebbe danneggiare l\'udito."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Usare la scorciatoia Accessibilità?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Quando la scorciatoia è attiva, puoi premere entrambi i pulsanti del volume per tre secondi per avviare una funzione di accessibilità.\n\n Funzione di accessibilità corrente:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Puoi cambiare la funzione in Impostazioni &gt; Accessibilità."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Svuota"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Modifica scorciatoie"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Annulla"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Disattiva scorciatoia"</string>
@@ -1847,11 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"App non disponibile"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> non è al momento disponibile. Viene gestita tramite <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Ulteriori informazioni"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Attivare il profilo di lavoro?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Le tue app di lavoro, le notifiche, i dati e altri elementi del profilo di lavoro saranno attivati."</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Attiva"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"L\'app non è disponibile"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"L\'app <xliff:g id="APP_NAME">%1$s</xliff:g> non è al momento disponibile."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Questa app è stata realizzata per una versione precedente di Android e potrebbe non funzionare correttamente. Prova a verificare la disponibilità di aggiornamenti o contatta lo sviluppatore."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Verifica la presenza di aggiornamenti"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Hai nuovi messaggi"</string>
@@ -1984,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"Foglio di lavoro <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Presentazione"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Presentazione <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Il Bluetooth rimane attivo durante l\'uso della modalità aereo"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Caricamento"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> file</item>
@@ -2001,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Attiva/disattiva schermo diviso"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Schermata di blocco"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Screenshot"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Barra del titolo di <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> è stato inserito nel bucket RESTRICTED"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index cf6fa22..9c8d0a3 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -198,6 +198,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"תתבצע מחיקה של המכשיר"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"לא ניתן להשתמש באפליקציה של מנהל המערכת.\n\nאם יש לך שאלות, יש ליצור קשר עם מנהל המערכת של הארגון."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"ההדפסה הושבתה על ידי <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"אני"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"אפשרויות טאבלט"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"‏אפשרויות Android TV"</string>
@@ -293,8 +297,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"גישה אל היומן"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"‏שליחה והצגה של הודעות SMS"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"קבצים ומדיה"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"גישה לתמונות, למדיה ולקבצים במכשיר שלך"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"מיקרופון"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"הקלטת אודיו"</string>
@@ -320,10 +323,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"יכול להקיש, להחליק, לעשות תנועת צביטה ולבצע תנועות אחרות."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"תנועות של טביעות אצבעות"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"אפשרות לזהות תנועות בזמן נגיעה בחיישן טביעות האצבע של המכשיר."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"שמירת צילום המסך"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ניתן לצלם צילום מסך של התצוגה."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"השבת או שנה את שורת המצב"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"מאפשר לאפליקציה להשבית את שורת המצב או להוסיף ולהסיר סמלי מערכת."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"להיות שורת הסטטוס"</string>
@@ -1656,10 +1657,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"שרטטת את קו ביטול הנעילה באופן שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, תתבקש לבטל את נעילת הטלפון באמצעות חשבון אימייל‏.\n\nנסה שוב בעוד <xliff:g id="NUMBER_2">%3$d</xliff:g> שניות."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"הסר"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"האם להעלות את עוצמת הקול מעל לרמה המומלצת?\n\nהאזנה בעוצמת קול גבוהה למשכי זמן ממושכים עלולה לפגוע בשמיעה."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"להשתמש בקיצור הדרך לתכונת הנגישות?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"כשקיצור הדרך מופעל, לחיצה על שני לחצני עוצמת השמע למשך שלוש שניות מפעילה את תכונת הנגישות.\n\n תכונת הנגישות המוגדרת כרגע:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n אפשר לשנות את התכונה בקטע \'הגדרות ונגישות\'."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"ריק"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"עריכת קיצורי הדרך"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"ביטול"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"כבה את קיצור הדרך"</string>
@@ -1914,13 +1916,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"האפליקציה אינה זמינה"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"האפליקציה <xliff:g id="APP_NAME_0">%1$s</xliff:g> לא זמינה כרגע. את הזמינות שלה אפשר לנהל באפליקציה <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"מידע נוסף"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"להפעיל את פרופיל העבודה?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"אפליקציות העבודה, התראות, נתונים ותכונות נוספות של פרופיל העבודה יופעלו"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"הפעל"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"‏האפליקציה הזו עוצבה לגרסה ישנה יותר של Android וייתכן שלא תפעל כראוי. ניתן לבדוק אם יש עדכונים או ליצור קשר עם המפתח."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"האם יש עדכון חדש?"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"יש לך הודעות חדשות"</string>
@@ -2033,14 +2033,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"הסוללה עלולה להתרוקן לפני המועד הרגיל של הטעינה"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"תכונת החיסכון בסוללה הופעלה כדי להאריך את חיי הסוללה"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"חיסכון בסוללה"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"\'חיסכון בסוללה\' כבוי"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"הטלפון טעון מספיק. התכונות כבר לא מוגבלות."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"הטאבלט טעון מספיק. התכונות כבר לא מוגבלות."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"המכשיר טעון מספיק. התכונות כבר לא מוגבלות."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"תיקייה"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"‏אפליקציית Android"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"קובץ"</string>
@@ -2059,6 +2055,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"גיליון אלקטרוני <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"מצגת"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"מצגת <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"‏Bluetooth יישאר מופעל במהלך מצב טיסה"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"בטעינה"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="two"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> קבצים</item>
@@ -2078,5 +2075,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"החלפת מצב של מסך מפוצל"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"מסך הנעילה"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"צילום מסך"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"סרגל כיתוב של <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> התווספה לקטגוריה \'מוגבל\'"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index e7f5e85..529d011 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"デバイスのデータが消去されます"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"管理アプリを使用できません。デバイスのデータはこれから消去されます。\n\nご不明な点がある場合は、組織の管理者にお問い合わせください。"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"「<xliff:g id="OWNER_APP">%s</xliff:g>」により印刷は無効にされています。"</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"自分"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"タブレットオプション"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV のオプション"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"カレンダーへのアクセス"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMSメッセージの送信と表示"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"ファイルとメディア"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"デバイス内の写真、メディア、ファイルへのアクセス"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"マイク"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"音声の録音"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"タップ、スワイプ、ピンチ、その他の操作を行えます。"</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"指紋認証センサーでの操作"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"デバイスの指紋認証センサーで行われた操作をキャプチャできます。"</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"スクリーンショットの撮影"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ディスプレイのスクリーンショットを撮影できます。"</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"ステータスバーの無効化や変更"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"ステータスバーの無効化、システムアイコンの追加や削除をアプリに許可します。"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"ステータスバーへの表示"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%1$d</xliff:g>回間違えました。あと<xliff:g id="NUMBER_1">%2$d</xliff:g>回間違えると、モバイルデバイスのロック解除にメールアカウントが必要になります。\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g>秒後にもう一度お試しください。"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" - "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"削除"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"推奨レベルを超えるまで音量を上げますか?\n\n大音量で長時間聞き続けると、聴力を損なう恐れがあります。"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ユーザー補助機能のショートカットの使用"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"ショートカットが ON の場合、両方の音量ボタンを 3 秒間押し続けるとユーザー補助機能が起動します。\n\n現在のユーザー補助機能:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\nユーザー補助機能は [設定] &gt; [ユーザー補助] で変更できます。"</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"空"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ショートカットの編集"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"キャンセル"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"ショートカットを OFF にする"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"このアプリは使用できません"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"現在、<xliff:g id="APP_NAME_0">%1$s</xliff:g> は使用できません。このアプリの使用は [<xliff:g id="APP_NAME_1">%2$s</xliff:g>] で管理されています。"</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"詳細"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"仕事用プロファイルの有効化"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"仕事用のアプリ、通知、データなど、仕事用プロファイルの機能が ON になります"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"ON にする"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"このアプリは以前のバージョンの Android 用に作成されており、正常に動作しない可能性があります。アップデートを確認するか、デベロッパーにお問い合わせください。"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"アップデートを確認"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"新着メッセージがあります"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"通常の充電を行う前に電池が切れる可能性があります"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"電池を長持ちさせるため、バッテリー セーバーが有効になりました"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"バッテリー セーバー"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"バッテリー セーバーが OFF になりました"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"スマートフォンが十分に充電されました。機能は制限されなくなりました。"</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"タブレットが十分に充電されました。機能は制限されなくなりました。"</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"デバイスが十分に充電されました。機能は制限されなくなりました。"</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"フォルダ"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android アプリ"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"ファイル"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> スプレッドシート"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"プレゼンテーション"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> プレゼンテーション"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"機内モードでも Bluetooth はオンのままになります"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"読み込んでいます"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g>、他 <xliff:g id="COUNT_3">%d</xliff:g> ファイル</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"分割画面の切り替え"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"ロック画面"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"スクリーンショット"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> のキャプション バーです。"</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> は RESTRICTED バケットに移動しました。"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 5d4a560..3f97338 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"თქვენი მოწყობილობა წაიშლება"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"ადმინისტრატორის აპის გამოყენება ვერ მოხერხდება. თქვენი მოწყობილობა ახლა ამოიშლება.\n\nთუ შეკითხვები გაქვთ, დაუკავშირდით თქვენი ორგანიზაციის ადმინისტრატორს."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"ბეჭდვა გათიშულია <xliff:g id="OWNER_APP">%s</xliff:g>-ის მიერ."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"მე"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"ტაბლეტის პარამეტრები"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV ვარიანტები"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"თქვენს კალენდარზე წვდომა"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS შეტყობინებების გაგზავნა და ნახვა"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"ფაილები და მედია"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"თქვენს მოწყობილობაზე არსებულ ფოტოებზე, მედიასა და ფაილებზე წვდომა"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"მიკროფონი"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"აუდიოს ჩაწერა"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"შეუძლია შეხება, გადაფურცვლა, მასშტაბირება და სხვა ჟესტების შესრულება."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"თითის ანაბეჭდის ჟესტები"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"შეუძლია აღბეჭდოს მოწყობილობის თითის ანაბეჭდის სენსორზე განხორციელებული ჟესტები."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ეკრანის ანაბეჭდის გადაღება"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"შეუძლია ეკრანის ანაბეჭდის გადაღება."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"სტატუსის ზოლის გათიშვა ან ცვლილება"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"აპს შეეძლება სტატუსების ზოლის გათიშვა და სისტემის ხატულების დამატება/წაშლა."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"სტატუსის ზოლის ჩანაცვლება"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"თქვენ არასწორად დახატეთ თქვენი განბლოკვის ნიმუში <xliff:g id="NUMBER_0">%1$d</xliff:g>-ჯერ. კიდევ <xliff:g id="NUMBER_1">%2$d</xliff:g> წარუმატებელი ცდის შემდეგ, დაგჭირდებათ თქვენი ტელეფონის განბლოკვა ელფოსტის ანგარიშის გამოყენებით.\n\n ხელახლა სცადეთ <xliff:g id="NUMBER_2">%3$d</xliff:g> წამში."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ამოშლა"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"გსურთ ხმის რეკომენდებულ დონეზე მაღლა აწევა?\n\nხანგრძლივად ხმამაღლა მოსმენით შესაძლოა სმენადობა დაიზიანოთ."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"გსურთ მარტივი წვდომის მალსახმობის გამოყენება?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"მალსახმობის ჩართვის შემთხვევაში, ხმის ორივე ღილაკზე 3 წამის განმავლობაში დაჭერით მარტივი წვდომის ფუნქცია ჩაირთვება.\n\n მარტივი წვდომის ამჟამინდელი ფუნქციაა:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n ამ ფუნქციის შეცვლა შეგიძლიათ აქ: პარამეტრები &gt; მარტივი წვდომა."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"ცარიელი"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"მალსახმობების რედაქტირება"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"გაუქმება"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"მალსახმობის გამორთვა"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"აპი მიუწვდომელია"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ამჟამად მიუწვდომელია. ის იმართება <xliff:g id="APP_NAME_1">%2$s</xliff:g>-ის მიერ."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"შეიტყვეთ მეტი"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"ჩაირთოს სამსახურის პროფილი?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"თქვენი სამსახურის აპები, შეტყობინებები, მონაცემები და სამსახურის პროფილის ყველა სხვა ფუნქცია ჩაირთვება"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"ჩართვა"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ეს აპი Android-ის ძველი ვერსიისთვის შეიქმნა და შესაძლოა სათანადოდ არ მუშაობდეს. გადაამოწმეთ განახლებები ან დაუკავშირდით დეველოპერს."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"განახლების შემოწმება"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"თქვენ ახალი შეტყობინებები გაქვთ"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"ბატარეა შეიძლება დაჯდეს დატენის ჩვეულ დრომდე"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"ბატარეის დამზოგი გააქტიურდა ბატარეის მუშაობის გასახანგრძლივლებლად"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ბატარეის დამზოგი"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"ბატარეის დამზოგი გამორთულია"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ტელეფონი საკმარისად არის დატენილი. ფუნქციები შეზღუდული აღარ არის."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"ტაბლეტი საკმარისად არის დატენილი. ფუნქციები შეზღუდული აღარ არის."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"მოწყობილობა საკმარისად არის დატენილი. ფუნქციები შეზღუდული აღარ არის."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"საქაღალდე"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android-ის აპლიკაცია"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"ფაილი"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> ელცხრილი"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"პრეზენტაცია"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> პრეზენტაცია"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth ჩართული იქნება თვითმფრინავის რეჟიმში"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"იტვირთება"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ფაილი</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"გაყოფილი ეკრანის გადართვა"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"ჩაკეტილი ეკრანი"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"ეკრანის ანაბეჭდი"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ის სუბტიტრების ზოლი."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> მოთავსდა კალათაში „შეზღუდული“"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 2acbb17..bccd3f4 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Құрылғыңыздағы деректер өшіріледі"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Әкімші қолданбасын пайдалану мүмкін емес. Қазір құрылғыдағы деректер өшіріледі\n\nСұрақтарыңыз болса, ұйым әкімшісіне хабарласыңыз."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Басып шығаруды <xliff:g id="OWNER_APP">%s</xliff:g> өшірді."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Мен"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Планшет опциялары"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV опциялары"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"күнтізбеге кіру"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS хабарларын жіберу және көру"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Файлдар және мультимедиа"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"құрылғыдағы фотосуреттерге, мультимедиаға және файлдарға қол жеткізу"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Микрофон"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"аудио жазу"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Түртуге, сырғытуға, қысуға және басқа қимылдарды орындауға болады."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Саусақ ізі сканеріндегі қимылдар"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Құрылғының саусақ ізі сенсорында орындалған қимылдарды сақтайды."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Скриншот жасау"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Дисплейдің скриншотын жасай аласыз."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"күйін көрсету тақтасын өшіру немесе өзгерту"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Қолданбаға күй жолағын өшіруге немесе жүйелік белгішелерді қосуға және жоюға рұқсат береді."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"күй жолағы болу"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Бекітпені ашу кескінін <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате сыздыңыз. <xliff:g id="NUMBER_1">%2$d</xliff:g> сәтсіз әрекеттен кейін телефоныңызды есептік жазба арқылы ашу өтінішін аласыз. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін қайта әрекеттеніңіз."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Алып тастау"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Дыбыс деңгейін ұсынылған деңгейден көтеру керек пе?\n\nЖоғары дыбыс деңгейінде ұзақ кезеңдер бойы тыңдау есту қабілетіңізге зиян тигізуі мүмкін."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Арнайы мүмкіндік төте жолын пайдалану керек пе?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Бұл төте жол қосулы кезде дыбыс деңгейі түймелерінің екеуін де 3 секунд бойы басқанда арнайы мүмкіндік іске қосылады.\n\n Ағымдағы арнайы мүмкіндік:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Бұл мүмкіндікті \"Параметрлер\" &gt; \"Арнайы мүмкіндіктер\" тармағында өзгертуге болады."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Бос"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Таңбашаларды өзгерту"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Бас тарту"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Төте жолды өшіру"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Қолданба қолжетімді емес"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> дәл қазір қолжетімді емес. Ол <xliff:g id="APP_NAME_1">%2$s</xliff:g> арқылы басқарылады."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Толығырақ"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Жұмыс профилі қосылсын ба?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Жұмыс қолданбалары, хабарландырулар, деректер және басқа да жұмыс профильдерінің мүмкіндіктері қосылады"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Қосу"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Қолданба Android жүйесінің ескі нұсқасына арналған және дұрыс жұмыс істемеуі мүмкін. Жаңартылған нұсқаны тексеріңіз немесе әзірлеушіге хабарласыңыз."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Жаңартылған нұсқаны тексеру"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Сізде жаңа хабарлар бар"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Батарея заряды азаюы мүмкін"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Батарея ұзаққа жетуі үшін, Battery Saver іске қосылды"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Battery Saver"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Battery Saver өшірілді"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Телефонның заряды жеткілікті. Функцияларға енді шектеу қойылмайды."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Планшеттің заряды жеткілікті. Функцияларға енді шектеу қойылмайды."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Құрылғының заряды жеткілікті. Функцияларға енді шектеу қойылмайды."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"Қалта"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android қолданбасы"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Файл"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> электрондық кестесі"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Презентация"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> презентациясы"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth ұшақ режимінде қосулы болады."</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Жүктелуде"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> файл</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Экранды бөлу мүмкіндігін қосу/өшіру"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Құлып экраны"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Скриншот"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасының жазу жолағы."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> ШЕКТЕЛГЕН себетке салынды."</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 0e277ef..ee451e9 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"ឧបករណ៍របស់អ្នកនឹងត្រូវបានលុប"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"មិនអាច​ប្រើ​កម្មវិធី​អ្នកគ្រប់គ្រង​បានទេ។ ឧបករណ៍​របស់អ្នក​នឹងលុប​ឥឡូវនេះ។\n\nប្រសិនបើ​អ្នកមាន​សំណួរផ្សេងៗ​ សូមទាក់ទង​ទៅអ្នក​គ្រប់គ្រង​ស្ថាប័ន​របស់​អ្នក។"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"ការបោះពុម្ព​ត្រូវបាន​បិទ​ដោយ <xliff:g id="OWNER_APP">%s</xliff:g> ។"</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"ខ្ញុំ"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"ជម្រើស​កុំព្យូទ័រ​បន្ទះ"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"ជម្រើស Android TV"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"ចូលប្រើប្រិតិទិនរបស់អ្នក"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"សារ SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"ផ្ញើ និងមើលសារ SMS"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"ឯកសារ និង​មេឌៀ"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"ចូលដំណើការរូបភាព មេឌៀ និងឯកសារនៅលើឧបករណ៍របស់អ្នក"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"មីក្រូ​ហ្វូន"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ថតសំឡេង"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"អាចប៉ះ អូស ច្បិច និងធ្វើកាយវិការផ្សេងទៀត"</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"ចលនា​ស្នាមម្រាមដៃ"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"អាចចាប់យក​ចលនា​ដែលធ្វើនៅលើ​នៅលើ​ឧបករណ៍​ចាប់​ស្នាម​ម្រាមដៃ​របស់ឧបករណ៍បាន។"</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ថត​អេក្រង់"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"អាច​ថត​អេក្រង់​នៃ​ផ្ទាំង​អេក្រង់​បាន។"</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"បិទ ឬ​កែ​របារ​ស្ថានភាព"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"ឲ្យ​កម្មវិធី​បិទ​របារ​ស្ថានភាព ឬ​បន្ថែម និង​លុប​រូប​តំណាង​ប្រព័ន្ធ។"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"ធ្វើជារបារស្ថានភាព"</string>
@@ -1614,10 +1615,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"អ្នក​បាន​គូរ​លំនាំ​ដោះ​​សោ​របស់​អ្នក​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER_0">%1$d</xliff:g> ដង។ បន្ទាប់​ពី​ការ​ព្យាយាម​មិន​ជោគជ័យ​​ច្រើនជាង <xliff:g id="NUMBER_1">%2$d</xliff:g> ដង អ្នក​នឹង​ត្រូវ​បាន​​ស្នើ​ឲ្យ​ដោះ​សោ​ទូរស័ព្ទ​របស់​អ្នក​ដោយ​ប្រើ​គណនី​អ៊ីមែល។\n\n ព្យាយាម​ម្ដង​ទៀត​ក្នុង​រយៈ​ពេល <xliff:g id="NUMBER_2">%3$d</xliff:g> វិនាទី។"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"លុប​ចេញ"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"បង្កើន​កម្រិត​សំឡេង​លើស​ពី​កម្រិត​បាន​ផ្ដល់​យោបល់?\n\nការ​ស្ដាប់​នៅ​កម្រិត​សំឡេង​ខ្លាំង​យូរ​អាច​ធ្វើឲ្យ​ខូច​ត្រចៀក។"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ប្រើប្រាស់​ផ្លូវកាត់​ភាព​ងាយស្រួល?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"នៅពេល​ផ្លូវកាត់​នេះបើក ការ​ចុច​ប៊ូតុង​កម្រិត​សំឡេង​ទាំង​ពីរ​ឲ្យ​ជាប់​រយៈពេល​ 3 វិនាទីនឹង​ចាប់ផ្តើម​មុខងារ​ភាពងាយស្រួល។\n\n មុខងារ​ភាពងាយស្រួល​បច្ចុប្បន្ន៖\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n អ្នក​អាច​ផ្លាស់​ប្តូរ​មុខងារ​នេះ​បាន​នៅក្នុង​ការ កំណត់ &gt; ភាព​ងាយស្រួល។"</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"លុបទាំងអស់"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"កែ​ផ្លូវកាត់"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"បោះបង់"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"បិទ​ផ្លូវកាត់"</string>
@@ -1852,13 +1854,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"​កម្មវិធី​មិន​អាច​ប្រើ​បានទេ"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> មិន​អាច​ប្រើ​បាន​ទេនៅពេលនេះ។ វា​ស្ថិត​ក្រោម​ការគ្រប់គ្រងរបស់ <xliff:g id="APP_NAME_1">%2$s</xliff:g> ។"</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"ស្វែងយល់បន្ថែម"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"បើក​កម្រង​ព័ត៌មាន​ការ​ងារ?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"កម្មវិធី​ការងារ ការ​ជូនដំណឹង ទិន្នន័យ និង​មុខងារ​កម្រង​ព័ត៌មាន​ការងារ​ផ្សេង​ទៀត​របស់អ្នក​នឹង​ត្រូវ​បាន​បើក"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"បើក"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"កម្មវិធី​នេះ​ត្រូវបាន​បង្កើត​ឡើង​សម្រាប់​កំណែ​ប្រព័ន្ធ​ប្រតិបត្តិការ Android ចាស់ ហើយ​វាអាច​ដំណើរការ​ខុសប្រក្រតី។ សូម​សាកល្បង​ពិនិត្យមើល​កំណែ​ថ្មី ឬ​ទាក់ទង​ទៅអ្នក​អភិវឌ្ឍន៍។"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"រក​មើល​កំណែ​ថ្មី"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"អ្នកមានសារថ្មី"</string>
@@ -1969,14 +1969,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"ថ្ម​អាច​នឹង​អស់ មុនពេល​សាកថ្មធម្មតា"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"បាន​បើក​ដំណើរការកម្មវិធី​សន្សំ​ថ្ម ដើម្បីបង្កើនកម្រិត​ថាមពល​​ថ្ម"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"កម្មវិធីសន្សំថ្ម"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"កម្មវិធី​សន្សំ​ថ្ម​ត្រូវបានបិទ"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ទូរសព្ទ​មាន​កម្រិតថ្ម​គ្រប់គ្រាន់​។ មុខងារ​ផ្សេងៗ​មិន​ត្រូវបាន​រឹតបន្តឹងទៀត​ទេ។"</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"ថេប្លេត​មាន​កម្រិតថ្ម​គ្រប់គ្រាន់​។ មុខងារ​ផ្សេងៗ​មិន​ត្រូវបាន​រឹតបន្តឹងទៀត​ទេ។"</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"ឧបករណ៍​មាន​កម្រិតថ្ម​គ្រប់គ្រាន់​។ មុខងារ​ផ្សេងៗ​មិន​ត្រូវបាន​រឹតបន្តឹងទៀត​ទេ។"</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"ថត"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"​កម្មវិធី Android"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"ឯកសារ"</string>
@@ -1995,6 +1991,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"បញ្ជី​ <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"បទ​បង្ហាញ"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"បទបង្ហាញ​ <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"ប៊្លូធូស​នឹងនៅបន្តបើក អំឡុងពេល​ប្រើមុខងារ​ពេលជិះយន្តហោះ"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"កំពុងផ្ទុក"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other">ឯកសារ <xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g></item>
@@ -2012,5 +2009,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"បិទ/បើក​មុខងារ​បំបែកអេក្រង់"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"អេក្រង់ចាក់សោ"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"រូបថតអេក្រង់"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"របារពណ៌នា​អំពី <xliff:g id="APP_NAME">%1$s</xliff:g>។"</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> ត្រូវបានដាក់​ទៅក្នុងធុង​ដែលបានដាក់កំហិត"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 50b1bba..7528284 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"ನಿಮ್ಮ ಸಾಧನವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"ನಿರ್ವಹಣೆ ಅಪ್ಲಿಕೇಶನ್ ಬಳಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ನಿಮ್ಮ ಸಾಧನವನ್ನು ಇದೀಗ ಅಳಿಸಲಾಗುತ್ತದೆ.\n\nನಿಮ್ಮಲ್ಲಿ ಪ್ರಶ್ನೆಗಳಿದ್ದರೆ, ನಿಮ್ಮ ಸಂಸ್ಥೆಯ ನಿರ್ವಾಹಕರನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ಮೂಲಕ ಪ್ರಿಂಟಿಂಗ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"ನಾನು"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"ಟ್ಯಾಬ್ಲೆಟ್ ಆಯ್ಕೆಗಳು"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV ಆಯ್ಕೆಗಳು"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"ನಿಮ್ಮ ಕ್ಯಾಲೆಂಡರ್ ಪ್ರವೇಶಿಸಲು"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಲು ಮತ್ತು ನಿರ್ವಹಿಸಲು"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"ಫೈಲ್‌ಗಳು ಮತ್ತು ಮಾಧ್ಯಮ"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"ಸಾಧನದಲ್ಲಿ ಫೋಟೋಗಳು, ಮಾಧ್ಯಮ ಮತ್ತು ಫೈಲ್‌ಗಳನ್ನು ಪ್ರವೇಶಿಸಲು"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"ಮೈಕ್ರೋಫೋನ್‌"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ಆಡಿಯೊ ರೆಕಾರ್ಡ್ ಮಾಡಿ"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"ಟ್ಯಾಪ್ ಮಾಡಬಹುದು, ಸ್ವೈಪ್ ಮಾಡಬಹುದು, ಪಿಂಚ್ ಮಾಡಬಹುದು ಮತ್ತು ಇತರ ಗೆಸ್ಚರ್‌ಗಳನ್ನು ಮಾಡಬಹುದು."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್‌ ಗೆಶ್ಚರ್‌ಗಳು"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ಸಾಧನದ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್‌ನಲ್ಲಿ ನಡೆಸಿದ ಗೆಶ್ಚರ್‌ಗಳನ್ನು ಕ್ಯಾಪ್ಚರ್ ಮಾಡಿ."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ತೆಗೆದುಕೊಳ್ಳಿ"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ಪ್ರದರ್ಶನದ ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಅನ್ನು ತೆಗೆದುಕೊಳ್ಳಬಲ್ಲದು."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ ಇಲ್ಲವೇ ಮಾರ್ಪಡಿಸಿ"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಅಥವಾ ಸೇರಿಸಲು ಮತ್ತು ಸಿಸ್ಟಂ ಐಕಾನ್‌ಗಳನ್ನು ತೆಗೆದುಹಾಕಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯಾಗಿರಲು"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"ನಿಮ್ಮ ಅನ್‍‍ಲಾಕ್ ಪ್ಯಾಟರ್ನ್ ಅನ್ನು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಡ್ರಾ ಮಾಡಿರುವಿರಿ. <xliff:g id="NUMBER_1">%2$d</xliff:g> ಹೆಚ್ಚಿನ ವಿಫಲ ಪ್ರಯತ್ನಗಳ ಬಳಿಕ, ನಿಮ್ಮ ಇಮೇಲ್ ಖಾತೆಯನ್ನು ಬಳಸಿಕೊಂಡು ನಿಮ್ಮ ಫೋನ್ ಅನ್‌ಲಾಕ್ ಮಾಡುವಂತೆ ನಿಮ್ಮಲ್ಲಿ ಕೇಳಿಕೊಳ್ಳಲಾಗುತ್ತದೆ.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ತೆಗೆದುಹಾಕು"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ವಾಲ್ಯೂಮ್‌ ಅನ್ನು ಶಿಫಾರಸು ಮಾಡಲಾದ ಮಟ್ಟಕ್ಕಿಂತಲೂ ಹೆಚ್ಚು ಮಾಡುವುದೇ?\n\nದೀರ್ಘ ಅವಧಿಯವರೆಗೆ ಹೆಚ್ಚಿನ ವಾಲ್ಯೂಮ್‌ನಲ್ಲಿ ಆಲಿಸುವುದರಿಂದ ನಿಮ್ಮ ಆಲಿಸುವಿಕೆ ಸಾಮರ್ಥ್ಯಕ್ಕೆ ಹಾನಿಯುಂಟು ಮಾಡಬಹುದು."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ಪ್ರವೇಶಿಸುವಿಕೆ ಶಾರ್ಟ್‌ಕಟ್ ಬಳಸುವುದೇ?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"ಶಾರ್ಟ್‌ಕಟ್ ಆನ್ ಆಗಿರುವಾಗ ಪ್ರವೇಶಿಸುವಿಕೆ ವೈಶಿಷ್ಟ್ಯ ಆನ್ ಮಾಡಲು, ಎರಡೂ ವಾಲ್ಯೂಮ್ ಬಟನ್‌ಗಳನ್ನು ನೀವು 3 ಸೆಕೆಂಡುಗಳ ಕಾಲ ಒತ್ತಬೇಕು.\n\nಪ್ರಸ್ತುತ ಪ್ರವೇಶಿಸುವಿಕೆ ವೈಶಿಷ್ಟ್ಯ: \n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n ಸೆಟ್ಟಿಂಗ್‌ಗಳು ಮತ್ತು ಪ್ರವೇಶಿಸುವಿಕೆಯಲ್ಲಿ ನೀವು ವೈಶಿಷ್ಟ್ಯವನ್ನು ಬದಲಾಯಿಸಬಹುದು."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"ಖಾಲಿ"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ಶಾರ್ಟ್‌ಕಟ್‌‍ಗಳನ್ನು ಎಡಿಟ್ ಮಾಡಿ"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"ರದ್ದುಗೊಳಿಸಿ"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"ಶಾರ್ಟ್‌ಕಟ್‌ ಆಫ್ ಮಾಡಿ"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"ಅಪ್ಲಿಕೇಶನ್ ಲಭ್ಯವಿಲ್ಲ"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ಅಪ್ಲಿಕೇಶನ್‌ ಸದ್ಯಕ್ಕೆ ಲಭ್ಯವಿಲ್ಲ. ಇದನ್ನು <xliff:g id="APP_NAME_1">%2$s</xliff:g> ನಲ್ಲಿ ನಿರ್ವಹಿಸಲಾಗುತ್ತಿದೆ."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್‌ ಆನ್ ಮಾಡುವುದೇ?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"ನಿಮ್ಮ ಕೆಲಸದ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು, ಅಧಿಸೂಚನೆಗಳು, ಡೇಟಾ ಮತ್ತು ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್‌ನ ಇತರ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಆನ್ ಮಾಡಲಾಗುತ್ತದೆ"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"ಆನ್‌ ಮಾಡಿ"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ಈ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು Android ನ ಹಳೆಯ ಆವೃತ್ತಿಗೆ ರಚಿಸಲಾಗಿದೆ ಮತ್ತು ಸರಿಯಾಗಿ ಕೆಲಸ ಮಾಡದಿರಬಹುದು. ಅಪ್‌ಡೇಟ್‌ಗಳನ್ನು ಪರಿಶೀಲಿಸಲು ಪ್ರಯತ್ನಿಸಿ ಅಥವಾ ಡೆವಲಪರ್ ಅನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"ಅಪ್‌ಡೇಟ್‌ಗಾಗಿ ಪರಿಶೀಲಿಸಿ"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"ನೀವು ಹೊಸ ಸಂದೇಶಗಳನ್ನು ಹೊಂದಿರುವಿರಿ"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"ಚಾರ್ಜ್‌ಗೆ ಮೊದಲೆ ಬ್ಯಾಟರಿ ಮುಗಿದು ಬಿಡಬಹುದು"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"ಬ್ಯಾಟರಿ ಅವಧಿ ಹೆಚ್ಚಿಸಲು ಬ್ಯಾಟರಿ ಸೇವರ್ ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ಬ್ಯಾಟರಿ ಸೇವರ್"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"ಬ್ಯಾಟರಿ ಸೇವರ್ ಅನ್ನು ಆಫ್ ಮಾಡಲಾಗಿದೆ"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ಫೋನ್‌ನಲ್ಲಿ ಸಾಕಷ್ಟು ಚಾರ್ಜ್ ಇದೆ. ಇನ್ನು ಮುಂದೆ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗುವುದಿಲ್ಲ."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"ಟ್ಯಾಬ್ಲೆಟ್‌ನಲ್ಲಿ ಸಾಕಷ್ಟು ಚಾರ್ಜ್ ಇದೆ. ಇನ್ನು ಮುಂದೆ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗುವುದಿಲ್ಲ."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"ಸಾಧನದಲ್ಲಿ ಸಾಕಷ್ಟು ಚಾರ್ಜ್ ಇದೆ. ಇನ್ನು ಮುಂದೆ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗುವುದಿಲ್ಲ."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"ಫೋಲ್ಡರ್"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android ಆ್ಯಪ್‌"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"ಫೈಲ್"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> ಸ್ಪ್ರೆಡ್‌ಶೀಟ್"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"ಪ್ರಸ್ತುತಿ"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> ಪ್ರಸ್ತುತಿ"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"ಏರ್‌ಪ್ಲೇನ್ ಮೋಡ್‌ನಲ್ಲಿರುವಾಗಲೂ ಬ್ಲೂಟೂತ್ ಆನ್ ಆಗಿರುತ್ತದೆ"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"ಲೋಡ್ ಆಗುತ್ತಿದೆ"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ಫೈಲ್‌ಗಳು</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"ಸ್ಪ್ಲಿಟ್-ಸ್ಕ್ರೀನ್ ಟಾಗಲ್ ಮಾಡಿ"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"ಲಾಕ್ ಸ್ಕ್ರೀನ್"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಆ್ಯಪ್‌ನ ಶೀರ್ಷಿಕೆಯ ಪಟ್ಟಿ."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> ಅನ್ನು ನಿರ್ಬಂಧಿತ ಬಕೆಟ್‌ಗೆ ಹಾಕಲಾಗಿದೆ"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 7e12490..d5b4507 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"기기가 삭제됩니다."</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"관리자 앱을 사용할 수 없습니다. 곧 기기가 삭제됩니다.\n\n궁금한 점이 있으면 조직의 관리자에게 문의하세요."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g>에 의해 사용 중지되었습니다."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"나"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"태블릿 옵션"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV 옵션"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"캘린더에 액세스"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS 메시지 전송 및 보기"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"파일 및 미디어"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"기기 사진, 미디어, 파일 액세스"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"마이크"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"오디오 녹음"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"탭, 스와이프, 확대/축소 및 기타 동작을 실행할 수 있습니다."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"지문 동작"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"기기 지문 센서에서 동작을 캡처합니다."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"스크린샷 촬영"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"디스플레이 스크린샷을 촬영할 수 있습니다."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"상태 표시줄 사용 중지 또는 수정"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"앱이 상태 표시줄을 사용중지하거나 시스템 아이콘을 추가 및 제거할 수 있도록 허용합니다."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"상태 표시줄에 위치"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"잠금해제 패턴을 <xliff:g id="NUMBER_0">%1$d</xliff:g>회 잘못 그렸습니다. <xliff:g id="NUMBER_1">%2$d</xliff:g>회 더 실패하면 이메일 계정을 사용하여 휴대전화를 잠금해제해야 합니다.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g>초 후에 다시 시도해 주세요."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"삭제"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"권장 수준 이상으로 볼륨을 높이시겠습니까?\n\n높은 볼륨으로 장시간 청취하면 청력에 손상이 올 수 있습니다."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"접근성 단축키를 사용하시겠습니까?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"단축키가 사용 설정된 경우 두 개의 볼륨 버튼을 3초간 누르면 접근성 기능이 시작됩니다.\n\n 현재 접근성 기능:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n \'설정 &gt; 접근성\'에서 기능을 변경할 수 있습니다."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"비우기"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"단축키 수정"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"취소"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"단축키 사용 중지"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"앱을 사용할 수 없음"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g>은(는) 현재 사용할 수 없습니다. <xliff:g id="APP_NAME_1">%2$s</xliff:g>에서 관리하는 앱입니다."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"자세히 알아보기"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"직장 프로필을 사용 설정하시겠어요?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"업무용 앱, 알림, 데이터 및 기타 직장 프로필 기능이 사용 설정됩니다."</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"사용 설정"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"이 앱은 Android 이전 버전에 맞게 개발되었기 때문에 제대로 작동하지 않을 수 있습니다. 업데이트를 확인하거나 개발자에게 문의하세요."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"업데이트 확인"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"새 메시지 있음"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"평소에 충전하는 시간 전에 배터리가 소진될 수 있습니다."</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"배터리 수명을 연장하기 위해 배터리 세이버가 활성화되었습니다."</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"절전 모드"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"절전 모드가 사용 중지되었습니다"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"휴대전화의 배터리가 충분하므로 기능이 더 이상 제한되지 않습니다"</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"태블릿의 배터리가 충분하므로 기능이 더 이상 제한되지 않습니다"</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"기기의 배터리가 충분하므로 기능이 더 이상 제한되지 않습니다"</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"폴더"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android 애플리케이션"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"파일"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> 스프레드시트"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"프레젠테이션"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> 프레젠테이션"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"비행기 모드에서 블루투스가 켜진 상태로 유지됩니다."</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"로드 중"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> 및 파일 <xliff:g id="COUNT_3">%d</xliff:g>개</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"화면 분할 모드 전환"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"잠금 화면"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"스크린샷"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g>의 자막 표시줄입니다."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> 항목이 RESTRICTED 버킷으로 이동함"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index c887c34..533e0b8 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Түзмөгүңүз тазаланат"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Түзмөктү башкаруучу колдонмо жараксыз. Түзмөгүңүз азыр тазаланат.\n\nСуроолоруңуз болсо, ишканаңыздын администраторуна кайрылыңыз."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Басып чыгаруу <xliff:g id="OWNER_APP">%s</xliff:g> тарабынан өчүрүлдү."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Мен"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Планшет мүмкүнчүлүктөрү"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV параметрлери"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"жылнаамаңызды пайдалануу"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS билдирүүлөрдү жиберүү жана көрсөтүү"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Файлдар жана медиа"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"түзмөгүңүздөгү сүрөттөрдү жана башка мультимедиа файлдарын пайдаланууга"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Микрофон"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"аудио жаздыруу"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Таптап, серпип, чымчып жана башка жаңсоолорду аткара алат."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Манжа изинин жаңсоолору"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Түзмөктөгү манжа изинин сенсорунда жасалган жаңсоолорду жаздырып алат."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Скриншот тартып алуу"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Дисплейдин скриншотун тартып алууга болот."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"абал тилкесин өчүрүү же өзгөртүү"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Колдонмого абал тилкесин өчүрүү же тутум сүрөтчөлөрүн кошуу же алып салуу мүмкүнчүлүгүн берет."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"абал тилкесинин милдетин аткаруу"</string>
@@ -539,7 +540,7 @@
     <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Манжа изин күтүү мөөнөтү бүттү. Кайра аракет кылыңыз."</string>
     <string name="fingerprint_error_canceled" msgid="540026881380070750">"Манжа изи иш-аракети жокко чыгарылды."</string>
     <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Манжа изи операциясын колдонуучу жокко чыгарды."</string>
-    <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Аракеттер өтө көп болду. Кийинчерээк кайра аракет кылыңыз."</string>
+    <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Аракеттер өтө көп болду. Бир аздан кийин кайталап көрүңүз."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Өтө көп жолу аракет жасадыңыз. Манжа изинин сенсору өчүрүлдү."</string>
     <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Кайра бир аракеттениңиз."</string>
     <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Бир да манжа изи катталган эмес."</string>
@@ -582,7 +583,7 @@
     <string name="face_error_no_space" msgid="5649264057026021723">"Жаңы жүздү сактоо мүмкүн эмес. Адегенде эскисин өчүрүңүз."</string>
     <string name="face_error_canceled" msgid="2164434737103802131">"Жүздүн аныктыгын текшерүү жокко чыгарылды."</string>
     <string name="face_error_user_canceled" msgid="8553045452825849843">"Жүзүнөн таануу функциясын колдонуучу өчүрүп салды."</string>
-    <string name="face_error_lockout" msgid="7864408714994529437">"Өтө көп жолу аракет жасадыңыз. Кийинчерээк кайра аракет кылыңыз."</string>
+    <string name="face_error_lockout" msgid="7864408714994529437">"Өтө көп жолу аракет жасадыңыз. Бир аздан кийин кайталап көрүңүз."</string>
     <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Өтө көп жолу аракет кылдыңыз. Жүзүнөн таануу функциясы өчүрүлдү."</string>
     <string name="face_error_unable_to_process" msgid="5723292697366130070">"Жүз ырасталбай жатат. Кайра аракет кылыңыз."</string>
     <string name="face_error_not_enrolled" msgid="7369928733504691611">"Жүзүнөн таануу функциясын жөндөй элексиз."</string>
@@ -843,9 +844,9 @@
     <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="3069635524964070596">"Кулпуну ачуу үлгүсүн <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тарттыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу туура эмес тартсаңыз, планшетиңиздин кулпусун Google\'га кирип ачууга туура келет.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундадан кийин дагы аракет кылып көрүңүз."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="6399092175942158529">"Графикалык ачкычыңызды <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес чийдиңиз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> ийгиликсиз аракеттен кийин, Android TV түзмөгүңүздүн кулпусун Google аккаунтуңузга кирип ачышыңыз керек болот.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секунддан кийин кайра аракет кылыңыз."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="5691623136957148335">"Кулпуну ачуу үлгүсүн <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тарттыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу туура эмес тартсаңыз, телефонуңуздун кулпусун Google\'га кирип ачууга туура келет.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундадан кийин дагы аракет кылып көрүңүз."</string>
-    <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="7914445759242151426">"Сиз планшетиңизди бөгөттөн чыгарууга <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес аракет кылдыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> аракеттен кийин, планшет баштапкы абалына келтирилет жана бардык маалыматтар жок кылынат."</string>
+    <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="7914445759242151426">"Сиз планшетиңизди бөгөттөн чыгарууга <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес аракет кылдыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> аракеттен кийин, планшет баштапкы абалына келтирилет жана бардык маалыматтар өчүрүлөт."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="4275591249631864248">"Android TV түзмөгүңүздүн кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> ийгиликсиз аракеттен кийин, Android TV түзмөгүңүз демейки жөндөөлөргө кайтарылып, бардык колдонуучу дайындары жоголот."</string>
-    <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="1166532464798446579">"Сиз телефонуңузду бөгөттөн чыгарууга <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес аракет кылдыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> аракеттен кийин, телефон баштапкы абалына келтирилет жана бардык маалыматтар жок кылынат."</string>
+    <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="1166532464798446579">"Сиз телефонуңузду бөгөттөн чыгарууга <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес аракет кылдыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> аракеттен кийин, телефон баштапкы абалына келтирилет жана бардык маалыматтар өчүрүлөт."</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="8682445539263683414">"Сиз планшетти бөгөттөн чыгарууга <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес аракет кылдыңыз. Планшет баштапкы абалына келтирилет."</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="2205435033340091883">"Android TV түзмөгүңүздүн кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Android TV түзмөгүңүз эми демейки жөндөөлөргө кайтарылат."</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="2203704707679895487">"Сиз телефонду бөгөттөн чыгарууга <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес аракет кылдыңыз. Телефон баштапкы абалына келтирилет."</string>
@@ -1601,9 +1602,9 @@
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="23741434207544038">"Сиз PIN-кодуңузду <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тердиңиз. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> секундадан кийин кайталаңыз."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="3328686432962224215">"Сиз сырсөзүңүздү <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тердиңиз. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> секундадан кийин кайталаңыз."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="7357404233979139075">"Сиз бөгөттөн чыгаруу үлгүсүн <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес көрсөттүңүз. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> секундадан кийин кайталаңыз."</string>
-    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="3479940221343361587">"Сиз планшетиңизди <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу ийгиликсиз бөгөттөн чыгаруу аракетин кылдыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> ийгиликсиз аракеттен кийин, планшет баштапкы абалына кайтарылат жана бардык берилиштериңиз жок кылынат."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="3479940221343361587">"Сиз планшетиңизди <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу ийгиликсиз бөгөттөн чыгаруу аракетин кылдыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> ийгиликсиз аракеттен кийин, планшет баштапкы абалына кайтарылат жана бардык берилиштериңиз өчүрүлөт."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="9064457748587850217">"Android TV түзмөгүңүздүн кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> ийгиликсиз аракеттен кийин, Android TV түзмөгүңүз демейки жөндөөлөргө кайтарылып, бардык колдонуучу дайындары жоголот."</string>
-    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="5955398963754432548">"Сиз телефонуңузду <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу ийгиликсиз бөгөттөн чыгаруу аракетин кылдыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> ийгиликсиз аракеттен кийин, телефон баштапкы абалына кайтарылат жана бардык берилиштериңиз жок кылынат."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="5955398963754432548">"Сиз телефонуңузду <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу ийгиликсиз бөгөттөн чыгаруу аракетин кылдыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> ийгиликсиз аракеттен кийин, телефон баштапкы абалына кайтарылат жана бардык берилиштериңиз өчүрүлөт."</string>
     <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2299099385175083308">"Сиз планшетиңизди <xliff:g id="NUMBER">%d</xliff:g> жолу ийгиликсиз бөгөттөн чыгаруу аракетин кылдыңыз. Планшет баштапкы абалына кайтарылат."</string>
     <string name="kg_failed_attempts_now_wiping" product="tv" msgid="5045460916106267585">"Android TV түзмөгүңүздүн кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Android TV түзмөгүңүз эми демейки жөндөөлөргө кайтарылат."</string>
     <string name="kg_failed_attempts_now_wiping" product="default" msgid="5043730590446071189">"Сиз телефонуңузду <xliff:g id="NUMBER">%d</xliff:g> жолу ийгиликсиз бөгөттөн чыгаруу аракетин кылдыңыз. Телефон баштапкы абалына кайтарылат."</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Графикалык ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес көрсөттүңүз. <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу туура эмес көрсөтүлгөндөн кийин, телефондун кулпусун ачуу үчүн Google аккаунтуңузга кирүүгө туура келет.\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> секундадан кийин кайталап көрсөңүз болот."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Алып салуу"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Сунушталган деңгээлден да катуулатып уккуңуз келеби?\n\nМузыканы узакка чейин катуу уксаңыз, угууңуз начарлап кетиши мүмкүн."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Ыкчам иштетесизби?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Атайын мүмкүнчүлүктөр функциясын пайдалануу үчүн, ал күйгүзүлгөндө, үндү катуулатып/акырындаткан эки баскычты тең үч секунддай кое бербей басып туруңуз.\n\n Учурдагы атайын мүмкүнчүлүктөрдүн жөндөөлөрү:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\nЖөндөөлөр &gt; Атайын мүмкүнчүлүктөр бөлүмүнөн өзгөртө аласыз."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Бошотуу"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Кыска жолдорду түзөтүү"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Жокко чыгаруу"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Кыска жолду өчүрүү"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Колдонмо жеткиликсиз"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> колдонмосу учурда жеткиликсиз. Анын жеткиликтүүлүгү <xliff:g id="APP_NAME_1">%2$s</xliff:g> тарабынан башкарылат."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Кеңири маалымат"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Жумуш профили күйгүзүлсүнбү?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Жумуш колдонмолоруңуз, эскертмелериңиз, дайын-даректериңиз жана жумуш профилинин башка функциялары күйгүзүлөт."</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Күйгүзүү"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Бул колдонмо Android\'дин эски версиясы үчүн иштеп чыгарылган, андыктан туура эмес иштеши мүмкүн. Жаңыртууларды издеп көрүңүз же иштеп чыгуучуга кайрылыңыз."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Жаңыртууну издөө"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Сизге жаңы билдирүүлөр келди"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Батарея кубаттоого чейин отуруп калышы мүмкүн"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Батареянын отуруп калбашы үчүн Батареяны үнөмдөгүч режими иштетилди"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Батареяны үнөмдөгүч"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Батареяны үнөмдөгүч режими өчүрүлдү"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Телефон жеткиликтүү кубатталды. Функцияны колдоно берсеңиз болот."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Планшет жеткиликтүү кубатталды. Функцияны колдоно берсеңиз болот."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Түзмөк жеткиликтүү кубатталды. Функцияны колдоно берсеңиз болот."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"Папка"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android колдонмосу"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Файл"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> форматындагы электр. жадыбал"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Презентация"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> форматындагы презентация"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth учак режиминде күйүп турат"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Жүктөлүүдө"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> файл</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Экранды бөлүүнү күйгүзүү же өчүрүү"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Кулпуланган экран"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Скриншот"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосунун маалымат тилкеси."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> ЧЕКТЕЛГЕН чакага коюлган"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 52674c0..7a3e85e 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"ອຸ​ປະ​ກອນ​ຂອງ​ທ່ານ​ຈະ​ຖືກ​ລຶບ"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"ບໍ່ສາມາດໃຊ້ແອັບຜູ້ເບິ່ງແຍງລະບົບໄດ້. ອຸປະກອນຂອງທ່ານຈະຖືກລຶບຂໍ້ມູນໃນຕອນນີ້.\n\nຫາກທ່ານມີຄຳຖາມ, ໃຫ້ຕິດຕໍ່ຜູ້ເບິ່ງແຍງລະບົບອົງກອນຂອງທ່ານ."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"ການພິມຖືກປິດໄວ້ໂດຍ <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"ຂ້າພະເຈົ້າ"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"ໂຕເລືອກແທັບເລັດ"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"ຕົວເລືອກ Android TV"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"ເຂົ້າ​ຫາ​ປະ​ຕິ​ທິນ​ຂອງ​ທ່ານ"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"ສົ່ງ ແລະ​ເບິ່ງ​ຂໍ້​ຄວາມ SMS"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"ໄຟລ໌ ແລະ ມີເດຍ"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"ເຂົ້າເຖິງຮູບຖ່າຍ, ສື່ ແລະໄຟລ໌ຢູ່ເທິງອຸປະກອນຂອງທ່ານ"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"ໄມໂຄຣໂຟນ"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ບັນທຶກສຽງ"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"ສາມາດແຕະ, ປັດນີ້ວມື, ຢິບນິ້ວມື ແລະ ດຳເນີນທ່າທາງອື່ນ."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"ທ່າທາງລາຍນິ້ວມື"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ສາມາດບັນທຶກທ່າທາງທີ່ເກີດຂຶ້ນໃນອຸປະກອນເຊັນເຊີລາຍນິ້ວມືໄດ້."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ຖ່າຍຮູບໜ້າຈໍ"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ສາມາດຖ່າຍຮູບໜ້າຈໍໄດ້."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"ປິດການນນຳໃຊ້ ຫຼື ແກ້ໄຂແຖບສະຖານະ"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"ອະນຸຍາດໃຫ້ແອັບຯປິດການເຮັດວຽກຂອງແຖບສະຖານະ ຫຼືເພີ່ມ ແລະລຶບໄອຄອນລະບົບອອກໄດ້."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"ເປັນ​ແຖບ​ສະ​ຖາ​ນະ"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"ທ່ານແຕ້ມຮູບແບບປົດລັອກຂອງທ່ານຜິດ <xliff:g id="NUMBER_0">%1$d</xliff:g> ເທື່ອແລ້ວ. ຫຼັງຈາກຄວາມພະຍາຍາມອີກ <xliff:g id="NUMBER_1">%2$d</xliff:g> ເທື່ອ ທ່ານຈະຖືກຖາມໃຫ້ປົດລັອກໂທລະສັບຂອງທ່ານດ້ວຍບັນຊີອີເມວ.\n\n ລອງໃໝ່ອີກຄັ້ງໃນ <xliff:g id="NUMBER_2">%3$d</xliff:g> ວິນາທີ."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ລຶບອອກ"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ເພີ່ມ​ລະ​ດັບ​ສຽງ​ໃຫ້​ເກີນກວ່າ​ລະ​ດັບ​ທີ່​ແນະ​ນຳ​ບໍ?\n\n​ການ​ຮັບ​ຟັງ​ສຽງ​ໃນ​ລະ​ດັບ​ທີ່​ສູງ​ເປັນ​ໄລ​ຍະ​ເວ​ລາ​ດົນ​​ອາດ​ເຮັດ​ໃຫ້​ການ​ຟັງ​ຂອງ​ທ່ານ​ມີ​ບັນ​ຫາ​ໄດ້."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ໃຊ້ປຸ່ມລັດການຊ່ວຍເຂົ້າເຖິງບໍ?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"ເມື່ອເປີດໃຊ້ປຸ່ມລັດແລ້ວ, ໃຫ້ກົດປຸ່ມສຽງທັງສອງຄ້າງໄວ້ 3 ວິນາທີເພື່ອເລີ່ມຄຸນສົມບັດການຊ່ວຍເຂົ້າເຖິງ.\n\n ຄຸນສົມບັດການຊ່ວຍເຂົ້າເຖິງປັດຈຸບັນ:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n ທ່ານສາມາດປ່ຽນຄຸນສົມບັດໄດ້ໃນການຕັ້ງຄ່າ &gt; ການຊ່ວຍເຂົ້າເຖິງ."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"ຫວ່າງເປົ່າ"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ແກ້ໄຂທາງລັດ"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"ຍົກເລີກ"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"ປິດປຸ່ມລັດ"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"ບໍ່ສາມາດໃຊ້ແອັບໄດ້"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ບໍ່ສາມາດໃຊ້ໄດ້ໃນຕອນນີ້. ມັນຖືກຈັດການໂດຍ <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"ສຶກສາເພີ່ມເຕີມ"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"ເປີດໃຊ້ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກບໍ?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"ແອັບວຽກຂອງທ່ານ, ການແຈ້ງເຕືອນ, ຂໍ້ມູນ ແລະ ຄຸນສົມບັດໂປຣໄຟລ໌ວຽກຈະຖືກເປີດໃຊ້"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"ເປີດ​"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ແອັບນີ້ຖືກສ້າງຂຶ້ນສຳລັບ Android ເວີຊັນທີ່ເກົ່າກວ່າ ແລະ ອາດເຮັດວຽກໄດ້ບໍ່ປົກກະຕິ. ໃຫ້ລອງກວດສອບເບິ່ງອັບເດດ ຫຼື ຕິດຕໍ່ຜູ້ພັດທະນາ."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"ກວດເບິ່ງອັບເດດ"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"ທ່ານມີຂໍ້ຄວາມໃໝ່"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"ແບັດເຕີຣີອາດໝົດກ່ອນການສາກຕາມປົກກະຕິ"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"ເປີດຕົວປະຢັດແບັດເຕີຣີເພື່ອຂະຫຍາຍອາຍຸແບັດເຕີຣີ"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ຕົວປະຢັດແບັດເຕີຣີ"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"ປິດຕົວປະຢັດແບັດເຕີຣີແລ້ວ"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ໂທລະສັບມີໄຟພຽງພໍແລ້ວ. ບໍ່ມີການຈຳກັດຄຸນສົມບັດອີກຕໍ່ໄປແລ້ວ."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"ແທັບເລັດມີໄຟພຽງພໍແລ້ວ. ບໍ່ມີການຈຳກັດຄຸນສົມບັດອີກຕໍ່ໄປແລ້ວ."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"ອຸປະກອນມີໄຟພຽງພໍແລ້ວ. ບໍ່ມີການຈຳກັດຄຸນສົມບັດອີກຕໍ່ໄປແລ້ວ."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"ໂຟນເດີ"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"ແອັບພລິເຄຊັນ Android"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"ໄຟລ໌"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"ສະເປຣດຊີດ <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"ພຣີເຊັນເທເຊິນ"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"ພຣີເຊັນເທເຊິນ <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth ຈະເປີດໄວ້ໃນລະຫວ່າງໂໝດຢູ່ໃນຍົນ"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"ກຳລັງໂຫລດ"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ໄຟລ໌</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"ເປີດ/ປິດການແບ່ງໜ້າຈໍ"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"ໜ້າຈໍລັອກ"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"ຮູບໜ້າຈໍ"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"ແຖບຄຳບັນຍາຍຂອງ <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> ຖືກວາງໄວ້ໃນກະຕ່າ \"ຈຳກັດ\" ແລ້ວ"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 5097d45..265c97e 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -198,6 +198,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Įrenginys bus ištrintas"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Administratoriaus programos negalima naudoti. Dabar įrenginio duomenys bus ištrinti.\n\nJei turite klausimų, susisiekite su organizacijos administratoriumi."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Neleidžiama spausdinti (<xliff:g id="OWNER_APP">%s</xliff:g>)."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Aš"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Planšetinio kompiuterio parinktys"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"„Android TV“ parinktys"</string>
@@ -1653,10 +1657,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Netinkamai nupiešėte atrakinimo piešinį <xliff:g id="NUMBER_0">%1$d</xliff:g> k. Po dar <xliff:g id="NUMBER_1">%2$d</xliff:g> nesėkm. band. būsite paprašyti atrakinti telefoną naudodami „Google“ prisijungimo duomenis.\n\n Bandykite dar kartą po <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Pašalinti"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Padidinti garsą daugiau nei rekomenduojamas lygis?\n\nIlgai klausydami dideliu garsu galite pažeisti klausą."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Naudoti spartųjį pritaikymo neįgaliesiems klavišą?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Kai spartusis klavišas įjungtas, spaudžiant abu garsumo mygtukus 3 sekundes bus paleista pritaikymo neįgaliesiems funkcija.\n\n Dabartinė pritaikymo neįgaliesiems funkcija:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>„\n“\n Funkciją galite pakeisti skiltyje „Nustatymai“ &gt; „Pritaikymas neįgaliesiems“."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Išvalyti"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Redaguoti sparčiuosius klavišus"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Atšaukti"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Išjungti spartųjį klavišą"</string>
@@ -1911,11 +1916,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Programa nepasiekiama"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"Programa „<xliff:g id="APP_NAME_0">%1$s</xliff:g>“ šiuo metu nepasiekiama. Tai tvarkoma naudojant programą „<xliff:g id="APP_NAME_1">%2$s</xliff:g>“."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Sužinoti daugiau"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Įjungti darbo profilį?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Darbo programos, pranešimai, duomenys ir kitos darbo profilio funkcijos bus išjungtos"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Įjungti"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"Programa nepasiekiama."</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"Programa „<xliff:g id="APP_NAME">%1$s</xliff:g>“ šiuo metu nepasiekiama."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ši programa sukurta naudoti senesnės versijos sistemoje „Android“ ir gali tinkamai neveikti. Pabandykite patikrinti, ar yra naujinių, arba susisiekite su kūrėju."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Tikrinti, ar yra naujinių"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Turite naujų pranešimų"</string>
@@ -2050,6 +2055,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> skaičiuoklė"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Pristatymas"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> pristatymas"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"„Bluetooth“ liks įjungtas veikiant lėktuvo režimui"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Įkeliama"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one">„<xliff:g id="FILE_NAME_2">%s</xliff:g>“ ir <xliff:g id="COUNT_3">%d</xliff:g> failas</item>
@@ -2069,5 +2075,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Perjungti išskaidyto ekrano režimą"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Užrakinimo ekranas"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Ekrano kopija"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Programos „<xliff:g id="APP_NAME">%1$s</xliff:g>“ antraštės juosta."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"„<xliff:g id="PACKAGE_NAME">%1$s</xliff:g>“ įkeltas į grupę APRIBOTA"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 7d11634f..a535f6d 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -196,6 +196,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Jūsu ierīces dati tiks dzēsti"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Administratora lietotni nevar izmantot. Ierīcē saglabātie dati tiks dzēsti.\n\nJa jums ir kādi jautājumi, sazinieties ar savas organizācijas administratoru."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Drukāšanu atspējoja <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Man"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Planšetdatora opcijas"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV opcijas"</string>
@@ -290,8 +294,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"piekļūt jūsu kalendāram"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"Īsziņas"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"sūtīt un skatīt īsziņas"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Faili un multivides saturs"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"piekļūt fotoattēliem, multividei un failiem jūsu ierīcē"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofons"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ierakstīt audio"</string>
@@ -317,10 +320,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Atbalsta pieskaršanos, vilkšanu, savilkšanu un citus žestus."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Pirksta nospieduma žesti"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Var uztvert žestus ierīces pirksta nospieduma sensorā."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ekrānuzņēmuma izveide"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Var izveidot displeja ekrānuzņēmumu."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"atspējot vai pārveidot statusa joslu"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Ļauj lietotnei atspējot statusa joslu vai pievienot un noņemt sistēmas ikonas."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"Būt par statusa joslu"</string>
@@ -1634,10 +1635,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Jūs nepareizi norādījāt atbloķēšanas kombināciju <xliff:g id="NUMBER_0">%1$d</xliff:g> reizes. Pēc vēl <xliff:g id="NUMBER_1">%2$d</xliff:g> neveiksmīgiem mēģinājumiem tālrunis būs jāatbloķē, izmantojot e-pasta kontu.\n\nMēģiniet vēlreiz pēc <xliff:g id="NUMBER_2">%3$d</xliff:g> sekundēm."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">"  — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Noņemt"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vai palielināt skaļumu virs ieteicamā līmeņa?\n\nIlgstoši klausoties skaņu lielā skaļumā, var tikt bojāta dzirde."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Vai izmantot pieejamības saīsni?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Ja saīsne ir iespējota, vienlaikus nospiežot abas skaļuma regulēšanas pogas un trīs sekundes turot tās, tiks palaista pieejamības funkcija.\n\n Pašreiz iestatītā pieejamības funkcija:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Šo funkciju var mainīt sadaļā Iestatījumi &gt; Pieejamība."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Notīrīt"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Rediģēt īsinājumtaustiņus"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Atcelt"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Izslēgt saīsni"</string>
@@ -1882,13 +1884,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Lietotne nav pieejama"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> pašlaik nav pieejama. Šo darbību pārvalda <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Uzzināt vairāk"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Vai ieslēgt darba profilu?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Tiks ieslēgtas jūsu darba lietotnes, paziņojumi, dati un citas darba profila funkcijas."</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Ieslēgt"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Šī lietotne tika izstrādāta vecākai Android versijai un var nedarboties pareizi. Meklējiet atjauninājumus vai sazinieties ar izstrādātāju."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Meklēt atjauninājumu"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Jums ir jaunas īsziņas."</string>
@@ -2000,14 +2000,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Akumulators var izlādēties pirms parastā uzlādes laika"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Aktivizēts akumulatora jaudas taupīšanas režīms, lai palielinātu akumulatora darbības ilgumu"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Akumulatora jaudas taupīšanas režīms"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Akumulatora jaudas taupīšanas režīms ir izslēgts"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Tālruņa uzlādes līmenis ir pietiekams. Funkcijas vairs netiek ierobežotas."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Planšetdatora uzlādes līmenis ir pietiekams. Funkcijas vairs netiek ierobežotas."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Ierīces uzlādes līmenis ir pietiekams. Funkcijas vairs netiek ierobežotas."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"Mape"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android lietojumprogramma"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Fails"</string>
@@ -2026,6 +2022,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> izklājlapa"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Prezentācija"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> prezentācija"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth joprojām būs ieslēgts lidojuma režīmā."</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Ielāde"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="zero"><xliff:g id="FILE_NAME_2">%s</xliff:g> un <xliff:g id="COUNT_3">%d</xliff:g> failu</item>
@@ -2044,5 +2041,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Pārslēgt ekrāna sadalīšanu"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Bloķēt ekrānu"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Ekrānuzņēmums"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Lietotnes <xliff:g id="APP_NAME">%1$s</xliff:g> subtitru josla."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Pakotne “<xliff:g id="PACKAGE_NAME">%1$s</xliff:g>” ir ievietota ierobežotā kopā."</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 72048b5..2f75269 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Уредот ќе се избрише"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Апликацијата на администраторот не може да се користи. Уредот ќе се избрише сега.\n\nАко имате прашања, контактирајте со администраторот на организацијата."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Печатењето е оневозможено од <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Јас"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Опции на таблет"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Опции на Android TV"</string>
@@ -1611,10 +1615,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Погрешно сте ја употребиле вашата шема на отклучување <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. По <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни обиди, ќе побараат од вас да го отклучите телефонот со користење сметка на е-пошта.\n\n Обидете се повторно за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунди."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Отстрани"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Да го зголемиме звукот над препорачаното ниво?\n\nСлушањето звуци со голема јачина подолги периоди може да ви го оштети сетилото за слух."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Да се користи кратенка за „Пристапност“?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Кога е вклучена кратенката, ако ги притиснете двете копчиња за јачина на звук во времетраење од 3 секунди, ќе се стартува функција на пристапност.\n\n Тековна функција на пристапност:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Функцијата може да ја промените во „Поставки“ &gt; „Пристапност“."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Испразни"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Изменете ги кратенките"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Откажи"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Исклучи ја кратенката"</string>
@@ -1849,11 +1854,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Апликацијата не е достапна"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"Апликацијата <xliff:g id="APP_NAME_0">%1$s</xliff:g> не е достапна во моментов. Со ова управува <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Дознај повеќе"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Да се вклучи работниот профил?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Вашите работни апликации, известувања, податоци и други функции на работниот профил ќе бидат вклучени"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Вклучи"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"Апликацијата не е достапна"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> не е достапна во моментов."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Апликацијава е создадена за постара верзија на Android и може да не функционира правилно. Проверете за ажурирања или контактирајте со програмерот."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Проверка за ажурирање"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Имате нови пораки"</string>
@@ -1986,6 +1991,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g>-табела"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Презентација"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g>-презентација"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth ќе остане вклучен при авионски режим"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Се вчитува"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> датотека</item>
@@ -2003,5 +2009,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Вклучи/исклучи поделен екран"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Заклучен екран"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Слика од екранот"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Насловна лента на <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> е ставен во корпата ОГРАНИЧЕНИ"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index b0bbb67..25d7212 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"നിങ്ങളുടെ ഉപകരണം മായ്‌ക്കും"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"അഡ്‌മിൻ ആപ്പ് ഉപയോഗിക്കാനാകില്ല. നിങ്ങളുടെ ഉപകരണം ഇപ്പോൾ മായ്ക്കപ്പെടും.\n\nനിങ്ങൾക്ക് ചോദ്യങ്ങൾ ഉണ്ടെങ്കിൽ, നിങ്ങളുടെ സ്ഥാപനത്തിന്റെ അഡ്‌മിനെ ബന്ധപ്പെടുക."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> പ്രിന്റിംഗ് പ്രവർത്തനരഹിതമാക്കി."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"ഞാന്‍"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"ടാബ്‌ലെറ്റ് ഓപ്‌ഷനുകൾ"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android ടിവി ഓപ്‌ഷനുകൾ"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"നിങ്ങളുടെ കലണ്ടർ ആക്‌സസ്സ് ചെയ്യുക"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS സന്ദേശങ്ങൾ അയയ്‌ക്കുകയും കാണുകയും ചെയ്യുക"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"ഫയലുകളും മീഡിയയും"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"നിങ്ങളുടെ ഉപകരണത്തിലെ ഫോട്ടോകളും മീഡിയയും ഫയലുകളും ആക്സസ് ചെയ്യുക"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"മൈക്രോഫോണ്‍"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ഓഡിയോ റെക്കോർഡ് ചെയ്യുക"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"ടാപ്പുചെയ്യാനോ സ്വൈപ്പുചെയ്യാനോ പിഞ്ചുചെയ്യാനോ മറ്റ് ജെസ്‌റ്ററുകൾ നിർവഹിക്കാനോ കഴിയും."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"ഫിംഗർപ്രിന്റ് ജെസ്‌റ്ററുകൾ"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ഉപകരണത്തിന്റെ ഫിംഗർപ്രിന്റ് സെൻസറിൽ ചെയ്‌ത ജെസ്‌റ്ററുകൾ ക്യാപ്‌ചർ ചെയ്യാനാകും."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"സ്ക്രീന്‍ഷോട്ട് എടുക്കുക"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ഡിസ്‌പ്ലേയുടെ സ്‌ക്രീൻഷോട്ട് എടുക്കാൻ കഴിയും."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"സ്റ്റാറ്റസ് ബാർ പ്രവർത്തനരഹിതമാക്കുക അല്ലെങ്കിൽ പരിഷ്‌ക്കരിക്കുക"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"നില ബാർ പ്രവർത്തരഹിതമാക്കുന്നതിന് അല്ലെങ്കിൽ സിസ്‌റ്റം ഐക്കണുകൾ ചേർക്കുന്നതിനും നീക്കംചെയ്യുന്നതിനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"സ്റ്റാറ്റസ് ബാർ ആയിരിക്കുക"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"നിങ്ങളുടെ അൺലോക്ക് പാറ്റേൺ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായി വരച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി വിജയിച്ചില്ലെങ്കിൽ, ഒരു ഇമെയിൽ അക്കൗണ്ട് ഉപയോഗിച്ച് ഫോൺ അൺലോക്ക് ചെയ്യാൻ നിങ്ങളോട് ആവശ്യപ്പെടും.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> സെക്കൻഡിനുള്ള വീണ്ടും ശ്രമിക്കുക."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"നീക്കംചെയ്യുക"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"മുകളിൽക്കൊടുത്തിരിക്കുന്ന ശുപാർശചെയ്‌ത ലെവലിലേക്ക് വോളിയം വർദ്ധിപ്പിക്കണോ?\n\nഉയർന്ന വോളിയത്തിൽ ദീർഘനേരം കേൾക്കുന്നത് നിങ്ങളുടെ ശ്രവണ ശേഷിയെ ദോഷകരമായി ബാധിക്കാം."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ഉപയോഗസഹായി കുറുക്കുവഴി ഉപയോഗിക്കണോ?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"കുറുക്കുവഴി ഓണാണെങ്കിൽ, രണ്ട് വോളിയം ബട്ടണുകളും 3 സെക്കൻഡ് നേരത്തേക്ക് അമർത്തുന്നത് ഉപയോഗസഹായി ഫീച്ചർ ആരംഭിക്കും.\n\n നിലവിലെ  ഉപയോഗസഹായി ഫീച്ചർ:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n ക്രമീകരണം &gt; ഉപയോഗസഹായി എന്നതിൽ ഏത് സമയത്തും നിങ്ങൾക്ക് ഫീച്ചർ മാറ്റാവുന്നതാണ്."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"ശൂന്യം"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"കുറുക്കുവഴികൾ തിരുത്തുക"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"റദ്ദാക്കുക"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"കുറുക്കുവഴി ‌ഓഫാക്കുക"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"ആപ്പ് ലഭ്യമല്ല"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ഇപ്പോൾ ലഭ്യമല്ല. <xliff:g id="APP_NAME_1">%2$s</xliff:g> ആണ് ഇത് മാനേജ് ചെയ്യുന്നത്."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"കൂടുതലറിയുക"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"ഔദ്യോഗിക പ്രൊഫൈൽ ഓണാക്കണോ?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"നിങ്ങളുടെ ഔദ്യോഗിക ആപ്പുകൾ, അറിയിപ്പുകൾ, ഡാറ്റ, മറ്റ് ഔദ്യോഗിക പ്രൊഫൈൽ ഫീച്ചറുകൾ എന്നിവ ഓണാക്കും"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"ഓണാക്കുക"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ഈ ആപ്പ് Android-ന്റെ പഴയ പതിപ്പിനായി നിർമ്മിച്ചിരിക്കുന്നതിനാൽ ശരിയായി പ്രവർത്തിച്ചേക്കില്ല. അപ്‌ഡേറ്റിനായി പരിശോധിക്കുക, അല്ലെങ്കിൽ ഡെവലപ്പറുമായി ബന്ധപ്പെടുക."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"അപ്‌ഡേറ്റിനായി പരിശോധിക്കുക"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"നിങ്ങൾക്ക് പുതിയ സന്ദേശങ്ങൾ ഉണ്ട്"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"സാധാരണയുള്ളതിലും നേരത്തെ ബാറ്ററിയുടെ ചാർജ് തീർന്നേക്കാം"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"ബാറ്ററി ലൈഫ് വര്‍ദ്ധിപ്പിക്കാൻ, ബാറ്ററി ലാഭിക്കൽ സജീവമാക്കി"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ബാറ്ററി ലാഭിക്കൽ"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"ബാറ്ററി ലാഭിക്കൽ ഓഫാക്കിയിരിക്കുന്നു"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ഫോണിൽ വേണ്ടത്ര ചാർജ് ഉണ്ട്. ഫീച്ചറുകൾക്ക് ഇനി നിയന്ത്രണമില്ല."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"ടാബ്‌ലെറ്റിൽ വേണ്ടത്ര ചാർജ് ഉണ്ട്. ഫീച്ചറുകൾക്ക് ഇനി നിയന്ത്രണമില്ല."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"ഉപകരണത്തിൽ വേണ്ടത്ര ചാർജ് ഉണ്ട്. ഫീച്ചറുകൾക്ക് ഇനി നിയന്ത്രണമില്ല."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"ഫോള്‍ഡര്‍"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android ആപ്പ്"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"ഫയൽ"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> സ്പ്രെഡ്ഷീറ്റ്"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"അവതരണം"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> അവതരണം"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"ഫ്ലൈറ്റ് മോഡ് ഓണാക്കിയിരിക്കുമ്പോഴും Bluetooth ലഭ്യമാകും"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"ലോഡ് ചെയ്യുന്നു"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ഫയലുകൾ</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"സ്‌ക്രീൻ വിഭജന മോഡ് മാറ്റുക"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"ലോക്ക് സ്‌ക്രീൻ"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"സ്ക്രീൻഷോട്ട്"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിന്റെ അടിക്കുറിപ്പ് ബാർ."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> നിയന്ത്രിത ബക്കറ്റിലേക്ക് നീക്കി"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 205df27..3acdb72 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Таны төхөөрөмж устах болно."</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Админ аппыг ашиглах боломжгүй. Таны төхөөрөмжийг одоо устгана.\n\nХэрэв танд асуулт байгаа бол байгууллагынхаа админтай холбогдоно уу."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> хэвлэх үйлдлийг идэвхгүй болгосон."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Би"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Таблетын сонголтууд"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android ТВ-н сонголт"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"Хуанли руу хандах"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"Мессеж"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS мессежийг илгээх, харах"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Файл болон мeдиа"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"Tөхөөрөмж дээрх зураг, медиа болон файлд хандалт хийх"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Микрофон"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"дуу хураах"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Товших, шудрах, жижигрүүлэх болон бусад зангааг хийх боломжтой."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Хурууны хээний зангаа"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Төхөөрөмжийн хурууны хээ мэдрэгчид зангасан зангааг танина."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Дэлгэцийн зургийг дарах"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Дэлгэцийн зургийг дарах боломжтой."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"статус самбарыг идэвхгүй болгох болон өөрчлөх"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Апп нь статус самбарыг идэвхгүй болгох эсвэл систем дүрсийг нэмэх, хасах боломжтой."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"статусын хэсэг болох"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Та тайлах хээг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу зурлаа. <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа дахин буруу оруулбал, та утсаа тайлахын тулд имэйл бүртгэлээ ашиглах шаардлагатай болно.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Устгах"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Дууг санал болгосноос чанга болгож өсгөх үү?\n\nУрт хугацаанд чанга хөгжим сонсох нь таны сонсголыг муутгаж болно."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Хүртээмжийн товчлолыг ашиглах уу?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Товчлолыг асаасан үед дуун товчлуурыг 3 секунд дарснаар хүртээмжийн онцлогийг эхлүүлнэ.\n\n Одоогийн хүртээмжийн онцлог:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Онцлогийг Тохиргоо &gt; Хүртээмж хэсэгт өөрчлөх боломжтой."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Хоосон"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Товчлолуудыг засах"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Болих"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Товчлолыг унтраах"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Апп боломжгүй байна"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> одоогоор боломжгүй байна. Үүнийг <xliff:g id="APP_NAME_1">%2$s</xliff:g>-р удирддаг."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Дэлгэрэнгүй үзэх"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Ажлын профайлыг асаах уу?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Таны ажлын апп, мэдэгдэл, өгөгдөл болон бусад ажлын профайлын онцлогийг асаана"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Асаах"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Энэ аппыг Андройдын хуучин хувилбарт зориулсан бөгөөд буруу ажиллаж болзошгүй. Шинэчлэлтийг шалгаж эсвэл хөгжүүлэгчтэй холбогдоно уу."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Шинэчлэлтийг шалгах"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Танд шинэ зурвасууд байна"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Батарей ихэвчлэн цэнэглэдэг хугацаанаас өмнө дуусаж болзошгүй"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Батарейн ажиллах хугацааг уртасгахын тулд Батарей хэмнэгчийг идэвхжүүллээ"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Батарей хэмнэгч"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Батарей хэмнэгчийг унтраалаа"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Утас хангалттай цэнэгтэй боллоо. Онцлогуудыг цаашид хязгаарлахгүй."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Таблет хангалттай цэнэгтэй боллоо. Онцлогуудыг цаашид хязгаарлахгүй."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Төхөөрөмж хангалттай цэнэгтэй боллоо. Онцлогуудыг цаашид хязгаарлахгүй."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"Фолдер"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Андройд апп"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Файл"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g>-н хүснэгт"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Үзүүлэн"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g>-н үзүүлэн"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Нислэгийн горимын үеэр Bluetooth асаалттай байх болно"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Ачаалж байна"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> файл</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Дэлгэц хуваахыг унтраах/асаах"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Дэлгэцийг түгжих"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Дэлгэцийн зураг дарах"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g>-н гарчгийн талбар."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g>-г ХЯЗГААРЛАСАН сагс руу орууллаа"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index b27e1c9..ff9f3e7 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"तुमचे डिव्हाइस मिटविले जाईल"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"प्रशासक अ‍ॅप वापरता येणार नाही. तुमचे डिव्हाइस आता साफ केले जाईल.\n\nतुम्हाला कुठलेही प्रश्न असल्यास, तुमच्या संस्थेच्या प्रशासकाशी संपर्क साधा."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> नी प्रिंट करणे बंद केले आहे."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"मी"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"टॅबलेट पर्याय"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV पर्याय"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"आपल्या कॅलेंडरवर प्रवेश"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS मेसेज पाठवणे आणि पाहणे हे"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"फाइल आणि मीडिया"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"तुमच्या डिव्हाइस वरील फोटो, मीडिया आणि फायलींमध्‍ये अ‍ॅक्सेस"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"मायक्रोफोन"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ऑडिओ रेकॉर्ड"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"टॅप, स्वाइप, पिंच आणि इतर जेश्चर करू शकते."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"फिंगरप्रिंट जेश्चर"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"डिव्‍हाइसच्‍या फिंगरप्रिंट सेंन्सरवरील जेश्चर कॅप्‍चर करू शकते."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"स्क्रीनशॉट घ्या"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"डिस्प्लेचा स्क्रीनशॉट घेऊ शकतो."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"स्टेटस बार अक्षम करा किंवा सुधारित करा"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"स्टेटस बार अक्षम करण्यासाठी किंवा सिस्टम चिन्हे जोडण्यासाठी आणि काढण्यासाठी अ‍ॅप ला अनुमती देते."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"स्टेटस बार होऊ द्या"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"तुम्ही तुमचा अनलॉक पॅटर्न <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा अयोग्यपणे काढला आहे. आणखी <xliff:g id="NUMBER_1">%2$d</xliff:g> अयशस्वी प्रयत्नांनंतर, तुम्हाला ईमेल खाते वापरून तुमचा फोन अनलॉक करण्यास सांगितले जाईल.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"काढा"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"शिफारस केलेल्‍या पातळीच्या वर आवाज वाढवायचा?\n\nउच्च आवाजात दीर्घ काळ ऐकण्‍याने आपल्‍या श्रवणशक्तीची हानी होऊ शकते."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"प्रवेशयोग्यता शॉर्टकट वापरायचा?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"शॉर्टकट चालू असताना, दोन्ही आवाज बटणे 3 सेकंद दाबल्याने प्रवेशयोग्यता वैशिष्ट्य सुरू होईल.\n\n वर्तमान प्रवेशयोग्यता वैशिष्ट्य:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n तुम्ही सेटिंग्ज &gt; प्रवेशयोग्यता मध्ये वैशिष्ट्य बदलू शकता."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"रिकामे करा"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"शॉर्टकट संपादित करा"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"रद्द करा"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"शॉर्टकट बंद करा"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"अ‍ॅप उपलब्ध नाही"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> आत्ता उपलब्ध नाही. हे <xliff:g id="APP_NAME_1">%2$s</xliff:g> कडून व्यवस्थापित केले जाते."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"अधिक जाणून घ्या"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"कार्य प्रोफाइल चालू ठेवायची?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"तुमची कार्य अ‍ॅप्स, सूचना, डेटा आणि अन्य कार्य प्रोफाइल वैशिष्ट्ये चालू केली जातील"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"चालू करा"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"हे अ‍ॅप Android च्या जुन्या आवृत्ती साठी तयार करण्यात आले होते आणि योग्यरितीने कार्य करू शकणार नाही. अपडेट आहेत का ते तपासून पाहा, किंवा डेव्हलपरशी संपर्क साधण्याचा प्रयत्न करा."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"अपडेट आहे का ते तपासा"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"आपल्याकडे नवीन मेसेज आहेत"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"चार्जिंगची सामान्य पातळी गाठेपर्यंत कदाचित बॅटरी संपू शकते"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"बॅटरी लाइफ वाढवण्यासाठी बॅटरी सेव्हर सुरू केला आहे"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"बॅटरी सेव्‍हर"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"बॅटरी सेव्हर बंद केलेला आहे"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"फोन पुरेसा चार्ज केलेला आहे. वैशिष्ट्ये मर्यादित नाहीत."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"टॅबलेट पुरेसा चार्ज केलेला आहे. वैशिष्ट्ये मर्यादित नाहीत."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"डिव्हाइस पुरेसे चार्ज केलेले आहे. वैशिष्ट्ये मर्यादित नाहीत."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"फोल्डर"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android अ‍ॅप्लिकेशन"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"फाइल"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> स्प्रेडशीट"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"सादरीकरण"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> सादरीकरण"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"विमान मोड दरम्यान ब्लूटूथ चालू राहील"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"लोड होत आहे"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> फायली</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"विभाजित स्क्रीन टॉगल करा"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"स्‍क्रीन लॉक करा"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"स्क्रीनशॉट"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> चा शीर्षक बार."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> हे प्रतिबंधित बादलीमध्ये ठेवण्यात आले आहे"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index a29e363..e436408 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Peranti anda akan dipadam"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Apl pentadbir tidak dapat digunakan. Peranti anda akan dipadamkan sekarang.\n\nJika anda ingin mengemukakan soalan, hubungi pentadbir organisasi anda."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Pencetakan dilumpuhkan oleh <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Saya"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Pilihan tablet"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Pilihan Android TV"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"mengakses kalendar"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"menghantar dan melihat mesej SMS"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Fail dan media"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"mengakses foto, media dan fail pada peranti anda"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"rakam audio"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Boleh ketik, leret, cubit dan laksanakan gerak isyarat lain."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gerak isyarat cap jari"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Boleh menangkap gerak isyarat yang dilakukan pada penderia cap jari peranti."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ambil tangkapan skrin"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Boleh mengambil tangkapan skrin paparan."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"lumpuhkan atau ubah suai bar status"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Membenarkan apl melumpuhkan bar status atau menambah dan mengalih keluar ikon sistem."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"jadi bar status"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Anda telah tersilap lukis corak buka kunci sebanyak <xliff:g id="NUMBER_0">%1$d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi percubaan yang tidak berjaya, anda akan diminta membuka kunci telefon anda menggunakan log masuk Google anda.\n\n Cuba lagi dalam <xliff:g id="NUMBER_2">%3$d</xliff:g> saat."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Alih keluar"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Naikkan kelantangan melebihi paras yang disyokorkan?\n\nMendengar pada kelantangan yang tinggi untuk tempoh yang lama boleh merosakkan pendengaran anda."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Gunakan Pintasan Kebolehaksesan?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Apabila pintasan dihidupkan, tindakan menekan kedua-dua butang kelantangan selama 3 saat akan memulakan ciri kebolehaksesan.\n\n Ciri kebolehaksesan semasa:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Anda boleh menukar ciri itu dalam Tetapan &gt; Kebolehaksesan."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Kosong"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit pintasan"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Batal"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Matikan pintasan"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Apl tidak tersedia"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> tidak tersedia sekarang. Ini diurus oleh <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Ketahui lebih lanjut"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Hidupkan profil kerja?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Apl kerja, pemberitahuan, data dan ciri profil kerja anda yang lain akan dihidupkan"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Hidupkan"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Apl ini dibina untuk versi Android yang lebih lama dan mungkin tidak berfungsi dengan betul. Cuba semak kemas kini atau hubungi pembangun."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Semak kemas kini"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Anda mempunyai mesej baharu"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Bateri mungkin habis sebelum pengecasan biasa"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Penjimat Bateri diaktifkan untuk memanjangkan hayat bateri"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Penjimat Bateri"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Penjimat Bateri dimatikan"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Cas telefon mencukupi. Ciri tidak lagi dihadkan."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Cas tablet mencukupi. Ciri tidak lagi dihadkan."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Cas peranti mencukupi. Ciri tidak lagi dihadkan."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"Folder"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Aplikasi Android"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Fail"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"Hamparan <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Pembentangan"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Pembentangan <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth akan kekal hidup semasa dalam mod pesawat"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Memuatkan"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> fail</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Togol Skrin Pisah"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Skrin Kunci"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Tangkapan skrin"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Bar kapsyen <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> telah diletakkan dalam baldi TERHAD"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index a53deaf..56f49c2 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"သင့်ကိရိယာအား ပယ်ဖျက်လိမ့်မည်"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"စီမံခန့်ခွဲမှု အက်ပ်ကို သုံး၍မရပါ။ သင်၏ စက်ပစ္စည်းအတွင်းရှိ အရာများကို ဖျက်လိုက်ပါမည်\n\nမေးစရာများရှိပါက သင့်အဖွဲ့အစည်း၏ စီမံခန့်ခွဲသူကို ဆက်သွယ်ပါ။"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> က ပုံနှိပ်ထုတ်ယူခြင်းကို ပိတ်ထားသည်။"</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"ကျွန်ုပ်"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tabletဆိုင်ရာရွေးချယ်မှုများ"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV ရွေးချယ်စရာများ"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"သင့်ပြက္ခဒိန်အား ဝင်ရောက်သုံးရန်"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS စာတိုစနစ်"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS စာများကို ပို့ကာ ကြည့်မည်"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Files နှင့် မီဒီယာ"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"သင့်ဖုန်းရှိ ဓာတ်ပုံများ၊ မီဒီယာနှင့် ဖိုင်များအား ဝင်သုံးပါ"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"မိုက်ခရိုဖုန်း"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"အသံဖမ်းခြင်း"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"တို့ခြင်း၊ ပွတ်ဆွဲခြင်း၊ နှင့် အခြား လက်ဟန်များကို အသုံးပြုနိုင်ပါသည်။"</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"လက်ဗွေဟန်များ"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"စက်ပစ္စည်း၏ လက်ဗွေအာရုံခံကိရိယာတွင် လုပ်ဆောင်ထားသည့် လက်ဟန်များကို မှတ်သားထားနိုင်သည်။"</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ဖန်သားပြင်ဓာတ်ပုံ ရိုက်ရန်"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ဖန်သားပြင်ပြသမှုကို ဓာတ်ပုံရိုက်နိုင်ပါသည်။"</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"အခြေအနေပြဘားအား အလုပ်မလုပ်ခိုင်းရန်သို့မဟုတ် မွမ်းမံရန်"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"အက်ပ်အား အခြေအနေပြ ဘားကို ပိတ်ခွင့် သို့မဟတ် စနစ် အိုင်ကွန်များကို ထည့်ခြင်း ဖယ်ရှားခြင်း ပြုလုပ်ခွင့် ပြုသည်။"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"အခြေအနေပြ ဘားဖြစ်ပါစေ"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"သင် ပုံဖော်၍သော့ဖွင့်ခြင်းကို <xliff:g id="NUMBER_0">%1$d</xliff:g> အကြိမ် မှန်ကန်စွာ မပြုလုပ်နိုင်ပါ။ နောက်ထပ် <xliff:g id="NUMBER_1">%2$d</xliff:g> အကြိမ် မမှန်ကန်ပါက သင့်ဖုန်းအား အီးမေးလ်အသုံးပြု၍ သော့ဖွင့်ရန် တောင်းဆိုပါလိမ့်မည်။ \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> စက္ကန့်အကြာတွင် ပြန်လည် ကြိုးစားပါ"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ဖယ်ရှားရန်"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"အသံကို အကြံပြုထားသည့် ပမာဏထက် မြှင့်ပေးရမလား?\n\nအသံကို မြင့်သည့် အဆင့်မှာ ကြာရှည်စွာ နားထောင်ခြင်းက သင်၏ နားကို ထိခိုက်စေနိုင်သည်။"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"အများသုံးစွဲနိုင်မှု ဖြတ်လမ်းလင့်ခ်ကို အသုံးပြုလိုပါသလား။"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"ဖြတ်လမ်းလင့်ခ်ကို ဖွင့်ထားစဉ် အသံအတိုးအလျှော့ခလုတ် နှစ်ခုစလုံးကို ၃ စက္ကန့်ခန့် ဖိထားခြင်းဖြင့် အများသုံးစွဲနိုင်မှုဆိုင်ရာ ဝန်ဆောင်မှုကို ဖွင့်နိုင်သည်။\n\n လက်ရှိ အများသုံးစွဲနိုင်မှုဆိုင်ရာ ဝန်ဆောင်မှု−\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n ဝန်ဆောင်မှုကို ဆက်တင်များ &gt; အများသုံးစွဲနိုင်မှုတွင် ပြောင်းလဲနိုင်ပါသည်။"</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"အလွတ်"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ဖြတ်လမ်းများကို တည်းဖြတ်ရန်"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"မလုပ်တော့"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"ဖြတ်လမ်းလင့်ခ်ကို ပိတ်ရန်"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"အက်ပ်ကို မရရှိနိုင်ပါ"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ကို လောလောဆယ် မရနိုင်ပါ။ ၎င်းကို <xliff:g id="APP_NAME_1">%2$s</xliff:g> က စီမံထားပါသည်။"</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"ပိုမိုလေ့လာရန်"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"အလုပ်ပရိုဖိုင် ဖွင့်လိုသလား။"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"သင်၏ အလုပ်အက်ပ်၊ အကြောင်းကြားချက်၊ ဒေတာနှင့် အခြားအလုပ်ပရိုဖိုင် ဝန်ဆောင်မှုများကို ဖွင့်လိုက်ပါမည်"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"ဖွင့်ပါ"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ဤအက်ပ်ကို Android ဗားရှင်းဟောင်းအတွက် ပြုလုပ်ထားခြင်းဖြစ်ပြီး ပုံမှန်အလုပ်မလုပ်နိုင်ပါ။ အပ်ဒိတ်များအတွက် ရှာကြည့်ပါ သို့မဟုတ် ဆော့ဖ်ဝဲအင်ဂျင်နီယာကို ဆက်သွယ်ပါ။"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"အပ်ဒိတ်စစ်ရန်"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"သင့်ထံတွင် စာအသစ်များရောက်နေသည်"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"ပုံမှန်အားသွင်းမှုမပြုလုပ်မီ ဘက်ထရီကုန်သွားနိုင်သည်"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"ဘက်ထရီသက်တမ်းကို တိုးမြှင့်ရန် \'ဘက်ထရီအားထိန်း\' စတင်ပြီးပါပြီ"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ဘက်ထရီ အားထိန်း"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"ဘက်ထရီ အားထိန်းကို ပိတ်ထားသည်"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ဖုန်းတွင် ဘက်ထရီအား အလုံအလောက် ရှိသည်။ လုပ်ဆောင်ချက်များကို ကန့်သတ်မထားတော့ပါ။"</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"တက်ဘလက်တွင် ဘက်ထရီအား အလုံအလောက် ရှိသည်။ လုပ်ဆောင်ချက်များကို ကန့်သတ်မထားတော့ပါ။"</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"စက်တွင် ဘက်ထရီအား အလုံအလောက် ရှိသည်။ လုပ်ဆောင်ချက်များကို ကန့်သတ်မထားတော့ပါ။"</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"ဖိုင်တွဲ"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android အပလီကေးရှင်း"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"ဖိုင်"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> spreadsheet"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"တင်ပြမှု"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> တင်ပြမှု"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"လေယာဉ်ပျံမုဒ်ကို ဖွင့်ထားစဉ် ဘလူးတုသ် ပွင့်နေပါမည်"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"တင်နေသည်"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ဖိုင်</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"မျက်နှာပြင် ခွဲ၍ပြသခြင်းကို နှိပ်ပါ"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"လော့ခ်မျက်နှာပြင်"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"ဖန်သားပြင်ဓာတ်ပုံ"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g>၏ ခေါင်းစီး ဘား။"</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> ကို တားမြစ်ထားသော သိမ်းဆည်းမှုအတွင်းသို့ ထည့်ပြီးပါပြီ"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index ee16f90..bb3d52f 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Enheten blir slettet"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Administratorappen kan ikke brukes. Enheten din blir nå tømt.\n\nTa kontakt med administratoren for organisasjonen din hvis du har spørsmål."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> har slått av utskrift."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Meg"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Innstillinger for nettbrettet"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV-alternativer"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"åpne kalenderen din"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"sende og lese SMS-meldinger"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Filer og medier"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"åpne bilder, medieinnhold og filer på enheten din"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ta opp lyd"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Kan trykke, sveipe, klype og gjøre andre bevegelser."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Bevegelser på fingeravtrykkssensor"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Kan fange inn bevegelser som utføres på enhetens fingeravtrykkssensor."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ta skjermdump"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan ikke ta en skjermdump av skjermen."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"deaktivere eller endre statusfeltet"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Lar appen deaktivere statusfeltet eller legge til og fjerne systemikoner."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"vise appen i statusfeltet"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Du har tegnet opplåsningsmønsteret feil <xliff:g id="NUMBER_0">%1$d</xliff:g> ganger. Etter ytterligere <xliff:g id="NUMBER_1">%2$d</xliff:g> gale forsøk, blir du bedt om å låse opp telefonen via en e-postkonto.\n\n Prøv på nytt om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Fjern"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vil du øke volumet til over anbefalt nivå?\n\nHvis du hører på et høyt volum over lengre perioder, kan det skade hørselen din."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Vil du bruke tilgjengelighetssnarveien?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Når snarveien er på, starter en tilgjengelighetsfunksjon når du trykker inn begge volumknappene i tre sekunder.\n\n Nåværende tilgjengelighetsfunksjon:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Du kan endre funksjonen i Innstillinger &gt; Tilgjengelighet."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Tøm"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Endre snarveier"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Avbryt"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Slå av snarveien"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Appen er ikke tilgjengelig"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> er ikke tilgjengelig akkurat nå. Dette administreres av <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Finn ut mer"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Vil du slå på jobbprofilen?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Jobbappene dine samt varsler, data og andre funksjoner i jobbprofilen din blir slått på"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Slå på"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Denne appen er utviklet for en eldre versjon av Android og fungerer kanskje ikke som den skal. Prøv å se etter oppdateringer, eller kontakt utvikleren."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Se etter oppdateringer"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Du har nye meldinger"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Batteriet kan gå tomt før den vanlige ladingen"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Batterisparing er aktivert for å forlenge batterilevetiden"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Batterisparing"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Batterisparing er slått av"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefonen har nok batteri. Funksjoner begrenses ikke lenger."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Nettbrettet har nok batteri. Funksjoner begrenses ikke lenger."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Enheten har nok batteri. Funksjoner begrenses ikke lenger."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"Mappe"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android-app"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Fil"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g>-regneark"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Presentasjon"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g>-presentasjon"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth holdes på i flymodus"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Laster inn"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> filer</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Slå delt skjerm av/på"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Låseskjerm"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Skjermdump"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Tekstingsfelt i <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> er blitt plassert i TILGANGSBEGRENSET-toppmappen"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 1b85b28..b3d6cde 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"तपाईंको यन्त्र मेटिनेछ"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"प्रशासकको अनुप्रयोग प्रयोग गर्न मिल्दैन। तपाईंको यन्त्रको डेटा अब मेटाइने छ।\n\nतपाईंसँग प्रश्नहरू भएका खण्डमा आफ्नो संगठनका प्रशासकसँग सम्पर्क गर्नुहोस्।"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ले छाप्ने कार्यलाई असक्षम पार्यो।"</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"मलाई"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"ट्याब्लेट विकल्पहरू"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV सम्बन्धी विकल्पहरू"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"तपाईंको पात्रोमाथि पहुँच गर्नुहोस्"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS सन्देशहरू पठाउनुहोस् र हेर्नुहोस्"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"फाइल र मिडिया"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"तपाईंको यन्त्रमा तस्बिर, मिडिया, र फाइलहरूमाथि पहुँच गर्नुहोस्"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"माइक्रोफोन"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"अडियो रेकर्ड गर्नुहोस्"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"ट्याप, स्वाइप गर्न, थिच्न र अन्य इसाराहरू सम्बन्धी कार्य गर्न सक्छ"</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"फिंगरप्रिन्टका इसाराहरू"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"यसले यन्त्रक‍ो फिंगरप्रिन्टसम्बन्धी सेन्सरमा गरिएका इसाराहरूलाई खिच्‍न सक्छ।"</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"स्क्रिनसट लिनुहोस्"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"डिस्प्लेको स्क्रिनसट लिन सकिन्छ।"</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"स्थिति पट्टिलाई अक्षम वा संशोधित गर्नुहोस्"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"स्थिति पट्टि असक्षम पार्न वा प्रणाली आइकनहरू थप्न र हटाउन अनुप्रयोगलाई अनुमति दिन्छ।"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"वस्तुस्थिति पट्टी हुन दिनुहोस्"</string>
@@ -1618,10 +1619,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"तपाईँले आफ्नो अनलक ढाँचा गलत रूपमा <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक तान्नु भएको छ। <xliff:g id="NUMBER_1">%2$d</xliff:g> धेरै असफल प्रयासहरूपछि, तपाईँलाई एउटा इमेल खाताको प्रयोग गरेर तपाईँको फोन अनलक गर्न सोधिने छ।\n\n फेरि <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डमा प्रयास गर्नुहोस्।"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"हटाउनुहोस्"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"सिफारिस तहभन्दा आवाज ठुलो गर्नुहुन्छ?\n\nलामो समय सम्म उच्च आवाजमा सुन्दा तपाईँको सुन्ने शक्तिलाई हानी गर्न सक्छ।"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"पहुँच सम्बन्धी सर्टकट प्रयोग गर्ने हो?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"सर्टकट सक्रिय हुँदा, भोल्युमका दुवै बटनहरूलाई ३ सेकेन्डसम्म थिची राख्नाले पहुँच सम्बन्धी कुनै सुविधा सुरु हुनेछ।\n\n हाल व्यवहारमा रहेको पहुँच सम्बन्धी सुविधा:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n तपाईं सेटिङहरू अन्तर्गतको पहुँच सम्बन्धी विकल्पमा गई उक्त सुविधालाई बदल्न सक्नुहुन्छ।"</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"खाली"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"सर्टकटहरू सम्पादन गर्नुहोस्"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"रद्द गर्नुहोस्"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"सर्टकटलाई निष्क्रिय पार्नुहोस्"</string>
@@ -1856,13 +1858,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"अनुप्रयोग उपलब्ध छैन"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> अहिले उपलब्ध छैन। यो <xliff:g id="APP_NAME_1">%2$s</xliff:g> द्वारा व्यवस्थित छ।"</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"थप जान्नुहोस्"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"कार्य प्रोफाइल सक्रिय गर्ने?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"तपाईंका कार्यसम्बन्धी अनुप्रयोग, सूचना, डेटा र कार्य प्रोफाइलका अन्य सुविधाहरू सक्रिय गरिने छन्‌"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"सक्रिय गर्नुहोस्"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"यो अनुप्रयोग Android को पुरानो संस्करणका लागि बनाइएको हुनाले यसले सही ढङ्गले काम नगर्न सक्छ। अद्यावधिकहरू उपलब्ध छन् वा छैनन् भनी जाँच गरी हेर्नुहोस् वा यसको विकासकर्तालाई सम्पर्क गर्नुहोस्।"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"अद्यावधिक उपलब्ध छ वा छैन भनी जाँच गर्नुहोस्"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"तपाईंलाई नयाँ सन्देश आएको छ"</string>
@@ -1973,14 +1973,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"प्रायः चार्ज गर्ने समय हुनुभन्दा पहिले नै ब्याट्री सकिन सक्छ"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"ब्याट्रीको आयु बढाउन ब्याट्री सेभर सक्रिय गरियो"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ब्याट्री सेभर"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"ब्याट्री सेभर निष्क्रिय पारियो"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"फोनमा पर्याप्त चार्ज छ। सुविधाहरूलाई अब उप्रान्त प्रतिबन्ध लगाइँदैन।"</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"ट्याब्लेटमा पर्याप्त चार्ज छ। सुविधाहरूलाई अब उप्रान्त प्रतिबन्ध लगाइँदैन।"</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"यन्त्रमा पर्याप्त चार्ज छ। सुविधाहरूलाई अब उप्रान्त प्रतिबन्ध लगाइँदैन।"</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"फोल्डर"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android अनुप्रयोग"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"फाइल"</string>
@@ -1999,6 +1995,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> स्प्रेडसिट"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"प्रस्तुति"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> प्रस्तुति"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"हवाइजहाज मोडमा ब्लुटुथ सक्रिय रहने छ"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"लोड गर्दै"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> फाइलहरू</item>
@@ -2016,5 +2013,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"विभाजित स्क्रिन टगल गर्नुहोस्"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"लक स्क्रिन"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"स्क्रिनसट"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> को क्याप्सन बार।"</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> लाई प्रतिबन्धित बाल्टीमा राखियो"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index dece9ae..47de950 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Je apparaat wordt gewist"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"De beheer-app kan niet worden gebruikt. Je apparaat wordt nu gewist.\n\nNeem contact op met de beheerder van je organisatie als je vragen hebt."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Afdrukken uitgeschakeld door <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Ik"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tabletopties"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Opties voor Android TV"</string>
@@ -1609,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Je hebt je ontgrendelingspatroon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer onjuist getekend. Na nog eens <xliff:g id="NUMBER_1">%2$d</xliff:g> mislukte pogingen wordt u gevraagd je telefoon te ontgrendelen via een e-mailaccount.\n\n Probeer het over <xliff:g id="NUMBER_2">%3$d</xliff:g> seconden opnieuw."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Verwijderen"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Volume verhogen tot boven het aanbevolen niveau?\n\nAls je langere tijd op hoog volume naar muziek luistert, raakt je gehoor mogelijk beschadigd."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Snelkoppeling toegankelijkheid gebruiken?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Wanneer de snelkoppeling is ingeschakeld, kun je drie seconden op beide volumeknoppen drukken om een toegankelijkheidsfunctie te starten.\n\n Huidige toegankelijkheidsfunctie:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Je kunt de functie wijzigen in Instellingen &gt; Toegankelijkheid."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Leeg"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Snelkoppelingen bewerken"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Annuleren"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Sneltoets uitschakelen"</string>
@@ -1847,11 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"App is niet beschikbaar"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> is nu niet beschikbaar. Dit wordt beheerd door <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Meer info"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Werkprofiel inschakelen?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Je werk-apps, meldingen, gegevens en andere functies van je werkprofiel worden uitgeschakeld"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Inschakelen"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"App is niet beschikbaar"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is momenteel niet beschikbaar."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Deze app is ontwikkeld voor een oudere versie van Android en werkt mogelijk niet op de juiste manier. Controleer op updates of neem contact op met de ontwikkelaar."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Controleren op update"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Je hebt nieuwe berichten"</string>
@@ -1984,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g>-spreadsheet"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Presentatie"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g>-presentatie"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth blijft ingeschakeld in de vliegtuigmodus"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Laden"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> bestanden</item>
@@ -2001,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Gesplitst scherm schakelen"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Scherm vergrendelen"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Screenshot"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Ondertitelingsbalk van <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> is in de bucket RESTRICTED geplaatst"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 2018a7f..1242188 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"ଆପଣଙ୍କ ଡିଭାଇସ୍‍ ବର୍ତ୍ତମାନ ଲିଭାଯିବ"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"ଆଡମିନ୍‍ ଆପ୍‍‍ ବ୍ୟବହାର କରାଯାଇପାରିବ ନାହିଁ। ଆପଣଙ୍କ ଡିଭାଇସ୍‍‌ର ସମସ୍ତ ଡାଟାକୁ ବର୍ତ୍ତମାନ ଲିଭାଇଦିଆଯିବ। \n\nଯଦି ଆପଣଙ୍କର କୌଣସି ପ୍ରଶ୍ନ ରହିଥାଏ, ଆପଣଙ୍କ ସଂସ୍ଥାର ଆଡମିନ୍‌ଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ଦ୍ଵାରା ପ୍ରିଣ୍ଟିଙ୍ଗ ଅକ୍ଷମ କରାଯାଇଛି"</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"ମୁଁ"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"ଟାବଲେଟ୍‌ର ବିକଳ୍ପ"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android ଟିଭିର ବିକଳ୍ପଗୁଡ଼ିକ"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"ଆପଣଙ୍କ କ୍ୟାଲେଣ୍ଡର୍‍ ଆକ୍ସେସ୍‍ କରେ"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS ମେସେଜ୍‍ ପଠାନ୍ତୁ ଓ ଦେଖନ୍ତୁ"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"ଫାଇଲଗୁଡ଼ିକ ଏବଂ ମିଡିଆ"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"ଆପଣଙ୍କ ଡିଭାଇସ୍‌ରେ ଥିବା ଫଟୋ, ମିଡିଆ ଓ ଫାଇଲ୍‍ ଆକ୍ସେସ୍‍ କରେ"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"ମାଇକ୍ରୋଫୋନ୍"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ଅଡିଓ ରେକର୍ଡ କରେ"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"ଟାପ୍‍, ସ୍ୱାଇପ୍‍, ପିଞ୍ଚ ଓ ଅନ୍ୟାନ୍ୟ ଜେଶ୍ଚର୍‍ ସମ୍ପାଦନ କରିପାରିବ।"</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"ଟିପଚିହ୍ନ ଜେଶ୍ଚର"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ଡିଭାଇସ୍‌ର ଟିପଚିହ୍ନ ସେନସର୍ ଉପରେ ଜେଶ୍ଚର୍‍ କ୍ୟାପଚର୍‍ କାର୍ଯ୍ୟ କରାଯାଇପାରିବ।"</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ସ୍କ୍ରିନସଟ୍ ନିଅନ୍ତୁ"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ଡିସପ୍ଲେର ଏକ ସ୍କ୍ରିନସଟ୍ ନିଆଯାଇପାରେ।"</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"ଷ୍ଟାଟସ୍‌ ବାର୍‌କୁ ଅକ୍ଷମ କିମ୍ୱା ସଂଶୋଧନ କରନ୍ତୁ"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"ଆପ୍‍କୁ, ସ୍ଥିତି ବାର୍‍ ଅକ୍ଷମ କରିବାକୁ କିମ୍ବା ସିଷ୍ଟମ୍‍ ଆଇକନ୍‍ ଯୋଡ଼ିବା କିମ୍ବା ବାହାର କରିବାକୁ ଦେଇଥାଏ।"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"ଷ୍ଟାଟସ୍‍ ବାର୍‍ ରହିବାକୁ ଦିଅନ୍ତୁ"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"ଆପଣଙ୍କ ଅନଲକ୍‍ ପାଟର୍ନକୁ ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଭୁଲ ଭାବେ ଅଙ୍କନ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ ପ୍ରୟାସ ପରେ ଏକ ଇମେଲ୍‍ ଆକାଉଣ୍ଟ ବ୍ୟବହାର କରି ନିଜ ଫୋନ୍‌କୁ ଅନଲକ୍‌ କରିବା ପାଇଁ କୁହାଯିବ।\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ବାହାର କରନ୍ତୁ"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ମାତ୍ରା ବଢ଼ାଇ ସୁପାରିଶ ସ୍ତର ବଢ଼ାଉଛନ୍ତି? \n\n ଲମ୍ବା ସମୟ ପର୍ଯ୍ୟନ୍ତ ଉଚ୍ଚ ଶବ୍ଦରେ ଶୁଣିଲେ ଆପଣଙ୍କ ଶ୍ରବଣ ଶକ୍ତି ଖରାପ ହୋଇପାରେ।"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ଆକ୍ସେସବିଲିଟି ଶର୍ଟକଟ୍‍ ବ୍ୟବହାର କରିବେ?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"ସର୍ଟକଟ୍‌ ଅନ୍‌ ଥିବା ବେଳେ, ଉଭୟ ଭଲ୍ୟୁମ୍‍ ବଟନ୍‍ 3 ସେକେଣ୍ଡ ପାଇଁ ଦବାଇବା ଦ୍ୱାରା ଆକ୍ସେସବିଲିଟି ବୈଶିଷ୍ଟ ଆରମ୍ଭ ହେବ।\n\n ସମ୍ପ୍ରତି ଆକ୍ସେସବିଲିଟି ବୈଶିଷ୍ଟ୍ୟ:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n ସେଟିଙ୍ଗ ଓ ଆକ୍ସେସବିଲିଟିରେ ଆପଣ ବୈଶିଷ୍ଟ୍ୟ ବଦଳାଇ ପାରିବେ।"</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"ଖାଲି କରନ୍ତୁ"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ସର୍ଟକଟଗୁଡ଼ିକୁ ସମ୍ପାଦନ କରନ୍ତୁ"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"ବାତିଲ୍ କରନ୍ତୁ"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"ଶର୍ଟକଟ୍‍ ବନ୍ଦ କରନ୍ତୁ"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"ଆପ୍‌ ଉପଲବ୍ଧ ନାହିଁ"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"ବର୍ତ୍ତମାନ <xliff:g id="APP_NAME_0">%1$s</xliff:g> ଉପଲବ୍ଧ ନାହିଁ। ଏହା <xliff:g id="APP_NAME_1">%2$s</xliff:g> ଦ୍ଵାରା ପରିଚାଳିତ ହେଉଛି।"</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"ଅଧିକ ଜାଣନ୍ତୁ"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"ୱର୍କ ପ୍ରୋଫାଇଲ୍‌କୁ ଚାଲୁ କରିବେ?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"ଆପଣଙ୍କର କାର୍ଯ୍ୟକାରୀ ଆପ୍‌, ବିଜ୍ଞପ୍ତି, ଡାଟା ଓ ଅନ୍ୟ ୱର୍କ ପ୍ରୋଫାଇଲ୍‌ଗୁଡ଼ିକ ଚାଲୁ ହୋଇଯିବ"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"ଅନ୍ କରନ୍ତୁ"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ଏହି ଆପ୍‌କୁ Androidର ପୁରୁଣା ଭର୍ସନ୍ ପାଇଁ ନିର୍ମାଣ କରାଯାଇଥିଲା ଏବଂ ଠିକ୍ ଭାବେ କାମ କରିନପାରେ। ଏହାପାଇଁ ଅପଡେଟ୍‌ ଅଛି କି ନାହିଁ ଯାଞ୍ଚ କରନ୍ତୁ କିମ୍ବା ଡେଭେଲପର୍‌ଙ୍କ ସହିତ ସମ୍ପର୍କ କରନ୍ତୁ।"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"ଅପଡେଟ୍‌ ପାଇଁ ଯାଞ୍ଚ କରନ୍ତୁ"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"ଆପଣଙ୍କ ପାଖରେ ନୂଆ ମେସେଜ୍‍ ରହିଛି"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"ସାଧାରଣ ଭାବରେ ଚାର୍ଜ୍ କରିବା ପୂର୍ବରୁ ବ୍ୟାଟେରୀ ସରିଯାଇପାରେ"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"ବ୍ୟାଟେରୀର ସମୟକୁ ବଢ଼ାଇବା ପାଇଁ ବ୍ୟଟେରୀ ସେଭର୍‍କୁ କାର୍ଯ୍ୟକାରୀ କରାଯାଇଛି"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ବ୍ୟାଟେରୀ ସେଭର୍"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"ବ୍ୟାଟେରୀ ସେଭର୍ ବନ୍ଦ ଅଛି"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ଫୋନରେ ଯଥେଷ୍ଟ ଚାର୍ଜ ଅଛି। ଫିଚରଗୁଡ଼ିକ ଆଉ ପ୍ରତିବନ୍ଧିତ ନୁହେଁ।"</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"ଟାବଲେଟରେ ଯଥେଷ୍ଟ ଚାର୍ଜ ଅଛି। ଫିଚରଗୁଡ଼ିକ ଆଉ ପ୍ରତିବନ୍ଧିତ ନୁହେଁ।"</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"ଡିଭାଇସରେ ଯଥେଷ୍ଟ ଚାର୍ଜ ଅଛି। ଫିଚରଗୁଡ଼ିକ ଆଉ ପ୍ରତିବନ୍ଧିତ ନୁହେଁ।"</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"ଫୋଲ୍ଡର୍"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android ଆପ୍ଲିକେସନ୍"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"ଫାଇଲ୍"</string>
@@ -1993,6 +1989,8 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> ସ୍ପ୍ରେଡ୍‌ସିଟ୍"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"ଉପସ୍ଥାପନା"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> ଉପସ୍ଥାପନା"</string>
+    <!-- no translation found for bluetooth_airplane_mode_toast (2066399056595768554) -->
+    <skip />
     <string name="car_loading_profile" msgid="8219978381196748070">"ଲୋଡ୍ ହେଉଛି"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g>ଟି ଫାଇଲ୍</item>
@@ -2010,5 +2008,13 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"ଦୁଇଟି ସ୍କ୍ରିନ୍ ମଧ୍ୟରେ ଟୋଗଲ୍ କରନ୍ତୁ"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"ସ୍କ୍ରିନ୍ ଲକ୍ କରନ୍ତୁ"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"ସ୍କ୍ରି‍ନ୍‍ସଟ୍ ନିଅନ୍ତୁ"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g>ର କ୍ୟାପ୍ସନ୍ ବାର୍।"</string>
+    <!-- no translation found for as_app_forced_to_restricted_bucket (8233871289353898964) -->
+    <skip />
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 552f77d..b6513c3 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"ਤੁਹਾਡਾ ਡੀਵਾਈਸ ਮਿਟਾਇਆ ਜਾਏਗਾ"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"ਪ੍ਰਸ਼ਾਸਕ ਐਪ ਵਰਤੀ ਨਹੀਂ ਜਾ ਸਕਦੀ। ਹੁਣ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦਾ ਡਾਟਾ ਮਿਟਾਇਆ ਜਾਵੇਗਾ।\n\nਜੇਕਰ ਤੁਹਾਡੇ ਕੋਲ ਕੋਈ ਸਵਾਲ ਹਨ, ਤਾਂ ਆਪਣੀ ਸੰਸਥਾ ਦੇ ਪ੍ਰਸ਼ਾਸਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ਵੱਲੋਂ ਪ੍ਰਿੰਟ ਕਰਨਾ ਬੰਦ ਕੀਤਾ ਗਿਆ।"</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"ਮੈਂ"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"ਟੈਬਲੈੱਟ ਵਿਕਲਪ"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV ਦੇ ਵਿਕਲਪ"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"ਤੁਹਾਡੇ ਕੈਲੰਡਰ ਤੱਕ ਪਹੁੰਚ ਕਰਨ"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS ਸੁਨੇਹੇ ਭੇਜੋ ਅਤੇ ਦੇਖੋ"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"ਫ਼ਾਈਲਾਂ ਅਤੇ ਮੀਡੀਆ"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"ਆਪਣੇ ਡੀਵਾਈਸ \'ਤੇ ਫ਼ੋਟੋਆਂ, ਮੀਡੀਆ ਅਤੇ ਫ਼ਾਈਲਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨਾ"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">" ਆਡੀਓ  ਰਿਕਾਰਡ ਕਰਨ"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"ਟੈਪ ਕਰ ਸਕਦੀ ਹੈ, ਸਵਾਈਪ ਕਰ ਸਕਦੀ ਹੈ, ਚੂੰਢੀ ਭਰ ਸਕਦੀ ਹੈ, ਅਤੇ ਹੋਰ ਸੰਕੇਤ ਕਰ ਸਕਦੀ ਹੈ।"</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੰਕੇਤ"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ਡੀਵਾਈਸਾਂ ਦੇ ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ \'ਤੇ ਕੀਤੇ ਗਏ ਸੰਕੇਤਾਂ ਨੂੰ ਕੈਪਚਰ ਕਰ ਸਕਦੇ ਹਨ।"</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਲਓ"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ਡਿਸਪਲੇ ਦਾ ਸਕ੍ਰੀਨਸ਼ਾਟ ਲੈ ਸਕਦੀ ਹੈ।"</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"ਸਥਿਤੀ ਪੱਟੀ ਬੰਦ ਕਰੋ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰੋ"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"ਐਪ ਨੂੰ ਸਥਿਤੀ ਪੱਟੀ ਨੂੰ ਚਾਲੂ ਕਰਨ ਜਾਂ ਸਿਸਟਮ ਪ੍ਰਤੀਕਾਂ ਨੂੰ ਜੋੜਨ ਅਤੇ ਹਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"ਸਥਿਤੀ ਪੱਟੀ ਬਣਨ ਦਿਓ"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਣਲਾਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਡ੍ਰਾ ਕੀਤਾ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਇੱਕ ਈਮੇਲ ਖਾਤਾ ਵਰਤਦੇ ਹੋਏ ਆਪਣਾ ਫ਼ੋਨ ਅਣਲਾਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਏਗਾ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ਹਟਾਓ"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ਕੀ ਵੌਲਿਊਮ  ਸਿਫ਼ਾਰਸ਼  ਕੀਤੇ ਪੱਧਰ ਤੋਂ ਵਧਾਉਣੀ ਹੈ?\n\nਲੰਮੇ ਸਮੇਂ ਤੱਕ ਉੱਚ ਵੌਲਿਊਮ ਤੇ ਸੁਣਨ ਨਾਲ ਤੁਹਾਡੀ ਸੁਣਨ ਸ਼ਕਤੀ ਨੂੰ ਨੁਕਸਾਨ ਪਹੁੰਚ ਸਕਦਾ ਹੈ।"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ਕੀ ਪਹੁੰਚਯੋਗਤਾ ਸ਼ਾਰਟਕੱਟ ਵਰਤਣਾ ਹੈ?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"ਸ਼ਾਰਟਕੱਟ ਚਾਲੂ ਹੋਣ \'ਤੇ, ਕਿਸੇ ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਅਵਾਜ਼ ਬਟਨਾਂ ਨੂੰ 3 ਸਕਿੰਟ ਲਈ ਦਬਾ ਕੇ ਰੱਖੋ।\n\n ਵਰਤਮਾਨ ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾ:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n ਤੁਸੀਂ ਸੈਟਿੰਗਾਂ &gt; ਪਹੁੰਚਯੋਗਤਾ ਵਿੱਚ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਬਦਲ ਸਕਦੇ ਹੋ।"</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"ਖਾਲੀ"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ਸ਼ਾਰਟਕੱਟਾਂ ਦਾ ਸੰਪਾਦਨ ਕਰੋ"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"ਰੱਦ ਕਰੋ"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"ਸ਼ਾਰਟਕੱਟ ਬੰਦ ਕਰੋ"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"ਐਪ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ਐਪ ਫਿਲਹਾਲ ਉਪਲਬਧ ਨਹੀਂ ਹੈ। ਇਸਦਾ ਪ੍ਰਬੰਧਨ <xliff:g id="APP_NAME_1">%2$s</xliff:g> ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।"</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"ਹੋਰ ਜਾਣੋ"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"ਕੀ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਚਾਲੂ ਕਰਨੀ ਹੈ?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"ਤੁਹਾਡੀਆਂ ਕਾਰਜ-ਸਥਾਨ ਐਪਾਂ, ਸੂਚਨਾਵਾਂ, ਡਾਟਾ ਅਤੇ ਹੋਰ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਚਾਲੂ ਕੀਤੀਆਂ ਜਾਣਗੀਆਂ"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"ਚਾਲੂ ਕਰੋ"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ਇਹ ਐਪ Android ਦੇ ਕਿਸੇ ਵਧੇਰੇ ਪੁਰਾਣੇ ਵਰਜਨ ਲਈ ਬਣਾਈ ਗਈ ਸੀ ਅਤੇ ਸ਼ਾਇਦ ਸਹੀ ਢੰਗ ਨਾਲ ਕੰਮ ਨਾ ਕਰੇ। ਅੱਪਡੇਟਾਂ ਲਈ ਜਾਂਚ ਕਰੋ ਜਾਂ ਵਿਕਾਸਕਾਰ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"ਅੱਪਡੇਟ ਦੀ ਜਾਂਚ ਕਰੋ"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"ਤੁਹਾਨੂੰ ਨਵੇਂ ਸੁਨੇਹੇ ਪ੍ਰਾਪਤ ਹੋਏ ਹਨ"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"ਬੈਟਰੀ ਚਾਰਜ ਕਰਨ ਦੇ ਮਿੱਥੇ ਸਮੇਂ ਤੋਂ ਪਹਿਲਾਂ ਸ਼ਾਇਦ ਬੈਟਰੀ ਖਤਮ ਹੋ ਜਾਵੇ"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"ਬੈਟਰੀ ਲਾਈਫ਼ ਵਧਾਉਣ ਲਈ ਬੈਟਰੀ ਸੇਵਰ ਚਾਲੂ ਕੀਤਾ ਗਿਆ"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ਬੈਟਰੀ ਸੇਵਰ"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"ਬੈਟਰੀ ਸੇਵਰ ਬੰਦ ਕੀਤਾ ਗਿਆ"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ਫ਼ੋਨ ਲੋੜੀਂਦਾ ਚਾਰਜ ਹੈ। ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਹੁਣ ਪ੍ਰਤਿਬੰਧਿਤ ਨਹੀਂ ਹਨ।"</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"ਟੈਬਲੈੱਟ ਲੋੜੀਂਦਾ ਚਾਰਜ ਹੈ। ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਹੁਣ ਪ੍ਰਤਿਬੰਧਿਤ ਨਹੀਂ ਹਨ।"</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"ਡੀਵਾਈਸ ਲੋੜੀਂਦਾ ਚਾਰਜ ਹੈ। ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਹੁਣ ਪ੍ਰਤਿਬੰਧਿਤ ਨਹੀਂ ਹਨ।"</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"ਫੋਲਡਰ"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android ਐਪਲੀਕੇਸ਼ਨ"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"ਫ਼ਾਈਲ"</string>
@@ -1993,6 +1989,8 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> ਸਪਰੈੱਡਸ਼ੀਟ"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"ਪੇਸ਼ਕਾਰੀ"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> ਪੇਸ਼ਕਾਰੀ"</string>
+    <!-- no translation found for bluetooth_airplane_mode_toast (2066399056595768554) -->
+    <skip />
     <string name="car_loading_profile" msgid="8219978381196748070">"ਲੋਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ਫ਼ਾਈਲ</item>
@@ -2010,5 +2008,13 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਨੂੰ ਟੌਗਲ ਕਰੋ"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"ਲਾਕ ਸਕ੍ਰੀਨ"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"ਸਕ੍ਰੀਨਸ਼ਾਟ"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਦੀ ਸੁਰਖੀ ਪੱਟੀ।"</string>
+    <!-- no translation found for as_app_forced_to_restricted_bucket (8233871289353898964) -->
+    <skip />
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 5f94b18..964c973 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -198,6 +198,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Twoje urządzenie zostanie wyczyszczone"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Nie można użyć aplikacji administratora. Dane z urządzenia zostaną wykasowane.\n\nJeśli masz pytania, skontaktuj się z administratorem organizacji."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Drukowanie wyłączone przez: <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Ja"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opcje tabletu"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Opcje Androida TV"</string>
@@ -293,8 +297,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"dostęp do kalendarza"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"wysyłanie i wyświetlanie SMS‑ów"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Pliki i multimedia"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"dostęp do zdjęć, multimediów i plików na Twoim urządzeniu"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"nagrywanie dźwięku"</string>
@@ -320,10 +323,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Obsługuje kliknięcia, przesunięcia, ściągnięcia palców i inne gesty."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gesty związane z odciskiem palca"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Może przechwytywać gesty wykonywane na czytniku linii papilarnych w urządzeniu."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Robienie zrzutu ekranu"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Może robić zrzuty ekranu wyświetlacza."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"wyłączanie lub zmienianie paska stanu"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Pozwala aplikacji na wyłączanie paska stanu oraz dodawanie i usuwanie ikon systemowych."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"działanie jako pasek stanu"</string>
@@ -1656,10 +1657,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> nieprawidłowo narysowałeś wzór odblokowania. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach konieczne będzie odblokowanie telefonu przy użyciu danych logowania na konto Google.\n\n Spróbuj ponownie za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Usuń"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Zwiększyć głośność ponad zalecany poziom?\n\nSłuchanie głośno przez długi czas może uszkodzić Twój słuch."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Użyć skrótu do ułatwień dostępu?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Gdy skrót jest włączony, jednoczesne naciśnięcie przez trzy sekundy obu klawiszy sterowania głośnością uruchomi funkcję ułatwień dostępu.\n\nBieżąca funkcja ułatwień dostępu:\n<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\nFunkcję możesz zmienić, wybierając Ustawienia &gt; Ułatwienia dostępu."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Puste"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edytuj skróty"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Anuluj"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Wyłącz skrót"</string>
@@ -1914,13 +1916,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Aplikacja niedostępna"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"Aplikacja <xliff:g id="APP_NAME_0">%1$s</xliff:g> nie jest teraz dostępna. Zarządza tym aplikacja <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Więcej informacji"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Włączyć profil służbowy?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Aplikacje do pracy, powiadomienia, dane i inne funkcje profilu do pracy zostaną włączone"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Włącz"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ta aplikacja jest na starszą wersję Androida i może nie działać prawidłowo. Sprawdź dostępność aktualizacji lub skontaktuj się z programistą."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Sprawdź dostępność aktualizacji"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Masz nowe wiadomości"</string>
@@ -2033,14 +2033,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Bateria może się wyczerpać przed zwykłą porą ładowania"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Włączono Oszczędzanie baterii, by wydłużyć czas pracy na baterii"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Oszczędzanie baterii"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Oszczędzanie baterii zostało wyłączone"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefon jest wystarczająco naładowany. Funkcje nie są już ograniczone."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Tablet jest wystarczająco naładowany. Funkcje nie są już ograniczone."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Urządzenie jest wystarczająco naładowane. Funkcje nie są już ograniczone."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"Folder"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Aplikacja na Androida"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Plik"</string>
@@ -2059,6 +2055,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"Arkusz kalkulacyjny <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Prezentacja"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Prezentacja <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth pozostanie włączony w trybie samolotowym"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Ładuję"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="few"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> pliki</item>
@@ -2078,5 +2075,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Przełącz podzielony ekran"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Ekran blokady"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Zrzut ekranu"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Pasek napisów w aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Umieszczono pakiet <xliff:g id="PACKAGE_NAME">%1$s</xliff:g> w zasobniku danych RESTRICTED"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 567d6d4..a6fd0fe 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Seu dispositivo será limpo"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Não é possível usar o aplicativo para administrador. Seu dispositivo passará por uma limpeza agora.\n\nEm caso de dúvidas, entre em contato com o administrador da sua organização."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Impressão desativada por <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Eu"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opções do tablet"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Opções do Android TV"</string>
@@ -1609,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, será solicitado que você use o login do Google para desbloquear.\n\n Tente novamente em <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remover"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Aumentar o volume acima do nível recomendado?\n\nOuvir em volume alto por longos períodos pode danificar sua audição."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Usar atalho de Acessibilidade?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Quando o atalho está ativado, pressione os dois botões de volume por três segundos para iniciar um recurso de acessibilidade.\n\n Recurso de acessibilidade atual:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n É possível alterar o recurso em Configurações &gt; Acessibilidade."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Limpar"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar atalhos"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Cancelar"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Desativar atalho"</string>
@@ -1847,11 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"O app não está disponível"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"O app <xliff:g id="APP_NAME_0">%1$s</xliff:g> não está disponível no momento. Isso é gerenciado pelo app <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Saiba mais"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Ativar o perfil de trabalho?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Seus apps, notificações, dados e outros recursos do perfil de trabalho serão ativados"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Ativar"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"O app não está disponível"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> não está disponível no momento."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Este app foi criado para uma versão mais antiga do Android e pode não funcionar corretamente. Tente verificar se há atualizações ou entre em contato com o desenvolvedor."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Procurar atualizações"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Você tem mensagens novas"</string>
@@ -1984,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"Planilha em <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Apresentação"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Apresentação em <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"O Bluetooth permanecerá ativado no modo avião"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Carregando"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> arquivo</item>
@@ -2001,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Ativar tela dividida"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Bloquear tela"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Capturar tela"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Barra de legendas do app <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> foi colocado no intervalo RESTRITO"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index b746c92..81f5ced 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"O seu dispositivo será apagado"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Não é possível utilizar a aplicação de administrador. O seu dispositivo será agora apagado.\n\nSe tiver questões, contacte o administrador da entidade."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Impressão desativada por <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Eu"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opções do tablet"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Opções do Android TV"</string>
@@ -1609,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Desenhou o padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Depois de mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas sem sucesso, ser-lhe-á pedido para desbloquear o telemóvel através de uma conta de email.\n\n Tente novamente dentro de <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" - "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remover"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Aumentar o volume acima do nível recomendado?\n\nOuvir com um volume elevado durante longos períodos poderá ser prejudicial para a sua audição."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Pretende utilizar o atalho de acessibilidade?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Quando o atalho está ativado, premir ambos os botões de volume durante 3 segundos inicia uma funcionalidade de acessibilidade.\n\n Funcionalidade de acessibilidade atual:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Pode alterar a funcionalidade em Definições &gt; Acessibilidade."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Esvaziar"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar atalhos"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Cancelar"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Desativar atalho"</string>
@@ -1847,11 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"A aplicação não está disponível"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"A aplicação <xliff:g id="APP_NAME_0">%1$s</xliff:g> não está disponível neste momento. A aplicação <xliff:g id="APP_NAME_1">%2$s</xliff:g> gere esta definição."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Saiba mais"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Ativar o perfil de trabalho?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"As aplicações de trabalho, as notificações, os dados e outras funcionalidades do perfil de trabalho serão desativados"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Ativar"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"A app não está disponível"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"De momento, a app <xliff:g id="APP_NAME">%1$s</xliff:g> não está disponível."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Esta aplicação foi concebida para uma versão mais antiga do Android e pode não funcionar corretamente. Experimente verificar se existem atualizações ou contacte o programador."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Verificar se existem atualizações"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Tem mensagens novas"</string>
@@ -1984,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"Folha de cálculo <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Apresentação"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Apresentação <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"O Bluetooth continuará ativado durante o modo de avião."</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"A carregar…"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ficheiros</item>
@@ -2001,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Ativar/desativar o ecrã dividido"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Ecrã de bloqueio"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Captura de ecrã"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Barra de legendas da aplicação <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> foi colocado no contentor RESTRITO."</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 567d6d4..a6fd0fe 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Seu dispositivo será limpo"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Não é possível usar o aplicativo para administrador. Seu dispositivo passará por uma limpeza agora.\n\nEm caso de dúvidas, entre em contato com o administrador da sua organização."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Impressão desativada por <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Eu"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opções do tablet"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Opções do Android TV"</string>
@@ -1609,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, será solicitado que você use o login do Google para desbloquear.\n\n Tente novamente em <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remover"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Aumentar o volume acima do nível recomendado?\n\nOuvir em volume alto por longos períodos pode danificar sua audição."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Usar atalho de Acessibilidade?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Quando o atalho está ativado, pressione os dois botões de volume por três segundos para iniciar um recurso de acessibilidade.\n\n Recurso de acessibilidade atual:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n É possível alterar o recurso em Configurações &gt; Acessibilidade."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Limpar"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar atalhos"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Cancelar"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Desativar atalho"</string>
@@ -1847,11 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"O app não está disponível"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"O app <xliff:g id="APP_NAME_0">%1$s</xliff:g> não está disponível no momento. Isso é gerenciado pelo app <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Saiba mais"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Ativar o perfil de trabalho?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Seus apps, notificações, dados e outros recursos do perfil de trabalho serão ativados"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Ativar"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"O app não está disponível"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> não está disponível no momento."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Este app foi criado para uma versão mais antiga do Android e pode não funcionar corretamente. Tente verificar se há atualizações ou entre em contato com o desenvolvedor."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Procurar atualizações"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Você tem mensagens novas"</string>
@@ -1984,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"Planilha em <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Apresentação"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Apresentação em <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"O Bluetooth permanecerá ativado no modo avião"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Carregando"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> arquivo</item>
@@ -2001,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Ativar tela dividida"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Bloquear tela"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Capturar tela"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Barra de legendas do app <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> foi colocado no intervalo RESTRITO"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 5b115375..cb8d3fe 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -196,6 +196,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Datele de pe dispozitiv vor fi șterse"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Aplicația de administrare nu poate fi utilizată. Dispozitivul va fi șters.\n\nDacă aveți întrebări, contactați administratorul organizației dvs."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Printare dezactivată de <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Eu"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opțiuni tablet PC"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Opțiuni pentru Android TV"</string>
@@ -290,8 +294,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"acceseze calendarul"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"trimită și să vadă mesajele SMS"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Fișiere și media"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"acceseze fotografiile, conținutul media și fișierele de pe dispozitiv"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Microfon"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"înregistreze sunet"</string>
@@ -317,10 +320,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Poate atinge, glisa, ciupi sau folosi alte gesturi."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gesturi ce implică amprente"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Poate reda gesturile făcute pe senzorul de amprentă al dispozitivului."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Faceți o captură de ecran"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Poate face o captură de ecran."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"dezactivare sau modificare bare de stare"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Permite aplicației să dezactiveze bara de stare sau să adauge și să elimine pictograme de sistem."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"să fie bara de stare"</string>
@@ -1634,10 +1635,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Ați desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, vi se va solicita să deblocați telefonul cu ajutorul unui cont de e-mail.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g>   secunde."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Eliminați"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Ridicați volumul mai sus de nivelul recomandat?\n\nAscultarea la volum ridicat pe perioade lungi de timp vă poate afecta auzul."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Utilizați comanda rapidă pentru accesibilitate?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Când comanda rapidă este activată, dacă apăsați ambele butoane de volum timp de 3 secunde, veți lansa o funcție de accesibilitate.\n\n Funcția actuală de accesibilitate:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Puteți schimba funcția în Setări &gt; Accesibilitate."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Goliți"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editați comenzile rapide"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Anulați"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Dezactivați comanda rapidă"</string>
@@ -1882,13 +1884,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Aplicația nu este disponibilă"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"Momentan, aplicația <xliff:g id="APP_NAME_0">%1$s</xliff:g> nu este disponibilă. Aceasta este gestionată de <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Aflați mai multe"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Activați profilul de serviciu?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Se vor activa aplicațiile dvs. de serviciu, notificările, datele și alte funcții ale profilului de serviciu"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Activați"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Această aplicație a fost creată pentru o versiune Android mai veche și este posibil să nu funcționeze corect. Încercați să căutați actualizări sau contactați dezvoltatorul."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Căutați actualizări"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Aveți mesaje noi"</string>
@@ -2000,14 +2000,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Bateria se poate descărca înainte de încărcarea obișnuită"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Economisirea bateriei este activată pentru a prelungi durata de funcționare a bateriei"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Economisirea bateriei"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Economisirea bateriei a fost dezactivată"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefonul este încărcat suficient. Funcțiile nu mai sunt limitate."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Tableta este încărcată suficient. Funcțiile nu mai sunt limitate."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Dispozitivul este încărcat suficient. Funcțiile nu mai sunt limitate."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"Dosar"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Aplicație Android"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Fișier"</string>
@@ -2026,6 +2022,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"Foaie de calcul <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Prezentare"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Prezentare <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Conexiunea Bluetooth va rămâne activată în modul Avion"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Se încarcă"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="few"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> fișiere</item>
@@ -2044,5 +2041,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Activați ecranul împărțit"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Ecran de blocare"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Captură de ecran"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Bară cu legenda pentru <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> a fost adăugat la grupul RESTRICȚIONATE"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index fa283d8..4821c7f 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -198,6 +198,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Все данные с устройства будут удалены"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Невозможно использовать приложение для администрирования. С устройства будут удалены все данные.\n\nЕсли у вас возникли вопросы, обратитесь к администратору."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Функция печати отключена приложением \"<xliff:g id="OWNER_APP">%s</xliff:g>\""</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Я"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Настройки планшетного ПК"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Настройки Android TV"</string>
@@ -293,8 +297,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"доступ к календарю"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"отправлять и просматривать SMS-сообщения"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Файлы и медиафайлы"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"доступ к фото, мультимедиа и файлам на вашем устройстве"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Микрофон"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"записывать аудио"</string>
@@ -320,10 +323,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Может выполнять жесты нажатия, пролистывания, масштабирования и т. д."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Регистрировать жесты на сканере отпечатков пальцев"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Использовать сканер отпечатков пальцев для дополнительных жестов."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Создавать скриншоты"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Создавать скриншоты экрана."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"Отключение/изменение строки состояния"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Приложение сможет отключать строку состояния, а также добавлять и удалять системные значки."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"Замена строки состояния"</string>
@@ -1656,10 +1657,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Вы <xliff:g id="NUMBER_0">%1$d</xliff:g> раз неверно указали графический ключ. После <xliff:g id="NUMBER_1">%2$d</xliff:g> неверных попыток для разблокировки телефона потребуется войти в аккаунт Google.\n\nПовтор через <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Удалить"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Установить громкость выше рекомендуемого уровня?\n\nВоздействие громкого звука в течение долгого времени может привести к повреждению слуха."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Использовать быстрое включение?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Чтобы использовать функцию специальных возможностей, когда она включена, нажмите и удерживайте три секунды обе кнопки регулировки громкости.\n\nТекущая функция специальных возможностей:\n<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\nВы можете изменить ее в разделе \"Настройки &gt; Специальные возможности\"."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Очистить"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Изменить быстрые клавиши"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Отмена"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Деактивировать быстрое включение"</string>
@@ -1914,13 +1916,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Приложение недоступно"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"Приложение \"<xliff:g id="APP_NAME_0">%1$s</xliff:g>\" недоступно. Его работу ограничивает приложение \"<xliff:g id="APP_NAME_1">%2$s</xliff:g>\"."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Подробнее"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Включить рабочий профиль?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Будут включены корпоративные приложения, уведомления, данные и другие функции рабочего профиля."</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Включить"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Это приложение было создано для более ранней версии Android и может работать со сбоями. Проверьте наличие обновлений или свяжитесь с разработчиком."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Проверить обновления"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Новые сообщения"</string>
@@ -2033,14 +2033,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Батарея может разрядиться"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Чтобы увеличить время работы от батареи, был включен режим энергосбережения."</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Режим энергосбережения"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Режим энергосбережения отключен"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Телефон заряжен достаточно. Функции больше не ограничены."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Планшет заряжен достаточно. Функции больше не ограничены."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Устройство заряжено достаточно. Функции больше не ограничены."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"Папка"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Приложение Android"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Файл"</string>
@@ -2059,6 +2055,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"Таблица <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Презентация"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Презентация <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth будет работать в режиме полета."</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Загрузка"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one">\"<xliff:g id="FILE_NAME_2">%s</xliff:g>\" и ещё <xliff:g id="COUNT_3">%d</xliff:g> файл</item>
@@ -2078,5 +2075,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Включить или выключить разделение экрана"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Заблокированный экран"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Скриншот"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Строка субтитров в приложении \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Приложение \"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g>\" помещено в категорию с ограниченным доступом."</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 3899cd7..df14036 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"ඔබගේ උපාංගය මකා දැමෙනු ඇත"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"පරිපාලක යෙදුම භාවිතා කළ නොහැකිය. ඔබේ උපාංගය දැන් මකා දමනු ඇත.\n\nඔබට ප්‍රශ්න තිබේ නම්, ඔබේ සංවිධානයේ පරිපාලකට අමතන්න."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> විසින් මුද්‍රණය කිරීම අබල කර ඇත."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"මම"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"ටැබ්ලට විකල්ප"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV විකල්ප"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"ඔබේ දින දර්ශනයට පිවිසෙන්න"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"කෙටි පණිවිඩ"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS පණිවිඩ යැවීම සහ බැලීම"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"ගොනු සහ මාධ්‍ය"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"ඔබේ උපාංගයේ ඇති ඡායාරූප, මාධ්‍ය සහ ගොනුවලට පිවිසීම"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"මයික්‍රොෆෝනය"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ශ්‍රව්‍ය පටිගත කරන්න"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"තට්ටු කිරීමට, ස්වයිප් කිරීමට, පින්ච් කිරීමට, සහ වෙනත් අභින සිදු කිරීමට හැකිය."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"ඇඟිලි සලකුණු ඉංගිත"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"උපාංගයෙහි ඇඟිලි සලකුණු සංවේදකය මත සිදු කරන ඉංගිත ග්‍රහණය කළ හැකිය."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"තිර රුව ගන්න"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"සංදර්ශකයේ තිර රුවක් ගැනීමට හැකිය."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"තත්ව තීරුව අබල කරන්න හෝ වෙනස් කරන්න"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"තත්ව තීරුව අක්‍රිය කිරීමට හෝ පද්ධති නිරූපක එකතු හෝ ඉවත් කිරීමට යෙදුමට අවසර දේ."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"තත්ත්ව තීරුව බවට පත්වීම"</string>
@@ -1614,10 +1615,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"ඔබ වැරදියට <xliff:g id="NUMBER_0">%1$d</xliff:g> වතාවක් ඔබගේ අගුළු හැරීමේ රටාව ඇඳ ඇත. අසාර්ථක උත්සහ කිරීම් <xliff:g id="NUMBER_1">%2$d</xliff:g> න් පසුව, ඔබගේ ඊ-තැපැල් ලිපිනය භාවිතයෙන් ඔබගේ දුරකථනය අගුළු හැරීමට ඔබගෙන් අසයි.\n\n තත්පර <xliff:g id="NUMBER_2">%3$d</xliff:g> න් පසුව නැවත උත්සහ කරන්න."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ඉවත් කරන්න"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"නිර්දේශිතයි මට්ටමට වඩා ශබ්දය වැඩිද?\n\nදිගු කාලයක් සඳහා ඉහළ ශබ්දයක් ඇසීමෙන් ඇතැම් විට ඔබගේ ඇසීමට හානි විය හැක."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ප්‍රවේශ්‍යතා කෙටිමඟ භාවිතා කරන්නද?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"කෙටිමඟ සක්‍රිය විට, හඬ බොත්තම් දෙකම තත්පර 3ක් අල්ලාගෙන සිටීමෙන් ප්‍රවේශ්‍යත අංගයක් ඇරඹේ.\n\n වත්මන් ප්‍රවේශ්‍යතා අංගය:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n සැකසීම් &gt; ප්‍රවේශ්‍යතාව තුළ ඔබට අංගය වෙනස් කළ හැක."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"හිස්"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"කෙටිමං සංස්කරණ කරන්න"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"අවලංගු කරන්න"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"කෙටිමඟ ක්‍රියාවිරහිත කරන්න"</string>
@@ -1852,13 +1854,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"යෙදුම නොතිබේ"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> මේ අවස්ථාවේදී ලබා ගත නොහැකිය. මෙය <xliff:g id="APP_NAME_1">%2$s</xliff:g> මගින් කළමනාකරණය කෙරේ."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"තව දැන ගන්න"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"කාර්යාල පැතිකඩ ක්‍රියාත්මක කරන්නද?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"ඔබගේ වැඩ යෙදුම්, දැනුම්දීම්, දත්ත සහ වෙනත් කාර්යාල පැතිකඩ විශේෂාංග ක්‍රියාත්මක කරනු ඇත"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"ක්‍රියාත්මක කරන්න"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"මෙම යෙදුම Android හි පැරණි අනුවාදයක් සඳහා තනා ඇති අතර නිසියාකාරව ක්‍රියා නොකරනු ඇත. යාවත්කාලීන සඳහා පරික්ෂා කිරීම උත්සාහ කරන්න, නැතහොත් සංවර්ධක අමතන්න."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"යාවත්කාලීන සඳහා පරික්ෂා කරන්න"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"ඔබට නව පණිවිඩ තිබේ"</string>
@@ -1969,14 +1969,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"බැටරිය සුපුරුදු ආරෝපණයට පෙර ඉවර විය හැක"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"බැටරි සුරැකුම බැටරි ආයු කාලය දීර්ඝ කිරීමට සක්‍රිය කෙරිණි"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"බැටරි සුරැකුම"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"බැටරි සුරැකුම ක්‍රියාවිරහිත කර ඇත"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"දුරකථනයට ප්‍රමාණවත් ආරෝපණයක් තිබේ. විශේෂාංග තවදුරටත් සීමා කර නැත."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"ටැබ්ලට් පරිගණකයට ප්‍රමාණවත් ආරෝපණයක් තිබේ. විශේෂාංග තවදුරටත් සීමා කර නැත."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"උපාංගයට ප්‍රමාණවත් ආරෝපණයක් තිබේ. විශේෂාංග තවදුරටත් සීමා කර නැත."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"ෆෝල්ඩරය"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android යෙදුම"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"ගොනුව"</string>
@@ -1995,6 +1991,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> පැතුරුම්පත"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"ඉදිරිපත් කිරීම"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> ඉදිරිපත් කිරීම"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"බ්ලූටූත් ගුවන් යානා ප්‍රකාරය තුළ ක්‍රියාත්මකව පවතිනු ඇත"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"පූරණය කරමින්"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one">ගොනු<xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g></item>
@@ -2012,5 +2009,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"බෙදුම් තිරය ටොගල කරන්න"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"අගුලු තිරය"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"තිර රුව"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> හි සිරස්තල තීරුව."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> අවහිර කළ බාල්දියට දමා ඇත"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index f48368f..b0dc5f3 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -198,6 +198,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Vaše zariadenie bude vymazané"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Daná aplikácia na správu sa nedá použiť. Vaše zariadenie bude vymazané.\n\nV prípade otázok kontaktujte správcu organizácie."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Tlač zakázala aplikácia <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Ja"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Možnosti tabletu"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Možnosti zariadenia Android TV"</string>
@@ -293,8 +297,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"prístup ku kalendáru"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"posielanie a zobrazovanie SMS"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Súbory a médiá"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"prístup k fotkám, médiám a súborom v zariadení"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofón"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"nahrávanie zvuku"</string>
@@ -320,10 +323,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Je možné použiť klepnutie, prejdenie, stiahnutie prstami a ďalšie gestá."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gestá odtlačkom prsta"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Dokáže zaznamenať gestá na senzore odtlačkov prstov zariadenia."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Vytvoriť snímku obrazovky"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Je možné vytvoriť snímku obrazovky."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"zakázanie alebo zmeny stavového riadka"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Umožňuje aplikácii vypnúť stavový riadok alebo pridať a odstrániť systémové ikony."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"vydávanie sa za stavový riadok"</string>
@@ -1656,10 +1657,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"<xliff:g id="NUMBER_0">%1$d</xliff:g>-krát ste nesprávne nakreslili svoj bezpečnostný vzor. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> ďalších neúspešných pokusoch sa zobrazí výzva na odomknutie telefónu pomocou e-mailového účtu.\n\n Skúste to znova o <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Odstrániť"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Zvýšiť hlasitosť nad odporúčanú úroveň?\n\nDlhodobé počúvanie pri vysokej hlasitosti môže poškodiť váš sluch."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Použiť skratku dostupnosti?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Keď je skratka zapnutá, stlačením obidvoch tlačidiel hlasitosti na tri sekundy spustíte funkciu dostupnosti.\n\n Aktuálna funkcia dostupnosti:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Funkciu môžete zmeniť v časti Nastavenia &gt; Dostupnosť."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Prázdne"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Upraviť skratky"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Zrušiť"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Vypnúť skratku"</string>
@@ -1914,13 +1916,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Aplikácia nie je k dispozícii"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"Aplikácia <xliff:g id="APP_NAME_0">%1$s</xliff:g> nie je momentálne k dispozícii. Spravuje to aplikácia <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Ďalšie informácie"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Zapnúť pracovný profil?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Pracovné aplikácie, upozornenia, dáta a ďalšie funkcie pracovného profilu sa zapnú"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Zapnúť"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Táto aplikácia bola zostavená pre staršiu verziu Androidu a nemusí správne fungovať. Skúste skontrolovať dostupnosť aktualizácií alebo kontaktovať vývojára."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Skontrolovať dostupnosť aktualizácie"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Máte nové správy."</string>
@@ -2033,14 +2033,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Batéria sa môže vybiť pred obvyklým nabitím"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Bol aktivovaný šetrič batérie na predĺženie výdrže batérie"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Šetrič batérie"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Šetrič batérie bol vypnutý."</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefón je dostatočne nabitý. Funkcie už nie sú obmedzené."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Tablet je dostatočne nabitý. Funkcie už nie sú obmedzené."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Zariadenie je dostatočne nabité. Funkcie už nie sú obmedzené."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"Priečinok"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Aplikácia pre Android"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Súbor"</string>
@@ -2059,6 +2055,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"Tabuľka <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Prezentácia"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Prezentácia <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Rozhranie Bluetooth zostane počas režimu v lietadle zapnuté"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Načítava sa"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="few"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> súbory</item>
@@ -2078,5 +2075,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Prepnúť rozdelenú obrazovku"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Uzamknúť obrazovku"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Snímka obrazovky"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Popis aplikácie <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Balík <xliff:g id="PACKAGE_NAME">%1$s</xliff:g> bol vložený do kontajnera OBMEDZENÉ"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 6343e0e..bdd5925 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -198,6 +198,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Podatki v napravi bodo izbrisani"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Skrbniške aplikacije ni mogoče uporabljati. Podatki v napravi bodo izbrisani.\n\nČe imate vprašanja, se obrnite na skrbnika organizacije."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Tiskanje je onemogočil pravilnik <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Jaz"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Možnosti tabličnega računalnika"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Možnosti naprave Android TV"</string>
@@ -293,8 +297,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"dostop do koledarja"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"pošiljanje in ogled sporočil SMS"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Datoteke in predstavnost"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"dostop do fotografij, predstavnosti in datotek v napravi"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"snemanje zvoka"</string>
@@ -320,10 +323,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Mogoče je izvajanje dotikov, vlečenja, primikanja in razmikanja prstov ter drugih potez."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Poteze po tipalu prstnih odtisov"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Prepoznava poteze, narejene po tipalu prstnih odtisov naprave."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ustvarjanje posnetka zaslona"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Lahko naredi posnetek zaslona."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"onemogočanje ali spreminjanje vrstice stanja"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Aplikacijam omogoča onemogočenje vrstice stanja ali dodajanje in odstranjevanje ikon sistema."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"postane vrstica stanja"</string>
@@ -1656,10 +1657,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Vzorec za odklepanje ste <xliff:g id="NUMBER_0">%1$d</xliff:g>-krat napačno vnesli. Po nadaljnjih <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešnih poskusih boste pozvani, da odklenete telefon z Googlovimi podatki za prijavo.\n\nPoskusite znova čez <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Odstrani"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Ali želite povečati glasnost nad priporočeno raven?\n\nDolgotrajno poslušanje pri veliki glasnosti lahko poškoduje sluh."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Želite uporabljati bližnjico funkcij za ljudi s posebnimi potrebami?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Ko je bližnjica vklopljena, pritisnite gumba za glasnost in ju pridržite tri sekunde, če želite zagnati funkcijo za ljudi s posebnimi potrebami.\n\n Trenutna funkcija za ljudi s posebnimi potrebami:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Funkcijo lahko spremenite v »Nastavitve &gt; Funkcije za ljudi s posebnimi potrebami«."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Prazno"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Uredi bližnjice"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Prekliči"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Izklopi bližnjico"</string>
@@ -1914,13 +1916,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Aplikacija ni na voljo"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"Aplikacija <xliff:g id="APP_NAME_0">%1$s</xliff:g> trenutno ni na voljo. To upravlja aplikacija <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Več o tem"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Želite vklopiti delovni profil?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Vklopili boste svoje delovne aplikacije, obvestila, podatke in druge funkcije delovnega profila"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Vklop"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ta aplikacija je bila zasnovana za starejšo različico Androida in morda ne bo delovala pravilno. Preverite, ali so na voljo posodobitve, ali pa se obrnite na razvijalca."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Preveri, ali je na voljo posodobitev"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Imate nova sporočila."</string>
@@ -2033,14 +2033,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Akumulator se bo morda izpraznil, preden ga običajno priključite na polnjenje"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Vklopilo se je varčevanje z energijo akumulatorja za podaljšanje časa delovanja akumulatorja"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Varčevanje z energijo akumulatorja"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Varčevanje z energijo baterije je izklopljeno"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Baterija v telefonu je dovolj napolnjena. Funkcije niso več omejene."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Baterija v tabličnem računalniku je dovolj napolnjena. Funkcije niso več omejene."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Baterija v napravi je dovolj napolnjena. Funkcije niso več omejene."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"Mapa"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Aplikacija za Android"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Datoteka"</string>
@@ -2059,6 +2055,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"Preglednica <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Predstavitev"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Predstavitev <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth bo v načinu za letalo ostal vklopljen"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Nalaganje"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> in še <xliff:g id="COUNT_3">%d</xliff:g> datoteka</item>
@@ -2078,5 +2075,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Preklop razdeljenega zaslona"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Zaklenjen zaslon"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Posnetek zaslona"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Vrstica s podnapisi aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Paket <xliff:g id="PACKAGE_NAME">%1$s</xliff:g> je bil dodan v segment OMEJENO"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index ceba0be..fd8dda0 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Pajisja do të spastrohet"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Aplikacioni i administratorit nuk mund të përdoret. Pajisja jote tani do të fshihet.\n\nNëse ke pyetje, kontakto me administratorin e organizatës."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Printimi është çaktivizuar nga <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Unë"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opsionet e tabletit"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Opsionet e Android TV"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"qasje te kalendari yt"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"dërgo dhe shiko mesazhet SMS"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Skedarët dhe media"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"qasjen te fotografitë, përmbajtjet audio-vizuale dhe skedarët në pajisje"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofoni"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"regjistro audio"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Mund të trokasë, rrëshqasë, bashkojë gishtat dhe kryejë gjeste të tjera."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gjestet e gjurmës së gishtit"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Mund të regjistrojë gjestet e kryera në sensorin e gjurmës së gishtit të pajisjes."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Nxirr një pamje të ekranit"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Mund të nxirret një pamje e ekranit."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"çaktivizo ose modifiko shiritin e statusit"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Lejon aplikacionin të çaktivizojë shiritin e statusit dhe të heqë ikonat e sistemit."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"të bëhet shiriti i statusit"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Ke vizatuar <xliff:g id="NUMBER_0">%1$d</xliff:g> herë pa sukses motivin tënd. Pas <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativave të tjera të pasuksesshme, do të të duhet ta shkyçësh telefonin duke përdorur një llogari mail-i.\n\n Provo sërish për <xliff:g id="NUMBER_2">%3$d</xliff:g> sekonda."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" - "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Hiq"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Të ngrihet volumi mbi nivelin e rekomanduar?\n\nDëgjimi me volum të lartë për periudha të gjata mund të dëmtojë dëgjimin."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Të përdoret shkurtorja e qasshmërisë?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Kur shkurtorja është e aktivizuar, shtypja e të dy butonave për 3 sekonda do të nisë një funksion qasshmërie.\n\n Funksioni aktual i qasshmërisë:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Mund ta ndryshosh funksionin te Cilësimet &gt; Qasshmëria."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Boshatis"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Redakto shkurtoret"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Anulo"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Çaktivizo shkurtoren"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Aplikacioni nuk ofrohet"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> nuk ofrohet në këtë moment. Kjo menaxhohet nga <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Mëso më shumë"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Të aktivizohet profili i punës?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Aplikacionet e punës, njoftimet, të dhënat e tua dhe funksionet e tjera të profilit të punës do të aktivizohen"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Aktivizo"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ky aplikacion është ndërtuar për një version më të vjetër të Android dhe mund të mos funksionojë mirë. Provo të kontrollosh për përditësime ose kontakto me zhvilluesin."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Kontrollo për përditësim"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Ke mesazhe të reja"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Bateria mund të mbarojë përpara ngarkimit të zakonshëm"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"\"Kursyesi i baterisë\" u aktivizua për të zgjatur jetëgjatësinë e baterisë"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Kursyesi i baterisë"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"\"Kursyesi i baterisë\" është çaktivizuar"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefoni ka nivel të mjaftueshëm baterie. Funksionet nuk janë më të kufizuara."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Tableti ka nivel të mjaftueshëm baterie. Funksionet nuk janë më të kufizuara."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Pajisja ka nivel të mjaftueshëm baterie. Funksionet nuk janë më të kufizuara."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"Dosje"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Aplikacion i Android"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Skedar"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"Fletëllogaritëse <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Prezantim"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Prezantim <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth-i do të qëndrojë i aktivizuar gjatë modalitetit të aeroplanit"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Po ngarkohet"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> skedarë</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Kalo tek ekrani i ndarë"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Ekrani i kyçjes"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Pamja e ekranit"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Shiriti i nëntitullit të <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> është vendosur në grupin E KUFIZUAR"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index f3a2ce5..d82faa6 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -196,6 +196,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Уређај ће бити обрисан"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Не можете да користите ову апликацију за администраторе. Уређај ће сада бити обрисан.\n\nАко имате питања, контактирајте администратора организације."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Штампање је онемогућила апликација <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Ја"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Опције за таблет"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Опције Android TV-а"</string>
@@ -1631,10 +1635,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Нацртали сте шаблон за откључавање нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја, од вас ће бити затражено да откључате телефон помоћу налога е-поште.\n\nПробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунде/и."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Уклони"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Желите да појачате звук изнад препорученог нивоа?\n\nСлушање гласне музике дуже време може да вам оштети слух."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Желите ли да користите пречицу за приступачност?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Када је пречица укључена, притисните оба дугмета за јачину звука да бисте покренули функцију приступачности.\n\n Актуелна функција приступачности:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Можете да промените функцију у одељку Подешавања &gt; Приступачност."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Празно"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Измените пречице"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Откажи"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Искључи пречицу"</string>
@@ -1879,11 +1884,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Апликација није доступна"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"Апликација <xliff:g id="APP_NAME_0">%1$s</xliff:g> тренутно није доступна. <xliff:g id="APP_NAME_1">%2$s</xliff:g> управља доступношћу."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Сазнајте више"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Да укључимо профил за Work?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Укључиће се пословне апликације, обавештења, подаци и друге функције профила за Work"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Укључи"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"Апликација није доступна"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"Апликација <xliff:g id="APP_NAME">%1$s</xliff:g> тренутно није доступна."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ова апликација је направљена за старију верзију Android-а, па можда неће радити исправно. Потражите ажурирања или контактирајте програмера."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Потражи ажурирање"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Имате нове поруке"</string>
@@ -2017,6 +2022,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> табела"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Презентација"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> презентација"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth остаје укључен током режима рада у авиону"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Учитава се"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> и још <xliff:g id="COUNT_3">%d</xliff:g> датотека</item>
@@ -2035,5 +2041,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Укључите/искључите подељени екран"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Закључани екран"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Снимак екрана"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Трака са насловима апликације <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Пакет <xliff:g id="PACKAGE_NAME">%1$s</xliff:g> је додат у сегмент ОГРАНИЧЕНО"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index ade5e6a..9c7e1e5 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Enheten kommer att rensas"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Det går inte att använda administratörsappen. Enheten rensas.\n\nKontakta organisationens administratör om du har några frågor."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Utskrift har inaktiverats av <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Jag"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Alternativ för surfplattan"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Alternativ för Android TV"</string>
@@ -1609,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Du har ritat ditt grafiska lösenord fel <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%2$d</xliff:g> försök ombeds du låsa upp mobilen med hjälp av ett e-postkonto.\n\n Försök igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Ta bort"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vill du höja volymen över den rekommenderade nivån?\n\nAtt lyssna med stark volym långa stunder åt gången kan skada hörseln."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Vill du använda Aktivera tillgänglighet snabbt?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"När kortkommandot har aktiverats startar du en tillgänglighetsfunktion genom att trycka ned båda volymknapparna i tre sekunder.\n\n Aktuell tillgänglighetsfunktion:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Du kan ändra funktionen i Inställningar &gt; Tillgänglighet."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Töm"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Redigera genvägar"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Avbryt"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Inaktivera kortkommandot"</string>
@@ -1847,11 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Appen är inte tillgänglig"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> är inte tillgänglig just nu. Detta hanteras av <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Läs mer"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Vill du aktivera jobbprofilen?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Jobbappar, aviseringar, data och andra funktioner i jobbprofilen aktiveras"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Aktivera"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"Appen är inte tillgänglig"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> är inte tillgängligt just nu."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Appen har utvecklats för en äldre version av Android och kanske inte fungerar som den ska. Testa att söka efter uppdateringar eller kontakta utvecklaren."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Sök efter uppdateringar"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Du har nya meddelanden"</string>
@@ -1984,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g>-kalkylark"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Presentation"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g>-presentation"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth fortsätter att vara på i flygplansläget"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Läser in"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> filer</item>
@@ -2001,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Aktivera och inaktivera delad skärm"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Låsskärm"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Skärmdump"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Textningsfält för <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> har placerats i hinken RESTRICTED"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index f893af3..f53efe0 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Data iliyomo kwenye kifaa chako itafutwa"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Huwezi kutumia programu ya msimamizi. Sasa data iliyo kwenye kifaa chako itafutwa.\n\nIkiwa una maswali yoyote, wasiliana na msimamizi wa shirika lako."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Kipengele cha kuchapisha kimezimwa na <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Mimi"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Chaguo za kompyuta ndogo"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Chaguo za Android TV"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"ifikie kalenda yako"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"itume na iangalie SMS"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Faili na maudhui"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"ifikie picha, maudhui na faili kwenye kifaa chako"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Kipokea sauti"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"irekodi sauti"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Unaweza kugusa, kutelezesha kidole, kubana na kutekeleza ishara zingine."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Ishara za alama ya kidole"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Inaweza kurekodi ishara zinazotekelezwa kwenye kitambua alama ya kidole."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Piga picha ya skrini"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Inaweza kupiga picha ya skrini ya onyesho."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"zima au rekebisha mwambaa hali"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Inaruhusu programu kulemaza upau wa hali au kuongeza na kutoa aikoni za mfumo."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"kuwa sehemu ya arifa"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Umekosea kuchora mchoro wako wa kufungua mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Baada ya majaribio <xliff:g id="NUMBER_1">%2$d</xliff:g> yasiyofaulu, utaombwa kufungua simu yako kwa kutumia akaunti ya barua pepe.\n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_2">%3$d</xliff:g>."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Ondoa"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Ungependa kupandisha sauti zaidi ya kiwango kinachopendekezwa?\n\nKusikiliza kwa sauti ya juu kwa muda mrefu kunaweza kuharibu uwezo wako wa kusikia."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Ungependa kutumia njia ya mkato ya ufikivu?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Unapowasha kipengele cha njia ya mkato, hatua ya kubonyeza vitufe vyote viwili vya sauti kwa dakika 3 itafungua kipengele cha ufikivu.\n\n Kipengele cha ufikivu kilichopo kwa sasa:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Unaweza kubadilisha kipengele hiki katika Mipangilio &gt; Zana za ufikivu."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Tupu"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Kubadilisha njia za mkato"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Ghairi"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Zima kipengele cha Njia ya Mkato"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Programu haipatikani"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> haipatikani kwa sasa. Inasimamiwa na <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Pata maelezo zaidi"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Ungependa kuwasha wasifu wa kazini?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Hatua hii itawasha data, arifa, programu za kazini, arifa na vipengele vingine vya wasifu wa kazini"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Washa"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Programu hii iliundwa kwa ajili ya toleo la zamani la Android na huenda isifanye kazi vizuri. Jaribu kuangalia masasisho au uwasiliane na msanidi programu."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Angalia masasisho"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Una ujumbe mpya"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Huenda betri itakwisha chaji mapema"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Imewasha Kiokoa Betri ili kurefusha muda wa matumizi ya betri"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Kiokoa betri"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Kiokoa Betri kimezimwa"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Simu ina chaji ya kutosha. Vipengele havizuiliwi tena."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Kompyuta kibao ina chaji ya kutosha. Vipengele havizuiliwi tena."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Kifaa kina chaji ya kutosha. Vipengele havizuiliwi tena."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"Folda"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Programu ya Android"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Faili"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"Lahajedwali la <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Wasilisho"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Wasilisho la <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth haitazima katika hali ya ndegeni"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Inapakia"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other">Faili <xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g></item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Geuza Skrini Iliyogawanywa"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Skrini Iliyofungwa"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Picha ya skrini"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Upau wa manukuu wa <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> kimewekwa katika kikundi KILICHODHIBITIWA"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index d3a4613..c7c4ea3 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"சாதனத் தரவு அழிக்கப்படும்"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"நிர்வாகி ஆப்ஸை உபயோகிக்க முடியாது. இப்போது, உங்கள் சாதனம் ஆரம்ப நிலைக்கு மீட்டமைக்கப்படும்.\n\nஏதேனும் கேள்விகள் இருப்பின், உங்கள் நிறுவனத்தின் நிர்வாகியைத் தொடர்புகொள்ளவும்."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"பிரிண்ட் செய்வதை <xliff:g id="OWNER_APP">%s</xliff:g> தடுத்துள்ளது."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"நான்"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"டேப்லெட் விருப்பங்கள்"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV விருப்பத்தேர்வுகள்"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"கேலெண்டரை அணுகலாம்"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS அனுப்பலாம், வந்த SMSகளைப் பார்க்கலாம்"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"ஃபைல்களும் மீடியாவும்"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"உங்கள் சாதனத்தில் உள்ள படங்கள், மீடியா மற்றும் கோப்புகளை அணுக வேண்டும்"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"மைக்ரோஃபோன்"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ஒலிப் பதிவு செய்யலாம்"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"தட்டலாம், ஸ்வைப் செய்யலாம், பின்ச் செய்யலாம் மற்றும் பிற சைகைகளைச் செயல்படுத்தலாம்."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"கைரேகை சைகைகள்"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"சாதனத்தின் கைரேகை சென்சார்மேல் செய்யப்படும் சைகைகளைக் கேப்ட்சர் செய்ய முடியும்."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ஸ்கிரீன்ஷாட்டை எடுக்கும்"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"டிஸ்ப்ளேவை ஸ்கிரீன்ஷாட் எடுக்க முடியும்."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"நிலைப் பட்டியை முடக்குதல் அல்லது மாற்றுதல்"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"நிலைப் பட்டியை முடக்க அல்லது முறைமையில் ஐகான்களைச் சேர்க்க மற்றும் அகற்ற ஆப்ஸை அனுமதிக்கிறது."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"நிலைப் பட்டியில் இருக்கும்"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"திறப்பதற்கான வடிவத்தை <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக வரைந்துள்ளீர்கள். மேலும் <xliff:g id="NUMBER_1">%2$d</xliff:g> தோல்வி முயற்சிகளுக்குப் பிறகு, மின்னஞ்சல் கணக்கைப் பயன்படுத்தி உங்கள் மொபைலைத் திறக்கக் கேட்கப்படுவீர்கள்.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"அகற்று"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"பரிந்துரைத்த அளவை விட ஒலியை அதிகரிக்கவா?\n\nநீண்ட நேரத்திற்கு அதிகளவில் ஒலி கேட்பது கேட்கும் திறனைப் பாதிக்கலாம்."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"அணுகல்தன்மை ஷார்ட்கட்டைப் பயன்படுத்தவா?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"ஷார்ட்கட் இயக்கத்தில் இருந்தால், இரண்டு ஒலியளவு பொத்தான்களையும் 3 வினாடிகள் அழுத்தி, அணுகல்தன்மை அம்சத்தை இயக்கலாம்.\n\n தற்போதைய அணுகல்தன்மை அம்சம்:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n அமைப்புகள் &gt; அணுகல்தன்மை என்பதற்குச் சென்று, அம்சத்தை மாற்றலாம்."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"காலியானது"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ஷார்ட்கட்களை மாற்று"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"ரத்துசெய்"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"ஷார்ட்கட்டை முடக்கு"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"ஆப்ஸை உபயோகிக்க இயலாது"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"இப்போது <xliff:g id="APP_NAME_0">%1$s</xliff:g> ஆப்ஸை உபயோகிக்க இயலாது. இதை <xliff:g id="APP_NAME_1">%2$s</xliff:g> நிர்வகிக்கிறது."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"மேலும் அறிக"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"பணிச் சுயவிவரத்தை ஆன் செய்யவா?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"பணி ஆப்ஸ், அறிவிப்புகள், தரவு மற்றும் பிற பணிச் சுயவிவர அம்சங்கள் ஆன் செய்யப்படும்"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"இயக்கு"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"இந்த ஆப்ஸ் Android இன் பழைய பதிப்புக்காக உருவாக்கப்பட்டதால், சரியாக வேலை செய்யாமல் போகலாம். புதுப்பிப்புகள் ஏதேனும் உள்ளதா எனப் பார்க்கவும் அல்லது டெவெலப்பரைத் தொடர்புகொள்ளவும்."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"புதுப்பிப்பு உள்ளதா எனப் பார்"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"புதிய செய்திகள் வந்துள்ளன"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"வழக்கமாகச் சார்ஜ் செய்வதற்கு முன்பே பேட்டரி தீர்ந்துபோகக்கூடும்"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"பேட்டரி நிலையை நீட்டிக்க பேட்டரி சேமிப்பான் இயக்கப்பட்டுள்ளது"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"பேட்டரி சேமிப்பான்"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"பேட்டரி சேமிப்பான் ஆஃப் செய்யப்பட்டுள்ளது"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"மொபைலில் போதுமான சார்ஜ் உள்ளது. அம்சங்கள் இனி தடையின்றி இயங்கும்."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"டேப்லெட்டில் போதுமான சார்ஜ் உள்ளது. அம்சங்கள் இனி தடையின்றி இயங்கும்."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"சாதனத்தில் போதுமான சார்ஜ் உள்ளது. அம்சங்கள் இனி தடையின்றி இயங்கும்."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"கோப்புறை"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android ஆப்ஸ்"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"ஃபைல்"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> விரிதாள்"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"விளக்கக்காட்சி"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> விளக்கக்காட்சி"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"விமானப் பயன்முறையில் இருக்கும்போதும் புளூடூத் ஆன் செய்யப்பட்டே இருக்கும்"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"ஏற்றுகிறது"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ஃபைல்கள்</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"திரைப் பிரிப்பை நிலைமாற்று"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"பூட்டுத் திரை"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"ஸ்கிரீன்ஷாட்"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸின் தலைப்புப் பட்டி."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> என்பதை வரம்பிடப்பட்ட பக்கெட்திற்குள் சேர்க்கப்பட்டது"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 04a4d41..9c77ccd 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"మీ పరికరంలోని డేటా తొలగించబడుతుంది"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"నిర్వాహక యాప్‌ ఉపయోగించడం సాధ్యపడదు. మీ పరికరంలోని డేటా ఇప్పుడు తొలగించబడుతుంది.\n\nమీకు ప్రశ్నలు ఉంటే, మీ సంస్థ యొక్క నిర్వాహకులను సంప్రదించండి."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"ముద్రణ <xliff:g id="OWNER_APP">%s</xliff:g> ద్వారా నిలిపివేయబడింది."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"నేను"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"టాబ్లెట్ ఎంపికలు"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV ఎంపికలు"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"మీ క్యాలెండర్‌ను యాక్సెస్ చేయడానికి"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS సందేశాలను పంపడం మరియు వీక్షించడం"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"ఫైల్స్ మరియు మీడియా"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"మీ పరికరంలోని ఫోటోలు, మీడియా మరియు ఫైల్‌లను యాక్సెస్ చేయడానికి"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"మైక్రోఫోన్"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ఆడియోను రికార్డ్ చేయడానికి"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"నొక్కగలరు, స్వైప్ చేయగలరు, స్క్రీన్‌పై రెండు వేళ్లను ఉంచి ఆ వేళ్లను దగ్గరకు లేదా దూరానికి లాగగలరు మరియు ఇతర సంజ్ఞలను చేయగలరు."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"వేలిముద్ర సంజ్ఞలు"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"పరికర వేలిముద్ర సెన్సార్‌లో ఉపయోగించిన సంజ్ఞలను క్యాప్చర్ చేయవచ్చు."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"స్క్రీన్‌షాట్‌ను తీయండి"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"డిస్‌ప్లే యొక్క స్క్రీన్‌షాట్ తీసుకోవచ్చు."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"స్థితి బార్‌ను నిలిపివేయడం లేదా సవరించడం"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"స్థితి బార్‌ను నిలిపివేయడానికి లేదా సిస్టమ్ చిహ్నాలను జోడించడానికి మరియు తీసివేయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"స్థితి పట్టీగా ఉండటం"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"మీరు మీ అన్‌లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత, ఇమెయిల్ ఖాతాను ఉపయోగించి మీ ఫోన్‌ను అన్‌లాక్ చేయాల్సిందిగా మిమ్మల్ని అడుగుతారు.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"తీసివేయి"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"వాల్యూమ్‌ను సిఫార్సు చేయబడిన స్థాయి కంటే ఎక్కువగా పెంచాలా?\n\nసుదీర్ఘ వ్యవధుల పాటు అధిక వాల్యూమ్‌లో వినడం వలన మీ వినికిడి శక్తి దెబ్బ తినవచ్చు."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"యాక్సెస్ సామర్థ్యం షార్ట్‌కట్‌ను ఉపయోగించాలా?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"షార్ట్‌కట్ ఆన్‌లో ఉన్నప్పుడు, రెండు వాల్యూమ్ బటన్‌లను 3 సెకన్ల పాటు నొక్కితే యాక్సెస్ సామర్థ్య ఫీచర్ ప్రారంభం అవుతుంది.\n\n ప్రస్తుత యాక్సెస్ సామర్థ్య ఫీచర్:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n సెట్టింగ్‌లు &gt; యాక్సెస్ సామర్థ్యంలో మీరు ఫీచర్‌ను మార్చవచ్చు."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"ఖాళీ"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"షార్ట్‌కట్‌లను ఎడిట్ చేయి"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"రద్దు చేయి"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"సత్వరమార్గాన్ని ఆఫ్ చేయి"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"యాప్ అందుబాటులో లేదు"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ప్రస్తుతం అందుబాటులో లేదు. ఇది <xliff:g id="APP_NAME_1">%2$s</xliff:g> ద్వారా నిర్వహించబడుతుంది."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"మరింత తెలుసుకోండి"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"కార్యాలయ ప్రొఫైల్‌ని ఆన్ చేయాలా?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"మీ కార్యాలయ యాప్‌లు, నోటిఫికేషన్‌లు, డేటా మరియు ఇతర కార్యాలయ ప్రొఫైల్ ఫీచర్‌లు ఆన్ చేయబడతాయి"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"ఆన్ చేయి"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ఈ యాప్ పాత వెర్షన్ Android కోసం రూపొందించబడింది మరియు అది సరిగ్గా పని చేయకపోవచ్చు. అప్‌డేట్‌ల కోసం తనిఖీ చేయడానికి ప్రయత్నించండి లేదా డెవలపర్‌ని సంప్రదించండి."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"అప్‌డేట్ కోసం తనిఖీ చేయండి"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"మీకు కొత్త సందేశాలు ఉన్నాయి"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"మామూలుగా ఛార్జ్ చేసేలోపు బ్యాటరీ ఖాళీ కావచ్చు"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"బ్యాటరీ జీవితకాలాన్ని పెంచడానికి బ్యాటరీ సేవర్ యాక్టివేట్ చేయబడింది"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"బ్యాటరీ సేవర్"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"బ్యాటరీ సేవర్ ఆఫ్ చేయబడింది"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ఫోన్‌కు తగినంత ఛార్జింగ్ ఉంది. ఫీచర్‌లు ఇప్పటి నుండి పరిమితం చేయబడవు."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"టాబ్లెట్‌ కు తగినంత ఛార్జింగ్ ఉంది. ఫీచర్‌లు ఇప్పటి నుండి పరిమితం చేయబడవు."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"పరికరానికి తగినంత ఛార్జింగ్ ఉంది. ఫీచర్‌లు ఇప్పటి నుండి పరిమితం చేయబడవు."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"ఫోల్డర్"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android అప్లికేషన్"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"ఫైల్"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> స్ప్రెడ్‌షీట్"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"ప్రదర్శన"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> ప్రదర్శన"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"విమానం మోడ్‌లో బ్లూటూత్ ఆన్‌లో ఉంటుంది"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"లోడవుతోంది"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ఫైల్‌లు</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"స్క్రీన్ విభజనను టోగుల్ చేయి"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"స్క్రీన్‌ను లాక్ చేయి"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"స్క్రీన్‌షాట్"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> క్యాప్షన్ బార్."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> పరిమితం చేయబడిన బకెట్‌లో ఉంచబడింది"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 11aa407..efff25b 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"ระบบจะลบข้อมูลในอุปกรณ์ของคุณ"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"ใช้แอปผู้ดูแลระบบนี้ไม่ได้ ขณะนี้ระบบจะลบข้อมูลในอุปกรณ์ของคุณ\n\nโปรดติดต่อผู้ดูแลระบบขององค์กรหากมีคำถาม"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ปิดใช้การพิมพ์แล้ว"</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"ฉัน"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"ตัวเลือกของแท็บเล็ต"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"ตัวเลือกของ Android TV"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"เข้าถึงปฏิทิน"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"ส่งและดูข้อความ SMS"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"ไฟล์และสื่อ"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"เข้าถึงรูปภาพ สื่อ และไฟล์บนอุปกรณ์ของคุณ"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"ไมโครโฟน"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"บันทึกเสียง"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"สามารถแตะ เลื่อน บีบ และทำท่าทางสัมผัสอื่นๆ"</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"ท่าทางสัมผัสลายนิ้วมือ"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"สามารถจับท่าทางสัมผัสที่เกิดขึ้นบนเซ็นเซอร์ลายนิ้วมือของอุปกรณ์"</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ถ่ายภาพหน้าจอ"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ถ่ายภาพหน้าจอได้"</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"ปิดการใช้งานหรือแก้ไขแถบสถานะ"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"อนุญาตให้แอปพลิเคชันปิดใช้งานแถบสถานะหรือเพิ่มและนำไอคอนระบบออก"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"เป็นแถบสถานะ"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้งแล้ว หากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะขอให้คุณปลดล็อกโทรศัพท์โดยใช้ับัญชีอีเมล\n\n โปรดลองอีกครั้งในอีก <xliff:g id="NUMBER_2">%3$d</xliff:g> วินาที"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ลบ"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"นี่เป็นการเพิ่มระดับเสียงเกินระดับที่แนะนำ\n\nการฟังเสียงดังเป็นเวลานานอาจทำให้การได้ยินของคุณบกพร่องได้"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ใช้ทางลัดการช่วยเหลือพิเศษไหม"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"เมื่อทางลัดเปิดอยู่ การกดปุ่มปรับระดับเสียงทั้ง 2 ปุ่มเป็นเวลา 3 วินาทีจะเริ่มฟีเจอร์การช่วยเหลือพิเศษ\n\n ฟีเจอร์การช่วยเหลือพิเศษปัจจุบัน:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n คุณสามารถเปลี่ยนฟีเจอร์ในการตั้งค่า &gt; การช่วยเหลือพิเศษ"</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"ล้าง"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"แก้ไขทางลัด"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"ยกเลิก"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"ปิดทางลัด"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"แอปไม่พร้อมใช้งาน"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"เปิด <xliff:g id="APP_NAME_0">%1$s</xliff:g> ไม่ได้ในขณะนี้ แอปนี้จัดการโดย <xliff:g id="APP_NAME_1">%2$s</xliff:g>"</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"ดูข้อมูลเพิ่มเติม"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"เปิดโปรไฟล์งานไหม"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"ระบบจะเปิดแอปงาน การแจ้งเตือน ข้อมูล และฟีเจอร์อื่นๆ ในโปรไฟล์งาน"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"เปิด"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"แอปนี้สร้างขึ้นเพื่อ Android เวอร์ชันเก่าและอาจทำงานผิดปกติ โปรดลองตรวจหาการอัปเดตหรือติดต่อนักพัฒนาซอฟต์แวร์"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"ตรวจสอบอัปเดต"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"คุณมีข้อความใหม่"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"แบตเตอรี่อาจหมดก่อนการชาร์จปกติ"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"เปิดใช้งานโหมดประหยัดแบตเตอรี่แล้วเพื่อยืดอายุการใช้งานแบตเตอรี่"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"โหมดประหยัดแบตเตอรี่"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"ปิดโหมดประหยัดแบตเตอรี่แล้ว"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"โทรศัพท์มีแบตเตอรี่เพียงพอ ไม่มีการจำกัดฟีเจอร์แล้ว"</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"แท็บเล็ตมีแบตเตอรี่เพียงพอ ไม่มีการจำกัดฟีเจอร์แล้ว"</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"อุปกรณ์มีแบตเตอรี่เพียงพอ ไม่มีการจำกัดฟีเจอร์แล้ว"</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"โฟลเดอร์"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"ไฟล์แอปพลิเคชัน Android"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"ไฟล์"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"ไฟล์สเปรดชีต <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"ไฟล์งานนำเสนอ"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"ไฟล์งานนำเสนอ <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"บลูทูธจะเปิดอยู่ในโหมดบนเครื่องบิน"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"กำลังโหลด"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> และอีก <xliff:g id="COUNT_3">%d</xliff:g> ไฟล์</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"เปิด/ปิดการแบ่งหน้าจอ"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"หน้าจอล็อก"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"ภาพหน้าจอ"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"แถบคำบรรยาย <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"ใส่ <xliff:g id="PACKAGE_NAME">%1$s</xliff:g> ในที่เก็บข้อมูลที่ถูกจำกัดแล้ว"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 718e170..7cfa7b0 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Buburahin ang iyong device"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Hindi magamit ang admin app. Mabubura na ang iyong device.\n\nKung mayroon kang mga tanong, makipag-ugnayan sa admin ng iyong organisasyon."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Na-disable ng <xliff:g id="OWNER_APP">%s</xliff:g> ang pag-print."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Ako"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Mga pagpipilian sa tablet"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Mga opsyon sa Android TV"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"i-access ang iyong kalendaryo"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"magpadala at tumingin ng mga mensaheng SMS"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Mga file at media"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"i-access ang mga larawan, media at file sa iyong device"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikropono"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"mag-record ng audio"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"May kakayahang mag-tap, mag-swipe, mag-pinch at magsagawa ng iba pang mga galaw."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Mga galaw gamit ang fingerprint"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Makukunan ang mga galaw na ginawa sa sensor para sa fingerprint ng device."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Kumuha ng screenshot"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Puwedeng kumuha ng screenshot ng display."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"i-disable o baguhin ang status bar"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Pinapayagan ang app na i-disable ang status bar o magdagdag at mag-alis ng mga icon ng system."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"maging status bar"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Naguhit mo nang hindi tama ang iyong pattern sa pag-unlock nang <xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses. Pagkatapos ng <xliff:g id="NUMBER_1">%2$d</xliff:g> pang hindi matagumpay na pagtatangka, hihilingin sa iyong i-unlock ang telepono mo gamit ang isang email account.\n\n Subukang muli sa loob ng <xliff:g id="NUMBER_2">%3$d</xliff:g> (na) segundo."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Alisin"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Lakasan ang volume nang lagpas sa inirerekomendang antas?\n\nMaaaring mapinsala ng pakikinig sa malakas na volume sa loob ng mahahabang panahon ang iyong pandinig."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Gagamitin ang Shortcut sa Pagiging Accessible?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Kapag naka-on ang shortcut, magsisimula ang isang feature ng pagiging naa-access kapag pinindot ang parehong button ng volume sa loob ng 3 segundo.\n\n Kasalukuyang feature ng pagiging naa-access:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Maaari mong baguhin ang feature sa Mga Setting &gt; Pagiging Accessible."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Bakantehin"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"I-edit ang mga shortcut"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Kanselahin"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"I-off ang Shortcut"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Hindi available ang app"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"Hindi available ang <xliff:g id="APP_NAME_0">%1$s</xliff:g> sa ngayon. Pinamamahalaan ito ng <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Matuto pa"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"I-on ang profile sa trabaho?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Mao-on ang iyong mga app sa trabaho, notification, data, at iba pang feature sa profile sa trabaho"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"I-on"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ang app na ito ay ginawa para sa mas lumang bersyon ng Android at maaaring hindi gumana nang maayos. Subukang tingnan kung may mga update, o makipag-ugnayan sa developer."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Tingnan kung may update"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Mayroon kang mga bagong mensahe"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Maaaring maubos ang baterya bago ang karaniwang pag-charge"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Na-activate ang Pangtipid sa Baterya para patagalin ang buhay ng baterya"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Pangtipid sa Baterya"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Na-off ang Pangtipid sa Baterya"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"May sapat na charge ang telepono. Hindi na pinaghihigpitan ang mga feature."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"May sapat na charge ang tablet. Hindi na pinaghihigpitan ang mga feature."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"May sapat na charge ang device. Hindi na pinaghihigpitan ang mga feature."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"Folder"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android application"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"File"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> na spreadsheet"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Presentation"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> na presentation"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Mananatiling naka-on ang bluetooth habang nasa airplane mode"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Naglo-load"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> file</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"I-toggle ang Split Screen"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Lock Screen"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Screenshot"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Caption bar ng <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Inilagay ang <xliff:g id="PACKAGE_NAME">%1$s</xliff:g> sa PINAGHIHIGPITANG bucket"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 93d9af1..b47eb4b 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Cihazınız silinecek"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Yönetim uygulaması kullanılamıyor. Cihazınız şimdi silinecek.\n\nSorularınız varsa kuruluşunuzun yöneticisine başvurun."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Yazdırma işlemi <xliff:g id="OWNER_APP">%s</xliff:g> tarafından devre dışı bırakıldı."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Ben"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tablet seçenekleri"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV seçenekleri"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"takviminize erişme"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS mesajları gönderme ve görüntüleme"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Dosyalar ve medya"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"cihazınızdaki fotoğraflara, medyaya ve dosyalara erişme"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ses kaydetme"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Dokunabilir, hızlıca kaydırabilir, sıkıştırabilir ve diğer hareketleri yapabilirsiniz."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Parmak izi hareketleri"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Cihazın parmak izi sensörlerinde gerçekleştirilen hareketleri yakalayabilir."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ekran görüntüsü al"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Ekran görüntüsü alınabilir."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"durum çubuğunu devre dışı bırak veya değiştir"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Uygulamaya, durum çubuğunu devre dışı bırakma ve sistem simgelerini ekleyip kaldırma izni verir."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"durum çubuğunda olma"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Kilit açma deseninizi <xliff:g id="NUMBER_0">%1$d</xliff:g> kez yanlış çizdiniz. <xliff:g id="NUMBER_1">%2$d</xliff:g> başarısız denemeden sonra telefonunuzu bir e-posta hesabı kullanarak açmanız istenir.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> saniye içinde tekrar deneyin."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Kaldır"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Ses seviyesi önerilen düzeyin üzerine yükseltilsin mi?\n\nUzun süre yüksek ses seviyesinde dinlemek işitme duyunuza zarar verebilir."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Erişilebilirlik Kısayolu Kullanılsın mı?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Kısayol açık olduğunda, ses düğmelerinin ikisini birden 3 saniyeliğine basılı tutmanız bir erişilebilirlik özelliğini başlatır.\n\n Geçerli erişilebilirlik özelliği:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Özelliği, Ayarlar &gt; Erişilebilirlik seçeneğinden değiştirebilirsiniz."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Boş"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Kısayolları düzenle"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"İptal"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Kısayolu Kapat"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Uygulama kullanılamıyor"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> uygulaması şu anda kullanılamıyor. Uygulamanın kullanım durumu <xliff:g id="APP_NAME_1">%2$s</xliff:g> tarafından yönetiliyor."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Daha fazla bilgi"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"İş profili açılsın mı?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"İş uygulamalarınız, bildirimleriniz, verileriniz ve diğer iş profili özellikleriniz açılacak"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Aç"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Bu uygulama Android\'in daha eski bir sürümü için oluşturuldu ve düzgün çalışmayabilir. Güncellemeleri kontrol etmeyi deneyin veya geliştiriciyle iletişime geçin."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Güncellemeleri denetle"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Yeni mesajlarınız var"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Pil normal şarjdan önce bitebilir"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Pilin ömrünü uzatmak için Pil Tasarrufu etkinleştirildi"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Pil Tasarrufu"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Pil Tasarrufu kapatıldı"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefon yeterince şarj oldu. Özellikler artık kısıtlanmış değil."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Tablet yeterince şarj oldu. Özellikler artık kısıtlanmış değil."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Cihaz yeterince şarj oldu. Özellikler artık kısıtlanmış değil."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"Klasör"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android uygulaması"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Dosya"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> e-tablo dosyası"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Sunu"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> sunu dosyası"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Uçak modunda Bluetooth açık kalacak"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Yükleniyor"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> dosya</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Bölünmüş Ekranı aç/kapat"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Kilit Ekranı"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Ekran görüntüsü"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> uygulamasının başlık çubuğu."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> KISITLANMIŞ gruba yerleştirildi"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 0f8b368..22aa199 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -198,6 +198,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"З вашого пристрою буде стерто всі дані"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Не можна запускати додаток для адміністраторів. Буде відновлено заводські налаштування пристрою.\n\nЯкщо у вас є запитання, зв’яжіться з адміністратором своєї організації."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Додаток <xliff:g id="OWNER_APP">%s</xliff:g> вимкнув друк."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Я"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Парам. пристрою"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Опції Android TV"</string>
@@ -293,8 +297,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"отримувати доступ до календаря"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"надсилати та переглядати SMS-повідомлення"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Файли й мультимедіа"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"отримувати доступ до фотографій, мультимедійного вмісту та файлів на вашому пристрої"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Мікрофон"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"записувати аудіо"</string>
@@ -320,10 +323,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Можна торкатися, проводити пальцем, стискати пальці та виконувати інші жести."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Жести на сканері відбитків пальців"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Може фіксувати жести на сканері відбитків пальців."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Робити знімки екрана"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Може робити знімки екрана."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"вимикати чи змін. рядок стану"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Дозволяє програмі вимикати рядок стану чи додавати та видаляти піктограми системи."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"відображатися як рядок стану"</string>
@@ -1656,10 +1657,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Ключ розблокування неправильно намальовано стільки разів: <xliff:g id="NUMBER_0">%1$d</xliff:g>. У вас є ще стільки спроб: <xliff:g id="NUMBER_1">%2$d</xliff:g>. У разі невдачі з’явиться запит розблокувати телефон за допомогою облікового запису електронної пошти.\n\n Повторіть спробу через <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Вилучити"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Збільшити гучність понад рекомендований рівень?\n\nЯкщо слухати надто гучну музику тривалий час, можна пошкодити слух."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Використовувати швидке ввімкнення?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Коли ярлик увімкнено, після натискання обох клавіш гучності й утримування їх протягом 3 секунд увімкнеться функція спеціальних можливостей.\n\n Поточна функція спеціальних можливостей:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Цю функцію можна змінити в меню \"Налаштування\" &gt; \"Спеціальні можливості\"."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Очистити"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Редагувати засоби"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Скасувати"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Вимкнути ярлик"</string>
@@ -1914,13 +1916,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Додаток недоступний"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"Додаток <xliff:g id="APP_NAME_0">%1$s</xliff:g> зараз недоступний. Керує додаток <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Докладніше"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Увімкнути робочий профіль?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Додатки, сповіщення, дані й інші функції робочого профілю буде ввімкнено"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Увімкнути"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Цей додаток створений для старішої версії Android і може працювати неналежним чином. Спробуйте знайти оновлення або зв’яжіться з розробником."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Шукати оновлення"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"У вас є нові повідомлення"</string>
@@ -2033,14 +2033,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Акумулятор може розрядитися раніше ніж зазвичай"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Режим енергозбереження активовано для збільшення часу роботи акумулятора"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Режим енергозбереження"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Режим енергозбереження вимкнено."</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Телефон має достатньо заряду акумулятора. Функції вже не обмежено."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Планшет має достатньо заряду акумулятора. Функції вже не обмежено."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Пристрій має достатньо заряду акумулятора. Функції вже не обмежено."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"Папка"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Додаток Android"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Файл"</string>
@@ -2059,6 +2055,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"Таблиця у форматі <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Презентація"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Презентація у форматі <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"У режимі польоту Bluetooth залишатиметься ввімкненим"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Завантаження"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> і ще <xliff:g id="COUNT_3">%d</xliff:g> файл</item>
@@ -2078,5 +2075,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Розділити екран"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Заблокувати екран"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Знімок екрана"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Смуга із субтитрами для додатка <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Пакет \"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g>\" додано в сегмент з обмеженнями"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 5b957159..a88d6c5 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"آپ کا آلہ صاف کر دیا جائے گا"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"منتظم کی ایپ استعمال نہیں کی جا سکتی۔ آپ کا آلہ اب مٹا دیا جائے گا۔\n\nاگر آپ کے سوالات ہیں تو اپنی تنظیم کے منتظم سے رابطہ کریں۔"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> نے پرنٹنگ کو غیر فعال کر دیا ہے۔"</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"میں"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"ٹیبلیٹ کے اختیارات"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"‏Android TV اختیارات"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"اپنے کیلنڈر تک رسائی حاصل کریں"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"‏SMS پیغامات بھیجیں اور دیکھیں"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"فائلز اور میڈیا"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"آپ کے آلہ پر تصاویر، میڈیا اور فائلوں تک رسائی حاصل کر سکتی ہیں"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"مائکروفون"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"آڈیو ریکارڈ کریں"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"تھپتھپانا، سوائپ کرنا، چٹکی بھرنا اور دیگر اشارے انجام دے سکتی ہے"</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"فنگر پرنٹ کے اشارے"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"آلہ کے فنگر پرنٹ سینسر پر کیے گئے اشاروں کو کیپچر کر سکتا ہے۔"</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"اسکرین شاٹ لیں"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ڈسپلے کا اسکرین شاٹ لیا جا سکتا ہے۔"</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"اسٹیٹس بار کو غیر فعال یا اس میں ترمیم کریں"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"ایپ کو اسٹیٹس بار غیر فعال کرنے یا سسٹم آئیکنز شامل کرنے اور ہٹانے کی اجازت دیتا ہے۔"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"بطور اسٹیٹس بار کام لیں"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"آپ نے اپنا غیر مقفل کرنے کا پیٹرن <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے ڈرا کیا ہے۔ <xliff:g id="NUMBER_1">%2$d</xliff:g> مزید ناکام کوششوں کے بعد، آپ سے ایک ای میل اکاؤنٹ استعمال کرکے اپنا فون غیر مقفل کرنے کو کہا جائے گا۔\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> سیکنڈ میں دوبارہ کوشش کریں۔"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ہٹائیں"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"والیوم کو تجویز کردہ سطح سے زیادہ کریں؟\n\nزیادہ وقت تک اونچی آواز میں سننے سے آپ کی سماعت کو نقصان پہنچ سکتا ہے۔"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ایکسیسبیلٹی شارٹ کٹ استعمال کریں؟"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"شارٹ کٹ آن ہونے پر، 3 سیکنڈ تک دونوں والیوم بٹنز کو دبانے سے ایک ایکسیسبیلٹی خصوصیت شروع ہو جائے گی۔\n\n موجودہ ایکسیسبیلٹی خصوصیت:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n آپ خصوصیت کو ترتیبات &gt; ایکسیسبیلٹی میں جا کر تبدیل کر سکتے ہیں۔"</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"خالی"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"شارٹ کٹس میں ترمیم کریں"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"منسوخ کریں"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"شارٹ کٹ آف کریں"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"ایپ دستیاب نہیں ہے"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ابھی دستیاب نہیں ہے۔ یہ <xliff:g id="APP_NAME_1">%2$s</xliff:g> کے زیر انتظام ہے۔"</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"مزید جانیں"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"دفتری پروفائل آن کریں؟"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"آپ کی دفتری ایپس، اطلاعات، ڈیٹا اور دفتری پروفائل کی دیگر خصوصیات آن کر دی جائیں گی"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"آن کریں"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"‏یہ ایپ Android کے پرانے ورژن کے لئے بنائی گئی ہے اور ہو سکتا ہے صحیح طور پر کام نہ کرے۔ اپ ڈیٹس چیک کر کے آزمائیں یا ڈیولپر سے رابطہ کریں۔"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"اپ ڈیٹ چیک کریں"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"آپ کے پاس نئے پیغامات ہیں"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"معمول چارج سے پہلے بیٹری ختم ہو سکتی ہے"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"بیٹری لائف کو بڑھانے کے لیے بیٹری سیور کو فعال کر دیا گیا ہے"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"بیٹری سیور"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"بیٹری سیور کو آف کر دیا گیا"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"فون میں کافی چارج ہے۔ خصوصیات پر اب پابندی نہیں ہے۔"</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"ٹیبلیٹ میں کافی چارج ہے۔ خصوصیات پر اب پابندی نہیں ہے۔"</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"آلہ میں کافی چارج ہے۔ خصوصیات پر اب پابندی نہیں ہے۔"</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"فولڈر"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"‏Android ایپلیکیشن"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"فائل"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> اسپریڈشیٹ"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"پیشکش"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> پیشکش"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"ہوائی جہاز وضع کے دوران بلوٹوتھ آن رہے گا"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"لوڈ ہو رہا ہے"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> فائلز</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"اسپلٹ اسکرین ٹوگل کریں"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"مقفل اسکرین"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"اسکرین شاٹ"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> کی کیپشن بار۔"</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> کو پابند کردہ بکٹ میں رکھ دیا گیا ہے"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index c837414..a08b178 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Qurilmangizdagi ma’lumotlar o‘chirib tashlanadi"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Administrator ilovasini ishlatib bo‘lmaydi. Qurilmada barcha ma’lumotlar o‘chirib tashlanadi.\n\nSavollaringiz bo‘lsa, administrator bilan bog‘laning."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Chop etish funksiyasi <xliff:g id="OWNER_APP">%s</xliff:g> tomonidan faolsizlantirilgan."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Men"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Planshet sozlamalari"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV parametrlari"</string>
@@ -1609,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Siz grafik kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri chizdingiz. <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinishdan so‘ng, sizdan e-pochtangizdan foydalanib, telefon qulfini ochishingiz so‘raladi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan so‘ng yana urinib ko‘ring."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Olib tashlash"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Tovush balandligi tavsiya etilgan darajadan ham yuqori qilinsinmi?\n\nUzoq vaqt davomida baland ovozda tinglash eshitish qobiliyatingizga salbiy ta’sir ko‘rsatishi mumkin."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Tezkor ishga tushirishdan foydalanilsinmi?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Maxsus imkoniyatlar funksiyasidan foydalanish uchun u yoniqligida ikkala ovoz balandligini boshqarish tugmasini 3 soniya bosib turing.\n\n Joriy maxsus imkoniyatlar funksiyasi:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Bu funksiyani Sozlamalar &gt; Maxsus imkoniyatlar orqali o‘zgartirish mumkin."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Boʻshatish"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Tezkor tugmalarni tahrirlash"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Bekor qilish"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Tezkor ishga tushirishni o‘chirib qo‘yish"</string>
@@ -1847,11 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Ilova ishlamayapti"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ishlamayapti. Uning ishlashini <xliff:g id="APP_NAME_1">%2$s</xliff:g> cheklamoqda."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Batafsil"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Ishchi profil yoqilsinmi?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Ishchi ilovalar, bildirishnomalar, ma’lumotlar va boshqa ishchi profil imkoniyatlari yoqiladi"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Yoqish"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"Ilova ishlamayapti"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"Ayni vaqtda <xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi ishlamayapti."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Bu ilova eskiroq Android versiyalariga chiqarilgan va xato ishlashi mumkin. Yangilanishlarini tekshiring yoki dasturchi bilan bog‘laning."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Yangilanish borligini tekshirish"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Sizga yangi SMS keldi"</string>
@@ -1984,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> jadval"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Taqdimot"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> taqdimot"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth parvoz rejimida yoniq qoladi"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Yuklanmoqda"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ta fayl</item>
@@ -2001,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Ekranni ikkiga ajratish tugmasi"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Ekran qulfi"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Skrinshot"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> taglavhalar paneli."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> cheklangan turkumga joylandi"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 82662ab..db55613 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Thiết bị của bạn sẽ bị xóa"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Không thể sử dụng ứng dụng quản trị. Thiết bị của bạn sẽ bị xóa ngay bây giờ.\n\nHãy liên hệ với quản trị viên của tổ chức nếu bạn có thắc mắc."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> đã tắt tính năng in."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Tôi"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tùy chọn máy tính bảng"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Tùy chọn dành cho Android TV"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"truy cập lịch của bạn"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"Tin nhắn SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"gửi và xem tin nhắn SMS"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"Tệp và nội dung nghe nhìn"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"truy cập ảnh, phương tiện và tệp trên thiết bị của bạn"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Micrô"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ghi âm"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Có thể nhấn, vuốt, chụm và thực hiện các cử chỉ khác."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Cử chỉ vân tay"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Có thể ghi lại các cử chỉ được thực hiện trên cảm biến vân tay của thiết bị."</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Chụp ảnh màn hình"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Có thể chụp ảnh màn hình."</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"vô hiệu hóa hoặc sửa đổi thanh trạng thái"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Cho phép ứng dụng vô hiệu hóa thanh trạng thái hoặc thêm và xóa biểu tượng hệ thống."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"trở thành thanh trạng thái"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Bạn đã <xliff:g id="NUMBER_0">%1$d</xliff:g> lần vẽ không chính xác hình mở khóa của mình. Sau <xliff:g id="NUMBER_1">%2$d</xliff:g> lần thử không thành công nữa, bạn sẽ được yêu cầu mở khóa điện thoại bằng tài khoản email.\n\n Vui lòng thử lại sau <xliff:g id="NUMBER_2">%3$d</xliff:g> giây."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Xóa"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Bạn tăng âm lượng lên quá mức khuyên dùng?\n\nViệc nghe ở mức âm lượng cao trong thời gian dài có thể gây tổn thương thính giác của bạn."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Sử dụng phím tắt Hỗ trợ tiếp cận?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Khi phím tắt được bật, nhấn cả hai nút âm lượng trong 3 giây sẽ bắt đầu một tính năng trợ năng.\n\n Tính năng trợ năng hiện tại:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Bạn có thể thay đổi tính năng trong Cài đặt &gt; Trợ năng."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Xóa sạch"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Chỉnh sửa phím tắt"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Hủy"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Tắt phím tắt"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Ứng dụng không sử dụng được"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> hiện không sử dụng được. Chính sách này do <xliff:g id="APP_NAME_1">%2$s</xliff:g> quản lý."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Tìm hiểu thêm"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Bạn muốn bật hồ sơ công việc?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Ứng dụng công việc, thông báo, dữ liệu và các tính năng khác của hồ sơ công việc sẽ được bật"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Bật"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ứng dụng này được xây dựng cho một phiên bản Android cũ hơn và có thể hoạt động không bình thường. Hãy thử kiểm tra các bản cập nhật hoặc liên hệ với nhà phát triển."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Kiểm tra bản cập nhật"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Bạn có tin nhắn mới"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Pin có thể hết trước khi sạc bình thường"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Trình tiết kiệm pin được kích hoạt để kéo dài thời lượng pin"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Trình tiết kiệm pin"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Trình tiết kiệm pin đã tắt"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Điện thoại còn đủ pin. Các tính năng không bị hạn chế nữa."</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Máy tính bảng còn đủ pin. Các tính năng không bị hạn chế nữa."</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Thiết bị còn đủ pin. Các tính năng không bị hạn chế nữa."</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"Thư mục"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Ứng dụng Android"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Tệp"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"Bảng tính <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Bản trình bày"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Bản trình bày <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth sẽ không tắt khi chế độ trên máy bay bật"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Đang tải"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> tệp</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Bật/tắt chế độ chia đôi màn hình"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Khóa màn hình"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Chụp ảnh màn hình"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Thanh phụ đề của <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Đã đưa <xliff:g id="PACKAGE_NAME">%1$s</xliff:g> vào bộ chứa BỊ HẠN CHẾ"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 101a2ec..08d2326 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"系统将清空您的设备"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"无法使用管理应用,系统现在将清空您的设备。\n\n如有疑问,请与您所在单位的管理员联系。"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"“<xliff:g id="OWNER_APP">%s</xliff:g>”已停用打印功能。"</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"我"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"平板电脑选项"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV 选项"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"访问您的日历"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"短信"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"发送和查看短信"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"文件和媒体"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"访问您设备上的照片、媒体内容和文件"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"麦克风"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"录制音频"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"可执行点按、滑动、双指张合等手势。"</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"指纹手势"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"可以捕获在设备指纹传感器上执行的手势。"</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"截取屏幕截图"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"可截取显示画面的屏幕截图。"</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"停用或修改状态栏"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"允许应用停用状态栏或者增删系统图标。"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"用作状态栏"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"您已连续 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次画错解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次后仍不成功,系统就会要求您使用自己的电子邮件帐号解锁手机。\n\n请在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒后重试。"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"删除"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"要将音量调高到建议的音量以上吗?\n\n长时间保持高音量可能会损伤听力。"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"要使用无障碍快捷方式吗?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"开启快捷方式后,同时按下两个音量按钮 3 秒钟即可启动所设定的无障碍功能。\n\n当前设定的无障碍功能:\n<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n如需更改设定的功能,请依次转到“设置”&gt;“无障碍”。"</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"清空"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"修改快捷方式"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"取消"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"关闭快捷方式"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"应用无法使用"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g>目前无法使用。该应用是由<xliff:g id="APP_NAME_1">%2$s</xliff:g>所管理。"</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"了解详情"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"要开启工作资料吗?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"您的工作应用、通知、数据及其他工作资料功能将会开启"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"开启"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"此应用专为旧版 Android 打造,因此可能无法正常运行。请尝试检查更新或与开发者联系。"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"检查更新"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"您有新消息"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"电池电量可能会在您平时的充电时间之前耗尽"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"已启用省电模式以延长电池续航时间"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"省电模式"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"省电模式已关闭"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"手机电量充足。各项功能不再受限。"</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"平板电脑电量充足。各项功能不再受限。"</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"设备电量充足。各项功能不再受限。"</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"文件夹"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android 应用"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"文件"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> 电子表格"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"演示文稿"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> 演示文稿"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"在飞行模式下,蓝牙将保持开启状态"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"正在加载"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> 个文件</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"开启/关闭分屏"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"锁定屏幕"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"屏幕截图"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g>的标题栏。"</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> 已被放入受限存储分区"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 2929869..ea106c6 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"您的裝置將被清除"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"無法使用管理員應用程式。系統會現在清除您的裝置。\n\n如有任何疑問,請聯絡您的機構管理員。"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"「<xliff:g id="OWNER_APP">%s</xliff:g>」暫停了列印。"</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"我本人"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"平板電腦選項"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV 選項"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"存取您的日曆"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"短訊"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"傳送和查看短訊"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"檔案及媒體"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"存取裝置上的相片、媒體和檔案"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"麥克風"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"錄音"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"可以輕按、滑動和兩指縮放,並執行其他手勢。"</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"指紋手勢"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"可以擷取在裝置指紋感應器上執行的手勢。"</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"擷取螢幕擷圖"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"可以擷取螢幕截圖。"</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"停用或修改狀態列"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"允許應用程式停用狀態列,並可新增或移除系統圖示。"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"成為狀態列"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"您已畫錯解鎖圖案 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次,如果再嘗試 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次仍未成功,系統會要求您透過電郵帳戶解開上鎖的手機。\n\n請在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後再試一次。"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"移除"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"要調高音量 (比建議的音量更大聲) 嗎?\n\n長時間聆聽高分貝音量可能會導致您的聽力受損。"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"要使用無障礙功能快速鍵嗎?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"快速鍵開啟後,同時按住音量按鈕 3 秒,無障礙功能便會啟用。\n\n目前的無障礙功能:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n如要變更功能,請前往「設定」&gt;「無障礙功能」。"</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"空白"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"編輯捷徑"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"取消"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"關閉快速鍵"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"目前無法使用此應用程式"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"目前無法使用 <xliff:g id="APP_NAME_0">%1$s</xliff:g>。此應用程式是由「<xliff:g id="APP_NAME_1">%2$s</xliff:g>」管理。"</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"瞭解詳情"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"要開啟工作設定檔嗎?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"系統將開啟您的工作應用程式、通知、資料和其他工作設定檔功能"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"開啟"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"此應用程式專為舊版 Android 打造,因此可能無法正常運作。請嘗試檢查更新,或與開發人員聯絡。"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"檢查更新"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"您有新的訊息"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"電量可能會在日常充電前耗盡"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"「省電模式」已啟用,以便延長電池壽命"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"省電模式"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"已關閉省電模式"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"手機電量充足。各項功能已不再受限。"</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"平板電腦電量充足。各項功能已不再受限。"</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"裝置電量充足。各項功能已不再受限。"</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"資料夾"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android 應用程式"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"檔案"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> 試算表"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"簡報"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> 簡報"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"啟用飛行模式期間,藍牙會保持開啟"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"正在載入"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> 個檔案</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"切換分割螢幕"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"將畫面上鎖"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"螢幕截圖"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」的說明列。"</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> 已納入受限制的儲存區"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 48ff3f6..7065181 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"你的裝置資料將遭到清除"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"無法使用管理應用程式,系統現在將清除你裝置中的資料。\n\n如有任何問題,請與貴機構的管理員聯絡。"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"「<xliff:g id="OWNER_APP">%s</xliff:g>」已停用列印功能。"</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"我"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"平板電腦選項"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV 選項"</string>
@@ -287,8 +291,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"存取你的日曆"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"簡訊"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"傳送及查看簡訊"</string>
-    <!-- no translation found for permgrouplab_storage (1938416135375282333) -->
-    <skip />
+    <string name="permgrouplab_storage" msgid="1938416135375282333">"檔案和媒體"</string>
     <string name="permgroupdesc_storage" msgid="6351503740613026600">"存取裝置中的相片、媒體和檔案"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"麥克風"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"錄音"</string>
@@ -314,10 +317,8 @@
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"可使用輕觸、滑動和雙指撥動等手勢。"</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"指紋手勢"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"可以擷取使用者對裝置的指紋感應器執行的手勢。"</string>
-    <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) -->
-    <skip />
-    <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) -->
-    <skip />
+    <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"擷取螢幕畫面"</string>
+    <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"可以擷取螢幕畫面。"</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"停用或變更狀態列"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"允許應用程式停用狀態列,並可新增或移除系統圖示。"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"以狀態列顯示"</string>
@@ -1612,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"你的解鎖圖案已畫錯 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次,如果再嘗試 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次仍未成功,系統就會要求你透過電子郵件帳戶解除手機的鎖定狀態。\n\n請在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後再試一次。"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"移除"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"要調高音量,比建議的音量更大聲嗎?\n\n長時間聆聽高分貝音量可能會使你的聽力受損。"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"要使用無障礙捷徑嗎?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"啟用捷徑功能後,只要同時按下兩個音量鍵 3 秒,就能啟動無障礙功能。\n\n 目前設定的無障礙功能為:\n<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n 如要變更設定的功能,請依序輕觸 [設定] &gt; [無障礙設定]。"</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"空白"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"編輯捷徑"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"取消"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"停用捷徑"</string>
@@ -1850,13 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"應用程式目前無法使用"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"目前無法使用「<xliff:g id="APP_NAME_0">%1$s</xliff:g>」。這項設定是由「<xliff:g id="APP_NAME_1">%2$s</xliff:g>」管理。"</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"瞭解詳情"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"要開啟工作資料夾嗎?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"系統將開啟你的辦公應用程式、通知、資料和其他工作資料夾功能"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"開啟"</string>
-    <!-- no translation found for app_blocked_title (7353262160455028160) -->
-    <skip />
-    <!-- no translation found for app_blocked_message (542972921087873023) -->
-    <skip />
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"這個應用程式是專為舊版 Android 所打造,因此可能無法正常運作。請嘗試檢查更新,或是與開發人員聯絡。"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"檢查更新"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"你有新訊息"</string>
@@ -1967,14 +1967,10 @@
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"電池電力可能會在你平常的充電時間前耗盡"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"已啟用節約耗電量模式以延長電池續航力"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"節約耗電量"</string>
-    <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) -->
-    <skip />
-    <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) -->
-    <skip />
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"節約耗電量模式已關閉"</string>
+    <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"手機電力充足,各項功能不再受到限制。"</string>
+    <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"平板電腦電力充足,各項功能不再受到限制。"</string>
+    <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"裝置電力充足,各項功能不再受到限制。"</string>
     <string name="mime_type_folder" msgid="2203536499348787650">"資料夾"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android 應用程式"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"檔案"</string>
@@ -1993,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> 試算表"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"簡報"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> 簡報"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"藍牙將在飛航模式下保持開啟狀態"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"載入中"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other">「<xliff:g id="FILE_NAME_2">%s</xliff:g>」及另外 <xliff:g id="COUNT_3">%d</xliff:g> 個檔案</item>
@@ -2010,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"切換分割畫面模式"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"螢幕鎖定"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"擷取螢幕畫面"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」的說明文字列。"</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"已將「<xliff:g id="PACKAGE_NAME">%1$s</xliff:g>」移入受限制的值區"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index d736562..1cb67e1 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -194,6 +194,10 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"Idivayisi yakho izosulwa"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Uhlelo lokusebenza lomlawuli alikwazi ukusetshenziswa. Idivayisi yakho manje izosuswa.\n\nUma unemibuzo, xhumana nomlawuli wezinhlangano zakho."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Ukuphrinta kukhutshazwe nge-<xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+    <!-- no translation found for personal_apps_suspended_notification_title (6551578720258229430) -->
+    <skip />
+    <!-- no translation found for personal_apps_suspended_notification_text (8321053338614244297) -->
+    <skip />
     <string name="me" msgid="6207584824693813140">"Mina"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Okukhethwa kukho kwethebhulethi"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Izinketho ze-Android TV"</string>
@@ -1609,10 +1613,11 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Ukulayisha ungenisa iphathini yakho yokuvula ngendlela engalungile izikhathi ezi-<xliff:g id="NUMBER_0">%1$d</xliff:g> Emva kweminye imizamo engu-<xliff:g id="NUMBER_1">%2$d</xliff:g>, uzocelwa ukuvula ifoni yakho usebenzisa ukungena ngemvume ku-Google\n\n Zame futhi emumva kwengu- <xliff:g id="NUMBER_2">%3$d</xliff:g> amasekhondi."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Susa"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Khuphukisa ivolumu ngaphezu kweleveli enconyiwe?\n\nUkulalela ngevolumu ephezulu izikhathi ezide kungahle kulimaze ukuzwa kwakho."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Sebenzisa isinqamuleli sokufinyelela?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Uma kuvulwe isinqamuleli, ukucindezela zombili izinkinobho zevolumu amasekhondi angu-3 kuzoqala isici sokufinyelela.\n\n Isici samanje sokufinyelela:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Ungashintsha isici kuzilungiselelo &gt; Ukufinyelela."</string>
-    <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Akunalutho"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Hlela izinqamuleli"</string>
     <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Khansela"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Vala isinqamuleli"</string>
@@ -1847,11 +1852,11 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Uhlelo lokusebenza alutholakali"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"I-<xliff:g id="APP_NAME_0">%1$s</xliff:g> ayitholakali okwamanje. Lokhu kuphethwe i-<xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Funda kabanzi"</string>
+    <!-- no translation found for app_suspended_unsuspend_message (1665438589450555459) -->
+    <skip />
     <string name="work_mode_off_title" msgid="5503291976647976560">"Vula iphrofayela yomsebenzi?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Izinhlelo zakho zokusebenza zomsebenzi, izaziso, idatha, nezinye izici zephrofayela yomsebenzi kuzovulwa"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Vula"</string>
-    <string name="app_blocked_title" msgid="7353262160455028160">"Uhlelo lokusebenza alutholakali"</string>
-    <string name="app_blocked_message" msgid="542972921087873023">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> ayitholakali khona manje."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Lolu hlelo lokusebenza belakhelwe inguqulo endala ye-Android futhi kungenzeka lungasebenzi kahle. Zama ukuhlolela izibuyekezo, noma uxhumane nonjiniyela."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Hlola izibuyekezo"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Unemilayezo emisha"</string>
@@ -1984,6 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> isipredishithi"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Iphrezentheshini"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> iphrezentheshini"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"I-Bluetooth izohlala ivuliwe ngesikhathi semodi yendiza"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Iyalayisha"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> amafayela</item>
@@ -2001,5 +2007,12 @@
     <string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Guqula ukuhlukanisa isikrini"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Khiya isikrini"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Isithombe-skrini"</string>
+    <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
+    <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Ibha yamazwibela we-<xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"I-<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> ifakwe kubhakede LOKUKHAWULELWE"</string>
+    <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
+    <skip />
+    <!-- no translation found for resolver_work_tab (2690019516263167035) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index 8f2d6c3..deb6afc 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -165,7 +165,7 @@
         <item>中文 (繁體)</item>
     </string-array>
 
-    <array name="sim_colors">
+    <array name="simColors">
         <item>@color/Teal_700</item>
         <item>@color/Blue_700</item>
         <item>@color/Indigo_700</item>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 940e9f1..20901e0 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3714,6 +3714,10 @@
             <flag name="flagRequestFingerprintGestures" value="0x00000200" />
             <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK}. -->
             <flag name="flagRequestShortcutWarningDialogSpokenFeedback" value="0x00000400" />
+            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_SERVICE_HANDLES_DOUBLE_TAP}. -->
+            <flag name="flagServiceHandlesDoubleTap" value="0x00000800" />
+            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_MULTI_FINGER_GESTURES}. -->
+            <flag name="flagRequestMultiFingerGestures" value="0x00001000" />
         </attr>
         <!-- Component name of an activity that allows the user to modify
              the settings for this service. This setting cannot be changed at runtime. -->
@@ -9197,4 +9201,12 @@
     </declare-styleable>
 
     <attr name="autoSizePresetSizes" />
+
+    <declare-styleable name="AutofillInlineSuggestion">
+        <!-- @hide @SystemApi -->
+        <attr name="isAutofillInlineSuggestionTheme" format="boolean" />
+        <attr name="autofillInlineSuggestionChip" format="reference" />
+        <attr name="autofillInlineSuggestionTitle" format="reference" />
+        <attr name="autofillInlineSuggestionSubtitle" format="reference" />
+    </declare-styleable>
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 42127e7..dadb9241 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2685,6 +2685,11 @@
     <!-- The amount to scale fullscreen snapshots for Overview and snapshot starting windows. -->
     <item name="config_fullTaskSnapshotScale" format="float" type="dimen">1.0</item>
 
+    <!-- The amount to scale reduced scale snapshots for Overview and snapshot starting windows.
+         Reduced scale snapshots are loaded before full screen snapshots to improve load times and
+         minimize the chance the user will see an empty task card. -->
+    <item name="config_reducedTaskSnapshotScale" format="float" type="dimen">0.5</item>
+
     <!-- Feature flag to store TaskSnapshot in 16 bit pixel format to save memory. -->
     <bool name="config_use16BitTaskSnapshotPixelFormat">false</bool>
 
@@ -4173,7 +4178,7 @@
          where: IDs are unique per device, Modality as defined in BiometricAuthenticator.java,
          and Strength as defined in Authenticators.java -->
     <string-array name="config_biometric_sensors" translatable="false" >
-        <item>0:2:15</item> <!-- ID0:Fingerprint:Strong -->
+        <!-- <item>0:2:15</item>  ID0:Fingerprint:Strong -->
     </string-array>
 
     <!-- Messages that should not be shown to the user during face auth enrollment. This should be
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 36dbcbd..4f61730a 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3012,12 +3012,18 @@
       <public name="sdkVersion" />
       <!-- @hide @SystemApi -->
       <public name="minExtensionVersion" />
+      <public name="autofillInlineSuggestionChip" />
+      <public name="autofillInlineSuggestionTitle" />
+      <public name="autofillInlineSuggestionSubtitle" />
+      <!-- @hide @SystemApi -->
+      <public name="isAutofillInlineSuggestionTheme" />
     </public-group>
 
     <public-group type="drawable" first-id="0x010800b5">
     </public-group>
 
     <public-group type="style" first-id="0x010302e5">
+      <public name="Theme.AutofillInlineSuggestion" />
     </public-group>
 
     <public-group type="id" first-id="0x0102004a">
@@ -3037,6 +3043,8 @@
       <public name="config_defaultCallScreening" />
       <!-- @hide @SystemApi @TestApi -->
       <public name="config_systemGallery" />
+      <!-- @hide @SystemApi -->
+      <public name="low_memory" />
     </public-group>
 
     <public-group type="bool" first-id="0x01110005">
@@ -3059,6 +3067,18 @@
       <public name="accessibilitySystemActionLockScreen" />
       <public name="accessibilitySystemActionTakeScreenshot" />
     </public-group>
+
+    <public-group type="array" first-id="0x01070006">
+      <!-- @hide @SystemApi -->
+      <public name="simColors" />
+      <!-- @hide @SystemApi -->
+      <public name="config_restrictedPreinstalledCarrierApps" />
+      <!-- @hide @SystemApi -->
+      <public name="config_sms_enabled_single_shift_tables" />
+      <!-- @hide @SystemApi -->
+      <public name="config_sms_enabled_locking_shift_tables" />
+    </public-group>
+
   <!-- ===============================================================
        DO NOT ADD UN-GROUPED ITEMS HERE
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index be2b678..11cc365 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4345,6 +4345,9 @@
     <!-- The delete-widget drop target button text -->
     <string name="kg_reordering_delete_drop_target_text">Remove</string>
 
+    <!-- Toast message for background started foreground service while-in-use permission restriction feature -->
+    <string name="allow_while_in_use_permission_in_fgs">The background started foreground service from <xliff:g id="packageName" example="com.example">%1$s</xliff:g> will not have while-in-use permission in future R builds. Please see go/r-bg-fgs-restriction and file a bugreport.</string>
+
     <!-- Message shown in dialog when user is attempting to set the music volume above the
     recommended maximum level for headphones -->
     <string name="safe_media_volume_warning" product="default">
@@ -4923,6 +4926,8 @@
     </string>
     <!-- Title of the button to show users more details about why the app has been suspended [CHAR LIMIT=50]-->
     <string name="app_suspended_more_details">Learn more</string>
+    <!-- Title of the button to unsuspend a suspended app immediately [CHAR LIMIT=50]-->
+    <string name="app_suspended_unsuspend_message">Unpause app</string>
 
     <!-- Title of a dialog. The string is asking if the user wants to turn on their work profile, which contains work apps that are managed by their employer. "Work" is an adjective. [CHAR LIMIT=30] -->
     <string name="work_mode_off_title">Turn on work profile?</string>
@@ -4931,13 +4936,6 @@
     <!-- Title for button to turn on work profile. [CHAR LIMIT=NONE] -->
     <string name="work_mode_turn_on">Turn on</string>
 
-    <!-- Title of the dialog that is shown when the user tries to launch a suspended application [CHAR LIMIT=50] -->
-    <string name="app_blocked_title">App is not available</string>
-    <!-- Default message shown in the dialog that is shown when the user tries to launch a suspended application [CHAR LIMIT=NONE] -->
-    <string name="app_blocked_message">
-        <xliff:g id="app_name" example="Gmail">%1$s</xliff:g> is not available right now.
-    </string>
-
     <!-- Message displayed in dialog when app is too old to run on this verison of android. [CHAR LIMIT=NONE] -->
     <string name="deprecated_target_sdk_message">This app was built for an older version of Android and may not work properly. Try checking for updates, or contact the developer.</string>
     <!-- Title for button to see application detail in app store which it came from - it may allow user to update to newer version. [CHAR LIMIT=50] -->
@@ -5318,7 +5316,8 @@
     <string name="accessibility_system_action_lock_screen_label">Lock Screen</string>
     <!-- Label for taking screenshot action [CHAR LIMIT=NONE] -->
     <string name="accessibility_system_action_screenshot_label">Screenshot</string>
-
+    <!-- Label for showing accessibility menu action [CHAR LIMIT=NONE] -->
+    <string name="accessibility_system_action_accessibility_menu_label">Accessibility Menu</string>
     <!-- Accessibility description of caption view -->
     <string name="accessibility_freeform_caption">Caption bar of <xliff:g id="app_name">%1$s</xliff:g>.</string>
 
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index bcce1f0..751eca0 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1482,6 +1482,22 @@
         <item name="android:windowExitAnimation">@anim/slide_out_down</item>
     </style>
 
+    <!-- The style for the Autofill inline suggestion chip. -->
+    <!-- @hide -->
+    <style name="AutofillInlineSuggestionChip">
+        <item name="background">@drawable/autofill_dataset_picker_background</item>
+    </style>
+
+    <!-- @hide -->
+    <style name="AutofillInlineSuggestionTitle">
+        <item name="android:textAppearance">@style/TextAppearance</item>
+    </style>
+
+    <!-- @hide -->
+    <style name="AutofillInlineSuggestionSubtitle">
+        <item name="android:textAppearance">@style/TextAppearance.Small</item>
+    </style>
+
     <!-- The style for the container of media actions in a notification. -->
     <!-- @hide -->
     <style name="NotificationMediaActionContainer">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ea8ca9a..d238485 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -360,6 +360,7 @@
   <java-symbol type="bool" name="config_enableNewAutoSelectNetworkUI"/>
   <java-symbol type="bool" name="config_disableUsbPermissionDialogs"/>
   <java-symbol type="dimen" name="config_fullTaskSnapshotScale" />
+  <java-symbol type="dimen" name="config_reducedTaskSnapshotScale" />
   <java-symbol type="bool" name="config_use16BitTaskSnapshotPixelFormat" />
   <java-symbol type="bool" name="config_hasRecents" />
   <java-symbol type="string" name="config_recentsComponentName" />
@@ -1240,7 +1241,7 @@
   <java-symbol type="array" name="preloaded_color_state_lists" />
   <java-symbol type="array" name="preloaded_drawables" />
   <java-symbol type="array" name="preloaded_freeform_multi_window_drawables" />
-  <java-symbol type="array" name="sim_colors" />
+  <java-symbol type="array" name="simColors" />
   <java-symbol type="array" name="special_locale_codes" />
   <java-symbol type="array" name="special_locale_names" />
   <java-symbol type="array" name="supported_locales" />
@@ -3038,11 +3039,9 @@
 
   <java-symbol type="string" name="app_suspended_title" />
   <java-symbol type="string" name="app_suspended_more_details" />
+  <java-symbol type="string" name="app_suspended_unsuspend_message" />
   <java-symbol type="string" name="app_suspended_default_message" />
 
-  <java-symbol type="string" name="app_blocked_title" />
-  <java-symbol type="string" name="app_blocked_message" />
-
   <!-- Used internally for assistant to launch activity transitions -->
   <java-symbol type="id" name="cross_task_transition" />
 
@@ -3803,6 +3802,7 @@
   <java-symbol type="string" name="accessibility_system_action_recents_label" />
   <java-symbol type="string" name="accessibility_system_action_screenshot_label" />
   <java-symbol type="string" name="accessibility_system_action_toggle_split_screen_label" />
+  <java-symbol type="string" name="accessibility_system_action_accessibility_menu_label" />
 
   <java-symbol type="string" name="accessibility_freeform_caption" />
 
@@ -3847,4 +3847,6 @@
   <java-symbol type="string" name="resolver_work_tab" />
   <java-symbol type="id" name="stub" />
 
+  <!-- Toast message for background started foreground service while-in-use permission restriction feature -->
+  <java-symbol type="string" name="allow_while_in_use_permission_in_fgs" />
 </resources>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index ad38f3d..5e6dd82 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -893,4 +893,11 @@
         <item name="windowActivityTransitions">false</item>
     </style>
 
+    <!-- Theme for the Autofill inline suggestion on IME -->
+    <style name="Theme.AutofillInlineSuggestion" parent="Theme.DeviceDefault">
+        <item name="isAutofillInlineSuggestionTheme">true</item>
+        <item name="autofillInlineSuggestionChip">@style/AutofillInlineSuggestionChip</item>
+        <item name="autofillInlineSuggestionTitle">@style/AutofillInlineSuggestionTitle</item>
+        <item name="autofillInlineSuggestionSubtitle">@style/AutofillInlineSuggestionSubtitle</item>
+    </style>
 </resources>
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index 3836d6f..38454ec 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -41,6 +41,7 @@
         "truth-prebuilt",
         "print-test-util-lib",
         "testng",
+        "servicestests-utils"
     ],
 
     libs: [
diff --git a/core/tests/coretests/src/android/app/PullAtomMetadataTest.java b/core/tests/coretests/src/android/app/PullAtomMetadataTest.java
index 2e3f892..0ae6134 100644
--- a/core/tests/coretests/src/android/app/PullAtomMetadataTest.java
+++ b/core/tests/coretests/src/android/app/PullAtomMetadataTest.java
@@ -32,7 +32,7 @@
 
     @Test
     public void testEmpty() {
-        PullAtomMetadata metadata = PullAtomMetadata.newBuilder().build();
+        PullAtomMetadata metadata = new PullAtomMetadata.Builder().build();
         assertThat(metadata.getTimeoutNs()).isEqualTo(StatsManager.DEFAULT_TIMEOUT_NS);
         assertThat(metadata.getCoolDownNs()).isEqualTo(StatsManager.DEFAULT_COOL_DOWN_NS);
         assertThat(metadata.getAdditiveFields()).isNull();
@@ -42,7 +42,7 @@
     public void testSetTimeoutNs() {
         long timeoutNs = 500_000_000L;
         PullAtomMetadata metadata =
-                PullAtomMetadata.newBuilder().setTimeoutNs(timeoutNs).build();
+                new PullAtomMetadata.Builder().setTimeoutNs(timeoutNs).build();
         assertThat(metadata.getTimeoutNs()).isEqualTo(timeoutNs);
         assertThat(metadata.getCoolDownNs()).isEqualTo(StatsManager.DEFAULT_COOL_DOWN_NS);
         assertThat(metadata.getAdditiveFields()).isNull();
@@ -52,7 +52,7 @@
     public void testSetCoolDownNs() {
         long coolDownNs = 10_000_000_000L;
         PullAtomMetadata metadata =
-                PullAtomMetadata.newBuilder().setCoolDownNs(coolDownNs).build();
+                new PullAtomMetadata.Builder().setCoolDownNs(coolDownNs).build();
         assertThat(metadata.getTimeoutNs()).isEqualTo(StatsManager.DEFAULT_TIMEOUT_NS);
         assertThat(metadata.getCoolDownNs()).isEqualTo(coolDownNs);
         assertThat(metadata.getAdditiveFields()).isNull();
@@ -62,7 +62,7 @@
     public void testSetAdditiveFields() {
         int[] fields = {2, 4, 6};
         PullAtomMetadata metadata =
-                PullAtomMetadata.newBuilder().setAdditiveFields(fields).build();
+                new PullAtomMetadata.Builder().setAdditiveFields(fields).build();
         assertThat(metadata.getTimeoutNs()).isEqualTo(StatsManager.DEFAULT_TIMEOUT_NS);
         assertThat(metadata.getCoolDownNs()).isEqualTo(StatsManager.DEFAULT_COOL_DOWN_NS);
         assertThat(metadata.getAdditiveFields()).isEqualTo(fields);
@@ -73,7 +73,7 @@
         long timeoutNs = 300L;
         long coolDownNs = 9572L;
         int[] fields = {3, 2};
-        PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
                 .setTimeoutNs(timeoutNs)
                 .setCoolDownNs(coolDownNs)
                 .setAdditiveFields(fields)
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index d8b527c..c986db8 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -96,16 +96,6 @@
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
     }
 
-    @Test
-    public void testSleepAndStop() throws Exception {
-        final Activity activity = mActivityTestRule.launchActivity(new Intent());
-        final IApplicationThread appThread = activity.getActivityThread().getApplicationThread();
-
-        appThread.scheduleSleeping(activity.getActivityToken(), true /* sleeping */);
-        appThread.scheduleTransaction(newStopTransaction(activity));
-        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
-    }
-
     /** Verify that repeated resume requests to activity will be ignored. */
     @Test
     public void testRepeatedResume() throws Exception {
diff --git a/core/tests/coretests/src/android/app/appsearch/AppSearchDocumentTest.java b/core/tests/coretests/src/android/app/appsearch/AppSearchDocumentTest.java
index abba7fc..4a4f1367 100644
--- a/core/tests/coretests/src/android/app/appsearch/AppSearchDocumentTest.java
+++ b/core/tests/coretests/src/android/app/appsearch/AppSearchDocumentTest.java
@@ -20,12 +20,11 @@
 
 import static org.testng.Assert.assertThrows;
 
-import android.app.appsearch.AppSearch.Document;
-
 import androidx.test.filters.SmallTest;
 
 import com.google.android.icing.proto.DocumentProto;
 import com.google.android.icing.proto.PropertyProto;
+import com.google.android.icing.protobuf.ByteString;
 
 import org.junit.Test;
 
@@ -36,22 +35,36 @@
 
 @SmallTest
 public class AppSearchDocumentTest {
+    private static final byte[] sByteArray1 = new byte[]{(byte) 1, (byte) 2, (byte) 3};
+    private static final byte[] sByteArray2 = new byte[]{(byte) 4, (byte) 5, (byte) 6};
+    private static final AppSearchDocument sDocumentProperties1 = new AppSearchDocument
+            .Builder("sDocumentProperties1", "sDocumentPropertiesSchemaType1")
+            .build();
+    private static final AppSearchDocument sDocumentProperties2 = new AppSearchDocument
+            .Builder("sDocumentProperties2", "sDocumentPropertiesSchemaType2")
+            .build();
 
     @Test
     public void testDocumentEquals_Identical() {
-        Document document1 = Document.newBuilder("uri1", "schemaType1")
+        AppSearchDocument document1 = new AppSearchDocument.Builder("uri1", "schemaType1")
                 .setCreationTimestampMillis(5L)
+                .setTtlMillis(1L)
                 .setProperty("longKey1", 1L, 2L, 3L)
                 .setProperty("doubleKey1", 1.0, 2.0, 3.0)
                 .setProperty("booleanKey1", true, false, true)
                 .setProperty("stringKey1", "test-value1", "test-value2", "test-value3")
+                .setProperty("byteKey1", sByteArray1, sByteArray2)
+                .setProperty("documentKey1", sDocumentProperties1, sDocumentProperties2)
                 .build();
-        Document document2 = Document.newBuilder("uri1", "schemaType1")
+        AppSearchDocument document2 = new AppSearchDocument.Builder("uri1", "schemaType1")
                 .setCreationTimestampMillis(5L)
+                .setTtlMillis(1L)
                 .setProperty("longKey1", 1L, 2L, 3L)
                 .setProperty("doubleKey1", 1.0, 2.0, 3.0)
                 .setProperty("booleanKey1", true, false, true)
                 .setProperty("stringKey1", "test-value1", "test-value2", "test-value3")
+                .setProperty("byteKey1", sByteArray1, sByteArray2)
+                .setProperty("documentKey1", sDocumentProperties1, sDocumentProperties2)
                 .build();
         assertThat(document1).isEqualTo(document2);
         assertThat(document1.hashCode()).isEqualTo(document2.hashCode());
@@ -59,20 +72,24 @@
 
     @Test
     public void testDocumentEquals_DifferentOrder() {
-        Document document1 = Document.newBuilder("uri1", "schemaType1")
+        AppSearchDocument document1 = new AppSearchDocument.Builder("uri1", "schemaType1")
                 .setCreationTimestampMillis(5L)
                 .setProperty("longKey1", 1L, 2L, 3L)
+                .setProperty("byteKey1", sByteArray1, sByteArray2)
                 .setProperty("doubleKey1", 1.0, 2.0, 3.0)
                 .setProperty("booleanKey1", true, false, true)
+                .setProperty("documentKey1", sDocumentProperties1, sDocumentProperties2)
                 .setProperty("stringKey1", "test-value1", "test-value2", "test-value3")
                 .build();
 
         // Create second document with same parameter but different order.
-        Document document2 = Document.newBuilder("uri1", "schemaType1")
+        AppSearchDocument document2 = new AppSearchDocument.Builder("uri1", "schemaType1")
                 .setCreationTimestampMillis(5L)
                 .setProperty("booleanKey1", true, false, true)
+                .setProperty("documentKey1", sDocumentProperties1, sDocumentProperties2)
                 .setProperty("stringKey1", "test-value1", "test-value2", "test-value3")
                 .setProperty("doubleKey1", 1.0, 2.0, 3.0)
+                .setProperty("byteKey1", sByteArray1, sByteArray2)
                 .setProperty("longKey1", 1L, 2L, 3L)
                 .build();
         assertThat(document1).isEqualTo(document2);
@@ -81,13 +98,13 @@
 
     @Test
     public void testDocumentEquals_Failure() {
-        Document document1 = Document.newBuilder("uri1", "schemaType1")
+        AppSearchDocument document1 = new AppSearchDocument.Builder("uri1", "schemaType1")
                 .setCreationTimestampMillis(5L)
                 .setProperty("longKey1", 1L, 2L, 3L)
                 .build();
 
         // Create second document with same order but different value.
-        Document document2 = Document.newBuilder("uri1", "schemaType1")
+        AppSearchDocument document2 = new AppSearchDocument.Builder("uri1", "schemaType1")
                 .setCreationTimestampMillis(5L)
                 .setProperty("longKey1", 1L, 2L, 4L) // Different
                 .build();
@@ -97,13 +114,13 @@
 
     @Test
     public void testDocumentEquals_Failure_RepeatedFieldOrder() {
-        Document document1 = Document.newBuilder("uri1", "schemaType1")
+        AppSearchDocument document1 = new AppSearchDocument.Builder("uri1", "schemaType1")
                 .setCreationTimestampMillis(5L)
                 .setProperty("booleanKey1", true, false, true)
                 .build();
 
         // Create second document with same order but different value.
-        Document document2 = Document.newBuilder("uri1", "schemaType1")
+        AppSearchDocument document2 = new AppSearchDocument.Builder("uri1", "schemaType1")
                 .setCreationTimestampMillis(5L)
                 .setProperty("booleanKey1", true, true, false) // Different
                 .build();
@@ -113,14 +130,19 @@
 
     @Test
     public void testDocumentGetSingleValue() {
-        Document document = Document.newBuilder("uri1", "schemaType1")
+        AppSearchDocument document = new AppSearchDocument.Builder("uri1", "schemaType1")
                 .setCreationTimestampMillis(5L)
                 .setScore(1)
+                .setTtlMillis(1L)
                 .setProperty("longKey1", 1L)
                 .setProperty("doubleKey1", 1.0)
                 .setProperty("booleanKey1", true)
-                .setProperty("stringKey1", "test-value1").build();
+                .setProperty("stringKey1", "test-value1")
+                .setProperty("byteKey1", sByteArray1)
+                .setProperty("documentKey1", sDocumentProperties1)
+                .build();
         assertThat(document.getUri()).isEqualTo("uri1");
+        assertThat(document.getTtlMillis()).isEqualTo(1L);
         assertThat(document.getSchemaType()).isEqualTo("schemaType1");
         assertThat(document.getCreationTimestampMillis()).isEqualTo(5);
         assertThat(document.getScore()).isEqualTo(1);
@@ -128,16 +150,21 @@
         assertThat(document.getPropertyDouble("doubleKey1")).isEqualTo(1.0);
         assertThat(document.getPropertyBoolean("booleanKey1")).isTrue();
         assertThat(document.getPropertyString("stringKey1")).isEqualTo("test-value1");
+        assertThat(document.getPropertyBytes("byteKey1"))
+                .asList().containsExactly((byte) 1, (byte) 2, (byte) 3);
+        assertThat(document.getPropertyDocument("documentKey1")).isEqualTo(sDocumentProperties1);
     }
 
     @Test
     public void testDocumentGetArrayValues() {
-        Document document = Document.newBuilder("uri1", "schemaType1")
+        AppSearchDocument document = new AppSearchDocument.Builder("uri1", "schemaType1")
                 .setCreationTimestampMillis(5L)
                 .setProperty("longKey1", 1L, 2L, 3L)
                 .setProperty("doubleKey1", 1.0, 2.0, 3.0)
                 .setProperty("booleanKey1", true, false, true)
                 .setProperty("stringKey1", "test-value1", "test-value2", "test-value3")
+                .setProperty("byteKey1", sByteArray1, sByteArray2)
+                .setProperty("documentKey1", sDocumentProperties1, sDocumentProperties2)
                 .build();
 
         assertThat(document.getUri()).isEqualTo("uri1");
@@ -149,11 +176,15 @@
                 .containsExactly(true, false, true);
         assertThat(document.getPropertyStringArray("stringKey1")).asList()
                 .containsExactly("test-value1", "test-value2", "test-value3");
+        assertThat(document.getPropertyBytesArray("byteKey1")).asList()
+                .containsExactly(sByteArray1, sByteArray2);
+        assertThat(document.getPropertyDocumentArray("documentKey1")).asList()
+                .containsExactly(sDocumentProperties1, sDocumentProperties2);
     }
 
     @Test
     public void testDocumentGetValues_DifferentTypes() {
-        Document document = Document.newBuilder("uri1", "schemaType1")
+        AppSearchDocument document = new AppSearchDocument.Builder("uri1", "schemaType1")
                 .setScore(1)
                 .setProperty("longKey1", 1L)
                 .setProperty("booleanKey1", true, false, true)
@@ -180,25 +211,32 @@
 
     @Test
     public void testDocumentInvalid() {
-        Document.Builder builder = Document.newBuilder("uri1", "schemaType1");
+        AppSearchDocument.Builder builder = new AppSearchDocument.Builder("uri1", "schemaType1");
         assertThrows(
                 IllegalArgumentException.class, () -> builder.setProperty("test", new boolean[]{}));
     }
 
     @Test
     public void testDocumentProtoPopulation() {
-        Document document = Document.newBuilder("uri1", "schemaType1")
+        AppSearchDocument document = new AppSearchDocument.Builder("uri1", "schemaType1")
                 .setCreationTimestampMillis(5L)
                 .setScore(1)
+                .setTtlMillis(1L)
                 .setProperty("longKey1", 1L)
                 .setProperty("doubleKey1", 1.0)
                 .setProperty("booleanKey1", true)
                 .setProperty("stringKey1", "test-value1")
+                .setProperty("byteKey1", sByteArray1)
+                .setProperty("documentKey1", sDocumentProperties1)
                 .build();
 
         // Create the Document proto. Need to sort the property order by key.
         DocumentProto.Builder documentProtoBuilder = DocumentProto.newBuilder()
-                .setUri("uri1").setSchema("schemaType1").setScore(1).setCreationTimestampMs(5L);
+                .setUri("uri1")
+                .setSchema("schemaType1")
+                .setCreationTimestampMs(5L)
+                .setScore(1)
+                .setTtlMs(1L);
         HashMap<String, PropertyProto.Builder> propertyProtoMap = new HashMap<>();
         propertyProtoMap.put("longKey1",
                 PropertyProto.newBuilder().setName("longKey1").addInt64Values(1L));
@@ -208,6 +246,12 @@
                 PropertyProto.newBuilder().setName("booleanKey1").addBooleanValues(true));
         propertyProtoMap.put("stringKey1",
                 PropertyProto.newBuilder().setName("stringKey1").addStringValues("test-value1"));
+        propertyProtoMap.put("byteKey1",
+                PropertyProto.newBuilder().setName("byteKey1").addBytesValues(
+                        ByteString.copyFrom(sByteArray1)));
+        propertyProtoMap.put("documentKey1",
+                PropertyProto.newBuilder().setName("documentKey1")
+                        .addDocumentValues(sDocumentProperties1.getProto()));
         List<String> sortedKey = new ArrayList<>(propertyProtoMap.keySet());
         Collections.sort(sortedKey);
         for (String key : sortedKey) {
diff --git a/core/tests/coretests/src/android/app/appsearch/AppSearchEmailTest.java b/core/tests/coretests/src/android/app/appsearch/AppSearchEmailTest.java
index c50b1da..6aa16cc 100644
--- a/core/tests/coretests/src/android/app/appsearch/AppSearchEmailTest.java
+++ b/core/tests/coretests/src/android/app/appsearch/AppSearchEmailTest.java
@@ -18,8 +18,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import android.app.appsearch.AppSearch.Email;
-
 import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
@@ -29,7 +27,7 @@
 
     @Test
     public void testBuildEmailAndGetValue() {
-        Email email = Email.newBuilder("uri")
+        AppSearchEmail email = new AppSearchEmail.Builder("uri")
                 .setFrom("FakeFromAddress")
                 .setCc("CC1", "CC2")
                 // Score and Property are mixed into the middle to make sure DocumentBuilder's
diff --git a/core/tests/coretests/src/android/app/appsearch/impl/CustomerDocumentTest.java b/core/tests/coretests/src/android/app/appsearch/impl/CustomerDocumentTest.java
index c5986bb..b29483c 100644
--- a/core/tests/coretests/src/android/app/appsearch/impl/CustomerDocumentTest.java
+++ b/core/tests/coretests/src/android/app/appsearch/impl/CustomerDocumentTest.java
@@ -19,28 +19,42 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.annotation.NonNull;
-import android.app.appsearch.AppSearch.Document;
+import android.app.appsearch.AppSearchDocument;
 
 import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
 
-/** Tests that {@link Document} and {@link Document.Builder} are extendable by developers.
+/**
+ * Tests that {@link AppSearchDocument} and {@link AppSearchDocument.Builder} are extendable by
+ * developers.
  *
- * <p>This class is intentionally in a different package than {@link Document} to make sure there
- * are no package-private methods required for external developers to add custom types.
+ * <p>This class is intentionally in a different package than {@link AppSearchDocument} to make sure
+ * there are no package-private methods required for external developers to add custom types.
  */
 @SmallTest
 public class CustomerDocumentTest {
+
+    private static byte[] sByteArray1 = new byte[]{(byte) 1, (byte) 2, (byte) 3};
+    private static byte[] sByteArray2 = new byte[]{(byte) 4, (byte) 5, (byte) 6};
+    private static AppSearchDocument sDocumentProperties1 = new AppSearchDocument
+            .Builder("sDocumentProperties1", "sDocumentPropertiesSchemaType1")
+            .build();
+    private static AppSearchDocument sDocumentProperties2 = new AppSearchDocument
+            .Builder("sDocumentProperties2", "sDocumentPropertiesSchemaType2")
+            .build();
+
     @Test
     public void testBuildCustomerDocument() {
-        CustomerDocument customerDocument = CustomerDocument.newBuilder("uri1")
+        CustomerDocument customerDocument = new CustomerDocument.Builder("uri1")
                 .setScore(1)
                 .setCreationTimestampMillis(0)
                 .setProperty("longKey1", 1L, 2L, 3L)
                 .setProperty("doubleKey1", 1.0, 2.0, 3.0)
                 .setProperty("booleanKey1", true, false, true)
                 .setProperty("stringKey1", "test-value1", "test-value2", "test-value3")
+                .setProperty("byteKey1", sByteArray1, sByteArray2)
+                .setProperty("documentKey1", sDocumentProperties1, sDocumentProperties2)
                 .build();
 
         assertThat(customerDocument.getUri()).isEqualTo("uri1");
@@ -55,22 +69,22 @@
                 .containsExactly(true, false, true);
         assertThat(customerDocument.getPropertyStringArray("stringKey1")).asList()
                 .containsExactly("test-value1", "test-value2", "test-value3");
+        assertThat(customerDocument.getPropertyBytesArray("byteKey1")).asList()
+                .containsExactly(sByteArray1, sByteArray2);
+        assertThat(customerDocument.getPropertyDocumentArray("documentKey1")).asList()
+                .containsExactly(sDocumentProperties1, sDocumentProperties2);
     }
 
     /**
      * An example document type for test purposes, defined outside of
      * {@link android.app.appsearch.AppSearch} (the way an external developer would define it).
      */
-    private static class CustomerDocument extends Document {
-        private CustomerDocument(Document document) {
+    private static class CustomerDocument extends AppSearchDocument {
+        private CustomerDocument(AppSearchDocument document) {
             super(document);
         }
 
-        public static CustomerDocument.Builder newBuilder(String uri) {
-            return new CustomerDocument.Builder(uri);
-        }
-
-        public static class Builder extends Document.Builder<CustomerDocument.Builder> {
+        public static class Builder extends AppSearchDocument.Builder<CustomerDocument.Builder> {
             private Builder(@NonNull String uri) {
                 super(uri, "customerDocument");
             }
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
index ecea901..372b8c2 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
@@ -448,10 +448,6 @@
         }
 
         @Override
-        public void scheduleSleeping(IBinder iBinder, boolean b) throws RemoteException {
-        }
-
-        @Override
         public void profilerControl(boolean b, ProfilerInfo profilerInfo, int i)
                 throws RemoteException {
         }
diff --git a/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java b/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java
index e48f1c3..7328f35 100644
--- a/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java
+++ b/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java
@@ -16,14 +16,11 @@
 
 package android.content.integrity;
 
-import static android.content.integrity.TestUtils.assertExpectException;
+import static com.google.common.truth.Truth.assertThat;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.testng.Assert.expectThrows;
 
 import android.content.integrity.AtomicFormula.BooleanAtomicFormula;
-import android.content.integrity.AtomicFormula.IntAtomicFormula;
 import android.content.integrity.AtomicFormula.StringAtomicFormula;
 import android.os.Parcel;
 
@@ -36,19 +33,93 @@
 
     @Test
     public void testValidAtomicFormula_stringValue() {
+        String packageName = "com.test.app";
         StringAtomicFormula stringAtomicFormula =
                 new StringAtomicFormula(
-                        AtomicFormula.PACKAGE_NAME, "com.test.app", /* isHashedValue= */ false);
+                        AtomicFormula.PACKAGE_NAME, packageName, /* isHashedValue= */false);
 
-        assertEquals(AtomicFormula.PACKAGE_NAME, stringAtomicFormula.getKey());
+        assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.PACKAGE_NAME);
+        assertThat(stringAtomicFormula.getValue()).isEqualTo(packageName);
+        assertThat(stringAtomicFormula.getIsHashedValue()).isFalse();
     }
 
     @Test
-    public void testValidAtomicFormula_intValue() {
-        IntAtomicFormula intAtomicFormula =
-                new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.LE, 1);
+    public void testValidAtomicFormula_stringValue_autoHash_packageNameLessThanLimit() {
+        String packageName = "com.test.app";
+        StringAtomicFormula stringAtomicFormula =
+                new StringAtomicFormula(AtomicFormula.PACKAGE_NAME, packageName);
 
-        assertEquals(AtomicFormula.VERSION_CODE, intAtomicFormula.getKey());
+        assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.PACKAGE_NAME);
+        assertThat(stringAtomicFormula.getValue()).isEqualTo(packageName);
+        assertThat(stringAtomicFormula.getIsHashedValue()).isFalse();
+    }
+
+    @Test
+    public void testValidAtomicFormula_stringValue_autoHash_longPackageName() {
+        String packageName = "com.test.app.test.app.test.app.test.app.test.app";
+        StringAtomicFormula stringAtomicFormula =
+                new StringAtomicFormula(AtomicFormula.PACKAGE_NAME, packageName);
+
+        assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.PACKAGE_NAME);
+        assertThat(stringAtomicFormula.getValue()).doesNotMatch(packageName);
+        assertThat(stringAtomicFormula.getIsHashedValue()).isTrue();
+    }
+
+    @Test
+    public void testValidAtomicFormula_stringValue_autoHash_installerNameLessThanLimit() {
+        String installerName = "com.test.app";
+        StringAtomicFormula stringAtomicFormula =
+                new StringAtomicFormula(AtomicFormula.INSTALLER_NAME, installerName);
+
+
+        assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.INSTALLER_NAME);
+        assertThat(stringAtomicFormula.getValue()).isEqualTo(installerName);
+        assertThat(stringAtomicFormula.getIsHashedValue()).isFalse();
+    }
+
+    @Test
+    public void testValidAtomicFormula_stringValue_autoHash_longInstallerName() {
+        String installerName = "com.test.app.test.app.test.app.test.app.test.app";
+        StringAtomicFormula stringAtomicFormula =
+                new StringAtomicFormula(AtomicFormula.INSTALLER_NAME, installerName);
+
+        assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.INSTALLER_NAME);
+        assertThat(stringAtomicFormula.getValue()).doesNotMatch(installerName);
+        assertThat(stringAtomicFormula.getIsHashedValue()).isTrue();
+    }
+
+    @Test
+    public void testValidAtomicFormula_stringValue_appCertificateAutoHashed() {
+        String appCert = "cert";
+        StringAtomicFormula stringAtomicFormula =
+                new StringAtomicFormula(AtomicFormula.APP_CERTIFICATE, appCert);
+
+        assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.APP_CERTIFICATE);
+        assertThat(stringAtomicFormula.getValue()).doesNotMatch(appCert);
+        assertThat(stringAtomicFormula.getIsHashedValue()).isTrue();
+    }
+
+    @Test
+    public void testValidAtomicFormula_stringValue_installerCertificateAutoHashed() {
+        String installerCert = "cert";
+        StringAtomicFormula stringAtomicFormula =
+                new StringAtomicFormula(AtomicFormula.INSTALLER_CERTIFICATE,
+                        installerCert);
+
+        assertThat(stringAtomicFormula.getKey()).isEqualTo(
+                AtomicFormula.INSTALLER_CERTIFICATE);
+        assertThat(stringAtomicFormula.getValue()).doesNotMatch(installerCert);
+        assertThat(stringAtomicFormula.getIsHashedValue()).isTrue();
+    }
+
+    @Test
+    public void testValidAtomicFormula_longValue() {
+        AtomicFormula.LongAtomicFormula longAtomicFormula =
+                new AtomicFormula.LongAtomicFormula(
+                        AtomicFormula.VERSION_CODE, AtomicFormula.GTE, 1);
+
+        assertThat(longAtomicFormula.getKey()).isEqualTo(AtomicFormula.VERSION_CODE);
+        assertThat(longAtomicFormula.getValue()).isEqualTo(1);
     }
 
     @Test
@@ -56,180 +127,44 @@
         BooleanAtomicFormula atomicFormula =
                 new BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true);
 
-        assertEquals(AtomicFormula.PRE_INSTALLED, atomicFormula.getKey());
+        assertThat(atomicFormula.getKey()).isEqualTo(AtomicFormula.PRE_INSTALLED);
+        assertThat(atomicFormula.getValue()).isTrue();
     }
 
     @Test
     public void testInvalidAtomicFormula_stringValue() {
-        assertExpectException(
-                IllegalArgumentException.class,
-                /* expectedExceptionMessageRegex */
-                String.format("Key VERSION_CODE cannot be used with StringAtomicFormula"),
-                () ->
-                        new StringAtomicFormula(
-                                AtomicFormula.VERSION_CODE,
-                                "test-value",
-                                /* isHashedValue= */ false));
+        Exception e =
+                expectThrows(
+                        IllegalArgumentException.class,
+                        () ->
+                                new StringAtomicFormula(
+                                        AtomicFormula.VERSION_CODE,
+                                        "test-value",
+                                        /* isHashedValue= */ false));
+        assertThat(e.getMessage()).matches(
+                "Key VERSION_CODE cannot be used with StringAtomicFormula");
     }
 
     @Test
-    public void testInvalidAtomicFormula_intValue() {
-        assertExpectException(
-                IllegalArgumentException.class,
-                /* expectedExceptionMessageRegex */
-                String.format("Key PACKAGE_NAME cannot be used with IntAtomicFormula"),
-                () -> new IntAtomicFormula(AtomicFormula.PACKAGE_NAME, AtomicFormula.EQ, 1));
+    public void testInvalidAtomicFormula_longValue() {
+        Exception e =
+                expectThrows(
+                        IllegalArgumentException.class,
+                        () ->
+                                new AtomicFormula.LongAtomicFormula(
+                                        AtomicFormula.PACKAGE_NAME, AtomicFormula.EQ, 1));
+        assertThat(e.getMessage()).matches(
+                "Key PACKAGE_NAME cannot be used with LongAtomicFormula");
     }
 
     @Test
     public void testInvalidAtomicFormula_boolValue() {
-        assertExpectException(
-                IllegalArgumentException.class,
-                /* expectedExceptionMessageRegex */
-                String.format("Key PACKAGE_NAME cannot be used with BooleanAtomicFormula"),
-                () -> new BooleanAtomicFormula(AtomicFormula.PACKAGE_NAME, true));
-    }
-
-    @Test
-    public void testIsSatisfiable_string_true() {
-        StringAtomicFormula stringAtomicFormula =
-                new StringAtomicFormula(
-                        AtomicFormula.PACKAGE_NAME, "com.test.app", /* isHashedValue= */ false);
-        AppInstallMetadata appInstallMetadata =
-                getAppInstallMetadataBuilder().setPackageName("com.test.app").build();
-
-        assertTrue(stringAtomicFormula.isSatisfied(appInstallMetadata));
-    }
-
-    @Test
-    public void testIsSatisfiable_string_false() {
-        StringAtomicFormula stringAtomicFormula =
-                new StringAtomicFormula(
-                        AtomicFormula.PACKAGE_NAME, "com.test.app", /* isHashedValue= */ false);
-        AppInstallMetadata appInstallMetadata =
-                getAppInstallMetadataBuilder().setPackageName("com.foo.bar").build();
-
-        assertFalse(stringAtomicFormula.isSatisfied(appInstallMetadata));
-    }
-
-    @Test
-    public void testIsSatisfiable_int_eq_true() {
-        IntAtomicFormula intAtomicFormula =
-                new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 0);
-        AppInstallMetadata appInstallMetadata =
-                getAppInstallMetadataBuilder().setVersionCode(0).build();
-
-        assertTrue(intAtomicFormula.isSatisfied(appInstallMetadata));
-    }
-
-    @Test
-    public void testIsSatisfiable_int_eq_false() {
-        IntAtomicFormula intAtomicFormula =
-                new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 0);
-        AppInstallMetadata appInstallMetadata =
-                getAppInstallMetadataBuilder().setVersionCode(1).build();
-
-        assertFalse(intAtomicFormula.isSatisfied(appInstallMetadata));
-    }
-
-    @Test
-    public void testIsSatisfiable_int_gt_true() {
-        IntAtomicFormula intAtomicFormula =
-                new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.GT, 0);
-        AppInstallMetadata appInstallMetadata =
-                getAppInstallMetadataBuilder().setVersionCode(1).build();
-
-        assertTrue(intAtomicFormula.isSatisfied(appInstallMetadata));
-    }
-
-    @Test
-    public void testIsSatisfiable_int_gt_false() {
-        IntAtomicFormula intAtomicFormula =
-                new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.GT, 1);
-        AppInstallMetadata appInstallMetadata =
-                getAppInstallMetadataBuilder().setVersionCode(0).build();
-
-        assertFalse(intAtomicFormula.isSatisfied(appInstallMetadata));
-    }
-
-    @Test
-    public void testIsSatisfiable_int_ge_true() {
-        IntAtomicFormula intAtomicFormula =
-                new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.GE, 0);
-        AppInstallMetadata appInstallMetadata =
-                getAppInstallMetadataBuilder().setVersionCode(1).build();
-
-        assertTrue(intAtomicFormula.isSatisfied(appInstallMetadata));
-    }
-
-    @Test
-    public void testIsSatisfiable_int_ge_false() {
-        IntAtomicFormula intAtomicFormula =
-                new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.GE, 1);
-        AppInstallMetadata appInstallMetadata =
-                getAppInstallMetadataBuilder().setVersionCode(0).build();
-
-        assertFalse(intAtomicFormula.isSatisfied(appInstallMetadata));
-    }
-
-    @Test
-    public void testIsSatisfiable_int_lt_true() {
-        IntAtomicFormula intAtomicFormula =
-                new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.LT, 1);
-        AppInstallMetadata appInstallMetadata =
-                getAppInstallMetadataBuilder().setVersionCode(0).build();
-
-        assertTrue(intAtomicFormula.isSatisfied(appInstallMetadata));
-    }
-
-    @Test
-    public void testIsSatisfiable_int_lt_false() {
-        IntAtomicFormula intAtomicFormula =
-                new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.LT, 1);
-        AppInstallMetadata appInstallMetadata =
-                getAppInstallMetadataBuilder().setVersionCode(2).build();
-
-        assertFalse(intAtomicFormula.isSatisfied(appInstallMetadata));
-    }
-
-    @Test
-    public void testIsSatisfiable_int_le_true() {
-        IntAtomicFormula intAtomicFormula =
-                new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.LE, 1);
-        AppInstallMetadata appInstallMetadata =
-                getAppInstallMetadataBuilder().setVersionCode(0).build();
-
-        assertTrue(intAtomicFormula.isSatisfied(appInstallMetadata));
-    }
-
-    @Test
-    public void testIsSatisfiable_int_le_false() {
-        IntAtomicFormula intAtomicFormula =
-                new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.LE, 1);
-        AppInstallMetadata appInstallMetadata =
-                getAppInstallMetadataBuilder().setVersionCode(2).build();
-
-        assertFalse(intAtomicFormula.isSatisfied(appInstallMetadata));
-    }
-
-    @Test
-    public void testIsSatisfiable_bool_true() {
-        BooleanAtomicFormula boolFormula =
-                new BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true);
-        AppInstallMetadata appInstallMetadata =
-                getAppInstallMetadataBuilder().setIsPreInstalled(true).build();
-
-        assertTrue(boolFormula.isSatisfied(appInstallMetadata));
-    }
-
-    @Test
-    public void testIsSatisfiable_bool_false() {
-        BooleanAtomicFormula boolFormula =
-                new BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true);
-        AppInstallMetadata appInstallMetadata =
-                getAppInstallMetadataBuilder().setIsPreInstalled(false).build();
-
-        assertFalse(boolFormula.isSatisfied(appInstallMetadata));
+        Exception e =
+                expectThrows(
+                        IllegalArgumentException.class,
+                        () -> new BooleanAtomicFormula(AtomicFormula.PACKAGE_NAME, true));
+        assertThat(e.getMessage()).matches(
+                "Key PACKAGE_NAME cannot be used with BooleanAtomicFormula");
     }
 
     @Test
@@ -242,46 +177,169 @@
         p.setDataPosition(0);
         StringAtomicFormula newFormula = StringAtomicFormula.CREATOR.createFromParcel(p);
 
-        assertEquals(formula, newFormula);
+        assertThat(newFormula).isEqualTo(formula);
     }
 
     @Test
     public void testParcelUnparcel_int() {
-        IntAtomicFormula formula =
-                new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.LT, 1);
+        AtomicFormula.LongAtomicFormula formula =
+                new AtomicFormula.LongAtomicFormula(
+                        AtomicFormula.VERSION_CODE, AtomicFormula.GT, 1);
         Parcel p = Parcel.obtain();
         formula.writeToParcel(p, 0);
         p.setDataPosition(0);
-        IntAtomicFormula newFormula = IntAtomicFormula.CREATOR.createFromParcel(p);
+        AtomicFormula.LongAtomicFormula newFormula =
+                AtomicFormula.LongAtomicFormula.CREATOR.createFromParcel(p);
 
-        assertEquals(formula, newFormula);
+        assertThat(newFormula).isEqualTo(formula);
     }
 
     @Test
     public void testParcelUnparcel_bool() {
-        BooleanAtomicFormula formula = new BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true);
+        BooleanAtomicFormula formula = new BooleanAtomicFormula(
+                AtomicFormula.PRE_INSTALLED, true);
         Parcel p = Parcel.obtain();
         formula.writeToParcel(p, 0);
         p.setDataPosition(0);
         BooleanAtomicFormula newFormula = BooleanAtomicFormula.CREATOR.createFromParcel(p);
 
-        assertEquals(formula, newFormula);
+        assertThat(newFormula).isEqualTo(formula);
     }
 
     @Test
     public void testInvalidAtomicFormula_invalidKey() {
-        assertExpectException(
-                IllegalArgumentException.class,
-                /* expectedExceptionMessageRegex */ "Unknown key: -1",
-                () -> new IntAtomicFormula(/* key= */ -1, AtomicFormula.EQ, 0));
+        Exception e =
+                expectThrows(
+                        IllegalArgumentException.class,
+                        () -> new AtomicFormula.LongAtomicFormula(/* key= */ -1,
+                                AtomicFormula.EQ, /* value= */0));
+        assertThat(e.getMessage()).matches("Unknown key: -1");
     }
 
     @Test
     public void testInvalidAtomicFormula_invalidOperator() {
-        assertExpectException(
-                IllegalArgumentException.class,
-                /* expectedExceptionMessageRegex */ "Unknown operator: -1",
-                () -> new IntAtomicFormula(AtomicFormula.VERSION_CODE, /* operator= */ -1, 0));
+        Exception e =
+                expectThrows(
+                        IllegalArgumentException.class,
+                        () ->
+                                new AtomicFormula.LongAtomicFormula(
+                                        AtomicFormula.VERSION_CODE, /* operator= */ -1, /* value= */
+                                        0));
+        assertThat(e.getMessage()).matches("Unknown operator: -1");
+    }
+
+    @Test
+    public void testFormulaMatches_string_true() {
+        StringAtomicFormula stringAtomicFormula =
+                new StringAtomicFormula(
+                        AtomicFormula.PACKAGE_NAME, "com.test.app", /* isHashedValue= */
+                        false);
+        AppInstallMetadata appInstallMetadata =
+                getAppInstallMetadataBuilder().setPackageName("com.test.app").build();
+
+        assertThat(stringAtomicFormula.matches(appInstallMetadata)).isTrue();
+    }
+
+    @Test
+    public void testFormulaMatches_string_false() {
+        StringAtomicFormula stringAtomicFormula =
+                new StringAtomicFormula(
+                        AtomicFormula.PACKAGE_NAME, "com.test.app", /* isHashedValue= */
+                        false);
+        AppInstallMetadata appInstallMetadata =
+                getAppInstallMetadataBuilder().setPackageName("com.foo.bar").build();
+
+        assertThat(stringAtomicFormula.matches(appInstallMetadata)).isFalse();
+    }
+
+    @Test
+    public void testFormulaMatches_long_eq_true() {
+        AtomicFormula.LongAtomicFormula longAtomicFormula =
+                new AtomicFormula.LongAtomicFormula(
+                        AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 0);
+        AppInstallMetadata appInstallMetadata =
+                getAppInstallMetadataBuilder().setVersionCode(0).build();
+
+        assertThat(longAtomicFormula.matches(appInstallMetadata)).isTrue();
+    }
+
+    @Test
+    public void testFormulaMatches_long_eq_false() {
+        AtomicFormula.LongAtomicFormula longAtomicFormula =
+                new AtomicFormula.LongAtomicFormula(
+                        AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 0);
+        AppInstallMetadata appInstallMetadata =
+                getAppInstallMetadataBuilder().setVersionCode(1).build();
+
+        assertThat(longAtomicFormula.matches(appInstallMetadata)).isFalse();
+    }
+
+    @Test
+    public void testFormulaMatches_long_gt_true() {
+        AtomicFormula.LongAtomicFormula longAtomicFormula =
+                new AtomicFormula.LongAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.GT,
+                        0);
+        AppInstallMetadata appInstallMetadata =
+                getAppInstallMetadataBuilder().setVersionCode(1).build();
+
+        assertThat(longAtomicFormula.matches(appInstallMetadata)).isTrue();
+    }
+
+    @Test
+    public void testFormulaMatches_long_gt_false() {
+        AtomicFormula.LongAtomicFormula longAtomicFormula =
+                new AtomicFormula.LongAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.GT,
+                        1);
+        AppInstallMetadata appInstallMetadata =
+                getAppInstallMetadataBuilder().setVersionCode(0).build();
+
+        assertThat(longAtomicFormula.matches(appInstallMetadata)).isFalse();
+    }
+
+    @Test
+    public void testFormulaMatches_long_gte_true() {
+        AtomicFormula.LongAtomicFormula longAtomicFormula =
+                new AtomicFormula.LongAtomicFormula(
+                        AtomicFormula.VERSION_CODE, AtomicFormula.GTE, 1);
+
+        AppInstallMetadata appInstallMetadata1 =
+                getAppInstallMetadataBuilder().setVersionCode(1).build();
+        assertThat(longAtomicFormula.matches(appInstallMetadata1)).isTrue();
+
+        AppInstallMetadata appInstallMetadata2 =
+                getAppInstallMetadataBuilder().setVersionCode(2).build();
+        assertThat(longAtomicFormula.matches(appInstallMetadata2)).isTrue();
+    }
+
+    @Test
+    public void testFormulaMatches_long_gte_false() {
+        AtomicFormula.LongAtomicFormula longAtomicFormula =
+                new AtomicFormula.LongAtomicFormula(
+                        AtomicFormula.VERSION_CODE, AtomicFormula.GTE, 1);
+        AppInstallMetadata appInstallMetadata =
+                getAppInstallMetadataBuilder().setVersionCode(0).build();
+
+        assertThat(longAtomicFormula.matches(appInstallMetadata)).isFalse();
+    }
+
+    @Test
+    public void testFormulaMatches_bool_true() {
+        BooleanAtomicFormula boolFormula =
+                new BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true);
+        AppInstallMetadata appInstallMetadata =
+                getAppInstallMetadataBuilder().setIsPreInstalled(true).build();
+
+        assertThat(boolFormula.matches(appInstallMetadata)).isTrue();
+    }
+
+    @Test
+    public void testFormulaMatches_bool_false() {
+        BooleanAtomicFormula boolFormula =
+                new BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true);
+        AppInstallMetadata appInstallMetadata =
+                getAppInstallMetadataBuilder().setIsPreInstalled(false).build();
+
+        assertThat(boolFormula.matches(appInstallMetadata)).isFalse();
     }
 
     /** Returns a builder with all fields filled with some dummy data. */
diff --git a/core/tests/coretests/src/android/content/integrity/CompoundFormulaTest.java b/core/tests/coretests/src/android/content/integrity/CompoundFormulaTest.java
index 927e4db..4054c49 100644
--- a/core/tests/coretests/src/android/content/integrity/CompoundFormulaTest.java
+++ b/core/tests/coretests/src/android/content/integrity/CompoundFormulaTest.java
@@ -16,11 +16,9 @@
 
 package android.content.integrity;
 
-import static android.content.integrity.TestUtils.assertExpectException;
+import static com.google.common.truth.Truth.assertThat;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.testng.Assert.expectThrows;
 
 import android.os.Parcel;
 
@@ -38,7 +36,7 @@
             new AtomicFormula.StringAtomicFormula(
                     AtomicFormula.PACKAGE_NAME, "test1", /* isHashedValue= */ false);
     private static final AtomicFormula ATOMIC_FORMULA_2 =
-            new AtomicFormula.IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 1);
+            new AtomicFormula.LongAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 1);
 
     @Test
     public void testValidCompoundFormula() {
@@ -46,168 +44,32 @@
                 new CompoundFormula(
                         CompoundFormula.AND, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
 
-        assertEquals(CompoundFormula.AND, compoundFormula.getConnector());
-        assertEquals(
-                Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2), compoundFormula.getFormulas());
+        assertThat(compoundFormula.getConnector()).isEqualTo(CompoundFormula.AND);
+        assertThat(compoundFormula.getFormulas()).containsAllOf(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2);
     }
 
     @Test
     public void testValidateAuxiliaryFormula_binaryConnectors() {
-        assertExpectException(
-                IllegalArgumentException.class,
-                /* expectedExceptionMessageRegex */
-                "Connector AND must have at least 2 formulas",
-                () ->
-                        new CompoundFormula(
-                                CompoundFormula.AND, Collections.singletonList(ATOMIC_FORMULA_1)));
+        Exception e =
+                expectThrows(
+                        IllegalArgumentException.class,
+                        () ->
+                                new CompoundFormula(
+                                        CompoundFormula.AND,
+                                        Collections.singletonList(ATOMIC_FORMULA_1)));
+        assertThat(e.getMessage()).matches("Connector AND must have at least 2 formulas");
     }
 
     @Test
     public void testValidateAuxiliaryFormula_unaryConnectors() {
-        assertExpectException(
-                IllegalArgumentException.class,
-                /* expectedExceptionMessageRegex */
-                "Connector NOT must have 1 formula only",
-                () ->
-                        new CompoundFormula(
-                                CompoundFormula.NOT,
-                                Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2)));
-    }
-
-    @Test
-    public void testIsSatisfiable_notFalse_true() {
-        CompoundFormula compoundFormula =
-                new CompoundFormula(CompoundFormula.NOT, Arrays.asList(ATOMIC_FORMULA_1));
-        AppInstallMetadata appInstallMetadata =
-                getAppInstallMetadataBuilder().setPackageName("test2").build();
-        // validate assumptions about the metadata
-        assertFalse(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
-
-        assertTrue(compoundFormula.isSatisfied(appInstallMetadata));
-    }
-
-    @Test
-    public void testIsSatisfiable_notTrue_false() {
-        CompoundFormula compoundFormula =
-                new CompoundFormula(CompoundFormula.NOT, Arrays.asList(ATOMIC_FORMULA_1));
-        AppInstallMetadata appInstallMetadata =
-                getAppInstallMetadataBuilder().setPackageName("test1").build();
-        // validate assumptions about the metadata
-        assertTrue(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
-
-        assertFalse(compoundFormula.isSatisfied(appInstallMetadata));
-    }
-
-    @Test
-    public void testIsSatisfiable_trueAndTrue_true() {
-        CompoundFormula compoundFormula =
-                new CompoundFormula(
-                        CompoundFormula.AND, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
-        AppInstallMetadata appInstallMetadata =
-                getAppInstallMetadataBuilder().setPackageName("test1").setVersionCode(1).build();
-        // validate assumptions about the metadata
-        assertTrue(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
-        assertTrue(ATOMIC_FORMULA_2.isSatisfied(appInstallMetadata));
-
-        assertTrue(compoundFormula.isSatisfied(appInstallMetadata));
-    }
-
-    @Test
-    public void testIsSatisfiable_trueAndFalse_false() {
-        CompoundFormula compoundFormula =
-                new CompoundFormula(
-                        CompoundFormula.AND, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
-        AppInstallMetadata appInstallMetadata =
-                getAppInstallMetadataBuilder().setPackageName("test1").setVersionCode(2).build();
-        // validate assumptions about the metadata
-        assertTrue(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
-        assertFalse(ATOMIC_FORMULA_2.isSatisfied(appInstallMetadata));
-
-        assertFalse(compoundFormula.isSatisfied(appInstallMetadata));
-    }
-
-    @Test
-    public void testIsSatisfiable_falseAndTrue_false() {
-        CompoundFormula compoundFormula =
-                new CompoundFormula(
-                        CompoundFormula.AND, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
-        AppInstallMetadata appInstallMetadata =
-                getAppInstallMetadataBuilder().setPackageName("test2").setVersionCode(1).build();
-        // validate assumptions about the metadata
-        assertFalse(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
-        assertTrue(ATOMIC_FORMULA_2.isSatisfied(appInstallMetadata));
-
-        assertFalse(compoundFormula.isSatisfied(appInstallMetadata));
-    }
-
-    @Test
-    public void testIsSatisfiable_falseAndFalse_false() {
-        CompoundFormula compoundFormula =
-                new CompoundFormula(
-                        CompoundFormula.AND, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
-        AppInstallMetadata appInstallMetadata =
-                getAppInstallMetadataBuilder().setPackageName("test2").setVersionCode(2).build();
-        // validate assumptions about the metadata
-        assertFalse(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
-        assertFalse(ATOMIC_FORMULA_2.isSatisfied(appInstallMetadata));
-
-        assertFalse(compoundFormula.isSatisfied(appInstallMetadata));
-    }
-
-    @Test
-    public void testIsSatisfiable_trueOrTrue_true() {
-        CompoundFormula compoundFormula =
-                new CompoundFormula(
-                        CompoundFormula.OR, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
-        AppInstallMetadata appInstallMetadata =
-                getAppInstallMetadataBuilder().setPackageName("test1").setVersionCode(1).build();
-        // validate assumptions about the metadata
-        assertTrue(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
-        assertTrue(ATOMIC_FORMULA_2.isSatisfied(appInstallMetadata));
-
-        assertTrue(compoundFormula.isSatisfied(appInstallMetadata));
-    }
-
-    @Test
-    public void testIsSatisfiable_trueOrFalse_true() {
-        CompoundFormula compoundFormula =
-                new CompoundFormula(
-                        CompoundFormula.OR, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
-        AppInstallMetadata appInstallMetadata =
-                getAppInstallMetadataBuilder().setPackageName("test1").setVersionCode(2).build();
-        // validate assumptions about the metadata
-        assertTrue(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
-        assertFalse(ATOMIC_FORMULA_2.isSatisfied(appInstallMetadata));
-
-        assertTrue(compoundFormula.isSatisfied(appInstallMetadata));
-    }
-
-    @Test
-    public void testIsSatisfiable_falseOrTrue_true() {
-        CompoundFormula compoundFormula =
-                new CompoundFormula(
-                        CompoundFormula.OR, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
-        AppInstallMetadata appInstallMetadata =
-                getAppInstallMetadataBuilder().setPackageName("test2").setVersionCode(1).build();
-        // validate assumptions about the metadata
-        assertFalse(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
-        assertTrue(ATOMIC_FORMULA_2.isSatisfied(appInstallMetadata));
-
-        assertTrue(compoundFormula.isSatisfied(appInstallMetadata));
-    }
-
-    @Test
-    public void testIsSatisfiable_falseOrFalse_false() {
-        CompoundFormula compoundFormula =
-                new CompoundFormula(
-                        CompoundFormula.OR, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
-        AppInstallMetadata appInstallMetadata =
-                getAppInstallMetadataBuilder().setPackageName("test2").setVersionCode(2).build();
-        // validate assumptions about the metadata
-        assertFalse(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
-        assertFalse(ATOMIC_FORMULA_2.isSatisfied(appInstallMetadata));
-
-        assertFalse(compoundFormula.isSatisfied(appInstallMetadata));
+        Exception e =
+                expectThrows(
+                        IllegalArgumentException.class,
+                        () ->
+                                new CompoundFormula(
+                                        CompoundFormula.NOT,
+                                        Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2)));
+        assertThat(e.getMessage()).matches("Connector NOT must have 1 formula only");
     }
 
     @Test
@@ -218,20 +80,149 @@
         Parcel p = Parcel.obtain();
         formula.writeToParcel(p, 0);
         p.setDataPosition(0);
-        CompoundFormula newFormula = CompoundFormula.CREATOR.createFromParcel(p);
 
-        assertEquals(formula, newFormula);
+        assertThat(CompoundFormula.CREATOR.createFromParcel(p)).isEqualTo(formula);
     }
 
     @Test
     public void testInvalidCompoundFormula_invalidConnector() {
-        assertExpectException(
-                IllegalArgumentException.class,
-                /* expectedExceptionMessageRegex */ "Unknown connector: -1",
-                () ->
-                        new CompoundFormula(
-                                /* connector= */ -1,
-                                Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2)));
+        Exception e =
+                expectThrows(
+                        IllegalArgumentException.class,
+                        () ->
+                                new CompoundFormula(
+                                        /* connector= */ -1,
+                                        Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2)));
+        assertThat(e.getMessage()).matches("Unknown connector: -1");
+    }
+
+    @Test
+    public void testFormulaMatches_notFalse_true() {
+        AppInstallMetadata appInstallMetadata =
+                getAppInstallMetadataBuilder().setPackageName("test2").build();
+
+        assertThat(ATOMIC_FORMULA_1.matches(appInstallMetadata)).isFalse();
+
+        CompoundFormula compoundFormula =
+                new CompoundFormula(CompoundFormula.NOT, Arrays.asList(ATOMIC_FORMULA_1));
+        assertThat(compoundFormula.matches(appInstallMetadata)).isTrue();
+    }
+
+    @Test
+    public void testFormulaMatches_notTrue_false() {
+        AppInstallMetadata appInstallMetadata =
+                getAppInstallMetadataBuilder().setPackageName("test1").build();
+
+        assertThat(ATOMIC_FORMULA_1.matches(appInstallMetadata)).isTrue();
+
+        CompoundFormula compoundFormula =
+                new CompoundFormula(CompoundFormula.NOT, Arrays.asList(ATOMIC_FORMULA_1));
+        assertThat(compoundFormula.matches(appInstallMetadata)).isFalse();
+    }
+
+    @Test
+    public void testFormulaMatches_trueAndTrue_true() {
+        CompoundFormula compoundFormula =
+                new CompoundFormula(
+                        CompoundFormula.AND, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
+        AppInstallMetadata appInstallMetadata =
+                getAppInstallMetadataBuilder().setPackageName("test1").setVersionCode(1).build();
+        // validate assumptions about the metadata
+        assertThat(ATOMIC_FORMULA_1.matches(appInstallMetadata)).isTrue();
+        assertThat(ATOMIC_FORMULA_1.matches(appInstallMetadata)).isTrue();
+
+        assertThat(compoundFormula.matches(appInstallMetadata)).isTrue();
+    }
+
+    @Test
+    public void testFormulaMatches_trueAndFalse_false() {
+        CompoundFormula compoundFormula =
+                new CompoundFormula(
+                        CompoundFormula.AND, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
+        AppInstallMetadata appInstallMetadata =
+                getAppInstallMetadataBuilder().setPackageName("test1").setVersionCode(2).build();
+
+        assertThat(ATOMIC_FORMULA_1.matches(appInstallMetadata)).isTrue();
+        assertThat(ATOMIC_FORMULA_2.matches(appInstallMetadata)).isFalse();
+        assertThat(compoundFormula.matches(appInstallMetadata)).isFalse();
+    }
+
+    @Test
+    public void testFormulaMatches_falseAndTrue_false() {
+        CompoundFormula compoundFormula =
+                new CompoundFormula(
+                        CompoundFormula.AND, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
+        AppInstallMetadata appInstallMetadata =
+                getAppInstallMetadataBuilder().setPackageName("test2").setVersionCode(1).build();
+
+        assertThat(ATOMIC_FORMULA_1.matches(appInstallMetadata)).isFalse();
+        assertThat(ATOMIC_FORMULA_2.matches(appInstallMetadata)).isTrue();
+        assertThat(compoundFormula.matches(appInstallMetadata)).isFalse();
+    }
+
+    @Test
+    public void testFormulaMatches_falseAndFalse_false() {
+        CompoundFormula compoundFormula =
+                new CompoundFormula(
+                        CompoundFormula.AND, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
+        AppInstallMetadata appInstallMetadata =
+                getAppInstallMetadataBuilder().setPackageName("test2").setVersionCode(2).build();
+
+        assertThat(ATOMIC_FORMULA_1.matches(appInstallMetadata)).isFalse();
+        assertThat(ATOMIC_FORMULA_2.matches(appInstallMetadata)).isFalse();
+        assertThat(compoundFormula.matches(appInstallMetadata)).isFalse();
+    }
+
+    @Test
+    public void testFormulaMatches_trueOrTrue_true() {
+        CompoundFormula compoundFormula =
+                new CompoundFormula(
+                        CompoundFormula.OR, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
+        AppInstallMetadata appInstallMetadata =
+                getAppInstallMetadataBuilder().setPackageName("test1").setVersionCode(1).build();
+
+        assertThat(ATOMIC_FORMULA_1.matches(appInstallMetadata)).isTrue();
+        assertThat(ATOMIC_FORMULA_2.matches(appInstallMetadata)).isTrue();
+        assertThat(compoundFormula.matches(appInstallMetadata)).isTrue();
+    }
+
+    @Test
+    public void testFormulaMatches_trueOrFalse_true() {
+        CompoundFormula compoundFormula =
+                new CompoundFormula(
+                        CompoundFormula.OR, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
+        AppInstallMetadata appInstallMetadata =
+                getAppInstallMetadataBuilder().setPackageName("test1").setVersionCode(2).build();
+
+        assertThat(ATOMIC_FORMULA_1.matches(appInstallMetadata)).isTrue();
+        assertThat(ATOMIC_FORMULA_2.matches(appInstallMetadata)).isFalse();
+        assertThat(compoundFormula.matches(appInstallMetadata)).isTrue();
+    }
+
+    @Test
+    public void testFormulaMatches_falseOrTrue_true() {
+        CompoundFormula compoundFormula =
+                new CompoundFormula(
+                        CompoundFormula.OR, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
+        AppInstallMetadata appInstallMetadata =
+                getAppInstallMetadataBuilder().setPackageName("test2").setVersionCode(1).build();
+
+        assertThat(ATOMIC_FORMULA_1.matches(appInstallMetadata)).isFalse();
+        assertThat(ATOMIC_FORMULA_2.matches(appInstallMetadata)).isTrue();
+        assertThat(compoundFormula.matches(appInstallMetadata)).isTrue();
+    }
+
+    @Test
+    public void testFormulaMatches_falseOrFalse_false() {
+        CompoundFormula compoundFormula =
+                new CompoundFormula(
+                        CompoundFormula.OR, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
+        AppInstallMetadata appInstallMetadata =
+                getAppInstallMetadataBuilder().setPackageName("test2").setVersionCode(2).build();
+
+        assertThat(ATOMIC_FORMULA_1.matches(appInstallMetadata)).isFalse();
+        assertThat(ATOMIC_FORMULA_2.matches(appInstallMetadata)).isFalse();
+        assertThat(compoundFormula.matches(appInstallMetadata)).isFalse();
     }
 
     /** Returns a builder with all fields filled with some dummy data. */
diff --git a/core/tests/coretests/src/android/content/integrity/IntegrityFormulaTest.java b/core/tests/coretests/src/android/content/integrity/IntegrityFormulaTest.java
new file mode 100644
index 0000000..c180602
--- /dev/null
+++ b/core/tests/coretests/src/android/content/integrity/IntegrityFormulaTest.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.integrity;
+
+import static android.content.integrity.IntegrityFormula.COMPOUND_FORMULA_TAG;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.assertThrows;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class IntegrityFormulaTest {
+
+    @Test
+    public void createEqualsFormula_packageName() {
+        String packageName = "com.test.app";
+        IntegrityFormula formula =
+                IntegrityFormula.PACKAGE_NAME.equalTo(packageName);
+
+        AtomicFormula.StringAtomicFormula stringAtomicFormula =
+                (AtomicFormula.StringAtomicFormula) formula;
+
+        assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.PACKAGE_NAME);
+        assertThat(stringAtomicFormula.getValue()).isEqualTo(packageName);
+        assertThat(stringAtomicFormula.getIsHashedValue()).isEqualTo(false);
+    }
+
+    @Test
+    public void createEqualsFormula_appCertificate() {
+        String appCertificate = "com.test.app";
+        IntegrityFormula formula =
+                IntegrityFormula.APP_CERTIFICATE.equalTo(appCertificate);
+
+        AtomicFormula.StringAtomicFormula stringAtomicFormula =
+                (AtomicFormula.StringAtomicFormula) formula;
+
+        assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.APP_CERTIFICATE);
+        assertThat(stringAtomicFormula.getValue()).doesNotMatch(appCertificate);
+        assertThat(stringAtomicFormula.getIsHashedValue()).isEqualTo(true);
+    }
+
+    @Test
+    public void createEqualsFormula_installerName() {
+        String installerName = "com.test.app";
+        IntegrityFormula formula =
+                IntegrityFormula.INSTALLER_NAME.equalTo(installerName);
+
+        AtomicFormula.StringAtomicFormula stringAtomicFormula =
+                (AtomicFormula.StringAtomicFormula) formula;
+
+        assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.INSTALLER_NAME);
+        assertThat(stringAtomicFormula.getValue()).isEqualTo(installerName);
+        assertThat(stringAtomicFormula.getIsHashedValue()).isEqualTo(false);
+    }
+
+    @Test
+    public void createEqualsFormula_installerCertificate() {
+        String installerCertificate = "com.test.app";
+        IntegrityFormula formula =
+                IntegrityFormula.INSTALLER_CERTIFICATE.equalTo(installerCertificate);
+
+        AtomicFormula.StringAtomicFormula stringAtomicFormula =
+                (AtomicFormula.StringAtomicFormula) formula;
+
+        assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.INSTALLER_CERTIFICATE);
+        assertThat(stringAtomicFormula.getValue()).doesNotMatch(installerCertificate);
+        assertThat(stringAtomicFormula.getIsHashedValue()).isEqualTo(true);
+    }
+
+    @Test
+    public void createEqualsFormula_versionCode() {
+        int versionCode = 12;
+        IntegrityFormula formula =
+                IntegrityFormula.VERSION_CODE.equalTo(versionCode);
+
+        AtomicFormula.LongAtomicFormula stringAtomicFormula =
+                (AtomicFormula.LongAtomicFormula) formula;
+
+        assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.VERSION_CODE);
+        assertThat(stringAtomicFormula.getValue()).isEqualTo(versionCode);
+        assertThat(stringAtomicFormula.getOperator()).isEqualTo(AtomicFormula.EQ);
+    }
+
+    @Test
+    public void createEqualsFormula_invalidKeyTypeForStringParameter() {
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> IntegrityFormula.PRE_INSTALLED.equalTo("wrongString"));
+    }
+
+    @Test
+    public void createEqualsFormula_invalidKeyTypeForLongParameter() {
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> IntegrityFormula.PACKAGE_NAME.equalTo(12));
+    }
+
+    @Test
+    public void createGreaterThanFormula_versionCode() {
+        int versionCode = 12;
+        IntegrityFormula formula =
+                IntegrityFormula.VERSION_CODE.greaterThan(versionCode);
+
+        AtomicFormula.LongAtomicFormula stringAtomicFormula =
+                (AtomicFormula.LongAtomicFormula) formula;
+
+        assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.VERSION_CODE);
+        assertThat(stringAtomicFormula.getValue()).isEqualTo(versionCode);
+        assertThat(stringAtomicFormula.getOperator()).isEqualTo(AtomicFormula.GT);
+    }
+
+    @Test
+    public void createGreaterThanFormula_invalidKeyTypeForLongParameter() {
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> IntegrityFormula.PACKAGE_NAME.greaterThan(12));
+    }
+
+    @Test
+    public void createGreaterThanOrEqualsToFormula_versionCode() {
+        int versionCode = 12;
+        IntegrityFormula formula =
+                IntegrityFormula.VERSION_CODE.greaterThanOrEquals(versionCode);
+
+        AtomicFormula.LongAtomicFormula stringAtomicFormula =
+                (AtomicFormula.LongAtomicFormula) formula;
+
+        assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.VERSION_CODE);
+        assertThat(stringAtomicFormula.getValue()).isEqualTo(versionCode);
+        assertThat(stringAtomicFormula.getOperator()).isEqualTo(AtomicFormula.GTE);
+    }
+
+    @Test
+    public void createGreaterThanOrEqualsToFormula_invalidKeyTypeForLongParameter() {
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> IntegrityFormula.PACKAGE_NAME.greaterThanOrEquals(12));
+    }
+
+    @Test
+    public void createIsTrueFormula_preInstalled() {
+        IntegrityFormula formula = IntegrityFormula.PRE_INSTALLED.equalTo(true);
+
+        AtomicFormula.BooleanAtomicFormula stringAtomicFormula =
+                (AtomicFormula.BooleanAtomicFormula) formula;
+
+        assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.PRE_INSTALLED);
+        assertThat(stringAtomicFormula.getValue()).isTrue();
+    }
+
+    @Test
+    public void createIsTrueFormula_invalidKeyTypeForBoolParameter() {
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> IntegrityFormula.PACKAGE_NAME.equalTo(true));
+    }
+
+    @Test
+    public void createAllFormula() {
+        String packageName = "com.test.package";
+        String certificateName = "certificate";
+        IntegrityFormula formula1 =
+                IntegrityFormula.PACKAGE_NAME.equalTo(packageName);
+        IntegrityFormula formula2 =
+                IntegrityFormula.APP_CERTIFICATE.equalTo(certificateName);
+
+        IntegrityFormula compoundFormula = IntegrityFormula.all(formula1, formula2);
+
+        assertThat(compoundFormula.getTag()).isEqualTo(COMPOUND_FORMULA_TAG);
+    }
+
+    @Test
+    public void createAnyFormula() {
+        String packageName = "com.test.package";
+        String certificateName = "certificate";
+        IntegrityFormula formula1 =
+                IntegrityFormula.PACKAGE_NAME.equalTo(packageName);
+        IntegrityFormula formula2 =
+                IntegrityFormula.APP_CERTIFICATE.equalTo(certificateName);
+
+        IntegrityFormula compoundFormula = IntegrityFormula.any(formula1, formula2);
+
+        assertThat(compoundFormula.getTag()).isEqualTo(COMPOUND_FORMULA_TAG);
+    }
+
+    @Test
+    public void createNotFormula() {
+        String packageName = "com.test.package";
+
+        IntegrityFormula compoundFormula =
+                IntegrityFormula.not(
+                        IntegrityFormula.PACKAGE_NAME.equalTo(packageName));
+
+        assertThat(compoundFormula.getTag()).isEqualTo(COMPOUND_FORMULA_TAG);
+    }
+}
diff --git a/core/tests/coretests/src/android/content/integrity/IntegrityUtilsTest.java b/core/tests/coretests/src/android/content/integrity/IntegrityUtilsTest.java
new file mode 100644
index 0000000..e6f6686
--- /dev/null
+++ b/core/tests/coretests/src/android/content/integrity/IntegrityUtilsTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.integrity;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.expectThrows;
+import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Unit test for {@link IntegrityUtils} */
+@RunWith(JUnit4.class)
+public class IntegrityUtilsTest {
+
+    private static final String HEX_DIGEST = "1234567890ABCDEF";
+    private static final byte[] BYTES =
+            new byte[]{0x12, 0x34, 0x56, 0x78, (byte) 0x90, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF};
+
+    @Test
+    public void testGetBytesFromHexDigest() {
+        assertArrayEquals(BYTES, IntegrityUtils.getBytesFromHexDigest(HEX_DIGEST));
+    }
+
+    @Test
+    public void testGetHexDigest() {
+        assertThat(IntegrityUtils.getHexDigest(BYTES)).isEqualTo(HEX_DIGEST);
+    }
+
+    @Test
+    public void testInvalidHexDigest_mustHaveEvenLength() {
+        Exception e =
+                expectThrows(
+                        IllegalArgumentException.class,
+                        () -> IntegrityUtils.getBytesFromHexDigest("ABC"));
+        assertThat(e.getMessage()).containsMatch("must have even length");
+    }
+
+    @Test
+    public void testInvalidHexDigest_invalidHexChar() {
+        Exception e =
+                expectThrows(
+                        IllegalArgumentException.class,
+                        () -> IntegrityUtils.getBytesFromHexDigest("GH"));
+        assertThat(e.getMessage()).containsMatch("Invalid hex char");
+    }
+}
diff --git a/core/tests/coretests/src/android/content/integrity/RuleTest.java b/core/tests/coretests/src/android/content/integrity/RuleTest.java
index 19e74e6..8faf8ba 100644
--- a/core/tests/coretests/src/android/content/integrity/RuleTest.java
+++ b/core/tests/coretests/src/android/content/integrity/RuleTest.java
@@ -16,10 +16,9 @@
 
 package android.content.integrity;
 
-import static android.content.integrity.TestUtils.assertExpectException;
+import static com.google.common.truth.Truth.assertThat;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
+import static org.testng.Assert.expectThrows;
 
 import android.os.Parcel;
 
@@ -35,27 +34,31 @@
     private static final @Rule.Effect int DENY_EFFECT = Rule.DENY;
     private static final String PACKAGE_NAME = "com.test.app";
     private static final String APP_CERTIFICATE = "test_cert";
-    private static final Formula PACKAGE_NAME_ATOMIC_FORMULA =
-            new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, PACKAGE_NAME,
+    private static final IntegrityFormula PACKAGE_NAME_ATOMIC_FORMULA =
+            new AtomicFormula.StringAtomicFormula(
+                    AtomicFormula.PACKAGE_NAME,
+                    PACKAGE_NAME,
                     /* isHashedValue= */ false);
-    private static final Formula APP_CERTIFICATE_ATOMIC_FORMULA =
-            new AtomicFormula.StringAtomicFormula(AtomicFormula.APP_CERTIFICATE, APP_CERTIFICATE,
+    private static final IntegrityFormula APP_CERTIFICATE_ATOMIC_FORMULA =
+            new AtomicFormula.StringAtomicFormula(
+                    AtomicFormula.APP_CERTIFICATE,
+                    APP_CERTIFICATE,
                     /* isHashedValue= */ false);
 
     @Test
     public void testValidRule() {
         Rule validRule = new Rule(PACKAGE_NAME_ATOMIC_FORMULA, DENY_EFFECT);
 
-        assertEquals(PACKAGE_NAME_ATOMIC_FORMULA, validRule.getFormula());
-        assertEquals(DENY_EFFECT, validRule.getEffect());
+        assertThat(validRule.getFormula()).isEqualTo(PACKAGE_NAME_ATOMIC_FORMULA);
+        assertThat(validRule.getEffect()).isEqualTo(DENY_EFFECT);
     }
 
     @Test
     public void testInvalidRule_invalidFormula() {
-        assertExpectException(
-                NullPointerException.class,
-                /* expectedExceptionMessageRegex */ null,
-                () -> new Rule(null, DENY_EFFECT));
+        Exception e =
+                expectThrows(
+                        NullPointerException.class,
+                        () -> new Rule(null, DENY_EFFECT));
     }
 
     @Test
@@ -66,27 +69,23 @@
                         Arrays.asList(PACKAGE_NAME_ATOMIC_FORMULA, APP_CERTIFICATE_ATOMIC_FORMULA));
         Rule rule = new Rule(compoundFormula, Rule.DENY);
 
-        assertEquals(
-                String.format(
-                        "Rule: (PACKAGE_NAME EQ %s) AND (APP_CERTIFICATE EQ %s), DENY",
-                        PACKAGE_NAME, APP_CERTIFICATE),
-                rule.toString());
+        assertThat(rule.toString())
+                .isEqualTo(
+                        String.format(
+                                "Rule: (PACKAGE_NAME EQ %s) AND (APP_CERTIFICATE EQ %s), DENY",
+                                PACKAGE_NAME, APP_CERTIFICATE));
     }
 
     @Test
     public void testEquals_trueCase() {
-        Rule rule1 = new Rule(PACKAGE_NAME_ATOMIC_FORMULA, DENY_EFFECT);
-        Rule rule2 = new Rule(PACKAGE_NAME_ATOMIC_FORMULA, DENY_EFFECT);
-
-        assertEquals(rule1, rule2);
+        assertThat(new Rule(PACKAGE_NAME_ATOMIC_FORMULA, DENY_EFFECT))
+                .isEqualTo(new Rule(PACKAGE_NAME_ATOMIC_FORMULA, DENY_EFFECT));
     }
 
     @Test
     public void testEquals_falseCase() {
-        Rule rule1 = new Rule(PACKAGE_NAME_ATOMIC_FORMULA, DENY_EFFECT);
-        Rule rule2 = new Rule(APP_CERTIFICATE_ATOMIC_FORMULA, DENY_EFFECT);
-
-        assertNotEquals(rule1, rule2);
+        assertThat(new Rule(PACKAGE_NAME_ATOMIC_FORMULA, DENY_EFFECT))
+                .isNotEqualTo(new Rule(APP_CERTIFICATE_ATOMIC_FORMULA, DENY_EFFECT));
     }
 
     @Test
@@ -104,16 +103,16 @@
         Parcel p = Parcel.obtain();
         rule.writeToParcel(p, 0);
         p.setDataPosition(0);
-        Rule newRule = Rule.CREATOR.createFromParcel(p);
 
-        assertEquals(newRule, rule);
+        assertThat(Rule.CREATOR.createFromParcel(p)).isEqualTo(rule);
     }
 
     @Test
     public void testInvalidRule_invalidEffect() {
-        assertExpectException(
-                IllegalArgumentException.class,
-                /* expectedExceptionMessageRegex */ "Unknown effect: -1",
-                () -> new Rule(PACKAGE_NAME_ATOMIC_FORMULA, /* effect= */ -1));
+        Exception e =
+                expectThrows(
+                        IllegalArgumentException.class,
+                        () -> new Rule(PACKAGE_NAME_ATOMIC_FORMULA, /* effect= */ -1));
+        assertThat(e.getMessage()).isEqualTo("Unknown effect: -1");
     }
 }
diff --git a/core/tests/coretests/src/android/content/integrity/TestUtils.java b/core/tests/coretests/src/android/content/integrity/TestUtils.java
deleted file mode 100644
index af984cf..0000000
--- a/core/tests/coretests/src/android/content/integrity/TestUtils.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.content.integrity;
-
-import android.test.MoreAsserts;
-
-import junit.framework.Assert;
-
-/** Helper methods used in tests. */
-class TestUtils {
-    private TestUtils() {}
-
-    public interface ExceptionRunnable {
-        void run() throws Exception;
-    }
-
-    public static void assertExpectException(
-            Class<? extends Throwable> expectedExceptionType,
-            String expectedExceptionMessageRegex,
-            ExceptionRunnable r) {
-        try {
-            r.run();
-        } catch (Throwable e) {
-            Assert.assertTrue(
-                    "Expected exception type was "
-                            + expectedExceptionType.getName()
-                            + " but caught "
-                            + e.getClass().getName(),
-                    expectedExceptionType.isAssignableFrom(e.getClass()));
-            if (expectedExceptionMessageRegex != null) {
-                MoreAsserts.assertContainsRegex(expectedExceptionMessageRegex, e.getMessage());
-            }
-            return; // Pass.
-        }
-        Assert.fail(
-                "Expected exception type " + expectedExceptionType.getName() + " was not thrown");
-    }
-}
diff --git a/core/tests/coretests/src/android/content/pm/PackageParserTest.java b/core/tests/coretests/src/android/content/pm/PackageParserTest.java
index 47c4286..dfd762b 100644
--- a/core/tests/coretests/src/android/content/pm/PackageParserTest.java
+++ b/core/tests/coretests/src/android/content/pm/PackageParserTest.java
@@ -470,7 +470,7 @@
         PackageParser.collectCertificates(p, false);
         PackageInfo pi = PackageParser.generatePackageInfo(p, apexInfo, flags);
 
-        assertEquals("com.google.android.tzdata2", pi.applicationInfo.packageName);
+        assertEquals("com.google.android.tzdata", pi.applicationInfo.packageName);
         assertTrue(pi.applicationInfo.enabled);
         assertEquals(28, pi.applicationInfo.targetSdkVersion);
         assertEquals(191000070, pi.applicationInfo.longVersionCode);
@@ -479,7 +479,7 @@
         assertEquals("Bundle[{com.android.vending.derived.apk.id=1}]",
                 pi.applicationInfo.metaData.toString());
 
-        assertEquals("com.google.android.tzdata2", pi.packageName);
+        assertEquals("com.google.android.tzdata", pi.packageName);
         assertEquals(191000070, pi.getLongVersionCode());
         assertNotNull(pi.signingInfo);
         assertTrue(pi.signingInfo.getApkContentsSigners().length > 0);
diff --git a/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java b/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
index 895b22c..4370462 100644
--- a/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
+++ b/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
@@ -132,7 +132,7 @@
         BrightnessConfiguration.Builder builder =
                 new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
         builder.setShouldCollectColorSamples(true);
-        builder.setShortTermModelTimeout(1234L);
+        builder.setShortTermModelTimeoutMillis(1234L);
         builder.setShortTermModelLowerLuxMultiplier(0.9f);
         builder.setShortTermModelUpperLuxMultiplier(0.2f);
         builder.addCorrectionByCategory(3,
@@ -153,7 +153,7 @@
         BrightnessConfiguration.Builder builder =
                 new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
         builder.setShouldCollectColorSamples(true);
-        builder.setShortTermModelTimeout(123L);
+        builder.setShortTermModelTimeoutMillis(123L);
         builder.setShortTermModelLowerLuxMultiplier(0.4f);
         builder.setShortTermModelUpperLuxMultiplier(0.8f);
         builder.addCorrectionByCategory(3,
@@ -236,7 +236,7 @@
         assertNotEquals(baseConfig, colorCollectionDiffers);
 
         builder = new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
-        builder.setShortTermModelTimeout(300L);
+        builder.setShortTermModelTimeoutMillis(300L);
         BrightnessConfiguration timeoutDiffers = builder.build();
         assertNotEquals(baseConfig, timeoutDiffers);
 
diff --git a/core/tests/coretests/src/android/provider/NameValueCacheTest.java b/core/tests/coretests/src/android/provider/NameValueCacheTest.java
new file mode 100644
index 0000000..4212ef2
--- /dev/null
+++ b/core/tests/coretests/src/android/provider/NameValueCacheTest.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.content.ContentProvider;
+import android.content.IContentProvider;
+import android.os.Bundle;
+import android.platform.test.annotations.Presubmit;
+import android.test.mock.MockContentResolver;
+import android.util.MemoryIntArray;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * These tests are verifying that Settings#NameValueCache is working as expected with DeviceConfig.
+ * Due to how the classes are structured, we have to test it in a somewhat roundabout way. We're
+ * mocking out the contentProvider and are handcrafting very specific Bundles to answer the queries.
+ */
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class NameValueCacheTest {
+
+    private static final String NAMESPACE = "namespace";
+    private static final String NAMESPACE2 = "namespace2";
+
+    @Mock
+    private IContentProvider mMockIContentProvider;
+    @Mock
+    private ContentProvider mMockContentProvider;
+    private MockContentResolver mMockContentResolver;
+    private MemoryIntArray mCacheGenerationStore;
+    private int mCurrentGeneration = 123;
+
+    private HashMap<String, HashMap<String, String>> mStorage;
+
+    @Before
+    public void setUp() throws Exception {
+        Settings.Config.clearProviderForTest();
+        MockitoAnnotations.initMocks(this);
+        when(mMockContentProvider.getIContentProvider()).thenReturn(mMockIContentProvider);
+        mMockContentResolver = new MockContentResolver();
+        mMockContentResolver.addProvider(DeviceConfig.CONTENT_URI.getAuthority(),
+                mMockContentProvider);
+        mCacheGenerationStore = new MemoryIntArray(1);
+        mStorage = new HashMap<>();
+
+        // Stores keyValues for a given prefix and increments the generation. (Note that this
+        // increments the generation no matter what, it doesn't pay attention to if anything
+        // actually changed).
+        when(mMockIContentProvider.call(any(), any(), eq(DeviceConfig.CONTENT_URI.getAuthority()),
+                eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
+                any(), any(Bundle.class))).thenAnswer(invocationOnMock -> {
+                    Bundle incomingBundle = invocationOnMock.getArgument(5);
+                    HashMap<String, String> keyValues =
+                            (HashMap<String, String>) incomingBundle.getSerializable(
+                                    Settings.CALL_METHOD_FLAGS_KEY);
+                    String prefix = incomingBundle.getString(Settings.CALL_METHOD_PREFIX_KEY);
+                    mStorage.put(prefix, keyValues);
+                    mCacheGenerationStore.set(0, ++mCurrentGeneration);
+
+                    Bundle result = new Bundle();
+                    result.putBoolean(Settings.KEY_CONFIG_SET_RETURN, true);
+                    return result;
+                });
+
+        // Returns the keyValues corresponding to a namespace, or an empty map if the namespace
+        // doesn't have anything stored for it. Returns the generation key if the caller asked
+        // for one.
+        when(mMockIContentProvider.call(any(), any(), eq(DeviceConfig.CONTENT_URI.getAuthority()),
+                eq(Settings.CALL_METHOD_LIST_CONFIG),
+                any(), any(Bundle.class))).thenAnswer(invocationOnMock -> {
+                    Bundle incomingBundle = invocationOnMock.getArgument(5);
+
+                    String prefix = incomingBundle.getString(Settings.CALL_METHOD_PREFIX_KEY);
+
+                    if (!mStorage.containsKey(prefix)) {
+                        mStorage.put(prefix, new HashMap<>());
+                    }
+                    HashMap<String, String> keyValues = mStorage.get(prefix);
+
+                    Bundle bundle = new Bundle();
+                    bundle.putSerializable(Settings.NameValueTable.VALUE, keyValues);
+
+                    if (incomingBundle.containsKey(Settings.CALL_METHOD_TRACK_GENERATION_KEY)) {
+                        bundle.putParcelable(Settings.CALL_METHOD_TRACK_GENERATION_KEY,
+                                mCacheGenerationStore);
+                        bundle.putInt(Settings.CALL_METHOD_GENERATION_INDEX_KEY, 0);
+                        bundle.putInt(Settings.CALL_METHOD_GENERATION_KEY,
+                                mCacheGenerationStore.get(0));
+                    }
+                    return bundle;
+                });
+    }
+
+    @Test
+    public void testCaching_singleNamespace() throws Exception {
+        HashMap<String, String> keyValues = new HashMap<>();
+        keyValues.put("a", "b");
+        Settings.Config.setStrings(mMockContentResolver, NAMESPACE, keyValues);
+        verify(mMockIContentProvider).call(any(), any(), any(),
+                eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
+                any(), any(Bundle.class));
+
+        Map<String, String> returnedValues = Settings.Config.getStrings(mMockContentResolver,
+                NAMESPACE,
+                Collections.emptyList());
+        verify(mMockIContentProvider).call(any(), any(), any(),
+                eq(Settings.CALL_METHOD_LIST_CONFIG),
+                any(), any(Bundle.class));
+        assertThat(returnedValues).containsExactlyEntriesIn(keyValues);
+
+        Map<String, String> cachedKeyValues = Settings.Config.getStrings(mMockContentResolver,
+                NAMESPACE, Collections.emptyList());
+        verifyNoMoreInteractions(mMockIContentProvider);
+        assertThat(cachedKeyValues).containsExactlyEntriesIn(keyValues);
+
+        // Modify the value to invalidate the cache.
+        keyValues.put("a", "c");
+        Settings.Config.setStrings(mMockContentResolver, NAMESPACE, keyValues);
+        verify(mMockIContentProvider, times(2)).call(any(), any(), any(),
+                eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
+                any(), any(Bundle.class));
+
+        Map<String, String> returnedValues2 = Settings.Config.getStrings(mMockContentResolver,
+                NAMESPACE, Collections.emptyList());
+        verify(mMockIContentProvider, times(2)).call(any(), any(), any(),
+                eq(Settings.CALL_METHOD_LIST_CONFIG),
+                any(), any(Bundle.class));
+        assertThat(returnedValues2).containsExactlyEntriesIn(keyValues);
+
+        Map<String, String> cachedKeyValues2 = Settings.Config.getStrings(mMockContentResolver,
+                NAMESPACE, Collections.emptyList());
+        verifyNoMoreInteractions(mMockIContentProvider);
+        assertThat(cachedKeyValues2).containsExactlyEntriesIn(keyValues);
+    }
+
+    @Test
+    public void testCaching_multipleNamespaces() throws Exception {
+        HashMap<String, String> keyValues = new HashMap<>();
+        keyValues.put("a", "b");
+        Settings.Config.setStrings(mMockContentResolver, NAMESPACE, keyValues);
+        verify(mMockIContentProvider).call(any(), any(), any(),
+                eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
+                any(), any(Bundle.class));
+
+        HashMap<String, String> keyValues2 = new HashMap<>();
+        keyValues2.put("c", "d");
+        keyValues2.put("e", "f");
+        Settings.Config.setStrings(mMockContentResolver, NAMESPACE2, keyValues2);
+        verify(mMockIContentProvider, times(2)).call(any(), any(), any(),
+                eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
+                any(), any(Bundle.class));
+
+        Map<String, String> returnedValues = Settings.Config.getStrings(mMockContentResolver,
+                NAMESPACE,
+                Collections.emptyList());
+        verify(mMockIContentProvider).call(any(), any(), any(),
+                eq(Settings.CALL_METHOD_LIST_CONFIG),
+                any(), any(Bundle.class));
+        assertThat(returnedValues).containsExactlyEntriesIn(keyValues);
+
+        Map<String, String> returnedValues2 = Settings.Config.getStrings(mMockContentResolver,
+                NAMESPACE2,
+                Collections.emptyList());
+        verify(mMockIContentProvider, times(2)).call(any(), any(), any(),
+                eq(Settings.CALL_METHOD_LIST_CONFIG),
+                any(), any(Bundle.class));
+        assertThat(returnedValues2).containsExactlyEntriesIn(keyValues2);
+
+        Map<String, String> cachedKeyValues = Settings.Config.getStrings(mMockContentResolver,
+                NAMESPACE, Collections.emptyList());
+        verifyNoMoreInteractions(mMockIContentProvider);
+        assertThat(cachedKeyValues).containsExactlyEntriesIn(keyValues);
+
+        Map<String, String> cachedKeyValues2 = Settings.Config.getStrings(mMockContentResolver,
+                NAMESPACE2, Collections.emptyList());
+        verifyNoMoreInteractions(mMockIContentProvider);
+        assertThat(cachedKeyValues2).containsExactlyEntriesIn(keyValues2);
+    }
+
+    @Test
+    public void testCaching_emptyNamespace() throws Exception {
+        Map<String, String> returnedValues = Settings.Config.getStrings(mMockContentResolver,
+                NAMESPACE,
+                Collections.emptyList());
+        verify(mMockIContentProvider).call(any(), any(), any(),
+                eq(Settings.CALL_METHOD_LIST_CONFIG),
+                any(), any(Bundle.class));
+        assertThat(returnedValues).isEmpty();
+
+        Map<String, String> cachedKeyValues = Settings.Config.getStrings(mMockContentResolver,
+                NAMESPACE, Collections.emptyList());
+        verifyNoMoreInteractions(mMockIContentProvider);
+        assertThat(cachedKeyValues).isEmpty();
+    }
+
+}
diff --git a/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java b/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java
new file mode 100644
index 0000000..2648a06
--- /dev/null
+++ b/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.controls;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.PendingIntent;
+import android.content.IIntentSender;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.service.controls.actions.CommandAction;
+import android.service.controls.actions.ControlAction;
+import android.service.controls.actions.ControlActionWrapper;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.Flow.Publisher;
+import java.util.concurrent.Flow.Subscriber;
+import java.util.concurrent.Flow.Subscription;
+import java.util.function.Consumer;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ControlProviderServiceTest {
+
+    private IBinder mToken = new Binder();
+    @Mock
+    private IControlsActionCallback.Stub mActionCallback;
+    @Mock
+    private IControlsLoadCallback.Stub mLoadCallback;
+    @Mock
+    private IControlsSubscriber.Stub mSubscriber;
+    @Mock
+    private IIntentSender mIIntentSender;
+
+    private PendingIntent mPendingIntent;
+    private FakeControlsProviderService mControlsProviderService;
+
+    private IControlsProvider mControlsProvider;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        when(mActionCallback.asBinder()).thenCallRealMethod();
+        when(mActionCallback.queryLocalInterface(any())).thenReturn(mActionCallback);
+        when(mLoadCallback.asBinder()).thenCallRealMethod();
+        when(mLoadCallback.queryLocalInterface(any())).thenReturn(mLoadCallback);
+        when(mSubscriber.asBinder()).thenCallRealMethod();
+        when(mSubscriber.queryLocalInterface(any())).thenReturn(mSubscriber);
+
+        Bundle b = new Bundle();
+        b.putBinder(ControlsProviderService.CALLBACK_TOKEN, mToken);
+        Intent intent = new Intent();
+        intent.putExtra(ControlsProviderService.CALLBACK_BUNDLE, b);
+
+        mPendingIntent = new PendingIntent(mIIntentSender);
+
+        mControlsProviderService = new FakeControlsProviderService();
+        mControlsProvider = IControlsProvider.Stub.asInterface(
+                mControlsProviderService.onBind(intent));
+    }
+
+    @Test
+    public void testOnLoad_allStateless() throws RemoteException {
+        Control control1 = new Control.StatelessBuilder("TEST_ID", mPendingIntent).build();
+        Control control2 = new Control.StatelessBuilder("TEST_ID_2", mPendingIntent)
+                .setDeviceType(DeviceTypes.TYPE_AIR_FRESHENER).build();
+
+        @SuppressWarnings("unchecked")
+        ArgumentCaptor<List<Control>> captor = ArgumentCaptor.forClass(List.class);
+
+        ArrayList<Control> list = new ArrayList<>();
+        list.add(control1);
+        list.add(control2);
+
+        mControlsProviderService.setControls(list);
+        mControlsProvider.load(mLoadCallback);
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+        verify(mLoadCallback).accept(eq(mToken), captor.capture());
+        List<Control> l = captor.getValue();
+        assertEquals(2, l.size());
+        assertTrue(equals(control1, l.get(0)));
+        assertTrue(equals(control2, l.get(1)));
+    }
+
+    @Test
+    public void testOnLoad_statefulConvertedToStateless() throws RemoteException {
+        Control control = new Control.StatefulBuilder("TEST_ID", mPendingIntent)
+                .setTitle("TEST_TITLE")
+                .setStatus(Control.STATUS_OK)
+                .build();
+        Control statelessControl = new Control.StatelessBuilder(control).build();
+
+        @SuppressWarnings("unchecked")
+        ArgumentCaptor<List<Control>> captor = ArgumentCaptor.forClass(List.class);
+
+        ArrayList<Control> list = new ArrayList<>();
+        list.add(control);
+
+        mControlsProviderService.setControls(list);
+        mControlsProvider.load(mLoadCallback);
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+        verify(mLoadCallback).accept(eq(mToken), captor.capture());
+        List<Control> l = captor.getValue();
+        assertEquals(1, l.size());
+        assertFalse(equals(control, l.get(0)));
+        assertTrue(equals(statelessControl, l.get(0)));
+        assertEquals(Control.STATUS_UNKNOWN, l.get(0).getStatus());
+    }
+
+    @Test
+    public void testSubscribe() throws RemoteException {
+        Control control = new Control.StatefulBuilder("TEST_ID", mPendingIntent)
+                .setTitle("TEST_TITLE")
+                .setStatus(Control.STATUS_OK)
+                .build();
+
+        @SuppressWarnings("unchecked")
+        ArgumentCaptor<Control> controlCaptor =
+                ArgumentCaptor.forClass(Control.class);
+        ArgumentCaptor<IControlsSubscription.Stub> subscriptionCaptor =
+                ArgumentCaptor.forClass(IControlsSubscription.Stub.class);
+
+        ArrayList<Control> list = new ArrayList<>();
+        list.add(control);
+
+        mControlsProviderService.setControls(list);
+
+        mControlsProvider.subscribe(new ArrayList<String>(), mSubscriber);
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+        verify(mSubscriber).onSubscribe(eq(mToken), subscriptionCaptor.capture());
+        subscriptionCaptor.getValue().request(1);
+
+        verify(mSubscriber).onNext(eq(mToken), controlCaptor.capture());
+        Control c = controlCaptor.getValue();
+        assertTrue(equals(c, list.get(0)));
+    }
+
+    @Test
+    public void testOnAction() throws RemoteException {
+        mControlsProvider.action("TEST_ID", new ControlActionWrapper(
+                new CommandAction("", null)), mActionCallback);
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+        verify(mActionCallback).accept(mToken, "TEST_ID",
+                ControlAction.RESPONSE_OK);
+    }
+
+    private static boolean equals(Control c1, Control c2) {
+        if (c1 == c2) return true;
+        if (c1 == null || c2 == null) return false;
+        return Objects.equals(c1.getControlId(), c2.getControlId())
+                && c1.getDeviceType() == c2.getDeviceType()
+                && Objects.equals(c1.getTitle(), c2.getTitle())
+                && Objects.equals(c1.getSubtitle(), c2.getSubtitle())
+                && Objects.equals(c1.getStructure(), c2.getStructure())
+                && Objects.equals(c1.getZone(), c2.getZone())
+                && Objects.equals(c1.getAppIntent(), c2.getAppIntent())
+                && Objects.equals(c1.getCustomIcon(), c2.getCustomIcon())
+                && Objects.equals(c1.getCustomColor(), c2.getCustomColor())
+                && c1.getStatus() == c2.getStatus()
+                && Objects.equals(c1.getControlTemplate(), c2.getControlTemplate())
+                && Objects.equals(c1.getStatusText(), c2.getStatusText());
+    }
+
+    static class FakeControlsProviderService extends ControlsProviderService {
+
+        private List<Control> mControls;
+
+        public void setControls(List<Control> controls) {
+            mControls = controls;
+        }
+
+        @Override
+        public void loadAvailableControls(Consumer<List<Control>> cb) {
+            cb.accept(mControls);
+        }
+
+        @Override
+        public Publisher<Control> publisherFor(List<String> ids) {
+            return new Publisher<Control>() {
+                public void subscribe(final Subscriber s) {
+                    s.onSubscribe(new Subscription() {
+                            public void request(long n) {
+                                for (Control c : mControls) {
+                                    s.onNext(c);
+                                }
+                            }
+                            public void cancel() {}
+                        });
+                }
+            };
+        }
+
+        @Override
+        public void performControlAction(String controlId, ControlAction action,
+                Consumer<Integer> cb) {
+            cb.accept(ControlAction.RESPONSE_OK);
+        }
+    }
+}
+
+
diff --git a/core/tests/coretests/src/android/service/controls/ControlActionTest.java b/core/tests/coretests/src/android/service/controls/actions/ControlActionTest.java
similarity index 84%
rename from core/tests/coretests/src/android/service/controls/ControlActionTest.java
rename to core/tests/coretests/src/android/service/controls/actions/ControlActionTest.java
index d0264da..10a7b76 100644
--- a/core/tests/coretests/src/android/service/controls/ControlActionTest.java
+++ b/core/tests/coretests/src/android/service/controls/actions/ControlActionTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.service.controls;
+package android.service.controls.actions;
 
 import static junit.framework.Assert.assertTrue;
 
@@ -22,12 +22,6 @@
 import static org.junit.Assert.assertNotNull;
 
 import android.os.Parcel;
-import android.service.controls.actions.BooleanAction;
-import android.service.controls.actions.CommandAction;
-import android.service.controls.actions.ControlAction;
-import android.service.controls.actions.FloatAction;
-import android.service.controls.actions.ModeAction;
-import android.service.controls.actions.MultiFloatAction;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
@@ -97,9 +91,9 @@
         assertNotNull(parcel);
 
         parcel.setDataPosition(0);
-        toParcel.writeToParcel(parcel, 0);
+        new ControlActionWrapper(toParcel).writeToParcel(parcel, 0);
         parcel.setDataPosition(0);
 
-        return ControlAction.CREATOR.createFromParcel(parcel);
+        return ControlActionWrapper.CREATOR.createFromParcel(parcel).getWrappedAction();
     }
 }
diff --git a/core/tests/coretests/src/android/service/controls/ControlTemplateTest.java b/core/tests/coretests/src/android/service/controls/templates/ControlTemplateTest.java
similarity index 71%
rename from core/tests/coretests/src/android/service/controls/ControlTemplateTest.java
rename to core/tests/coretests/src/android/service/controls/templates/ControlTemplateTest.java
index 2756891..c9b5eec 100644
--- a/core/tests/coretests/src/android/service/controls/ControlTemplateTest.java
+++ b/core/tests/coretests/src/android/service/controls/templates/ControlTemplateTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.service.controls;
+package android.service.controls.templates;
 
 import static junit.framework.Assert.assertTrue;
 
@@ -24,16 +24,6 @@
 import android.annotation.DrawableRes;
 import android.graphics.drawable.Icon;
 import android.os.Parcel;
-import android.service.controls.templates.ControlButton;
-import android.service.controls.templates.ControlTemplate;
-import android.service.controls.templates.CoordinatedRangeTemplate;
-import android.service.controls.templates.DiscreteToggleTemplate;
-import android.service.controls.templates.RangeTemplate;
-import android.service.controls.templates.StatelessTemplate;
-import android.service.controls.templates.TemperatureControlTemplate;
-import android.service.controls.templates.ThumbnailTemplate;
-import android.service.controls.templates.ToggleRangeTemplate;
-import android.service.controls.templates.ToggleTemplate;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
@@ -65,8 +55,7 @@
 
     @Test
     public void testUnparcelingCorrectClass_none() {
-        ControlTemplate
-                toParcel = ControlTemplate.NO_TEMPLATE;
+        ControlTemplate toParcel = ControlTemplate.NO_TEMPLATE;
 
         ControlTemplate fromParcel = parcelAndUnparcel(toParcel);
 
@@ -75,8 +64,7 @@
 
     @Test
     public void testUnparcelingCorrectClass_toggle() {
-        ControlTemplate
-                toParcel = new android.service.controls.templates.ToggleTemplate(TEST_ID, mControlButton);
+        ControlTemplate toParcel = new ToggleTemplate(TEST_ID, mControlButton);
 
         ControlTemplate fromParcel = parcelAndUnparcel(toParcel);
 
@@ -86,8 +74,7 @@
 
     @Test
     public void testUnparcelingCorrectClass_range() {
-        ControlTemplate
-                toParcel = new RangeTemplate(TEST_ID, 0, 2, 1, 1, "%f");
+        ControlTemplate toParcel = new RangeTemplate(TEST_ID, 0, 2, 1, 1, "%f");
 
         ControlTemplate fromParcel = parcelAndUnparcel(toParcel);
 
@@ -117,8 +104,7 @@
 
     @Test
     public void testUnparcelingCorrectClass_thumbnail() {
-        ControlTemplate
-                toParcel = new ThumbnailTemplate(TEST_ID, mIcon, TEST_ACTION_DESCRIPTION);
+        ControlTemplate toParcel = new ThumbnailTemplate(TEST_ID, mIcon, TEST_ACTION_DESCRIPTION);
 
         ControlTemplate fromParcel = parcelAndUnparcel(toParcel);
 
@@ -140,7 +126,7 @@
     @Test
     public void testUnparcelingCorrectClass_coordRange() {
         ControlTemplate toParcel =
-                new CoordinatedRangeTemplate(TEST_ID,0.1f,  0, 1, 0.5f, 1, 2, 1.5f, 0.1f, "%f");
+                new CoordinatedRangeTemplate(TEST_ID, 0.1f,  0, 1, 0.5f, 1, 2, 1.5f, 0.1f, "%f");
         ControlTemplate fromParcel = parcelAndUnparcel(toParcel);
         assertEquals(ControlTemplate.TYPE_COORD_RANGE, fromParcel.getTemplateType());
         assertTrue(fromParcel instanceof CoordinatedRangeTemplate);
@@ -149,7 +135,7 @@
     @Test
     public void testCoordRangeParameters_negativeMinGap() {
         CoordinatedRangeTemplate template =
-                new CoordinatedRangeTemplate(TEST_ID,-0.1f,  0, 1, 0.5f, 1, 2, 1.5f, 0.1f, "%f");
+                new CoordinatedRangeTemplate(TEST_ID, -0.1f,  0, 1, 0.5f, 1, 2, 1.5f, 0.1f, "%f");
         assertEquals(0, template.getMinGap(), 0);
     }
 
@@ -176,9 +162,8 @@
 
     @Test
     public void testUnparcelingCorrectClass_toggleRange() {
-        ControlTemplate toParcel =
-                new ToggleRangeTemplate(TEST_ID, mControlButton,
-                        new RangeTemplate(TEST_ID, 0, 2, 1, 1, "%f"));
+        ControlTemplate toParcel = new ToggleRangeTemplate(TEST_ID, mControlButton,
+                new RangeTemplate(TEST_ID, 0, 2, 1, 1, "%f"));
 
         ControlTemplate fromParcel = parcelAndUnparcel(toParcel);
 
@@ -198,11 +183,12 @@
 
     @Test
     public void testUnparcelingCorrectClass_thermostat() {
-        ControlTemplate toParcel = new TemperatureControlTemplate(TEST_ID,
-            new ToggleTemplate("", mControlButton),
-            TemperatureControlTemplate.MODE_OFF,
-            TemperatureControlTemplate.MODE_OFF,
-            TemperatureControlTemplate.FLAG_MODE_OFF);
+        ControlTemplate toParcel = new TemperatureControlTemplate(
+                TEST_ID,
+                new ToggleTemplate("", mControlButton),
+                TemperatureControlTemplate.MODE_OFF,
+                TemperatureControlTemplate.MODE_OFF,
+                TemperatureControlTemplate.FLAG_MODE_OFF);
 
         ControlTemplate fromParcel = parcelAndUnparcel(toParcel);
 
@@ -212,48 +198,70 @@
 
     @Test
     public void testThermostatParams_wrongMode() {
-        TemperatureControlTemplate thermostat = new TemperatureControlTemplate(TEST_ID, ControlTemplate.NO_TEMPLATE, -1,
-                TemperatureControlTemplate.MODE_OFF, TemperatureControlTemplate.FLAG_MODE_OFF);
+        TemperatureControlTemplate thermostat = new TemperatureControlTemplate(
+                TEST_ID,
+                ControlTemplate.NO_TEMPLATE,
+                -1,
+                TemperatureControlTemplate.MODE_OFF,
+                TemperatureControlTemplate.FLAG_MODE_OFF);
         assertEquals(TemperatureControlTemplate.MODE_UNKNOWN, thermostat.getCurrentMode());
 
-        thermostat = new TemperatureControlTemplate(TEST_ID, ControlTemplate.NO_TEMPLATE, 100,
-                TemperatureControlTemplate.MODE_OFF, TemperatureControlTemplate.FLAG_MODE_OFF);
+        thermostat = new TemperatureControlTemplate(
+                TEST_ID,
+                ControlTemplate.NO_TEMPLATE,
+                100,
+                TemperatureControlTemplate.MODE_OFF,
+                TemperatureControlTemplate.FLAG_MODE_OFF);
         assertEquals(TemperatureControlTemplate.MODE_UNKNOWN, thermostat.getCurrentMode());
     }
 
     @Test
     public void testThermostatParams_wrongActiveMode() {
-        TemperatureControlTemplate thermostat = new TemperatureControlTemplate(TEST_ID, ControlTemplate.NO_TEMPLATE,
-                TemperatureControlTemplate.MODE_OFF,-1, TemperatureControlTemplate.FLAG_MODE_OFF);
+        TemperatureControlTemplate thermostat = new TemperatureControlTemplate(
+                TEST_ID,
+                ControlTemplate.NO_TEMPLATE,
+                TemperatureControlTemplate.MODE_OFF,
+                -1,
+                TemperatureControlTemplate.FLAG_MODE_OFF);
         assertEquals(TemperatureControlTemplate.MODE_UNKNOWN, thermostat.getCurrentActiveMode());
 
-        thermostat = new TemperatureControlTemplate(TEST_ID, ControlTemplate.NO_TEMPLATE,
-                TemperatureControlTemplate.MODE_OFF,100, TemperatureControlTemplate.FLAG_MODE_OFF);
+        thermostat = new TemperatureControlTemplate(
+                TEST_ID,
+                ControlTemplate.NO_TEMPLATE,
+                TemperatureControlTemplate.MODE_OFF,
+                100,
+                TemperatureControlTemplate.FLAG_MODE_OFF);
         assertEquals(TemperatureControlTemplate.MODE_UNKNOWN, thermostat.getCurrentActiveMode());
     }
 
     @Test(expected = IllegalArgumentException.class)
     public void testThermostatParams_wrongFlags_currentMode() {
-        new TemperatureControlTemplate(TEST_ID, ControlTemplate.NO_TEMPLATE, TemperatureControlTemplate.MODE_HEAT,
-                TemperatureControlTemplate.MODE_OFF, TemperatureControlTemplate.FLAG_MODE_OFF);
+        new TemperatureControlTemplate(
+                TEST_ID,
+                ControlTemplate.NO_TEMPLATE,
+                TemperatureControlTemplate.MODE_HEAT,
+                TemperatureControlTemplate.MODE_OFF,
+                TemperatureControlTemplate.FLAG_MODE_OFF);
     }
 
     @Test(expected = IllegalArgumentException.class)
     public void testThermostatParams_wrongFlags_currentActiveMode() {
-        new TemperatureControlTemplate(TEST_ID, ControlTemplate.NO_TEMPLATE, TemperatureControlTemplate.MODE_HEAT,
-                TemperatureControlTemplate.MODE_OFF, TemperatureControlTemplate.FLAG_MODE_HEAT);
+        new TemperatureControlTemplate(TEST_ID,
+                ControlTemplate.NO_TEMPLATE,
+                TemperatureControlTemplate.MODE_HEAT,
+                TemperatureControlTemplate.MODE_OFF,
+                TemperatureControlTemplate.FLAG_MODE_HEAT);
     }
 
-    private ControlTemplate parcelAndUnparcel(
-            ControlTemplate toParcel) {
+    private ControlTemplate parcelAndUnparcel(ControlTemplate toParcel) {
         Parcel parcel = Parcel.obtain();
 
         assertNotNull(parcel);
 
         parcel.setDataPosition(0);
-        toParcel.writeToParcel(parcel, 0);
+        new ControlTemplateWrapper(toParcel).writeToParcel(parcel, 0);
         parcel.setDataPosition(0);
 
-        return ControlTemplate.CREATOR.createFromParcel(parcel);
+        return ControlTemplateWrapper.CREATOR.createFromParcel(parcel).getWrappedTemplate();
     }
 }
diff --git a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
index bcf0b8c..169716f 100644
--- a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
+++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
@@ -176,8 +176,6 @@
         when(mMockController.getState()).thenReturn(mInsetsState);
         mController.finish(true /* shown */);
         mController.applyChangeInsets(mInsetsState);
-        assertTrue(mInsetsState.getSource(ITYPE_STATUS_BAR).isVisible());
-        assertTrue(mInsetsState.getSource(ITYPE_NAVIGATION_BAR).isVisible());
         assertEquals(Insets.of(0, 100, 100, 0), mController.getCurrentInsets());
         verify(mMockController).notifyFinished(eq(mController), eq(true /* shown */));
     }
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index f720c98..e68c4b8 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -19,10 +19,13 @@
 import static android.view.InsetsController.ANIMATION_TYPE_HIDE;
 import static android.view.InsetsController.ANIMATION_TYPE_NONE;
 import static android.view.InsetsController.ANIMATION_TYPE_SHOW;
+import static android.view.InsetsSourceConsumer.ShowResult.IME_SHOW_DELAYED;
+import static android.view.InsetsSourceConsumer.ShowResult.SHOW_IMMEDIATELY;
 import static android.view.InsetsState.ITYPE_IME;
 import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
 import static android.view.InsetsState.ITYPE_STATUS_BAR;
 import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
+import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowInsets.Type.statusBars;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
 
@@ -32,6 +35,8 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.notNull;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
@@ -41,6 +46,7 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
+import android.view.SurfaceControl.Transaction;
 import android.view.WindowInsets.Type;
 import android.view.WindowManager.BadTokenException;
 import android.view.WindowManager.LayoutParams;
@@ -48,6 +54,9 @@
 import android.view.test.InsetsModeSession;
 import android.widget.TextView;
 
+import com.android.server.testutils.OffsettableClock;
+import com.android.server.testutils.TestHandler;
+
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
@@ -59,6 +68,7 @@
 import org.mockito.ArgumentCaptor;
 
 import java.util.concurrent.CountDownLatch;
+import java.util.function.Supplier;
 
 /**
  * Tests for {@link InsetsController}.
@@ -77,6 +87,8 @@
     private SurfaceSession mSession = new SurfaceSession();
     private SurfaceControl mLeash;
     private ViewRootImpl mViewRoot;
+    private TestHandler mTestHandler;
+    private OffsettableClock mTestClock;
     private static InsetsModeSession sInsetsModeSession;
 
     @BeforeClass
@@ -103,7 +115,26 @@
             } catch (BadTokenException e) {
                 // activity isn't running, we will ignore BadTokenException.
             }
-            mController = new InsetsController(mViewRoot);
+            mTestClock = new OffsettableClock();
+            mTestHandler = new TestHandler(null, mTestClock);
+            mController = new InsetsController(mViewRoot, (controller, type) -> {
+                if (type == ITYPE_IME) {
+                    return new InsetsSourceConsumer(type, controller.getState(),
+                            Transaction::new, controller) {
+                        @Override
+                        public int requestShow(boolean fromController) {
+                            if (fromController) {
+                                return SHOW_IMMEDIATELY;
+                            } else {
+                                return IME_SHOW_DELAYED;
+                            }
+                        }
+                    };
+                } else {
+                    return new InsetsSourceConsumer(type, controller.getState(), Transaction::new,
+                            controller);
+                }
+            }, mTestHandler);
             final Rect rect = new Rect(5, 5, 5, 5);
             mController.getState().getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 10));
             mController.getState().getSource(ITYPE_NAVIGATION_BAR).setFrame(
@@ -395,6 +426,71 @@
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
     }
 
+    @Test
+    public void testControlImeNotReady() {
+        prepareControls();
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+            WindowInsetsAnimationControlListener listener =
+                    mock(WindowInsetsAnimationControlListener.class);
+            mController.controlInputMethodAnimation(0, new LinearInterpolator(), listener);
+
+            // Ready gets deferred until next predraw
+            mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw();
+
+            verify(listener, never()).onReady(any(), anyInt());
+
+            // Pretend that IME is calling.
+            mController.show(ime(), true);
+
+            // Ready gets deferred until next predraw
+            mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw();
+
+            verify(listener).onReady(notNull(), eq(ime()));
+
+        });
+    }
+
+    @Test
+    public void testControlImeNotReady_controlRevoked() {
+        prepareControls();
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+            WindowInsetsAnimationControlListener listener =
+                    mock(WindowInsetsAnimationControlListener.class);
+            mController.controlInputMethodAnimation(0, new LinearInterpolator(), listener);
+
+            // Ready gets deferred until next predraw
+            mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw();
+
+            verify(listener, never()).onReady(any(), anyInt());
+
+            // Pretend that we are losing control
+            mController.onControlsChanged(new InsetsSourceControl[0]);
+
+            verify(listener).onCancelled();
+        });
+    }
+
+    @Test
+    public void testControlImeNotReady_timeout() {
+        prepareControls();
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+            WindowInsetsAnimationControlListener listener =
+                    mock(WindowInsetsAnimationControlListener.class);
+            mController.controlInputMethodAnimation(0, new LinearInterpolator(), listener);
+
+            // Ready gets deferred until next predraw
+            mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw();
+
+            verify(listener, never()).onReady(any(), anyInt());
+
+            // Pretend that timeout is happening
+            mTestClock.fastForward(2500);
+            mTestHandler.timeAdvance();
+
+            verify(listener).onCancelled();
+        });
+    }
+
     private void waitUntilNextFrame() throws Exception {
         final CountDownLatch latch = new CountDownLatch(1);
         Choreographer.getMainThreadInstance().postCallback(Choreographer.CALLBACK_COMMIT,
diff --git a/core/tests/coretests/src/android/view/KeyEventTest.java b/core/tests/coretests/src/android/view/KeyEventTest.java
index 88d3bdb..14999c7 100644
--- a/core/tests/coretests/src/android/view/KeyEventTest.java
+++ b/core/tests/coretests/src/android/view/KeyEventTest.java
@@ -20,8 +20,10 @@
 
 import static org.junit.Assert.assertEquals;
 
+import android.os.Parcel;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -40,6 +42,7 @@
     private static final int SCAN_CODE = 0;
     private static final int FLAGS = 0;
     private static final int SOURCE = InputDevice.SOURCE_KEYBOARD;
+    private static final byte[] HMAC = null;
     private static final String CHARACTERS = null;
 
     @Test
@@ -65,25 +68,15 @@
         KeyEvent keyEvent = KeyEvent.obtain(DOWN_TIME, EVENT_TIME, ACTION, KEYCODE, REPEAT,
                 METASTATE, DEVICE_ID, SCAN_CODE, FLAGS, SOURCE, CHARACTERS);
         KeyEvent keyEvent2 = KeyEvent.obtain(keyEvent);
-        assertEquals(keyEvent.getDownTime(), keyEvent2.getDownTime());
-        assertEquals(keyEvent.getEventTime(), keyEvent2.getEventTime());
-        assertEquals(keyEvent.getAction(), keyEvent2.getAction());
-        assertEquals(keyEvent.getKeyCode(), keyEvent2.getKeyCode());
-        assertEquals(keyEvent.getRepeatCount(), keyEvent2.getRepeatCount());
-        assertEquals(keyEvent.getMetaState(), keyEvent2.getMetaState());
-        assertEquals(keyEvent.getDeviceId(), keyEvent2.getDeviceId());
-        assertEquals(keyEvent.getScanCode(), keyEvent2.getScanCode());
-        assertEquals(keyEvent.getFlags(), keyEvent2.getFlags());
-        assertEquals(keyEvent.getSource(), keyEvent2.getSource());
-        assertEquals(keyEvent.getDisplayId(), keyEvent2.getDisplayId());
-        assertEquals(keyEvent.getCharacters(), keyEvent2.getCharacters());
+        compareKeys(keyEvent, keyEvent2);
     }
 
     @Test
     public void testObtainWithDisplayId() {
         final int displayId = 5;
         KeyEvent keyEvent = KeyEvent.obtain(DOWN_TIME, EVENT_TIME, ACTION, KEYCODE, REPEAT,
-                METASTATE, DEVICE_ID, SCAN_CODE, FLAGS, SOURCE, displayId, CHARACTERS);
+                METASTATE, DEVICE_ID, SCAN_CODE, FLAGS, SOURCE, displayId, null /* hmac*/,
+                CHARACTERS);
         assertEquals(DOWN_TIME, keyEvent.getDownTime());
         assertEquals(EVENT_TIME, keyEvent.getEventTime());
         assertEquals(ACTION, keyEvent.getAction());
@@ -97,4 +90,44 @@
         assertEquals(displayId, keyEvent.getDisplayId());
         assertEquals(CHARACTERS, keyEvent.getCharacters());
     }
+
+    @Test
+    public void testParcelUnparcel() {
+        KeyEvent key1 = createKey();
+        Parcel parcel = Parcel.obtain();
+        key1.writeToParcel(parcel, 0 /*flags*/);
+        parcel.setDataPosition(0);
+
+        KeyEvent key2 = KeyEvent.CREATOR.createFromParcel(parcel);
+        parcel.recycle();
+
+        compareKeys(key1, key2);
+    }
+
+    @Test
+    public void testConstructor() {
+        KeyEvent key1 = createKey();
+        KeyEvent key2 = new KeyEvent(key1);
+        compareKeys(key1, key2);
+    }
+
+    private static KeyEvent createKey() {
+        return KeyEvent.obtain(DOWN_TIME, EVENT_TIME, ACTION, KEYCODE, REPEAT,
+                METASTATE, DEVICE_ID, SCAN_CODE, FLAGS, SOURCE, INVALID_DISPLAY, HMAC, CHARACTERS);
+    }
+
+    private static void compareKeys(KeyEvent key1, KeyEvent key2) {
+        assertEquals(key1.getDownTime(), key2.getDownTime());
+        assertEquals(key1.getEventTime(), key2.getEventTime());
+        assertEquals(key1.getAction(), key2.getAction());
+        assertEquals(key1.getKeyCode(), key2.getKeyCode());
+        assertEquals(key1.getRepeatCount(), key2.getRepeatCount());
+        assertEquals(key1.getMetaState(), key2.getMetaState());
+        assertEquals(key1.getDeviceId(), key2.getDeviceId());
+        assertEquals(key1.getScanCode(), key2.getScanCode());
+        assertEquals(key1.getFlags(), key2.getFlags());
+        assertEquals(key1.getSource(), key2.getSource());
+        assertEquals(key1.getDisplayId(), key2.getDisplayId());
+        assertEquals(key1.getCharacters(), key2.getCharacters());
+    }
 }
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index 411868d..d4c3621 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -92,7 +92,9 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.function.Function;
 
 /**
@@ -976,6 +978,8 @@
                 .launchActivity(Intent.createChooser(sendIntent, null));
 
         // Insert the direct share target
+        Map<ChooserTarget, ShortcutInfo> directShareToShortcutInfos = new HashMap<>();
+        directShareToShortcutInfos.put(serviceTargets.get(0), null);
         InstrumentationRegistry.getInstrumentation().runOnMainSync(
                 () -> activity.getAdapter().addServiceResults(
                         activity.createTestDisplayResolveInfo(sendIntent,
@@ -985,7 +989,8 @@
                                 sendIntent,
                                 /* resolveInfoPresentationGetter */ null),
                         serviceTargets,
-                        TARGET_TYPE_CHOOSER_TARGET)
+                        TARGET_TYPE_CHOOSER_TARGET,
+                        directShareToShortcutInfos)
         );
 
         // Thread.sleep shouldn't be a thing in an integration test but it's
@@ -1044,6 +1049,8 @@
                 .launchActivity(Intent.createChooser(sendIntent, null));
 
         // Insert the direct share target
+        Map<ChooserTarget, ShortcutInfo> directShareToShortcutInfos = new HashMap<>();
+        directShareToShortcutInfos.put(serviceTargets.get(0), null);
         InstrumentationRegistry.getInstrumentation().runOnMainSync(
                 () -> activity.getAdapter().addServiceResults(
                         activity.createTestDisplayResolveInfo(sendIntent,
@@ -1053,7 +1060,8 @@
                                 sendIntent,
                                 /* resolveInfoPresentationGetter */ null),
                         serviceTargets,
-                        TARGET_TYPE_CHOOSER_TARGET)
+                        TARGET_TYPE_CHOOSER_TARGET,
+                        directShareToShortcutInfos)
         );
         // Thread.sleep shouldn't be a thing in an integration test but it's
         // necessary here because of the way the code is structured
@@ -1128,6 +1136,8 @@
         final ChooserWrapperActivity activity = mActivityRule
                 .launchActivity(Intent.createChooser(sendIntent, null));
         // Insert the direct share target
+        Map<ChooserTarget, ShortcutInfo> directShareToShortcutInfos = new HashMap<>();
+        directShareToShortcutInfos.put(serviceTargets.get(0), null);
         InstrumentationRegistry.getInstrumentation().runOnMainSync(
                 () -> activity.getAdapter().addServiceResults(
                         activity.createTestDisplayResolveInfo(sendIntent,
@@ -1137,7 +1147,8 @@
                                 sendIntent,
                                 /* resolveInfoPresentationGetter */ null),
                         serviceTargets,
-                        TARGET_TYPE_CHOOSER_TARGET)
+                        TARGET_TYPE_CHOOSER_TARGET,
+                        directShareToShortcutInfos)
         );
         // Thread.sleep shouldn't be a thing in an integration test but it's
         // necessary here because of the way the code is structured
diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerTestRunner.java b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerTestRunner.java
index 70c266a..ac63853 100644
--- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerTestRunner.java
+++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerTestRunner.java
@@ -58,7 +58,7 @@
         }
         // enable verbose wifi logging
         ((WifiManager)getContext().getSystemService(Context.WIFI_SERVICE))
-            .enableVerboseLogging(1);
+                .setVerboseLoggingEnabled(true);
         super.onCreate(icicle);
     }
 
diff --git a/core/tests/screenshothelpertests/src/com/android/internal/util/ScreenshotHelperTest.java b/core/tests/screenshothelpertests/src/com/android/internal/util/ScreenshotHelperTest.java
index 1472b90..cd6b3af 100644
--- a/core/tests/screenshothelpertests/src/com/android/internal/util/ScreenshotHelperTest.java
+++ b/core/tests/screenshothelpertests/src/com/android/internal/util/ScreenshotHelperTest.java
@@ -31,6 +31,9 @@
 
 import android.content.Context;
 import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Insets;
+import android.graphics.Rect;
 import android.os.Handler;
 import android.os.Looper;
 
@@ -85,6 +88,13 @@
     }
 
     @Test
+    public void testProvidedImageScreenshot() {
+        mScreenshotHelper.provideScreenshot(
+                Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888), new Rect(),
+                Insets.of(0, 0, 0, 0), 1, mHandler, null);
+    }
+
+    @Test
     public void testScreenshotTimesOut() {
         long timeoutMs = 10;
 
diff --git a/core/tests/utiltests/src/com/android/internal/util/ConnectivityUtilTest.java b/core/tests/utiltests/src/com/android/internal/util/LocationPermissionCheckerTest.java
similarity index 84%
rename from core/tests/utiltests/src/com/android/internal/util/ConnectivityUtilTest.java
rename to core/tests/utiltests/src/com/android/internal/util/LocationPermissionCheckerTest.java
index 0809f69..6010f39 100644
--- a/core/tests/utiltests/src/com/android/internal/util/ConnectivityUtilTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/LocationPermissionCheckerTest.java
@@ -28,6 +28,7 @@
 import static org.mockito.Mockito.when;
 
 import android.Manifest;
+import android.app.ActivityManager;
 import android.app.AppOpsManager;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -48,8 +49,8 @@
 
 import java.util.HashMap;
 
-/** Unit tests for {@link ConnectivityUtil}. */
-public class ConnectivityUtilTest {
+/** Unit tests for {@link LocationPermissionChecker}. */
+public class LocationPermissionCheckerTest {
 
     public static final String TAG = "ConnectivityUtilTest";
 
@@ -85,18 +86,7 @@
     private boolean mThrowSecurityException;
     private Answer<Integer> mReturnPermission;
     private HashMap<String, Integer> mPermissionsList = new HashMap<String, Integer>();
-
-    private class TestConnectivityUtil extends ConnectivityUtil {
-
-        TestConnectivityUtil(Context context) {
-            super(context);
-        }
-
-        @Override
-        protected int getCurrentUser() {
-            return mCurrentUser;
-        }
-    }
+    private LocationPermissionChecker mChecker;
 
     @Before
     public void setUp() {
@@ -141,11 +131,12 @@
         mThrowSecurityException = true;
         mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.M;
         mIsLocationEnabled = false;
-        mCurrentUser = UserHandle.USER_SYSTEM;
+        mCurrentUser = ActivityManager.getCurrentUser();
         mCoarseLocationPermission = PackageManager.PERMISSION_DENIED;
         mFineLocationPermission = PackageManager.PERMISSION_DENIED;
         mAllowCoarseLocationApps = AppOpsManager.MODE_ERRORED;
         mAllowFineLocationApps = AppOpsManager.MODE_ERRORED;
+        mChecker = new LocationPermissionChecker(mMockContext);
     }
 
     private void setupMockInterface() {
@@ -189,8 +180,7 @@
         mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED;
         mUid = mCurrentUser;
         setupTestCase();
-        new TestConnectivityUtil(mMockContext)
-                .enforceLocationPermission(TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null);
+        mChecker.enforceLocationPermission(TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null);
     }
 
     @Test
@@ -203,8 +193,7 @@
         mAllowFineLocationApps = AppOpsManager.MODE_ALLOWED;
         mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED;
         setupTestCase();
-        new TestConnectivityUtil(mMockContext)
-                .enforceLocationPermission(TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null);
+        mChecker.enforceLocationPermission(TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null);
     }
 
     @Test
@@ -217,22 +206,8 @@
         setupTestCase();
 
         assertThrows(SecurityException.class,
-                () -> new TestConnectivityUtil(mMockContext)
-                        .enforceLocationPermission(TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null));
-    }
-
-    @Test
-    public void testenforceCanAccessScanResults_UserOrProfileNotCurrent() throws Exception {
-        mIsLocationEnabled = true;
-        mThrowSecurityException = false;
-        mCoarseLocationPermission = PackageManager.PERMISSION_GRANTED;
-        mAllowCoarseLocationApps = AppOpsManager.MODE_ALLOWED;
-        mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED;
-        setupTestCase();
-
-        assertThrows(SecurityException.class,
-                () -> new TestConnectivityUtil(mMockContext)
-                        .enforceLocationPermission(TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null));
+                () -> mChecker.enforceLocationPermission(
+                        TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null));
     }
 
     @Test
@@ -241,8 +216,8 @@
         mIsLocationEnabled = true;
         setupTestCase();
         assertThrows(SecurityException.class,
-                () -> new TestConnectivityUtil(mMockContext)
-                        .enforceLocationPermission(TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null));
+                () -> mChecker.enforceLocationPermission(
+                        TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null));
     }
 
     @Test
@@ -256,8 +231,8 @@
         setupTestCase();
 
         assertThrows(SecurityException.class,
-                () -> new TestConnectivityUtil(mMockContext)
-                        .enforceLocationPermission(TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null));
+                () -> mChecker.enforceLocationPermission(
+                        TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null));
         verify(mMockAppOps, never()).noteOp(anyInt(), anyInt(), anyString());
     }
 
@@ -272,8 +247,8 @@
         setupTestCase();
 
         assertThrows(SecurityException.class,
-                () -> new TestConnectivityUtil(mMockContext)
-                        .enforceLocationPermission(TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null));
+                () -> mChecker.enforceLocationPermission(
+                        TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null));
     }
 
     private static void assertThrows(Class<? extends Exception> exceptionClass, Runnable r) {
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 0541db1..da50550 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -60,6 +60,10 @@
         <group gid="log" />
     </permission>
 
+    <permission name="android.permission.MANAGE_EXTERNAL_STORAGE" >
+        <group gid="external_storage" />
+    </permission>
+
     <permission name="android.permission.ACCESS_MTP" >
         <group gid="mtp" />
     </permission>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 3677b8f..133b1ae 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -200,6 +200,7 @@
         <permission name="android.permission.CLEAR_APP_CACHE"/>
         <permission name="android.permission.CONNECTIVITY_INTERNAL"/>
         <permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/>
+        <permission name="android.permission.WRITE_MEDIA_STORAGE"/>
         <permission name="android.permission.UPDATE_APP_OPS_STATS"/>
         <permission name="android.permission.UPDATE_DEVICE_STATS"/>
     </privapp-permissions>
@@ -357,6 +358,11 @@
         <permission name="android.permission.CONTROL_INCALL_EXPERIENCE"/>
         <!-- Permission required for Tethering CTS tests. -->
         <permission name="android.permission.TETHER_PRIVILEGED"/>
+        <!-- Permissions required to test ambient display. -->
+        <permission name="android.permission.READ_DREAM_STATE" />
+        <permission name="android.permission.WRITE_DREAM_STATE" />
+        <!-- Permission required to test lights control APIs. -->
+        <permission name="android.permission.CONTROL_DEVICE_LIGHTS" />
     </privapp-permissions>
 
     <privapp-permissions package="com.android.statementservice">
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 1e98e3a..79589bf 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -697,12 +697,6 @@
       "group": "WM_DEBUG_REMOTE_ANIMATIONS",
       "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
     },
-    "-650040763": {
-      "message": "rotationForOrientation(orient=%d, last=%d); user=%d %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/DisplayRotation.java"
-    },
     "-635082269": {
       "message": "******** booted=%b msg=%b haveBoot=%b haveApp=%b haveWall=%b wallEnabled=%b haveKeyguard=%b",
       "level": "INFO",
@@ -901,6 +895,12 @@
       "group": "WM_DEBUG_WINDOW_MOVEMENT",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "-177040661": {
+      "message": "Start rotation animation. customAnim=%s, mCurRotation=%s, mOriginalRotation=%s",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_ORIENTATION",
+      "at": "com\/android\/server\/wm\/ScreenRotationAnimation.java"
+    },
     "-167822951": {
       "message": "Attempted to add starting window to token with already existing starting window",
       "level": "WARN",
@@ -1105,6 +1105,12 @@
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/ScreenRotationAnimation.java"
     },
+    "202263690": {
+      "message": "rotationForOrientation(orient=%s (%d), last=%s (%d)); user=%s (%d) %s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_ORIENTATION",
+      "at": "com\/android\/server\/wm\/DisplayRotation.java"
+    },
     "221540118": {
       "message": "mUserActivityTimeout set to %d",
       "level": "DEBUG",
diff --git a/docs/html/reference/images/camera2/metadata/android.scaler.rotateAndCrop/crop-region-rotate-90-43-ratio.png b/docs/html/reference/images/camera2/metadata/android.scaler.rotateAndCrop/crop-region-rotate-90-43-ratio.png
new file mode 100644
index 0000000..2633996
--- /dev/null
+++ b/docs/html/reference/images/camera2/metadata/android.scaler.rotateAndCrop/crop-region-rotate-90-43-ratio.png
Binary files differ
diff --git a/drm/java/android/drm/DrmConvertedStatus.java b/drm/java/android/drm/DrmConvertedStatus.java
index f6e570a..0f7ceb4 100644
--- a/drm/java/android/drm/DrmConvertedStatus.java
+++ b/drm/java/android/drm/DrmConvertedStatus.java
@@ -25,7 +25,9 @@
  * An valid offset value is provided only from a success call to
  * {@link DrmManagerClient#closeConvertSession DrmManagerClient.closeConvertSession()}.
  *
+ * @deprecated Please use {@link android.media.MediaDrm}
  */
+@Deprecated
 public class DrmConvertedStatus {
     // The following status code constants must be in sync with
     // DrmConvertedStatus.cpp. Please also update isValidStatusCode()
diff --git a/drm/java/android/drm/DrmErrorEvent.java b/drm/java/android/drm/DrmErrorEvent.java
index c61819d..f37c8ac 100644
--- a/drm/java/android/drm/DrmErrorEvent.java
+++ b/drm/java/android/drm/DrmErrorEvent.java
@@ -22,7 +22,9 @@
  * An entity class that is passed to the
  * {@link DrmManagerClient.OnErrorListener#onError onError()} callback.
  *
+ * @deprecated Please use {@link android.media.MediaDrm}
  */
+@Deprecated
 public class DrmErrorEvent extends DrmEvent {
 
     // Please add newly defined type constants to the end of the list,
diff --git a/drm/java/android/drm/DrmEvent.java b/drm/java/android/drm/DrmEvent.java
index 1a19f5c..e2fe87b 100644
--- a/drm/java/android/drm/DrmEvent.java
+++ b/drm/java/android/drm/DrmEvent.java
@@ -21,7 +21,9 @@
 /**
  * A base class that is used to send asynchronous event information from the DRM framework.
  *
+ * @deprecated Please use {@link android.media.MediaDrm}
  */
+@Deprecated
 public class DrmEvent {
 
     // Please do not add type constants in this class. More event type constants
diff --git a/drm/java/android/drm/DrmInfo.java b/drm/java/android/drm/DrmInfo.java
index 8c43252..3240893 100644
--- a/drm/java/android/drm/DrmInfo.java
+++ b/drm/java/android/drm/DrmInfo.java
@@ -30,7 +30,9 @@
  * The caller can retrieve the {@link DrmInfo} instance by passing a {@link DrmInfoRequest}
  * instance to {@link DrmManagerClient#acquireDrmInfo}.
  *
+ * @deprecated Please use {@link android.media.MediaDrm}
  */
+@Deprecated
 public class DrmInfo {
     private byte[] mData;
     private final String mMimeType;
diff --git a/drm/java/android/drm/DrmInfoEvent.java b/drm/java/android/drm/DrmInfoEvent.java
index 2826dce..853f566c 100644
--- a/drm/java/android/drm/DrmInfoEvent.java
+++ b/drm/java/android/drm/DrmInfoEvent.java
@@ -22,7 +22,9 @@
  * An entity class that is passed to the 
  * {@link DrmManagerClient.OnInfoListener#onInfo onInfo()} callback.
  *
+ * @deprecated Please use {@link android.media.MediaDrm}
  */
+@Deprecated
 public class DrmInfoEvent extends DrmEvent {
 
     // Please add newly defined type constants to the end of the list,
diff --git a/drm/java/android/drm/DrmInfoRequest.java b/drm/java/android/drm/DrmInfoRequest.java
index 621da41..135bbc0 100644
--- a/drm/java/android/drm/DrmInfoRequest.java
+++ b/drm/java/android/drm/DrmInfoRequest.java
@@ -24,7 +24,9 @@
  * class is passed to the {@link DrmManagerClient#acquireDrmInfo acquireDrmInfo()} method to get an
  * instance of a {@link DrmInfo}.
  *
+ * @deprecated Please use {@link android.media.MediaDrm}
  */
+@Deprecated
 public class DrmInfoRequest {
     // Changes in following constants should be in sync with DrmInfoRequest.h
     /**
diff --git a/drm/java/android/drm/DrmInfoStatus.java b/drm/java/android/drm/DrmInfoStatus.java
index 9a3a7df..0fa1a70 100644
--- a/drm/java/android/drm/DrmInfoStatus.java
+++ b/drm/java/android/drm/DrmInfoStatus.java
@@ -25,7 +25,9 @@
  * This class contains the {@link ProcessedData} object, which can be used
  * to instantiate a {@link DrmRights} object during license acquisition.
  *
+ * @deprecated Please use {@link android.media.MediaDrm}
  */
+@Deprecated
 public class DrmInfoStatus {
     // The following status code constants must be in sync with DrmInfoStatus.cpp
     // Please update isValidStatusCode() if more status codes are added.
diff --git a/drm/java/android/drm/DrmManagerClient.java b/drm/java/android/drm/DrmManagerClient.java
index 041300c..ba3ebdd 100644
--- a/drm/java/android/drm/DrmManagerClient.java
+++ b/drm/java/android/drm/DrmManagerClient.java
@@ -47,7 +47,9 @@
  * The main programming interface for the DRM framework. An application must instantiate this class
  * to access DRM agents through the DRM framework.
  *
+ * @deprecated Please use {@link android.media.MediaDrm}
  */
+@Deprecated
 public class DrmManagerClient implements AutoCloseable {
     /**
      * Indicates that a request was successful or that no error occurred.
diff --git a/drm/java/android/drm/DrmOutputStream.java b/drm/java/android/drm/DrmOutputStream.java
index 9c23834..73e7f23 100644
--- a/drm/java/android/drm/DrmOutputStream.java
+++ b/drm/java/android/drm/DrmOutputStream.java
@@ -40,7 +40,9 @@
  * writing to disk, similar to a {@link FilterOutputStream}.
  *
  * @hide
+ * @deprecated Please use {@link android.media.MediaDrm}
  */
+@Deprecated
 public class DrmOutputStream extends OutputStream {
     private static final String TAG = "DrmOutputStream";
 
diff --git a/drm/java/android/drm/DrmRights.java b/drm/java/android/drm/DrmRights.java
index 8747f77..0a8df09 100644
--- a/drm/java/android/drm/DrmRights.java
+++ b/drm/java/android/drm/DrmRights.java
@@ -37,7 +37,9 @@
  * agent or plugin, they can be either null, or an empty string, or any other don't-care
  * string value.
  *
+ * @deprecated Please use {@link android.media.MediaDrm}
  */
+@Deprecated
 public class DrmRights {
     private byte[] mData;
     private String mMimeType;
diff --git a/drm/java/android/drm/DrmStore.java b/drm/java/android/drm/DrmStore.java
index 3a77ea1..98d4449 100644
--- a/drm/java/android/drm/DrmStore.java
+++ b/drm/java/android/drm/DrmStore.java
@@ -19,7 +19,9 @@
 /**
  * Defines constants that are used by the DRM framework.
  *
+ * @deprecated Please use {@link android.media.MediaDrm}
  */
+@Deprecated
 public class DrmStore {
     /**
      * Interface definition for the columns that represent DRM constraints.
diff --git a/drm/java/android/drm/DrmSupportInfo.java b/drm/java/android/drm/DrmSupportInfo.java
index 3694ff4..f7e4fbd 100644
--- a/drm/java/android/drm/DrmSupportInfo.java
+++ b/drm/java/android/drm/DrmSupportInfo.java
@@ -26,7 +26,9 @@
  * Plug-in developers can expose the capability of their plug-in by passing an instance of this
  * class to an application.
  *
+ * @deprecated Please use {@link android.media.MediaDrm}
  */
+@Deprecated
 public class DrmSupportInfo {
     private final ArrayList<String> mFileSuffixList = new ArrayList<String>();
     private final ArrayList<String> mMimeTypeList = new ArrayList<String>();
diff --git a/drm/java/android/drm/DrmUtils.java b/drm/java/android/drm/DrmUtils.java
index 60ee6d9..66a60cf 100644
--- a/drm/java/android/drm/DrmUtils.java
+++ b/drm/java/android/drm/DrmUtils.java
@@ -33,7 +33,9 @@
  * constraints, the constraints will show up in the
  * {@link DrmStore.ConstraintsColumns#EXTENDED_METADATA} key. You can use
  * {@link DrmUtils.ExtendedMetadataParser} to iterate over those values.
+ * @deprecated Please use {@link android.media.MediaDrm}
  */
+@Deprecated
 public class DrmUtils {
     /* Should be used when we need to read from local file */
     /* package */ static byte[] readBytes(String path) throws IOException {
diff --git a/drm/java/android/drm/ProcessedData.java b/drm/java/android/drm/ProcessedData.java
index 06e03e7..35b7288 100644
--- a/drm/java/android/drm/ProcessedData.java
+++ b/drm/java/android/drm/ProcessedData.java
@@ -23,7 +23,9 @@
  *
  * In a license acquisition scenario this class holds the rights information in binary form.
  *
+ * @deprecated Please use {@link android.media.MediaDrm}
  */
+@Deprecated
 public class ProcessedData {
     private final byte[] mData;
     private String mAccountId = "_NO_USER";
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index ac094ba..9c2e95f 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -2132,7 +2132,7 @@
     public void writeToParcel(Parcel p, int flags) {
         checkRecycled("Can't parcel a recycled bitmap");
         noteHardwareBitmapSlowCall();
-        if (!nativeWriteToParcel(mNativePtr, isMutable(), mDensity, p)) {
+        if (!nativeWriteToParcel(mNativePtr, mDensity, p)) {
             throw new RuntimeException("native writeToParcel failed");
         }
     }
@@ -2285,7 +2285,6 @@
     private static native Bitmap nativeCreateFromParcel(Parcel p);
     // returns true on success
     private static native boolean nativeWriteToParcel(long nativeBitmap,
-                                                      boolean isMutable,
                                                       int density,
                                                       Parcel p);
     // returns a new bitmap built from the native bitmap's alpha, and the paint
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 9a0ca3e..d949444 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -1162,6 +1162,7 @@
      * @see #quickReject(float, float, float, float, EdgeType)
      * @see #quickReject(Path, EdgeType)
      * @see #quickReject(RectF, EdgeType)
+     * @deprecated quickReject no longer uses this.
      */
     public enum EdgeType {
 
@@ -1197,13 +1198,30 @@
      *              non-antialiased ({@link Canvas.EdgeType#BW}).
      * @return      true if the rect (transformed by the canvas' matrix)
      *              does not intersect with the canvas' clip
+     * @deprecated The EdgeType is ignored. Use {@link #quickReject(RectF)} instead.
      */
+    @Deprecated
     public boolean quickReject(@NonNull RectF rect, @NonNull EdgeType type) {
         return nQuickReject(mNativeCanvasWrapper,
                 rect.left, rect.top, rect.right, rect.bottom);
     }
 
     /**
+     * Return true if the specified rectangle, after being transformed by the
+     * current matrix, would lie completely outside of the current clip. Call
+     * this to check if an area you intend to draw into is clipped out (and
+     * therefore you can skip making the draw calls).
+     *
+     * @param rect  the rect to compare with the current clip
+     * @return      true if the rect (transformed by the canvas' matrix)
+     *              does not intersect with the canvas' clip
+     */
+    public boolean quickReject(@NonNull RectF rect) {
+        return nQuickReject(mNativeCanvasWrapper,
+                rect.left, rect.top, rect.right, rect.bottom);
+    }
+
+    /**
      * Return true if the specified path, after being transformed by the
      * current matrix, would lie completely outside of the current clip. Call
      * this to check if an area you intend to draw into is clipped out (and
@@ -1217,12 +1235,30 @@
      *                    non-antialiased ({@link Canvas.EdgeType#BW}).
      * @return            true if the path (transformed by the canvas' matrix)
      *                    does not intersect with the canvas' clip
+     * @deprecated The EdgeType is ignored. Use {@link #quickReject(Path)} instead.
      */
+    @Deprecated
     public boolean quickReject(@NonNull Path path, @NonNull EdgeType type) {
         return nQuickReject(mNativeCanvasWrapper, path.readOnlyNI());
     }
 
     /**
+     * Return true if the specified path, after being transformed by the
+     * current matrix, would lie completely outside of the current clip. Call
+     * this to check if an area you intend to draw into is clipped out (and
+     * therefore you can skip making the draw calls). Note: for speed it may
+     * return false even if the path itself might not intersect the clip
+     * (i.e. the bounds of the path intersects, but the path does not).
+     *
+     * @param path        The path to compare with the current clip
+     * @return            true if the path (transformed by the canvas' matrix)
+     *                    does not intersect with the canvas' clip
+     */
+    public boolean quickReject(@NonNull Path path) {
+        return nQuickReject(mNativeCanvasWrapper, path.readOnlyNI());
+    }
+
+    /**
      * Return true if the specified rectangle, after being transformed by the
      * current matrix, would lie completely outside of the current clip. Call
      * this to check if an area you intend to draw into is clipped out (and
@@ -1241,13 +1277,37 @@
      *                    non-antialiased ({@link Canvas.EdgeType#BW}).
      * @return            true if the rect (transformed by the canvas' matrix)
      *                    does not intersect with the canvas' clip
+     * @deprecated The EdgeType is ignored. Use {@link #quickReject(float, float, float, float)}
+     *             instead.
      */
+    @Deprecated
     public boolean quickReject(float left, float top, float right, float bottom,
             @NonNull EdgeType type) {
         return nQuickReject(mNativeCanvasWrapper, left, top, right, bottom);
     }
 
     /**
+     * Return true if the specified rectangle, after being transformed by the
+     * current matrix, would lie completely outside of the current clip. Call
+     * this to check if an area you intend to draw into is clipped out (and
+     * therefore you can skip making the draw calls).
+     *
+     * @param left        The left side of the rectangle to compare with the
+     *                    current clip
+     * @param top         The top of the rectangle to compare with the current
+     *                    clip
+     * @param right       The right side of the rectangle to compare with the
+     *                    current clip
+     * @param bottom      The bottom of the rectangle to compare with the
+     *                    current clip
+     * @return            true if the rect (transformed by the canvas' matrix)
+     *                    does not intersect with the canvas' clip
+     */
+    public boolean quickReject(float left, float top, float right, float bottom) {
+        return nQuickReject(mNativeCanvasWrapper, left, top, right, bottom);
+    }
+
+    /**
      * Return the bounds of the current clip (in local coordinates) in the
      * bounds parameter, and return true if it is non-empty. This can be useful
      * in a way similar to quickReject, in that it tells you that drawing
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index 3c402e9..7c0efe1 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -471,36 +471,14 @@
     return BitmapPalette::Unknown;
 }
 
-Bitmap::CompressResult Bitmap::compress(JavaCompressFormat format, int32_t quality,
-                                        SkWStream* stream) {
+bool Bitmap::compress(JavaCompressFormat format, int32_t quality, SkWStream* stream) {
     SkBitmap skbitmap;
     getSkBitmap(&skbitmap);
     return compress(skbitmap, format, quality, stream);
 }
 
-Bitmap::CompressResult Bitmap::compress(const SkBitmap& bitmap, JavaCompressFormat format,
-                                        int32_t quality, SkWStream* stream) {
-    SkBitmap skbitmap = bitmap;
-    if (skbitmap.colorType() == kRGBA_F16_SkColorType) {
-        // Convert to P3 before encoding. This matches
-        // SkAndroidCodec::computeOutputColorSpace for wide gamuts. Now that F16
-        // could already be P3, we still want to convert to 8888.
-        auto cs = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDCIP3);
-        auto info = skbitmap.info().makeColorType(kRGBA_8888_SkColorType)
-                                   .makeColorSpace(std::move(cs));
-        SkBitmap p3;
-        if (!p3.tryAllocPixels(info)) {
-            return CompressResult::AllocationFailed;
-        }
-
-        SkPixmap pm;
-        SkAssertResult(p3.peekPixels(&pm));  // should always work if tryAllocPixels() did.
-        if (!skbitmap.readPixels(pm)) {
-            return CompressResult::Error;
-        }
-        skbitmap = p3;
-    }
-
+bool Bitmap::compress(const SkBitmap& bitmap, JavaCompressFormat format,
+                      int32_t quality, SkWStream* stream) {
     SkEncodedImageFormat fm;
     switch (format) {
         case JavaCompressFormat::Jpeg:
@@ -518,12 +496,10 @@
             options.fQuality = quality;
             options.fCompression = format == JavaCompressFormat::WebpLossy ?
                     SkWebpEncoder::Compression::kLossy : SkWebpEncoder::Compression::kLossless;
-            return SkWebpEncoder::Encode(stream, skbitmap.pixmap(), options)
-                    ? CompressResult::Success : CompressResult::Error;
+            return SkWebpEncoder::Encode(stream, bitmap.pixmap(), options);
         }
     }
 
-    return SkEncodeImage(stream, skbitmap, fm, quality)
-            ? CompressResult::Success : CompressResult::Error;
+    return SkEncodeImage(stream, bitmap, fm, quality);
 }
 }  // namespace android
diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h
index ee365af..3bfb780 100644
--- a/libs/hwui/hwui/Bitmap.h
+++ b/libs/hwui/hwui/Bitmap.h
@@ -154,16 +154,10 @@
     WebpLossless = 4,
   };
 
-  enum class CompressResult {
-    Success,
-    AllocationFailed,
-    Error,
-  };
+  bool compress(JavaCompressFormat format, int32_t quality, SkWStream* stream);
 
-  CompressResult compress(JavaCompressFormat format, int32_t quality, SkWStream* stream);
-
-  static CompressResult compress(const SkBitmap& bitmap, JavaCompressFormat format,
-                                 int32_t quality, SkWStream* stream);
+  static bool compress(const SkBitmap& bitmap, JavaCompressFormat format,
+                       int32_t quality, SkWStream* stream);
 private:
     static sk_sp<Bitmap> allocateAshmemBitmap(size_t size, const SkImageInfo& i, size_t rowBytes);
     static sk_sp<Bitmap> allocateHeapBitmap(size_t size, const SkImageInfo& i, size_t rowBytes);
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index 52305b8..ebc622b 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -100,6 +100,7 @@
     virtual int32_t getDisplayId() const;
     virtual void fade(Transition transition);
     virtual void unfade(Transition transition);
+    virtual void setDisplayViewport(const DisplayViewport& viewport);
 
     virtual void setPresentation(Presentation presentation);
     virtual void setSpots(const PointerCoords* spotCoords,
@@ -108,7 +109,6 @@
 
     void updatePointerIcon(int32_t iconId);
     void setCustomPointerIcon(const SpriteIcon& icon);
-    void setDisplayViewport(const DisplayViewport& viewport);
     void setInactivityTimeout(InactivityTimeout inactivityTimeout);
     void reloadPointerResources();
 
diff --git a/libs/services/Android.bp b/libs/services/Android.bp
index 901ffaa..9b047ca 100644
--- a/libs/services/Android.bp
+++ b/libs/services/Android.bp
@@ -21,7 +21,6 @@
         "src/content/ComponentName.cpp",
         "src/os/DropBoxManager.cpp",
         "src/os/StatsDimensionsValue.cpp",
-        "src/os/StatsLogEventWrapper.cpp",
     ],
 
     shared_libs: [
diff --git a/libs/services/include/android/os/StatsLogEventWrapper.h b/libs/services/include/android/os/StatsLogEventWrapper.h
deleted file mode 100644
index 8de2ab4..0000000
--- a/libs/services/include/android/os/StatsLogEventWrapper.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef STATS_LOG_EVENT_WRAPPER_H
-#define STATS_LOG_EVENT_WRAPPER_H
-
-#include <binder/Parcel.h>
-#include <binder/Parcelable.h>
-#include <binder/Status.h>
-#include <utils/RefBase.h>
-#include <vector>
-
-namespace android {
-namespace os {
-
-/**
- * A wrapper for a union type to contain multiple types of values.
- *
- */
-struct StatsLogValue {
-  // Keep in sync with FieldValue.h
-  enum STATS_LOG_VALUE_TYPE {
-    UNKNOWN = 0,
-    INT = 1,
-    LONG = 2,
-    FLOAT = 3,
-    DOUBLE = 4,
-    STRING = 5,
-    STORAGE = 6
-  };
-
-  StatsLogValue() : type(UNKNOWN) {}
-
-  StatsLogValue(int32_t v) {
-    int_value = v;
-    type = INT;
-  }
-
-  StatsLogValue(int64_t v) {
-    long_value = v;
-    type = LONG;
-  }
-
-  StatsLogValue(float v) {
-    float_value = v;
-    type = FLOAT;
-  }
-
-  StatsLogValue(double v) {
-    double_value = v;
-    type = DOUBLE;
-  }
-
-  StatsLogValue(const std::string& v) {
-    str_value = v;
-    type = STRING;
-  }
-
-  void setType(STATS_LOG_VALUE_TYPE t) { type = t; }
-
-  union {
-    int32_t int_value;
-    int64_t long_value;
-    float float_value;
-    double double_value;
-  };
-  std::string str_value;
-  std::vector<uint8_t> storage_value;
-
-  STATS_LOG_VALUE_TYPE type;
-};
-
-struct WorkChain {
-  std::vector<int32_t> uids;
-  std::vector<std::string> tags;
-};
-
-// Represents a parcelable object. Only used to send data from Android OS to statsd.
-class StatsLogEventWrapper : public android::Parcelable {
- public:
-  StatsLogEventWrapper();
-
-  StatsLogEventWrapper(StatsLogEventWrapper&& in) = default;
-
-  android::status_t writeToParcel(android::Parcel* out) const;
-
-  android::status_t readFromParcel(const android::Parcel* in);
-
-  int getTagId() const { return mTagId; }
-
-  int64_t getElapsedRealTimeNs() const { return mElapsedRealTimeNs; }
-
-  int64_t getWallClockTimeNs() const { return mWallClockTimeNs; }
-
-  const std::vector<StatsLogValue>& getElements() const { return mElements; }
-
-  const std::vector<WorkChain>& getWorkChains() const { return mWorkChains; }
-
- private:
-  int mTagId;
-
-  int64_t mElapsedRealTimeNs;
-
-  int64_t mWallClockTimeNs;
-
-  std::vector<StatsLogValue> mElements;
-
-  std::vector<WorkChain> mWorkChains;
-};
-} // Namespace os
-} // Namespace android
-
-
-#endif  // STATS_LOG_EVENT_WRAPPER_H
-
diff --git a/libs/services/src/os/StatsLogEventWrapper.cpp b/libs/services/src/os/StatsLogEventWrapper.cpp
deleted file mode 100644
index f6dfdef..0000000
--- a/libs/services/src/os/StatsLogEventWrapper.cpp
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <android/os/StatsLogEventWrapper.h>
-
-#include <binder/Parcel.h>
-#include <binder/Parcelable.h>
-#include <binder/Status.h>
-#include <utils/RefBase.h>
-#include <vector>
-
-using android::Parcel;
-using android::Parcelable;
-using android::status_t;
-using std::vector;
-
-namespace android {
-namespace os {
-
-StatsLogEventWrapper::StatsLogEventWrapper(){};
-
-status_t StatsLogEventWrapper::writeToParcel(Parcel* out) const {
-  // Implement me if desired. We don't currently use this.
-  ALOGE(
-      "Cannot do c++ StatsLogEventWrapper.writeToParcel(); it is not "
-      "implemented.");
-  (void)out;  // To prevent compile error of unused parameter 'in'
-  return UNKNOWN_ERROR;
-};
-
-status_t StatsLogEventWrapper::readFromParcel(const Parcel* in) {
-  status_t res = OK;
-  if (in == NULL) {
-    ALOGE("statsd received parcel argument was NULL.");
-    return BAD_VALUE;
-  }
-  if ((res = in->readInt32(&mTagId)) != OK) {
-    ALOGE("statsd could not read tagId from parcel");
-    return res;
-  }
-  if ((res = in->readInt64(&mElapsedRealTimeNs)) != OK) {
-    ALOGE("statsd could not read elapsed real time from parcel");
-    return res;
-  }
-  if ((res = in->readInt64(&mWallClockTimeNs)) != OK) {
-    ALOGE("statsd could not read wall clock time from parcel");
-    return res;
-  }
-  int numWorkChain = 0;
-  if ((res = in->readInt32(&numWorkChain)) != OK) {
-    ALOGE("statsd could not read number of work chains from parcel");
-    return res;
-  }
-  if (numWorkChain > 0) {
-    for (int i = 0; i < numWorkChain; i++) {
-      int numNodes = 0;
-      if ((res = in->readInt32(&numNodes)) != OK) {
-        ALOGE(
-            "statsd could not read number of nodes in work chain from parcel");
-        return res;
-      }
-      if (numNodes == 0) {
-        ALOGE("empty work chain");
-        return BAD_VALUE;
-      }
-      WorkChain wc;
-      for (int j = 0; j < numNodes; j++) {
-        wc.uids.push_back(in->readInt32());
-        wc.tags.push_back(std::string(String8(in->readString16()).string()));
-      }
-      mWorkChains.push_back(wc);
-    }
-  }
-  int dataSize = 0;
-  if ((res = in->readInt32(&dataSize)) != OK) {
-    ALOGE("statsd could not read data size from parcel");
-    return res;
-  }
-  if (mTagId <= 0 || mElapsedRealTimeNs <= 0 || mWallClockTimeNs <= 0 ||
-      dataSize <= 0) {
-    ALOGE("statsd received invalid parcel");
-    return BAD_VALUE;
-  }
-
-  for (int i = 0; i < dataSize; i++) {
-    int type = in->readInt32();
-    switch (type) {
-      case StatsLogValue::INT:
-        mElements.push_back(StatsLogValue(in->readInt32()));
-        break;
-      case StatsLogValue::LONG:
-        mElements.push_back(StatsLogValue(in->readInt64()));
-        break;
-      case StatsLogValue::STRING:
-        mElements.push_back(
-            StatsLogValue(std::string(String8(in->readString16()).string())));
-        break;
-      case StatsLogValue::FLOAT:
-        mElements.push_back(StatsLogValue(in->readFloat()));
-        break;
-      case StatsLogValue::STORAGE:
-        mElements.push_back(StatsLogValue());
-        mElements.back().setType(StatsLogValue::STORAGE);
-        in->readByteVector(&(mElements.back().storage_value));
-        break;
-      default:
-        ALOGE("unrecognized data type: %d", type);
-        return BAD_TYPE;
-    }
-  }
-  return NO_ERROR;
-};
-
-} // Namespace os
-} // Namespace android
diff --git a/location/java/android/location/GnssClock.java b/location/java/android/location/GnssClock.java
index 8a7878b..ed4bf1b 100644
--- a/location/java/android/location/GnssClock.java
+++ b/location/java/android/location/GnssClock.java
@@ -17,6 +17,7 @@
 package android.location;
 
 import android.annotation.FloatRange;
+import android.annotation.NonNull;
 import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -39,6 +40,9 @@
     private static final int HAS_DRIFT_UNCERTAINTY = (1<<6);
     private static final int HAS_ELAPSED_REALTIME_NANOS = (1 << 7);
     private static final int HAS_ELAPSED_REALTIME_UNCERTAINTY_NANOS = (1 << 8);
+    private static final int HAS_REFERENCE_CONSTELLATION_TYPE_FOR_ISB = (1 << 9);
+    private static final int HAS_REFERENCE_CARRIER_FREQUENCY_FOR_ISB = (1 << 10);
+    private static final int HAS_REFERENCE_CODE_TYPE_FOR_ISB = (1 << 11);
 
     // End enumerations in sync with gps.h
 
@@ -54,6 +58,9 @@
     private int mHardwareClockDiscontinuityCount;
     private long mElapsedRealtimeNanos;
     private double mElapsedRealtimeUncertaintyNanos;
+    private int mReferenceConstellationTypeForIsb;
+    private double mReferenceCarrierFrequencyHzForIsb;
+    private String mReferenceCodeTypeForIsb;
 
     /**
      * @hide
@@ -81,6 +88,9 @@
         mHardwareClockDiscontinuityCount = clock.mHardwareClockDiscontinuityCount;
         mElapsedRealtimeNanos = clock.mElapsedRealtimeNanos;
         mElapsedRealtimeUncertaintyNanos = clock.mElapsedRealtimeUncertaintyNanos;
+        mReferenceConstellationTypeForIsb = clock.mReferenceConstellationTypeForIsb;
+        mReferenceCarrierFrequencyHzForIsb = clock.mReferenceCarrierFrequencyHzForIsb;
+        mReferenceCodeTypeForIsb = clock.mReferenceCodeTypeForIsb;
     }
 
     /**
@@ -196,7 +206,6 @@
     @TestApi
     public void resetTimeUncertaintyNanos() {
         resetFlag(HAS_TIME_UNCERTAINTY);
-        mTimeUncertaintyNanos = Double.NaN;
     }
 
     /**
@@ -286,7 +295,6 @@
     @TestApi
     public void resetBiasNanos() {
         resetFlag(HAS_BIAS);
-        mBiasNanos = Double.NaN;
     }
 
     /**
@@ -327,7 +335,6 @@
     @TestApi
     public void resetBiasUncertaintyNanos() {
         resetFlag(HAS_BIAS_UNCERTAINTY);
-        mBiasUncertaintyNanos = Double.NaN;
     }
 
     /**
@@ -371,7 +378,6 @@
     @TestApi
     public void resetDriftNanosPerSecond() {
         resetFlag(HAS_DRIFT);
-        mDriftNanosPerSecond = Double.NaN;
     }
 
     /**
@@ -411,7 +417,6 @@
     @TestApi
     public void resetDriftUncertaintyNanosPerSecond() {
         resetFlag(HAS_DRIFT_UNCERTAINTY);
-        mDriftUncertaintyNanosPerSecond = Double.NaN;
     }
 
     /**
@@ -495,7 +500,128 @@
     @TestApi
     public void resetElapsedRealtimeUncertaintyNanos() {
         resetFlag(HAS_ELAPSED_REALTIME_UNCERTAINTY_NANOS);
-        mElapsedRealtimeUncertaintyNanos = Double.NaN;
+    }
+
+    /**
+     * Returns {@code true} if {@link #getReferenceConstellationTypeForIsb()} is available,
+     * {@code false} otherwise.
+     */
+    public boolean hasReferenceConstellationTypeForIsb() {
+        return isFlagSet(HAS_REFERENCE_CONSTELLATION_TYPE_FOR_ISB);
+    }
+
+    /**
+     * Returns the reference constellation type for inter-signal bias.
+     *
+     * <p>The value is only available if {@link #hasReferenceConstellationTypeForIsb()} is
+     * {@code true}.
+     *
+     * <p>The return value is one of those constants with {@code CONSTELLATION_} prefix in
+     * {@link GnssStatus}.
+     */
+    @GnssStatus.ConstellationType
+    public int getReferenceConstellationTypeForIsb() {
+        return mReferenceConstellationTypeForIsb;
+    }
+
+    /**
+     * Sets the reference constellation type for inter-signal bias.
+     * @hide
+     */
+    @TestApi
+    public void setReferenceConstellationTypeForIsb(@GnssStatus.ConstellationType int value) {
+        setFlag(HAS_REFERENCE_CONSTELLATION_TYPE_FOR_ISB);
+        mReferenceConstellationTypeForIsb = value;
+    }
+
+    /**
+     * Resets the reference constellation type for inter-signal bias.
+     * @hide
+     */
+    @TestApi
+    public void resetReferenceConstellationTypeForIsb() {
+        resetFlag(HAS_REFERENCE_CONSTELLATION_TYPE_FOR_ISB);
+        mReferenceConstellationTypeForIsb = GnssStatus.CONSTELLATION_UNKNOWN;
+    }
+
+    /**
+     * Returns {@code true} if {@link #getReferenceCarrierFrequencyHzForIsb()} is available, {@code
+     * false} otherwise.
+     */
+    public boolean hasReferenceCarrierFrequencyHzForIsb() {
+        return isFlagSet(HAS_REFERENCE_CARRIER_FREQUENCY_FOR_ISB);
+    }
+
+    /**
+     * Returns the reference carrier frequency in Hz for inter-signal bias.
+     *
+     * <p>The value is only available if {@link #hasReferenceCarrierFrequencyHzForIsb()} is
+     * {@code true}.
+     */
+    @FloatRange(from = 0.0)
+    public double getReferenceCarrierFrequencyHzForIsb() {
+        return mReferenceCarrierFrequencyHzForIsb;
+    }
+
+    /**
+     * Sets the reference carrier frequency in Hz for inter-signal bias.
+     * @hide
+     */
+    @TestApi
+    public void setReferenceCarrierFrequencyHzForIsb(@FloatRange(from = 0.0) double value) {
+        setFlag(HAS_REFERENCE_CARRIER_FREQUENCY_FOR_ISB);
+        mReferenceCarrierFrequencyHzForIsb = value;
+    }
+
+    /**
+     * Resets the reference carrier frequency in Hz for inter-signal bias.
+     * @hide
+     */
+    @TestApi
+    public void resetReferenceCarrierFrequencyHzForIsb() {
+        resetFlag(HAS_REFERENCE_CARRIER_FREQUENCY_FOR_ISB);
+    }
+
+    /**
+     * Returns {@code true} if {@link #getReferenceCodeTypeForIsb()} is available, {@code
+     * false} otherwise.
+     */
+    public boolean hasReferenceCodeTypeForIsb() {
+        return isFlagSet(HAS_REFERENCE_CODE_TYPE_FOR_ISB);
+    }
+
+    /**
+     * Returns the reference code type for inter-signal bias.
+     *
+     * <p>The value is only available if {@link #hasReferenceCodeTypeForIsb()} is
+     * {@code true}.
+     *
+     * <p>The return value is one of those constants defined in
+     * {@link GnssMeasurement#getCodeType()}.
+     */
+    @NonNull
+    public String getReferenceCodeTypeForIsb() {
+        return mReferenceCodeTypeForIsb;
+    }
+
+    /**
+     * Sets the reference code type for inter-signal bias.
+     * @hide
+     */
+    @TestApi
+    public void setReferenceCodeTypeForIsb(@NonNull String codeType) {
+        setFlag(HAS_REFERENCE_CODE_TYPE_FOR_ISB);
+        mReferenceCodeTypeForIsb = codeType;
+    }
+
+    /**
+     * Resets the reference code type for inter-signal bias.
+     * @hide
+     */
+    @TestApi
+    public void resetReferenceCodeTypeForIsb() {
+        resetFlag(HAS_REFERENCE_CODE_TYPE_FOR_ISB);
+        mReferenceCodeTypeForIsb = "UNKNOWN";
     }
 
     /**
@@ -543,6 +669,9 @@
             gpsClock.mHardwareClockDiscontinuityCount = parcel.readInt();
             gpsClock.mElapsedRealtimeNanos = parcel.readLong();
             gpsClock.mElapsedRealtimeUncertaintyNanos = parcel.readDouble();
+            gpsClock.mReferenceConstellationTypeForIsb = parcel.readInt();
+            gpsClock.mReferenceCarrierFrequencyHzForIsb = parcel.readDouble();
+            gpsClock.mReferenceCodeTypeForIsb = parcel.readString();
 
             return gpsClock;
         }
@@ -567,6 +696,9 @@
         parcel.writeInt(mHardwareClockDiscontinuityCount);
         parcel.writeLong(mElapsedRealtimeNanos);
         parcel.writeDouble(mElapsedRealtimeUncertaintyNanos);
+        parcel.writeInt(mReferenceConstellationTypeForIsb);
+        parcel.writeDouble(mReferenceCarrierFrequencyHzForIsb);
+        parcel.writeString(mReferenceCodeTypeForIsb);
     }
 
     @Override
@@ -580,7 +712,9 @@
         final String formatWithUncertainty = "   %-15s = %-25s   %-26s = %s\n";
         StringBuilder builder = new StringBuilder("GnssClock:\n");
 
-        builder.append(String.format(format, "LeapSecond", hasLeapSecond() ? mLeapSecond : null));
+        if (hasLeapSecond()) {
+            builder.append(String.format(format, "LeapSecond", mLeapSecond));
+        }
 
         builder.append(String.format(
                 formatWithUncertainty,
@@ -589,39 +723,57 @@
                 "TimeUncertaintyNanos",
                 hasTimeUncertaintyNanos() ? mTimeUncertaintyNanos : null));
 
-        builder.append(String.format(
-                format,
-                "FullBiasNanos",
-                hasFullBiasNanos() ? mFullBiasNanos : null));
+        if (hasFullBiasNanos()) {
+            builder.append(String.format(format, "FullBiasNanos", mFullBiasNanos));
+        }
 
-        builder.append(String.format(
-                formatWithUncertainty,
-                "BiasNanos",
-                hasBiasNanos() ? mBiasNanos : null,
-                "BiasUncertaintyNanos",
-                hasBiasUncertaintyNanos() ? mBiasUncertaintyNanos : null));
+        if (hasBiasNanos() || hasBiasUncertaintyNanos()) {
+            builder.append(String.format(
+                    formatWithUncertainty,
+                    "BiasNanos",
+                    hasBiasNanos() ? mBiasNanos : null,
+                    "BiasUncertaintyNanos",
+                    hasBiasUncertaintyNanos() ? mBiasUncertaintyNanos : null));
+        }
 
-        builder.append(String.format(
-                formatWithUncertainty,
-                "DriftNanosPerSecond",
-                hasDriftNanosPerSecond() ? mDriftNanosPerSecond : null,
-                "DriftUncertaintyNanosPerSecond",
-                hasDriftUncertaintyNanosPerSecond() ? mDriftUncertaintyNanosPerSecond : null));
+        if (hasDriftNanosPerSecond() || hasDriftUncertaintyNanosPerSecond()) {
+            builder.append(String.format(
+                    formatWithUncertainty,
+                    "DriftNanosPerSecond",
+                    hasDriftNanosPerSecond() ? mDriftNanosPerSecond : null,
+                    "DriftUncertaintyNanosPerSecond",
+                    hasDriftUncertaintyNanosPerSecond() ? mDriftUncertaintyNanosPerSecond : null));
+        }
 
         builder.append(String.format(
                 format,
                 "HardwareClockDiscontinuityCount",
                 mHardwareClockDiscontinuityCount));
 
-        builder.append(String.format(
-                format,
-                "ElapsedRealtimeNanos",
-                hasElapsedRealtimeNanos() ? mElapsedRealtimeNanos : null));
+        if (hasElapsedRealtimeNanos() || hasElapsedRealtimeUncertaintyNanos()) {
+            builder.append(String.format(
+                    formatWithUncertainty,
+                    "ElapsedRealtimeNanos",
+                    hasElapsedRealtimeNanos() ? mElapsedRealtimeNanos : null,
+                    "ElapsedRealtimeUncertaintyNanos",
+                    hasElapsedRealtimeUncertaintyNanos() ? mElapsedRealtimeUncertaintyNanos
+                            : null));
+        }
 
-        builder.append(String.format(
-                format,
-                "ElapsedRealtimeUncertaintyNanos",
-                hasElapsedRealtimeUncertaintyNanos() ? mElapsedRealtimeUncertaintyNanos : null));
+        if (hasReferenceConstellationTypeForIsb()) {
+            builder.append(String.format(format, "ReferenceConstellationTypeForIsb",
+                    mReferenceConstellationTypeForIsb));
+        }
+
+        if (hasReferenceCarrierFrequencyHzForIsb()) {
+            builder.append(String.format(format, "ReferenceCarrierFrequencyHzForIsb",
+                    mReferenceCarrierFrequencyHzForIsb));
+        }
+
+        if (hasReferenceCodeTypeForIsb()) {
+            builder.append(
+                    String.format(format, "ReferenceCodeTypeForIsb", mReferenceCodeTypeForIsb));
+        }
 
         return builder.toString();
     }
@@ -639,6 +791,9 @@
         setHardwareClockDiscontinuityCount(Integer.MIN_VALUE);
         resetElapsedRealtimeNanos();
         resetElapsedRealtimeUncertaintyNanos();
+        resetReferenceConstellationTypeForIsb();
+        resetReferenceCarrierFrequencyHzForIsb();
+        resetReferenceCodeTypeForIsb();
     }
 
     private void setFlag(int flag) {
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index 3eeb3a2..83a8995 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -16,11 +16,21 @@
 
 package android.location;
 
+import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_AUTOMATIC_GAIN_CONTROL;
+import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_CARRIER_CYCLES;
+import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_CARRIER_FREQUENCY;
+import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_CARRIER_PHASE;
+import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_CARRIER_PHASE_UNCERTAINTY;
+import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_RECEIVER_ISB;
+import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_RECEIVER_ISB_UNCERTAINTY;
+import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_SATELLITE_ISB;
+import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_SATELLITE_ISB_UNCERTAINTY;
+import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_SNR;
+
 import android.annotation.FloatRange;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.TestApi;
-import android.hardware.gnss.V1_0.IGnssMeasurementCallback.GnssMeasurementFlags;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -53,19 +63,14 @@
     private double mSnrInDb;
     private double mAutomaticGainControlLevelInDb;
     @NonNull private String mCodeType;
+    private double mReceiverInterSignalBiasNanos;
+    private double mReceiverInterSignalBiasUncertaintyNanos;
+    private double mSatelliteInterSignalBiasNanos;
+    private double mSatelliteInterSignalBiasUncertaintyNanos;
 
     // The following enumerations must be in sync with the values declared in GNSS HAL.
 
     private static final int HAS_NO_FLAGS = 0;
-    private static final int HAS_SNR = GnssMeasurementFlags.HAS_SNR;
-    private static final int HAS_CARRIER_FREQUENCY = GnssMeasurementFlags.HAS_CARRIER_FREQUENCY;
-    private static final int HAS_CARRIER_CYCLES = GnssMeasurementFlags.HAS_CARRIER_CYCLES;
-    private static final int HAS_CARRIER_PHASE = GnssMeasurementFlags.HAS_CARRIER_PHASE;
-    private static final int HAS_CARRIER_PHASE_UNCERTAINTY =
-            GnssMeasurementFlags.HAS_CARRIER_PHASE_UNCERTAINTY;
-    private static final int HAS_AUTOMATIC_GAIN_CONTROL =
-            GnssMeasurementFlags.HAS_AUTOMATIC_GAIN_CONTROL;
-
     private static final int HAS_CODE_TYPE = (1 << 14);
     private static final int HAS_BASEBAND_CN0 = (1 << 15);
 
@@ -263,6 +268,12 @@
         mSnrInDb = measurement.mSnrInDb;
         mAutomaticGainControlLevelInDb = measurement.mAutomaticGainControlLevelInDb;
         mCodeType = measurement.mCodeType;
+        mReceiverInterSignalBiasNanos = measurement.mReceiverInterSignalBiasNanos;
+        mReceiverInterSignalBiasUncertaintyNanos =
+                measurement.mReceiverInterSignalBiasUncertaintyNanos;
+        mSatelliteInterSignalBiasNanos = measurement.mSatelliteInterSignalBiasNanos;
+        mSatelliteInterSignalBiasUncertaintyNanos =
+                measurement.mSatelliteInterSignalBiasUncertaintyNanos;
     }
 
     /**
@@ -838,7 +849,6 @@
     @TestApi
     public void resetBasebandCn0DbHz() {
         resetFlag(HAS_BASEBAND_CN0);
-        mBasebandCn0DbHz = Double.NaN;
     }
 
     /**
@@ -1169,7 +1179,6 @@
     @Deprecated
     public void resetCarrierPhase() {
         resetFlag(HAS_CARRIER_PHASE);
-        mCarrierPhase = Double.NaN;
     }
 
     /**
@@ -1224,7 +1233,6 @@
     @Deprecated
     public void resetCarrierPhaseUncertainty() {
         resetFlag(HAS_CARRIER_PHASE_UNCERTAINTY);
-        mCarrierPhaseUncertainty = Double.NaN;
     }
 
     /**
@@ -1295,7 +1303,6 @@
     @TestApi
     public void resetSnrInDb() {
         resetFlag(HAS_SNR);
-        mSnrInDb = Double.NaN;
     }
 
     /**
@@ -1343,7 +1350,6 @@
     @TestApi
     public void resetAutomaticGainControlLevel() {
         resetFlag(HAS_AUTOMATIC_GAIN_CONTROL);
-        mAutomaticGainControlLevelInDb = Double.NaN;
     }
 
     /**
@@ -1428,7 +1434,200 @@
         mCodeType = "UNKNOWN";
     }
 
-    public static final @android.annotation.NonNull Creator<GnssMeasurement> CREATOR = new Creator<GnssMeasurement>() {
+    /**
+     * Returns {@code true} if {@link #getReceiverInterSignalBiasNanos()} is available,
+     * {@code false} otherwise.
+     */
+    public boolean hasReceiverInterSignalBiasNanos() {
+        return isFlagSet(HAS_RECEIVER_ISB);
+    }
+
+    /**
+     * Gets the GNSS measurement's receiver inter-signal bias in nanoseconds with sub-nanosecond
+     * accuracy.
+     *
+     * <p>This value is the estimated receiver-side inter-system (different from the
+     * constellation in {@link GnssClock#getReferenceConstellationTypeForIsb()} bias and
+     * inter-frequency (different from the carrier frequency in
+     * {@link GnssClock#getReferenceCarrierFrequencyHzForIsb()}) bias. The reported receiver
+     * inter-signal bias must include signal delays caused by:
+     *
+     * <ul>
+     * <li>Receiver inter-constellation bias</li>
+     * <li>Receiver inter-frequency bias</li>
+     * <li>Receiver inter-code bias</li>
+     * </ul>
+     *
+     * <p>The value does not include the inter-frequency Ionospheric bias.
+     *
+     * <p>The value is only available if {@link #hasReceiverInterSignalBiasNanos()} is {@code true}.
+     */
+    public double getReceiverInterSignalBiasNanos() {
+        return mReceiverInterSignalBiasNanos;
+    }
+
+    /**
+     * Sets the GNSS measurement's receiver inter-signal bias in nanoseconds.
+     *
+     * @hide
+     */
+    @TestApi
+    public void setReceiverInterSignalBiasNanos(double receiverInterSignalBiasNanos) {
+        setFlag(HAS_RECEIVER_ISB);
+        mReceiverInterSignalBiasNanos = receiverInterSignalBiasNanos;
+    }
+
+    /**
+     * Resets the GNSS measurement's receiver inter-signal bias in nanoseconds.
+     *
+     * @hide
+     */
+    @TestApi
+    public void resetReceiverInterSignalBiasNanos() {
+        resetFlag(HAS_RECEIVER_ISB);
+    }
+
+    /**
+     * Returns {@code true} if {@link #getReceiverInterSignalBiasUncertaintyNanos()} is available,
+     * {@code false} otherwise.
+     */
+    public boolean hasReceiverInterSignalBiasUncertaintyNanos() {
+        return isFlagSet(HAS_RECEIVER_ISB_UNCERTAINTY);
+    }
+
+    /**
+     * Gets the GNSS measurement's receiver inter-signal bias uncertainty (1 sigma) in
+     * nanoseconds with sub-nanosecond accuracy.
+     *
+     * <p>The value is only available if {@link #hasReceiverInterSignalBiasUncertaintyNanos()} is
+     * {@code true}.
+     */
+    @FloatRange(from = 0.0)
+    public double getReceiverInterSignalBiasUncertaintyNanos() {
+        return mReceiverInterSignalBiasUncertaintyNanos;
+    }
+
+    /**
+     * Sets the GNSS measurement's receiver inter-signal bias uncertainty (1 sigma) in nanoseconds.
+     *
+     * @hide
+     */
+    @TestApi
+    public void setReceiverInterSignalBiasUncertaintyNanos(@FloatRange(from = 0.0)
+            double receiverInterSignalBiasUncertaintyNanos) {
+        setFlag(HAS_RECEIVER_ISB_UNCERTAINTY);
+        mReceiverInterSignalBiasUncertaintyNanos = receiverInterSignalBiasUncertaintyNanos;
+    }
+
+    /**
+     * Resets the GNSS measurement's receiver inter-signal bias uncertainty (1 sigma) in
+     * nanoseconds.
+     *
+     * @hide
+     */
+    @TestApi
+    public void resetReceiverInterSignalBiasUncertaintyNanos() {
+        resetFlag(HAS_RECEIVER_ISB_UNCERTAINTY);
+    }
+
+    /**
+     * Returns {@code true} if {@link #getSatelliteInterSignalBiasNanos()} is available,
+     * {@code false} otherwise.
+     */
+    public boolean hasSatelliteInterSignalBiasNanos() {
+        return isFlagSet(HAS_SATELLITE_ISB);
+    }
+
+    /**
+     * Gets the GNSS measurement's satellite inter-signal bias in nanoseconds with sub-nanosecond
+     * accuracy.
+     *
+     * <p>This value is the satellite-and-control-segment-side inter-system (different from the
+     * constellation in {@link GnssClock#getReferenceConstellationTypeForIsb()}) bias and
+     * inter-frequency (different from the carrier frequency in
+     * {@link GnssClock#getReferenceCarrierFrequencyHzForIsb()}) bias, including:
+     *
+     * <ul>
+     * <li>Master clock bias (e.g., GPS-GAL Time Offset (GGTO), GPT-UTC Time Offset (TauGps),
+     * BDS-GLO Time Offset (BGTO))</li>
+     * <li>Group delay (e.g., Total Group Delay (TGD))</li>
+     * <li>Satellite inter-signal bias, which includes satellite inter-frequency bias (GLO only),
+     * and satellite inter-code bias (e.g., Differential Code Bias (DCB)).</li>
+     * </ul>
+     *
+     * <p>The value is only available if {@link #hasSatelliteInterSignalBiasNanos()} is {@code
+     * true}.
+     */
+    public double getSatelliteInterSignalBiasNanos() {
+        return mSatelliteInterSignalBiasNanos;
+    }
+
+    /**
+     * Sets the GNSS measurement's satellite inter-signal bias in nanoseconds.
+     *
+     * @hide
+     */
+    @TestApi
+    public void setSatelliteInterSignalBiasNanos(double satelliteInterSignalBiasNanos) {
+        setFlag(HAS_SATELLITE_ISB);
+        mSatelliteInterSignalBiasNanos = satelliteInterSignalBiasNanos;
+    }
+
+    /**
+     * Resets the GNSS measurement's satellite inter-signal bias in nanoseconds.
+     *
+     * @hide
+     */
+    @TestApi
+    public void resetSatelliteInterSignalBiasNanos() {
+        resetFlag(HAS_SATELLITE_ISB);
+    }
+
+    /**
+     * Returns {@code true} if {@link #getSatelliteInterSignalBiasUncertaintyNanos()} is available,
+     * {@code false} otherwise.
+     */
+    public boolean hasSatelliteInterSignalBiasUncertaintyNanos() {
+        return isFlagSet(HAS_SATELLITE_ISB_UNCERTAINTY);
+    }
+
+    /**
+     * Gets the GNSS measurement's satellite inter-signal bias uncertainty (1 sigma) in
+     * nanoseconds with sub-nanosecond accuracy.
+     *
+     * <p>The value is only available if {@link #hasSatelliteInterSignalBiasUncertaintyNanos()} is
+     * {@code true}.
+     */
+    @FloatRange(from = 0.0)
+    public double getSatelliteInterSignalBiasUncertaintyNanos() {
+        return mSatelliteInterSignalBiasUncertaintyNanos;
+    }
+
+    /**
+     * Sets the GNSS measurement's satellite inter-signal bias uncertainty (1 sigma) in nanoseconds.
+     *
+     * @hide
+     */
+    @TestApi
+    public void setSatelliteInterSignalBiasUncertaintyNanos(@FloatRange(from = 0.0)
+            double satelliteInterSignalBiasUncertaintyNanos) {
+        setFlag(HAS_SATELLITE_ISB_UNCERTAINTY);
+        mSatelliteInterSignalBiasUncertaintyNanos = satelliteInterSignalBiasUncertaintyNanos;
+    }
+
+    /**
+     * Resets the GNSS measurement's satellite inter-signal bias uncertainty (1 sigma) in
+     * nanoseconds.
+     *
+     * @hide
+     */
+    @TestApi
+    public void resetSatelliteInterSignalBiasUncertaintyNanos() {
+        resetFlag(HAS_SATELLITE_ISB_UNCERTAINTY);
+    }
+
+
+    public static final @NonNull Creator<GnssMeasurement> CREATOR = new Creator<GnssMeasurement>() {
         @Override
         public GnssMeasurement createFromParcel(Parcel parcel) {
             GnssMeasurement gnssMeasurement = new GnssMeasurement();
@@ -1455,6 +1654,10 @@
             gnssMeasurement.mAutomaticGainControlLevelInDb = parcel.readDouble();
             gnssMeasurement.mCodeType = parcel.readString();
             gnssMeasurement.mBasebandCn0DbHz = parcel.readDouble();
+            gnssMeasurement.mReceiverInterSignalBiasNanos = parcel.readDouble();
+            gnssMeasurement.mReceiverInterSignalBiasUncertaintyNanos = parcel.readDouble();
+            gnssMeasurement.mSatelliteInterSignalBiasNanos = parcel.readDouble();
+            gnssMeasurement.mSatelliteInterSignalBiasUncertaintyNanos = parcel.readDouble();
 
             return gnssMeasurement;
         }
@@ -1489,6 +1692,10 @@
         parcel.writeDouble(mAutomaticGainControlLevelInDb);
         parcel.writeString(mCodeType);
         parcel.writeDouble(mBasebandCn0DbHz);
+        parcel.writeDouble(mReceiverInterSignalBiasNanos);
+        parcel.writeDouble(mReceiverInterSignalBiasUncertaintyNanos);
+        parcel.writeDouble(mSatelliteInterSignalBiasNanos);
+        parcel.writeDouble(mSatelliteInterSignalBiasUncertaintyNanos);
     }
 
     @Override
@@ -1517,8 +1724,9 @@
 
         builder.append(String.format(format, "Cn0DbHz", mCn0DbHz));
 
-        builder.append(String.format(format, "BasebandCn0DbHz",
-                hasBasebandCn0DbHz() ? mBasebandCn0DbHz : null));
+        if (hasBasebandCn0DbHz()) {
+            builder.append(String.format(format, "BasebandCn0DbHz", mBasebandCn0DbHz));
+        }
 
         builder.append(String.format(
                 formatWithUncertainty,
@@ -1539,37 +1747,57 @@
                 "AccumulatedDeltaRangeUncertaintyMeters",
                 mAccumulatedDeltaRangeUncertaintyMeters));
 
-        builder.append(String.format(
-                format,
-                "CarrierFrequencyHz",
-                hasCarrierFrequencyHz() ? mCarrierFrequencyHz : null));
+        if (hasCarrierFrequencyHz()) {
+            builder.append(String.format(format, "CarrierFrequencyHz", mCarrierFrequencyHz));
+        }
 
-        builder.append(String.format(
-                format,
-                "CarrierCycles",
-                hasCarrierCycles() ? mCarrierCycles : null));
+        if (hasCarrierCycles()) {
+            builder.append(String.format(format, "CarrierCycles", mCarrierCycles));
+        }
 
-        builder.append(String.format(
-                formatWithUncertainty,
-                "CarrierPhase",
-                hasCarrierPhase() ? mCarrierPhase : null,
-                "CarrierPhaseUncertainty",
-                hasCarrierPhaseUncertainty() ? mCarrierPhaseUncertainty : null));
+        if (hasCarrierPhase() || hasCarrierPhaseUncertainty()) {
+            builder.append(String.format(
+                    formatWithUncertainty,
+                    "CarrierPhase",
+                    hasCarrierPhase() ? mCarrierPhase : null,
+                    "CarrierPhaseUncertainty",
+                    hasCarrierPhaseUncertainty() ? mCarrierPhaseUncertainty : null));
+        }
 
         builder.append(String.format(format, "MultipathIndicator", getMultipathIndicatorString()));
 
-        builder.append(String.format(
-                format,
-                "SnrInDb",
-                hasSnrInDb() ? mSnrInDb : null));
-        builder.append(String.format(
-                format,
-                "AgcLevelDb",
-                hasAutomaticGainControlLevelDb() ? mAutomaticGainControlLevelInDb : null));
-        builder.append(String.format(
-                format,
-                "CodeType",
-                hasCodeType() ? mCodeType : null));
+        if (hasSnrInDb()) {
+            builder.append(String.format(format, "SnrInDb", mSnrInDb));
+        }
+
+        if (hasAutomaticGainControlLevelDb()) {
+            builder.append(String.format(format, "AgcLevelDb", mAutomaticGainControlLevelInDb));
+        }
+
+        if (hasCodeType()) {
+            builder.append(String.format(format, "CodeType", mCodeType));
+        }
+
+        if (hasReceiverInterSignalBiasNanos() || hasReceiverInterSignalBiasUncertaintyNanos()) {
+            builder.append(String.format(
+                    formatWithUncertainty,
+                    "ReceiverInterSignalBiasNs",
+                    hasReceiverInterSignalBiasNanos() ? mReceiverInterSignalBiasNanos : null,
+                    "ReceiverInterSignalBiasUncertaintyNs",
+                    hasReceiverInterSignalBiasUncertaintyNanos()
+                            ? mReceiverInterSignalBiasUncertaintyNanos : null));
+        }
+
+        if (hasSatelliteInterSignalBiasNanos() || hasSatelliteInterSignalBiasUncertaintyNanos()) {
+            builder.append(String.format(
+                    formatWithUncertainty,
+                    "SatelliteInterSignalBiasNs",
+                    hasSatelliteInterSignalBiasNanos() ? mSatelliteInterSignalBiasNanos : null,
+                    "SatelliteInterSignalBiasUncertaintyNs",
+                    hasSatelliteInterSignalBiasUncertaintyNanos()
+                            ? mSatelliteInterSignalBiasUncertaintyNanos
+                            : null));
+        }
 
         return builder.toString();
     }
@@ -1596,6 +1824,10 @@
         resetAutomaticGainControlLevel();
         resetCodeType();
         resetBasebandCn0DbHz();
+        resetReceiverInterSignalBiasNanos();
+        resetReceiverInterSignalBiasUncertaintyNanos();
+        resetSatelliteInterSignalBiasNanos();
+        resetSatelliteInterSignalBiasUncertaintyNanos();
     }
 
     private void setFlag(int flag) {
diff --git a/location/java/android/location/GnssMeasurementCorrections.java b/location/java/android/location/GnssMeasurementCorrections.java
index a23213f..19c3992 100644
--- a/location/java/android/location/GnssMeasurementCorrections.java
+++ b/location/java/android/location/GnssMeasurementCorrections.java
@@ -79,6 +79,25 @@
     @NonNull
     private final List<GnssSingleSatCorrection> mSingleSatCorrectionList;
 
+    /**
+     * Indicates whether the environment bearing is available.
+     */
+    private final boolean mHasEnvironmentBearing;
+
+    /**
+     * Environment bearing in degrees clockwise from true north, in the direction of user motion.
+     * Environment bearing is provided when it is known with high probability that velocity is
+     * aligned with an environment feature (such as edge of a building, or road).
+     */
+    @FloatRange(from = 0.0f, to = 360.0f)
+    private final float mEnvironmentBearingDegrees;
+
+    /**
+     * Environment bearing uncertainty in degrees.
+     */
+    @FloatRange(from = 0.0f, to = 180.0f)
+    private final float mEnvironmentBearingUncertaintyDegrees;
+
     private GnssMeasurementCorrections(Builder builder) {
         mLatitudeDegrees = builder.mLatitudeDegrees;
         mLongitudeDegrees = builder.mLongitudeDegrees;
@@ -89,6 +108,10 @@
         final List<GnssSingleSatCorrection> singleSatCorrList =  builder.mSingleSatCorrectionList;
         Preconditions.checkArgument(singleSatCorrList != null && !singleSatCorrList.isEmpty());
         mSingleSatCorrectionList = Collections.unmodifiableList(new ArrayList<>(singleSatCorrList));
+        mHasEnvironmentBearing = builder.mEnvironmentBearingIsSet
+                && builder.mEnvironmentBearingUncertaintyIsSet;
+        mEnvironmentBearingDegrees = builder.mEnvironmentBearingDegrees;
+        mEnvironmentBearingUncertaintyDegrees = builder.mEnvironmentBearingUncertaintyDegrees;
     }
 
     /** Gets the latitude in degrees at which the corrections are computed. */
@@ -145,6 +168,31 @@
         return mSingleSatCorrectionList;
     }
 
+    /**
+     * If true, environment bearing will be available.
+     */
+    public boolean hasEnvironmentBearing() {
+        return mHasEnvironmentBearing;
+    }
+
+    /**
+     * Gets the environment bearing in degrees clockwise from true north, in the direction of user
+     * motion. Environment bearing is provided when it is known with high probability that
+     * velocity is aligned with an environment feature (such as edge of a building, or road).
+     */
+    @FloatRange(from = 0.0f, to = 360.0f)
+    public float getEnvironmentBearingDegrees() {
+        return mEnvironmentBearingDegrees;
+    }
+
+    /**
+     * Gets the environment bearing uncertainty in degrees.
+     */
+    @FloatRange(from = 0.0f, to = 180.0f)
+    public float getEnvironmentBearingUncertaintyDegrees() {
+        return mEnvironmentBearingUncertaintyDegrees;
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -167,6 +215,12 @@
                     parcel.readTypedList(singleSatCorrectionList, GnssSingleSatCorrection.CREATOR);
                     gnssMeasurementCorrectons.setSingleSatelliteCorrectionList(
                             singleSatCorrectionList);
+                    boolean hasEnvironmentBearing = parcel.readBoolean();
+                    if (hasEnvironmentBearing) {
+                        gnssMeasurementCorrectons.setEnvironmentBearingDegrees(parcel.readFloat());
+                        gnssMeasurementCorrectons.setEnvironmentBearingUncertaintyDegrees(
+                                parcel.readFloat());
+                    }
                     return gnssMeasurementCorrectons.build();
                 }
 
@@ -192,6 +246,14 @@
                 String.format(format, "ToaGpsNanosecondsOfWeek = ", mToaGpsNanosecondsOfWeek));
         builder.append(
                 String.format(format, "mSingleSatCorrectionList = ", mSingleSatCorrectionList));
+        builder.append(
+                String.format(format, "HasEnvironmentBearing = ", mHasEnvironmentBearing));
+        builder.append(
+                String.format(format, "EnvironmentBearingDegrees = ",
+                        mEnvironmentBearingDegrees));
+        builder.append(
+                String.format(format, "EnvironmentBearingUncertaintyDegrees = ",
+                mEnvironmentBearingUncertaintyDegrees));
         return builder.toString();
     }
 
@@ -204,6 +266,11 @@
         parcel.writeDouble(mVerticalPositionUncertaintyMeters);
         parcel.writeLong(mToaGpsNanosecondsOfWeek);
         parcel.writeTypedList(mSingleSatCorrectionList);
+        parcel.writeBoolean(mHasEnvironmentBearing);
+        if (mHasEnvironmentBearing) {
+            parcel.writeFloat(mEnvironmentBearingDegrees);
+            parcel.writeFloat(mEnvironmentBearingUncertaintyDegrees);
+        }
     }
 
     /** Builder for {@link GnssMeasurementCorrections} */
@@ -219,6 +286,10 @@
         private double mVerticalPositionUncertaintyMeters;
         private long mToaGpsNanosecondsOfWeek;
         @Nullable private List<GnssSingleSatCorrection> mSingleSatCorrectionList;
+        private float mEnvironmentBearingDegrees;
+        private boolean mEnvironmentBearingIsSet = false;
+        private float mEnvironmentBearingUncertaintyDegrees;
+        private boolean mEnvironmentBearingUncertaintyIsSet = false;
 
         /** Sets the latitude in degrees at which the corrections are computed. */
         @NonNull public Builder setLatitudeDegrees(
@@ -282,8 +353,37 @@
             return this;
         }
 
+        /**
+         * Sets the environment bearing in degrees clockwise from true north, in the direction of
+         * user motion. Environment bearing is provided when it is known with high probability
+         * that velocity is aligned with an environment feature (such as edge of a building, or
+         * road).
+         */
+        @NonNull public Builder setEnvironmentBearingDegrees(
+                @FloatRange(from = 0.0f, to = 360.0f)
+                        float environmentBearingDegrees) {
+            mEnvironmentBearingDegrees = environmentBearingDegrees;
+            mEnvironmentBearingIsSet = true;
+            return this;
+        }
+
+        /**
+         * Sets the environment bearing uncertainty in degrees.
+         */
+        @NonNull public Builder setEnvironmentBearingUncertaintyDegrees(
+                @FloatRange(from = 0.0f, to = 180.0f)
+                        float environmentBearingUncertaintyDegrees) {
+            mEnvironmentBearingUncertaintyDegrees = environmentBearingUncertaintyDegrees;
+            mEnvironmentBearingUncertaintyIsSet = true;
+            return this;
+        }
+
         /** Builds a {@link GnssMeasurementCorrections} instance as specified by this builder. */
         @NonNull public GnssMeasurementCorrections build() {
+            if (mEnvironmentBearingIsSet ^ mEnvironmentBearingUncertaintyIsSet) {
+                throw new IllegalStateException("Both environment bearing and environment bearing "
+                        + "uncertainty must be set.");
+            }
             return new GnssMeasurementCorrections(this);
         }
     }
diff --git a/location/java/android/location/GnssStatus.java b/location/java/android/location/GnssStatus.java
index 89a3bc0..f17fa39 100644
--- a/location/java/android/location/GnssStatus.java
+++ b/location/java/android/location/GnssStatus.java
@@ -189,6 +189,7 @@
      * <li>QZSS: 193-200</li>
      * <li>Galileo: 1-36</li>
      * <li>Beidou: 1-37</li>
+     * <li>IRNSS: 1-14</li>
      * </ul>
      *
      * @param satelliteIndex An index from zero to {@link #getSatelliteCount()} - 1
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 687535c3..0c5fe78 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -74,7 +74,7 @@
  * still return location results, but the exact location will be obfuscated to a coarse level of
  * accuracy.
  */
-@SuppressWarnings({"deprecation", "DeprecatedIsStillUsed"})
+@SuppressWarnings({"deprecation"})
 @SystemService(Context.LOCATION_SERVICE)
 @RequiresFeature(PackageManager.FEATURE_LOCATION)
 public class LocationManager {
diff --git a/location/java/android/location/LocationManagerInternal.java b/location/java/android/location/LocationManagerInternal.java
new file mode 100644
index 0000000..44d9d23
--- /dev/null
+++ b/location/java/android/location/LocationManagerInternal.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.location;
+
+
+import android.annotation.NonNull;
+
+/**
+ * Location manager local system service interface.
+ *
+ * @hide Only for use within the system server.
+ */
+public abstract class LocationManagerInternal {
+
+    /**
+     * Requests that a provider change its allowed state. A provider may or may not honor this
+     * request, and if the provider does change its state as a result, that may happen
+     * asynchronously after some delay.
+     *
+     * <p>Setting a provider's state to allowed implies that any consents or terms and conditions
+     * that may be necessary to allow the provider are agreed to. Setting a providers state to
+     * disallowed implies that any consents or terms and conditions have their agreement revoked.
+     *
+     * @param provider A location provider as listed by {@link LocationManager#getAllProviders()}
+     * @param allowed  Whether the location provider is being requested to allow or disallow
+     *                 itself
+     * @throws IllegalArgumentException if provider is null
+     */
+    public abstract void requestSetProviderAllowed(@NonNull String provider, boolean allowed);
+}
diff --git a/location/java/com/android/internal/location/ILocationProvider.aidl b/location/java/com/android/internal/location/ILocationProvider.aidl
index 4246c6c..b7817ff 100644
--- a/location/java/com/android/internal/location/ILocationProvider.aidl
+++ b/location/java/com/android/internal/location/ILocationProvider.aidl
@@ -37,4 +37,6 @@
 
     @UnsupportedAppUsage
     oneway void sendExtraCommand(String command, in Bundle extras);
+
+    oneway void requestSetAllowed(boolean allowed);
 }
diff --git a/location/java/com/android/internal/location/ILocationProviderManager.aidl b/location/java/com/android/internal/location/ILocationProviderManager.aidl
index 85e18ba..4390391 100644
--- a/location/java/com/android/internal/location/ILocationProviderManager.aidl
+++ b/location/java/com/android/internal/location/ILocationProviderManager.aidl
@@ -29,7 +29,7 @@
     void onSetAdditionalProviderPackages(in List<String> packageNames);
 
     @UnsupportedAppUsage
-    void onSetEnabled(boolean enabled);
+    void onSetAllowed(boolean allowed);
 
     @UnsupportedAppUsage
     void onSetProperties(in ProviderProperties properties);
diff --git a/location/lib/api/current.txt b/location/lib/api/current.txt
index 5471bea..49fcaab 100644
--- a/location/lib/api/current.txt
+++ b/location/lib/api/current.txt
@@ -9,18 +9,21 @@
   public abstract class LocationProviderBase {
     ctor public LocationProviderBase(String, com.android.location.provider.ProviderPropertiesUnbundled);
     method public android.os.IBinder getBinder();
-    method @RequiresApi(android.os.Build.VERSION_CODES.Q) public boolean isEnabled();
+    method @RequiresApi(android.os.Build.VERSION_CODES.R) public boolean isAllowed();
+    method @Deprecated @RequiresApi(android.os.Build.VERSION_CODES.Q) public boolean isEnabled();
     method @Deprecated protected void onDisable();
     method @Deprecated protected void onDump(java.io.FileDescriptor, java.io.PrintWriter, String[]);
     method @Deprecated protected void onEnable();
     method @Deprecated protected int onGetStatus(android.os.Bundle);
     method @Deprecated protected long onGetStatusUpdateTime();
     method protected void onInit();
+    method protected void onRequestSetAllowed(boolean);
     method protected boolean onSendExtraCommand(@Nullable String, @Nullable android.os.Bundle);
     method protected abstract void onSetRequest(com.android.location.provider.ProviderRequestUnbundled, android.os.WorkSource);
     method public void reportLocation(android.location.Location);
     method @RequiresApi(android.os.Build.VERSION_CODES.Q) public void setAdditionalProviderPackages(java.util.List<java.lang.String>);
-    method @RequiresApi(android.os.Build.VERSION_CODES.Q) public void setEnabled(boolean);
+    method @RequiresApi(android.os.Build.VERSION_CODES.R) public void setAllowed(boolean);
+    method @Deprecated @RequiresApi(android.os.Build.VERSION_CODES.Q) public void setEnabled(boolean);
     method @RequiresApi(android.os.Build.VERSION_CODES.Q) public void setProperties(com.android.location.provider.ProviderPropertiesUnbundled);
     field public static final String EXTRA_NO_GPS_LOCATION = "noGPSLocation";
     field public static final String FUSED_PROVIDER = "fused";
diff --git a/location/lib/java/com/android/location/provider/LocationProviderBase.java b/location/lib/java/com/android/location/provider/LocationProviderBase.java
index fc7bff3..f67d08e 100644
--- a/location/lib/java/com/android/location/provider/LocationProviderBase.java
+++ b/location/lib/java/com/android/location/provider/LocationProviderBase.java
@@ -92,7 +92,7 @@
     // write locked on mBinder, read lock is optional depending on atomicity requirements
     @Nullable private volatile ILocationProviderManager mManager;
     private volatile ProviderProperties mProperties;
-    private volatile boolean mEnabled;
+    private volatile boolean mAllowed;
     private final ArrayList<String> mAdditionalProviderPackages;
 
     public LocationProviderBase(String tag, ProviderPropertiesUnbundled properties) {
@@ -104,7 +104,7 @@
 
         mManager = null;
         mProperties = properties.getProviderProperties();
-        mEnabled = true;
+        mAllowed = true;
         mAdditionalProviderPackages = new ArrayList<>(0);
     }
 
@@ -113,35 +113,44 @@
     }
 
     /**
-     * Sets whether this provider is currently enabled or not. Note that this is specific to the
-     * provider only, and is not related to global location settings. This is a hint to the Location
-     * Manager that this provider will generally be unable to fulfill incoming requests. This
-     * provider may still receive callbacks to onSetRequest while not enabled, and must decide
-     * whether to attempt to satisfy those requests or not.
-     *
-     * Some guidelines: providers should set their own enabled/disabled status based only on state
-     * "owned" by that provider. For instance, providers should not take into account the state of
-     * the location master setting when setting themselves enabled or disabled, as this state is not
-     * owned by a particular provider. If a provider requires some additional user consent that is
-     * particular to the provider, this should be use to set the enabled/disabled state. If the
-     * provider proxies to another provider, the child provider's enabled/disabled state should be
-     * taken into account in the parent's enabled/disabled state. For most providers, it is expected
-     * that they will be always enabled.
+     * @deprecated Use {@link #setAllowed(boolean)} instead.
      */
+    @Deprecated
     @RequiresApi(VERSION_CODES.Q)
     public void setEnabled(boolean enabled) {
+        setAllowed(enabled);
+    }
+
+    /**
+     * Sets whether this provider is currently allowed or not. Note that this is specific to the
+     * provider only, and is not related to global location settings. This is a hint to the Location
+     * Manager that this provider will generally be unable to fulfill incoming requests. This
+     * provider may still receive callbacks to onSetRequest while not allowed, and must decide
+     * whether to attempt to satisfy those requests or not.
+     *
+     * <p>Some guidelines: providers should set their own allowed/disallowed status based only on
+     * state "owned" by that provider. For instance, providers should not take into account the
+     * state of the location master setting when setting themselves allowed or disallowed, as this
+     * state is not owned by a particular provider. If a provider requires some additional user
+     * consent that is particular to the provider, this should be use to set the allowed/disallowed
+     * state. If the provider proxies to another provider, the child provider's allowed/disallowed
+     * state should be taken into account in the parent's allowed state. For most providers, it is
+     * expected that they will be always allowed.
+     */
+    @RequiresApi(VERSION_CODES.R)
+    public void setAllowed(boolean allowed) {
         synchronized (mBinder) {
-            if (mEnabled == enabled) {
+            if (mAllowed == allowed) {
                 return;
             }
 
-            mEnabled = enabled;
+            mAllowed = allowed;
         }
 
         ILocationProviderManager manager = mManager;
         if (manager != null) {
             try {
-                manager.onSetEnabled(mEnabled);
+                manager.onSetAllowed(mAllowed);
             } catch (RemoteException | RuntimeException e) {
                 Log.w(mTag, e);
             }
@@ -193,12 +202,20 @@
     }
 
     /**
-     * Returns true if this provider has been set as enabled. This will be true unless explicitly
-     * set otherwise.
+     * @deprecated Use {@link #isAllowed()} instead.
      */
+    @Deprecated
     @RequiresApi(VERSION_CODES.Q)
     public boolean isEnabled() {
-        return mEnabled;
+        return isAllowed();
+    }
+
+    /**
+     * Returns true if this provider is allowed. Providers start as allowed on construction.
+     */
+    @RequiresApi(VERSION_CODES.R)
+    public boolean isAllowed() {
+        return mAllowed;
     }
 
     /**
@@ -285,6 +302,17 @@
         return false;
     }
 
+    /**
+     * Invoked when the system wishes to request that the provider sets its allowed state as
+     * desired. This implies that the caller is providing/retracting consent for any terms and
+     * conditions or consents associated with the provider.
+     *
+     * <p>It is generally only necessary to override this function if the provider has some barriers
+     * or gates for enabling/disabling itself, in which case this function should handle those
+     * appropriately. A provider that is always allowed has no need to override this function.
+     */
+    protected void onRequestSetAllowed(boolean allowed) {}
+
     private final class Service extends ILocationProvider.Stub {
 
         @Override
@@ -295,7 +323,7 @@
                         manager.onSetAdditionalProviderPackages(mAdditionalProviderPackages);
                     }
                     manager.onSetProperties(mProperties);
-                    manager.onSetEnabled(mEnabled);
+                    manager.onSetAllowed(mAllowed);
                 } catch (RemoteException e) {
                     Log.w(mTag, e);
                 }
@@ -315,5 +343,10 @@
         public void sendExtraCommand(String command, Bundle extras) {
             onSendExtraCommand(command, extras);
         }
+
+        @Override
+        public void requestSetAllowed(boolean allowed) {
+            onRequestSetAllowed(allowed);
+        }
     }
 }
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index cbc9683..197786f 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -763,7 +763,13 @@
                 int maxLevel = 0;
                 for (CodecProfileLevel pl : profileLevels) {
                     if (pl.profile == profile && pl.level > maxLevel) {
-                        maxLevel = pl.level;
+                        // H.263 levels are not completely ordered:
+                        // Level45 support only implies Level10 support
+                        if (!mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_H263)
+                                || pl.level != CodecProfileLevel.H263Level45
+                                || maxLevel == CodecProfileLevel.H263Level10) {
+                            maxLevel = pl.level;
+                        }
                     }
                 }
                 levelCaps = createFromProfileLevel(mMime, profile, maxLevel);
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index f408ac3..57405d7 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -20,6 +20,8 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
+import android.media.MediaCodec;
+import android.media.MediaParser;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -45,10 +47,12 @@
  * <table>
  * <tr><th>Name</th><th>Value Type</th><th>Description</th></tr>
  * <tr><td>{@link #KEY_MIME}</td><td>String</td><td>The type of the format.</td></tr>
+ * <tr><td>{@link #KEY_CODECS_STRING}</td><td>String</td><td>optional, the RFC 6381 codecs string of the MediaFormat</td></tr>
  * <tr><td>{@link #KEY_MAX_INPUT_SIZE}</td><td>Integer</td><td>optional, maximum size of a buffer of input data</td></tr>
  * <tr><td>{@link #KEY_PIXEL_ASPECT_RATIO_WIDTH}</td><td>Integer</td><td>optional, the pixel aspect ratio width</td></tr>
  * <tr><td>{@link #KEY_PIXEL_ASPECT_RATIO_HEIGHT}</td><td>Integer</td><td>optional, the pixel aspect ratio height</td></tr>
  * <tr><td>{@link #KEY_BIT_RATE}</td><td>Integer</td><td><b>encoder-only</b>, desired bitrate in bits/second</td></tr>
+ * <tr><td>{@link #KEY_DURATION}</td><td>long</td><td>the duration of the content (in microseconds)</td></tr>
  * </table>
  *
  * Video formats have the following keys:
@@ -217,6 +221,15 @@
     public static final String KEY_MIME = "mime";
 
     /**
+     * A key describing the codecs string of the MediaFormat. See RFC 6381 section 3.2 for the
+     * syntax of the value. The value does not hold {@link MediaCodec}-exposed codec names.
+     * The associated value is a string.
+     *
+     * @see MediaParser.TrackData#mediaFormat
+     */
+    public static final String KEY_CODECS_STRING = "codecs-string";
+
+    /**
      * An optional key describing the low latency decoding mode. This is an optional parameter
      * that applies only to decoders. If enabled, the decoder doesn't hold input and output
      * data more than required by the codec standards.
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index 4cd581b..1617b87 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -28,6 +28,7 @@
 import android.net.Uri;
 import android.os.Build;
 import android.os.IBinder;
+import android.text.TextUtils;
 
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
@@ -44,6 +45,162 @@
  * frame and meta data from an input media file.
  */
 public class MediaMetadataRetriever implements AutoCloseable {
+
+    // borrowed from ExoPlayer
+    private static final String[] STANDARD_GENRES = new String[] {
+            // These are the official ID3v1 genres.
+            "Blues",
+            "Classic Rock",
+            "Country",
+            "Dance",
+            "Disco",
+            "Funk",
+            "Grunge",
+            "Hip-Hop",
+            "Jazz",
+            "Metal",
+            "New Age",
+            "Oldies",
+            "Other",
+            "Pop",
+            "R&B",
+            "Rap",
+            "Reggae",
+            "Rock",
+            "Techno",
+            "Industrial",
+            "Alternative",
+            "Ska",
+            "Death Metal",
+            "Pranks",
+            "Soundtrack",
+            "Euro-Techno",
+            "Ambient",
+            "Trip-Hop",
+            "Vocal",
+            "Jazz+Funk",
+            "Fusion",
+            "Trance",
+            "Classical",
+            "Instrumental",
+            "Acid",
+            "House",
+            "Game",
+            "Sound Clip",
+            "Gospel",
+            "Noise",
+            "AlternRock",
+            "Bass",
+            "Soul",
+            "Punk",
+            "Space",
+            "Meditative",
+            "Instrumental Pop",
+            "Instrumental Rock",
+            "Ethnic",
+            "Gothic",
+            "Darkwave",
+            "Techno-Industrial",
+            "Electronic",
+            "Pop-Folk",
+            "Eurodance",
+            "Dream",
+            "Southern Rock",
+            "Comedy",
+            "Cult",
+            "Gangsta",
+            "Top 40",
+            "Christian Rap",
+            "Pop/Funk",
+            "Jungle",
+            "Native American",
+            "Cabaret",
+            "New Wave",
+            "Psychadelic",
+            "Rave",
+            "Showtunes",
+            "Trailer",
+            "Lo-Fi",
+            "Tribal",
+            "Acid Punk",
+            "Acid Jazz",
+            "Polka",
+            "Retro",
+            "Musical",
+            "Rock & Roll",
+            "Hard Rock",
+            // These were made up by the authors of Winamp and later added to the ID3 spec.
+            "Folk",
+            "Folk-Rock",
+            "National Folk",
+            "Swing",
+            "Fast Fusion",
+            "Bebob",
+            "Latin",
+            "Revival",
+            "Celtic",
+            "Bluegrass",
+            "Avantgarde",
+            "Gothic Rock",
+            "Progressive Rock",
+            "Psychedelic Rock",
+            "Symphonic Rock",
+            "Slow Rock",
+            "Big Band",
+            "Chorus",
+            "Easy Listening",
+            "Acoustic",
+            "Humour",
+            "Speech",
+            "Chanson",
+            "Opera",
+            "Chamber Music",
+            "Sonata",
+            "Symphony",
+            "Booty Bass",
+            "Primus",
+            "Porn Groove",
+            "Satire",
+            "Slow Jam",
+            "Club",
+            "Tango",
+            "Samba",
+            "Folklore",
+            "Ballad",
+            "Power Ballad",
+            "Rhythmic Soul",
+            "Freestyle",
+            "Duet",
+            "Punk Rock",
+            "Drum Solo",
+            "A capella",
+            "Euro-House",
+            "Dance Hall",
+            // These were made up by the authors of Winamp but have not been added to the ID3 spec.
+            "Goa",
+            "Drum & Bass",
+            "Club-House",
+            "Hardcore",
+            "Terror",
+            "Indie",
+            "BritPop",
+            "Afro-Punk",
+            "Polsk Punk",
+            "Beat",
+            "Christian Gangsta Rap",
+            "Heavy Metal",
+            "Black Metal",
+            "Crossover",
+            "Contemporary Christian",
+            "Christian Rock",
+            "Merengue",
+            "Salsa",
+            "Thrash Metal",
+            "Anime",
+            "Jpop",
+            "Synthpop"
+    };
+
     static {
         System.loadLibrary("media_jni");
         native_init();
@@ -225,6 +382,8 @@
     private native void _setDataSource(MediaDataSource dataSource)
           throws IllegalArgumentException;
 
+    private native @Nullable String nativeExtractMetadata(int keyCode);
+
     /**
      * Call this method after setDataSource(). This method retrieves the
      * meta data value associated with the keyCode.
@@ -236,7 +395,118 @@
      * @return The meta data value associate with the given keyCode on success;
      * null on failure.
      */
-    public native @Nullable String extractMetadata(int keyCode);
+    public @Nullable String extractMetadata(int keyCode) {
+        String meta = nativeExtractMetadata(keyCode);
+        if (keyCode == METADATA_KEY_GENRE) {
+            // translate numeric genre code(s) to human readable
+            meta = convertGenreTag(meta);
+        }
+        return meta;
+    }
+
+    /*
+     * The id3v2 spec doesn't specify the syntax of the genre tag very precisely, so
+     * some assumptions are made. Using one possible interpretation of the id3v2
+     * spec, this method converts an id3 genre tag string to a human readable string,
+     * as follows:
+     * - if the first character of the tag is a digit, the entire tag is assumed to
+     *   be an id3v1 numeric genre code. If the tag does not parse to a number, or
+     *   the number is outside the range of defined standard genres, it is ignored.
+     * - if the tag does not start with a digit, it is assumed to be an id3v2 style
+     *   tag consisting of one or more genres, with each genre being either a parenthesized
+     *   integer referring to an id3v1 numeric genre code, the special indicators "(CR)" or
+     *   "(RX)" (for "Cover" or "Remix", respectively), or a custom genre string. When
+     *   a custom genre string is encountered, it is assumed to continue until the end
+     *   of the tag, unless it starts with "((" in which case it is assumed to continue
+     *   until the next close-parenthesis or the end of the tag. Any parse error in the tag
+     *   causes it to be ignored.
+     * The human-readable genre string is not localized, and uses the English genre names
+     * from the spec.
+     */
+    private String convertGenreTag(String meta) {
+        if (TextUtils.isEmpty(meta)) {
+            return null;
+        }
+
+        if (Character.isDigit(meta.charAt(0))) {
+            // assume a single id3v1-style bare number without any extra characters
+            try {
+                int genreIndex = Integer.parseInt(meta);
+                if (genreIndex >= 0 && genreIndex < STANDARD_GENRES.length) {
+                    return STANDARD_GENRES[genreIndex];
+                }
+            } catch (NumberFormatException e) {
+                // ignore and fall through
+            }
+            return null;
+        } else {
+            // assume id3v2-style genre tag, with parenthesized numeric genres
+            // and/or literal genre strings, possibly more than one per tag.
+            StringBuilder genres = null;
+            String nextGenre = null;
+            while (true) {
+                if (!TextUtils.isEmpty(nextGenre)) {
+                    if (genres == null) {
+                        genres = new StringBuilder();
+                    }
+                    if (genres.length() != 0) {
+                        genres.append(", ");
+                    }
+                    genres.append(nextGenre);
+                    nextGenre = null;
+                }
+                if (TextUtils.isEmpty(meta)) {
+                    // entire tag has been processed.
+                    break;
+                }
+                if (meta.startsWith("(RX)")) {
+                    nextGenre = "Remix";
+                    meta = meta.substring(4);
+                } else if (meta.startsWith("(CR)")) {
+                    nextGenre = "Cover";
+                    meta = meta.substring(4);
+                } else if (meta.startsWith("((")) {
+                    // the id3v2 spec says that custom genres that start with a parenthesis
+                    // should be "escaped" with another parenthesis, however the spec doesn't
+                    // specify escaping parentheses inside the custom string. We'll parse any
+                    // such strings until a closing parenthesis is found, or the end of
+                    // the tag is reached.
+                    int closeParenOffset = meta.indexOf(')');
+                    if (closeParenOffset == -1) {
+                        // string continues to end of tag
+                        nextGenre = meta.substring(1);
+                        meta = "";
+                    } else {
+                        nextGenre = meta.substring(1, closeParenOffset + 1);
+                        meta = meta.substring(closeParenOffset + 1);
+                    }
+                } else if (meta.startsWith("(")) {
+                    // should be a parenthesized numeric genre
+                    int closeParenOffset = meta.indexOf(')');
+                    if (closeParenOffset == -1) {
+                        return null;
+                    }
+                    String genreNumString = meta.substring(1, closeParenOffset);
+                    try {
+                        int genreIndex = Integer.parseInt(genreNumString.toString());
+                        if (genreIndex >= 0 && genreIndex < STANDARD_GENRES.length) {
+                            nextGenre = STANDARD_GENRES[genreIndex];
+                        } else {
+                            return null;
+                        }
+                    } catch (NumberFormatException e) {
+                        return null;
+                    }
+                    meta = meta.substring(closeParenOffset + 1);
+                } else {
+                    // custom genre
+                    nextGenre = meta;
+                    meta = "";
+                }
+            }
+            return genres == null || genres.length() == 0 ? null : genres.toString();
+        }
+    }
 
     /**
      * This method is similar to {@link #getFrameAtTime(long, int, BitmapParams)}
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index eae13d0..dd01243 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -79,6 +79,11 @@
      */
     public static final int CONNECTION_STATE_CONNECTED = 2;
 
+    /** @hide */
+    @IntDef({PLAYBACK_VOLUME_FIXED, PLAYBACK_VOLUME_VARIABLE})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface PlaybackVolume {}
+
     /**
      * Playback information indicating the playback volume is fixed, i&#46;e&#46; it cannot be
      * controlled from this object. An example of fixed playback volume is a remote player,
@@ -326,6 +331,7 @@
      *
      * @return {@link #PLAYBACK_VOLUME_FIXED} or {@link #PLAYBACK_VOLUME_VARIABLE}
      */
+    @PlaybackVolume
     public int getVolumeHandling() {
         return mVolumeHandling;
     }
@@ -375,6 +381,7 @@
      *
      * @param features the list of route features to consider
      * @return true if the route has at least one feature in the list
+     * @hide
      */
     public boolean hasAnyFeatures(@NonNull Collection<String> features) {
         Objects.requireNonNull(features, "features must not be null");
@@ -548,6 +555,12 @@
 
         /**
          * Adds a feature for the route.
+         * @param feature a feature that the route has. May be one of predefined features
+         *                such as {@link #FEATURE_LIVE_AUDIO}, {@link #FEATURE_LIVE_VIDEO} or
+         *                {@link #FEATURE_REMOTE_PLAYBACK} or a custom feature defined by
+         *                a provider.
+         *
+         * @see #addFeatures(Collection)
          */
         @NonNull
         public Builder addFeature(@NonNull String feature) {
@@ -560,6 +573,12 @@
 
         /**
          * Adds features for the route. A route must support at least one route type.
+         * @param features features that the route has. May include predefined features
+         *                such as {@link #FEATURE_LIVE_AUDIO}, {@link #FEATURE_LIVE_VIDEO} or
+         *                {@link #FEATURE_REMOTE_PLAYBACK} or custom features defined by
+         *                a provider.
+         *
+         * @see #addFeature(String)
          */
         @NonNull
         public Builder addFeatures(@NonNull Collection<String> features) {
@@ -643,7 +662,7 @@
          * Sets the route's volume handling.
          */
         @NonNull
-        public Builder setVolumeHandling(int volumeHandling) {
+        public Builder setVolumeHandling(@PlaybackVolume int volumeHandling) {
             mVolumeHandling = volumeHandling;
             return this;
         }
diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java
index 1e8b188..e39b7bc 100644
--- a/media/java/android/media/MediaRoute2ProviderService.java
+++ b/media/java/android/media/MediaRoute2ProviderService.java
@@ -21,6 +21,7 @@
 import android.annotation.CallSuper;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SdkConstant;
 import android.app.Service;
 import android.content.Intent;
 import android.os.Binder;
@@ -57,6 +58,11 @@
 public abstract class MediaRoute2ProviderService extends Service {
     private static final String TAG = "MR2ProviderService";
 
+    /**
+     * The {@link Intent} action that must be declared as handled by the service.
+     * Put this in your manifest to provide media routes.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
     public static final String SERVICE_INTERFACE = "android.media.MediaRoute2ProviderService";
 
     /**
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index 18670e9..7b9a44f 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -49,10 +49,10 @@
 /**
  * Media Router 2 allows applications to control the routing of media channels
  * and streams from the current device to remote speakers and devices.
- *
  */
 // TODO: Add method names at the beginning of log messages. (e.g. updateControllerOnHandler)
 //       Not only MediaRouter2, but also to service / manager / provider.
+// TODO: ensure thread-safe and document it
 public class MediaRouter2 {
     private static final String TAG = "MR2";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -159,7 +159,8 @@
     /**
      * Registers a callback to discover routes and to receive events when they change.
      * <p>
-     * If you register the same callback twice or more, it will be ignored.
+     * If the specified callback is already registered, its registration will be updated for the
+     * given {@link Executor executor} and {@link RouteDiscoveryPreference discovery preference}.
      * </p>
      */
     public void registerRouteCallback(@NonNull @CallbackExecutor Executor executor,
@@ -170,10 +171,11 @@
         Objects.requireNonNull(preference, "preference must not be null");
 
         RouteCallbackRecord record = new RouteCallbackRecord(executor, routeCallback, preference);
-        if (!mRouteCallbackRecords.addIfAbsent(record)) {
-            Log.w(TAG, "Ignoring the same callback");
-            return;
-        }
+
+        mRouteCallbackRecords.remove(record);
+        // It can fail to add the callback record if another registration with the same callback
+        // is happening but it's okay because either this or the other registration should be done.
+        mRouteCallbackRecords.addIfAbsent(record);
 
         synchronized (sRouterLock) {
             if (mClient == null) {
diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java
index cad5aa6..c25a533 100644
--- a/media/java/android/media/audiofx/AudioEffect.java
+++ b/media/java/android/media/audiofx/AudioEffect.java
@@ -356,10 +356,14 @@
     public static final String EFFECT_AUXILIARY = "Auxiliary";
     /**
      * Effect connection mode is pre processing.
-     * The audio pre processing effects are attached to an audio input (AudioRecord).
-     * @hide
+     * The audio pre processing effects are attached to an audio input stream or device
      */
     public static final String EFFECT_PRE_PROCESSING = "Pre Processing";
+    /**
+     * Effect connection mode is post processing.
+     * The audio post processing effects are attached to an audio output stream or device
+     */
+    public static final String EFFECT_POST_PROCESSING = "Post Processing";
 
     // --------------------------------------------------------------------------
     // Member variables
diff --git a/media/java/android/media/audiopolicy/AudioProductStrategy.java b/media/java/android/media/audiopolicy/AudioProductStrategy.java
index 612f83a..60b3fc6 100644
--- a/media/java/android/media/audiopolicy/AudioProductStrategy.java
+++ b/media/java/android/media/audiopolicy/AudioProductStrategy.java
@@ -134,7 +134,9 @@
                             + "DO NOT USE STREAM TO CONTROL THE VOLUME");
                     return AudioSystem.STREAM_MUSIC;
                 }
-                return streamType;
+                if (streamType < AudioSystem.getNumStreamTypes()) {
+                    return streamType;
+                }
             }
         }
         return AudioSystem.STREAM_MUSIC;
diff --git a/media/java/android/media/tv/DvbDeviceInfo.java b/media/java/android/media/tv/DvbDeviceInfo.java
index 96c8528..54fc39e 100644
--- a/media/java/android/media/tv/DvbDeviceInfo.java
+++ b/media/java/android/media/tv/DvbDeviceInfo.java
@@ -16,6 +16,7 @@
 
 package android.media.tv;
 
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.os.Parcel;
@@ -23,9 +24,13 @@
 import android.util.Log;
 
 /**
- * Simple container for information about DVB device.
- * Not for third-party developers.
+ * A digital video broadcasting (DVB) device.
  *
+ * <p> Simple wrapper around a <a href="https://www.linuxtv.org/docs/dvbapi/dvbapi.html">Linux DVB
+ * v3</a> device.
+ *
+ * @see TvInputManager#getDvbDeviceList()
+ * @see TvInputManager#openDvbDevice(DvbDeviceInfo, int)
  * @hide
  */
 @SystemApi
@@ -67,17 +72,19 @@
     }
 
     /**
-     * Returns the adapter ID of DVB device, in terms of enumerating the DVB device adapters
-     * installed in the system. The adapter ID counts from zero.
+     * Returns the adapter ID.
+     *
+     * <p>DVB Adapters contain one or more devices.
      */
+    @IntRange(from = 0)
     public int getAdapterId() {
         return mAdapterId;
     }
 
     /**
-     * Returns the device ID of DVB device, in terms of enumerating the DVB devices attached to
-     * the same device adapter. The device ID counts from zero.
+     * Returns the device ID.
      */
+    @IntRange(from = 0)
     public int getDeviceId() {
         return mDeviceId;
     }
diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
index c199c6f..508a46f4 100644
--- a/media/java/android/media/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -89,7 +89,7 @@
     void timeShiftEnablePositionTracking(in IBinder sessionToken, boolean enable, int userId);
 
     // For the recording session
-    void startRecording(in IBinder sessionToken, in Uri programUri, int userId);
+    void startRecording(in IBinder sessionToken, in Uri programUri, in Bundle params, int userId);
     void stopRecording(in IBinder sessionToken, int userId);
 
     // For TV input hardware binding
diff --git a/media/java/android/media/tv/ITvInputSession.aidl b/media/java/android/media/tv/ITvInputSession.aidl
index 356ec3c..24b87d5 100644
--- a/media/java/android/media/tv/ITvInputSession.aidl
+++ b/media/java/android/media/tv/ITvInputSession.aidl
@@ -56,6 +56,6 @@
     void timeShiftEnablePositionTracking(boolean enable);
 
     // For the recording session
-    void startRecording(in Uri programUri);
+    void startRecording(in Uri programUri, in Bundle params);
     void stopRecording();
 }
diff --git a/media/java/android/media/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java
index 07cfbda..e89d33d 100644
--- a/media/java/android/media/tv/ITvInputSessionWrapper.java
+++ b/media/java/android/media/tv/ITvInputSessionWrapper.java
@@ -216,7 +216,8 @@
                 break;
             }
             case DO_START_RECORDING: {
-                mTvInputRecordingSessionImpl.startRecording((Uri) msg.obj);
+                SomeArgs args = (SomeArgs) msg.obj;
+                mTvInputRecordingSessionImpl.startRecording((Uri) args.arg1, (Bundle) args.arg2);
                 break;
             }
             case DO_STOP_RECORDING: {
@@ -352,8 +353,9 @@
     }
 
     @Override
-    public void startRecording(@Nullable Uri programUri) {
-        mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_START_RECORDING, programUri));
+    public void startRecording(@Nullable Uri programUri, @Nullable Bundle params) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageOO(DO_START_RECORDING, programUri,
+                params));
     }
 
     @Override
diff --git a/media/java/android/media/tv/TvContentRating.java b/media/java/android/media/tv/TvContentRating.java
index 9e671b1..5babb16 100644
--- a/media/java/android/media/tv/TvContentRating.java
+++ b/media/java/android/media/tv/TvContentRating.java
@@ -17,7 +17,6 @@
 package android.media.tv;
 
 import android.annotation.NonNull;
-import android.annotation.SystemApi;
 import android.text.TextUtils;
 
 import com.android.internal.util.Preconditions;
@@ -725,16 +724,16 @@
  *         <td>NZ_TV_G</td>
  *         <td>Programmes which exclude material likely to be unsuitable for children. Programmes
  *         may not necessarily be designed for child viewers but should not contain material likely
- *         to alarm or distress them.</td>
+ *         to alarm or distress them</td>
  *     </tr>
  *     <tr>
  *         <td>NZ_TV_PGR</td>
  *         <td>Programmes containing material more suited for mature audiences but not necessarily
- *         unsuitable for child viewers when subject to the guidance of a parent or an adult.</td>
+ *         unsuitable for child viewers when subject to the guidance of a parent or an adult</td>
  *     </tr>
  *     <tr>
  *         <td>NZ_TV_AO</td>
- *         <td>Programmes containing adult themes and directed primarily at mature audiences.</td>
+ *         <td>Programmes containing adult themes and directed primarily at mature audiences</td>
  *     </tr>
  *     <tr>
  *         <td valign="top" rowspan="6">SG_TV</td>
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 9cdfa2a..2589521 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -1833,7 +1833,7 @@
     }
 
     /**
-     * Returns the list of currently available DVB devices on the system.
+     * Returns the list of currently available DVB frontend devices on the system.
      *
      * @return the list of {@link DvbDeviceInfo} objects representing available DVB devices.
      * @hide
@@ -1850,16 +1850,17 @@
     }
 
     /**
-     * Returns a {@link ParcelFileDescriptor} of a specified DVB device for a given
-     * {@link DvbDeviceInfo}
+     * Returns a {@link ParcelFileDescriptor} of a specified DVB device of a given type for a given
+     * {@link DvbDeviceInfo}.
      *
      * @param info A {@link DvbDeviceInfo} to open a DVB device.
-     * @param deviceType A DVB device type. The type can be {@link #DVB_DEVICE_DEMUX},
-     *            {@link #DVB_DEVICE_DVR} or {@link #DVB_DEVICE_FRONTEND}.
+     * @param deviceType A DVB device type.
      * @return a {@link ParcelFileDescriptor} of a specified DVB device for a given
-     *         {@link DvbDeviceInfo}, or {@code null} if the given {@link DvbDeviceInfo}
-     *         failed to open.
+     * {@link DvbDeviceInfo}, or {@code null} if the given {@link DvbDeviceInfo}
+     * failed to open.
      * @throws IllegalArgumentException if {@code deviceType} is invalid or the device is not found.
+
+     * @see <a href="https://www.linuxtv.org/docs/dvbapi/dvbapi.html">Linux DVB API v3</a>
      * @hide
      */
     @SystemApi
@@ -2380,12 +2381,23 @@
          *            {@link TvContract#buildProgramUri(long)}. Can be {@code null}.
          */
         void startRecording(@Nullable Uri programUri) {
+            startRecording(programUri, null);
+        }
+
+        /**
+         * Starts TV program recording in the current recording session.
+         *
+         * @param programUri The URI for the TV program to record as a hint, built by
+         *            {@link TvContract#buildProgramUri(long)}. Can be {@code null}.
+         * @param params A set of extra parameters which might be handled with this event.
+         */
+        void startRecording(@Nullable Uri programUri, @Nullable Bundle params) {
             if (mToken == null) {
                 Log.w(TAG, "The session has been already released");
                 return;
             }
             try {
-                mService.startRecording(mToken, programUri, mUserId);
+                mService.startRecording(mToken, programUri, params, mUserId);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 7e1f44c..62c7e51 100755
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -1818,6 +1818,30 @@
         public abstract void onStartRecording(@Nullable Uri programUri);
 
         /**
+         * Called when the application requests to start TV program recording. Recording must start
+         * immediately when this method is called.
+         *
+         * <p>The application may supply the URI for a TV program for filling in program specific
+         * data fields in the {@link android.media.tv.TvContract.RecordedPrograms} table.
+         * A non-null {@code programUri} implies the started recording should be of that specific
+         * program, whereas null {@code programUri} does not impose such a requirement and the
+         * recording can span across multiple TV programs. In either case, the application must call
+         * {@link TvRecordingClient#stopRecording()} to stop the recording.
+         *
+         * <p>The session must call {@link #notifyError(int)} if the start request cannot be
+         * fulfilled.
+         *
+         * @param programUri The URI for the TV program to record, built by
+         *            {@link TvContract#buildProgramUri(long)}. Can be {@code null}.
+         * @param params Domain-specific data for this tune request. Keys <em>must</em> be a scoped
+         *            name, i.e. prefixed with a package name you own, so that different developers
+         *            will not create conflicting keys.
+         */
+        public void onStartRecording(@Nullable Uri programUri, @NonNull Bundle params) {
+            onStartRecording(programUri);
+        }
+
+        /**
          * Called when the application requests to stop TV program recording. Recording must stop
          * immediately when this method is called.
          *
@@ -1867,11 +1891,11 @@
         }
 
         /**
-         * Calls {@link #onStartRecording(Uri)}.
+         * Calls {@link #onStartRecording(Uri, Bundle)}.
          *
          */
-        void startRecording(@Nullable  Uri programUri) {
-            onStartRecording(programUri);
+        void startRecording(@Nullable  Uri programUri, @NonNull Bundle params) {
+            onStartRecording(programUri, params);
         }
 
         /**
diff --git a/media/java/android/media/tv/TvRecordingClient.java b/media/java/android/media/tv/TvRecordingClient.java
index 5aadeb6..8ae98ae 100644
--- a/media/java/android/media/tv/TvRecordingClient.java
+++ b/media/java/android/media/tv/TvRecordingClient.java
@@ -170,11 +170,37 @@
      * @throws IllegalStateException If {@link #tune} request hasn't been handled yet.
      */
     public void startRecording(@Nullable Uri programUri) {
+        startRecording(programUri, Bundle.EMPTY);
+    }
+
+    /**
+     * Starts TV program recording in the current recording session. Recording is expected to start
+     * immediately when this method is called. If the current recording session has not yet tuned to
+     * any channel, this method throws an exception.
+     *
+     * <p>The application may supply the URI for a TV program for filling in program specific data
+     * fields in the {@link android.media.tv.TvContract.RecordedPrograms} table.
+     * A non-null {@code programUri} implies the started recording should be of that specific
+     * program, whereas null {@code programUri} does not impose such a requirement and the
+     * recording can span across multiple TV programs. In either case, the application must call
+     * {@link TvRecordingClient#stopRecording()} to stop the recording.
+     *
+     * <p>The recording session will respond by calling {@link RecordingCallback#onError(int)} if
+     * the start request cannot be fulfilled.
+     *
+     * @param programUri The URI for the TV program to record, built by
+     *            {@link TvContract#buildProgramUri(long)}. Can be {@code null}.
+     * @param params Domain-specific data for this request. Keys <em>must</em> be a scoped
+     *            name, i.e. prefixed with a package name you own, so that different developers will
+     *            not create conflicting keys.
+     * @throws IllegalStateException If {@link #tune} request hasn't been handled yet.
+     */
+    public void startRecording(@Nullable Uri programUri, @NonNull Bundle params) {
         if (!mIsTuned) {
             throw new IllegalStateException("startRecording failed - not yet tuned");
         }
         if (mSession != null) {
-            mSession.startRecording(programUri);
+            mSession.startRecording(programUri, params);
             mIsRecordingStarted = true;
         }
     }
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index ab6966d..9b37f95 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -1750,22 +1750,150 @@
         return;
     }
 
-    NativeCryptoInfo cryptoInfo{env, cryptoInfoObj};
+    jint numSubSamples =
+        env->GetIntField(cryptoInfoObj, gFields.cryptoInfoNumSubSamplesID);
+
+    jintArray numBytesOfClearDataObj =
+        (jintArray)env->GetObjectField(
+                cryptoInfoObj, gFields.cryptoInfoNumBytesOfClearDataID);
+
+    jintArray numBytesOfEncryptedDataObj =
+        (jintArray)env->GetObjectField(
+                cryptoInfoObj, gFields.cryptoInfoNumBytesOfEncryptedDataID);
+
+    jbyteArray keyObj =
+        (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoKeyID);
+
+    jbyteArray ivObj =
+        (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoIVID);
+
+    jint jmode = env->GetIntField(cryptoInfoObj, gFields.cryptoInfoModeID);
+    enum CryptoPlugin::Mode mode;
+    if (jmode == gCryptoModes.Unencrypted) {
+        mode = CryptoPlugin::kMode_Unencrypted;
+    } else if (jmode == gCryptoModes.AesCtr) {
+        mode = CryptoPlugin::kMode_AES_CTR;
+    } else if (jmode == gCryptoModes.AesCbc) {
+        mode = CryptoPlugin::kMode_AES_CBC;
+    }  else {
+        throwExceptionAsNecessary(env, INVALID_OPERATION);
+        return;
+    }
+
+    jobject patternObj = env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoPatternID);
+
+    CryptoPlugin::Pattern pattern;
+    if (patternObj == NULL) {
+        pattern.mEncryptBlocks = 0;
+        pattern.mSkipBlocks = 0;
+    } else {
+        pattern.mEncryptBlocks = env->GetIntField(patternObj, gFields.patternEncryptBlocksID);
+        pattern.mSkipBlocks = env->GetIntField(patternObj, gFields.patternSkipBlocksID);
+    }
+
+    status_t err = OK;
+
+    CryptoPlugin::SubSample *subSamples = NULL;
+    jbyte *key = NULL;
+    jbyte *iv = NULL;
+
+    if (numSubSamples <= 0) {
+        err = -EINVAL;
+    } else if (numBytesOfClearDataObj == NULL
+            && numBytesOfEncryptedDataObj == NULL) {
+        err = -EINVAL;
+    } else if (numBytesOfEncryptedDataObj != NULL
+            && env->GetArrayLength(numBytesOfEncryptedDataObj) < numSubSamples) {
+        err = -ERANGE;
+    } else if (numBytesOfClearDataObj != NULL
+            && env->GetArrayLength(numBytesOfClearDataObj) < numSubSamples) {
+        err = -ERANGE;
+    // subSamples array may silently overflow if number of samples are too large.  Use
+    // INT32_MAX as maximum allocation size may be less than SIZE_MAX on some platforms
+    } else if ( CC_UNLIKELY(numSubSamples >= (signed)(INT32_MAX / sizeof(*subSamples))) ) {
+        err = -EINVAL;
+    } else {
+        jboolean isCopy;
+
+        jint *numBytesOfClearData =
+            (numBytesOfClearDataObj == NULL)
+                ? NULL
+                : env->GetIntArrayElements(numBytesOfClearDataObj, &isCopy);
+
+        jint *numBytesOfEncryptedData =
+            (numBytesOfEncryptedDataObj == NULL)
+                ? NULL
+                : env->GetIntArrayElements(numBytesOfEncryptedDataObj, &isCopy);
+
+        subSamples = new CryptoPlugin::SubSample[numSubSamples];
+
+        for (jint i = 0; i < numSubSamples; ++i) {
+            subSamples[i].mNumBytesOfClearData =
+                (numBytesOfClearData == NULL) ? 0 : numBytesOfClearData[i];
+
+            subSamples[i].mNumBytesOfEncryptedData =
+                (numBytesOfEncryptedData == NULL)
+                    ? 0 : numBytesOfEncryptedData[i];
+        }
+
+        if (numBytesOfEncryptedData != NULL) {
+            env->ReleaseIntArrayElements(
+                    numBytesOfEncryptedDataObj, numBytesOfEncryptedData, 0);
+            numBytesOfEncryptedData = NULL;
+        }
+
+        if (numBytesOfClearData != NULL) {
+            env->ReleaseIntArrayElements(
+                    numBytesOfClearDataObj, numBytesOfClearData, 0);
+            numBytesOfClearData = NULL;
+        }
+    }
+
+    if (err == OK && keyObj != NULL) {
+        if (env->GetArrayLength(keyObj) != 16) {
+            err = -EINVAL;
+        } else {
+            jboolean isCopy;
+            key = env->GetByteArrayElements(keyObj, &isCopy);
+        }
+    }
+
+    if (err == OK && ivObj != NULL) {
+        if (env->GetArrayLength(ivObj) != 16) {
+            err = -EINVAL;
+        } else {
+            jboolean isCopy;
+            iv = env->GetByteArrayElements(ivObj, &isCopy);
+        }
+    }
+
     AString errorDetailMsg;
 
-    status_t err = cryptoInfo.mErr;
     if (err == OK) {
         err = codec->queueSecureInputBuffer(
                 index, offset,
-                cryptoInfo.mSubSamples, cryptoInfo.mNumSubSamples,
-                (const uint8_t *)cryptoInfo.mKey, (const uint8_t *)cryptoInfo.mIv,
-                cryptoInfo.mMode,
-                cryptoInfo.mPattern,
+                subSamples, numSubSamples,
+                (const uint8_t *)key, (const uint8_t *)iv,
+                mode,
+                pattern,
                 timestampUs,
                 flags,
                 &errorDetailMsg);
     }
 
+    if (iv != NULL) {
+        env->ReleaseByteArrayElements(ivObj, iv, 0);
+        iv = NULL;
+    }
+
+    if (key != NULL) {
+        env->ReleaseByteArrayElements(keyObj, key, 0);
+        key = NULL;
+    }
+
+    delete[] subSamples;
+    subSamples = NULL;
+
     throwExceptionAsNecessary(
             env, err, ACTION_CODE_FATAL, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str());
 }
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index a5c62cb..1c9b349 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -728,7 +728,7 @@
             (void *)android_media_MediaMetadataRetriever_getFrameAtIndex
         },
 
-        {"extractMetadata", "(I)Ljava/lang/String;",
+        {"nativeExtractMetadata", "(I)Ljava/lang/String;",
                 (void *)android_media_MediaMetadataRetriever_extractMetadata},
         {"getEmbeddedPicture", "(I)[B",
                 (void *)android_media_MediaMetadataRetriever_getEmbeddedPicture},
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 4f1125f..007d367 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -314,7 +314,7 @@
 
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     return env->NewObject(
-            env->FindClass("android/media/tv/tuner/Tuner$Lnb"),
+            env->FindClass("android/media/tv/tuner/Lnb"),
             gFields.lnbInitID,
             mObject,
             id);
@@ -373,7 +373,7 @@
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jobject descramblerObj =
             env->NewObject(
-                    env->FindClass("android/media/tv/tuner/Tuner$Descrambler"),
+                    env->FindClass("android/media/tv/tuner/Descrambler"),
                     gFields.descramblerInitID,
                     mObject);
 
@@ -408,7 +408,7 @@
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jobject filterObj =
             env->NewObject(
-                    env->FindClass("android/media/tv/tuner/Tuner$Filter"),
+                    env->FindClass("android/media/tv/tuner/filter/Filter"),
                     gFields.filterInitID,
                     mObject,
                     (jint) fId);
@@ -443,7 +443,7 @@
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jobject dvrObj =
             env->NewObject(
-                    env->FindClass("android/media/tv/tuner/Tuner$Dvr"),
+                    env->FindClass("android/media/tv/tuner/dvr/Dvr"),
                     gFields.dvrInitID,
                     mObject);
     sp<Dvr> dvrSp = new Dvr(iDvrSp, dvrObj);
@@ -495,14 +495,14 @@
 
 static FrontendSettings getFrontendSettings(JNIEnv *env, int type, jobject settings) {
     FrontendSettings frontendSettings;
-    jclass clazz = env->FindClass("android/media/tv/tuner/FrontendSettings");
+    jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendSettings");
     jfieldID freqField = env->GetFieldID(clazz, "mFrequency", "I");
     uint32_t freq = static_cast<uint32_t>(env->GetIntField(clazz, freqField));
 
     // TODO: handle the other 8 types of settings
     if (type == 1) {
         // analog
-        clazz = env->FindClass("android/media/tv/tuner/FrontendSettings$FrontendAnalogSettings");
+        clazz = env->FindClass("android/media/tv/tuner/frontend/AnalogFrontendSettings");
         FrontendAnalogType analogType =
                 static_cast<FrontendAnalogType>(
                         env->GetIntField(settings, env->GetFieldID(clazz, "mAnalogType", "I")));
@@ -525,7 +525,7 @@
 
 static DvrSettings getDvrSettings(JNIEnv *env, jobject settings) {
     DvrSettings dvrSettings;
-    jclass clazz = env->FindClass("android/media/tv/tuner/DvrSettings");
+    jclass clazz = env->FindClass("android/media/tv/tuner/dvr/DvrSettings");
     uint32_t statusMask =
             static_cast<uint32_t>(env->GetIntField(
                     settings, env->GetFieldID(clazz, "mStatusMask", "I")));
@@ -585,23 +585,23 @@
     gFields.frontendInitID =
             env->GetMethodID(frontendClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;I)V");
 
-    jclass lnbClazz = env->FindClass("android/media/tv/tuner/Tuner$Lnb");
+    jclass lnbClazz = env->FindClass("android/media/tv/tuner/Lnb");
     gFields.lnbInitID =
             env->GetMethodID(lnbClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;I)V");
 
-    jclass filterClazz = env->FindClass("android/media/tv/tuner/Tuner$Filter");
+    jclass filterClazz = env->FindClass("android/media/tv/tuner/filter/Filter");
     gFields.filterContext = env->GetFieldID(filterClazz, "mNativeContext", "J");
     gFields.filterInitID =
             env->GetMethodID(filterClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;I)V");
     gFields.onFilterStatusID =
             env->GetMethodID(filterClazz, "onFilterStatus", "(I)V");
 
-    jclass descramblerClazz = env->FindClass("android/media/tv/tuner/Tuner$Descrambler");
+    jclass descramblerClazz = env->FindClass("android/media/tv/tuner/Descrambler");
     gFields.descramblerContext = env->GetFieldID(descramblerClazz, "mNativeContext", "J");
     gFields.descramblerInitID =
             env->GetMethodID(descramblerClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;)V");
 
-    jclass dvrClazz = env->FindClass("android/media/tv/tuner/Tuner$Dvr");
+    jclass dvrClazz = env->FindClass("android/media/tv/tuner/dvr/Dvr");
     gFields.dvrContext = env->GetFieldID(dvrClazz, "mNativeContext", "J");
     gFields.dvrInitID = env->GetMethodID(dvrClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;)V");
 }
@@ -649,7 +649,7 @@
     return 0;
 }
 
-static jobjectArray android_media_tv_Tuner_get_frontend_status(JNIEnv, jobject, jintArray) {
+static jobject android_media_tv_Tuner_get_frontend_status(JNIEnv, jobject, jintArray) {
     return NULL;
 }
 
@@ -684,7 +684,7 @@
 }
 
 static jobject android_media_tv_Tuner_open_filter(
-        JNIEnv *env, jobject thiz, jint type, jint subType, jint bufferSize) {
+        JNIEnv *env, jobject thiz, jint type, jint subType, jlong bufferSize) {
     sp<JTuner> tuner = getTuner(env, thiz);
     DemuxFilterType filterType {
         .mainType = static_cast<DemuxFilterMainType>(type),
@@ -708,17 +708,17 @@
             env->GetObjectField(
                     filterSettingsObj,
                     env->GetFieldID(
-                            env->FindClass("android/media/tv/tuner/FilterSettings"),
+                            env->FindClass("android/media/tv/tuner/filter/FilterConfiguration"),
                             "mSettings",
-                            "Landroid/media/tv/tuner/FilterSettings$Settings;"));
+                            "Landroid/media/tv/tuner/filter/Settings;"));
     if (type == (int)DemuxFilterMainType::TS) {
         // DemuxTsFilterSettings
-        jclass clazz = env->FindClass("android/media/tv/tuner/FilterSettings$TsFilterSettings");
+        jclass clazz = env->FindClass("android/media/tv/tuner/filter/TsFilterConfiguration");
         int tpid = env->GetIntField(filterSettingsObj, env->GetFieldID(clazz, "mTpid", "I"));
         if (subtype == (int)DemuxTsFilterType::PES) {
             // DemuxFilterPesDataSettings
             jclass settingClazz =
-                    env->FindClass("android/media/tv/tuner/FilterSettings$PesSettings");
+                    env->FindClass("android/media/tv/tuner/filter/PesSettings");
             int streamId = env->GetIntField(
                     settingsObj, env->GetFieldID(settingClazz, "mStreamId", "I"));
             bool isRaw = (bool)env->GetBooleanField(
@@ -831,7 +831,7 @@
 }
 
 static int android_media_tv_Tuner_read_filter_fmq(
-        JNIEnv *env, jobject filter, jbyteArray buffer, jint offset, jint size) {
+        JNIEnv *env, jobject filter, jbyteArray buffer, jlong offset, jlong size) {
     sp<Filter> filterSp = getFilter(env, filter);
     if (filterSp == NULL) {
         ALOGD("Failed to read filter FMQ: filter not found");
@@ -901,9 +901,14 @@
     return 0;
 }
 
-static jobject android_media_tv_Tuner_open_dvr(JNIEnv *env, jobject thiz, jint type, jint bufferSize) {
-    sp<JTuner> tuner = getTuner(env, thiz);
-    return tuner->openDvr(static_cast<DvrType>(type), bufferSize);
+static jobject android_media_tv_Tuner_open_dvr_recorder(
+        JNIEnv* /* env */, jobject /* thiz */, jlong /* bufferSize */) {
+    return NULL;
+}
+
+static jobject android_media_tv_Tuner_open_dvr_playback(
+        JNIEnv* /* env */, jobject /* thiz */, jlong /* bufferSize */) {
+    return NULL;
 }
 
 static jobject android_media_tv_Tuner_get_demux_caps(JNIEnv*, jobject) {
@@ -1019,35 +1024,35 @@
     ALOGD("set fd = %d", dvrSp->mFd);
 }
 
-static int android_media_tv_Tuner_read_dvr(JNIEnv *env, jobject dvr, jint size) {
+static jlong android_media_tv_Tuner_read_dvr(JNIEnv *env, jobject dvr, jlong size) {
     sp<Dvr> dvrSp = getDvr(env, dvr);
     if (dvrSp == NULL) {
         ALOGD("Failed to read dvr: dvr not found");
     }
 
-    int available = dvrSp->mDvrMQ->availableToWrite();
-    int write = std::min(size, available);
+    long available = dvrSp->mDvrMQ->availableToWrite();
+    long write = std::min((long) size, available);
 
     DvrMQ::MemTransaction tx;
-    int ret = 0;
+    long ret = 0;
     if (dvrSp->mDvrMQ->beginWrite(write, &tx)) {
         auto first = tx.getFirstRegion();
         auto data = first.getAddress();
-        int length = first.getLength();
-        int firstToWrite = std::min(length, write);
+        long length = first.getLength();
+        long firstToWrite = std::min(length, write);
         ret = read(dvrSp->mFd, data, firstToWrite);
         if (ret < firstToWrite) {
-            ALOGW("[DVR] file to MQ, first region: %d bytes to write, but %d bytes written",
+            ALOGW("[DVR] file to MQ, first region: %ld bytes to write, but %ld bytes written",
                     firstToWrite, ret);
         } else if (firstToWrite < write) {
-            ALOGD("[DVR] write second region: %d bytes written, %d bytes in total", ret, write);
+            ALOGD("[DVR] write second region: %ld bytes written, %ld bytes in total", ret, write);
             auto second = tx.getSecondRegion();
             data = second.getAddress();
             length = second.getLength();
             int secondToWrite = std::min(length, write - firstToWrite);
             ret += read(dvrSp->mFd, data, secondToWrite);
         }
-        ALOGD("[DVR] file to MQ: %d bytes need to be written, %d bytes written", write, ret);
+        ALOGD("[DVR] file to MQ: %ld bytes need to be written, %ld bytes written", write, ret);
         if (!dvrSp->mDvrMQ->commitWrite(ret)) {
             ALOGE("[DVR] Error: failed to commit write!");
         }
@@ -1055,17 +1060,17 @@
     } else {
         ALOGE("dvrMq.beginWrite failed");
     }
-    return ret;
+    return (jlong) ret;
 }
 
-static int android_media_tv_Tuner_read_dvr_from_array(
-        JNIEnv /* *env */, jobject /* dvr */, jbyteArray /* bytes */, jint /* offset */,
-        jint /* size */) {
+static jlong android_media_tv_Tuner_read_dvr_from_array(
+        JNIEnv /* *env */, jobject /* dvr */, jbyteArray /* bytes */, jlong /* offset */,
+        jlong /* size */) {
     //TODO: impl
     return 0;
 }
 
-static int android_media_tv_Tuner_write_dvr(JNIEnv *env, jobject dvr, jint size) {
+static jlong android_media_tv_Tuner_write_dvr(JNIEnv *env, jobject dvr, jlong size) {
     sp<Dvr> dvrSp = getDvr(env, dvr);
     if (dvrSp == NULL) {
         ALOGW("Failed to write dvr: dvr not found");
@@ -1079,28 +1084,28 @@
 
     DvrMQ& dvrMq = dvrSp->getDvrMQ();
 
-    int available = dvrMq.availableToRead();
-    int toRead = std::min(size, available);
+    long available = dvrMq.availableToRead();
+    long toRead = std::min((long) size, available);
 
-    int ret = 0;
+    long ret = 0;
     DvrMQ::MemTransaction tx;
     if (dvrMq.beginRead(toRead, &tx)) {
         auto first = tx.getFirstRegion();
         auto data = first.getAddress();
-        int length = first.getLength();
-        int firstToRead = std::min(length, toRead);
+        long length = first.getLength();
+        long firstToRead = std::min(length, toRead);
         ret = write(dvrSp->mFd, data, firstToRead);
         if (ret < firstToRead) {
-            ALOGW("[DVR] MQ to file: %d bytes read, but %d bytes written", firstToRead, ret);
+            ALOGW("[DVR] MQ to file: %ld bytes read, but %ld bytes written", firstToRead, ret);
         } else if (firstToRead < toRead) {
-            ALOGD("[DVR] read second region: %d bytes read, %d bytes in total", ret, toRead);
+            ALOGD("[DVR] read second region: %ld bytes read, %ld bytes in total", ret, toRead);
             auto second = tx.getSecondRegion();
             data = second.getAddress();
             length = second.getLength();
             int secondToRead = toRead - firstToRead;
             ret += write(dvrSp->mFd, data, secondToRead);
         }
-        ALOGD("[DVR] MQ to file: %d bytes to be read, %d bytes written", toRead, ret);
+        ALOGD("[DVR] MQ to file: %ld bytes to be read, %ld bytes written", toRead, ret);
         if (!dvrMq.commitRead(ret)) {
             ALOGE("[DVR] Error: failed to commit read!");
         }
@@ -1109,12 +1114,12 @@
         ALOGE("dvrMq.beginRead failed");
     }
 
-    return ret;
+    return (jlong) ret;
 }
 
-static int android_media_tv_Tuner_write_dvr_to_array(
-        JNIEnv /* *env */, jobject /* dvr */, jbyteArray /* bytes */, jint /* offset */,
-        jint /* size */) {
+static jlong android_media_tv_Tuner_write_dvr_to_array(
+        JNIEnv /* *env */, jobject /* dvr */, jbyteArray /* bytes */, jlong /* offset */,
+        jlong /* size */) {
     //TODO: impl
     return 0;
 }
@@ -1126,49 +1131,51 @@
             (void *)android_media_tv_Tuner_get_frontend_ids },
     { "nativeOpenFrontendById", "(I)Landroid/media/tv/tuner/Tuner$Frontend;",
             (void *)android_media_tv_Tuner_open_frontend_by_id },
-    { "nativeTune", "(ILandroid/media/tv/tuner/FrontendSettings;)I",
+    { "nativeTune", "(ILandroid/media/tv/tuner/frontend/FrontendSettings;)I",
             (void *)android_media_tv_Tuner_tune },
     { "nativeStopTune", "()I", (void *)android_media_tv_Tuner_stop_tune },
-    { "nativeScan", "(ILandroid/media/tv/tuner/FrontendSettings;I)I",
+    { "nativeScan", "(ILandroid/media/tv/tuner/frontend/FrontendSettings;I)I",
             (void *)android_media_tv_Tuner_scan },
     { "nativeStopScan", "()I", (void *)android_media_tv_Tuner_stop_scan },
     { "nativeSetLnb", "(I)I", (void *)android_media_tv_Tuner_set_lnb },
     { "nativeSetLna", "(Z)I", (void *)android_media_tv_Tuner_set_lna },
-    { "nativeGetFrontendStatus", "([I)[Landroid/media/tv/tuner/FrontendStatus;",
+    { "nativeGetFrontendStatus", "([I)Landroid/media/tv/tuner/frontend/FrontendStatus;",
             (void *)android_media_tv_Tuner_get_frontend_status },
-    { "nativeGetAvSyncHwId", "(Landroid/media/tv/tuner/Tuner$Filter;)I",
+    { "nativeGetAvSyncHwId", "(Landroid/media/tv/tuner/Tuner/filter/Filter;)I",
             (void *)android_media_tv_Tuner_gat_av_sync_hw_id },
     { "nativeGetAvSyncTime", "(I)J", (void *)android_media_tv_Tuner_gat_av_sync_time },
     { "nativeConnectCiCam", "(I)I", (void *)android_media_tv_Tuner_connect_cicam },
     { "nativeDisconnectCiCam", "()I", (void *)android_media_tv_Tuner_disconnect_cicam },
-    { "nativeGetFrontendInfo", "(I)[Landroid/media/tv/tuner/FrontendInfo;",
+    { "nativeGetFrontendInfo", "(I)Landroid/media/tv/tuner/FrontendInfo;",
             (void *)android_media_tv_Tuner_get_frontend_info },
-    { "nativeOpenFilter", "(III)Landroid/media/tv/tuner/Tuner$Filter;",
+    { "nativeOpenFilter", "(IIJ)Landroid/media/tv/tuner/Tuner/filter/Filter;",
             (void *)android_media_tv_Tuner_open_filter },
-    { "nativeOpenTimeFilter", "()Landroid/media/tv/tuner/Tuner$TimeFilter;",
+    { "nativeOpenTimeFilter", "()Landroid/media/tv/tuner/Tuner/filter/TimeFilter;",
             (void *)android_media_tv_Tuner_open_time_filter },
     { "nativeGetLnbIds", "()Ljava/util/List;",
             (void *)android_media_tv_Tuner_get_lnb_ids },
-    { "nativeOpenLnbById", "(I)Landroid/media/tv/tuner/Tuner$Lnb;",
+    { "nativeOpenLnbById", "(I)Landroid/media/tv/tuner/Lnb;",
             (void *)android_media_tv_Tuner_open_lnb_by_id },
-    { "nativeOpenDescrambler", "()Landroid/media/tv/tuner/Tuner$Descrambler;",
+    { "nativeOpenDescrambler", "()Landroid/media/tv/tuner/Descrambler;",
             (void *)android_media_tv_Tuner_open_descrambler },
-    { "nativeOpenDvr", "(II)Landroid/media/tv/tuner/Tuner$Dvr;",
-            (void *)android_media_tv_Tuner_open_dvr },
+    { "nativeOpenDvrRecorder", "(J)Landroid/media/tv/tuner/dvr/DvrRecorder;",
+            (void *)android_media_tv_Tuner_open_dvr_recorder },
+    { "nativeOpenDvrPlayback", "(J)Landroid/media/tv/tuner/dvr/DvrPlayback;",
+            (void *)android_media_tv_Tuner_open_dvr_playback },
     { "nativeGetDemuxCapabilities", "()Landroid/media/tv/tuner/DemuxCapabilities;",
             (void *)android_media_tv_Tuner_get_demux_caps },
 };
 
 static const JNINativeMethod gFilterMethods[] = {
-    { "nativeConfigureFilter", "(IILandroid/media/tv/tuner/FilterSettings;)I",
+    { "nativeConfigureFilter", "(IILandroid/media/tv/tuner/filter/FilterConfiguration;)I",
             (void *)android_media_tv_Tuner_configure_filter },
     { "nativeGetId", "()I", (void *)android_media_tv_Tuner_get_filter_id },
-    { "nativeSetDataSource", "(Landroid/media/tv/tuner/Tuner$Filter;)I",
+    { "nativeSetDataSource", "(Landroid/media/tv/tuner/filter/Filter;)I",
             (void *)android_media_tv_Tuner_set_filter_data_source },
     { "nativeStartFilter", "()I", (void *)android_media_tv_Tuner_start_filter },
     { "nativeStopFilter", "()I", (void *)android_media_tv_Tuner_stop_filter },
     { "nativeFlushFilter", "()I", (void *)android_media_tv_Tuner_flush_filter },
-    { "nativeRead", "([BII)I", (void *)android_media_tv_Tuner_read_filter_fmq },
+    { "nativeRead", "([BJJ)I", (void *)android_media_tv_Tuner_read_filter_fmq },
     { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_filter },
 };
 
@@ -1183,31 +1190,36 @@
 };
 
 static const JNINativeMethod gDescramblerMethods[] = {
-    { "nativeAddPid", "(IILandroid/media/tv/tuner/Tuner$Filter;)I",
+    { "nativeAddPid", "(IILandroid/media/tv/tuner/filter/Filter;)I",
             (void *)android_media_tv_Tuner_add_pid },
-    { "nativeRemovePid", "(IILandroid/media/tv/tuner/Tuner$Filter;)I",
+    { "nativeRemovePid", "(IILandroid/media/tv/tuner/filter/Filter;)I",
             (void *)android_media_tv_Tuner_remove_pid },
     { "nativeSetKeyToken", "([B)I", (void *)android_media_tv_Tuner_set_key_token },
     { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_descrambler },
 };
 
 static const JNINativeMethod gDvrMethods[] = {
-    { "nativeAttachFilter", "(Landroid/media/tv/tuner/Tuner$Filter;)I",
+    { "nativeAttachFilter", "(Landroid/media/tv/tuner/filter/Filter;)I",
             (void *)android_media_tv_Tuner_attach_filter },
-    { "nativeDetachFilter", "(Landroid/media/tv/tuner/Tuner$Filter;)I",
+    { "nativeDetachFilter", "(Landroid/media/tv/tuner/filter/Filter;)I",
             (void *)android_media_tv_Tuner_detach_filter },
-    { "nativeConfigureDvr", "(Landroid/media/tv/tuner/DvrSettings;)I",
+    { "nativeConfigureDvr", "(Landroid/media/tv/tuner/dvr/DvrSettings;)I",
             (void *)android_media_tv_Tuner_configure_dvr },
     { "nativeStartDvr", "()I", (void *)android_media_tv_Tuner_start_dvr },
     { "nativeStopDvr", "()I", (void *)android_media_tv_Tuner_stop_dvr },
     { "nativeFlushDvr", "()I", (void *)android_media_tv_Tuner_flush_dvr },
     { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_dvr },
-    { "nativeSetFileDescriptor", "(Ljava/io/FileDescriptor;)V",
-            (void *)android_media_tv_Tuner_dvr_set_fd },
-    { "nativeRead", "(I)I", (void *)android_media_tv_Tuner_read_dvr },
-    { "nativeRead", "([BII)I", (void *)android_media_tv_Tuner_read_dvr_from_array },
-    { "nativeWrite", "(I)I", (void *)android_media_tv_Tuner_write_dvr },
-    { "nativeWrite", "([BII)I", (void *)android_media_tv_Tuner_write_dvr_to_array },
+    { "nativeSetFileDescriptor", "(I)V", (void *)android_media_tv_Tuner_dvr_set_fd },
+};
+
+static const JNINativeMethod gDvrRecorderMethods[] = {
+    { "nativeWrite", "(J)J", (void *)android_media_tv_Tuner_write_dvr },
+    { "nativeWrite", "([BJJ)J", (void *)android_media_tv_Tuner_write_dvr_to_array },
+};
+
+static const JNINativeMethod gDvrPlaybackMethods[] = {
+    { "nativeRead", "(J)J", (void *)android_media_tv_Tuner_read_dvr },
+    { "nativeRead", "([BJJ)J", (void *)android_media_tv_Tuner_read_dvr_from_array },
 };
 
 static const JNINativeMethod gLnbMethods[] = {
@@ -1225,35 +1237,49 @@
         return false;
     }
     if (AndroidRuntime::registerNativeMethods(
-            env, "android/media/tv/tuner/Tuner$Filter",
+            env, "android/media/tv/tuner/filter/Filter",
             gFilterMethods,
             NELEM(gFilterMethods)) != JNI_OK) {
         ALOGE("Failed to register filter native methods");
         return false;
     }
     if (AndroidRuntime::registerNativeMethods(
-            env, "android/media/tv/tuner/Tuner$TimeFilter",
+            env, "android/media/tv/tuner/filter/TimeFilter",
             gTimeFilterMethods,
             NELEM(gTimeFilterMethods)) != JNI_OK) {
         ALOGE("Failed to register time filter native methods");
         return false;
     }
     if (AndroidRuntime::registerNativeMethods(
-            env, "android/media/tv/tuner/Tuner$Descrambler",
+            env, "android/media/tv/tuner/Descrambler",
             gDescramblerMethods,
             NELEM(gDescramblerMethods)) != JNI_OK) {
         ALOGE("Failed to register descrambler native methods");
         return false;
     }
     if (AndroidRuntime::registerNativeMethods(
-            env, "android/media/tv/tuner/Tuner$Dvr",
+            env, "android/media/tv/tuner/dvr/Dvr",
             gDvrMethods,
             NELEM(gDvrMethods)) != JNI_OK) {
         ALOGE("Failed to register dvr native methods");
         return false;
     }
     if (AndroidRuntime::registerNativeMethods(
-            env, "android/media/tv/tuner/Tuner$Lnb",
+            env, "android/media/tv/tuner/dvr/DvrRecorder",
+            gDvrRecorderMethods,
+            NELEM(gDvrRecorderMethods)) != JNI_OK) {
+        ALOGE("Failed to register dvr recorder native methods");
+        return false;
+    }
+    if (AndroidRuntime::registerNativeMethods(
+            env, "android/media/tv/tuner/dvr/DvrPlayback",
+            gDvrPlaybackMethods,
+            NELEM(gDvrPlaybackMethods)) != JNI_OK) {
+        ALOGE("Failed to register dvr playback native methods");
+        return false;
+    }
+    if (AndroidRuntime::registerNativeMethods(
+            env, "android/media/tv/tuner/Lnb",
             gLnbMethods,
             NELEM(gLnbMethods)) != JNI_OK) {
         ALOGE("Failed to register lnb native methods");
diff --git a/media/jni/soundpool/Android.bp b/media/jni/soundpool/Android.bp
index 0be2514..aa32793 100644
--- a/media/jni/soundpool/Android.bp
+++ b/media/jni/soundpool/Android.bp
@@ -13,6 +13,7 @@
 
     header_libs: [
         "libmedia_headers",
+        "libmediametrics_headers",
     ],
 
     shared_libs: [
diff --git a/media/jni/soundpool/tests/Android.bp b/media/jni/soundpool/tests/Android.bp
index 96ec4e5..52f59ed 100644
--- a/media/jni/soundpool/tests/Android.bp
+++ b/media/jni/soundpool/tests/Android.bp
@@ -16,6 +16,10 @@
         "libutils",
     ],
 
+    header_libs: [
+        "libmediametrics_headers",
+    ],
+
     srcs: [
         "soundpool_stress.cpp"
     ],
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
index f979fdd..c529952 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
@@ -311,6 +311,12 @@
                     cameraId, status));
         }
         @Override
+        public void onPhysicalCameraStatusChanged(int status, String cameraId,
+                String physicalCameraId) throws RemoteException {
+            Log.v(TAG, String.format("Camera %s : %s has status changed to 0x%x",
+                    cameraId, physicalCameraId, status));
+        }
+        @Override
         public void onCameraAccessPrioritiesChanged() {
             Log.v(TAG, "Camera access permission change");
         }
diff --git a/media/tests/audiotests/Android.bp b/media/tests/audiotests/Android.bp
index 8ef7694..5db0ab0 100644
--- a/media/tests/audiotests/Android.bp
+++ b/media/tests/audiotests/Android.bp
@@ -14,6 +14,10 @@
         "libaudioclient",
     ],
 
+    header_libs: [
+        "libmediametrics_headers",
+    ],
+
     cflags: [
         "-Wall",
         "-Werror",
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index 203adfc..97b861b 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -240,6 +240,7 @@
     ASurfaceTransaction_setColor; # introduced=29
     ASurfaceTransaction_setDamageRegion; # introduced=29
     ASurfaceTransaction_setDesiredPresentTime; # introduced=29
+    ASurfaceTransaction_setFrameRate; # introduced=30
     ASurfaceTransaction_setGeometry; # introduced=29
     ASurfaceTransaction_setHdrMetadata_cta861_3; # introduced=29
     ASurfaceTransaction_setHdrMetadata_smpte2086; # introduced=29
diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp
index b34b31a..392c9f6 100644
--- a/native/android/surface_control.cpp
+++ b/native/android/surface_control.cpp
@@ -545,3 +545,18 @@
 
     transaction->setBackgroundColor(surfaceControl, color, alpha, static_cast<ui::Dataspace>(dataspace));
 }
+
+void ASurfaceTransaction_setFrameRate(ASurfaceTransaction* aSurfaceTransaction,
+                                      ASurfaceControl* aSurfaceControl, float frameRate) {
+    CHECK_NOT_NULL(aSurfaceTransaction);
+    CHECK_NOT_NULL(aSurfaceControl);
+
+    sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
+    if (frameRate < 0) {
+        ALOGE("Failed to set frame ate - invalid frame rate");
+        return;
+    }
+
+    Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
+    transaction->setFrameRate(surfaceControl, frameRate);
+}
diff --git a/native/graphics/jni/imagedecoder.cpp b/native/graphics/jni/imagedecoder.cpp
index 1c45ea6..c1143ce 100644
--- a/native/graphics/jni/imagedecoder.cpp
+++ b/native/graphics/jni/imagedecoder.cpp
@@ -208,13 +208,6 @@
     return getMimeType(toDecoder(info)->mCodec->getEncodedFormat());
 }
 
-bool AImageDecoderHeaderInfo_isAnimated(const AImageDecoderHeaderInfo* info) {
-    if (!info) {
-        return false;
-    }
-    return toDecoder(info)->mCodec->codec()->getFrameCount() > 1;
-}
-
 int32_t AImageDecoderHeaderInfo_getDataSpace(const AImageDecoderHeaderInfo* info) {
     if (!info) {
         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
@@ -247,8 +240,7 @@
     }
 }
 
-AndroidBitmapFormat AImageDecoderHeaderInfo_getAndroidBitmapFormat(
-        const AImageDecoderHeaderInfo* info) {
+int32_t AImageDecoderHeaderInfo_getAndroidBitmapFormat(const AImageDecoderHeaderInfo* info) {
     if (!info) {
         return ANDROID_BITMAP_FORMAT_NONE;
     }
@@ -281,7 +273,7 @@
             ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
 }
 
-int AImageDecoder_setTargetSize(AImageDecoder* decoder, int width, int height) {
+int AImageDecoder_setTargetSize(AImageDecoder* decoder, int32_t width, int32_t height) {
     if (!decoder) {
         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
     }
@@ -291,7 +283,7 @@
 }
 
 int AImageDecoder_computeSampledSize(const AImageDecoder* decoder, int sampleSize,
-                                     int* width, int* height) {
+                                     int32_t* width, int32_t* height) {
     if (!decoder || !width || !height || sampleSize < 1) {
         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
     }
@@ -333,11 +325,9 @@
 
     ImageDecoder* imageDecoder = toDecoder(decoder);
 
-    const int height = imageDecoder->getOutputInfo().height();
-    const size_t minStride = AImageDecoder_getMinimumStride(decoder);
-    // If this calculation were to overflow, it would have been caught in
-    // setTargetSize.
-    if (stride < minStride || size < stride * (height - 1) + minStride) {
+    SkImageInfo info = imageDecoder->getOutputInfo();
+    size_t minSize = info.computeByteSize(stride);
+    if (SkImageInfo::ByteSizeOverflowed(minSize) || size < minSize || !info.validRowBytes(stride)) {
         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
     }
 
diff --git a/native/graphics/jni/libjnigraphics.map.txt b/native/graphics/jni/libjnigraphics.map.txt
index 1b396b8..01c1477 100644
--- a/native/graphics/jni/libjnigraphics.map.txt
+++ b/native/graphics/jni/libjnigraphics.map.txt
@@ -17,7 +17,6 @@
     AImageDecoderHeaderInfo_getHeight; # introduced=30
     AImageDecoderHeaderInfo_getMimeType; # introduced=30
     AImageDecoderHeaderInfo_getAlphaFlags; # introduced=30
-    AImageDecoderHeaderInfo_isAnimated; # introduced=30
     AImageDecoderHeaderInfo_getAndroidBitmapFormat; # introduced=30
     AImageDecoderHeaderInfo_getDataSpace; # introduced=30
     AndroidBitmap_getInfo;
diff --git a/opengl/java/com/google/android/gles_jni/EGLImpl.java b/opengl/java/com/google/android/gles_jni/EGLImpl.java
index f94f69f..b4ea0a6 100644
--- a/opengl/java/com/google/android/gles_jni/EGLImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLImpl.java
@@ -16,13 +16,12 @@
 
 package com.google.android.gles_jni;
 
+import android.compat.annotation.UnsupportedAppUsage;
 import android.graphics.SurfaceTexture;
 import android.view.Surface;
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
 import javax.microedition.khronos.egl.EGL10;
 import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.egl.EGLContext;
diff --git a/opengl/java/com/google/android/gles_jni/GLImpl.java b/opengl/java/com/google/android/gles_jni/GLImpl.java
index 2a8d07f..3c808a6 100644
--- a/opengl/java/com/google/android/gles_jni/GLImpl.java
+++ b/opengl/java/com/google/android/gles_jni/GLImpl.java
@@ -20,14 +20,13 @@
 package com.google.android.gles_jni;
 
 import android.app.AppGlobals;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.os.Build;
 import android.os.UserHandle;
 import android.util.Log;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
 import java.nio.Buffer;
 
 import javax.microedition.khronos.opengles.GL10;
diff --git a/packages/CarSystemUI/src/com/android/systemui/TEST_MAPPING b/packages/CarSystemUI/TEST_MAPPING
similarity index 100%
rename from packages/CarSystemUI/src/com/android/systemui/TEST_MAPPING
rename to packages/CarSystemUI/TEST_MAPPING
diff --git a/packages/CarSystemUI/res/layout/super_notification_shade.xml b/packages/CarSystemUI/res/layout/super_notification_shade.xml
index 3fe1ea3..cb65045 100644
--- a/packages/CarSystemUI/res/layout/super_notification_shade.xml
+++ b/packages/CarSystemUI/res/layout/super_notification_shade.xml
@@ -59,24 +59,6 @@
         sysui:ignoreRightInset="true"
     />
 
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/status_bar_height"
-        android:orientation="vertical"
-    >
-        <FrameLayout
-            android:id="@+id/status_bar_container"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:visibility="gone"
-        />
-
-        <FrameLayout
-            android:id="@+id/car_top_navigation_bar_container"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"/>
-    </LinearLayout>
-
     <include layout="@layout/brightness_mirror"/>
 
     <ViewStub android:id="@+id/fullscreen_user_switcher_stub"
diff --git a/packages/CarSystemUI/res/layout/super_status_bar.xml b/packages/CarSystemUI/res/layout/super_status_bar.xml
index c7b22f8..d93f62f 100644
--- a/packages/CarSystemUI/res/layout/super_status_bar.xml
+++ b/packages/CarSystemUI/res/layout/super_status_bar.xml
@@ -25,9 +25,22 @@
     android:layout_height="match_parent"
     android:fitsSystemWindows="true">
 
-    <FrameLayout
-        android:id="@+id/status_bar_container"
+    <LinearLayout
         android:layout_width="match_parent"
-        android:layout_height="wrap_content" />
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+    >
+        <FrameLayout
+            android:id="@+id/status_bar_container"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:visibility="gone"
+        />
+
+        <FrameLayout
+            android:id="@+id/car_top_navigation_bar_container"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"/>
+    </LinearLayout>
 
 </com.android.systemui.statusbar.phone.StatusBarWindowView>
diff --git a/packages/CarSystemUI/res/values/config.xml b/packages/CarSystemUI/res/values/config.xml
index 981c129..e2297e4 100644
--- a/packages/CarSystemUI/res/values/config.xml
+++ b/packages/CarSystemUI/res/values/config.xml
@@ -80,5 +80,6 @@
         <item>com.android.systemui.statusbar.notification.InstantAppNotifier</item>
         <item>com.android.systemui.theme.ThemeOverlayController</item>
         <item>com.android.systemui.navigationbar.car.CarNavigationBar</item>
+        <item>com.android.systemui.toast.ToastUI</item>
     </string-array>
 </resources>
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java
index 0bd2e06..07b7b22 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java
@@ -32,6 +32,7 @@
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.tv.TvStatusBar;
 import com.android.systemui.theme.ThemeOverlayController;
+import com.android.systemui.toast.ToastUI;
 import com.android.systemui.util.leak.GarbageMonitor;
 import com.android.systemui.volume.VolumeUI;
 
@@ -163,4 +164,10 @@
     @IntoMap
     @ClassKey(VolumeUI.class)
     public abstract SystemUI bindVolumeUI(VolumeUI sysui);
+
+    /** Inject into ToastUI. */
+    @Binds
+    @IntoMap
+    @ClassKey(ToastUI.class)
+    public abstract SystemUI bindToastUI(ToastUI service);
 }
diff --git a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java
index dc84935..3a52015 100644
--- a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java
@@ -235,7 +235,7 @@
 
     private void buildNavBarWindows() {
         mTopNavigationBarWindow = mSuperStatusBarViewFactory
-                .getNotificationShadeWindowView()
+                .getStatusBarWindowView()
                 .findViewById(R.id.car_top_navigation_bar_container);
         mBottomNavigationBarWindow = mCarNavigationBarController.getBottomWindow();
         mLeftNavigationBarWindow = mCarNavigationBarController.getLeftWindow();
diff --git a/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java b/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java
index 3312651..d1a379a 100644
--- a/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java
+++ b/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java
@@ -205,7 +205,7 @@
         }
 
         @Override
-        public void onSetEnabled(boolean enabled) {
+        public void onSetAllowed(boolean allowed) {
 
         }
 
diff --git a/packages/Incremental/NativeAdbDataLoader/jni/com_android_incremental_nativeadb_DataLoaderService.cpp b/packages/Incremental/NativeAdbDataLoader/jni/com_android_incremental_nativeadb_DataLoaderService.cpp
index 4e49302..01150b7 100644
--- a/packages/Incremental/NativeAdbDataLoader/jni/com_android_incremental_nativeadb_DataLoaderService.cpp
+++ b/packages/Incremental/NativeAdbDataLoader/jni/com_android_incremental_nativeadb_DataLoaderService.cpp
@@ -32,6 +32,7 @@
 #include <utils/Log.h>
 
 #include <charconv>
+#include <span>
 #include <string>
 #include <thread>
 #include <type_traits>
@@ -92,9 +93,7 @@
 
 static_assert(COMMAND_SIZE == sizeof(RequestCommand));
 
-static bool sendRequest(int fd,
-                        RequestType requestType,
-                        FileId fileId = -1,
+static bool sendRequest(int fd, RequestType requestType, FileId fileId = -1,
                         BlockIdx blockIdx = -1) {
     const RequestCommand command{
             .requestType = static_cast<int16_t>(be16toh(requestType)),
@@ -267,25 +266,24 @@
         std::lock_guard lock{mMapsMutex};
         CHECK(mIfs);
         for (auto&& pendingRead : pendingReads) {
-            const android::dataloader::Inode ino = pendingRead.file_ino;
-            const auto blockIdx =
-                    static_cast<BlockIdx>(pendingRead.block_index);
+            const android::dataloader::FileId id = pendingRead.id;
+            const auto blockIdx = static_cast<BlockIdx>(pendingRead.block);
             /*
             ALOGI("[AdbDataLoader] Missing: %d", (int) blockIdx);
             */
-            auto fileIdOr = getFileId(ino);
+            auto fileIdOr = getFileId(id);
             if (!fileIdOr) {
-                ALOGE("[AdbDataLoader] Failed to handle event for inode=%d. "
+                ALOGE("[AdbDataLoader] Failed to handle event for fileid=%s. "
                       "Ignore.",
-                      static_cast<int>(ino));
+                      android::incfs::toString(id).c_str());
                 continue;
             }
             const FileId fileId = *fileIdOr;
             if (mRequestedFiles.insert(fileId).second) {
                 if (!sendRequest(mOutFd, PREFETCH, fileId, blockIdx)) {
                     ALOGE("[AdbDataLoader] Failed to request prefetch for "
-                          "inode=%d. Ignore.",
-                          static_cast<int>(ino));
+                          "fileid=%s. Ignore.",
+                          android::incfs::toString(id).c_str());
                     mRequestedFiles.erase(fileId);
                     mStatusListener->reportStatus(DATA_LOADER_NO_CONNECTION);
                 }
@@ -296,7 +294,7 @@
 
     struct TracedRead {
         uint64_t timestampUs;
-        uint64_t fileIno;
+        android::dataloader::FileId fileId;
         uint32_t firstBlockIdx;
         uint32_t count;
     };
@@ -307,26 +305,26 @@
             return;
         }
 
-        TracedRead last = {0, 0, 0, 0};
+        TracedRead last = {};
         std::lock_guard lock{mMapsMutex};
         for (auto&& read : pageReads) {
-            if (read.file_ino != last.fileIno ||
-                read.block_index != last.firstBlockIdx + last.count) {
+            if (read.id != last.fileId || read.block != last.firstBlockIdx + last.count) {
                 traceOrLogRead(last, trace, log);
-                last = {read.timestamp_us, read.file_ino, read.block_index, 1};
+                last = {read.bootClockTsUs, read.id, (uint32_t)read.block, 1};
             } else {
                 ++last.count;
             }
         }
         traceOrLogRead(last, trace, log);
     }
-    void onFileCreated(android::dataloader::Inode inode, const android::dataloader::RawMetadata& metadata) {
-    }
+    void onFileCreated(android::dataloader::FileId fileid,
+                       const android::dataloader::RawMetadata& metadata) {}
 
 private:
     void receiver() {
         std::vector<uint8_t> data;
-        std::vector<incfs_new_data_block> instructions;
+        std::vector<IncFsDataBlock> instructions;
+        std::unordered_map<android::dataloader::FileId, unique_fd> writeFds;
         while (!mStopReceiving) {
             const int res = waitForDataOrSignal(mInFd, mEventFd);
             if (res == 0) {
@@ -366,21 +364,32 @@
                     mStopReceiving = true;
                     break;
                 }
-                const android::dataloader::Inode ino = mIdToNodeMap[header.fileId];
-                if (!ino) {
+                const android::dataloader::FileId id = mIdToNodeMap[header.fileId];
+                if (!android::incfs::isValidFileId(id)) {
                     ALOGE("Unknown data destination for file ID %d. "
                           "Ignore.",
                           header.fileId);
                     continue;
                 }
-                auto inst = incfs_new_data_block{
-                        .file_ino = static_cast<__aligned_u64>(ino),
-                        .block_index = static_cast<uint32_t>(header.blockIdx),
-                        .data_len = static_cast<uint16_t>(header.blockSize),
-                        .data = reinterpret_cast<uint64_t>(
-                                remainingData.data()),
-                        .compression =
-                                static_cast<uint8_t>(header.compressionType)};
+
+                auto& writeFd = writeFds[id];
+                if (writeFd < 0) {
+                    writeFd.reset(this->mIfs->openWrite(id));
+                    if (writeFd < 0) {
+                        ALOGE("Failed to open file %d for writing (%d). Aboring.", header.fileId,
+                              -writeFd);
+                        break;
+                    }
+                }
+
+                const auto inst = IncFsDataBlock{
+                        .fileFd = writeFd,
+                        .pageIndex = static_cast<IncFsBlockIndex>(header.blockIdx),
+                        .compression = static_cast<IncFsCompressionKind>(header.compressionType),
+                        .kind = INCFS_BLOCK_KIND_DATA,
+                        .dataSize = static_cast<uint16_t>(header.blockSize),
+                        .data = (const char*)remainingData.data(),
+                };
                 instructions.push_back(inst);
                 remainingData = remainingData.subspan(header.blockSize);
             }
@@ -390,9 +399,8 @@
         flushReadLog();
     }
 
-    void writeInstructions(std::vector<incfs_new_data_block>& instructions) {
-        auto res = this->mIfs->writeBlocks(instructions.data(),
-                                           instructions.size());
+    void writeInstructions(std::vector<IncFsDataBlock>& instructions) {
+        auto res = this->mIfs->writeBlocks(instructions);
         if (res != instructions.size()) {
             ALOGE("[AdbDataLoader] failed to write data to Incfs (res=%d when "
                   "expecting %d)",
@@ -406,30 +414,30 @@
         FileId fileId;
     };
 
-    MetaPair* updateMapsForFile(android::dataloader::Inode ino) {
-        android::dataloader::RawMetadata meta = mIfs->getRawMetadata(ino);
+    MetaPair* updateMapsForFile(android::dataloader::FileId id) {
+        android::dataloader::RawMetadata meta = mIfs->getRawMetadata(id);
         FileId fileId;
         auto res =
                 std::from_chars(meta.data(), meta.data() + meta.size(), fileId);
         if (res.ec != std::errc{} || fileId < 0) {
-            ALOGE("[AdbDataLoader] Invalid metadata for inode=%d (%s)",
-                  static_cast<int>(ino), meta.data());
+            ALOGE("[AdbDataLoader] Invalid metadata for fileid=%s (%s)",
+                  android::incfs::toString(id).c_str(), meta.data());
             return nullptr;
         }
-        mIdToNodeMap[fileId] = ino;
-        auto& metaPair = mNodeToMetaMap[ino];
+        mIdToNodeMap[fileId] = id;
+        auto& metaPair = mNodeToMetaMap[id];
         metaPair.meta = std::move(meta);
         metaPair.fileId = fileId;
         return &metaPair;
     }
 
-    android::dataloader::RawMetadata* getMeta(android::dataloader::Inode ino) {
-        auto it = mNodeToMetaMap.find(ino);
+    android::dataloader::RawMetadata* getMeta(android::dataloader::FileId id) {
+        auto it = mNodeToMetaMap.find(id);
         if (it != mNodeToMetaMap.end()) {
             return &it->second.meta;
         }
 
-        auto metaPair = updateMapsForFile(ino);
+        auto metaPair = updateMapsForFile(id);
         if (!metaPair) {
             return nullptr;
         }
@@ -437,13 +445,13 @@
         return &metaPair->meta;
     }
 
-    FileId* getFileId(android::dataloader::Inode ino) {
-        auto it = mNodeToMetaMap.find(ino);
+    FileId* getFileId(android::dataloader::FileId id) {
+        auto it = mNodeToMetaMap.find(id);
         if (it != mNodeToMetaMap.end()) {
             return &it->second.fileId;
         }
 
-        auto* metaPair = updateMapsForFile(ino);
+        auto* metaPair = updateMapsForFile(id);
         if (!metaPair) {
             return nullptr;
         }
@@ -456,7 +464,7 @@
             return;
         }
         if (trace) {
-            auto* meta = getMeta(read.fileIno);
+            auto* meta = getMeta(read.fileId);
             auto str = android::base::StringPrintf(
                     "page_read: index=%lld count=%lld meta=%.*s",
                     static_cast<long long>(read.firstBlockIdx),
@@ -468,7 +476,7 @@
         if (log) {
             mReadLog.reserve(ReadLogBufferSize);
 
-            auto fileId = getFileId(read.fileIno);
+            auto fileId = getFileId(read.fileId);
             android::base::StringAppendF(
                     &mReadLog, "%lld:%lld:%lld:%lld\n",
                     static_cast<long long>(read.timestampUs),
@@ -501,8 +509,8 @@
     std::string mReadLog;
     std::thread mReceiverThread;
     std::mutex mMapsMutex;
-    std::unordered_map<android::dataloader::Inode, MetaPair> mNodeToMetaMap GUARDED_BY(mMapsMutex);
-    std::unordered_map<FileId, android::dataloader::Inode> mIdToNodeMap GUARDED_BY(mMapsMutex);
+    std::unordered_map<android::dataloader::FileId, MetaPair> mNodeToMetaMap GUARDED_BY(mMapsMutex);
+    std::unordered_map<FileId, android::dataloader::FileId> mIdToNodeMap GUARDED_BY(mMapsMutex);
     /** Tracks which files have been requested */
     std::unordered_set<FileId> mRequestedFiles;
     std::atomic<bool> mStopReceiving = false;
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 9d4c24e..84dde05 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -1141,7 +1141,7 @@
         } else if (isActive()) {
             summary.append(getSummary(mContext, /* ssid */ null, getDetailedState(),
                     mInfo != null && mInfo.isEphemeral(),
-                    mInfo != null ? mInfo.getAppPackageName() : null));
+                    mInfo != null ? mInfo.getRequestingPackageName() : null));
         } else { // not active
             if (mConfig != null && mConfig.hasNoInternetAccess()) {
                 int messageID = mConfig.getNetworkSelectionStatus().isNetworkPermanentlyDisabled()
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEntryPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEntryPreference.java
index 2d7d59c..4ebb102 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEntryPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEntryPreference.java
@@ -199,8 +199,7 @@
             return;
         }
         if ((mWifiEntry.getSecurity() != WifiEntry.SECURITY_NONE)
-                && (mWifiEntry.getSecurity() != WifiEntry.SECURITY_OWE)
-                && (mWifiEntry.getSecurity() != WifiEntry.SECURITY_OWE_TRANSITION)) {
+                && (mWifiEntry.getSecurity() != WifiEntry.SECURITY_OWE)) {
             mFrictionSld.setState(STATE_SECURED);
         } else if (mWifiEntry.isMetered()) {
             mFrictionSld.setState(STATE_METERED);
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index ed4ff08..26abf71 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -226,7 +226,7 @@
         mConnectivityManager = connectivityManager;
 
         // check if verbose logging developer option has been turned on or off
-        sVerboseLogging = mWifiManager != null && (mWifiManager.getVerboseLoggingLevel() > 0);
+        sVerboseLogging = mWifiManager != null && mWifiManager.isVerboseLoggingEnabled();
 
         mFilter = filter;
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java
index b93b000..78ccba0 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java
@@ -102,10 +102,10 @@
             if (accessPoint.getSpeed() != AccessPoint.Speed.NONE) {
                 visibility.append(" speed=").append(accessPoint.getSpeedLabel());
             }
-            visibility.append(String.format(" tx=%.1f,", info.getTxSuccessRate()));
-            visibility.append(String.format("%.1f,", info.getTxRetriesRate()));
-            visibility.append(String.format("%.1f ", info.getTxBadRate()));
-            visibility.append(String.format("rx=%.1f", info.getRxSuccessRate()));
+            visibility.append(String.format(" tx=%.1f,", info.getSuccessfulTxPacketsPerSecond()));
+            visibility.append(String.format("%.1f,", info.getRetriedTxPacketsPerSecond()));
+            visibility.append(String.format("%.1f ", info.getLostTxPacketsPerSecond()));
+            visibility.append(String.format("rx=%.1f", info.getSuccessfulRxPacketsPerSecond()));
         }
 
         int maxRssi5 = INVALID_RSSI;
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index 03201ae..42f3cbb 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -507,7 +507,7 @@
         WifiInfo wifiInfo = new WifiInfo();
         wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(TEST_SSID));
         wifiInfo.setEphemeral(true);
-        wifiInfo.setAppPackageName(appPackageName);
+        wifiInfo.setRequestingPackageName(appPackageName);
         wifiInfo.setRssi(rssi);
 
         Context context = mock(Context.class);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 486386f..1072076 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -4488,7 +4488,7 @@
                         try {
                             overlayManager.setEnabledExclusiveInCategory(
                                     NAV_BAR_MODE_2BUTTON_OVERLAY, UserHandle.USER_CURRENT);
-                        } catch (RemoteException e) {
+                        } catch (SecurityException | IllegalStateException | RemoteException e) {
                             throw new IllegalStateException(
                                     "Failed to set nav bar interaction mode overlay");
                         }
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index b896a2a..6d94a90 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -31,6 +31,7 @@
 import android.provider.settings.backup.SystemSettings;
 
 import androidx.test.filters.SmallTest;
+import androidx.test.filters.Suppress;
 import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
@@ -224,6 +225,7 @@
                     Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES,
                     Settings.Global.DEVELOPMENT_FORCE_RTL,
                     Settings.Global.DEVELOPMENT_ENABLE_SIZECOMPAT_FREEFORM,
+                    Settings.Global.DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR,
                     Settings.Global.DEVICE_DEMO_MODE,
                     Settings.Global.DEVICE_IDLE_CONSTANTS,
                     Settings.Global.BATTERY_SAVER_ADAPTIVE_CONSTANTS,
@@ -277,6 +279,7 @@
                     Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED,
                     Settings.Global.WIFI_ON_WHEN_PROXY_DISCONNECTED,
                     Settings.Global.FSTRIM_MANDATORY_INTERVAL,
+                    Settings.Global.FOREGROUND_SERVICE_STARTS_LOGGING_ENABLED,
                     Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
                     Settings.Global.GLOBAL_HTTP_PROXY_HOST,
                     Settings.Global.GLOBAL_HTTP_PROXY_PAC,
@@ -574,7 +577,8 @@
                     Settings.Global.ENABLED_SUBSCRIPTION_FOR_SLOT,
                     Settings.Global.MODEM_STACK_ENABLED_FOR_SLOT,
                     Settings.Global.POWER_BUTTON_LONG_PRESS,
-                    Settings.Global.POWER_BUTTON_VERY_LONG_PRESS);
+                    Settings.Global.POWER_BUTTON_VERY_LONG_PRESS,
+                    Settings.Global.INTEGRITY_CHECK_INCLUDES_RULE_PROVIDER);
 
     private static final Set<String> BACKUP_BLACKLISTED_SECURE_SETTINGS =
              newHashSet(
@@ -746,6 +750,7 @@
     }
 
     @Test
+    @Suppress //("b/148236308")
     public void secureSettingsBackedUpOrBlacklisted() {
         HashSet<String> keys = new HashSet<String>();
         Collections.addAll(keys, SecureSettings.SETTINGS_TO_BACKUP);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index fb9bc52..0f35853 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -110,6 +110,7 @@
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" />
+    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
     <uses-permission android:name="android.permission.CREATE_USERS" />
@@ -239,6 +240,13 @@
     <!-- Allows setting brightness from the shell -->
     <uses-permission android:name="android.permission.CONTROL_DISPLAY_BRIGHTNESS"/>
 
+    <!-- Permissions required to test ambient display. -->
+    <uses-permission android:name="android.permission.READ_DREAM_STATE"/>
+    <uses-permission android:name="android.permission.WRITE_DREAM_STATE"/>
+
+    <!-- Permission required for CTS test - CtsLightsManagerTest -->
+    <uses-permission android:name="android.permission.CONTROL_DEVICE_LIGHTS" />
+
     <application android:label="@string/app_label"
                 android:theme="@android:style/Theme.DeviceDefault.DayNight"
                 android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 30ad9c5..48d405a 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -156,7 +156,6 @@
     static final String EXTRA_BUGREPORT_TYPE = "android.intent.extra.BUGREPORT_TYPE";
     static final String EXTRA_SCREENSHOT = "android.intent.extra.SCREENSHOT";
     static final String EXTRA_ID = "android.intent.extra.ID";
-    static final String EXTRA_MAX = "android.intent.extra.MAX";
     static final String EXTRA_NAME = "android.intent.extra.NAME";
     static final String EXTRA_TITLE = "android.intent.extra.TITLE";
     static final String EXTRA_DESCRIPTION = "android.intent.extra.DESCRIPTION";
@@ -173,7 +172,6 @@
 
     // Maximum progress displayed in %.
     private static final int CAPPED_PROGRESS = 99;
-    private static final int CAPPED_MAX = 100;
 
     /** Show the progress log every this percent. */
     private static final int LOG_PROGRESS_STEP = 10;
@@ -528,12 +526,10 @@
             }
             final String action = intent.getAction();
             final int id = intent.getIntExtra(EXTRA_ID, 0);
-            final int max = intent.getIntExtra(EXTRA_MAX, -1);
             final String name = intent.getStringExtra(EXTRA_NAME);
 
             if (DEBUG)
-                Log.v(TAG, "action: " + action + ", name: " + name + ", id: " + id
-                        + ", max: " + max);
+                Log.v(TAG, "action: " + action + ", name: " + name + ", id: " + id);
             switch (action) {
                 case INTENT_BUGREPORT_REQUESTED:
                     startBugreportAPI(intent);
@@ -608,7 +604,7 @@
         String name = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date());
 
         BugreportInfo info = new BugreportInfo(mContext, baseName, name,
-                100 /* max progress*/, shareTitle, shareDescription, bugreportType);
+                shareTitle, shareDescription, bugreportType);
 
         ParcelFileDescriptor bugreportFd = info.createBugreportFd();
         if (bugreportFd == null) {
@@ -662,8 +658,8 @@
      * Updates the system notification for a given bugreport.
      */
     private void updateProgress(BugreportInfo info) {
-        if (info.max <= 0 || info.progress < 0) {
-            Log.e(TAG, "Invalid progress values for " + info);
+        if (info.progress < 0) {
+            Log.e(TAG, "Invalid progress value for " + info);
             return;
         }
 
@@ -676,7 +672,7 @@
         final NumberFormat nf = NumberFormat.getPercentInstance();
         nf.setMinimumFractionDigits(2);
         nf.setMaximumFractionDigits(2);
-        final String percentageText = nf.format((double) info.progress / info.max);
+        final String percentageText = nf.format((double) info.progress / 100);
 
         String title = mContext.getString(R.string.bugreport_in_progress_title, info.id);
 
@@ -684,7 +680,7 @@
         if (mIsWatch) {
             nf.setMinimumFractionDigits(0);
             nf.setMaximumFractionDigits(0);
-            final String watchPercentageText = nf.format((double) info.progress / info.max);
+            final String watchPercentageText = nf.format((double) info.progress / 100);
             title = title + "\n" + watchPercentageText;
         }
 
@@ -695,7 +691,7 @@
                 .setContentTitle(title)
                 .setTicker(title)
                 .setContentText(name)
-                .setProgress(info.max, info.progress, false)
+                .setProgress(100 /* max value of progress percentage */, info.progress, false)
                 .setOngoing(true);
 
         // Wear and ATV bugreport doesn't need the bug info dialog, screenshot and cancel action.
@@ -724,7 +720,7 @@
                 .setActions(infoAction, screenshotAction, cancelAction);
         }
         // Show a debug log, every LOG_PROGRESS_STEP percent.
-        final int progress = (info.progress * 100) / info.max;
+        final int progress = info.progress;
 
         if ((info.progress == 0) || (info.progress >= 100) ||
                 ((progress / LOG_PROGRESS_STEP) != (mLastProgressPercent / LOG_PROGRESS_STEP))) {
@@ -1457,7 +1453,6 @@
         }
         final StringBuilder buffer = new StringBuilder(action).append(" extras: ");
         addExtra(buffer, intent, EXTRA_ID);
-        addExtra(buffer, intent, EXTRA_MAX);
         addExtra(buffer, intent, EXTRA_NAME);
         addExtra(buffer, intent, EXTRA_DESCRIPTION);
         addExtra(buffer, intent, EXTRA_BUGREPORT);
@@ -1761,26 +1756,11 @@
         String description;
 
         /**
-         * Maximum progress of the bugreport generation as displayed by the UI.
-         */
-        int max;
-
-        /**
-         * Current progress of the bugreport generation as displayed by the UI.
+         * Current progress (in percentage) of the bugreport generation as displayed by the UI.
          */
         int progress;
 
         /**
-         * Maximum progress of the bugreport generation as reported by dumpstate.
-         */
-        int realMax;
-
-        /**
-         * Current progress of the bugreport generation as reported by dumpstate.
-         */
-        int realProgress;
-
-        /**
          * Time of the last progress update.
          */
         long lastUpdate = System.currentTimeMillis();
@@ -1831,12 +1811,11 @@
         /**
          * Constructor for tracked bugreports - typically called upon receiving BUGREPORT_REQUESTED.
          */
-        BugreportInfo(Context context, String baseName, String name, int max,
+        BugreportInfo(Context context, String baseName, String name,
                 @Nullable String shareTitle, @Nullable String shareDescription,
                 @BugreportParams.BugreportMode int type) {
             this.context = context;
             this.name = this.initialName = name;
-            this.max = this.realMax = max;
             this.shareTitle = shareTitle == null ? "" : shareTitle;
             this.shareDescription = shareDescription == null ? "" : shareDescription;
             this.type = type;
@@ -1930,8 +1909,6 @@
 
         @Override
         public String toString() {
-            final float percent = ((float) progress * 100 / max);
-            final float realPercent = ((float) realProgress * 100 / realMax);
 
             final StringBuilder builder = new StringBuilder()
                     .append("\tid: ").append(id)
@@ -1953,10 +1930,7 @@
             return builder
                 .append("\n\tfile: ").append(bugreportFile)
                 .append("\n\tscreenshots: ").append(screenshotFiles)
-                .append("\n\tprogress: ").append(progress).append("/").append(max)
-                .append(" (").append(percent).append(")")
-                .append("\n\treal progress: ").append(realProgress).append("/").append(realMax)
-                .append(" (").append(realPercent).append(")")
+                .append("\n\tprogress: ").append(progress)
                 .append("\n\tlast_update: ").append(getFormattedLastUpdate())
                 .append("\n\taddingDetailsToZip: ").append(addingDetailsToZip)
                 .append(" addedDetailsToZip: ").append(addedDetailsToZip)
@@ -1974,10 +1948,7 @@
             initialName = in.readString();
             title = in.readString();
             description = in.readString();
-            max = in.readInt();
             progress = in.readInt();
-            realMax = in.readInt();
-            realProgress = in.readInt();
             lastUpdate = in.readLong();
             formattedLastUpdate = in.readString();
             bugreportFile = readFile(in);
@@ -2001,10 +1972,7 @@
             dest.writeString(initialName);
             dest.writeString(title);
             dest.writeString(description);
-            dest.writeInt(max);
             dest.writeInt(progress);
-            dest.writeInt(realMax);
-            dest.writeInt(realProgress);
             dest.writeLong(lastUpdate);
             dest.writeString(getFormattedLastUpdate());
             writeFile(dest, bugreportFile);
@@ -2055,22 +2023,13 @@
         if (progress > CAPPED_PROGRESS) {
             progress = CAPPED_PROGRESS;
         }
-        updateProgressInfo(info, progress, CAPPED_MAX);
-    }
-
-    private void updateProgressInfo(BugreportInfo info, int progress, int max) {
         if (DEBUG) {
             if (progress != info.progress) {
                 Log.v(TAG, "Updating progress for name " + info.name + "(id: " + info.id
                         + ") from " + info.progress + " to " + progress);
             }
-            if (max != info.max) {
-                Log.v(TAG, "Updating max progress for name " + info.name + "(id: " + info.id
-                        + ") from " + info.max + " to " + max);
-            }
         }
         info.progress = progress;
-        info.max = max;
         info.lastUpdate = System.currentTimeMillis();
 
         updateProgress(info);
diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
index bb298e9..b95092a 100644
--- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
+++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
@@ -27,7 +27,6 @@
 import static com.android.shell.BugreportPrefs.setWarningState;
 import static com.android.shell.BugreportProgressService.EXTRA_BUGREPORT;
 import static com.android.shell.BugreportProgressService.EXTRA_ID;
-import static com.android.shell.BugreportProgressService.EXTRA_MAX;
 import static com.android.shell.BugreportProgressService.EXTRA_NAME;
 import static com.android.shell.BugreportProgressService.EXTRA_SCREENSHOT;
 import static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_FINISHED;
@@ -144,6 +143,7 @@
     private static final String DESCRIPTION = "One's description...";
     private static final String DESCRIPTION2 = "...is another's treasure.";
     // TODO(b/143130523): Fix (update) tests and add to presubmit
+    private static final String EXTRA_MAX = "android.intent.extra.MAX";
     private static final String EXTRA_PID = "android.intent.extra.PID";
     private static final String INTENT_BUGREPORT_STARTED =
             "com.android.internal.intent.action.BUGREPORT_STARTED";
diff --git a/packages/SystemUI/TEST_MAPPING b/packages/SystemUI/TEST_MAPPING
index 9f13a7b..cff958f 100644
--- a/packages/SystemUI/TEST_MAPPING
+++ b/packages/SystemUI/TEST_MAPPING
@@ -16,5 +16,24 @@
         }
       ]
     }
+  ],
+  "platinum-postsubmit": [
+    {
+      "name": "PlatformScenarioTests",
+      "options": [
+        {
+            "include-filter": "android.platform.test.scenario.sysui"
+        },
+        {
+            "include-annotation": "android.platform.test.scenario.annotation.Scenario"
+        },
+        {
+            "exclude-annotation": "androidx.test.filters.FlakyTest"
+        },
+        {
+            "exclude-annotation": "android.platform.helpers.Staging"
+        }
+      ]
+    }
   ]
 }
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
index 6518924..17f2f47 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
@@ -133,6 +133,7 @@
         public CharSequence label;
         public CharSequence secondaryLabel;
         public CharSequence contentDescription;
+        public CharSequence stateDescription;
         public CharSequence dualLabelContentDescription;
         public boolean disabledByPolicy;
         public boolean dualTarget = false;
@@ -151,6 +152,7 @@
                     || !Objects.equals(other.label, label)
                     || !Objects.equals(other.secondaryLabel, secondaryLabel)
                     || !Objects.equals(other.contentDescription, contentDescription)
+                    || !Objects.equals(other.stateDescription, stateDescription)
                     || !Objects.equals(other.dualLabelContentDescription,
                             dualLabelContentDescription)
                     || !Objects.equals(other.expandedAccessibilityClassName,
@@ -168,6 +170,7 @@
             other.label = label;
             other.secondaryLabel = secondaryLabel;
             other.contentDescription = contentDescription;
+            other.stateDescription = stateDescription;
             other.dualLabelContentDescription = dualLabelContentDescription;
             other.expandedAccessibilityClassName = expandedAccessibilityClassName;
             other.disabledByPolicy = disabledByPolicy;
@@ -195,6 +198,7 @@
             sb.append(",label=").append(label);
             sb.append(",secondaryLabel=").append(secondaryLabel);
             sb.append(",contentDescription=").append(contentDescription);
+            sb.append(",stateDescription=").append(stateDescription);
             sb.append(",dualLabelContentDescription=").append(dualLabelContentDescription);
             sb.append(",expandedAccessibilityClassName=").append(expandedAccessibilityClassName);
             sb.append(",disabledByPolicy=").append(disabledByPolicy);
diff --git a/packages/SystemUI/res-product/values-ky/strings.xml b/packages/SystemUI/res-product/values-ky/strings.xml
index 8d96cb2..043faee 100644
--- a/packages/SystemUI/res-product/values-ky/strings.xml
+++ b/packages/SystemUI/res-product/values-ky/strings.xml
@@ -26,18 +26,18 @@
     <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Планшетте SIM-карта жок."</string>
     <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Телефондо SIM-карта жок."</string>
     <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN-коддор дал келген жок"</string>
-    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Планшеттин кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул планшет баштапкы абалга келтирилип, андагы бардык маалымат жок кылынат."</string>
-    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Телефондун кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул телефон баштапкы абалга келтирилип, андагы бардык маалымат жок кылынат."</string>
-    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Планшеттин кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Бул планшет баштапкы абалга келтирилип, андагы бардык маалымат жок кылынат."</string>
-    <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Телефондун кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес аракет жасадыңыз. Бул телефон баштапкы абалга келтирилип, андагы бардык маалымат жок кылынат."</string>
-    <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Планшеттин кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул колдонуучу өчүрүлүп, колдонуучунун бардык маалыматы жок кылынат."</string>
-    <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Телефондун кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул колдонуучу өчүрүлүп, колдонуучунун бардык маалыматы жок кылынат."</string>
-    <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Планшеттин кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Бул колдонуучу өчүрүлүп, колдонуучунун бардык маалыматы жок кылынат."</string>
-    <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Телефондун кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Бул колдонуучу өчүрүлүп, колдонуучунун бардык маалыматы жок кылынат."</string>
-    <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Планшетиңиздин кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, жумуш профилиңиз өчүрүлүп, профилдеги бардык маалымат жок кылынат."</string>
-    <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Телефондун кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, жумуш профилиңиз өчүрүлүп, профилдеги бардык маалымат жок кылынат."</string>
-    <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Планшеттин кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Жумуш профили өчүрүлүп, андагы бардык маалымат жок кылынат."</string>
-    <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Телефондун кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Жумуш профили өчүрүлүп, андагы бардык маалымат жок кылынат."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Планшеттин кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул планшет баштапкы абалга келтирилип, андагы бардык маалымат өчүрүлөт."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Телефондун кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул телефон баштапкы абалга келтирилип, андагы бардык маалымат өчүрүлөт."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Планшеттин кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Бул планшет баштапкы абалга келтирилип, андагы бардык маалымат өчүрүлөт."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Телефондун кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес аракет жасадыңыз. Бул телефон баштапкы абалга келтирилип, андагы бардык маалымат өчүрүлөт."</string>
+    <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Планшеттин кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул колдонуучу өчүрүлүп, колдонуучунун бардык маалыматы өчүрүлөт."</string>
+    <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Телефондун кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул колдонуучу өчүрүлүп, колдонуучунун бардык маалыматы өчүрүлөт."</string>
+    <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Планшеттин кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Бул колдонуучу өчүрүлүп, колдонуучунун бардык маалыматы өчүрүлөт."</string>
+    <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Телефондун кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Бул колдонуучу өчүрүлүп, колдонуучунун бардык маалыматы өчүрүлөт."</string>
+    <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Планшетиңиздин кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, жумуш профилиңиз өчүрүлүп, профилдеги бардык маалымат өчүрүлөт."</string>
+    <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Телефондун кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, жумуш профилиңиз өчүрүлүп, профилдеги бардык маалымат өчүрүлөт."</string>
+    <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Планшеттин кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Жумуш профили өчүрүлүп, андагы бардык маалымат өчүрүлөт."</string>
+    <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Телефондун кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Жумуш профили өчүрүлүп, андагы бардык маалымат өчүрүлөт."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Графикалык ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тарттыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> ийгиликсиз аракеттен кийин планшетиңизди бөгөттөн электрондук почтаңыз аркылуу чыгаруу талап кылынат.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секунддан кийин кайра аракеттениңиз."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Графикалык ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тарттыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> ийгиликсиз аракеттен кийин телефонуңузду бөгөттөн электрондук почтаңыз аркылуу чыгаруу талап кылынат.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секунддан кийин кайра аракеттениңиз."</string>
 </resources>
diff --git a/packages/SystemUI/res/color/light_background.xml b/packages/SystemUI/res/color/light_background.xml
new file mode 100644
index 0000000..2effd99
--- /dev/null
+++ b/packages/SystemUI/res/color/light_background.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+  <item android:state_enabled="false"
+        android:color="@color/control_default_background" />
+  <item android:color="@color/GM2_yellow_50" />
+</selector>
diff --git a/packages/SystemUI/res/color/light_foreground.xml b/packages/SystemUI/res/color/light_foreground.xml
new file mode 100644
index 0000000..8143028
--- /dev/null
+++ b/packages/SystemUI/res/color/light_foreground.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+  <item android:state_enabled="false"
+        android:color="@color/control_default_foreground" />
+  <item android:color="@color/GM2_orange_900" />
+</selector>
diff --git a/packages/SystemUI/res/color/lock_background.xml b/packages/SystemUI/res/color/lock_background.xml
new file mode 100644
index 0000000..646fe5d
--- /dev/null
+++ b/packages/SystemUI/res/color/lock_background.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+  <item android:state_enabled="false"
+        android:color="@color/control_default_background" />
+  <item android:color="@color/GM2_blue_50" />
+</selector>
diff --git a/packages/SystemUI/res/color/lock_foreground.xml b/packages/SystemUI/res/color/lock_foreground.xml
new file mode 100644
index 0000000..3e05653
--- /dev/null
+++ b/packages/SystemUI/res/color/lock_foreground.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+  <item android:state_enabled="false"
+        android:color="@color/control_default_foreground" />
+  <item android:color="@color/GM2_blue_700" />
+</selector>
diff --git a/packages/SystemUI/res/color/unknown_foreground.xml b/packages/SystemUI/res/color/unknown_foreground.xml
new file mode 100644
index 0000000..bf028f1
--- /dev/null
+++ b/packages/SystemUI/res/color/unknown_foreground.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+   <item android:state_enabled="false"
+         android:color="@color/control_default_foreground" />
+   <item android:color="@color/GM2_blue_700" />
+ </selector>
diff --git a/packages/SystemUI/res/drawable/control_background.xml b/packages/SystemUI/res/drawable/control_background.xml
new file mode 100644
index 0000000..b246ea0
--- /dev/null
+++ b/packages/SystemUI/res/drawable/control_background.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* 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.
+*/
+-->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+  <item>
+    <shape>
+      <solid android:color="?android:attr/colorBackgroundFloating"/>
+      <corners android:radius="@dimen/control_corner_radius" />
+    </shape>
+  </item>
+  <item
+      android:id="@+id/clip_layer">
+    <clip
+        android:clipOrientation="horizontal"
+        android:drawable="@drawable/control_layer"/>
+  </item>
+</layer-list>
diff --git a/packages/SystemUI/res/drawable/control_layer.xml b/packages/SystemUI/res/drawable/control_layer.xml
new file mode 100644
index 0000000..fe8c4a4
--- /dev/null
+++ b/packages/SystemUI/res/drawable/control_layer.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* 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.
+*/
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+  <solid android:color="@android:color/transparent"/>
+  <corners android:radius="@dimen/control_corner_radius" />
+</shape>
diff --git a/packages/SystemUI/res/drawable/control_no_favorites_background.xml b/packages/SystemUI/res/drawable/control_no_favorites_background.xml
new file mode 100644
index 0000000..1e282ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable/control_no_favorites_background.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* 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.
+*/
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+  <stroke android:width="1dp" android:color="?android:attr/colorBackgroundFloating"/>
+  <corners android:radius="@dimen/control_corner_radius" />
+</shape>
diff --git a/packages/SystemUI/res/drawable/ic_bubble_overflow_button.xml b/packages/SystemUI/res/drawable/ic_bubble_overflow_button.xml
new file mode 100644
index 0000000..64b57c5
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_bubble_overflow_button.xml
@@ -0,0 +1,23 @@
+<!--
+Copyright (C) 2020 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:viewportHeight="24"
+    android:viewportWidth="24"
+    android:height="52dp"
+    android:width="52dp">
+    <path android:fillColor="#1A73E8"
+          android:pathData="M6,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM18,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"/>
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_device_thermostat_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_device_thermostat_gm2_24px.xml
new file mode 100644
index 0000000..45a658f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_thermostat_gm2_24px.xml
@@ -0,0 +1,9 @@
+<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="M18,9h-5v2h5m3,-6h-8v2h8m-9,11.97c0.62,-0.83 1,-1.85 1,-2.97 0,-1.63 -0.79,-3.09 -2,-4V6c0,-1.66 -1.34,-3 -3,-3S5,4.34 5,6v6c-1.21,0.91 -2,2.37 -2,4 0,1.12 0.38,2.14 1,2.97V19h0.02c0.91,1.21 2.35,2 3.98,2s3.06,-0.79 3.98,-2H12v-0.03zM6.2,13.6L7,13V6c0,-0.55 0.45,-1 1,-1s1,0.45 1,1v7l0.8,0.6c0.75,0.57 1.2,1.46 1.2,2.4H5c0,-0.94 0.45,-1.84 1.2,-2.4z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_light_off_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_light_off_gm2_24px.xml
new file mode 100644
index 0000000..78c3cc5
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_light_off_gm2_24px.xml
@@ -0,0 +1,19 @@
+<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="M9,21v-1h6v1c0,0.55 -0.45,1 -1,1h-4c-0.55,0 -1,-0.45 -1,-1z"/>
+  <group>
+    <clip-path android:pathData="M0,0h24v24H0z M 0,0"/>
+  </group>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M12,2c-1.89,0 -3.6,0.75 -4.86,1.97l1.41,1.41C9.45,4.53 10.67,4 12,4c2.76,0 5,2.24 5,5 0,1.28 -0.5,2.5 -1.36,3.42l-0.02,0.02 1.41,1.41C18.25,12.6 19,10.89 19,9c0,-3.86 -3.14,-7 -7,-7z"
+      android:fillType="evenOdd"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M2.92,2.29L1.65,3.57l3.59,3.59C5.09,7.75 5,8.36 5,9c0,2.38 1.19,4.47 3,5.74V17c0,0.55 0.45,1 1,1h6c0.3,0 0.57,-0.13 0.75,-0.34L20.09,22l1.27,-1.27L2.92,2.29zM10,16v-2.3l-0.85,-0.6C7.8,12.16 7,10.63 7,9v-0.08L14.09,16H10z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_lock_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_lock_gm2_24px.xml
new file mode 100644
index 0000000..f4299e6
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_lock_gm2_24px.xml
@@ -0,0 +1,9 @@
+<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="M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM9,6c0,-1.66 1.34,-3 3,-3s3,1.34 3,3v2L9,8L9,6zM18,20L6,20L6,10h12v10zM12,17c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_lock_open_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_lock_open_gm2_24px.xml
new file mode 100644
index 0000000..59fe0a9
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_lock_open_gm2_24px.xml
@@ -0,0 +1,12 @@
+<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="M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6h2c0,-1.66 1.34,-3 3,-3s3,1.34 3,3v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM18,20L6,20L6,10h12v10z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M12,15m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_more_vert.xml b/packages/SystemUI/res/drawable/ic_more_vert.xml
new file mode 100644
index 0000000..1309fa8
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_more_vert.xml
@@ -0,0 +1,24 @@
+<!--
+    Copyright (C) 2020 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<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,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_power_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_power_gm2_24px.xml
new file mode 100644
index 0000000..cd95719
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_power_gm2_24px.xml
@@ -0,0 +1,9 @@
+<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="M16,9v4.66l-3.5,3.51V19h-1v-1.83L8,13.65V9h8m0,-6h-2v4h-4V3H8v4h-0.01C6.9,6.99 6,7.89 6,8.98v5.52L9.5,18v3h5v-3l3.5,-3.51V9c0,-1.1 -0.9,-2 -2,-2V3z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_power_off_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_power_off_gm2_24px.xml
new file mode 100644
index 0000000..3eb7dd6
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_power_off_gm2_24px.xml
@@ -0,0 +1,9 @@
+<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="M21.19,21.19L2.81,2.81 1.39,4.22l4.63,4.63L6,14.5 9.5,18v3h5v-3l0.34,-0.34 4.94,4.94 1.41,-1.41zM12.5,17.17L12.5,19h-1v-1.83L8,13.65v-2.83l5.42,5.42 -0.92,0.93zM11.83,9L8,5.17L8,3h2v4h4L14,3h2v4c1.1,0 2,0.9 2,2v5.49l-0.34,0.34L16,13.17L16,9h-4.17z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_power_settings_new_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_power_settings_new_gm2_24px.xml
new file mode 100644
index 0000000..f4edd87
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_power_settings_new_gm2_24px.xml
@@ -0,0 +1,9 @@
+<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="M11,2h2v10h-2zM18.37,5.64l-1.41,1.41c2.73,2.73 2.72,7.16 -0.01,9.89 -2.73,2.73 -7.17,2.73 -9.89,0.01 -2.73,-2.73 -2.74,-7.18 -0.01,-9.91l-1.41,-1.4c-3.51,3.51 -3.51,9.21 0.01,12.73 3.51,3.51 9.21,3.51 12.72,-0.01 3.51,-3.51 3.51,-9.2 0,-12.72z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_switches_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_switches_gm2_24px.xml
new file mode 100644
index 0000000..bb535ce
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_switches_gm2_24px.xml
@@ -0,0 +1,9 @@
+<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="M19,9h-8.02C10.06,7.79 8.63,7 7,7c-2.76,0 -5,2.24 -5,5s2.24,5 5,5c1.63,0 3.06,-0.79 3.98,-2H19c1.66,0 3,-1.34 3,-3S20.66,9 19,9zM19,13h-7.1c0.07,-0.32 0.1,-0.66 0.1,-1s-0.04,-0.68 -0.1,-1H19c0.55,0 1,0.45 1,1S19.55,13 19,13z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_vacuum_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_vacuum_gm2_24px.xml
new file mode 100644
index 0000000..86b9591
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_vacuum_gm2_24px.xml
@@ -0,0 +1,9 @@
+<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="M4,16c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3zM4,20c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1 1,0.45 1,1 -0.45,1 -1,1zM23,20v2h-7v-2h2.49L12.01,4.59C11.6,3.63 10.66,3 9.61,3 8.17,3 7,4.17 7,5.61L7,9h2c2.21,0 4,1.79 4,4v9L7.99,22c0.44,-0.58 0.76,-1.26 0.91,-2L11,20v-7c0,-1.1 -0.9,-2 -2,-2L4,11v3c-0.71,0 -1.39,0.15 -2,0.42L2,9h3L5,5.61C5,3.07 7.07,1 9.61,1c1.86,0 3.53,1.11 4.25,2.82L20.66,20L23,20z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_videocam_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_videocam_gm2_24px.xml
new file mode 100644
index 0000000..687c9c4
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_videocam_gm2_24px.xml
@@ -0,0 +1,9 @@
+<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="M18,10.48L18,6c0,-1.1 -0.9,-2 -2,-2L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2v-4.48l4,3.98v-11l-4,3.98zM16,9.69L16,18L4,18L4,6h12v3.69z"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/bubble_overflow_activity.xml b/packages/SystemUI/res/layout/bubble_overflow_activity.xml
index 4cee746..95f205a 100644
--- a/packages/SystemUI/res/layout/bubble_overflow_activity.xml
+++ b/packages/SystemUI/res/layout/bubble_overflow_activity.xml
@@ -13,8 +13,9 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License
   -->
+
 <androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/bubble_overflow_recycler"
-    android:scrollbars="vertical"
-    android:layout_width="wrap_content"
-    android:layout_height="match_parent"/>
+    android:layout_gravity="center_horizontal"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"/>
diff --git a/packages/SystemUI/res/layout/bubble_overflow_button.xml b/packages/SystemUI/res/layout/bubble_overflow_button.xml
new file mode 100644
index 0000000..eb5dc9b
--- /dev/null
+++ b/packages/SystemUI/res/layout/bubble_overflow_button.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+       ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<ImageView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/bubble_overflow_button"
+    android:layout_width="@dimen/individual_bubble_size"
+    android:layout_height="@dimen/individual_bubble_size"
+    android:src="@drawable/ic_bubble_overflow_button"
+    android:scaleType="center"
+    android:layout_gravity="end"/>
diff --git a/packages/SystemUI/res/layout/controls_base_item.xml b/packages/SystemUI/res/layout/controls_base_item.xml
new file mode 100644
index 0000000..3c4c61e
--- /dev/null
+++ b/packages/SystemUI/res/layout/controls_base_item.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="0dp"
+    android:layout_weight="1"
+    android:layout_height="@dimen/control_height"
+    android:padding="@dimen/control_padding"
+    android:clickable="true"
+    android:focusable="true"
+    android:layout_marginLeft="3dp"
+    android:layout_marginRight="3dp"
+    android:background="@drawable/control_background">
+
+    <ImageView
+        android:id="@+id/icon"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <TextView
+        android:id="@+id/status"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="@dimen/control_status_normal"
+        android:textColor="?android:attr/textColorPrimary"
+        android:fontFamily="@*android:string/config_bodyFontFamily"
+        android:paddingLeft="3dp"
+        app:layout_constraintBottom_toBottomOf="@+id/icon"
+        app:layout_constraintStart_toEndOf="@+id/icon" />
+
+    <TextView
+        android:id="@+id/status_extra"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="@dimen/control_status_normal"
+        android:textColor="?android:attr/textColorPrimary"
+        android:fontFamily="@*android:string/config_bodyFontFamily"
+        android:paddingLeft="3dp"
+        app:layout_constraintBottom_toBottomOf="@+id/icon"
+        app:layout_constraintStart_toEndOf="@+id/status" />
+
+    <TextView
+        android:id="@+id/title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="18sp"
+        android:textColor="?android:attr/textColorPrimary"
+        android:fontFamily="@*android:string/config_headlineFontFamily"
+        app:layout_constraintBottom_toTopOf="@+id/subtitle"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/icon" />
+
+    <TextView
+        android:id="@+id/subtitle"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="16sp"
+        android:textColor="?android:attr/textColorSecondary"
+        android:fontFamily="@*android:string/config_headlineFontFamily"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent" />
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/packages/SystemUI/res/layout/controls_no_favorites.xml b/packages/SystemUI/res/layout/controls_no_favorites.xml
new file mode 100644
index 0000000..79672ca
--- /dev/null
+++ b/packages/SystemUI/res/layout/controls_no_favorites.xml
@@ -0,0 +1,18 @@
+<merge
+    xmlns:android="http://schemas.android.com/apk/res/android">
+  <TextView
+      android:id="@+id/controls_title"
+      android:text="@string/quick_controls_title"
+      android:layout_width="match_parent"
+      android:layout_height="wrap_content"
+      android:singleLine="true"
+      android:gravity="center"
+      android:textSize="25dp"
+      android:paddingTop="40dp"
+      android:paddingBottom="40dp"
+      android:layout_marginLeft="10dp"
+      android:layout_marginRight="10dp"
+      android:textColor="?android:attr/textColorPrimary"
+      android:fontFamily="@*android:string/config_headlineFontFamily"
+      android:background="@drawable/control_no_favorites_background"/>
+</merge>
diff --git a/packages/SystemUI/res/layout/controls_row.xml b/packages/SystemUI/res/layout/controls_row.xml
new file mode 100644
index 0000000..13a6b36
--- /dev/null
+++ b/packages/SystemUI/res/layout/controls_row.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    orientation="horizontal"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_marginBottom="@dimen/control_spacing" />
diff --git a/packages/SystemUI/res/layout/controls_with_favorites.xml b/packages/SystemUI/res/layout/controls_with_favorites.xml
new file mode 100644
index 0000000..7804fe6
--- /dev/null
+++ b/packages/SystemUI/res/layout/controls_with_favorites.xml
@@ -0,0 +1,35 @@
+<merge
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+
+  <androidx.constraintlayout.widget.ConstraintLayout
+      android:layout_width="match_parent"
+      android:layout_height="wrap_content">
+
+    <TextView
+        android:text="@string/quick_controls_title"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:singleLine="true"
+        android:gravity="center"
+        android:textSize="25dp"
+        android:textColor="?android:attr/textColorPrimary"
+        android:fontFamily="@*android:string/config_headlineFontFamily"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"/>
+    <ImageView
+        android:id="@+id/controls_more"
+        android:src="@drawable/ic_more_vert"
+        android:layout_width="34dp"
+        android:layout_height="24dp" 
+        android:layout_marginEnd="10dp"
+        app:layout_constraintEnd_toEndOf="parent"/>
+
+  </androidx.constraintlayout.widget.ConstraintLayout>
+
+  <LinearLayout
+      android:id="@+id/global_actions_controls_list"
+      android:layout_width="match_parent"
+      android:layout_height="wrap_content"
+      android:orientation="vertical" />
+</merge>
diff --git a/packages/SystemUI/res/layout/global_actions_grid_v2.xml b/packages/SystemUI/res/layout/global_actions_grid_v2.xml
index 4cfb47e..6741484 100644
--- a/packages/SystemUI/res/layout/global_actions_grid_v2.xml
+++ b/packages/SystemUI/res/layout/global_actions_grid_v2.xml
@@ -111,20 +111,7 @@
         app:layout_constraintLeft_toLeftOf="parent"
         app:layout_constraintRight_toRightOf="parent"
         app:layout_constraintTop_toBottomOf="@id/global_actions_panel">
-      <TextView
-          android:text="Home"
-          android:layout_width="match_parent"
-          android:layout_height="wrap_content"
-          android:singleLine="true"
-          android:gravity="center"
-          android:textSize="25dp"
-          android:textColor="?android:attr/textColorPrimary"
-          android:fontFamily="@*android:string/config_headlineFontFamily" />
-    <LinearLayout
-        android:id="@+id/global_actions_controls_list"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="vertical" />
+
     </LinearLayout>
   </androidx.constraintlayout.widget.ConstraintLayout>
 </ScrollView>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 4de8543..823685e 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoem om skerm te vul"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Strek om skerm te vul"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Skermkiekie"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Prent is ingevoeg"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Stoor tans skermkiekie..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Stoor tans skermkiekie..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Skermkiekie is gestoor"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Begin opname"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Neem stemopname op"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Wys tikke"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Tik om te stop"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Stop"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Laat wag"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Hervat"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Batterybespaarder"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Aan met sonsondergang"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Tot sonsopkoms"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Aan om <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Tot <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is gedeaktiveer"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is geaktiveer"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Skermopname"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Begin"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Stop"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Pasmaak"</string>
     <string name="notification_done" msgid="6215117625922713976">"Klaar"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Ontdoen"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Merk hierdie kennisgewing as \"nie \'n gesprek nie\""</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Gunsteling"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Ontmerk as gunsteling"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Demp"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Ontdemp"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Wys as borrel"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Skakel borrels af"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Voeg by tuisskerm"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"kennisgewingkontroles"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"kennisgewing-sluimeropsies"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 87603ac..c324824 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"ማያ እንዲሞላ አጉላ"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"ማያ ለመሙለት ሳብ"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ቅጽበታዊ ገጽ እይታ"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"ምስል ገብቷል"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"ቅጽበታዊ ገጽ እይታ በማስቀመጥ ላይ..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ቅጽበታዊ ገጽ እይታ በማስቀመጥ ላይ..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ቅጽበታዊ ገጽ እይታ ተቀምጧል"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"መቅረጽ ጀምር"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"ድምጽን ቅረጽ"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"መታ ማድረጎችን አሳይ"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"ለማቆም መታ ያድርጉ"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"አቁም"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"ባለበት አቁም"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"ከቆመበት ቀጥል"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ባትሪ ቆጣቢ"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"ጸሐይ ስትጠልቅ ይበራል"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ጸሐይ እስክትወጣ ድረስ"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> ላይ ይበራል"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"እስከ <xliff:g id="TIME">%s</xliff:g> ድረስ"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"ኤንኤፍሲ"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"ኤንኤፍሲ ተሰናክሏል"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"ኤንኤፍሲ ነቅቷል"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index c764004..113d705 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"تكبير/تصغير لملء الشاشة"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"توسيع بملء الشاشة"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"لقطة شاشة"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"تم إدراج الصورة"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"جارٍ حفظ لقطة الشاشة..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"جارٍ حفظ لقطة الشاشة..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"تم حفظ لقطة الشاشة."</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"بدء التسجيل"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"تسجيل التعليق الصوتي"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"عرض النقرات"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"انقر لإيقاف التسجيل"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"إيقاف"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"إيقاف مؤقت"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"استئناف"</string>
@@ -396,15 +398,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"توفير شحن البطارية"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"تفعيل عند غروب الشمس"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"حتى شروق الشمس"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"تفعيل الوضع في <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"حتى <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"‏الاتصالات قصيرة المدى (NFC)"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"تم إيقاف الاتصال القريب المدى"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"تم تفعيل الاتصال القريب المدى"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"تسجيل الشاشة"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"بدء"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"إيقاف"</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>
@@ -708,22 +709,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"تخصيص"</string>
     <string name="notification_done" msgid="6215117625922713976">"تم"</string>
     <string name="inline_undo" msgid="9026953267645116526">"تراجع"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"تحويل الإشعار من محادثة إلى إشعار عادي"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"المفضّلة"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"إزالة المحادثة من المفضّلة"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"كتم الصوت"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"إعادة الصوت"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"إظهار الإشعار كفقاعة تفسيرية"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"إيقاف الفقاعات التفسيرية"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"إضافة إلى الشاشة الرئيسية"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"عناصر التحكم في الإشعارات"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"خيارات تأجيل الإشعارات"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 2fc393c..975d639 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"স্ক্ৰীণ পূর্ণ কৰিবলৈ জুম কৰক"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"স্ক্ৰীণ পূর্ণ কৰিবলৈ প্ৰসাৰিত কৰক"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"স্ক্ৰীনশ্বট"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"প্ৰতিচ্ছবি ভৰোৱা হ’ল"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"স্ক্ৰীণশ্বট ছেভ কৰি থকা হৈছে…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"স্ক্ৰীণশ্বট ছেভ কৰি থকা হৈছে…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"স্ক্ৰীণশ্বট ছেভ কৰা হ’ল"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"ৰেকৰ্ডিং কৰা আৰম্ভ কৰক"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"পাৰ্শ্ব-ধ্বনি ৰেকৰ্ড কৰক"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"টিপা ঠাইসমূহ দেখুৱাওক"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"বন্ধ কৰিবলৈ টিপক"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"বন্ধ কৰক"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"প\'জ কৰক"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"ৰখোৱাৰ পৰা পুনৰ আৰম্ভ কৰক"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"বেটাৰী সঞ্চয়কাৰী"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"সূৰ্যাস্তত অন হয়"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"সূৰ্যোদয়লৈকে"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>ত অন কৰক"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> পৰ্যন্ত"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC নিষ্ক্ৰিয় হৈ আছে"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC সক্ষম হৈ আছে"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"স্ক্ৰীন ৰেকর্ড"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"আৰম্ভ কৰক"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"বন্ধ কৰক"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"নিজৰ উপযোগিতা অনুসৰি"</string>
     <string name="notification_done" msgid="6215117625922713976">"সম্পন্ন হ’ল"</string>
     <string name="inline_undo" msgid="9026953267645116526">"আনডু কৰক"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"এই জাননীখন এটা বার্তালাপ নহয় বুলি চিহ্নিত কৰক"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"অপ্ৰিয় হিচাপে চিহ্নিত কৰক"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"অপ্ৰিয় হিচাপে চিহ্নিত কৰক"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"মিউট কৰক"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"আনমিউট কৰক"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"বাবল হিচাপে দেখুৱাওক"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"বাবলসমূহ অফ কৰক"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"গৃহ স্ক্ৰীনত যোগ কৰক"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"জাননীৰ নিয়ন্ত্ৰণসমূহ"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"জাননীক স্নুজ কৰাৰ বিকল্পসমূহ"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index de9c605..d98d939 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Ekranı doldurmaq üçün yaxınlaşdır"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Ekranı doldurmaq üçün uzat"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Ekran şəkli"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Şəkil daxil edildi"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Skrinşot yadda saxlanılır..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Skrinşot yadda saxlanır..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Skrinşot yadda saxlandı"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Ekranın Video Çəkimini Başladın"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Ekranın səsli video çəkimi"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Klikləmələri göstərin"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Dayandırmaq üçün toxunun"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Dayandırın"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Dayandırın"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Davam edin"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Enerjiyə qənaət"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Qürubda aktiv olacaq"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Şəfəq vaxtına qədər"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Bu vaxt aktiv olur: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Bu vaxtadək: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC deaktiv edilib"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC aktiv edilib"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Ekran yazması"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Başlayın"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Dayandırın"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Fərdiləşdirin"</string>
     <string name="notification_done" msgid="6215117625922713976">"Hazırdır"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Ləğv edin"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Bu bildirişi \"söhbət deyil\" kimi qeyd edin."</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Sevimli"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Sevimlilərdən silin"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Səssiz"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Susdurmayın"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Qabarcıq kimi göstərin"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Qabarcıqları deaktiv edin"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Əsas ekrana əlavə edin"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"bildiriş nəzarəti"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"bildiriş təxirə salma seçimləri"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index a895f35..ff03bb9 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zumiraj na celom ekranu"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Razvuci na ceo ekran"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Snimak ekrana"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Slika je umetnuta"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Čuvanje snimka ekrana..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Čuvanje snimka ekrana..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Snimak ekrana je sačuvan"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Započni snimanje"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Snimi prenos glasa"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Prikazuj dodire"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Dodirnite da biste zaustavili"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Zaustavi"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pauziraj"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Nastavi"</string>
@@ -390,6 +392,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Ušteda baterije"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Uključuje se po zalasku sunca"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do izlaska sunca"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Uključuje se u <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC je onemogućen"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC je omogućen"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 67aa899..1ebbb5e 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Павял. на ўвесь экран"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Расцягн. на ўвесь экран"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Здымак экрана"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Відарыс устаўлены"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Захаванне скрыншота..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Захаванне скрыншота..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Здымак экрана захаваны"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Пачаць запіс"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Закадравае агучванне запісу"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Паказваць дотыкі"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Націсніце, каб спыніць"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Спыніць"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Прыпыніць"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Узнавіць"</string>
@@ -394,15 +396,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Эканомія зараду"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Уключана ўвечары"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Да ўсходу сонца"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Уключана ў <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Да <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC адключаны"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC уключаны"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Запіс экрана"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Пачаць"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Спыніць"</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>
@@ -704,22 +705,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Наладзіць"</string>
     <string name="notification_done" msgid="6215117625922713976">"Гатова"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Адрабіць"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Не пазначаць гэта апавяшчэнне як размову"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"У абранае"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Выдаліць з абранага"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Ігнараваць"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Уключыць паказ"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Паказваць як усплывальнае апавяшчэнне"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Выключыць усплывальныя апавяшчэнні"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Дадаць на галоўны экран"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"кіраванне апавяшчэннямі"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"параметры адкладвання апавяшчэнняў"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index f83bf96..5cfea60 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Мащаб – запълва екрана"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Разпъване – запълва екрана"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Екранна снимка"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Изображението бе вмъкнато"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Екранната снимка се запазва..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Екранната снимка се запазва..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Екранната снимка е запазена"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Стартиране на записа"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Записване на озвучаване"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Показване на докосванията"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Докоснете за спиране"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Спиране"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Поставяне на пауза"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Възобновяване"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Запазв. на батерията"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Ще се вкл. по залез"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"До изгрев"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Ще се включи в <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"До <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"КБП"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"КБП е деактивирана"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"КБП е активирана"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 10479b1..f1e49ce 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"স্ক্রীণ পূরণ করতে জুম করুন"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"ফুল স্ক্রিন করুন"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"স্ক্রিনশট"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"ছবি যোগ করা হয়েছে"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"স্ক্রিনশট সেভ করা হচ্ছে..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"স্ক্রিনশট সেভ করা হচ্ছে..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"স্ক্রিনশট সেভ করা হয়েছে"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"রেকর্ডিং শুরু করুন"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"ভয়েসওভার রেকর্ড করুন"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"ট্যাপগুলি দেখুন"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"বন্ধ করতে ট্যাপ করুন"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"বন্ধ করুন"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"পজ করুন"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"আবার চালু করুন"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ব্যাটারি সেভার"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"সূর্যাস্তে চালু হবে"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"সূর্যোদয় পর্যন্ত"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>-এ চালু হবে"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> পর্যন্ত"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC অক্ষম করা আছে"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC সক্ষম করা আছে"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"স্ক্রিন রেকর্ড"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"শুরু করুন"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"বন্ধ করুন"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"কাস্টমাইজ করুন"</string>
     <string name="notification_done" msgid="6215117625922713976">"সম্পন্ন"</string>
     <string name="inline_undo" msgid="9026953267645116526">"আগের অবস্থায় ফিরে যান"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"কথোপকথন হিসেবে এই বিজ্ঞপ্তি চিহ্নিত করবেন না"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"পছন্দসই"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"পছন্দসই থেকে সরান"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"মিউট করুন"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"আনমিউট করুন"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"পপ-আপ হিসেবে দেখুন"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"পপ-আপ বন্ধ করুন"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"হোম স্ক্রিনে যোগ করুন"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"বিজ্ঞপ্তির নিয়ন্ত্রণগুলি"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"বিজ্ঞপ্তি মনে করিয়ে দেওয়ার বিকল্পগুলি"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 6c89d97..cabe87f 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Uvećaj prikaz na ekran"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Razvuci prikaz na ekran"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Snimak ekrana"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Slika je umetnuta"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Spašavanje snimka ekrana..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Spašavanje snimka ekrana..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Snimak ekrana je sačuvan"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Započni snimanje"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Govor snimka"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Prikaži dodire"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Dodirnite za zaustavljanje"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Zaustavi"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pauza"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Nastavi"</string>
@@ -390,6 +392,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Ušteda baterije"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Uključuje se u sumrak"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do svitanja"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Uključuje se u <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC je onemogućen"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC je omogućen"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index f675e20..3e25795 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom per omplir pantalla"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Estira per omplir pant."</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Captura de pantalla"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Imatge inserida"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"S\'està desant captura de pantalla..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"S\'està desant la captura de pantalla..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"S\'ha desat la captura de pantalla"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Inicia la gravació"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Grava la veu en off"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Mostra els tocs"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Toca per aturar"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Atura"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Posa en pausa"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Reprèn"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Estalvi de bateria"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Al vespre"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Fins a l\'alba"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"S\'activarà a les <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Fins a les <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"L\'NFC està desactivada"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"L\'NFC està activada"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 354ccf4..3c85880 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Přiblížit na celou obrazovku"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Na celou obrazovku"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Snímek obrazovky"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Vložen obrázek"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Ukládání snímku obrazovky..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Ukládání snímku obrazovky..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Snímek obrazovky byl uložen"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Spustit nahrávání"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Nahrávat komentář"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Zobrazovat klepnutí"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Klepnutím zastavíte"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Zastavit"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pozastavit"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Obnovit"</string>
@@ -392,6 +394,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Spořič baterie"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Při soumraku"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do svítání"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Zapnout v <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC je vypnuto"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC je zapnuto"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 04e83d4..f2ffdaa 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom til fuld skærm"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Stræk til fuld skærm"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Billedet blev indsat"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Gemmer screenshot..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Gemmer screenshot..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshottet blev gemt"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Start optagelse"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Optag voiceover"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Vis tryk"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Tryk for at stoppe"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Stop"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Sæt på pause"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Genoptag"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Batterisparefunktion"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Til ved solnedgang"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Indtil solopgang"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Tænd kl. <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Indtil kl. <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC er deaktiveret"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC er aktiveret"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index baf3e7c..58caef2 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom auf Bildschirmgröße"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Auf Bildschirmgröße anpassen"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Bild eingefügt"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Screenshot wird gespeichert..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Screenshot wird gespeichert..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot gespeichert"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Aufzeichnung starten"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Voice-over aufnehmen"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Fingertipps anzeigen"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Zum Stoppen tippen"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Anhalten"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pausieren"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Fortsetzen"</string>
@@ -392,15 +394,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Energiesparmodus"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"An bei Sonnenuntergang"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Bis Sonnenaufgang"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"An um <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Bis <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ist deaktiviert"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ist aktiviert"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Bildschirmaufnahme"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Starten"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Beenden"</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>
@@ -700,22 +701,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Anpassen"</string>
     <string name="notification_done" msgid="6215117625922713976">"Fertig"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Rückgängig machen"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Diese Benachrichtigung als keine Unterhaltung markieren"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Favorit"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Aus Favoriten entfernen"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Stummschalten"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Stummschaltung aufheben"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Als Infofeld anzeigen"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Infofelder deaktivieren"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Zum Startbildschirm hinzufügen"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> – <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"Benachrichtigungseinstellungen"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"Optionen für spätere Erinnerung bei Benachrichtigungen"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 45ad302..d3686c8 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Ζουμ σε πλήρη οθόνη"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Προβoλή σε πλήρη οθ."</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Στιγμιότυπο οθόνης"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Έγινε εισαγωγή εικόνας"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Αποθήκ. στιγμιότυπου οθόνης..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Αποθήκευση στιγμιότυπου οθόνης..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Το στιγμιότυπο οθόνης αποθηκεύτηκε"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Έναρξη εγγραφής"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Εγγραφή σπικάζ"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Εμφάνιση πατημάτων"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Πατήστε για διακοπή"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Διακοπή"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Παύση"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Συνέχιση"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Εξοικονόμ. μπαταρίας"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Κατά τη δύση"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Μέχρι την ανατολή"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Ενεργοποίηση στις <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Έως <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Το NFC είναι απενεργοποιημένο"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Το NFC είναι ενεργοποιημένο"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index b6a5d15..4f61daa 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom to fill screen"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Stretch to fill screen"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Image inserted"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Saving screenshot…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Saving screenshot…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Start Recording"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Record voiceover"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Show taps"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Tap to stop"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Stop"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pause"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Resume"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Battery Saver"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"On at sunset"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Until sunrise"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is disabled"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is enabled"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index e194e69..34a2f19 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom to fill screen"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Stretch to fill screen"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Image inserted"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Saving screenshot…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Saving screenshot…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Start Recording"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Record voiceover"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Show taps"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Tap to stop"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Stop"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pause"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Resume"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Battery Saver"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"On at sunset"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Until sunrise"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is disabled"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is enabled"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index b6a5d15..4f61daa 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom to fill screen"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Stretch to fill screen"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Image inserted"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Saving screenshot…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Saving screenshot…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Start Recording"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Record voiceover"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Show taps"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Tap to stop"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Stop"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pause"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Resume"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Battery Saver"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"On at sunset"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Until sunrise"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is disabled"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is enabled"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index b6a5d15..4f61daa 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom to fill screen"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Stretch to fill screen"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Image inserted"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Saving screenshot…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Saving screenshot…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Start Recording"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Record voiceover"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Show taps"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Tap to stop"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Stop"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pause"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Resume"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Battery Saver"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"On at sunset"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Until sunrise"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is disabled"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is enabled"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index e3a569a..2bb5131 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‏‎‎‎‏‎‏‎‏‎‎‏‎‏‎‎‎‎‎‏‏‎‏‎‎‏‏‏‎‏‏‎‏‎‏‏‎‎‏‏‎‎‎‏‏‏‎‏‏‏‎‏‎‎‎Zoom to fill screen‎‏‎‎‏‎"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‏‏‎‏‏‎‎‏‎‏‎‎‎‏‏‏‎‎‎‎‎‎‎‎‏‎‎‏‎‏‏‎‏‏‏‏‏‎‎‎‏‏‎‏‏‏‎‎‏‎‎‏‎Stretch to fill screen‎‏‎‎‏‎"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‎‎‏‏‏‎‎‏‏‏‎‎‎‎‏‎‏‏‏‎‏‎‎‏‏‎‎‏‏‎‎‏‏‎‏‎‎‏‏‏‎‏‎‎‎‏‏‎‎‎‎‏‏‎‎Screenshot‎‏‎‎‏‎"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‎‎‎‏‎‏‎‏‎‎‏‏‎‎‏‏‎‏‎‏‏‏‏‎‏‏‏‎‎‏‎‏‏‏‏‎‎‎‏‏‏‏‎‏‎‏‎‏‎‎‏‏‎‏‎Image inserted‎‏‎‎‏‎"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‏‏‏‎‎‎‏‏‎‎‏‏‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‎‎‎‎‏‏‏‎‎‎‎‏‏‎‏‎‎‎‏‎‏‎‎‎Saving screenshot…‎‏‎‎‏‎"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‎‎‎‎‏‏‏‏‎‎‏‏‏‏‎‎‎‎‏‏‎‏‎‏‏‎‏‎‎‎‎‏‏‎‎‎‏‎‏‎‎‏‎‏‎Saving screenshot…‎‏‎‎‏‎"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‎‎‏‏‏‎‏‏‏‏‎‎‏‏‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‎‏‏‎‏‎‏‏‏‎‎‏‎‎‎‏‎Screenshot saved‎‏‎‎‏‎"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‎‏‎‏‏‎‏‏‏‏‎‎‏‏‎‎‎‎‏‏‏‏‎‏‏‎‏‏‏‎‏‎‏‏‏‏‎‏‎‏‏‎‎‎‏‏‏‎‎‎‎‎‎‎‏‎‎Start Recording‎‏‎‎‏‎"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‎‎‎‎‏‎‎‎‎‏‏‎‎‏‎‏‎‎‏‏‏‎‏‏‏‎‎‎‎‎‏‏‎‎‏‎‎‎‏‏‏‏‏‎‎‏‎‎‏‎‎‎‎‎Record voiceover‎‏‎‎‏‎"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‎‎‏‏‎‎‏‏‏‎‎‏‎‏‏‎‏‎‏‎‏‎‎‎‏‎‏‎‏‏‎‏‏‏‏‎‏‏‏‏‏‎‏‎‏‎‎‎Show taps‎‏‎‎‏‎"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‎‎‏‏‏‎‏‏‏‏‏‏‎‏‎‏‏‏‎‏‎‎‎‎‏‏‎‏‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‎‎Tap to stop‎‏‎‎‏‎"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‎‎‎‏‎‏‏‏‏‏‎‎‎‏‎‏‎‎‎‏‎‏‏‎‏‎‏‎Stop‎‏‎‎‏‎"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‎‏‎‎‏‎‏‎‏‏‎‎‎‎‎‎‏‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‎‏‎‎‎‎‏‎‏‏‎‏‏‏‏‏‎‎‎‎‏‎Pause‎‏‎‎‏‎"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‎‎‎‎‎‏‏‏‎‎‎‏‎‏‎‎‎‎‎‏‏‏‎‏‎‏‎‎‏‏‎‎‎‎‎‏‏‎‎‎‎‎‎‎‎‎‏‏‏‎‏‏‏‎Resume‎‏‎‎‏‎"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‎‎‎‏‎‏‎‎‏‎‎‏‎‏‏‎‎‏‎‏‎‎‏‎‎‎‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‏‎Battery Saver‎‏‎‎‏‎"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‎‎‏‏‎‏‎‎‎‎‏‎‎‏‏‎‏‏‎‏‏‏‏‎‎On at sunset‎‏‎‎‏‎"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‎‏‎‎‎‎‏‎‏‎‎‏‎‏‏‏‎‏‎‎‎‏‎‎‎‏‎‎‏‎‎‏‎‏‎‎‏‏‎‎‏‎‎‎‎‎‏‏‎‏‏‏‎‎‎‎Until sunrise‎‏‎‎‏‎"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‎‏‎‏‏‎‏‎‎‎‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‏‏‎‎‎‎‎‏‏‏‎‏‎‏‏‏‏‏‏‎On at ‎‏‎‎‏‏‎<xliff:g id="TIME">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‏‎‏‎‎‏‏‏‏‎‎‏‏‏‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‎‎‏‏‎‏‏‎‏‏‎‎‏‎‏‎‏‎Until ‎‏‎‎‏‏‎<xliff:g id="TIME">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‎‎‎‏‏‎‏‏‎‎‎‎‎‎‎‏‏‎‏‎‏‎‏‎‎‎‏‎‎‏‎‏‏‏‏‎‏‏‎‏‎‎‎‏‏‏‎‏‎‏‎‏‎NFC‎‏‎‎‏‎"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‎‏‎‏‏‎‎‎‏‎‎‏‏‏‎‎‏‏‎‎‎‏‏‏‏‎‎‎‏‎‏‎‎‎‎‏‎‏‎‎‎‎‎‏‎‏‏‎‎‏‎‏‏‏‎NFC is disabled‎‏‎‎‏‎"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‏‏‏‏‎‎‏‎‎‏‏‎‎‏‎‎‏‏‏‎‎‏‏‏‎‎‏‏‏‏‏‎‎‏‎‏‎‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‎‏‏‎‎NFC is enabled‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 255db92..e2bf6ef 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom para ocupar la pantalla"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Estirar p/ ocupar la pantalla"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Captura de pantalla"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Se insertó la imagen"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Guardando captura de pantalla"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Guardando la captura de pantalla..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Se guardó la captura de pantalla"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Iniciar grabación"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Grabar voz superpuesta"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Mostrar toques"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Presiona para detener"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Detener"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pausar"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Reanudar"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Ahorro de batería"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Al atardecer"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Hasta el amanecer"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"A la(s) <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Hasta la(s) <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"La tecnología NFC está inhabilitada"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"La tecnología NFC está habilitada"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index d1d959c..40d7fe3 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom para ajustar"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Expandir para ajustar"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Captura de pantalla"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Se ha insertado la imagen"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Guardando captura..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Guardando captura..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Se ha guardado la captura de pantalla"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Iniciar grabación"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Grabar voz en off"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Mostrar toques"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Toca para detener"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Detener"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pausar"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Seguir"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Ahorro de batería"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Al anochecer"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Hasta el amanecer"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"A las <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Hasta las <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"El NFC está desactivado"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"El NFC está activado"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 6f69a17..d8f546c 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Suumi ekraani täitmiseks"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Venita ekraani täitmiseks"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Ekraanipilt"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Pilt on sisestatud"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Kuvatõmmise salvestamine ..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Kuvatõmmise salvestamine ..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Ekraanipilt salvestati"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Alusta salvestamist"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Salvesta hääl"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Kuva puudutused"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Puudutage peatamiseks"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Peata"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Peata"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Jätka"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Akusäästja"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Sisse päikeselooj."</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Kuni päikesetõusuni"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Sisse kell <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Kuni <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC on keelatud"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC on lubatud"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Ekraanikirje"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Alustage"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Peatage"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Kohandamine"</string>
     <string name="notification_done" msgid="6215117625922713976">"Valmis"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Võta tagasi"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Eemalda see meeldetuletus vestlustest"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Lisa lemmikutesse"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Tühista lemmikutesse lisamine"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Vaigista"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Tühista vaigistus"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Kuva mullina"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Lülita mullid välja"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Lisa avakuvale"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"märguannete juhtnupud"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"märguannete edasilükkamise valikud"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 1b89c5a..9dceb5f 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Handiagotu pantaila betetzeko"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Luzatu pantaila betetzeko"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Pantaila-argazkia"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Irudi bat txertatu da"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Pantaila-argazkia gordetzen…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Pantaila-argazkia gordetzen…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Gorde da pantaila-argazkia"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Hasi grabatzen"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Grabatu off ahotsa"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Erakutsi sakatzeak"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Sakatu gelditzeko"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Gelditu"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pausatu"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Berrekin"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Bateria-aurrezlea"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Ilunabarrean aktibatuko da"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Egunsentira arte"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Aktibatze-ordua: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Desaktibatze-ordua: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Desgaituta dago NFC"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Gaituta dago NFC"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Pantaila-grabaketa"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Hasi"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Gelditu"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Pertsonalizatu"</string>
     <string name="notification_done" msgid="6215117625922713976">"Eginda"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Desegin"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Markatu jakinarazpen hau ez dela elkarrizketa bat"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Markatu gogoko gisa"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Kendu gogokoetatik"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Ezkutatu"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Erakutsi"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Markatu burbuila gisa"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Desaktibatu burbuilak"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Gehitu hasierako pantailan"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"jakinarazpena kontrolatzeko aukerak"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"jakinarazpena atzeratzeko aukerak"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 2b76557..d27b420 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"بزرگ‌نمایی برای پر کردن صفحه"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"گسترده کردن برای پر کردن صفحه"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"عکس صفحه‌نمایش"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"تصویر درج شد"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"در حال ذخیره عکس صفحه‌نمایش..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"درحال ذخیره عکس صفحه‌نمایش…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"عکس صفحه‌نمایش ذخیره شد"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"شروع ضبط"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"ضبط صدا روی تصویر"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"نمایش ضربه‌ها"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"ضربه برای توقف"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"توقف"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"مکث"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"ازسرگیری"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"بهینه‌سازی باتری"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"غروب روشن می‌شود"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"تا طلوع آفتاب"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"ساعت <xliff:g id="TIME">%s</xliff:g> روشن می‌شود"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"تا<xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"‏NFC غیرفعال است"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"‏NFC فعال است"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ضبط کردن صفحه‌نمایش"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"شروع"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"توقف"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"سفارشی کردن"</string>
     <string name="notification_done" msgid="6215117625922713976">"تمام"</string>
     <string name="inline_undo" msgid="9026953267645116526">"واگرد"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"علامت‌گذاری این اعلان به‌عنوان غیرمکالمه"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"مورد دلخواه"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"حذف از موارد دلخواه"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"صامت کردن"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"باصدا کردن"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"نمایش به‌شکل ابزارک اعلان"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"خاموش کردن ابزارک‌های اعلان"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"افزودن به صفحه اصلی"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"کنترل‌های اعلان"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"گزینه‌های تعویق اعلان"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 9b76f39..cf01efd 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoomaa koko näyttöön"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Venytä koko näyttöön"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Kuvakaappaus"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Kuva lisätty"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Tallennetaan kuvakaappausta..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Tallennetaan kuvakaappausta..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Kuvakaappaus tallennettu"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Aloita tallennus"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Äänitä taustaselostus"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Näytä napautukset"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Lopeta napauttamalla"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Lopeta"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Keskeytä"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Jatka"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Virransäästö"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Auringon laskiessa"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Auringonnousuun"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Päälle klo <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> asti"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC on poistettu käytöstä"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC on käytössä"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Näytön tallentaminen"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Aloita"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Lopeta"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Muokkaa"</string>
     <string name="notification_done" msgid="6215117625922713976">"Valmis"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Kumoa"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Merkitse, että tämä ilmoitus ei ole keskustelu"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Suosikki"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Poista suosikeista"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Ohita"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Poista ohitus"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Näytä ohjekuplana"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Laita ohjekuplat pois päältä"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Lisää aloitusnäytölle"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"Ilmoitusten hallinta"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"Ilmoitusten torkkuasetukset"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 55eb39e..5f7a358 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoomer pour remplir l\'écran"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Étirer pour remplir l\'écran"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Capture d\'écran"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Image insérée"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Enregistrement capture écran…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Enregistrement capture écran…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Capture d\'écran enregistrée"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Commencer l\'enregistrement"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Enregistrer la voix hors champ"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Afficher les éléments sélectionnés"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Toucher pour arrêter"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Arrêter"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pause"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Reprendre"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Économiseur de pile"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Activé la nuit"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Jusqu\'à l\'aube"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Actif à <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Jusqu\'à <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC désactivée"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC activée"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 5b12612..3c12f66 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoomer pour remplir l\'écran"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Étirer pour remplir l\'écran"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Capture d\'écran"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Image insérée"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Enregistrement capture écran…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Enregistrement de la capture d\'écran…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Capture d\'écran enregistrée"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Démarrer l\'enregistrement"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Enregistrer une voix off"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Afficher les éléments sélectionnés"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Appuyez ici pour arrêter"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Arrêter"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pause"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Reprendre"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Économiseur batterie"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Activé la nuit"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Jusqu\'à l\'aube"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"À partir de <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Jusqu\'à <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC désactivée"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"La technologie NFC est activée"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 74ee202..0c444e4 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Ampliar ata ocupar todo"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Estirar ata ocupar todo"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Crear captura"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Engadiuse a imaxe"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Gardando captura de pantalla…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Gardando captura de pantalla…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Gardouse a captura de pantalla"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Iniciar gravación"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Gravar voz en off"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Mostrar toques"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Toca para deter a gravación"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Deter"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pór en pausa"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Retomar"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Aforro de batería"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Activación ao solpor"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Ata o amencer"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Activarase ás: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Utilizarase ata as: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"A opción NFC está desactivada"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"A opción NFC está activada"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 4b5dd25..9dde523 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"સ્ક્રીન ભરવા માટે ઝૂમ કરો"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"સ્ક્રીન ભરવા માટે ખેંચો"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"સ્ક્રીનશૉટ"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"છબી શામેલ કરી"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"સ્ક્રીનશોટ સાચવી રહ્યું છે…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"સ્ક્રીનશોટ સાચવી રહ્યું છે…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"સ્ક્રીનશૉટ સાચવ્યો"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"રેકોર્ડિંગ શરૂ કરો"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"વૉઇસઓવર રેકોર્ડ કરો"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"ટૅપ કર્યાની સંખ્યા બતાવો"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"રોકવા માટે ટૅપ કરો"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"રોકો"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"થોભાવો"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"ફરી શરૂ કરો"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"બૅટરી સેવર"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"સૂર્યાસ્ત વખતે"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"સૂર્યોદય સુધી"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> વાગ્યે ચાલુ"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> વાગ્યા સુધી"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC અક્ષમ કરેલ છે"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC સક્ષમ કરેલ છે"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"સ્ક્રીન રેકૉર્ડ કરો"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"શરૂ કરો"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"રોકો"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"કસ્ટમાઇઝ કરો"</string>
     <string name="notification_done" msgid="6215117625922713976">"થઈ ગયું"</string>
     <string name="inline_undo" msgid="9026953267645116526">"રદ કરો"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"આ નોટિફિકેશન વાતચીત ન હોવા તરીકે માર્ક કરો"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"મનપસંદ"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"મનપસંદમાંથી કાઢી નાખો"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"મ્યૂટ કરો"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"અનમ્યૂટ કરો"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"બબલ તરીકે બતાવો"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"બબલ બંધ કરો"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"હોમ સ્ક્રીન પર ઉમેરો"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"સૂચના નિયંત્રણો"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"સૂચના સ્નૂઝ કરવાના વિકલ્પો"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index c22d234..5522605 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"स्‍क्रीन भरने के लिए ज़ूम करें"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"स्‍क्रीन भरने के लिए खींचें"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"स्क्रीनशॉट"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"इमेज डाली गई"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"स्क्रीनशॉट सहेजा जा रहा है..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"स्क्रीनशॉट सहेजा जा रहा है..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"स्क्रीनशॉट सेव किया गया"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"रिकॉर्डिंग शुरू करें"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"वॉइसओवर रिकॉर्ड करें"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"टैप दिखाएं"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"रोकने के लिए टैप करें"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"रोकें"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"रोकें"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"फिर से शुरू करें"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"बैटरी सेवर"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"शाम को चालू होगा"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"सुबह तक चालू रहेगी"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> बजे चालू हाेगी"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> बजे तक चालू रहेगी"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"एनएफ़सी"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC बंद है"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC चालू है"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"स्क्रीन रिकॉर्ड"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"शुरू करें"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"रोकें"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"पसंद के मुताबिक बनाएं"</string>
     <string name="notification_done" msgid="6215117625922713976">"हो गया"</string>
     <string name="inline_undo" msgid="9026953267645116526">"पहले जैसा करें"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"इस सूचना को \'बातचीत नहीं\' के रूप में मार्क करें"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"पसंदीदा के रूप में मार्क करें"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"पसंदीदा से हटाएं"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"म्यूट करें"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"अनम्यूट करें"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"बबल के रूप में दिखाएं"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"बबल्स को बंद करें"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"होम स्क्रीन पर जोड़ें"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"सूचना नियंत्रण"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"सूचना को स्नूज़ (थोड़ी देर के लिए चुप करना) करने के विकल्प"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 1286709..55a0e78 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zumiraj i ispuni zaslon"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Rastegni i ispuni zaslon"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Snimka zaslona"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Umetnuta je slika"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Spremanje snimke zaslona..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Spremanje snimke zaslona..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Snimka zaslona spremljena"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Započni snimanje"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Snimi glasovni zapis"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Prikaži dodire"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Dodirnite da biste zaustavili"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Zaustavi"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pauza"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Nastavi"</string>
@@ -390,6 +392,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Štednja baterije"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Uključuje se u suton"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do izlaska sunca"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Uključuje se u <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC je onemogućen"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC je omogućen"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index a3b6d3f..a9b2d03 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Nagyítás a kitöltéshez"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Nyújtás kitöltéshez"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Képernyőkép"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Kép beszúrva"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Képernyőkép mentése..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Képernyőkép mentése..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"A képernyőkép mentése sikerült"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Rögzítés indítása"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Hang rögzítése"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Koppintások megjelenítése"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Koppintson a leállításhoz"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Leállítás"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Szünet"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Folytatás"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Akkumulátorkímélő"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Be: napnyugta"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Napfelkeltéig"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Be: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Eddig: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Az NFC ki van kapcsolva"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Az NFC be van kapcsolva"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 5c73ed1..78acb2e 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Խոշորացնել` էկրանը լցնելու համար"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Ձգել` էկրանը լցնելու համար"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Սքրինշոթ"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Պատկերը զետեղվեց"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Սքրինշոթը պահվում է…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Սքրինշոթը պահվում է..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Սքրինշոթը պահվեց"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Սկսել տեսագրումը"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Ձայնագրել ուղեկցող ձայները"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Ցույց տալ հպումները"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Հպեք՝ դադարեցնելու համար"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Կանգնեցնել"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Դադարեցնել"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Վերսկսել"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Մարտկոցի տնտեսում"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Կմիացվի մայրամուտին"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Մինչև լուսաբաց"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Կմիանա՝ <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Մինչև <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC-ն անջատված է"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC-ն միացված է"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Էկրանի ձայնագրում"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Սկսել"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Կանգնեցնել"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Կարգավորել"</string>
     <string name="notification_done" msgid="6215117625922713976">"Պատրաստ է"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Հետարկել"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Նշել այս ծանուցումը որպես ոչ խոսակցություն"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Ավելացնել ընտրանիում"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Հեռացնել ընտրանուց"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Անջատել ծանուցումները"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Միացնել ծանուցումները"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Ցուցադրել որպես ամպիկ"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Անջատել ամպիկները"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Ավելացնել հիմնական էկրանին"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"ծանուցման կառավարներ"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"ծանուցման հետաձգման ընտրանքներ"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index bad3e67..95c16c8 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Perbesar utk mengisi layar"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Rentangkn utk mngisi layar"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Gambar disisipkan"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Menyimpan screenshot..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Menyimpan screenshot..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot disimpan"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Mulai Merekam"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Rekam voiceover"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Tampilkan sentuhan"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Ketuk untuk menghentikan"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Stop"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Jeda"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Lanjutkan"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Penghemat Baterai"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Aktif saat malam"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Sampai pagi"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Aktif pada <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Sampai <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC dinonaktifkan"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC diaktifkan"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 68f04fb..985f62d 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Fylla skjá með aðdrætti"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Teygja yfir allan skjáinn"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Skjámynd"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Mynd sett inn"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Vistar skjámynd…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Vistar skjámynd…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Skjámynd vistuð"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Hefja upptöku"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Taka upp talsetningu"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Sýna snertingar"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Ýttu til að stöðva"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Stöðva"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Hlé"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Halda áfram"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Rafhlöðusparnaður"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Kveikt við sólsetur"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Til sólarupprásar"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Virkt kl. <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Til <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Slökkt á NFC"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Kveikt á NFC"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index bdf93fa..870e6b7 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom per riempire schermo"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Estendi per riemp. schermo"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Immagine inserita"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Salvataggio screenshot..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Salvataggio screenshot..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot salvato"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Avvia registrazione"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Registra voce fuori campo"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Mostra tocchi"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Tocca per interrompere"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Interrompi"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pausa"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Riprendi"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Risparmio energetico"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Attivato al tramonto"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Fino all\'alba"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Attivazione alle <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Fino alle <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC non attiva"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC attiva"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 9cfd0b3..775be02 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"הגדל תצוגה כדי למלא את המסך"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"מתח כדי למלא את המסך"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"צילום מסך"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"התמונה התווספה"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"שומר צילום מסך..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"שומר צילום מסך..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"צילום המסך נשמר"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"הפעלת ההקלטה"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"‏הקלטת voiceover"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"הצגת הקשות"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"אפשר להקיש כדי להפסיק"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"עצירה"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"השהיה"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"המשך"</string>
@@ -392,15 +394,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"חיסכון בסוללה"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"מופעל בשקיעה"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"עד הזריחה"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"יתחיל בשעה <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"עד <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"‏NFC מושבת"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"‏NFC מופעל"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"הקלטת המסך"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"התחלה"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"עצירה"</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>
@@ -702,22 +703,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"התאמה אישית"</string>
     <string name="notification_done" msgid="6215117625922713976">"סיום"</string>
     <string name="inline_undo" msgid="9026953267645116526">"ביטול"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"סימון ההתראה הזו כהתראה שאינה משיחה"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"סימון כמועדפת"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"הסרה מהמועדפים"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"השתקה"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"ביטול ההשתקה"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"הצגה בתור בועה"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"כיבוי הבועות"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"הוספה למסך הבית"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"בקרת התראות"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"אפשרויות של דחיית התראות לטיפול בהמשך"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 0c57372..7af3f86 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"画面サイズに合わせて拡大"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"画面サイズに合わせて拡大"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"スクリーンショット"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"画像を挿入しました"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"スクリーンショットを保存中..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"スクリーンショットを保存しています..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"スクリーンショットを保存しました"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"録画を開始"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"ナレーションの録音"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"タップの表示"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"タップして停止"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"停止"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"一時停止"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"再開"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"バッテリー セーバー"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"日の入りに ON"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"日の出まで"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>にオン"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g>まで"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC は無効です"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC は有効です"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"スクリーン レコード"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"開始"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"停止"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"カスタマイズ"</string>
     <string name="notification_done" msgid="6215117625922713976">"完了"</string>
     <string name="inline_undo" msgid="9026953267645116526">"元に戻す"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"この通知を会話ではないとマーク"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"お気に入り"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"お気に入りから削除"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"ミュート"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"ミュートを解除"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"ふきだしとして表示"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"ふきだしを OFF にする"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"ホーム画面に追加"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"通知管理"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"通知スヌーズ設定"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index a3827d2..2433f9e 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"მასშტაბი შეცვალეთ ეკრანის შესავსებად."</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"გაწიეთ ეკრანის შესავსებად."</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ეკრანის ანაბეჭდი"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"სურათი ჩასმულია"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"სკრინშოტის შენახვა…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ეკრანის სურათის შენახვა…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ეკრანის ანაბეჭდი შენახულია"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"ჩაწერის დაწყება"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"ხმის ჩაწერა"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"შეხებების ჩვენება"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"შეეხეთ შესაწყვეტად"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"შეწყვეტა"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"პაუზა"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"გაგრძელება"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ბატარეის დამზოგი"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"ჩაირთოს მზის ჩასვლისას"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"მზის ამოსვლამდე"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"ჩაირთოს <xliff:g id="TIME">%s</xliff:g>-ზე"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g>-მდე"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC გათიშულია"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ჩართულია"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ეკრანის ჩანაწერი"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"დაწყება"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"შეწყვეტა"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"მორგება"</string>
     <string name="notification_done" msgid="6215117625922713976">"მზადაა"</string>
     <string name="inline_undo" msgid="9026953267645116526">"მოქმედების გაუქმება"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"ამ შეტყობინების მონიშვნა, როგორც არა მიმოწერის"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"რჩეული"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"რჩეულებიდან ამოღება"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"დადუმება"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"დადუმების მოხსნა"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"ბუშტის სახით ჩვენება"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"ბუშტების გამორთვა"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"მთავარ ეკრანზე დამატება"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"შეტყობინებების მართვის საშუალებები"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"შეტყობინებების ჩაჩუმების ვარიანტები"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 19ae4e2..be93c18 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Экранды толтыру үшін ұлғайту"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Экранды толтыру үшін созу"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Скриншот"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Сурет енгізілді"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Скриншотты сақтауда…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Скриншотты сақтауда…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Скриншот сақталды"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Жазуды бастау"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Кадр сыртындағы дыбысты жазу"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Түрту әрекеттерін көрсету"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Тоқтату үшін түртіңіз"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Тоқтату"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Тоқтата тұру"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Жалғастыру"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Battery Saver"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Күн батқанда қосу"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Күн шыққанға дейін"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Қосылу уақыты: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> дейін"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC өшірулі"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC қосулы"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Экранды жазу"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Бастау"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Тоқтату"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Реттеу"</string>
     <string name="notification_done" msgid="6215117625922713976">"Дайын"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Қайтару"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Хабарландыруды сөйлесу емес деп белгілеу"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Таңдаулы"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Таңдаулылар тізімінен шығару"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Дыбысын өшіру"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Дыбысын қосу"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Қалқымалы анықтама ретінде көрсету"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Қалқымалы анықтамаларды өшіру"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Негізгі экранға қосу"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"хабарландыруларды басқару элементтері"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"хабарландыруды кідірту опциялары"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index d6ec177..413125c 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"ពង្រីក​​ដើម្បី​ឲ្យ​ពេញ​អេក្រង់"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"ទាញ​ដើម្បី​ឲ្យ​ពេញ​អេក្រង់"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"រូបថតអេក្រង់"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"បាន​បញ្ចូល​រូបភាព"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"កំពុង​រក្សាទុក​រូបថត​អេក្រង់…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"កំពុង​រក្សាទុក​រូបថត​អេក្រង់..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"បានរក្សាទុក​រូបថតអេក្រង់"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"ចាប់​ផ្តើមថត"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"ថត​ការបញ្ចូល​សំឡេង"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"បង្ហាញការចុច"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"ចុច ដើម្បីបញ្ឈប់"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"ឈប់"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"ផ្អាក"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"បន្ត"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"កម្មវិធីសន្សំថ្ម"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"បើក​នៅពេល​ថ្ងៃលិច"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"រហូត​ដល់​ពេល​ថ្ងៃរះ"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"បើកនៅម៉ោង <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"រហូតដល់ម៉ោង <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"បាន​បិទ NFC"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"បាន​បើក NFC"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ការថត​អេក្រង់"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ចាប់ផ្ដើម"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ឈប់"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"ប្ដូរតាមបំណង"</string>
     <string name="notification_done" msgid="6215117625922713976">"រួចរាល់"</string>
     <string name="inline_undo" msgid="9026953267645116526">"ត្រឡប់វិញ"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"សម្គាល់​ការជូន​ដំណឹង​នេះ​ថា​មិនមែនជា​ការសន្ទនា"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"សំណព្វ"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"ដក​ចេញ​ពី​សំណព្វ"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"បិទ​សំឡេង"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"បើក​សំឡេង"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"បង្ហាញ​ជា​សារ​លេចឡើង"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"បិទ​សារ​លេចឡើង"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"បញ្ចូល​ទៅក្នុង​អេក្រង់​ដើម"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"ការគ្រប់គ្រង​ការជូន​ដំណឹង"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"ជម្រើស​ផ្អាកការ​ជូនដំណឹង"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index fc0f8e6..0b98e06 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"ಪರದೆ ತುಂಬಿಸಲು ಝೂಮ್ ಮಾಡು"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"ಪರದೆ ತುಂಬಿಸಲು ವಿಸ್ತಾರಗೊಳಿಸು"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"ಚಿತ್ರವನ್ನು ಸೇರಿಸಲಾಗಿದೆ"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಉಳಿಸಲಾಗುತ್ತಿದೆ…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಉಳಿಸಲಾಗುತ್ತಿದೆ…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ ಅನ್ನು ಉಳಿಸಲಾಗಿದೆ"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"ರೆಕಾರ್ಡಿಂಗ್ ಆರಂಭಿಸಿ"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"voiceover ಅನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಿ"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"ಟ್ಯಾಪ್‌ಗಳನ್ನು ತೋರಿಸಿ"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"ನಿಲ್ಲಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"ನಿಲ್ಲಿಸಿ"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"ವಿರಾಮಗೊಳಿಸಿ"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"ಮುಂದುವರಿಸಿ"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ಬ್ಯಾಟರಿ ಸೇವರ್"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"ಸೂರ್ಯಾಸ್ತ ಸಮಯದಲ್ಲಿ"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ಸೂರ್ಯೋದಯದವರೆಗೆ"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> ಸಮಯದಲ್ಲಿ"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> ವರೆಗೂ"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ನಿಷ್ಕ್ರಿಯಗೊಂಡಿದೆ"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ಸಕ್ರಿಯಗೊಂಡಿದೆ"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡ್"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ಪ್ರಾರಂಭಿಸಿ"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ನಿಲ್ಲಿಸಿ"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"ಕಸ್ಟಮೈಜ್‌ ಮಾಡಿ"</string>
     <string name="notification_done" msgid="6215117625922713976">"ಮುಗಿದಿದೆ"</string>
     <string name="inline_undo" msgid="9026953267645116526">"ರದ್ದುಮಾಡಿ"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"ಈ ಅಧಿಸೂಚನೆಯನ್ನು ಸಂಭಾಷಣೆಯಲ್ಲ ಎಂಬುದಾಗಿ ಗುರುತಿಸಿ"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"ಮೆಚ್ಚಿನದು"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"ಮೆಚ್ಚಿನದಲ್ಲದ್ದು"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"ಮ್ಯೂಟ್ ಮಾಡಿ"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"ಅನ್‌ಮ್ಯೂಟ್ ಮಾಡಿ"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"ಗುಳ್ಳೆಯಾಗಿ ತೋರಿಸಿ"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"ಗುಳ್ಳೆಗಳನ್ನು ಆಫ್ ಮಾಡಿ"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"ಮುಖಪುಟದ ಪರದೆಗೆ ಸೇರಿಸಿ"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"ಅಧಿಸೂಚನೆ ನಿಯಂತ್ರಣಗಳು"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"ಅಧಿಸೂಚನೆ ಸ್ನೂಜ್ ಆಯ್ಕೆಗಳು"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index eb3ebc9..54b055d 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"전체화면 모드로 확대"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"전체화면 모드로 확대"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"스크린샷"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"이미지 삽입됨"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"캡쳐화면 저장 중..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"캡쳐화면 저장 중..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"스크린샷 저장됨"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"녹화 시작"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"음성 해설 녹음"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"탭한 항목 표시"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"탭하여 중지하기"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"중지"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"일시중지"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"재개"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"절전 모드"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"일몰에"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"일출까지"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>에"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g>까지"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC 사용 중지됨"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC 사용 설정됨"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"화면 녹화"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"시작"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"중지"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"맞춤설정"</string>
     <string name="notification_done" msgid="6215117625922713976">"완료"</string>
     <string name="inline_undo" msgid="9026953267645116526">"실행취소"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"이 알림을 대화가 아닌 일반 알림으로 표시"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"즐겨찾기"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"즐겨찾기 해제"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"숨기기"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"숨기기 취소"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"버블로 표시"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"버블 사용 중지"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"홈 화면에 추가"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"알림 관리"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"알림 일시 중지 옵션"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 06f8161..ed6b918 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Экрнд тлтр ү. чен өлч өзг"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Экранды толтуруу ү-н чоюу"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Скриншот"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Сүрөт киргизилди"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Скриншот сакталууда…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Скриншот сакталууда..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Скриншот сакталды"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Жаздырып баштоо"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Үн коштоону жаздыруу"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Басылган жерди көрсөтүү"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Токтотуш үчүн басыңыз"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Токтотуу"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Тындыруу"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Улантуу"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Батареяны үнөмдөгүч"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Күн батканда күйөт"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Күн чыкканга чейин"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Саат <xliff:g id="TIME">%s</xliff:g> күйөт"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> чейин"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC өчүрүлгөн"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC иштетилген"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Экранды жаздыруу"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Старт"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Токтотуу"</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>
@@ -444,7 +445,7 @@
     <string name="guest_new_guest" msgid="962155336259570156">"Конок кошуу"</string>
     <string name="guest_exit_guest" msgid="4030840507598850886">"Конокту алып салуу"</string>
     <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Конокту алып саласызбы?"</string>
-    <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Бул сеанстагы бардык колдонмолор жана дайындар жок кылынат."</string>
+    <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Бул сеанстагы бардык колдонмолор жана дайындар өчүрүлөт."</string>
     <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Алып салуу"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Кайтып келишиңиз менен, конок!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Сеансыңызды улантасызбы?"</string>
@@ -464,7 +465,7 @@
       <item quantity="one">Бир колдонуучуну гана кошууга болот.</item>
     </plurals>
     <string name="user_remove_user_title" msgid="9124124694835811874">"Колдонуучу алынып салынсынбы?"</string>
-    <string name="user_remove_user_message" msgid="6702834122128031833">"Бул колдонуучунун бардык колдонмолору жана дайындары жок кылынат."</string>
+    <string name="user_remove_user_message" msgid="6702834122128031833">"Бул колдонуучунун бардык колдонмолору жана дайындары өчүрүлөт."</string>
     <string name="user_remove_user_remove" msgid="8387386066949061256">"Алып салуу"</string>
     <string name="battery_saver_notification_title" msgid="8419266546034372562">"Батареяны үнөмдөгүч режими күйүк"</string>
     <string name="battery_saver_notification_text" msgid="2617841636449016951">"Иштин майнаптуулугун начарлатып, фондук дайындарды чектейт"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Ыңгайлаштыруу"</string>
     <string name="notification_done" msgid="6215117625922713976">"Бүттү"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Кайтаруу"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Бул билдирме \"жазышуу эмес\" катары белгиленсин"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Сүйүктүүлөргө кошуу"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Сүйүктүүлөрдөн чыгаруу"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Үнүн басуу"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Үнүн чыгаруу"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Көбүк катары көрсөтүү"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Көбүктөрдү өчүрүү"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Башкы экранга кошуу"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"эскертмелерди башкаруу каражаттары"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"эскертмени тындыруу опциялары"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 3013e1e..11c4f7c 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"ຊູມໃຫ້ເຕັມໜ້າຈໍ"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"ປັບໃຫ້ເຕັມໜ້າຈໍ"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ພາບໜ້າຈໍ"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"ແຊກຮູບແລ້ວ"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"ກຳລັງບັນທຶກຮູບໜ້າຈໍ"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ກຳລັງບັນທຶກພາບໜ້າຈໍ..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ບັນທຶກຮູບໜ້າຈໍໄວ້ແລ້ວ"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"ເລີ່ມການບັນທຶກ"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"ບັນທຶກສຽງພາກ"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"ສະແດງການແຕະ"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"ແຕະ​ເພື່ອ​ຢຸດ"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"ຢຸດ"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"ຢຸດຊົ່ວຄາວ"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"ສືບຕໍ່"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ຕົວປະຢັດແບັດເຕີຣີ"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"ເປີດຕອນຕາເວັນຕົກ"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ຈົນກວ່າຕາເວັນຂຶ້ນ"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"ເປີດເວລາ <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"ຈົນຮອດ <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is disabled"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is enabled"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ການບັນທຶກໜ້າຈໍ"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ເລີ່ມ"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ຢຸດ"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"ປັບແຕ່ງ"</string>
     <string name="notification_done" msgid="6215117625922713976">"ສຳເລັດແລ້ວ"</string>
     <string name="inline_undo" msgid="9026953267645116526">"ຍົກເລີກ"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"ໝາຍການແຈ້ງເຕືອນນີ້ວ່າບໍ່ແມ່ນການສົນທະນາ"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"ລາຍ​ການ​ທີ່​ມັກ"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"ຍົກເລີກລາຍການທີ່ມັກ"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"ປິດສຽງ"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"ເຊົາປິດສຽງ"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"ສະແດງເປັນ bubble"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"ປິດການໃຊ້ bubble"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"ເພີ່ມໃສ່ໜ້າຈໍຫຼັກ"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"ການຄວບຄຸມການແຈ້ງເຕືອນ"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"ຕົວເລືອກການເລື່ອນການແຈ້ງເຕືອນ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index c6b50d9..7da1174 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Keisti mast., kad atit. ekr."</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Ištempti, kad atit. ekr."</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Ekrano kopija"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Vaizdas įterptas"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Išsaugoma ekrano kopija..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Išsaugoma ekrano kopija..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Ekrano kopija išsaugota"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Pradėti įrašymą"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Įrašyti balsą už kadro"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Rodyti palietimus"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Sustabdykite palietę"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Sustabdyti"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pristabdyti"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Tęsti"</string>
@@ -392,6 +394,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Akum. taus. priemonė"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Per saulėlydį"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Iki saulėtekio"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Iki <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"ALR"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"ALR išjungtas"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"ALR įjungtas"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index b519f05..fed86b3 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Tālumm., lai aizp. ekr."</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Stiepiet, lai aizp. ekr."</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Ekrānuzņēmums"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Attēls ir ievietots"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Saglabā ekrānuzņēmumu…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Notiek ekrānuzņēmuma saglabāšana..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Ekrānuzņēmums saglabāts"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Sākt ierakstīšanu"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Ierakstīt balsi"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Rādīt pieskārienus"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Pieskarieties, lai apturētu"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Pārtraukt"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Apturēt"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Atsākt"</string>
@@ -390,15 +392,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Jaudas taupīšana"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Saulrietā"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Līdz saullēktam"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Plkst. <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Līdz plkst. <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ir atspējoti"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ir iespējoti"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Ekrāna ierakstīšana"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Sākt"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Apturēt"</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>
@@ -699,22 +700,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Pielāgot"</string>
     <string name="notification_done" msgid="6215117625922713976">"Gatavs"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Atsaukt"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Atzīmēt, ka šis paziņojums nav saruna"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Pievienot izlasei"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Noņemt no izlases"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Izslēgt skaņu"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Ieslēgt skaņu"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Rādīt kā burbuli"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Izslēgt burbuļus"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Pievienot sākuma ekrānam"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"paziņojumu vadīklas"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"paziņojumu atlikšanas opcijas"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 9080b57..a02f38e 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Зумирај да се исполни екранот"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Растегни да се исполни екранот"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Слика од екранот"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Вметната е слика"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Сликата на екранот се зачувува..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Сликата на екранот се зачувува..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Сликата од екранот е зачувана"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Започни со снимање"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Снимај коментар"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Прикажувај допири"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Допрете за запирање"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Сопри"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Паузирај"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Продолжи"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Штедач на батерија"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Вклуч. на зајдисонце"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"До изгрејсонце"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Се вклучува во <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"До <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC е оневозможено"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC е овозможено"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index b761c44..2d3f73f 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"സ്‌ക്രീനിൽ ഉൾക്കൊള്ളിക്കാൻ സൂം ചെയ്യുക"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"സ്‌ക്രീനിൽ ഉൾക്കൊള്ളിക്കാൻ വലിച്ചുനീട്ടുക"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"സ്ക്രീൻഷോട്ട്"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"ചിത്രം ചേർത്തു"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"സ്‌ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്നു..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"സ്‌ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്നു..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"സ്‌ക്രീൻഷോട്ട് സംരക്ഷിച്ചു"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"റെക്കോര്‍ഡിംഗ് ആരംഭിക്കുക"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"വോയ്‌സ് ഓവർ റെക്കോർഡ് ചെയ്യുക"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"ടാപ്പുകൾ കാണിക്കുക"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"നിർത്താൻ ടാപ്പ് ചെയ്യുക"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"നിർത്തുക"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"താൽക്കാലികമായി നിർത്തുക"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"പുനരാരംഭിക്കുക"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ബാറ്ററി ലാഭിക്കൽ"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"സൂര്യാസ്‌തമയത്തിന്"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"സൂര്യോദയം വരെ"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>-ന്"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> വരെ"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC പ്രവർത്തനരഹിതമാക്കി"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC പ്രവർത്തനക്ഷമമാക്കി"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"സ്‌ക്രീൻ റെക്കോർഡ്"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ആരംഭിക്കുക"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"നിര്‍ത്തുക"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"ഇഷ്‌ടാനുസൃതമാക്കുക"</string>
     <string name="notification_done" msgid="6215117625922713976">"പൂർത്തിയായി"</string>
     <string name="inline_undo" msgid="9026953267645116526">"പഴയപടിയാക്കുക"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"ഈ അറിയിപ്പ് സംഭാഷണമല്ലെന്ന് അടയാളപ്പെടുത്തുക"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"പ്രിയപ്പെട്ടവ"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"പ്രിയപ്പെട്ടതല്ലാതാക്കുക"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"മ്യൂട്ട് ചെയ്യുക"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"അൺമ്യൂട്ട് ചെയ്യുക"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"ബബ്‌ൾ ആയി കാണിക്കുക"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"ബബിളുകൾ ഓഫാക്കുക"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"ഹോം സ്‌ക്രീനിലേക്ക് ചേർക്കുക"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"അറിയിപ്പ് നിയന്ത്രണങ്ങൾ"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"അറിയിപ്പ് സ്‌നൂസ് ഓപ്ഷനുകൾ"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 4f9b447..85d7ead 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Дэлгэц дүүргэх бол өсгөнө үү"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Дэлгэц дүүргэх бол татна уу"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Дэлгэцийн зураг дарах"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Зургийг орууллаа"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Дэлгэцийн агшинг хадгалж байна…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Дэлгэцийн агшинг хадгалж байна…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Дэлгэцээс дарсан зургийг хадгалсан"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Бичлэгийг эхлүүлэх"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Дуу оруулалтыг бичих"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Товшилтыг харуулах"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Зогсоохын тулд товшино уу"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Зогсоох"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Түр зогсоох"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Үргэлжлүүлэх"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Батарей хэмнэгч"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Нар жаргах үед"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Нар мандах хүртэл"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>-д"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> хүртэл"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC-г цуцалсан"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC-г идэвхжүүлсэн"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Дэлгэцийн бичлэг хийх"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Эхлүүлэх"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Зогсоох"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Тохируулах"</string>
     <string name="notification_done" msgid="6215117625922713976">"Дууссан"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Болих"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Энэ мэдэгдлийг харилцаа биш гэж тэмдэглэх"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Дуртай"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Дургүй"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Дууг хаах"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Дууг нээх"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Хөөс маягаар харуулах"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Хөөсийг унтраах"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Үндсэн нүүрэнд нэмэх"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"мэдэгдлийн удирдлага"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"мэдэгдэл түр хойшлуулагчийн сонголт"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 99f48e6..3406edf 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"स्क्रीन भरण्यासाठी झूम करा"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"स्क्रीन भरण्यासाठी ताणा"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"स्क्रीनशॉट"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"इमेज घातली गेली"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"स्क्रीनशॉट सेव्ह करत आहे…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"स्क्रीनशॉट सेव्ह करत आहे…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"स्क्रीनशॉट सेव्ह केला"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"रेकॉर्डिंग सुरू करा"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"व्हॉइसओव्हर रेकॉर्ड करा"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"टॅप दाखवा"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"थांबवण्यासाठी टॅप करा"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"थांबवा"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"थांबवा"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"पुन्हा सुरू करा"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"बॅटरी सेव्‍हर"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"संध्याकाळी सुरू होते"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"सूर्योदयापर्यंत"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> वाजता सुरू होते"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> पर्यंत"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC अक्षम केले आहे"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC सक्षम केले आहे"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"स्क्रीन रेकॉर्ड"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"सुरू"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"थांबा"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"कस्टमाइझ करा"</string>
     <string name="notification_done" msgid="6215117625922713976">"पूर्ण झाले"</string>
     <string name="inline_undo" msgid="9026953267645116526">"पहिल्यासारखे करा"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"ही सूचना संभाषण नाही म्हणून खूण करा"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"आवडते"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"नावडते"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"म्यूट करा"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"अनम्यूट करा"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"बबल असे दाखवा"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"बुडबुडे बंद करा"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"होम स्क्रीनवर जोडा"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"सूचना नियंत्रणे"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"सूचना स्नूझ पर्याय"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 42c51b7..eeaacea 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zum untuk memenuhi skrin"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Regang utk memenuhi skrin"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Tangkapan skrin"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Imej disisipkan"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Menyimpan tangkapan skrin..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Menyimpan tangkapan skrin..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Tangkapan skrin disimpan"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Mula Merakam"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Rakam suara latar"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Tunjukkan ketikan"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Ketik untuk berhenti"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Berhenti"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Jeda"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Sambung semula"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Penjimat Bateri"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Dihidupkan pd senja"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Hingga matahari trbt"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Dihidupkan pada <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Hingga <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC dilumpuhkan"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC didayakan"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Saring Rekod"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Mula"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Berhenti"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Sesuaikan"</string>
     <string name="notification_done" msgid="6215117625922713976">"Selesai"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Buat asal"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Tandai pemberitahuan ini sebagai bukan perbualan"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Kegemaran"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Nyahgemari"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Redam"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Nyahredam"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Tunjukkan sebagai gelembung"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Matikan gelembung"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Tambahkan pada skrin utama"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"kawalan pemberitahuan"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"pilihan tunda pemberitahuan"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index dd5acfa..5ae82ea 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"ဇူးမ်အပြည့်ဆွဲခြင်း"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"ဖန်သားပြင်အပြည့်ဆန့်ခြင်း"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ဖန်သားပြင်ဓာတ်ပုံ"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"ပုံ ထည့်ထားသည်"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"ဖန်သားပြင်ဓါတ်ပုံသိမ်းစဉ်.."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ဖန်သားပြင်ဓါတ်ပုံရိုက်ခြင်းအား သိမ်းဆည်းပါမည်"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ဖန်သားပြင်ဓာတ်ပုံကို သိမ်းပြီးပါပြီ"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"စတင် ရိုက်ကူးရန်"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"နောက်ခံစကားပြော ကူးယူရန်"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"တို့ခြင်းများကို ပြရန်"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"ရပ်ရန် တို့ပါ"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"ရပ်ရန်"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"ခဏရပ်ရန်"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"ဆက်လုပ်ရန်"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ဘက်ထရီ အားထိန်း"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"နေဝင်ချိန်၌ ဖွင့်ရန်"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"နေထွက်ချိန် အထိ"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> တွင် ဖွင့်မည်"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> အထိ"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ကို ပိတ်ထားသည်"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ကို ဖွင့်ထားသည်"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ဖန်သားပြင် မှတ်တမ်းတင်ရန်"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"စတင်ရန်"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ရပ်ရန်"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"စိတ်ကြိုက်ပြုလုပ်ရန်"</string>
     <string name="notification_done" msgid="6215117625922713976">"ပြီးပါပြီ"</string>
     <string name="inline_undo" msgid="9026953267645116526">"တစ်ဆင့်နောက်ပြန်ရန်"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"ဤအကြောင်းကြားချက်ကို စကားဝိုင်းမဟုတ်ဟု မှတ်ထားရန်"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"အကြိုက်ဆုံး"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"အကြိုက်ဆုံးမှ ဖယ်ရှားရန်"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"အသံတိတ်ရန်"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"အသံဖွင့်ရန်"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"ပူဖောင်းကွက်အဖြစ် ပြရန်"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"ပူဖောင်းကွက်များကို ပိတ်ရန်"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"ပင်မစာမျက်နှာတွင် ထည့်ရန်"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"အကြောင်းကြားချက် ထိန်းချုပ်မှုများ"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"အကြောင်းကြားချက်များကို ဆိုင်းငံ့ရန် ရွေးချယ်စရာများ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 97d6792..463b95c 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom for å fylle skjermen"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Strekk for å fylle skjerm"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Skjermdump"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Bildet er satt inn"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Lagrer skjermdumpen …"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Lagrer skjermdumpen …"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Skjermdumpen er lagret"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Start opptak"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Ta opp et kommentarspor"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Vis trykk"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Trykk for å stoppe"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Stopp"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Sett på pause"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Gjenoppta"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Batterisparing"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"På ved solnedgang"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Til soloppgang"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Slås på klokken <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Til <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC er slått av"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC er slått på"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Skjermopptak"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Start"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Stopp"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Tilpass"</string>
     <string name="notification_done" msgid="6215117625922713976">"Ferdig"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Angre"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Marker dette varselet som ikke en samtale"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Favoritt"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Fjern som favoritt"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Ignorer"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Slutt å ignorere"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Vis som boble"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Slå av bobler"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Legg til på startskjermen"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"varselinnstillinger"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"slumrealternativer for varsler"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 1345b09..21a76a3 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"स्क्रिन भर्न जुम गर्नुहोस्"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"स्क्रिन भर्न तन्काउनुहोस्"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"स्क्रिनसट"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"छवि सम्मिलित गरियो"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"स्क्रिनसट बचत गर्दै…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"स्क्रिनसट बचत गर्दै…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"स्क्रिनसट सुरक्षित गरियो"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"रेकर्डिङ सुरु गर्नुहोस्"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"भ्वाइसओवर रेकर्ड गर्नुहोस्"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"ट्यापहरू देखाउनुहोस्"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"रोक्न ट्याप गर्नुहोस्"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"रोक्नुहोस्"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"पज गर्नुहोस्"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"जारी राख्नुहोस्"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ब्याट्री सेभर"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"सूर्यास्तमा सक्रिय"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"सूर्योदयसम्म"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> मा सक्रिय"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> सम्म"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC लाई असक्षम पारिएको छ"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC लाई सक्षम पारिएको छ"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"स्रिनको रेकर्ड"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"सुरु गर्नुहोस्"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"रोक्नुहोस्"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"आफू अनुकूल पार्नुहोस्"</string>
     <string name="notification_done" msgid="6215117625922713976">"सम्पन्‍न भयो"</string>
     <string name="inline_undo" msgid="9026953267645116526">"अन्डू गर्नुहोस्"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"यो सूचनालाई वार्तालाप होइन भनी चिन्ह लगाउनुहोस्"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"मन पर्ने"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"मन पर्ने कुराहरूबाट हटाउनुहोस्"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"म्युट गर्नुहोस्"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"अनम्युट गर्नुहोस्"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"बबलको रूपमा देखाउनुहोस्"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"बबलहरूलाई निष्क्रिय पार्नुहोस्"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"गृह स्क्रिनमा थप्नुहोस्"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"सूचना सम्बन्धी नियन्त्रणहरू"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"सूचना स्नुज गर्ने विकल्पहरू"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 71d2388..3c04015 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom om scherm te vullen"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Rek uit v. schermvulling"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Afbeelding ingevoegd"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Screenshot opslaan..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Screenshot opslaan..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot opgeslagen"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Opname starten"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Voice-over opnemen"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Tikken weergeven"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Tik om te stoppen"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Stoppen"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pauzeren"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Hervatten"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Batterijbesparing"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Aan bij zonsondergang"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Tot zonsopgang"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Aan om <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Tot <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is uitgeschakeld"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is ingeschakeld"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 85841fe..4230275 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"ସ୍କ୍ରୀନ ଭରିବା ପାଇଁ ଜୁମ୍ କରନ୍ତୁ"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"ସ୍କ୍ରୀନ୍‌କୁ ଭରିବା ପାଇଁ ଟାଣନ୍ତୁ"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ସ୍କ୍ରିନ୍‌ସଟ୍ ନିଅନ୍ତୁ"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"ଛବି ଭର୍ତ୍ତି କରାଯାଇଛି"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"ସ୍କ୍ରୀନଶଟ୍‍ ସେଭ୍‍ କରାଯାଉଛି…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ସ୍କ୍ରୀନଶଟ୍‍ ସେଭ୍‍ କରାଯାଉଛି…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ସ୍କ୍ରୀନଶଟ୍ ସେଭ୍ ହୋଇଛି"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"ରେକର୍ଡିଂ ଆରମ୍ଭ କରନ୍ତୁ"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"ଭଏସ୍‍‍‍‍‍‍‍‍‍ଓଭର୍‍ ରେକର୍ଡ କରନ୍ତୁ"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"ଟାପ୍‌ ଦେଖାନ୍ତୁ"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"ବନ୍ଦ କରିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"ବନ୍ଦ କରନ୍ତୁ"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"ବିରତି କରନ୍ତୁ"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"ପୁଣି ଚାଲୁ କରନ୍ତୁ"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ବ୍ୟାଟେରୀ ସେଭର୍"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"ସନ୍ଧ୍ୟାରେ ଚାଲୁ ହେବ"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ସକାଳ ପର୍ଯ୍ୟନ୍ତ"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>ରେ ଚାଲୁ ହେବ"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> ପର୍ଯ୍ୟନ୍ତ"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ଅକ୍ଷମ କରାଯାଇଛି"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ସକ୍ଷମ କରାଯାଇଛି"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ସ୍କ୍ରିନ୍ ରେକର୍ଡ"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ଆରମ୍ଭ କରନ୍ତୁ"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ବନ୍ଦ କରନ୍ତୁ"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"କଷ୍ଟମାଇଜ୍‌ କରନ୍ତୁ"</string>
     <string name="notification_done" msgid="6215117625922713976">"ହୋଇଗଲା"</string>
     <string name="inline_undo" msgid="9026953267645116526">"ପୂର୍ବସ୍ଥାନକୁ ଫେରାଇଆଣନ୍ତୁ"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"ଏହି ବିଜ୍ଞପ୍ତି କୌଣସି ବାର୍ତ୍ତାଳାପ ନୁହେଁ ବୋଲି ଚିହ୍ନଟ କରନ୍ତୁ"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"ପସନ୍ଦ ଭାବରେ ଚିହ୍ନଟ କରନ୍ତୁ"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"ନାପସନ୍ଦ କରନ୍ତୁ"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"ମ୍ୟୁଟ୍ କରନ୍ତୁ"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"ଅନମ୍ୟୁଟ୍ କରନ୍ତୁ"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"ବୁଦବୁଦ୍ ଭାବରେ ଦେଖାନ୍ତୁ"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"ବୁଦବୁଦଗୁଡ଼ିକ ବନ୍ଦ କରନ୍ତୁ"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"ମୂଳ ସ୍କ୍ରିନରେ ଯୋଗ କରନ୍ତୁ"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"ବିଜ୍ଞପ୍ତି ନିୟନ୍ତ୍ରଣ"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"ବିଜ୍ଞପ୍ତି ସ୍ନୁଜ୍‍ ବିକଳ୍ପ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 4ea51dd..f345d6a 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"ਸਕ੍ਰੀਨ ਭਰਨ ਲਈ ਜ਼ੂਮ ਕਰੋ"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"ਸਕ੍ਰੀਨ ਭਰਨ ਲਈ ਸਟ੍ਰੈਚ ਕਰੋ"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ਸਕ੍ਰੀਨਸ਼ਾਟ"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"ਚਿੱਤਰ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਸੁਰੱਖਿਅਤ ਕਰ ਰਿਹਾ ਹੈ…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਸੁਰੱਖਿਅਤ ਕਰ ਰਿਹਾ ਹੈ…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"ਰਿਕਾਰਡਿੰਗ ਸ਼ੁਰੂ ਕਰੋ"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"ਅਵਾਜ਼ ਰਿਕਾਰਡ ਕਰੋ"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"ਟੈਪਾਂ ਦਿਖਾਓ"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"ਰੋਕਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"ਬੰਦ ਕਰੋ"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"ਰੋਕੋ"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"ਮੁੜ-ਚਾਲੂ ਕਰੋ"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ਬੈਟਰੀ ਸੇਵਰ"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"ਸੂਰਜ ਛਿਪਣ \'ਤੇ ਚਾਲੂ"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ਸੂਰਜ ਚੜ੍ਹਨ ਤੱਕ"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> ਵਜੇ ਚਾਲੂ"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> ਵਜੇ ਤੱਕ"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ਨੂੰ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ਨੂੰ ਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਰ"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ਸ਼ੁਰੂ ਕਰੋ"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ਰੋਕੋ"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"ਵਿਉਂਤਬੱਧ ਕਰੋ"</string>
     <string name="notification_done" msgid="6215117625922713976">"ਹੋ ਗਿਆ"</string>
     <string name="inline_undo" msgid="9026953267645116526">"ਅਣਕੀਤਾ ਕਰੋ"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"ਇਸ ਸੂਚਨਾ ਦੀ ਗੱਲ-ਬਾਤ ਨਹੀਂ ਵਜੋਂ ਨਿਸ਼ਾਨਦੇਹੀ ਕਰੋ"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"ਮਨਪਸੰਦ"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"ਨਾਪਸੰਦ"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"ਮਿਊਟ ਕਰੋ"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"ਅਣਮਿਊਟ ਕਰੋ"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"ਬੁਲਬੁਲੇ ਵਜੋਂ ਦਿਖਾਓ"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"ਬੁਲਬੁਲੇ ਬੰਦ ਕਰੋ"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਸ਼ਾਮਲ ਕਰੋ"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"ਸੂਚਨਾ ਕੰਟਰੋਲ"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"ਸੂਚਨਾ ਸਨੂਜ਼ ਵਿਕਲਪ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 515d659..68cb14e 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Powiększ, aby wypełnić ekran"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Rozciągnij, aby wypełnić ekran"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Zrzut ekranu"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Wstawiono obraz"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Zapisywanie zrzutu ekranu..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Zapisywanie zrzutu ekranu..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Zrzut ekranu został zapisany"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Rozpocznij rejestrowanie"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Nagraj tekst lektora"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Pokaż dotknięcia"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Kliknij, by zatrzymać"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Zatrzymaj"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Wstrzymaj"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Wznów"</string>
@@ -392,15 +394,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Oszczędzanie baterii"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Włącz o zachodzie"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do wschodu słońca"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Włącz o <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"Komunikacja NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Komunikacja NFC jest wyłączona"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Komunikacja NFC jest włączona"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Zapis ekranu"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Rozpocznij"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Zatrzymaj"</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>
@@ -702,22 +703,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Dostosuj"</string>
     <string name="notification_done" msgid="6215117625922713976">"Gotowe"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Cofnij"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Nie oznaczaj tego powiadomienia jako wątku"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Dodaj do ulubionych"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Usuń z ulubionych"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Wycisz"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Wyłącz wyciszenie"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Pokaż jako dymek"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Wyłącz dymki"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Dodaj do ekranu głównego"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"sterowanie powiadomieniami"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"opcje odkładania powiadomień"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index d486b9b..a9101d7 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom p/ preencher a tela"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Ampliar p/ preencher tela"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Capturar tela"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Imagem inserida"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Salvando captura de tela..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Salvando captura de tela..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Captura de tela salva"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Iniciar gravação"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Gravar narração"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Mostrar toques"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Toque para parar"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Parar"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pausar"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Retomar"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Economia de bateria"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Ativ. ao pôr do sol"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Até o nascer do sol"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Ativar: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Até: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"A NFC está desativada"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"A NFC está ativada"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index d17b002..1a6e673 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom para preencher o ecrã"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Esticar p. caber em ec. int."</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Captura de ecrã"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Imagem inserida"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"A guardar captura de ecrã..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"A guardar captura de ecrã..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Captura de ecrã guardada"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Iniciar gravação"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Gravar voz-off"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Mostrar toques"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Tocar para parar"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Parar"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Colocar em pausa"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Retomar"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Poupança de bateria"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Ativ. ao pôr do sol"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Até ao amanhecer"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Ativado à(s) <xliff:g id="TIME">%s</xliff:g>."</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Até à(s) <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"O NFC está desativado"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"O NFC está ativado"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index d486b9b..a9101d7 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom p/ preencher a tela"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Ampliar p/ preencher tela"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Capturar tela"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Imagem inserida"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Salvando captura de tela..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Salvando captura de tela..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Captura de tela salva"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Iniciar gravação"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Gravar narração"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Mostrar toques"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Toque para parar"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Parar"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pausar"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Retomar"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Economia de bateria"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Ativ. ao pôr do sol"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Até o nascer do sol"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Ativar: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Até: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"A NFC está desativada"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"A NFC está ativada"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 2674504..e34fa2d 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom pt. a umple ecranul"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Înt. pt. a umple ecranul"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Captură de ecran"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"S-a inserat imaginea"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Se salv. captura de ecran..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Se salvează captura de ecran..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Captură de ecran salvată"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Începeți înregistrarea"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Înregistrați vocal"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Afișați atingerile"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Atingeți pentru a opri"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Opriți"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Întrerupeți"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Reluați"</string>
@@ -390,15 +392,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Economisire baterie"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Activată la apus"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Până la răsărit"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Activată la <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Până la <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Serviciul NFC este dezactivat"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Serviciul NFC este activat"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Înregistrarea ecranului"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Începeți"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Opriți"</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>
@@ -699,22 +700,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Personalizați"</string>
     <string name="notification_done" msgid="6215117625922713976">"Terminat"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Anulați"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Marcați această notificare ca nefiind o conversație"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Preferată"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Anulați marcarea ca preferată"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Ignorați"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Afișați"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Afișează sub formă de balon"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Dezactivați baloanele"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Adăugați pe ecranul de pornire"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"comenzile notificării"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"opțiuni de amânare a notificării"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 9156989..0ee159d 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Подогнать по размерам экрана"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Растянуть на весь экран"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Скриншот"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Изображение вставлено"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Сохранение..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Сохранение..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Скриншот сохранен"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Начать запись"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Записать закадровую речь"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Показывать нажатия"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Нажмите, чтобы остановить"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Остановить"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Приостановить"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Возобновить"</string>
@@ -392,15 +394,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Режим энергосбер."</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Вкл. на закате"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"До рассвета"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Включить в <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"До <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"Модуль NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Модуль NFC отключен"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Модуль NFC включен"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Запись экрана"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Начать"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Остановить"</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>
@@ -702,22 +703,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Настроить"</string>
     <string name="notification_done" msgid="6215117625922713976">"Готово"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Отменить"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Понизить приоритет уведомления (не считать чатом)"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Добавить в избранное"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Удалить из избранного"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Отключить звук"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Включить звук"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Показывать как всплывающее уведомление"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Отключить показ всплывающих уведомлений"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Добавить на главный экран"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g>: <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"настройки уведомлений"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"параметры отсрочки уведомлений"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 84e01d0..2c5e1d8 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"තිරය පිරවීමට විශාලනය කරන්න"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"තිරය පිරවීමට අදින්න"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"තිර රුව"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"රූපය ඇතුල් කරන ලදී"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"තිර රුව සුරකිමින්…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"තිර රුව සුරැකෙමින් පවතී…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"තිර රුව සුරකින ලදී"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"පටිගත කිරීම ආරම්භ කරන්න"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"පසුබිම් කථනය පටිගත කරන්න"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"තට්ටු කිරීම් පෙන්වන්න"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"නතර කිරීමට තට්ටු කරන්න"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"නතර කරන්න"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"විරාම කරන්න"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"නැවත අරඹන්න"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"බැටරි සුරැකුම"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"හිරු බැසීමේදී ඔන්ය"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"හිරු නගින තෙක්"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>ට ක්‍රියාත්මකයි"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> තෙක්"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC අබලයි"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC සබලයි"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"තිර පටිගත කිරීම"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ආරම්භ කරන්න"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"නතර කරන්න"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"අභිරුචිකරණය"</string>
     <string name="notification_done" msgid="6215117625922713976">"නිමයි"</string>
     <string name="inline_undo" msgid="9026953267645116526">"පසුගමනය කරන්න"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"මෙම දැනුම් දීම සංවාදයක් නොවේ ලෙස ලකුණු කරන්න"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"ප්‍රියතම"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"ප්‍රියතම වෙතින් ඉවත් කරන්න"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"නිහඬ කරන්න"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"නිහඬ වෙතින් ඉවත් කරන්න"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"බුබුලක් ලෙස පෙන්වන්න"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"බුබුලු ක්‍රියාවිරහිත කරන්න"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"මුල් තිරය වෙත එක් කරන්න"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"දැනුම්දීම් පාලන"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"දැනුම්දීම් මදක් නතර කිරීමේ විකල්ප"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index fced8a4..93f93a2 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Priblížiť na celú obrazovku"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Na celú obrazovku"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Snímka obrazovky"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Bol vložený obrázok"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Prebieha ukladanie snímky obrazovky..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Prebieha ukladanie snímky obrazovky..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Snímka obrazovky bola uložená"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Spustiť zaznamenávanie"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Hlasový vstup počas záznamu"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Zobrazovať klepnutia"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Zastavte klepnutím"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Ukončiť"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pozastaviť"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Obnoviť"</string>
@@ -392,6 +394,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Šetrič batérie"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Zap. pri záp. slnka"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do východu slnka"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Zapne sa o <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC je deaktivované"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC je aktivované"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 4816a66..452827f 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Povečava čez cel zaslon"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Raztegnitev čez zaslon"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Posnetek zaslona"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Slika je vstavljena"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Shranjev. posnetka zaslona ..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Shranjevanje posnetka zaslona ..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Posnetek zaslona je shranjen"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Začni snemanje"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Snemanje spremnega govora"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Prikaz dotikov"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Dotaknite se, da ustavite"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Ustavi"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Začasno ustavi"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Nadaljuj"</string>
@@ -392,15 +394,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Varč. z ener. bater."</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Ob sončnem zahodu"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do sončnega vzhoda"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Vklop ob <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Tehnologija NFC je onemogočena"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Tehnologija NFC je omogočena"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Snemanje zaslona"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Začni"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Ustavi"</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>
@@ -702,22 +703,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Prilagodi"</string>
     <string name="notification_done" msgid="6215117625922713976">"Dokončano"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Razveljavi"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Označi, da to obvestilo ni pogovor"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Priljubljeno"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Odstrani iz priljubljenih"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Prezri"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Znova prikaži"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Pokaži kot oblaček"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Izklopi oblačke"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Dodaj na začetni zaslon"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"kontrolniki obvestil"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"možnosti preložitve obvestil"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 14d72b4..2dc3cc8 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zmadho për të mbushur ekranin"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Shtrije për të mbushur ekranin"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Pamja e ekranit"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Imazhi është futur"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Po ruan pamjen e ekranit..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Po ruan pamjen e ekranit…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Pamja e ekranit u ruajt"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Nis regjistrimin"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Regjistro zërin e mikrofonit"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Shfaq trokitjet"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Trokit për të ndaluar"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Ndalo"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Ndërprit"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Vazhdo"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Kursyesi i baterisë"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Aktiv në perëndim"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Deri në lindje të diellit"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Aktiv në <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Deri në <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC është çaktivizuar"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC është aktivizuar"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Regjistrimi i ekranit"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Nis"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Ndalo"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Personalizo"</string>
     <string name="notification_done" msgid="6215117625922713976">"U krye"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Zhbëj"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Shëno se ky njoftim nuk është një bisedë"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Shëno si të preferuar"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Hiq nga të preferuarat"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Kalo në heshtje"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Aktivizo"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Shfaqe si flluskë"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Çaktivizo flluskat"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Shto në ekranin bazë"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"kontrollet e njoftimit"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"opsionet e shtyrjes së njoftimit"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 29e7e10..4127806 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Зумирај на целом екрану"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Развуци на цео екран"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Снимак екрана"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Слика је уметнута"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Чување снимка екрана..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Чување снимка екрана..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Снимак екрана је сачуван"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Започни снимање"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Сними пренос гласа"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Приказуј додире"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Додирните да бисте зауставили"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Заустави"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Паузирај"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Настави"</string>
@@ -390,6 +392,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Уштеда батерије"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Укључује се по заласку сунца"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"До изласка сунца"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Укључује се у <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"До <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC је онемогућен"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC је омогућен"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index b0d7877..3e29fa6 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zooma för att fylla skärm"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Dra för att fylla skärmen"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Skärmdump"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Bilden har infogats"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Skärmdumpen sparas ..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Skärmdumpen sparas ..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Skärmdumpen har sparats"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Börja spela in"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Spela in med mikrofondubbning"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Visa tryck"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Tryck för att stoppa"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Stoppa"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pausa"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Återuppta"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Batterisparläge"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"På från solnedgången"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Till soluppgången"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Aktivera kl. <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Till <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC är inaktiverat"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC är aktiverat"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index ecaefb0..9fd4284 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Kuza ili kujaza skrini"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Tanua ili kujaza skrini"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Picha ya skrini"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Picha imewekwa"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Inahifadhi picha ya skrini..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Inahifadhi picha ya skrini..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Imehifadhi picha ya skrini"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Anza Kurekodi"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Rekodi sauti"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Onyesha unapogusa"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Gusa ili ukomeshe"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Acha"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Sitisha"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Endelea"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Kiokoa betri"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Itawashwa machweo"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Hadi macheo"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Itawashwa saa <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Hadi saa <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC imezimwa"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC imewashwa"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Rekodi ya Skrini"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Anza kurekodi"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Acha kurekodi"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Weka mapendeleo"</string>
     <string name="notification_done" msgid="6215117625922713976">"Nimemaliza"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Tendua"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Tia alama arifa hii kuwa si mazungumzo"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Tia alama ya kipendwa kwenye mazungumzo haya"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Ondoa alama ya kipendwa kwenye mazungumzo haya"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Komesha mazungumzo"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Ruhusu mazungumzo"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Onyesha kuwa kiputo"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Zima viputo"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Ongeza kwenye skrini ya kwanza"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"vidhibiti vya arifa"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"chaguo za kuahirisha arifa"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 0bea7d6..55bd472 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"திரையை நிரப்ப அளவை மாற்று"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"திரையை நிரப்ப இழு"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ஸ்கிரீன்ஷாட்"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"படம் செருகப்பட்டது"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"ஸ்க்ரீன் ஷாட்டைச் சேமிக்கிறது…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ஸ்க்ரீன் ஷாட்டைச் சேமிக்கிறது…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ஸ்கிரீன்ஷாட் சேமிக்கப்பட்டது"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"ரெக்கார்டிங்கைத் தொடங்கு"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"வாய்ஸ் ஓவரை ரெக்கார்டு செய்"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"தட்டல்களைக் காட்டு"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"நிறுத்த, தட்டவும்"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"நிறுத்து"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"இடைநிறுத்து"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"மீண்டும் தொடங்கு"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"பேட்டரி சேமிப்பான்"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"மாலையில் ஆன் செய்"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"காலை வரை"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>க்கு ஆன் செய்"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> வரை"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC முடக்கப்பட்டது"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC இயக்கப்பட்டது"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ஸ்கிரீன் ரெக்கார்டு"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"தொடங்கு"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"நிறுத்து"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"தனிப்பயனாக்கு"</string>
     <string name="notification_done" msgid="6215117625922713976">"முடிந்தது"</string>
     <string name="inline_undo" msgid="9026953267645116526">"செயல்தவிர்"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"இந்த அறிவிப்பை உரையாடல் அல்லாததாகக் குறிக்கவும்"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"பிடித்தது"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"பிடித்ததிலிருந்து அகற்று"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"அறிவிப்பைக் காட்டாதே"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"அறிவிப்பைக் காட்டு"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"குமிழாகக் காட்டு"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"குமிழ்களை ஆஃப் செய்"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"முகப்புத் திரையில் சேர்"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"அறிவிப்புக் கட்டுப்பாடுகள்"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"அறிவிப்பை உறக்கநிலையாக்கும் விருப்பங்கள்"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index bb62490..8b9c07c 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"స్క్రీన్‌కు నింపేలా జూమ్ చేయండి"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"స్క్రీన్‌కు నింపేలా విస్తరించండి"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"స్క్రీన్‌షాట్"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"చిత్రం చొప్పించబడింది"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"స్క్రీన్‌షాట్‌ను సేవ్ చేస్తోంది…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"స్క్రీన్‌షాట్‌ను సేవ్ చేస్తోంది…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"స్క్రీన్‌షాట్ సేవ్ చేయబడింది"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"రికార్డింగ్‌ను ప్రారంభించు"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"వాయిస్ఓవర్‌ని రికార్డ్ చేయి"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"నొక్కినవి చూపు"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"ఆపడానికి నొక్కండి"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"ఆపివేయి"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"పాజ్ చేయి"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"కొనసాగించు"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"బ్యాటరీ సేవర్"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"సూర్యాస్తమయానికి"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"సూర్యోదయం వరకు"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> వద్ద"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> వరకు"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC నిలిపివేయబడింది"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ప్రారంభించబడింది"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"స్క్రీన్ రికార్డ్"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ప్రారంభించు"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ఆపు"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"అనుకూలపరచండి"</string>
     <string name="notification_done" msgid="6215117625922713976">"పూర్తయింది"</string>
     <string name="inline_undo" msgid="9026953267645116526">"చర్యరద్దు చేయి"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"ఈ నోటిఫికేషన్‌ను సంభాషణ కానిది అని గుర్తు పెట్టండి"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"ఇష్టమైనది"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"ఇష్టమైనదిగా పెట్టిన గుర్తును తీసివేయి"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"మ్యూట్ చేయి"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"అన్‌మ్యూట్ చేయి"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"బబుల్‌లా చూపించు"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"బబుల్‌లను ఆఫ్ చేయి"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"హోమ్ స్క్రీన్‌కు జోడించు"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"నోటిఫికేషన్ నియంత్రణలు"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"నోటిఫికేషన్ తాత్కాలిక ఆపివేత ఎంపికలు"</string>
diff --git a/packages/SystemUI/res/values-television/config.xml b/packages/SystemUI/res/values-television/config.xml
index 4cc5a67..dd4c321 100644
--- a/packages/SystemUI/res/values-television/config.xml
+++ b/packages/SystemUI/res/values-television/config.xml
@@ -36,5 +36,6 @@
         <item>com.android.systemui.SliceBroadcastRelayHandler</item>
         <item>com.android.systemui.SizeCompatModeActivityController</item>
         <item>com.android.systemui.statusbar.notification.InstantAppNotifier</item>
+        <item>com.android.systemui.toast.ToastUI</item>
     </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 54c3d73..c5e0123 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"ขยายจนเต็มหน้าจอ"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"ยืดจนเต็มหน้าจอ"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ภาพหน้าจอ"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"รูปภาพที่แทรก"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"กำลังบันทึกภาพหน้าจอ..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"กำลังบันทึกภาพหน้าจอ..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"บันทึกภาพหน้าจอแล้ว"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"เริ่มต้นการบันทึก"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"บันทึกเสียงบรรยาย"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"แสดงการแตะ"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"แตะเพื่อหยุด"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"หยุด"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"หยุด"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"ทำต่อ"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"โหมดประหยัดแบตเตอรี่"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"เปิดตอนพระอาทิตย์ตก"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"จนพระอาทิตย์ขึ้น"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"เปิดเวลา <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"จนถึง <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ถูกปิดใช้งาน"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"เปิดใช้งาน NFC แล้ว"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"บันทึกหน้าจอ"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"เริ่ม"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"หยุด"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"ปรับแต่ง"</string>
     <string name="notification_done" msgid="6215117625922713976">"เสร็จสิ้น"</string>
     <string name="inline_undo" msgid="9026953267645116526">"เลิกทำ"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"ทำเครื่องหมายการแจ้งเตือนนี้ว่าไม่ใช่บทสนทนา"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"รายการโปรด"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"นำออกจากรายการโปรด"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"ปิดเสียง"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"เปิดเสียง"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"แสดงเป็นบับเบิล"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"ปิดบับเบิล"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"เพิ่มลงในหน้าจอหลัก"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"ส่วนควบคุมการแจ้งเตือน"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"ตัวเลือกการปิดเสียงแจ้งเตือนชั่วคราว"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index ef812ff..3d343c5 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"I-zoom upang punan screen"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"I-stretch upang mapuno screen"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Inilagay ang larawan"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Sine-save ang screenshot…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Sine-save ang screenshot…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Na-save ang screenshot"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Simulan ang Pag-record"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"I-record ang voiceover"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Ipakita ang mga pag-tap"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"I-tap para ihinto"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Ihinto"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"I-pause"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Ituloy"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Pangtipid sa Baterya"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Mao-on sa sunset"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Hanggang sunrise"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Ma-o-on nang <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Hanggang <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Naka-disable ang NFC"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Naka-enable ang NFC"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Pag-record ng Screen"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Magsimula"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Ihinto"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"I-customize"</string>
     <string name="notification_done" msgid="6215117625922713976">"Tapos Na"</string>
     <string name="inline_undo" msgid="9026953267645116526">"I-undo"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Markahan ang notification na ito bilang hindi pag-uusap"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Gawing Paborito"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"I-unfavorite"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"I-mute"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"I-unmute"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Ipakita bilang bubble"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"I-off ang mga bubble"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Idagdag sa home screen"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"mga kontrol ng notification"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"mga opsyon sa pag-snooze ng notification"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 470606f..46e583f 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Yakınlaştır (ekranı kaplasın)"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Genişlet (ekran kapansın)"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Ekran görüntüsü"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Resim eklendi"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Ekran görüntüsü kaydediliyor..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Ekran görüntüsü kaydediliyor..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Ekran görüntüsü kaydedildi"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Kaydı Başlat"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Seslendirme kaydet"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Dokunmaları göster"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Durdurmak için dokunun"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Durdur"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Duraklat"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Devam ettir"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Pil Tasarrufu"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Gün batımı açılacak"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Sabaha kadar"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Açılacağı saat: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Şu saate kadar: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC devre dışı"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC etkin"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Ekran Kaydı"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Başlat"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Durdur"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Özelleştir"</string>
     <string name="notification_done" msgid="6215117625922713976">"Bitti"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Geri al"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Bu bildirimi ileti dizisi değil olarak işaretle"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Favori"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Favorilerden kaldır"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Kapat"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Aç"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Balon olarak göster"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Balonları kapat"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Ana ekrana ekle"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"Bildirim kontrolleri"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"bildirim erteleme seçenekleri"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 496206a..7baad0d 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Масштабув. на весь екран"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Розтягнути на весь екран"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Знімок екрана"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Вставлене зображення"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Збереження знімка екрана..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Збереження знімка екрана..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Знімок екрана збережено"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Почати запис"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Записувати голосовий супровід"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Показувати дотики"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Натисніть, щоб зупинити"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Зупинити"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Призупинити"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Відновити"</string>
@@ -392,15 +394,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Режим енергозбереження"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Увімкнеться ввечері"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"До сходу сонця"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Вмикається о <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"До <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC вимкнено"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ввімкнено"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Запис екрана"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Почати"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Зупинити"</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>
@@ -702,22 +703,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Налаштувати"</string>
     <string name="notification_done" msgid="6215117625922713976">"Готово"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Відмінити"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Перетворити з ланцюжка повідомлень на сповіщення"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Вибране"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Видалити з вибраного"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Ігнорувати"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Не ігнорувати"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Показувати як спливаюче сповіщення"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Вимкнути спливаючі сповіщення"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Додати на головний екран"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"елементи керування сповіщеннями"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"параметри відкладення сповіщень"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index a6de509..97d0a5d 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"پوری سکرین پر زوم کریں"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"پوری سکرین پر پھیلائیں"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"اسکرین شاٹ"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"تصویر داخل کر دی گئی"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"اسکرین شاٹ محفوظ ہو رہا ہے…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"اسکرین شاٹ محفوظ ہو رہا ہے…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"اسکرین شاٹ محفوظ ہو گیا"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"ریکارڈنگ شروع کریں"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"وائس اوور ریکارڈ کریں"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"تھپتھپاہٹیں دکھائیں"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"روکنے کے لیے تھپتھپائیں"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"روکیں"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"موقوف کریں"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"دوبارہ شروع کریں"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"بیٹری سیور"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"شام کے وقت آن ہوگی"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"طلوع آفتاب تک"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"آن ہوگی بوقت <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> تک"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"‏NFC غیر فعال ہے"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"‏NFC فعال ہے"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"اسکرین ریکارڈر کریں"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"آغاز"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"روکیں"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"حسب ضرورت بنائیں"</string>
     <string name="notification_done" msgid="6215117625922713976">"ہوگیا"</string>
     <string name="inline_undo" msgid="9026953267645116526">"کالعدم کریں"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"اس اطلاع کو بطور گفتگو نشان زد نہ کریں"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"پسندیدہ"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"پسندیدگی ختم کریں"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"خاموش کریں"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"آواز چلائیں"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"بلبلہ کے بطور دکھائیں"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"بلبلے آف کریں"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"ہوم اسکرین میں شامل کریں"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"اطلاع کے کنٹرولز"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"اطلاع اسنوز کرنے کے اختیارات"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 1eb02f3..b514f1e 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Ekranga moslashtirish"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Ekran hajmida cho‘zish"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Skrinshot"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Rasm joylandi"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Skrinshot saqlanmoqda…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Skrinshot saqlanmoqda…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Skrinshot saqlandi"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Yozuvni boshlash"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Kadrorti nutqini yozib olish"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Bosishlarni ko‘rsatish"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Toʻxtatish uchun bosing"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"To‘xtatish"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pauza"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Davom etish"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Quvvat tejash"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Kunbotarda yoqish"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Quyosh chiqqunicha"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> da yoqish"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> gacha"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC o‘chiq"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC yoniq"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index dc3882e..c4d7618 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"T.phóng để lấp đầy m.hình"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Giãn ra để lấp đầy m.hình"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Chụp ảnh màn hình"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Đã chèn hình ảnh"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Đang lưu ảnh chụp màn hình..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Đang lưu ảnh chụp màn hình..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Đã lưu ảnh chụp màn hình"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Bắt đầu ghi"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Ghi phần thuyết minh"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Hiển thị số lần nhấn"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Nhấn để dừng"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Dừng"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Tạm dừng"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Tiếp tục"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Trình tiết kiệm pin"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Bật khi trời tối"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Cho đến khi trời sáng"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Bật vào lúc <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Cho đến <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC đã được tắt"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC đã được bật"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Ghi lại nội dung trên màn hình"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Bắt đầu"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Dừng"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Tùy chỉnh"</string>
     <string name="notification_done" msgid="6215117625922713976">"Xong"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Hoàn tác"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Đánh dấu thông báo này không phải là cuộc trò chuyện"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Đánh dấu là yêu thích"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Bỏ thích"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Ẩn"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Hiển thị"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Hiển thị dưới dạng bong bóng"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Tắt bong bóng"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Thêm vào màn hình chính"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"điều khiển thông báo"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"Tùy chọn báo lại thông báo"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index baacdae..56edb64 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"缩放以填满屏幕"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"拉伸以填满屏幕"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"屏幕截图"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"已插入图片"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"正在保存屏幕截图..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"正在保存屏幕截图..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"已保存屏幕截图"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"开始录制"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"录制旁白"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"显示点按操作反馈"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"点按即可停止"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"停止"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"暂停"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"继续"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"省电模式"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"在日落时开启"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"在日出时关闭"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"在<xliff:g id="TIME">%s</xliff:g> 开启"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"直到<xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC 已停用"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC 已启用"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"屏幕录制"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"开始"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"停止"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"自定义"</string>
     <string name="notification_done" msgid="6215117625922713976">"完成"</string>
     <string name="inline_undo" msgid="9026953267645116526">"撤消"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"将此通知标记为非对话"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"收藏"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"取消收藏"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"静音"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"取消静音"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"显示为气泡"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"关闭气泡"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"添加到主屏幕"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g><xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"通知设置"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"通知延后选项"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 0f1696e7..251e23d 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"放大為全螢幕"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"放大為全螢幕"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"螢幕截圖"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"已插入圖片"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"正在儲存螢幕擷取畫面..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"正在儲存螢幕擷取畫面..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"螢幕擷取畫面已儲存"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"開始錄影"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"錄製畫面外的音效"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"顯示輕按選項"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"輕按即可停止"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"停止"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"暫停"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"繼續"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"省電模式"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"在日落時開啟"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"在日出時關閉"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"於<xliff:g id="TIME">%s</xliff:g>開啟"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"直至<xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC 已停用"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC 已啟用"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"畫面錄影"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"開始"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"停"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"自訂"</string>
     <string name="notification_done" msgid="6215117625922713976">"完成"</string>
     <string name="inline_undo" msgid="9026953267645116526">"復原"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"將此通知標示為非對話"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"我的最愛"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"取消收藏"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"靜音"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"取消靜音"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"以小視窗顯示"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"關閉小視窗"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"加入主畫面"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"通知控制項"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"通知延後選項"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index e8e76ec..a7ec598 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"放大為全螢幕"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"放大為全螢幕"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"擷取螢幕畫面"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"已插入圖片"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"正在儲存螢幕截圖…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"正在儲存螢幕截圖…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"螢幕截圖已儲存"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"開始錄製"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"錄製畫面外的音效"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"顯示觸控回應"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"輕觸即可停止"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"停止"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"暫停"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"繼續"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"節約耗電量"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"於日落時開啟"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"於日出時關閉"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"開啟時間:<xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"關閉時間:<xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC 已停用"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC 已啟用"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"螢幕畫面錄製"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"開始"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"停止"</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>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"自訂"</string>
     <string name="notification_done" msgid="6215117625922713976">"完成"</string>
     <string name="inline_undo" msgid="9026953267645116526">"復原"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"將這則通知標示為非對話"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"加入收藏"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"從收藏中移除"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"忽略"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"取消忽略"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"以泡泡形式顯示"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"關閉泡泡"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"新增至主螢幕"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"通知控制項"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"通知延後選項"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index fa764b5..1203b579c 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Sondeza ukugcwalisa isikrini"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Nweba ukugcwalisa isikrini"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Isithombe-skrini"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Isithombe sifakiwe"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Ilondoloz umfanekiso weskrini..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Ilondoloz umfanekiso weskrini..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Isithombe-skrini silondoloziwe"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Qala ukurekhoda"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Rekhoda izwi elingaphezulu"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Bonisa amathebhu"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Thepha ukuze umise"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Misa"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Phumula"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Qalisa kabusha"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Isilondolozi sebhethri"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Kuvulwe ekushoneni kwelanga"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Kuze kube sekuphumeni kwelanga"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Kuvulwe ngo-<xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Kuze kube ngu-<xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"I-NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"I-NFC ikhutshaziwe"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"I-NFC inikwe amandla"</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 8dd2a8b..09058f2 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -200,18 +200,28 @@
     <color name="GM2_grey_800">#3C4043</color>
     <color name="GM2_grey_900">#202124</color>
 
+    <color name="GM2_red_50">#FCE8E6</color>
     <color name="GM2_red_300">#F28B82</color>
     <color name="GM2_red_500">#B71C1C</color>
     <color name="GM2_red_700">#C5221F</color>
 
+    <color name="GM2_blue_50">#E8F0FE</color>
     <color name="GM2_blue_200">#AECBFA</color>
     <color name="GM2_blue_300">#8AB4F8</color>
+    <color name="GM2_blue_500">#FF4285F4</color>
     <color name="GM2_blue_600">#1A73E8</color>
     <color name="GM2_blue_700">#1967D2</color>
 
+    <color name="GM2_yellow_50">#FEF7E0</color>
     <color name="GM2_yellow_500">#FFFBBC04</color>
+
     <color name="GM2_green_500">#FF34A853</color>
-    <color name="GM2_blue_500">#FF4285F4</color>
+
+    <color name="GM2_orange_900">#B06000</color>
 
     <color name="magnification_border_color">#FF9900</color>
+
+    <!-- controls -->
+    <color name="control_default_foreground">?android:attr/textColorPrimary</color>
+    <color name="control_default_background">?android:attr/colorBackgroundFloating</color>
 </resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index e520106..2aa6d95 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -296,6 +296,8 @@
         <item>com.android.systemui.statusbar.notification.InstantAppNotifier</item>
         <item>com.android.systemui.theme.ThemeOverlayController</item>
         <item>com.android.systemui.accessibility.WindowMagnification</item>
+        <item>com.android.systemui.accessibility.SystemActions</item>
+        <item>com.android.systemui.toast.ToastUI</item>
     </string-array>
 
     <!-- SystemUI vender service, used in config_systemUIServiceComponents. -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 65ca9f2..cc58b20 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -96,6 +96,9 @@
     <!-- Spacing before the airplane mode icon if there are any icons preceding it. -->
     <dimen name="status_bar_airplane_spacer_width">4dp</dimen>
 
+    <!-- Spacing between system icons. -->
+    <dimen name="status_bar_system_icon_spacing">0dp</dimen>
+
     <!-- The amount to scale each of the status bar icons by. A value of 1 means no scaling. -->
     <item name="status_bar_icon_scale_factor" format="float" type="dimen">1.0</item>
 
@@ -1178,5 +1181,12 @@
     <dimen name="magnifier_up_down_controls_width">45dp</dimen>
     <dimen name="magnifier_up_down_controls_height">40dp</dimen>
 
+    <!-- Home Controls -->
+    <dimen name="control_spacing">5dp</dimen>
+    <dimen name="control_corner_radius">15dp</dimen>
+    <dimen name="control_height">100dp</dimen>
+    <dimen name="control_padding">15dp</dimen>
+    <dimen name="control_status_normal">12dp</dimen>
+    <dimen name="control_status_expanded">18dp</dimen>
     <dimen name="app_icon_size">32dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/integers.xml b/packages/SystemUI/res/values/integers.xml
index c1cf7b4..4171cd9 100644
--- a/packages/SystemUI/res/values/integers.xml
+++ b/packages/SystemUI/res/values/integers.xml
@@ -27,6 +27,12 @@
          performance issues arise. -->
     <integer name="bubbles_max_rendered">5</integer>
 
+    <!-- Number of columns in bubble overflow. -->
+    <integer name="bubbles_overflow_columns">4</integer>
+
+    <!-- Maximum number of bubbles we allow in overflow before we dismiss the oldest one. -->
+    <integer name="bubbles_max_overflow">16</integer>
+
     <!-- Ratio of "left" end of status bar that will swipe to QQS. -->
     <integer name="qqs_split_fraction">3</integer>
     <!-- Ratio of "right" end of status bar that will swipe to QS. -->
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 44a7fda..8d935ec 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2546,4 +2546,10 @@
     <string name="magnification_window_title">Magnification Window</string>
     <!-- Title for Magnification Controls Window [CHAR LIMIT=NONE] -->
     <string name="magnification_controls_title">Magnification Window Controls</string>
+
+    <!-- Quick Controls strings [CHAR LIMIT=30] -->
+    <string name="quick_controls_title">Quick Controls</string>
+
+    <!-- The tile in quick settings is unavailable. [CHAR LIMIT=32] -->
+    <string name="tile_unavailable">Unvailable</string>
 </resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 3ff8243..10f59a4 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -43,7 +43,7 @@
         <item name="android:windowIsTranslucent">true</item>
         <item name="android:windowNoTitle">true</item>
         <item name="android:windowContentOverlay">@null</item>
-        <item name="android:windowBackground">@null</item>
+        <item name="android:windowBackground">@android:color/transparent</item>
         <item name="android:colorBackgroundCacheHint">@null</item>
         <item name="android:statusBarColor">@*android:color/transparent</item>
         <item name="android:windowAnimationStyle">@style/Animation.PipPhoneOverlayControl</item>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
index 577e3bb..26ef1d6 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
@@ -27,7 +27,6 @@
 
     void onInitialize(in Bundle params) = 12;
 
-
     /**
      * @deprecated
      */
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
index 1cabee1..2d288ff 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
@@ -16,12 +16,15 @@
 
 package com.android.systemui.shared.recents;
 
+import android.graphics.Bitmap;
+import android.graphics.Insets;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.view.MotionEvent;
 
 /**
  * Temporary callbacks into SystemUI.
+ * Next id = 22
  */
 interface ISystemUiProxy {
 
@@ -114,4 +117,10 @@
      * Sets the shelf height and visibility.
      */
     void setShelfHeight(boolean visible, int shelfHeight) = 20;
+
+    /**
+     * Handle the provided image as if it was a screenshot.
+     */
+     void handleImageAsScreenshot(in Bitmap screenImage, in Rect locationInScreen,
+              in Insets visibleInsets, int taskId) = 21;
 }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
index 98b7e24..44a8d3c 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.shared.recents.model;
 
+import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
 import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
 
 import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_UNDEFINED;
@@ -31,6 +32,7 @@
 
     public final Bitmap thumbnail;
     public int orientation;
+    public int rotation;
     public Rect insets;
     public boolean reducedResolution;
     public boolean isRealSnapshot;
@@ -43,6 +45,7 @@
     public ThumbnailData() {
         thumbnail = null;
         orientation = ORIENTATION_UNDEFINED;
+        rotation = ROTATION_UNDEFINED;
         insets = new Rect();
         reducedResolution = false;
         scale = 1f;
@@ -57,6 +60,7 @@
         thumbnail = Bitmap.wrapHardwareBuffer(snapshot.getSnapshot(), snapshot.getColorSpace());
         insets = new Rect(snapshot.getContentInsets());
         orientation = snapshot.getOrientation();
+        rotation = snapshot.getRotation();
         reducedResolution = snapshot.isReducedResolution();
         scale = snapshot.getScale();
         isRealSnapshot = snapshot.isRealSnapshot();
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
index 08996c3..386fe53 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
@@ -85,6 +85,8 @@
     // The notification panel is expanded and interactive (either locked or unlocked), and the
     // quick settings is not expanded
     public static final int SYSUI_STATE_QUICK_SETTINGS_EXPANDED = 1 << 11;
+    // Winscope tracing is enabled
+    public static final int SYSUI_STATE_TRACING_ENABLED = 1 << 12;
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({SYSUI_STATE_SCREEN_PINNING,
@@ -98,7 +100,8 @@
             SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED,
             SYSUI_STATE_OVERVIEW_DISABLED,
             SYSUI_STATE_HOME_DISABLED,
-            SYSUI_STATE_SEARCH_DISABLED
+            SYSUI_STATE_SEARCH_DISABLED,
+            SYSUI_STATE_TRACING_ENABLED
     })
     public @interface SystemUiStateFlags {}
 
@@ -117,6 +120,7 @@
         str.add((flags & SYSUI_STATE_BOUNCER_SHOWING) != 0 ? "bouncer_visible" : "");
         str.add((flags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0 ? "a11y_click" : "");
         str.add((flags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0 ? "a11y_long_click" : "");
+        str.add((flags & SYSUI_STATE_TRACING_ENABLED) != 0 ? "tracing" : "");
         return str.toString();
     }
 
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/tracing/FrameProtoTracer.java b/packages/SystemUI/shared/src/com/android/systemui/shared/tracing/FrameProtoTracer.java
new file mode 100644
index 0000000..557845c
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/tracing/FrameProtoTracer.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shared.tracing;
+
+import android.os.Trace;
+import android.util.Log;
+import android.view.Choreographer;
+
+import com.android.internal.util.TraceBuffer;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.Queue;
+import java.util.function.Consumer;
+
+/**
+ * A proto tracer implementation that can be updated directly (upon state change), or on the next
+ * scheduled frame.
+ *
+ * @param <P> The class type of the proto provider
+ * @param <S> The proto class type of the encapsulating proto
+ * @param <T> The proto class type of the individual proto entries in the buffer
+ * @param <R> The proto class type of the entry root proto in the buffer
+ */
+public class FrameProtoTracer<P, S extends P, T extends P, R>
+        implements TraceBuffer.ProtoProvider<P, S, T>, Choreographer.FrameCallback {
+
+    private static final String TAG = "FrameProtoTracer";
+    private static final int BUFFER_CAPACITY = 1024 * 1024;
+
+    private final Object mLock = new Object();
+    private final TraceBuffer<P, S, T> mBuffer;
+    private final File mTraceFile;
+    private final ProtoTraceParams<P, S, T, R> mParams;
+    private final Choreographer mChoreographer;
+    private final Queue<T> mPool = new LinkedList<>();
+    private final ArrayList<ProtoTraceable<R>> mTraceables = new ArrayList<>();
+    private final ArrayList<ProtoTraceable<R>> mTmpTraceables = new ArrayList<>();
+
+    private volatile boolean mEnabled;
+    private boolean mFrameScheduled;
+
+    public interface ProtoTraceParams<P, S, T, R> {
+        File getTraceFile();
+        S getEncapsulatingTraceProto();
+        T updateBufferProto(T reuseObj, ArrayList<ProtoTraceable<R>> traceables);
+        byte[] serializeEncapsulatingProto(S encapsulatingProto, Queue<T> buffer);
+        byte[] getProtoBytes(P proto);
+        int getProtoSize(P proto);
+    }
+
+    public FrameProtoTracer(ProtoTraceParams<P, S, T, R> params) {
+        mParams = params;
+        mBuffer = new TraceBuffer<>(BUFFER_CAPACITY, this, new Consumer<T>() {
+            @Override
+            public void accept(T t) {
+                onProtoDequeued(t);
+            }
+        });
+        mTraceFile = params.getTraceFile();
+        mChoreographer = Choreographer.getMainThreadInstance();
+    }
+
+    @Override
+    public int getItemSize(P proto) {
+        return mParams.getProtoSize(proto);
+    }
+
+    @Override
+    public byte[] getBytes(P proto) {
+        return mParams.getProtoBytes(proto);
+    }
+
+    @Override
+    public void write(S encapsulatingProto, Queue<T> buffer, OutputStream os) throws IOException {
+        os.write(mParams.serializeEncapsulatingProto(encapsulatingProto, buffer));
+    }
+
+    public void start() {
+        synchronized (mLock) {
+            if (mEnabled) {
+                return;
+            }
+            mBuffer.resetBuffer();
+            mEnabled = true;
+        }
+        logState();
+    }
+
+    public void stop() {
+        synchronized (mLock) {
+            if (!mEnabled) {
+                return;
+            }
+            mEnabled = false;
+        }
+        writeToFile();
+    }
+
+    public boolean isEnabled() {
+        return mEnabled;
+    }
+
+    public void add(ProtoTraceable<R> traceable) {
+        synchronized (mLock) {
+            mTraceables.add(traceable);
+        }
+    }
+
+    public void remove(ProtoTraceable<R> traceable) {
+        synchronized (mLock) {
+            mTraceables.remove(traceable);
+        }
+    }
+
+    public void scheduleFrameUpdate() {
+        if (!mEnabled || mFrameScheduled) {
+            return;
+        }
+
+        // Schedule an update on the next frame
+        mChoreographer.postFrameCallback(this);
+        mFrameScheduled = true;
+    }
+
+    public void update() {
+        if (!mEnabled) {
+            return;
+        }
+
+        logState();
+    }
+
+    public float getBufferUsagePct() {
+        return (float) mBuffer.getBufferSize() / BUFFER_CAPACITY;
+    }
+
+    @Override
+    public void doFrame(long frameTimeNanos) {
+        logState();
+    }
+
+    private void onProtoDequeued(T proto) {
+        mPool.add(proto);
+    }
+
+    private void logState() {
+        synchronized (mLock) {
+            mTmpTraceables.addAll(mTraceables);
+        }
+
+        mBuffer.add(mParams.updateBufferProto(mPool.poll(), mTmpTraceables));
+        mTmpTraceables.clear();
+        mFrameScheduled = false;
+    }
+
+    private void writeToFile() {
+        try {
+            Trace.beginSection("ProtoTracer.writeToFile");
+            mBuffer.writeTraceToFile(mTraceFile, mParams.getEncapsulatingTraceProto());
+        } catch (IOException e) {
+            Log.e(TAG, "Unable to write buffer to file", e);
+        } finally {
+            Trace.endSection();
+        }
+    }
+}
+
+
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/tracing/ProtoTraceable.java b/packages/SystemUI/shared/src/com/android/systemui/shared/tracing/ProtoTraceable.java
new file mode 100644
index 0000000..e05b0b0
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/tracing/ProtoTraceable.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.shared.tracing;
+
+/**
+ * @see FrameProtoTracer
+ */
+public interface ProtoTraceable<T> {
+
+    /**
+     * NOTE: Implementations should update all fields in this proto.
+     */
+    void writeToProto(T proto);
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index f51cd83..58a6c17 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -92,7 +92,6 @@
 import android.util.SparseBooleanArray;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.settingslib.WirelessUtils;
 import com.android.systemui.DejankUtils;
@@ -1083,7 +1082,7 @@
                         MSG_BATTERY_UPDATE, new BatteryStatus(status, level, plugged, health,
                                 maxChargingMicroWatt));
                 mHandler.sendMessage(msg);
-            } else if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) {
+            } else if (Intent.ACTION_SIM_STATE_CHANGED.equals(action)) {
                 SimData args = SimData.fromIntent(intent);
                 // ACTION_SIM_STATE_CHANGED is rebroadcast after unlocking the device to
                 // keep compatibility with apps that aren't direct boot aware.
@@ -1122,7 +1121,7 @@
                 }
                 mHandler.sendMessage(
                         mHandler.obtainMessage(MSG_SERVICE_STATE_CHANGE, subId, 0, serviceState));
-            } else if (TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED.equals(action)) {
+            } else if (TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED.equals(action)) {
                 mHandler.sendEmptyMessage(MSG_SIM_SUBSCRIPTION_INFO_CHANGED);
             } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(
                     action)) {
@@ -1273,7 +1272,7 @@
 
         static SimData fromIntent(Intent intent) {
             int state;
-            if (!TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) {
+            if (!Intent.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) {
                 throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED");
             }
             String stateExtra = intent.getStringExtra(Intent.EXTRA_SIM_STATE);
@@ -1673,7 +1672,7 @@
         filter.addAction(Intent.ACTION_BATTERY_CHANGED);
         filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
         filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
-        filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+        filter.addAction(Intent.ACTION_SIM_STATE_CHANGED);
         filter.addAction(Intent.ACTION_SERVICE_STATE);
         filter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
         filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index aacc2c4..a6be091 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -117,6 +117,7 @@
 import com.android.systemui.statusbar.policy.UserInfoController;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.tracing.ProtoTracer;
 import com.android.systemui.tuner.TunablePadding.TunablePaddingService;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.util.leak.GarbageMonitor;
@@ -327,6 +328,7 @@
     @Inject Lazy<SystemWindows> mSystemWindows;
     @Inject Lazy<DisplayImeController> mDisplayImeController;
     @Inject Lazy<RecordingController> mRecordingController;
+    @Inject Lazy<ProtoTracer> mProtoTracer;
 
     @Inject
     public Dependency() {
@@ -519,6 +521,7 @@
         mProviders.put(DisplayWindowController.class, mDisplayWindowController::get);
         mProviders.put(SystemWindows.class, mSystemWindows::get);
         mProviders.put(DisplayImeController.class, mDisplayImeController::get);
+        mProviders.put(ProtoTracer.class, mProtoTracer::get);
 
         // TODO(b/118592525): to support multi-display , we start to add something which is
         //                    per-display, while others may be global. I think it's time to add
diff --git a/packages/SystemUI/src/com/android/systemui/DumpController.kt b/packages/SystemUI/src/com/android/systemui/DumpController.kt
index f14c4cd..7a83a89 100644
--- a/packages/SystemUI/src/com/android/systemui/DumpController.kt
+++ b/packages/SystemUI/src/com/android/systemui/DumpController.kt
@@ -19,10 +19,10 @@
 import android.util.ArraySet
 import android.util.Log
 import androidx.annotation.GuardedBy
-import com.android.internal.util.Preconditions
 import java.io.FileDescriptor
 import java.io.PrintWriter
 import java.lang.ref.WeakReference
+import java.util.Objects.requireNonNull
 import javax.inject.Inject
 import javax.inject.Singleton
 
@@ -58,7 +58,7 @@
      * @param dumpable the [Dumpable] to be added
      */
     fun registerDumpable(dumpable: Dumpable) {
-        Preconditions.checkNotNull(dumpable, "The dumpable to be added cannot be null")
+        requireNonNull(dumpable, "The dumpable to be added cannot be null")
         registerDumpable(dumpable.javaClass.simpleName, dumpable)
     }
 
@@ -71,7 +71,7 @@
      * @param dumpable the [Dumpable] to be added
      */
     fun registerDumpable(tag: String, dumpable: Dumpable) {
-        Preconditions.checkNotNull(dumpable, "The dumpable to be added cannot be null")
+        requireNonNull(dumpable, "The dumpable to be added cannot be null")
         if (DEBUG) Log.v(TAG, "*** register callback for $dumpable")
         synchronized<Unit>(listeners) {
             if (listeners.any { it.tag == tag }) {
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
new file mode 100644
index 0000000..7262f8c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
@@ -0,0 +1,393 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.accessibility;
+
+import android.accessibilityservice.AccessibilityService;
+import android.app.PendingIntent;
+import android.app.RemoteAction;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.drawable.Icon;
+import android.hardware.input.InputManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.Log;
+import android.view.Display;
+import android.view.IWindowManager;
+import android.view.InputDevice;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
+import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
+import android.view.accessibility.AccessibilityManager;
+
+import com.android.internal.R;
+import com.android.internal.util.ScreenshotHelper;
+import com.android.systemui.Dependency;
+import com.android.systemui.SystemUI;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.statusbar.phone.StatusBar;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Class to register system actions with accessibility framework.
+ */
+@Singleton
+public class SystemActions extends SystemUI {
+    private static final String TAG = "SystemActions";
+    // TODO(b/147916452): add implementation on launcher side to register this action.
+
+    /**
+     * Action ID to go back.
+     */
+    private static final int SYSTEM_ACTION_ID_BACK = AccessibilityService.GLOBAL_ACTION_BACK; // = 1
+
+    /**
+     * Action ID to go home.
+     */
+    private static final int SYSTEM_ACTION_ID_HOME = AccessibilityService.GLOBAL_ACTION_HOME; // = 2
+
+    /**
+     * Action ID to toggle showing the overview of recent apps. Will fail on platforms that don't
+     * show recent apps.
+     */
+    private static final int SYSTEM_ACTION_ID_RECENTS =
+            AccessibilityService.GLOBAL_ACTION_RECENTS; // = 3
+
+    /**
+     * Action ID to open the notifications.
+     */
+    private static final int SYSTEM_ACTION_ID_NOTIFICATIONS =
+            AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS; // = 4
+
+    /**
+     * Action ID to open the quick settings.
+     */
+    private static final int SYSTEM_ACTION_ID_QUICK_SETTINGS =
+            AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS; // = 5
+
+    /**
+     * Action ID to open the power long-press dialog.
+     */
+    private static final int SYSTEM_ACTION_ID_POWER_DIALOG =
+            AccessibilityService.GLOBAL_ACTION_POWER_DIALOG; // = 6
+
+    /**
+     * Action ID to toggle docking the current app's window
+     */
+    private static final int SYSTEM_ACTION_ID_TOGGLE_SPLIT_SCREEN =
+            AccessibilityService.GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN; // = 7
+
+    /**
+     * Action ID to lock the screen
+     */
+    private static final int SYSTEM_ACTION_ID_LOCK_SCREEN =
+            AccessibilityService.GLOBAL_ACTION_LOCK_SCREEN; // = 8
+
+    /**
+     * Action ID to take a screenshot
+     */
+    private static final int SYSTEM_ACTION_ID_TAKE_SCREENSHOT =
+            AccessibilityService.GLOBAL_ACTION_TAKE_SCREENSHOT; // = 9
+
+    /**
+     * Action ID to show accessibility menu
+     */
+    private static final int SYSTEM_ACTION_ID_ACCESSIBILITY_MENU = 10;
+
+    private Recents mRecents;
+    private StatusBar mStatusBar;
+    private SystemActionsBroadcastReceiver mReceiver;
+
+    @Inject
+    public SystemActions(Context context) {
+        super(context);
+        mRecents = Dependency.get(Recents.class);
+        mStatusBar = Dependency.get(StatusBar.class);
+        mReceiver = new SystemActionsBroadcastReceiver();
+    }
+
+    @Override
+    public void start() {
+        mContext.registerReceiverForAllUsers(mReceiver, mReceiver.createIntentFilter(), null, null);
+
+        // TODO(b/148087487): update the icon used below to a valid one
+        RemoteAction actionBack = new RemoteAction(
+                Icon.createWithResource(mContext, R.drawable.ic_info),
+                mContext.getString(R.string.accessibility_system_action_back_label),
+                mContext.getString(R.string.accessibility_system_action_back_label),
+                mReceiver.createPendingIntent(
+                        mContext, SystemActionsBroadcastReceiver.INTENT_ACTION_BACK));
+        RemoteAction actionHome = new RemoteAction(
+                Icon.createWithResource(mContext, R.drawable.ic_info),
+                mContext.getString(R.string.accessibility_system_action_home_label),
+                mContext.getString(R.string.accessibility_system_action_home_label),
+                mReceiver.createPendingIntent(
+                        mContext, SystemActionsBroadcastReceiver.INTENT_ACTION_HOME));
+
+        RemoteAction actionRecents = new RemoteAction(
+                Icon.createWithResource(mContext, R.drawable.ic_info),
+                mContext.getString(R.string.accessibility_system_action_recents_label),
+                mContext.getString(R.string.accessibility_system_action_recents_label),
+                mReceiver.createPendingIntent(
+                        mContext, SystemActionsBroadcastReceiver.INTENT_ACTION_RECENTS));
+
+        RemoteAction actionNotifications = new RemoteAction(
+                Icon.createWithResource(mContext, R.drawable.ic_info),
+                mContext.getString(R.string.accessibility_system_action_notifications_label),
+                mContext.getString(R.string.accessibility_system_action_notifications_label),
+                mReceiver.createPendingIntent(
+                        mContext, SystemActionsBroadcastReceiver.INTENT_ACTION_NOTIFICATIONS));
+
+        RemoteAction actionQuickSettings = new RemoteAction(
+                Icon.createWithResource(mContext, R.drawable.ic_info),
+                mContext.getString(R.string.accessibility_system_action_quick_settings_label),
+                mContext.getString(R.string.accessibility_system_action_quick_settings_label),
+                mReceiver.createPendingIntent(
+                        mContext, SystemActionsBroadcastReceiver.INTENT_ACTION_QUICK_SETTINGS));
+
+        RemoteAction actionPowerDialog = new RemoteAction(
+                Icon.createWithResource(mContext, R.drawable.ic_info),
+                mContext.getString(R.string.accessibility_system_action_power_dialog_label),
+                mContext.getString(R.string.accessibility_system_action_power_dialog_label),
+                mReceiver.createPendingIntent(
+                        mContext, SystemActionsBroadcastReceiver.INTENT_ACTION_POWER_DIALOG));
+
+        RemoteAction actionToggleSplitScreen = new RemoteAction(
+                Icon.createWithResource(mContext, R.drawable.ic_info),
+                mContext.getString(R.string.accessibility_system_action_toggle_split_screen_label),
+                mContext.getString(R.string.accessibility_system_action_toggle_split_screen_label),
+                mReceiver.createPendingIntent(
+                        mContext,
+                        SystemActionsBroadcastReceiver.INTENT_ACTION_TOGGLE_SPLIT_SCREEN));
+
+        RemoteAction actionLockScreen = new RemoteAction(
+                Icon.createWithResource(mContext, R.drawable.ic_info),
+                mContext.getString(R.string.accessibility_system_action_lock_screen_label),
+                mContext.getString(R.string.accessibility_system_action_lock_screen_label),
+                mReceiver.createPendingIntent(
+                        mContext, SystemActionsBroadcastReceiver.INTENT_ACTION_LOCK_SCREEN));
+
+        RemoteAction actionTakeScreenshot = new RemoteAction(
+                Icon.createWithResource(mContext, R.drawable.ic_info),
+                mContext.getString(R.string.accessibility_system_action_screenshot_label),
+                mContext.getString(R.string.accessibility_system_action_screenshot_label),
+                mReceiver.createPendingIntent(
+                        mContext, SystemActionsBroadcastReceiver.INTENT_ACTION_TAKE_SCREENSHOT));
+
+        RemoteAction actionAccessibilityMenu = new RemoteAction(
+                Icon.createWithResource(mContext, R.drawable.ic_info),
+                mContext.getString(R.string.accessibility_system_action_accessibility_menu_label),
+                mContext.getString(R.string.accessibility_system_action_accessibility_menu_label),
+                mReceiver.createPendingIntent(
+                        mContext, SystemActionsBroadcastReceiver.INTENT_ACTION_ACCESSIBILITY_MENU));
+
+        AccessibilityManager am = (AccessibilityManager) mContext.getSystemService(
+                Context.ACCESSIBILITY_SERVICE);
+
+        am.registerSystemAction(actionBack, SYSTEM_ACTION_ID_BACK);
+        am.registerSystemAction(actionHome, SYSTEM_ACTION_ID_HOME);
+        am.registerSystemAction(actionRecents, SYSTEM_ACTION_ID_RECENTS);
+        am.registerSystemAction(actionNotifications, SYSTEM_ACTION_ID_NOTIFICATIONS);
+        am.registerSystemAction(actionQuickSettings, SYSTEM_ACTION_ID_QUICK_SETTINGS);
+        am.registerSystemAction(actionPowerDialog, SYSTEM_ACTION_ID_POWER_DIALOG);
+        am.registerSystemAction(actionToggleSplitScreen, SYSTEM_ACTION_ID_TOGGLE_SPLIT_SCREEN);
+        am.registerSystemAction(actionLockScreen, SYSTEM_ACTION_ID_LOCK_SCREEN);
+        am.registerSystemAction(actionTakeScreenshot, SYSTEM_ACTION_ID_TAKE_SCREENSHOT);
+        am.registerSystemAction(actionAccessibilityMenu, SYSTEM_ACTION_ID_ACCESSIBILITY_MENU);
+    }
+
+    private void handleBack() {
+        sendDownAndUpKeyEvents(KeyEvent.KEYCODE_BACK);
+    }
+
+    private void handleHome() {
+        sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HOME);
+    }
+
+    private void sendDownAndUpKeyEvents(int keyCode) {
+        final long downTime = SystemClock.uptimeMillis();
+        sendKeyEventIdentityCleared(keyCode, KeyEvent.ACTION_DOWN, downTime, downTime);
+        sendKeyEventIdentityCleared(
+                keyCode, KeyEvent.ACTION_UP, downTime, SystemClock.uptimeMillis());
+    }
+
+    private void sendKeyEventIdentityCleared(int keyCode, int action, long downTime, long time) {
+        KeyEvent event = KeyEvent.obtain(downTime, time, action, keyCode, 0, 0,
+                KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM,
+                InputDevice.SOURCE_KEYBOARD, null);
+        InputManager.getInstance()
+                .injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
+        event.recycle();
+    }
+
+    private void handleRecents() {
+        mRecents.toggleRecentApps();
+    }
+
+    private void handleNotifications() {
+        mStatusBar.animateExpandNotificationsPanel();
+    }
+
+    private void handleQuickSettings() {
+        mStatusBar.animateExpandSettingsPanel(null);
+    }
+
+    private void handlePowerDialog() {
+        IWindowManager windowManager = WindowManagerGlobal.getWindowManagerService();
+
+        try {
+            windowManager.showGlobalActions();
+        } catch (RemoteException e) {
+            Log.e(TAG, "failed to display power dialog.");
+        }
+    }
+
+    private void handleToggleSplitScreen() {
+        mStatusBar.toggleSplitScreen();
+    }
+
+    private void handleLockScreen() {
+        IWindowManager windowManager = WindowManagerGlobal.getWindowManagerService();
+
+        mContext.getSystemService(PowerManager.class).goToSleep(SystemClock.uptimeMillis(),
+                PowerManager.GO_TO_SLEEP_REASON_ACCESSIBILITY, 0);
+        try {
+            windowManager.lockNow(null);
+        } catch (RemoteException e) {
+            Log.e(TAG, "failed to lock screen.");
+        }
+    }
+
+    private void handleTakeScreenshot() {
+        ScreenshotHelper screenshotHelper = new ScreenshotHelper(mContext);
+        screenshotHelper.takeScreenshot(WindowManager.TAKE_SCREENSHOT_FULLSCREEN,
+                true, true, new Handler(Looper.getMainLooper()), null);
+    }
+
+    private void handleAccessibilityMenu() {
+        AccessibilityManager.getInstance(mContext).notifyAccessibilityButtonClicked(
+                Display.DEFAULT_DISPLAY);
+    }
+
+    private class SystemActionsBroadcastReceiver extends BroadcastReceiver {
+        private static final String INTENT_ACTION_BACK = "SYSTEM_ACTION_BACK";
+        private static final String INTENT_ACTION_HOME = "SYSTEM_ACTION_HOME";
+        private static final String INTENT_ACTION_RECENTS = "SYSTEM_ACTION_RECENTS";
+        private static final String INTENT_ACTION_NOTIFICATIONS = "SYSTEM_ACTION_NOTIFICATIONS";
+        private static final String INTENT_ACTION_QUICK_SETTINGS = "SYSTEM_ACTION_QUICK_SETTINGS";
+        private static final String INTENT_ACTION_POWER_DIALOG = "SYSTEM_ACTION_POWER_DIALOG";
+        private static final String INTENT_ACTION_TOGGLE_SPLIT_SCREEN =
+                "SYSTEM_ACTION_TOGGLE_SPLIT_SCREEN";
+        private static final String INTENT_ACTION_LOCK_SCREEN = "SYSTEM_ACTION_LOCK_SCREEN";
+        private static final String INTENT_ACTION_TAKE_SCREENSHOT = "SYSTEM_ACTION_TAKE_SCREENSHOT";
+        private static final String INTENT_ACTION_ACCESSIBILITY_MENU =
+                "SYSTEM_ACTION_ACCESSIBILITY_MENU";
+
+        private PendingIntent createPendingIntent(Context context, String intentAction) {
+            switch (intentAction) {
+                case INTENT_ACTION_BACK:
+                case INTENT_ACTION_HOME:
+                case INTENT_ACTION_RECENTS:
+                case INTENT_ACTION_NOTIFICATIONS:
+                case INTENT_ACTION_QUICK_SETTINGS:
+                case INTENT_ACTION_POWER_DIALOG:
+                case INTENT_ACTION_TOGGLE_SPLIT_SCREEN:
+                case INTENT_ACTION_LOCK_SCREEN:
+                case INTENT_ACTION_TAKE_SCREENSHOT:
+                case INTENT_ACTION_ACCESSIBILITY_MENU: {
+                    Intent intent = new Intent(intentAction);
+                    return PendingIntent.getBroadcast(context, 0, intent, 0);
+                }
+                default:
+                    break;
+            }
+            return null;
+        }
+
+        private IntentFilter createIntentFilter() {
+            IntentFilter intentFilter = new IntentFilter();
+            intentFilter.addAction(INTENT_ACTION_BACK);
+            intentFilter.addAction(INTENT_ACTION_HOME);
+            intentFilter.addAction(INTENT_ACTION_RECENTS);
+            intentFilter.addAction(INTENT_ACTION_NOTIFICATIONS);
+            intentFilter.addAction(INTENT_ACTION_QUICK_SETTINGS);
+            intentFilter.addAction(INTENT_ACTION_POWER_DIALOG);
+            intentFilter.addAction(INTENT_ACTION_TOGGLE_SPLIT_SCREEN);
+            intentFilter.addAction(INTENT_ACTION_LOCK_SCREEN);
+            intentFilter.addAction(INTENT_ACTION_TAKE_SCREENSHOT);
+            intentFilter.addAction(INTENT_ACTION_ACCESSIBILITY_MENU);
+            return intentFilter;
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String intentAction = intent.getAction();
+            switch (intentAction) {
+                case INTENT_ACTION_BACK: {
+                    handleBack();
+                    break;
+                }
+                case INTENT_ACTION_HOME: {
+                    handleHome();
+                    break;
+                }
+                case INTENT_ACTION_RECENTS: {
+                    handleRecents();
+                    break;
+                }
+                case INTENT_ACTION_NOTIFICATIONS: {
+                    handleNotifications();
+                    break;
+                }
+                case INTENT_ACTION_QUICK_SETTINGS: {
+                    handleQuickSettings();
+                    break;
+                }
+                case INTENT_ACTION_POWER_DIALOG: {
+                    handlePowerDialog();
+                    break;
+                }
+                case INTENT_ACTION_TOGGLE_SPLIT_SCREEN: {
+                    handleToggleSplitScreen();
+                    break;
+                }
+                case INTENT_ACTION_LOCK_SCREEN: {
+                    handleLockScreen();
+                    break;
+                }
+                case INTENT_ACTION_TAKE_SCREENSHOT: {
+                    handleTakeScreenshot();
+                    break;
+                }
+                case INTENT_ACTION_ACCESSIBILITY_MENU: {
+                    handleAccessibilityMenu();
+                    break;
+                }
+                default:
+                    break;
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java
index ccfd3a5..82c8a46 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java
@@ -72,10 +72,10 @@
         }
 
         // Wait a bit to focus the field so the focusable flag on the window is already set then.
-        post(() -> {
+        postDelayed(() -> {
             mPasswordField.requestFocus();
             mImm.showSoftInput(mPasswordField, InputMethodManager.SHOW_IMPLICIT);
-        });
+        }, 100);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java
index dc24996..601bae2 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java
@@ -89,12 +89,12 @@
     /**
      * Updates the view with provided info.
      */
-    public void update(Bubble bubble, Bitmap bubbleImage, int dotColor, Path dotPath) {
+    public void update(Bubble bubble) {
         mBubble = bubble;
-        setImageBitmap(bubbleImage);
+        setImageBitmap(bubble.getBadgedImage());
         setDotState(DOT_STATE_SUPPRESSED_FOR_FLYOUT);
-        mDotColor = dotColor;
-        drawDot(dotPath);
+        mDotColor = bubble.getDotColor();
+        drawDot(bubble.getDotPath());
         animateDot();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
index 2d9775d..45705b7 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
@@ -31,6 +31,8 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ShortcutInfo;
 import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Path;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
@@ -58,6 +60,14 @@
     private long mLastUpdated;
     private long mLastAccessed;
 
+    private BubbleController.NotificationSuppressionChangedListener mSuppressionListener;
+
+    /** Whether the bubble should show a dot for the notification indicating updated content. */
+    private boolean mShowBubbleUpdateDot = true;
+
+    /** Whether flyout text should be suppressed, regardless of any other flags or state. */
+    private boolean mSuppressFlyout;
+
     // Items that are typically loaded later
     private String mAppName;
     private ShortcutInfo mShortcutInfo;
@@ -69,20 +79,6 @@
     private boolean mInflateSynchronously;
 
     /**
-     * Whether this notification should be shown in the shade when it is also displayed as a bubble.
-     *
-     * <p>When a notification is a bubble we don't show it in the shade once the bubble has been
-     * expanded</p>
-     */
-    private boolean mShowInShadeWhenBubble = true;
-
-    /** Whether the bubble should show a dot for the notification indicating updated content. */
-    private boolean mShowBubbleUpdateDot = true;
-
-    /** Whether flyout text should be suppressed, regardless of any other flags or state. */
-    private boolean mSuppressFlyout;
-
-    /**
      * Presentational info about the flyout.
      */
     public static class FlyoutMessage {
@@ -93,6 +89,9 @@
     }
 
     private FlyoutMessage mFlyoutMessage;
+    private Bitmap mBadgedImage;
+    private int mDotColor;
+    private Path mDotPath;
 
     public static String groupId(NotificationEntry entry) {
         UserHandle user = entry.getSbn().getUser();
@@ -101,11 +100,13 @@
 
     /** Used in tests when no UI is required. */
     @VisibleForTesting(visibility = PRIVATE)
-    Bubble(NotificationEntry e) {
+    Bubble(NotificationEntry e,
+            BubbleController.NotificationSuppressionChangedListener listener) {
         mEntry = e;
         mKey = e.getKey();
         mLastUpdated = e.getSbn().getPostTime();
         mGroupId = groupId(e);
+        mSuppressionListener = listener;
     }
 
     public String getKey() {
@@ -124,6 +125,18 @@
         return mEntry.getSbn().getPackageName();
     }
 
+    public Bitmap getBadgedImage() {
+        return mBadgedImage;
+    }
+
+    public int getDotColor() {
+        return mDotColor;
+    }
+
+    public Path getDotPath() {
+        return mDotPath;
+    }
+
     @Nullable
     public String getAppName() {
         return mAppName;
@@ -205,8 +218,12 @@
         mAppName = info.appName;
         mFlyoutMessage = info.flyoutMessage;
 
+        mBadgedImage = info.badgedBubbleImage;
+        mDotColor = info.dotColor;
+        mDotPath = info.dotPath;
+
         mExpandedView.update(this);
-        mIconView.update(this, info.badgedBubbleImage, info.dotColor, info.dotPath);
+        mIconView.update(this);
     }
 
     /**
@@ -257,25 +274,42 @@
      */
     void markAsAccessedAt(long lastAccessedMillis) {
         mLastAccessed = lastAccessedMillis;
-        setShowInShade(false);
+        setSuppressNotification(true);
         setShowDot(false /* show */, true /* animate */);
     }
 
     /**
-     * Whether this notification should be shown in the shade when it is also displayed as a
-     * bubble.
+     * Should be invoked whenever a Bubble is promoted from overflow.
      */
-    boolean showInShade() {
-        return !mEntry.isRowDismissed() && !shouldSuppressNotification()
-                && (!mEntry.isClearable() || mShowInShadeWhenBubble);
+    void markUpdatedAt(long lastAccessedMillis) {
+        mLastUpdated = lastAccessedMillis;
     }
 
     /**
-     * Sets whether this notification should be shown in the shade when it is also displayed as a
-     * bubble.
+     * Whether this notification should be shown in the shade.
      */
-    void setShowInShade(boolean showInShade) {
-        mShowInShadeWhenBubble = showInShade;
+    boolean showInShade() {
+        return !shouldSuppressNotification() || !mEntry.isClearable();
+    }
+
+    /**
+     * Sets whether this notification should be suppressed in the shade.
+     */
+    void setSuppressNotification(boolean suppressNotification) {
+        boolean prevShowInShade = showInShade();
+
+        Notification.BubbleMetadata data = mEntry.getBubbleMetadata();
+        int flags = data.getFlags();
+        if (suppressNotification) {
+            flags |= Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
+        } else {
+            flags &= ~Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
+        }
+        data.setFlags(flags);
+
+        if (showInShade() != prevShowInShade && mSuppressionListener != null) {
+            mSuppressionListener.onBubbleNotificationSuppressionChange(this);
+        }
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index e642d4e..894ecf6 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -103,6 +103,7 @@
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.function.Consumer;
 
 import javax.inject.Inject;
@@ -151,6 +152,7 @@
     private BubbleData mBubbleData;
     @Nullable private BubbleStackView mStackView;
     private BubbleIconFactory mBubbleIconFactory;
+    private int mMaxBubbles;
 
     // Tracks the id of the current (foreground) user.
     private int mCurrentUserId;
@@ -171,6 +173,8 @@
     private StatusBarStateListener mStatusBarStateListener;
     private final ScreenshotHelper mScreenshotHelper;
 
+    // Callback that updates BubbleOverflowActivity on data change.
+    @Nullable private Runnable mOverflowCallback = null;
 
     private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
     private IStatusBarService mBarService;
@@ -220,6 +224,17 @@
     }
 
     /**
+     * Listener to be notified when a bubbles' notification suppression state changes.
+     */
+    public interface NotificationSuppressionChangedListener {
+        /**
+         * Called when the notification suppression state of a bubble changes.
+         */
+        void onBubbleNotificationSuppressionChange(Bubble bubble);
+
+    }
+
+    /**
      * Listens for the current state of the status bar and updates the visibility state
      * of bubbles as needed.
      */
@@ -299,8 +314,22 @@
 
         configurationController.addCallback(this /* configurationListener */);
 
+        mMaxBubbles = mContext.getResources().getInteger(R.integer.bubbles_max_rendered);
         mBubbleData = data;
         mBubbleData.setListener(mBubbleDataListener);
+        mBubbleData.setSuppressionChangedListener(new NotificationSuppressionChangedListener() {
+            @Override
+            public void onBubbleNotificationSuppressionChange(Bubble bubble) {
+                // Make sure NoMan knows it's not showing in the shade anymore so anyone querying it
+                // can tell.
+                try {
+                    mBarService.onBubbleNotificationSuppressionChanged(bubble.getKey(),
+                            !bubble.showInShade());
+                } catch (RemoteException e) {
+                    // Bad things have happened
+                }
+            }
+        });
 
         mNotificationEntryManager = entryManager;
         mNotificationEntryManager.addNotificationEntryListener(mEntryListener);
@@ -370,6 +399,18 @@
         mInflateSynchronously = inflateSynchronously;
     }
 
+    void setOverflowCallback(Runnable updateOverflow) {
+        mOverflowCallback = updateOverflow;
+    }
+
+    /**
+     * @return Bubbles for updating overflow.
+     */
+    List<Bubble> getOverflowBubbles() {
+        return mBubbleData.getOverflowBubbles();
+    }
+
+
     /**
      * BubbleStackView is lazily created by this method the first time a Bubble is added. This
      * method initializes the stack view and adds it to the StatusBar just above the scrim.
@@ -537,6 +578,10 @@
         mBubbleData.setSelectedBubble(bubble);
     }
 
+    void promoteBubbleFromOverflow(Bubble bubble) {
+        mBubbleData.promoteBubbleFromOverflow(bubble);
+    }
+
     /**
      * Request the stack expand if needed, then select the specified Bubble as current.
      *
@@ -699,7 +744,7 @@
                 Bubble bubble = mBubbleData.getBubbleWithKey(key);
                 boolean bubbleExtended = entry != null && entry.isBubble() && userRemovedNotif;
                 if (bubbleExtended) {
-                    bubble.setShowInShade(false);
+                    bubble.setSuppressNotification(true);
                     bubble.setShowDot(false /* show */, true /* animate */);
                     mNotificationEntryManager.updateNotifications(
                             "BubbleController.onNotificationRemoveRequested");
@@ -726,7 +771,7 @@
                 // As far as group manager is concerned, once a child is no longer shown
                 // in the shade, it is essentially removed.
                 mNotificationGroupManager.onEntryRemoved(bubbleChild.getEntry());
-                bubbleChild.setShowInShade(false);
+                bubbleChild.setSuppressNotification(true);
                 bubbleChild.setShowDot(false /* show */, true /* animate */);
             }
             // And since all children are removed, remove the summary.
@@ -817,6 +862,11 @@
 
         @Override
         public void applyUpdate(BubbleData.Update update) {
+            // Update bubbles in overflow.
+            if (mOverflowCallback != null) {
+                mOverflowCallback.run();
+            }
+
             if (update.addedBubble != null) {
                 mStackView.addBubble(update.addedBubble);
             }
@@ -890,6 +940,8 @@
                 mStackView.updateBubble(update.updatedBubble);
             }
 
+            // At this point, the correct bubbles are inflated in the stack.
+            // Make sure the order in bubble data is reflected in bubble row.
             if (update.orderChanged) {
                 mStackView.updateBubbleOrder(update.bubbles);
             }
@@ -912,15 +964,18 @@
             updateStack();
 
             if (DEBUG_BUBBLE_CONTROLLER) {
-                Log.d(TAG, "[BubbleData]");
+                Log.d(TAG, "\n[BubbleData] bubbles:");
                 Log.d(TAG, BubbleDebugConfig.formatBubblesString(mBubbleData.getBubbles(),
                         mBubbleData.getSelectedBubble()));
 
                 if (mStackView != null) {
-                    Log.d(TAG, "[BubbleStackView]");
+                    Log.d(TAG, "\n[BubbleStackView]");
                     Log.d(TAG, BubbleDebugConfig.formatBubblesString(mStackView.getBubblesOnScreen(),
                             mStackView.getExpandedBubble()));
                 }
+                Log.d(TAG, "\n[BubbleData] overflow:");
+                Log.d(TAG, BubbleDebugConfig.formatBubblesString(mBubbleData.getOverflowBubbles(),
+                        null));
             }
         }
     };
@@ -1043,12 +1098,10 @@
 
         @Override
         public void onSingleTaskDisplayDrawn(int displayId) {
-            final Bubble expandedBubble = mStackView != null
-                    ? mStackView.getExpandedBubble()
-                    : null;
-            if (expandedBubble != null && expandedBubble.getDisplayId() == displayId) {
-                expandedBubble.setContentVisibility(true);
+            if (mStackView == null) {
+                return;
             }
+            mStackView.showExpandedViewContents(displayId);
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
index cc0824e..673121f 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
@@ -78,9 +78,11 @@
 
         // A read-only view of the bubbles list, changes there will be reflected here.
         final List<Bubble> bubbles;
+        final List<Bubble> overflowBubbles;
 
-        private Update(List<Bubble> bubbleOrder) {
-            bubbles = Collections.unmodifiableList(bubbleOrder);
+        private Update(List<Bubble> row, List<Bubble> overflow) {
+            bubbles = Collections.unmodifiableList(row);
+            overflowBubbles = Collections.unmodifiableList(overflow);
         }
 
         boolean anythingChanged() {
@@ -113,11 +115,14 @@
     private final Context mContext;
     /** Bubbles that are actively in the stack. */
     private final List<Bubble> mBubbles;
+    /** Bubbles that aged out to overflow. */
+    private final List<Bubble> mOverflowBubbles;
     /** Bubbles that are being loaded but haven't been added to the stack just yet. */
     private final List<Bubble> mPendingBubbles;
     private Bubble mSelectedBubble;
     private boolean mExpanded;
     private final int mMaxBubbles;
+    private final int mMaxOverflowBubbles;
 
     // State tracked during an operation -- keeps track of what listener events to dispatch.
     private Update mStateChange;
@@ -129,6 +134,9 @@
     @Nullable
     private Listener mListener;
 
+    @Nullable
+    private BubbleController.NotificationSuppressionChangedListener mSuppressionListener;
+
     /**
      * We track groups with summaries that aren't visibly displayed but still kept around because
      * the bubble(s) associated with the summary still exist.
@@ -146,9 +154,16 @@
     public BubbleData(Context context) {
         mContext = context;
         mBubbles = new ArrayList<>();
+        mOverflowBubbles = new ArrayList<>();
         mPendingBubbles = new ArrayList<>();
-        mStateChange = new Update(mBubbles);
+        mStateChange = new Update(mBubbles, mOverflowBubbles);
         mMaxBubbles = mContext.getResources().getInteger(R.integer.bubbles_max_rendered);
+        mMaxOverflowBubbles = mContext.getResources().getInteger(R.integer.bubbles_max_overflow);
+    }
+
+    public void setSuppressionChangedListener(
+            BubbleController.NotificationSuppressionChangedListener listener) {
+        mSuppressionListener = listener;
     }
 
     public boolean hasBubbles() {
@@ -184,6 +199,19 @@
         dispatchPendingChanges();
     }
 
+    public void promoteBubbleFromOverflow(Bubble bubble) {
+        if (DEBUG_BUBBLE_DATA) {
+            Log.d(TAG, "promoteBubbleFromOverflow: " + bubble);
+        }
+        mOverflowBubbles.remove(bubble);
+        doAdd(bubble);
+        setSelectedBubbleInternal(bubble);
+        // Preserve new order for next repack, which sorts by last updated time.
+        bubble.markUpdatedAt(mTimeSource.currentTimeMillis());
+        trim();
+        dispatchPendingChanges();
+    }
+
     /**
      * Constructs a new bubble or returns an existing one. Does not add new bubbles to
      * bubble data, must go through {@link #notificationEntryUpdated(Bubble, boolean, boolean)}
@@ -199,7 +227,7 @@
                     return b;
                 }
             }
-            bubble = new Bubble(entry);
+            bubble = new Bubble(entry, mSuppressionListener);
             mPendingBubbles.add(bubble);
         } else {
             bubble.setEntry(entry);
@@ -238,11 +266,13 @@
         } else if (mSelectedBubble == null) {
             setSelectedBubbleInternal(bubble);
         }
-        boolean isBubbleExpandedAndSelected = mExpanded && mSelectedBubble == bubble;
-        bubble.setShowInShade(!isBubbleExpandedAndSelected && showInShade);
-        bubble.setShowDot(!isBubbleExpandedAndSelected /* show */, true /* animate */);
-        dispatchPendingChanges();
 
+        boolean isBubbleExpandedAndSelected = mExpanded && mSelectedBubble == bubble;
+        boolean suppress = isBubbleExpandedAndSelected || !showInShade || !bubble.showInShade();
+        bubble.setSuppressNotification(suppress);
+        bubble.setShowDot(!isBubbleExpandedAndSelected /* show */, true /* animate */);
+
+        dispatchPendingChanges();
     }
 
     public void notificationEntryRemoved(NotificationEntry entry, @DismissReason int reason) {
@@ -343,6 +373,7 @@
             mStateChange.orderChanged = true;
         }
         mStateChange.addedBubble = bubble;
+
         if (!isExpanded()) {
             mStateChange.orderChanged |= packGroup(findFirstIndexForGroup(bubble.getGroupId()));
             // Top bubble becomes selected.
@@ -407,6 +438,17 @@
             mStateChange.orderChanged |= repackAll();
         }
 
+        if (reason == BubbleController.DISMISS_AGED) {
+            if (DEBUG_BUBBLE_DATA) {
+                Log.d(TAG, "overflowing bubble: " + bubbleToRemove);
+            }
+            mOverflowBubbles.add(0, bubbleToRemove);
+            if (mOverflowBubbles.size() == mMaxOverflowBubbles + 1) {
+                // Remove oldest bubble.
+                mOverflowBubbles.remove(mOverflowBubbles.size() - 1);
+            }
+        }
+
         // Note: If mBubbles.isEmpty(), then mSelectedBubble is now null.
         if (Objects.equals(mSelectedBubble, bubbleToRemove)) {
             // Move selection to the new bubble at the same position.
@@ -454,7 +496,7 @@
         if (mListener != null && mStateChange.anythingChanged()) {
             mListener.applyUpdate(mStateChange);
         }
-        mStateChange = new Update(mBubbles);
+        mStateChange = new Update(mBubbles, mOverflowBubbles);
     }
 
     /**
@@ -689,12 +731,19 @@
     }
 
     /**
-     * The set of bubbles.
+     * The set of bubbles in row.
      */
     @VisibleForTesting(visibility = PRIVATE)
     public List<Bubble> getBubbles() {
         return Collections.unmodifiableList(mBubbles);
     }
+    /**
+     * The set of bubbles in overflow.
+     */
+    @VisibleForTesting(visibility = PRIVATE)
+    public List<Bubble> getOverflowBubbles() {
+        return Collections.unmodifiableList(mOverflowBubbles);
+    }
 
     @VisibleForTesting(visibility = PRIVATE)
     Bubble getBubbleWithKey(String key) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 48ce4e9..cf8b2be 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -24,6 +24,7 @@
 import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_BUBBLES;
 import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
 
+import android.annotation.Nullable;
 import android.app.ActivityOptions;
 import android.app.ActivityTaskManager;
 import android.app.ActivityView;
@@ -83,7 +84,7 @@
     private ActivityViewStatus mActivityViewStatus = ActivityViewStatus.INITIALIZING;
     private int mTaskId = -1;
 
-    private PendingIntent mBubbleIntent;
+    private PendingIntent mPendingIntent;
 
     private boolean mKeyboardVisible;
     private boolean mNeedsNewHeight;
@@ -98,7 +99,9 @@
     private int[] mTempLoc = new int[2];
     private int mExpandedViewTouchSlop;
 
-    private Bubble mBubble;
+    @Nullable private Bubble mBubble;
+
+    private boolean mIsOverflow;
 
     private BubbleController mBubbleController = Dependency.get(BubbleController.class);
     private WindowManager mWindowManager;
@@ -125,7 +128,7 @@
                                     + "bubble=" + getBubbleKey());
                         }
                         try {
-                            if (mBubble.usingShortcutInfo()) {
+                            if (!mIsOverflow && mBubble.usingShortcutInfo()) {
                                 mActivityView.startShortcutActivity(mBubble.getShortcutInfo(),
                                         options, null /* sourceBounds */);
                             } else {
@@ -133,7 +136,7 @@
                                 // Apply flags to make behaviour match documentLaunchMode=always.
                                 fillInIntent.addFlags(FLAG_ACTIVITY_NEW_DOCUMENT);
                                 fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
-                                mActivityView.startActivity(mBubbleIntent, fillInIntent, options);
+                                mActivityView.startActivity(mPendingIntent, fillInIntent, options);
                             }
                         } catch (RuntimeException e) {
                             // If there's a runtime exception here then there's something
@@ -141,7 +144,7 @@
                             // the bubble again so we'll just remove it.
                             Log.w(TAG, "Exception while displaying bubble: " + getBubbleKey()
                                     + ", " + e.getMessage() + "; removing bubble");
-                            mBubbleController.removeBubble(mBubble.getKey(),
+                            mBubbleController.removeBubble(getBubbleKey(),
                                     BubbleController.DISMISS_INVALID_INTENT);
                         }
                     });
@@ -241,6 +244,7 @@
 
         mActivityView = new ActivityView(mContext, null /* attrs */, 0 /* defStyle */,
                 true /* singleTaskInstance */);
+
         // Set ActivityView's alpha value as zero, since there is no view content to be shown.
         setContentVisibility(false);
         addView(mActivityView);
@@ -342,6 +346,15 @@
         mStackView = stackView;
     }
 
+    public void setOverflow(boolean overflow) {
+        mIsOverflow = overflow;
+
+        Intent target = new Intent(mContext, BubbleOverflowActivity.class);
+        mPendingIntent = PendingIntent.getActivity(mContext, /* requestCode */ 0,
+                target, PendingIntent.FLAG_UPDATE_CURRENT);
+        mSettingsIcon.setVisibility(GONE);
+    }
+
     /**
      * Sets the bubble used to populate this view.
      */
@@ -350,14 +363,14 @@
             Log.d(TAG, "update: bubble=" + (bubble != null ? bubble.getKey() : "null"));
         }
         boolean isNew = mBubble == null;
-        if (isNew || bubble.getKey().equals(mBubble.getKey())) {
+        if (isNew || bubble != null && bubble.getKey().equals(mBubble.getKey())) {
             mBubble = bubble;
             mSettingsIcon.setContentDescription(getResources().getString(
                     R.string.bubbles_settings_button_description, bubble.getAppName()));
 
             if (isNew) {
-                mBubbleIntent = mBubble.getBubbleIntent();
-                if (mBubbleIntent != null || mBubble.getShortcutInfo() != null) {
+                mPendingIntent = mBubble.getBubbleIntent();
+                if (mPendingIntent != null || mBubble.getShortcutInfo() != null) {
                     setContentVisibility(false);
                     mActivityView.setVisibility(VISIBLE);
                 }
@@ -393,12 +406,16 @@
         return true;
     }
 
+    // TODO(138116789) Fix overflow height.
     void updateHeight() {
         if (DEBUG_BUBBLE_EXPANDED_VIEW) {
             Log.d(TAG, "updateHeight: bubble=" + getBubbleKey());
         }
         if (usingActivityView()) {
-            float desiredHeight = Math.max(mBubble.getDesiredHeight(mContext), mMinHeight);
+            float desiredHeight = mMinHeight;
+            if (!mIsOverflow) {
+                desiredHeight = Math.max(mBubble.getDesiredHeight(mContext), mMinHeight);
+            }
             float height = Math.min(desiredHeight, getMaxExpandedHeight());
             height = Math.max(height, mMinHeight);
             LayoutParams lp = (LayoutParams) mActivityView.getLayoutParams();
@@ -423,8 +440,12 @@
         int bottomInset = getRootWindowInsets() != null
                 ? getRootWindowInsets().getStableInsetBottom()
                 : 0;
-        return mDisplaySize.y - windowLocation[1] - mSettingsIconHeight - mPointerHeight
+        int mh = mDisplaySize.y - windowLocation[1] - mSettingsIconHeight - mPointerHeight
                 - mPointerMargin - bottomInset;
+        Log.i(TAG, "max exp height: " + mh);
+//        return mDisplaySize.y - windowLocation[1] - mSettingsIconHeight - mPointerHeight
+//                - mPointerMargin - bottomInset;
+        return mh;
     }
 
     /**
@@ -543,7 +564,7 @@
     }
 
     private boolean usingActivityView() {
-        return (mBubbleIntent != null || mBubble.getShortcutInfo() != null)
+        return (mPendingIntent != null || mBubble.getShortcutInfo() != null)
                 && mActivityView != null;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExperimentConfig.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExperimentConfig.java
index 4252f72..006de84 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExperimentConfig.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExperimentConfig.java
@@ -76,6 +76,9 @@
     private static final String ALLOW_BUBBLE_MENU = "allow_bubble_screenshot_menu";
     private static final boolean ALLOW_BUBBLE_MENU_DEFAULT = false;
 
+    private static final String ALLOW_BUBBLE_OVERFLOW = "allow_bubble_overflow";
+    private static final boolean ALLOW_BUBBLE_OVERFLOW_DEFAULT = false;
+
     /**
      * When true, if a notification has the information necessary to bubble (i.e. valid
      * contentIntent and an icon or image), then a {@link android.app.Notification.BubbleMetadata}
@@ -141,6 +144,16 @@
     }
 
     /**
+     * When true, show a menu when a bubble is long-pressed, which will allow the user to take
+     * actions on that bubble.
+     */
+    static boolean allowBubbleOverflow(Context context) {
+        return Settings.Secure.getInt(context.getContentResolver(),
+                ALLOW_BUBBLE_OVERFLOW,
+                ALLOW_BUBBLE_OVERFLOW_DEFAULT ? 1 : 0) != 0;
+    }
+
+    /**
      * If {@link #allowAnyNotifToBubble(Context)} is true, this method creates and adds
      * {@link android.app.Notification.BubbleMetadata} to the notification entry as long as
      * the notification has necessary info for BubbleMetadata.
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
index d99607f..bea55c8 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
@@ -1,15 +1,42 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package com.android.systemui.bubbles;
 
+import static com.android.systemui.bubbles.BubbleDebugConfig.DEBUG_OVERFLOW;
+import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_BUBBLES;
+import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
+
 import android.app.Activity;
 import android.content.res.TypedArray;
 import android.graphics.Color;
 import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
 
 import androidx.recyclerview.widget.GridLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.android.systemui.R;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
+
 import javax.inject.Inject;
 
 /**
@@ -17,9 +44,13 @@
  * Must be public to be accessible to androidx...AppComponentFactory
  */
 public class BubbleOverflowActivity extends Activity {
-    private RecyclerView mRecyclerView;
-    private int mMaxBubbles;
+    private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleOverflowActivity" : TAG_BUBBLES;
+
     private BubbleController mBubbleController;
+    private BubbleOverflowAdapter mAdapter;
+    private RecyclerView mRecyclerView;
+    private List<Bubble> mOverflowBubbles = new ArrayList<>();
+    private int mMaxBubbles;
 
     @Inject
     public BubbleOverflowActivity(BubbleController controller) {
@@ -35,17 +66,42 @@
         mMaxBubbles = getResources().getInteger(R.integer.bubbles_max_rendered);
         mRecyclerView = findViewById(R.id.bubble_overflow_recycler);
         mRecyclerView.setLayoutManager(
-                new GridLayoutManager(getApplicationContext(), /* numberOfColumns */ mMaxBubbles));
+                new GridLayoutManager(getApplicationContext(),
+                        getResources().getInteger(R.integer.bubbles_overflow_columns)));
+
+        mAdapter = new BubbleOverflowAdapter(mOverflowBubbles,
+                mBubbleController::promoteBubbleFromOverflow);
+        mRecyclerView.setAdapter(mAdapter);
+
+        updateData(mBubbleController.getOverflowBubbles());
+        mBubbleController.setOverflowCallback(() -> {
+            updateData(mBubbleController.getOverflowBubbles());
+        });
     }
 
     void setBackgroundColor() {
         final TypedArray ta = getApplicationContext().obtainStyledAttributes(
-                new int[] {android.R.attr.colorBackgroundFloating});
+                new int[]{android.R.attr.colorBackgroundFloating});
         int bgColor = ta.getColor(0, Color.WHITE);
         ta.recycle();
         findViewById(android.R.id.content).setBackgroundColor(bgColor);
     }
 
+    void updateData(List<Bubble> bubbles) {
+        mOverflowBubbles.clear();
+        if (bubbles.size() > mMaxBubbles) {
+            mOverflowBubbles.addAll(bubbles.subList(mMaxBubbles, bubbles.size()));
+        } else {
+            mOverflowBubbles.addAll(bubbles);
+        }
+        mAdapter.notifyDataSetChanged();
+
+        if (DEBUG_OVERFLOW) {
+            Log.d(TAG, "Updated overflow bubbles:\n" + BubbleDebugConfig.formatBubblesString(
+                    mOverflowBubbles, /*selected*/ null));
+        }
+    }
+
     @Override
     public void onStart() {
         super.onStart();
@@ -75,3 +131,48 @@
         super.onDestroy();
     }
 }
+
+class BubbleOverflowAdapter extends RecyclerView.Adapter<BubbleOverflowAdapter.ViewHolder> {
+    private Consumer<Bubble> mPromoteBubbleFromOverflow;
+    private List<Bubble> mBubbles;
+
+    public BubbleOverflowAdapter(List<Bubble> list, Consumer<Bubble> promoteBubble) {
+        mBubbles = list;
+        mPromoteBubbleFromOverflow = promoteBubble;
+    }
+
+    @Override
+    public BubbleOverflowAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
+            int viewType) {
+        BadgedImageView view = (BadgedImageView) LayoutInflater.from(parent.getContext())
+                .inflate(R.layout.bubble_view, parent, false);
+        view.setPadding(15, 15, 15, 15);
+        return new ViewHolder(view);
+    }
+
+    @Override
+    public void onBindViewHolder(ViewHolder vh, int index) {
+        Bubble bubble = mBubbles.get(index);
+
+        vh.mBadgedImageView.update(bubble);
+        vh.mBadgedImageView.setOnClickListener(view -> {
+            mBubbles.remove(bubble);
+            notifyDataSetChanged();
+            mPromoteBubbleFromOverflow.accept(bubble);
+        });
+    }
+
+    @Override
+    public int getItemCount() {
+        return mBubbles.size();
+    }
+
+    public static class ViewHolder extends RecyclerView.ViewHolder {
+        public BadgedImageView mBadgedImageView;
+
+        public ViewHolder(BadgedImageView v) {
+            super(v);
+            mBadgedImageView = v;
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 54a42a6..685bb94 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -33,6 +33,8 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Color;
 import android.graphics.ColorMatrix;
 import android.graphics.ColorMatrixColorFilter;
 import android.graphics.Paint;
@@ -40,6 +42,9 @@
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.graphics.RectF;
+import android.graphics.drawable.AdaptiveIconDrawable;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.InsetDrawable;
 import android.os.Bundle;
 import android.os.VibrationEffect;
 import android.os.Vibrator;
@@ -58,6 +63,7 @@
 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 import android.view.animation.AccelerateDecelerateInterpolator;
 import android.widget.FrameLayout;
+import android.widget.ImageView;
 
 import androidx.annotation.MainThread;
 import androidx.annotation.Nullable;
@@ -195,8 +201,6 @@
     private int mPointerHeight;
     private int mStatusBarHeight;
     private int mImeOffset;
-    private int mBubbleMenuOffset = 252;
-    private BubbleIconFactory mBubbleIconFactory;
     private Bubble mExpandedBubble;
     private boolean mIsExpanded;
 
@@ -320,6 +324,8 @@
     private Runnable mAfterMagnet;
 
     private int mOrientation = Configuration.ORIENTATION_UNDEFINED;
+    private BubbleExpandedView mOverflowExpandedView;
+    private ImageView mOverflowBtn;
 
     public BubbleStackView(Context context, BubbleData data,
             @Nullable SurfaceSynchronizer synchronizer) {
@@ -369,8 +375,6 @@
         mBubbleContainer.setClipChildren(false);
         addView(mBubbleContainer, new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
 
-        mBubbleIconFactory = new BubbleIconFactory(context);
-
         mExpandedViewContainer = new FrameLayout(context);
         mExpandedViewContainer.setElevation(elevation);
         mExpandedViewContainer.setPadding(mExpandedViewPadding, mExpandedViewPadding,
@@ -405,8 +409,12 @@
                         .setStiffness(SpringForce.STIFFNESS_LOW)
                         .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY));
         mExpandedViewYAnim.addEndListener((anim, cancelled, value, velocity) -> {
-            if (mIsExpanded && mExpandedBubble != null) {
-                mExpandedBubble.getExpandedView().updateView();
+            if (mIsExpanded) {
+                if (mExpandedBubble == null) {
+                    mOverflowExpandedView.updateView();
+                } else {
+                    mExpandedBubble.getExpandedView().updateView();
+                }
             }
         });
 
@@ -414,6 +422,10 @@
         setFocusable(true);
         mBubbleContainer.bringToFront();
 
+        if (BubbleExperimentConfig.allowBubbleOverflow(mContext)) {
+            setUpOverflow();
+        }
+
         setOnApplyWindowInsetsListener((View view, WindowInsets insets) -> {
             if (!mIsExpanded || mIsExpansionAnimating) {
                 return view.onApplyWindowInsets(insets);
@@ -421,7 +433,13 @@
             mExpandedAnimationController.updateYPosition(
                     // Update the insets after we're done translating otherwise position
                     // calculation for them won't be correct.
-                    () -> mExpandedBubble.getExpandedView().updateInsets(insets));
+                    () -> {
+                        if (mExpandedBubble == null) {
+                            mOverflowExpandedView.updateInsets(insets);
+                        } else {
+                            mExpandedBubble.getExpandedView().updateInsets(insets);
+                        }
+                    });
             return view.onApplyWindowInsets(insets);
         });
 
@@ -433,7 +451,11 @@
                     // Reposition & adjust the height for new orientation
                     if (mIsExpanded) {
                         mExpandedViewContainer.setTranslationY(getExpandedViewY());
-                        mExpandedBubble.getExpandedView().updateView();
+                        if (mExpandedBubble == null) {
+                            mOverflowExpandedView.updateView();
+                        } else {
+                            mExpandedBubble.getExpandedView().updateView();
+                        }
                     }
 
                     // Need to update the padding around the view
@@ -499,6 +521,38 @@
         mBubbleMenuView = findViewById(R.id.bubble_menu_container);
     }
 
+    private void setUpOverflow() {
+        mOverflowExpandedView = (BubbleExpandedView) mInflater.inflate(
+                R.layout.bubble_expanded_view, this /* root */, false /* attachToRoot */);
+        mOverflowExpandedView.setOverflow(true);
+
+        mInflater.inflate(R.layout.bubble_overflow_button, this);
+        mOverflowBtn = findViewById(R.id.bubble_overflow_button);
+        mOverflowBtn.setOnClickListener(v -> {
+            setSelectedBubble(null);
+        });
+
+        TypedArray ta = mContext.obtainStyledAttributes(
+                new int[]{android.R.attr.colorBackgroundFloating});
+        int bgColor = ta.getColor(0, Color.WHITE /* default */);
+        ta.recycle();
+
+        InsetDrawable fg = new InsetDrawable(mOverflowBtn.getDrawable(), 28);
+        ColorDrawable bg = new ColorDrawable(bgColor);
+        AdaptiveIconDrawable adaptiveIcon = new AdaptiveIconDrawable(bg, fg);
+        mOverflowBtn.setImageDrawable(adaptiveIcon);
+        mOverflowBtn.setVisibility(GONE);
+    }
+
+    void showExpandedViewContents(int displayId) {
+        if (mOverflowExpandedView.getVirtualDisplayId() == displayId) {
+            mOverflowExpandedView.setContentVisibility(true);
+        } else if (mExpandedBubble != null
+                && mExpandedBubble.getExpandedView().getVirtualDisplayId() == displayId) {
+            mExpandedBubble.setContentVisibility(true);
+        }
+    }
+
     private void setUpFlyout() {
         if (mFlyout != null) {
             removeView(mFlyout);
@@ -734,9 +788,10 @@
                 new FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
         ViewClippingUtil.setClippingDeactivated(bubble.getIconView(), true, mClippingParameters);
         animateInFlyoutForBubble(bubble);
+        updatePointerPosition();
+        updateOverflowBtnVisibility( /*apply */ true);
         requestUpdate();
         logBubbleEvent(bubble, SysUiStatsLog.BUBBLE_UICHANGED__ACTION__POSTED);
-        updatePointerPosition();
     }
 
     // via BubbleData.Listener
@@ -753,7 +808,32 @@
         } else {
             Log.d(TAG, "was asked to remove Bubble, but didn't find the view! " + bubble);
         }
-        updatePointerPosition();
+        updateOverflowBtnVisibility(/* apply */ true);
+    }
+
+    private void updateOverflowBtnVisibility(boolean apply) {
+        if (!BubbleExperimentConfig.allowBubbleOverflow(mContext)) {
+            return;
+        }
+        if (mIsExpanded) {
+            if (DEBUG_BUBBLE_STACK_VIEW) {
+                Log.d(TAG, "Expanded && overflow > 0. Show overflow button at");
+                Log.d(TAG, "x: " + mExpandedAnimationController.getOverflowBtnLeft());
+                Log.d(TAG, "y: " + mExpandedAnimationController.getExpandedY());
+            }
+            mOverflowBtn.setX(mExpandedAnimationController.getOverflowBtnLeft());
+            mOverflowBtn.setY(mExpandedAnimationController.getExpandedY());
+            mOverflowBtn.setVisibility(VISIBLE);
+            mExpandedAnimationController.setShowOverflowBtn(true);
+            if (apply) {
+                mExpandedAnimationController.expandFromStack(null /* after */);
+            }
+        } else {
+            if (DEBUG_BUBBLE_STACK_VIEW) {
+                Log.d(TAG, "Collapsed. Hide overflow button.");
+            }
+            mOverflowBtn.setVisibility(GONE);
+        }
     }
 
     // via BubbleData.Listener
@@ -794,7 +874,9 @@
             // expanded view becomes visible on the screen. See b/126856255
             mExpandedViewContainer.setAlpha(0.0f);
             mSurfaceSynchronizer.syncSurfaceAndRun(() -> {
-                if (previouslySelected != null) {
+                if (previouslySelected == null) {
+                    mOverflowExpandedView.setContentVisibility(false);
+                } else {
                     previouslySelected.setContentVisibility(false);
                 }
                 updateExpandedBubble();
@@ -953,6 +1035,12 @@
         final Bubble previouslySelected = mExpandedBubble;
         beforeExpandedViewAnimation();
 
+        if (DEBUG_BUBBLE_STACK_VIEW) {
+            Log.d(TAG, "animateCollapse");
+            Log.d(TAG, BubbleDebugConfig.formatBubblesString(this.getBubblesOnScreen(),
+                    this.getExpandedBubble()));
+        }
+        updateOverflowBtnVisibility(/* apply */ false);
         mBubbleContainer.cancelAllAnimations();
         mExpandedAnimationController.collapseBackToStack(
                 mStackAnimationController.getStackPositionAlongNearestHorizontalEdge()
@@ -960,7 +1048,11 @@
                 () -> {
                     mBubbleContainer.setActiveController(mStackAnimationController);
                     afterExpandedViewAnimation();
-                    previouslySelected.setContentVisibility(false);
+                    if (previouslySelected == null) {
+                        mOverflowExpandedView.setContentVisibility(false);
+                    } else {
+                        previouslySelected.setContentVisibility(false);
+                    }
                 });
 
         mExpandedViewXAnim.animateToFinalPosition(getCollapsedX());
@@ -975,12 +1067,12 @@
         beforeExpandedViewAnimation();
 
         mBubbleContainer.setActiveController(mExpandedAnimationController);
+        updateOverflowBtnVisibility(/* apply */ false);
         mExpandedAnimationController.expandFromStack(() -> {
             updatePointerPosition();
             afterExpandedViewAnimation();
         } /* after */);
 
-
         mExpandedViewContainer.setTranslationX(getCollapsedX());
         mExpandedViewContainer.setTranslationY(getCollapsedY());
         mExpandedViewContainer.setAlpha(0f);
@@ -1063,9 +1155,11 @@
             Log.d(TAG, "onDragStart()");
         }
         if (mIsExpanded || mIsExpansionAnimating) {
+            if (DEBUG_BUBBLE_STACK_VIEW) {
+                Log.d(TAG, "mIsExpanded or mIsExpansionAnimating");
+            }
             return;
         }
-
         hideBubbleMenu();
         mStackAnimationController.cancelStackPositionAnimations();
         mBubbleContainer.setActiveController(mStackAnimationController);
@@ -1526,10 +1620,14 @@
             Log.d(TAG, "updateExpandedBubble()");
         }
         mExpandedViewContainer.removeAllViews();
-        if (mExpandedBubble != null && mIsExpanded) {
-            mExpandedViewContainer.addView(mExpandedBubble.getExpandedView());
-            mExpandedBubble.getExpandedView().populateExpandedView();
-            mExpandedViewContainer.setVisibility(mIsExpanded ? VISIBLE : GONE);
+        if (mIsExpanded) {
+            BubbleExpandedView bev = mOverflowExpandedView;
+            if (mExpandedBubble != null) {
+                bev = mExpandedBubble.getExpandedView();
+            }
+            mExpandedViewContainer.addView(bev);
+            bev.populateExpandedView();
+            mExpandedViewContainer.setVisibility(VISIBLE);
             mExpandedViewContainer.setAlpha(1.0f);
         }
     }
@@ -1545,7 +1643,11 @@
             if (!mExpandedViewYAnim.isRunning()) {
                 // We're not animating so set the value
                 mExpandedViewContainer.setTranslationY(y);
-                mExpandedBubble.getExpandedView().updateView();
+                if (mExpandedBubble == null) {
+                    mOverflowExpandedView.updateView();
+                } else {
+                    mExpandedBubble.getExpandedView().updateView();
+                }
             } else {
                 // We are animating so update the value; there is an end listener on the animator
                 // that will ensure expandedeView.updateView gets called.
@@ -1571,23 +1673,28 @@
     }
 
     private void updatePointerPosition() {
-        if (DEBUG_BUBBLE_STACK_VIEW) {
-            Log.d(TAG, "updatePointerPosition()");
-        }
-
         Bubble expandedBubble = getExpandedBubble();
         if (expandedBubble == null) {
             return;
         }
 
         int index = getBubbleIndex(expandedBubble);
+        if (index >= mMaxBubbles) {
+            // In between state, where extra bubble will be overflowed, and new bubble added
+            index = 0;
+        }
         float bubbleLeftFromScreenLeft = mExpandedAnimationController.getBubbleLeft(index);
         float halfBubble = mBubbleSize / 2f;
         float bubbleCenter = bubbleLeftFromScreenLeft + halfBubble;
         // Padding might be adjusted for insets, so get it directly from the view
         bubbleCenter -= mExpandedViewContainer.getPaddingLeft();
 
-        expandedBubble.getExpandedView().setPointerPosition(bubbleCenter);
+        if (index >= mMaxBubbles) {
+            Bubble first = mBubbleData.getBubbles().get(0);
+            first.getExpandedView().setPointerPosition(bubbleCenter);
+        } else {
+            expandedBubble.getExpandedView().setPointerPosition(bubbleCenter);
+        }
     }
 
     /**
@@ -1680,7 +1787,11 @@
         if (!isExpanded()) {
             return false;
         }
-        return mExpandedBubble.getExpandedView().performBackPressIfNeeded();
+        if (mExpandedBubble == null) {
+            return mOverflowExpandedView.performBackPressIfNeeded();
+        } else {
+            return mExpandedBubble.getExpandedView().performBackPressIfNeeded();
+        }
     }
 
     /** For debugging only */
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewInfoTask.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewInfoTask.java
index e705584..55a7a11 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewInfoTask.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewInfoTask.java
@@ -157,6 +157,7 @@
             PackageManager pm = c.getPackageManager();
             ApplicationInfo appInfo;
             Drawable badgedIcon;
+            Drawable appIcon;
             try {
                 appInfo = pm.getApplicationInfo(
                         packageName,
@@ -167,7 +168,7 @@
                 if (appInfo != null) {
                     info.appName = String.valueOf(pm.getApplicationLabel(appInfo));
                 }
-                Drawable appIcon = pm.getApplicationIcon(packageName);
+                appIcon = pm.getApplicationIcon(packageName);
                 badgedIcon = pm.getUserBadgedIcon(appIcon, sbn.getUser());
             } catch (PackageManager.NameNotFoundException exception) {
                 // If we can't find package... don't think we should show the bubble.
@@ -178,6 +179,11 @@
             // Badged bubble image
             Drawable bubbleDrawable = iconFactory.getBubbleDrawable(c, info.shortcutInfo,
                     b.getEntry().getBubbleMetadata());
+            if (bubbleDrawable == null) {
+                // Default to app icon
+                bubbleDrawable = appIcon;
+            }
+
             BitmapInfo badgeBitmapInfo = iconFactory.getBadgeBitmap(badgedIcon);
             info.badgedBubbleImage = iconFactory.getBubbleBitmap(bubbleDrawable,
                     badgeBitmapInfo).icon;
@@ -240,7 +246,7 @@
                     bubbleMessage.senderName = sender != null
                             ? sender.getName()
                             : null;
-                    bubbleMessage.senderAvatar = sender != null
+                    bubbleMessage.senderAvatar = sender != null && sender.getIcon() != null
                             ? sender.getIcon().loadDrawable(context)
                             : null;
                     return bubbleMessage;
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
index 6528f37..6d6969d 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
@@ -67,6 +67,8 @@
     private float mBubblePaddingTop;
     /** Size of each bubble. */
     private float mBubbleSizePx;
+    /** Width of the overflow button. */
+    private float mOverflowBtnWidth;
     /** Height of the status bar. */
     private float mStatusBarHeight;
     /** Size of display. */
@@ -81,7 +83,7 @@
 
     private boolean mAnimatingExpand = false;
     private boolean mAnimatingCollapse = false;
-    private Runnable mAfterExpand;
+    private @Nullable Runnable mAfterExpand;
     private Runnable mAfterCollapse;
     private PointF mCollapsePoint;
 
@@ -97,6 +99,7 @@
     private boolean mSpringingBubbleToTouch = false;
 
     private int mExpandedViewPadding;
+    private boolean mShowOverflowBtn;
 
     public ExpandedAnimationController(Point displaySize, int expandedViewPadding,
             int orientation) {
@@ -116,7 +119,7 @@
     /**
      * Animates expanding the bubbles into a row along the top of the screen.
      */
-    public void expandFromStack(Runnable after) {
+    public void expandFromStack(@Nullable Runnable after) {
         mAnimatingCollapse = false;
         mAnimatingExpand = true;
         mAfterExpand = after;
@@ -150,6 +153,14 @@
         }
     }
 
+    public void setShowOverflowBtn(boolean showBtn) {
+        mShowOverflowBtn = showBtn;
+    }
+
+    public boolean getShowOverflowBtn() {
+        return mShowOverflowBtn;
+    }
+
     /**
      * Animates the bubbles along a curved path, either to expand them along the top or collapse
      * them back into a stack.
@@ -380,6 +391,7 @@
         mStackOffsetPx = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
         mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
         mBubbleSizePx = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
+        mOverflowBtnWidth = mBubbleSizePx;
         mStatusBarHeight =
                 res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
         mBubblesMaxRendered = res.getInteger(R.integer.bubbles_max_rendered);
@@ -498,6 +510,14 @@
         return getRowLeft() + bubbleFromRowLeft;
     }
 
+    public float getOverflowBtnLeft() {
+        if (mLayout == null || mLayout.getChildCount() == 0) {
+            return 0;
+        }
+        return getBubbleLeft(mLayout.getChildCount() - 1) + mBubbleSizePx
+                + getSpaceBetweenBubbles();
+    }
+
     /**
      * When expanded, the bubbles are centered in the screen. In portrait, all available space is
      * used. In landscape we have too much space so the value is restricted. This method accounts
@@ -505,7 +525,7 @@
      *
      * @return the desired width to display the expanded bubbles in.
      */
-    private float getWidthForDisplayingBubbles() {
+    public float getWidthForDisplayingBubbles() {
         final float availableWidth = getAvailableScreenWidth(true /* includeStableInsets */);
         if (mScreenOrientation == Configuration.ORIENTATION_LANDSCAPE) {
             // display size y in landscape will be the smaller dimension of the screen
@@ -551,7 +571,11 @@
 
         final float totalBubbleWidth = bubbleCount * mBubbleSizePx;
         final float totalGapWidth = (bubbleCount - 1) * getSpaceBetweenBubbles();
-        final float rowWidth = totalGapWidth + totalBubbleWidth;
+        float rowWidth = totalGapWidth + totalBubbleWidth;
+        if (mShowOverflowBtn) {
+            rowWidth += getSpaceBetweenBubbles();
+            rowWidth += mOverflowBtnWidth;
+        }
 
         // This display size we're using includes the size of the insets, we want the true
         // center of the display minus the notch here, which means we should include the
@@ -559,7 +583,6 @@
         final float trueCenter = getAvailableScreenWidth(false /* subtractStableInsets */) / 2f;
         final float halfRow = rowWidth / 2f;
         final float rowLeft = trueCenter - halfRow;
-
         return rowLeft;
     }
 
@@ -567,12 +590,12 @@
      * @return Space between bubbles in row above expanded view.
      */
     private float getSpaceBetweenBubbles() {
-        final float rowMargins = mExpandedViewPadding * 2;
-        final float maxRowWidth = getWidthForDisplayingBubbles() - rowMargins;
-
         final float totalBubbleWidth = mBubblesMaxRendered * mBubbleSizePx;
-        final float totalGapWidth = maxRowWidth - totalBubbleWidth;
-
+        final float rowMargins = mExpandedViewPadding * 2;
+        float totalGapWidth = getWidthForDisplayingBubbles() - rowMargins - totalBubbleWidth;
+        if (mShowOverflowBtn) {
+            totalGapWidth -= mBubbleSizePx;
+        }
         final int gapCount = mBubblesMaxRendered - 1;
         final float gapWidth = totalGapWidth / gapCount;
         return gapWidth;
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
index 80e48b9..2db2cf1 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
@@ -20,7 +20,10 @@
 import android.content.Context
 import android.os.IBinder
 import android.service.controls.Control
-import android.service.controls.IControlsProviderCallback
+import android.service.controls.IControlsActionCallback
+import android.service.controls.IControlsLoadCallback
+import android.service.controls.IControlsSubscriber
+import android.service.controls.IControlsSubscription
 import android.service.controls.actions.ControlAction
 import android.util.ArrayMap
 import android.util.Log
@@ -54,20 +57,14 @@
     private val componentMap: MutableMap<ComponentName, ControlsProviderLifecycleManager> =
             ArrayMap<ComponentName, ControlsProviderLifecycleManager>()
 
-    private val serviceCallback = object : IControlsProviderCallback.Stub() {
-        override fun onLoad(token: IBinder, controls: MutableList<Control>) {
+    private val loadCallbackService = object : IControlsLoadCallback.Stub() {
+        override fun accept(token: IBinder, controls: MutableList<Control>) {
             backgroundExecutor.execute(OnLoadRunnable(token, controls))
         }
+    }
 
-        override fun onRefreshState(token: IBinder, controlStates: List<Control>) {
-            if (!refreshing.get()) {
-                Log.d(TAG, "Refresh outside of window for token:$token")
-            } else {
-                backgroundExecutor.execute(OnRefreshStateRunnable(token, controlStates))
-            }
-        }
-
-        override fun onControlActionResponse(
+    private val actionCallbackService = object : IControlsActionCallback.Stub() {
+        override fun accept(
             token: IBinder,
             controlId: String,
             @ControlAction.ResponseResult response: Int
@@ -76,13 +73,36 @@
         }
     }
 
+    private val subscriberService = object : IControlsSubscriber.Stub() {
+        override fun onSubscribe(token: IBinder, subs: IControlsSubscription) {
+            backgroundExecutor.execute(OnSubscribeRunnable(token, subs))
+        }
+
+        override fun onNext(token: IBinder, c: Control) {
+            if (!refreshing.get()) {
+                Log.d(TAG, "Refresh outside of window for token:$token")
+            } else {
+                backgroundExecutor.execute(OnNextRunnable(token, c))
+            }
+        }
+        override fun onError(token: IBinder, s: String) {
+            backgroundExecutor.execute(OnErrorRunnable(token, s))
+        }
+
+        override fun onComplete(token: IBinder) {
+            backgroundExecutor.execute(OnCompleteRunnable(token))
+        }
+    }
+
     @VisibleForTesting
     internal open fun createProviderManager(component: ComponentName):
             ControlsProviderLifecycleManager {
         return ControlsProviderLifecycleManager(
                 context,
                 backgroundExecutor,
-                serviceCallback,
+                loadCallbackService,
+                actionCallbackService,
+                subscriberService,
                 component
         )
     }
@@ -176,16 +196,51 @@
         }
     }
 
-    private inner class OnRefreshStateRunnable(
+    private inner class OnNextRunnable(
         token: IBinder,
-        val list: List<Control>
+        val control: Control
     ) : CallbackRunnable(token) {
         override fun run() {
             if (!refreshing.get()) {
                 Log.d(TAG, "onRefresh outside of window from:${provider?.componentName}")
             }
             provider?.let {
-                lazyController.get().refreshStatus(it.componentName, list)
+                lazyController.get().refreshStatus(it.componentName, control)
+            }
+        }
+    }
+
+    private inner class OnSubscribeRunnable(
+        token: IBinder,
+        val subscription: IControlsSubscription
+    ) : CallbackRunnable(token) {
+        override fun run() {
+            if (!refreshing.get()) {
+                Log.d(TAG, "onRefresh outside of window from '${provider?.componentName}'")
+            }
+            provider?.let {
+                it.startSubscription(subscription)
+            }
+        }
+    }
+
+    private inner class OnCompleteRunnable(
+        token: IBinder
+    ) : CallbackRunnable(token) {
+        override fun run() {
+            provider?.let {
+                Log.i(TAG, "onComplete receive from '${provider?.componentName}'")
+            }
+        }
+    }
+
+    private inner class OnErrorRunnable(
+        token: IBinder,
+        val error: String
+    ) : CallbackRunnable(token) {
+        override fun run() {
+            provider?.let {
+                Log.e(TAG, "onError receive from '${provider?.componentName}': $error")
             }
         }
     }
@@ -201,4 +256,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
index 4d95822..e098faa 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
@@ -30,11 +30,11 @@
     fun changeFavoriteStatus(controlInfo: ControlInfo, state: Boolean)
     fun unsubscribe()
     fun action(controlInfo: ControlInfo, action: ControlAction)
-    fun refreshStatus(componentName: ComponentName, controls: List<Control>)
+    fun refreshStatus(componentName: ComponentName, control: Control)
     fun onActionResponse(
         componentName: ComponentName,
         controlId: String,
         @ControlAction.ResponseResult response: Int
     )
     fun clearFavorites()
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
index 7e328e4..d5b5b5f 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
@@ -210,20 +210,20 @@
         }
     }
 
-    override fun refreshStatus(componentName: ComponentName, controls: List<Control>) {
+    override fun refreshStatus(componentName: ComponentName, control: Control) {
         if (!available) {
             Log.d(TAG, "Controls not available")
             return
         }
         executor.execute {
             synchronized(currentFavorites) {
-                val changed = updateFavoritesLocked(componentName, controls)
+                val changed = updateFavoritesLocked(componentName, listOf(control))
                 if (changed) {
                     persistenceWrapper.storeFavorites(favoritesAsListLocked())
                 }
             }
         }
-        uiController.onRefreshState(componentName, controls)
+        uiController.onRefreshState(componentName, listOf(control))
     }
 
     override fun onActionResponse(componentName: ComponentName, controlId: String, response: Int) {
@@ -270,4 +270,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
index 79057ad..99aa360 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
@@ -25,11 +25,13 @@
 import android.os.IBinder
 import android.os.RemoteException
 import android.service.controls.Control
-import android.service.controls.ControlsProviderService.CALLBACK_BINDER
 import android.service.controls.ControlsProviderService.CALLBACK_BUNDLE
 import android.service.controls.ControlsProviderService.CALLBACK_TOKEN
+import android.service.controls.IControlsActionCallback
+import android.service.controls.IControlsLoadCallback
 import android.service.controls.IControlsProvider
-import android.service.controls.IControlsProviderCallback
+import android.service.controls.IControlsSubscriber
+import android.service.controls.IControlsSubscription
 import android.service.controls.actions.ControlAction
 import android.util.ArraySet
 import android.util.Log
@@ -41,19 +43,23 @@
 class ControlsProviderLifecycleManager(
     private val context: Context,
     private val executor: DelayableExecutor,
-    private val serviceCallback: IControlsProviderCallback.Stub,
+    private val loadCallbackService: IControlsLoadCallback.Stub,
+    private val actionCallbackService: IControlsActionCallback.Stub,
+    private val subscriberService: IControlsSubscriber.Stub,
     val componentName: ComponentName
 ) : IBinder.DeathRecipient {
 
     var lastLoadCallback: LoadCallback? = null
         private set
     val token: IBinder = Binder()
+    @GuardedBy("subscriptions")
+    private val subscriptions = mutableListOf<IControlsSubscription>()
     private var unbindImmediate = false
     private var requiresBound = false
     private var isBound = false
     @GuardedBy("queuedMessages")
     private val queuedMessages: MutableSet<Message> = ArraySet()
-    private var wrapper: ControlsProviderServiceWrapper? = null
+    private var wrapper: ServiceWrapper? = null
     private var bindTryCount = 0
     private val TAG = javaClass.simpleName
     private var onLoadCanceller: Runnable? = null
@@ -61,12 +67,12 @@
     companion object {
         private const val MSG_LOAD = 0
         private const val MSG_SUBSCRIBE = 1
-        private const val MSG_UNSUBSCRIBE = 2
-        private const val MSG_ON_ACTION = 3
-        private const val MSG_UNBIND = 4
+        private const val MSG_ACTION = 2
+        private const val MSG_UNBIND = 3
         private const val BIND_RETRY_DELAY = 1000L // ms
         private const val LOAD_TIMEOUT = 5000L // ms
         private const val MAX_BIND_RETRIES = 5
+        private const val MAX_CONTROLS_REQUEST = 100000L
         private const val DEBUG = true
         private val BIND_FLAGS = Context.BIND_AUTO_CREATE or Context.BIND_FOREGROUND_SERVICE or
                 Context.BIND_WAIVE_PRIORITY
@@ -75,7 +81,6 @@
     private val intent = Intent().apply {
         component = componentName
         putExtra(CALLBACK_BUNDLE, Bundle().apply {
-            putBinder(CALLBACK_BINDER, serviceCallback)
             putBinder(CALLBACK_TOKEN, token)
         })
     }
@@ -119,7 +124,7 @@
         override fun onServiceConnected(name: ComponentName, service: IBinder) {
             if (DEBUG) Log.d(TAG, "onServiceConnected $name")
             bindTryCount = 0
-            wrapper = ControlsProviderServiceWrapper(IControlsProvider.Stub.asInterface(service))
+            wrapper = ServiceWrapper(IControlsProvider.Stub.asInterface(service))
             try {
                 service.linkToDeath(this@ControlsProviderLifecycleManager, 0)
             } catch (_: RemoteException) {}
@@ -151,7 +156,7 @@
         }
         queue.filter { it is Message.Action }.forEach {
             val msg = it as Message.Action
-            onAction(msg.id, msg.action)
+            action(msg.id, msg.action)
         }
     }
 
@@ -182,7 +187,7 @@
         if (DEBUG) {
             Log.d(TAG, "load $componentName")
         }
-        if (!(wrapper?.load() ?: false)) {
+        if (!(wrapper?.load(loadCallbackService) ?: false)) {
             queueMessage(Message.Load)
             binderDied()
         }
@@ -194,7 +199,7 @@
         onLoadCanceller = executor.executeDelayed({
             // Didn't receive a response in time, log and send back empty list
             Log.d(TAG, "Timeout waiting onLoad for $componentName")
-            serviceCallback.onLoad(token, emptyList())
+            loadCallbackService.accept(token, emptyList())
         }, LOAD_TIMEOUT, TimeUnit.MILLISECONDS)
         if (isBound) {
             load()
@@ -218,7 +223,7 @@
         if (DEBUG) {
             Log.d(TAG, "subscribe $componentName - $controlIds")
         }
-        if (!(wrapper?.subscribe(controlIds) ?: false)) {
+        if (!(wrapper?.subscribe(controlIds, subscriberService) ?: false)) {
             queueMessage(Message.Subscribe(controlIds))
             binderDied()
         }
@@ -226,29 +231,45 @@
 
     fun maybeBindAndSendAction(controlId: String, action: ControlAction) {
         if (isBound) {
-            onAction(controlId, action)
+            action(controlId, action)
         } else {
             queueMessage(Message.Action(controlId, action))
             bindService(true)
         }
     }
 
-    private fun onAction(controlId: String, action: ControlAction) {
+    private fun action(controlId: String, action: ControlAction) {
         if (DEBUG) {
             Log.d(TAG, "onAction $componentName - $controlId")
         }
-        if (!(wrapper?.onAction(controlId, action) ?: false)) {
+        if (!(wrapper?.action(controlId, action, actionCallbackService) ?: false)) {
             queueMessage(Message.Action(controlId, action))
             binderDied()
         }
     }
 
+    fun startSubscription(subscription: IControlsSubscription) {
+        synchronized(subscriptions) {
+            subscriptions.add(subscription)
+        }
+        wrapper?.request(subscription, MAX_CONTROLS_REQUEST)
+    }
+
     fun unsubscribe() {
         if (DEBUG) {
             Log.d(TAG, "unsubscribe $componentName")
         }
         unqueueMessage(Message.Subscribe(emptyList())) // Removes all subscribe messages
-        wrapper?.unsubscribe()
+
+        val subs = synchronized(subscriptions) {
+            ArrayList(subscriptions).also {
+                subscriptions.clear()
+            }
+        }
+
+        subs.forEach {
+            wrapper?.cancel(it)
+        }
     }
 
     fun maybeUnbindAndRemoveCallback() {
@@ -277,7 +298,7 @@
             override val type = MSG_SUBSCRIBE
         }
         class Action(val id: String, val action: ControlAction) : Message() {
-            override val type = MSG_ON_ACTION
+            override val type = MSG_ACTION
         }
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderServiceWrapper.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderServiceWrapper.kt
deleted file mode 100644
index 882a10d..0000000
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderServiceWrapper.kt
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.controls.controller
-
-import android.service.controls.actions.ControlAction
-import android.service.controls.IControlsProvider
-import android.util.Log
-
-class ControlsProviderServiceWrapper(val service: IControlsProvider) {
-    companion object {
-        private const val TAG = "ControlsProviderServiceWrapper"
-    }
-
-    private fun callThroughService(block: () -> Unit): Boolean {
-        try {
-            block()
-            return true
-        } catch (ex: Exception) {
-            Log.d(TAG, "Caught exception from ControlsProviderService", ex)
-            return false
-        }
-    }
-
-    fun load(): Boolean {
-        return callThroughService {
-            service.load()
-        }
-    }
-
-    fun subscribe(controlIds: List<String>): Boolean {
-        return callThroughService {
-            service.subscribe(controlIds)
-        }
-    }
-
-    fun unsubscribe(): Boolean {
-        return callThroughService {
-            service.unsubscribe()
-        }
-    }
-
-    fun onAction(controlId: String, action: ControlAction): Boolean {
-        return callThroughService {
-            service.onAction(controlId, action)
-        }
-    }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt
new file mode 100644
index 0000000..5c812b1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.controls.controller
+
+import android.service.controls.actions.ControlAction
+import android.service.controls.IControlsActionCallback
+import android.service.controls.IControlsLoadCallback
+import android.service.controls.IControlsProvider
+import android.service.controls.IControlsSubscriber
+import android.service.controls.IControlsSubscription
+import android.service.controls.actions.ControlActionWrapper
+import android.util.Log
+
+class ServiceWrapper(val service: IControlsProvider) {
+    companion object {
+        private const val TAG = "ServiceWrapper"
+    }
+
+    private fun callThroughService(block: () -> Unit): Boolean {
+        try {
+            block()
+            return true
+        } catch (ex: Exception) {
+            Log.e(TAG, "Caught exception from ControlsProviderService", ex)
+            return false
+        }
+    }
+
+    fun load(cb: IControlsLoadCallback): Boolean {
+        return callThroughService {
+            service.load(cb)
+        }
+    }
+
+    fun subscribe(controlIds: List<String>, subscriber: IControlsSubscriber): Boolean {
+        return callThroughService {
+            service.subscribe(controlIds, subscriber)
+        }
+    }
+
+    fun request(subscription: IControlsSubscription, num: Long): Boolean {
+        return callThroughService {
+            subscription.request(num)
+        }
+    }
+
+    fun cancel(subscription: IControlsSubscription): Boolean {
+        return callThroughService {
+            subscription.cancel()
+        }
+    }
+
+    fun action(
+        controlId: String,
+        action: ControlAction,
+        cb: IControlsActionCallback
+    ): Boolean {
+        return callThroughService {
+            service.action(controlId, ControlActionWrapper(action), cb)
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt
index 9372162..3949c59 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt
@@ -51,7 +51,7 @@
             context,
             executor,
             ServiceListing.Builder(context)
-                    .setIntentAction(ControlsProviderService.CONTROLS_ACTION)
+                    .setIntentAction(ControlsProviderService.SERVICE_CONTROLS)
                     .setPermission("android.permission.BIND_CONTROLS")
                     .setNoun("Controls Provider")
                     .setSetting("controls_providers")
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
new file mode 100644
index 0000000..81b5f36
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.controls.ui
+
+import android.content.Context
+import android.graphics.drawable.ClipDrawable
+import android.graphics.drawable.Drawable
+import android.graphics.drawable.GradientDrawable
+import android.graphics.drawable.Icon
+import android.graphics.drawable.LayerDrawable
+import android.service.controls.Control
+import android.service.controls.DeviceTypes
+import android.service.controls.actions.BooleanAction
+import android.service.controls.actions.ControlAction
+import android.service.controls.actions.FloatAction
+import android.service.controls.templates.ControlTemplate
+import android.service.controls.templates.RangeTemplate
+import android.service.controls.templates.ToggleRangeTemplate
+import android.service.controls.templates.ToggleTemplate
+import android.util.TypedValue
+import android.view.MotionEvent
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+
+import com.android.systemui.controls.controller.ControlsController
+import com.android.systemui.R
+
+private const val MIN_LEVEL = 0
+private const val MAX_LEVEL = 10000
+
+class ControlViewHolder(
+    val layout: ViewGroup,
+    val controlsController: ControlsController
+) {
+    val icon: ImageView = layout.requireViewById(R.id.icon)
+    val status: TextView = layout.requireViewById(R.id.status)
+    val statusExtra: TextView = layout.requireViewById(R.id.status_extra)
+    val title: TextView = layout.requireViewById(R.id.title)
+    val subtitle: TextView = layout.requireViewById(R.id.subtitle)
+    val context: Context = layout.getContext()
+    val clipLayer: ClipDrawable
+    val gd: GradientDrawable
+    lateinit var cws: ControlWithState
+
+    init {
+        val ld = layout.getBackground() as LayerDrawable
+        ld.mutate()
+        clipLayer = ld.findDrawableByLayerId(R.id.clip_layer) as ClipDrawable
+        gd = clipLayer.getDrawable() as GradientDrawable
+    }
+
+    fun bindData(cws: ControlWithState) {
+        this.cws = cws
+
+        val (status, template) = cws.control?.let {
+            title.setText(it.getTitle())
+            subtitle.setText(it.getSubtitle())
+            Pair(it.getStatus(), it.getControlTemplate())
+        } ?: run {
+            title.setText(cws.ci.controlTitle)
+            subtitle.setText("")
+            Pair(Control.STATUS_UNKNOWN, ControlTemplate.NO_TEMPLATE)
+        }
+
+        findBehavior(status, template).apply(this, cws)
+    }
+
+    fun action(action: ControlAction) {
+        controlsController.action(cws.ci, action)
+    }
+
+    private fun findBehavior(status: Int, template: ControlTemplate): Behavior {
+        return when {
+            status == Control.STATUS_UNKNOWN -> UnknownBehavior()
+            template is ToggleTemplate -> ToggleTemplateBehavior()
+            template is ToggleRangeTemplate -> ToggleRangeTemplateBehavior()
+            else -> {
+                object : Behavior {
+                    override fun apply(cvh: ControlViewHolder, cws: ControlWithState) {
+                        cvh.status.setText(cws.control?.getStatusText())
+                        cvh.applyRenderInfo(findRenderInfo(cws.ci.deviceType, false))
+                    }
+                }
+            }
+        }
+    }
+
+    internal fun applyRenderInfo(ri: RenderInfo) {
+        val fg = context.getResources().getColorStateList(ri.foreground, context.getTheme())
+        val bg = context.getResources().getColorStateList(ri.background, context.getTheme())
+        status.setTextColor(fg)
+        statusExtra.setTextColor(fg)
+
+        icon.setImageIcon(Icon.createWithResource(context, ri.iconResourceId))
+        icon.setImageTintList(fg)
+
+        gd.setColor(bg)
+    }
+
+    fun setEnabled(enabled: Boolean) {
+        status.setEnabled(enabled)
+        icon.setEnabled(enabled)
+    }
+}
+
+private interface Behavior {
+    fun apply(cvh: ControlViewHolder, cws: ControlWithState)
+
+    fun findRenderInfo(deviceType: Int, isActive: Boolean): RenderInfo =
+        deviceRenderMap.getOrDefault(deviceType, unknownDeviceMap).getValue(isActive)
+}
+
+private class UnknownBehavior : Behavior {
+    override fun apply(cvh: ControlViewHolder, cws: ControlWithState) {
+        cvh.status.setText("Loading...")
+        cvh.applyRenderInfo(findRenderInfo(cws.ci.deviceType, false))
+    }
+}
+
+private class ToggleRangeTemplateBehavior : Behavior {
+    lateinit var clipLayer: Drawable
+    lateinit var template: ToggleRangeTemplate
+    lateinit var control: Control
+    lateinit var cvh: ControlViewHolder
+    lateinit var rangeTemplate: RangeTemplate
+    lateinit var statusExtra: TextView
+    lateinit var status: TextView
+    lateinit var context: Context
+
+    override fun apply(cvh: ControlViewHolder, cws: ControlWithState) {
+        this.control = cws.control!!
+        this.cvh = cvh
+
+        statusExtra = cvh.statusExtra
+        status = cvh.status
+
+        status.setText(control.getStatusText())
+
+        context = status.getContext()
+
+        cvh.layout.setOnTouchListener(ToggleRangeTouchListener())
+
+        val ld = cvh.layout.getBackground() as LayerDrawable
+        clipLayer = ld.findDrawableByLayerId(R.id.clip_layer)
+
+        template = control.getControlTemplate() as ToggleRangeTemplate
+        rangeTemplate = template.getRange()
+
+        val checked = template.isChecked()
+        val deviceType = control.getDeviceType()
+
+        updateRange((rangeTemplate.getCurrentValue() / 100.0f), checked)
+
+        cvh.setEnabled(checked)
+        cvh.applyRenderInfo(findRenderInfo(deviceType, checked))
+    }
+
+    fun toggle() {
+        cvh.action(BooleanAction(template.getTemplateId(), !template.isChecked()))
+
+        val nextLevel = if (template.isChecked()) MIN_LEVEL else MAX_LEVEL
+        clipLayer.setLevel(nextLevel)
+    }
+
+    fun beginUpdateRange() {
+        status.setVisibility(View.GONE)
+        statusExtra.setTextSize(TypedValue.COMPLEX_UNIT_PX, context.getResources()
+                .getDimensionPixelSize(R.dimen.control_status_expanded).toFloat())
+    }
+
+    fun updateRange(f: Float, checked: Boolean) {
+        clipLayer.setLevel(if (checked) (MAX_LEVEL * f).toInt() else MIN_LEVEL)
+
+        if (checked && f < 100.0f && f > 0.0f) {
+            statusExtra.setText("" + (f * 100.0).toInt() + "%")
+            statusExtra.setVisibility(View.VISIBLE)
+        } else {
+            statusExtra.setText("")
+            statusExtra.setVisibility(View.GONE)
+        }
+    }
+
+    fun endUpdateRange(f: Float) {
+        statusExtra.setText(" - " + (f * 100.0).toInt() + "%")
+
+        val newValue = rangeTemplate.getMinValue() +
+            (f * (rangeTemplate.getMaxValue() - rangeTemplate.getMinValue()))
+
+        statusExtra.setTextSize(TypedValue.COMPLEX_UNIT_PX, context.getResources()
+                .getDimensionPixelSize(R.dimen.control_status_normal).toFloat())
+        status.setVisibility(View.VISIBLE)
+
+        cvh.action(FloatAction(rangeTemplate.getTemplateId(), findNearestStep(newValue)))
+    }
+
+    fun findNearestStep(value: Float): Float {
+        var minDiff = 1000f
+
+        var f = rangeTemplate.getMinValue()
+        while (f <= rangeTemplate.getMaxValue()) {
+            val currentDiff = Math.abs(value - f)
+            if (currentDiff < minDiff) {
+                minDiff = currentDiff
+            } else {
+                return f - rangeTemplate.getStepValue()
+            }
+
+            f += rangeTemplate.getStepValue()
+        }
+
+        return rangeTemplate.getMaxValue()
+    }
+
+    inner class ToggleRangeTouchListener() : View.OnTouchListener {
+        private var initialTouchX: Float = 0.0f
+        private var initialTouchY: Float = 0.0f
+        private var isDragging: Boolean = false
+        private val minDragDiff = 20
+
+        override fun onTouch(v: View, e: MotionEvent): Boolean {
+            when (e.getActionMasked()) {
+                MotionEvent.ACTION_DOWN -> setupTouch(e)
+                MotionEvent.ACTION_MOVE -> detectDrag(v, e)
+                MotionEvent.ACTION_UP -> endTouch(v, e)
+            }
+
+            return true
+        }
+
+        private fun setupTouch(e: MotionEvent) {
+            initialTouchX = e.getX()
+            initialTouchY = e.getY()
+        }
+
+        private fun detectDrag(v: View, e: MotionEvent) {
+            val xDiff = Math.abs(e.getX() - initialTouchX)
+            val yDiff = Math.abs(e.getY() - initialTouchY)
+
+            if (xDiff < minDragDiff) {
+                isDragging = false
+            } else {
+                if (!isDragging) {
+                    this@ToggleRangeTemplateBehavior.beginUpdateRange()
+                }
+                v.getParent().requestDisallowInterceptTouchEvent(true)
+                isDragging = true
+                if (yDiff > xDiff) {
+                    endTouch(v, e)
+                } else {
+                    val percent = Math.max(0.0f, Math.min(1.0f, e.getX() / v.getWidth()))
+                    this@ToggleRangeTemplateBehavior.updateRange(percent, true)
+                }
+            }
+        }
+
+        private fun endTouch(v: View, e: MotionEvent) {
+            if (!isDragging) {
+                this@ToggleRangeTemplateBehavior.toggle()
+            } else {
+                val percent = Math.max(0.0f, Math.min(1.0f, e.getX() / v.getWidth()))
+                this@ToggleRangeTemplateBehavior.endUpdateRange(percent)
+            }
+
+            initialTouchX = 0.0f
+            initialTouchY = 0.0f
+            isDragging = false
+        }
+    }
+}
+
+private class ToggleTemplateBehavior : Behavior {
+    lateinit var clipLayer: Drawable
+    lateinit var template: ToggleTemplate
+    lateinit var control: Control
+    lateinit var cvh: ControlViewHolder
+    lateinit var context: Context
+    lateinit var status: TextView
+
+    override fun apply(cvh: ControlViewHolder, cws: ControlWithState) {
+        this.control = cws.control!!
+        this.cvh = cvh
+        status = cvh.status
+
+        status.setText(control.getStatusText())
+
+        cvh.layout.setOnClickListener(View.OnClickListener() { toggle() })
+
+        val ld = cvh.layout.getBackground() as LayerDrawable
+        clipLayer = ld.findDrawableByLayerId(R.id.clip_layer)
+
+        template = control.getControlTemplate() as ToggleTemplate
+
+        val checked = template.isChecked()
+        val deviceType = control.getDeviceType()
+
+        clipLayer.setLevel(if (checked) MAX_LEVEL else MIN_LEVEL)
+        cvh.setEnabled(checked)
+        cvh.applyRenderInfo(findRenderInfo(deviceType, checked))
+    }
+
+    fun toggle() {
+        cvh.action(BooleanAction(template.getTemplateId(), !template.isChecked()))
+
+        val nextLevel = if (template.isChecked()) MIN_LEVEL else MAX_LEVEL
+        clipLayer.setLevel(nextLevel)
+    }
+}
+
+internal data class RenderInfo(val iconResourceId: Int, val foreground: Int, val background: Int)
+
+private val unknownDeviceMap = mapOf(
+    false to RenderInfo(
+        R.drawable.ic_light_off_gm2_24px,
+        R.color.unknown_foreground,
+        R.color.unknown_foreground),
+    true to RenderInfo(
+        R.drawable.ic_lightbulb_outline_gm2_24px,
+        R.color.unknown_foreground,
+        R.color.unknown_foreground)
+)
+
+private val deviceRenderMap = mapOf<Int, Map<Boolean, RenderInfo>>(
+    DeviceTypes.TYPE_UNKNOWN to unknownDeviceMap,
+    DeviceTypes.TYPE_LIGHT to mapOf(
+        false to RenderInfo(
+            R.drawable.ic_light_off_gm2_24px,
+            R.color.light_foreground,
+            R.color.light_background),
+        true to RenderInfo(
+            R.drawable.ic_lightbulb_outline_gm2_24px,
+            R.color.light_foreground,
+            R.color.light_background)
+    ),
+    DeviceTypes.TYPE_THERMOSTAT to mapOf(
+        false to RenderInfo(
+            R.drawable.ic_device_thermostat_gm2_24px,
+            R.color.light_foreground,
+            R.color.light_background),
+        true to RenderInfo(
+            R.drawable.ic_device_thermostat_gm2_24px,
+            R.color.light_foreground,
+            R.color.light_background)
+    ),
+    DeviceTypes.TYPE_CAMERA to mapOf(
+        false to RenderInfo(
+            R.drawable.ic_videocam_gm2_24px,
+            R.color.light_foreground,
+            R.color.light_background),
+        true to RenderInfo(
+            R.drawable.ic_videocam_gm2_24px,
+            R.color.light_foreground,
+            R.color.light_background)
+    ),
+    DeviceTypes.TYPE_LOCK to mapOf(
+        false to RenderInfo(
+            R.drawable.ic_lock_open_gm2_24px,
+            R.color.lock_foreground,
+            R.color.lock_background),
+        true to RenderInfo(
+            R.drawable.ic_lock_gm2_24px,
+            R.color.lock_foreground,
+            R.color.lock_background)
+    ),
+    DeviceTypes.TYPE_SWITCH to mapOf(
+        false to RenderInfo(
+            R.drawable.ic_switches_gm2_24px,
+            R.color.lock_foreground,
+            R.color.lock_background),
+        true to RenderInfo(
+            R.drawable.ic_switches_gm2_24px,
+            R.color.lock_foreground,
+            R.color.lock_background)
+    ),
+    DeviceTypes.TYPE_OUTLET to mapOf(
+        false to RenderInfo(
+            R.drawable.ic_power_off_gm2_24px,
+            R.color.lock_foreground,
+            R.color.lock_background),
+        true to RenderInfo(
+            R.drawable.ic_power_gm2_24px,
+            R.color.lock_foreground,
+            R.color.lock_background)
+    )
+)
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlWithState.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlWithState.kt
new file mode 100644
index 0000000..816f0b2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlWithState.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.controls.ui
+
+import android.service.controls.Control
+
+import com.android.systemui.controls.controller.ControlInfo
+
+/**
+ * A container for:
+ * <ul>
+ *  <li>ControlInfo - Basic cached info about a Control
+ *  <li>Control - Actual Control parcelable received directly from
+ *  the participating application
+ * </ul>
+ */
+data class ControlWithState(val ci: ControlInfo, val control: Control?)
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
index 0270c2b..b07a75d 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
@@ -19,12 +19,15 @@
 import android.content.ComponentName
 import android.service.controls.Control
 import android.service.controls.actions.ControlAction
+import android.view.ViewGroup
 
 interface ControlsUiController {
+    fun show(parent: ViewGroup)
+    fun hide()
     fun onRefreshState(componentName: ComponentName, controls: List<Control>)
     fun onActionResponse(
         componentName: ComponentName,
         controlId: String,
         @ControlAction.ResponseResult response: Int
     )
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
index 0ace126..926fb6e 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -16,19 +16,204 @@
 
 package com.android.systemui.controls.ui
 
+import android.accounts.Account
+import android.accounts.AccountManager
 import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.content.ServiceConnection
+import android.os.IBinder
 import android.service.controls.Control
+import android.service.controls.TokenProvider
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+
+import com.android.systemui.controls.controller.ControlsController
+import com.android.systemui.controls.controller.ControlInfo
+import com.android.systemui.controls.management.ControlsProviderSelectorActivity
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.R
+
+import dagger.Lazy
+
+import java.util.concurrent.Executor
 import javax.inject.Inject
 import javax.inject.Singleton
 
+private const val TAG = "ControlsUi"
+
+// TEMP CODE for MOCK
+private const val TOKEN = "https://www.googleapis.com/auth/assistant"
+private const val SCOPE = "oauth2:" + TOKEN
+private var tokenProviderConnection: TokenProviderConnection? = null
+class TokenProviderConnection(val cc: ControlsController, val context: Context)
+    : ServiceConnection {
+    private var mTokenProvider: TokenProvider? = null
+
+    override fun onServiceConnected(cName: ComponentName, binder: IBinder) {
+        Thread({
+            Log.i(TAG, "TokenProviderConnection connected")
+            mTokenProvider = TokenProvider.Stub.asInterface(binder)
+
+            val mLastAccountName = mTokenProvider?.getAccountName()
+
+            if (mLastAccountName == null || mLastAccountName.isEmpty()) {
+                Log.e(TAG, "NO ACCOUNT IS SET. Open HomeMock app")
+            } else {
+                mTokenProvider?.setAuthToken(getAuthToken(mLastAccountName))
+                cc.subscribeToFavorites()
+            }
+        }, "TokenProviderThread").start()
+    }
+
+    override fun onServiceDisconnected(cName: ComponentName) {
+        mTokenProvider = null
+    }
+
+    fun getAuthToken(accountName: String): String? {
+        val am = AccountManager.get(context)
+        val accounts = am.getAccountsByType("com.google")
+        if (accounts == null || accounts.size == 0) {
+            Log.w(TAG, "No com.google accounts found")
+            return null
+        }
+
+        var account: Account? = null
+        for (a in accounts) {
+            if (a.name.equals(accountName)) {
+                account = a
+                break
+            }
+        }
+
+        if (account == null) {
+            account = accounts[0]
+        }
+
+        try {
+            return am.blockingGetAuthToken(account!!, SCOPE, true)
+        } catch (e: Throwable) {
+            Log.e(TAG, "Error getting auth token", e)
+            return null
+        }
+    }
+}
+
 @Singleton
-class ControlsUiControllerImpl @Inject constructor() : ControlsUiController {
+class ControlsUiControllerImpl @Inject constructor (
+    val controlsController: Lazy<ControlsController>,
+    val context: Context,
+    @Main val uiExecutor: Executor
+) : ControlsUiController {
+
+    private lateinit var controlInfos: List<ControlInfo>
+    private val controlsById = mutableMapOf<Pair<ComponentName, String>, ControlWithState>()
+    private val controlViewsById = mutableMapOf<String, ControlViewHolder>()
+    private lateinit var parent: ViewGroup
+
+    override fun show(parent: ViewGroup) {
+        Log.d(TAG, "show()")
+
+        this.parent = parent
+
+        controlInfos = controlsController.get().getFavoriteControls()
+
+        controlInfos.map {
+            ControlWithState(it, null)
+        }.associateByTo(controlsById) { Pair(it.ci.component, it.ci.controlId) }
+
+        if (controlInfos.isEmpty()) {
+            showInitialSetupView()
+        } else {
+            showControlsView()
+        }
+
+        // Temp code to pass auth
+        tokenProviderConnection = TokenProviderConnection(controlsController.get(), context)
+        val serviceIntent = Intent()
+        serviceIntent.setComponent(ComponentName("com.android.systemui.home.mock",
+                "com.android.systemui.home.mock.AuthService"))
+        context.bindService(serviceIntent, tokenProviderConnection!!, Context.BIND_AUTO_CREATE)
+    }
+
+    private fun showInitialSetupView() {
+        val inflater = LayoutInflater.from(context)
+        inflater.inflate(R.layout.controls_no_favorites, parent, true)
+
+        val textView = parent.requireViewById(R.id.controls_title) as TextView
+        textView.setOnClickListener {
+            val i = Intent()
+            i.setComponent(ComponentName(context, ControlsProviderSelectorActivity::class.java))
+            i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+            context.startActivity(i)
+        }
+    }
+
+    private fun showControlsView() {
+        val inflater = LayoutInflater.from(context)
+        inflater.inflate(R.layout.controls_with_favorites, parent, true)
+
+        val listView = parent.requireViewById(R.id.global_actions_controls_list) as ViewGroup
+        var lastRow: ViewGroup = createRow(inflater, listView)
+        controlInfos.forEach {
+            Log.d(TAG, "favorited control id: " + it.controlId)
+            if (lastRow.getChildCount() == 2) {
+                lastRow = createRow(inflater, listView)
+            }
+            val item = inflater.inflate(
+                R.layout.controls_base_item, lastRow, false) as ViewGroup
+            lastRow.addView(item)
+            val cvh = ControlViewHolder(item, controlsController.get())
+            cvh.bindData(controlsById.get(Pair(it.component, it.controlId))!!)
+            controlViewsById.put(it.controlId, cvh)
+        }
+
+        val moreImageView = parent.requireViewById(R.id.controls_more) as View
+        moreImageView.setOnClickListener {
+            val i = Intent()
+            i.setComponent(ComponentName(context, ControlsProviderSelectorActivity::class.java))
+            i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+            context.startActivity(i)
+        }
+    }
+
+    override fun hide() {
+        Log.d(TAG, "hide()")
+        controlsController.get().unsubscribe()
+        context.unbindService(tokenProviderConnection)
+        tokenProviderConnection = null
+
+        parent.removeAllViews()
+        controlsById.clear()
+        controlViewsById.clear()
+    }
 
     override fun onRefreshState(componentName: ComponentName, controls: List<Control>) {
-        TODO("not implemented")
+        Log.d(TAG, "onRefreshState()")
+        controls.forEach { c ->
+            controlsById.get(Pair(componentName, c.getControlId()))?.let {
+                Log.d(TAG, "onRefreshState() for id: " + c.getControlId())
+                val cws = ControlWithState(it.ci, c)
+                controlsById.put(Pair(componentName, c.getControlId()), cws)
+
+                uiExecutor.execute {
+                    controlViewsById.get(c.getControlId())?.bindData(cws)
+                }
+            }
+        }
     }
 
     override fun onActionResponse(componentName: ComponentName, controlId: String, response: Int) {
+        Log.d(TAG, "onActionResponse()")
         TODO("not implemented")
     }
-}
\ No newline at end of file
+
+    private fun createRow(inflater: LayoutInflater, parent: ViewGroup): ViewGroup {
+        val row = inflater.inflate(R.layout.controls_row, parent, false) as ViewGroup
+        parent.addView(row)
+        return row
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
index 99dd5e2..5de88e1 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
@@ -21,6 +21,7 @@
 import com.android.systemui.SizeCompatModeActivityController;
 import com.android.systemui.SliceBroadcastRelayHandler;
 import com.android.systemui.SystemUI;
+import com.android.systemui.accessibility.SystemActions;
 import com.android.systemui.accessibility.WindowMagnification;
 import com.android.systemui.biometrics.AuthController;
 import com.android.systemui.globalactions.GlobalActionsComponent;
@@ -36,6 +37,7 @@
 import com.android.systemui.statusbar.phone.StatusBarModule;
 import com.android.systemui.statusbar.tv.TvStatusBar;
 import com.android.systemui.theme.ThemeOverlayController;
+import com.android.systemui.toast.ToastUI;
 import com.android.systemui.util.leak.GarbageMonitor;
 import com.android.systemui.volume.VolumeUI;
 
@@ -140,12 +142,24 @@
     @ClassKey(StatusBar.class)
     public abstract SystemUI bindsStatusBar(StatusBar sysui);
 
+   /** Inject into SystemActions. */
+    @Binds
+    @IntoMap
+    @ClassKey(SystemActions.class)
+    public abstract SystemUI bindSystemActions(SystemActions sysui);
+
     /** Inject into ThemeOverlayController. */
     @Binds
     @IntoMap
     @ClassKey(ThemeOverlayController.class)
     public abstract SystemUI bindThemeOverlayController(ThemeOverlayController sysui);
 
+    /** Inject into ToastUI. */
+    @Binds
+    @IntoMap
+    @ClassKey(ToastUI.class)
+    public abstract SystemUI bindToastUI(ToastUI service);
+
     /** Inject into TvStatusBar. */
     @Binds
     @IntoMap
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 36a8450..f793b3d 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -27,6 +27,7 @@
 import com.android.systemui.DumpController;
 import com.android.systemui.assist.AssistModule;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.log.dagger.LogModule;
 import com.android.systemui.model.SysUiState;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.recents.Recents;
@@ -59,9 +60,12 @@
  * A dagger module for injecting components of System UI that are not overridden by the System UI
  * implementation.
  */
-@Module(includes = {AssistModule.class,
-                    ConcurrencyModule.class,
-                    PeopleHubModule.class},
+@Module(includes = {
+            AssistModule.class,
+            ConcurrencyModule.class,
+            LogModule.class,
+            PeopleHubModule.class,
+        },
         subcomponents = {StatusBarComponent.class, NotificationRowComponent.class})
 public abstract class SystemUIModule {
 
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 83f6d45..80d776a 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -93,12 +93,13 @@
 import com.android.systemui.MultiListLayout.MultiListAdapter;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.controls.ui.ControlsUiController;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
 import com.android.systemui.plugins.GlobalActionsPanelPlugin;
-import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
 import com.android.systemui.statusbar.BlurUtils;
+import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
 import com.android.systemui.statusbar.phone.ScrimController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -183,6 +184,7 @@
     private final IStatusBarService mStatusBarService;
     private final NotificationShadeWindowController mNotificationShadeWindowController;
     private GlobalActionsPanelPlugin mPanelPlugin;
+    private ControlsUiController mControlsUiController;
 
     /**
      * @param context everything needs a context :(
@@ -200,7 +202,8 @@
             TelecomManager telecomManager, MetricsLogger metricsLogger,
             BlurUtils blurUtils, SysuiColorExtractor colorExtractor,
             IStatusBarService statusBarService,
-            NotificationShadeWindowController notificationShadeWindowController) {
+            NotificationShadeWindowController notificationShadeWindowController,
+            ControlsUiController controlsUiController) {
         mContext = new ContextThemeWrapper(context, com.android.systemui.R.style.qs_theme);
         mWindowManagerFuncs = windowManagerFuncs;
         mAudioManager = audioManager;
@@ -220,6 +223,7 @@
         mSysuiColorExtractor = colorExtractor;
         mStatusBarService = statusBarService;
         mNotificationShadeWindowController = notificationShadeWindowController;
+        mControlsUiController = controlsUiController;
 
         // receive broadcasts
         IntentFilter filter = new IntentFilter();
@@ -455,9 +459,12 @@
                                 mKeyguardManager.isDeviceLocked())
                         : null;
 
+        boolean showControls = !mKeyguardManager.isDeviceLocked() && isControlsEnabled(mContext);
+
         ActionsDialog dialog = new ActionsDialog(mContext, mAdapter, panelViewController,
                 mBlurUtils, mSysuiColorExtractor, mStatusBarService,
-                mNotificationShadeWindowController, isControlsEnabled(mContext));
+                mNotificationShadeWindowController,
+                showControls ? mControlsUiController : null);
         dialog.setCanceledOnTouchOutside(false); // Handled by the custom class.
         dialog.setKeyguardShowing(mKeyguardShowing);
 
@@ -1543,13 +1550,15 @@
         private boolean mHadTopUi;
         private final NotificationShadeWindowController mNotificationShadeWindowController;
         private final BlurUtils mBlurUtils;
-        private final boolean mControlsEnabled;
+
+        private ControlsUiController mControlsUiController;
+        private ViewGroup mControlsView;
 
         ActionsDialog(Context context, MyAdapter adapter,
                 GlobalActionsPanelPlugin.PanelViewController plugin, BlurUtils blurUtils,
                 SysuiColorExtractor sysuiColorExtractor, IStatusBarService statusBarService,
                 NotificationShadeWindowController notificationShadeWindowController,
-                boolean controlsEnabled) {
+                ControlsUiController controlsUiController) {
             super(context, com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions);
             mContext = context;
             mAdapter = adapter;
@@ -1557,7 +1566,7 @@
             mColorExtractor = sysuiColorExtractor;
             mStatusBarService = statusBarService;
             mNotificationShadeWindowController = notificationShadeWindowController;
-            mControlsEnabled = controlsEnabled;
+            mControlsUiController = controlsUiController;
 
             // Window initialization
             Window window = getWindow();
@@ -1639,6 +1648,7 @@
         private void initializeLayout() {
             setContentView(getGlobalActionsLayoutId(mContext));
             fixNavBarClipping();
+            mControlsView = findViewById(com.android.systemui.R.id.global_actions_controls);
             mGlobalActionsLayout = findViewById(com.android.systemui.R.id.global_actions_view);
             mGlobalActionsLayout.setOutsideTouchListener(view -> dismiss());
             ((View) mGlobalActionsLayout.getParent()).setOnClickListener(view -> dismiss());
@@ -1674,7 +1684,7 @@
         }
 
         private int getGlobalActionsLayoutId(Context context) {
-            if (mControlsEnabled) {
+            if (mControlsUiController != null) {
                 return com.android.systemui.R.layout.global_actions_grid_v2;
             }
 
@@ -1758,6 +1768,9 @@
                                 mBlurUtils.radiusForRatio(animatedValue));
                     })
                     .start();
+            if (mControlsUiController != null) {
+                mControlsUiController.show(mControlsView);
+            }
         }
 
         @Override
@@ -1766,6 +1779,7 @@
                 return;
             }
             mShowing = false;
+            if (mControlsUiController != null) mControlsUiController.hide();
             mGlobalActionsLayout.setTranslationX(0);
             mGlobalActionsLayout.setTranslationY(0);
             mGlobalActionsLayout.setAlpha(1);
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 2fc7a9c..14eec59 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -18,6 +18,7 @@
 
 import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
 
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.NAV_BAR_HANDLE_SHOW_OVER_LOCKSCREEN;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
@@ -53,6 +54,7 @@
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.provider.DeviceConfig;
 import android.provider.Settings;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
@@ -371,6 +373,7 @@
     private boolean mPulsing;
 
     private boolean mLockLater;
+    private boolean mShowHomeOverLockscreen;
 
     private boolean mWakeAndUnlocking;
     private IKeyguardDrawnCallback mDrawnCallback;
@@ -703,6 +706,20 @@
         mStatusBarKeyguardViewManagerLazy = statusBarKeyguardViewManagerLazy;
         mDismissCallbackRegistry = dismissCallbackRegistry;
         mUiBgExecutor = uiBgExecutor;
+        mShowHomeOverLockscreen = DeviceConfig.getBoolean(
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                NAV_BAR_HANDLE_SHOW_OVER_LOCKSCREEN,
+                /* defaultValue = */ true);
+        DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI, mHandler::post,
+                new DeviceConfig.OnPropertiesChangedListener() {
+                    @Override
+                    public void onPropertiesChanged(DeviceConfig.Properties properties) {
+                        if (properties.getKeyset().contains(NAV_BAR_HANDLE_SHOW_OVER_LOCKSCREEN)) {
+                            mShowHomeOverLockscreen = properties.getBoolean(
+                                    NAV_BAR_HANDLE_SHOW_OVER_LOCKSCREEN, true /* defaultValue */);
+                        }
+                    }
+                });
     }
 
     public void userActivity() {
@@ -1972,7 +1989,10 @@
             // windows that appear on top, ever
             int flags = StatusBarManager.DISABLE_NONE;
             if (forceHideHomeRecentsButtons || isShowingAndNotOccluded()) {
-                flags |= StatusBarManager.DISABLE_HOME | StatusBarManager.DISABLE_RECENT;
+                if (!mShowHomeOverLockscreen) {
+                    flags |= StatusBarManager.DISABLE_HOME;
+                }
+                flags |= StatusBarManager.DISABLE_RECENT;
             }
 
             if (DEBUG) {
diff --git a/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt b/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt
new file mode 100644
index 0000000..18c7bae
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log
+
+import android.util.Log
+import com.android.systemui.DumpController
+import com.android.systemui.Dumpable
+import com.android.systemui.log.dagger.LogModule
+import java.text.SimpleDateFormat
+import java.util.ArrayDeque
+import java.util.Locale
+
+/**
+ * A simple ring buffer of recyclable log messages
+ *
+ * The goal of this class is to enable logging that is both extremely chatty and extremely
+ * lightweight. If done properly, logging a message will not result in any heap allocations or
+ * string generation. Messages are only converted to strings if the log is actually dumped (usually
+ * as the result of taking a bug report).
+ *
+ * You can dump the entire buffer at any time by running:
+ *
+ * ```
+ * $ adb shell dumpsys activity service com.android.systemui/.SystemUIService \
+ *      dependency DumpController <bufferName>
+ * ```
+ *
+ * where `bufferName` is the (case-sensitive) [name] passed to the constructor.
+ *
+ * By default, only messages of WARN level or higher are echoed to logcat, but this can be adjusted
+ * locally (usually for debugging purposes).
+ *
+ * To enable logcat echoing for an entire buffer:
+ *
+ * ```
+ * $ adb shell settings put global systemui/buffer/<bufferName> <level>
+ * ```
+ *
+ * To enable logcat echoing for a specific tag:
+ *
+ * ```
+ * $ adb shell settings put global systemui/tag/<tag> <level>
+ * ```
+ *
+ * In either case, `level` can be any of `verbose`, `debug`, `info`, `warn`, `error`, `assert`, or
+ * the first letter of any of the previous.
+ *
+ * Buffers are provided by [LogModule].
+ *
+ * @param name The name of this buffer
+ * @param maxLogs The maximum number of messages to keep in memory at any one time, including the
+ * unused pool.
+ * @param poolSize The maximum amount that the size of the buffer is allowed to flex in response to
+ * sequential calls to [document] that aren't immediately followed by a matching call to [push].
+ */
+class LogBuffer(
+    private val name: String,
+    private val maxLogs: Int,
+    private val poolSize: Int,
+    private val logcatEchoTracker: LogcatEchoTracker
+) {
+    private val buffer: ArrayDeque<LogMessageImpl> = ArrayDeque()
+
+    fun attach(dumpController: DumpController) {
+        dumpController.registerDumpable(name, onDump)
+    }
+
+    /**
+     * Logs a message to the log buffer
+     *
+     * May also log the message to logcat if echoing is enabled for this buffer or tag.
+     *
+     * The actual string of the log message is not constructed until it is needed. To accomplish
+     * this, logging a message is a two-step process. First, a fresh instance  of [LogMessage] is
+     * obtained and is passed to the [initializer]. The initializer stores any relevant data on the
+     * message's fields. The message is then inserted into the buffer where it waits until it is
+     * either pushed out by newer messages or it needs to printed. If and when this latter moment
+     * occurs, the [printer] function is called on the message. It reads whatever data the
+     * initializer stored and converts it to a human-readable log message.
+     *
+     * @param tag A string of at most 23 characters, used for grouping logs into categories or
+     * subjects. If this message is echoed to logcat, this will be the tag that is used.
+     * @param level Which level to log the message at, both to the buffer and to logcat if it's
+     * echoed. In general, a module should split most of its logs into either INFO or DEBUG level.
+     * INFO level should be reserved for information that other parts of the system might care
+     * about, leaving the specifics of code's day-to-day operations to DEBUG.
+     * @param initializer A function that will be called immediately to store relevant data on the
+     * log message. The value of `this` will be the LogMessage to be initialized.
+     * @param printer A function that will be called if and when the message needs to be dumped to
+     * logcat or a bug report. It should read the data stored by the initializer and convert it to
+     * a human-readable string. The value of `this` will be the LogMessage to be printed.
+     * **IMPORTANT:** The printer should ONLY ever reference fields on the LogMessage and NEVER any
+     * variables in its enclosing scope. Otherwise, the runtime will need to allocate a new instance
+     * of the printer for each call, thwarting our attempts at avoiding any sort of allocation.
+     */
+    inline fun log(
+        tag: String,
+        level: LogLevel,
+        initializer: LogMessage.() -> Unit,
+        noinline printer: LogMessage.() -> String
+    ) {
+        val message = obtain(tag, level, printer)
+        initializer(message)
+        push(message)
+    }
+
+    /**
+     * Same as [log], but doesn't push the message to the buffer. Useful if you need to supply a
+     * "reason" for doing something (the thing you supply the reason to will presumably call [push]
+     * on that message at some point).
+     */
+    inline fun document(
+        tag: String,
+        level: LogLevel,
+        initializer: LogMessage.() -> Unit,
+        noinline printer: LogMessage.() -> String
+    ): LogMessage {
+        val message = obtain(tag, level, printer)
+        initializer(message)
+        return message
+    }
+
+    /**
+     * Obtains an instance of [LogMessageImpl], usually from the object pool. If the pool has been
+     * exhausted, creates a new instance.
+     *
+     * In general, you should call [log] or [document] instead of this method.
+     */
+    fun obtain(
+        tag: String,
+        level: LogLevel,
+        printer: (LogMessage) -> String
+    ): LogMessageImpl {
+        val message = synchronized(buffer) {
+            if (buffer.size > maxLogs - poolSize) {
+                buffer.removeFirst()
+            } else {
+                LogMessageImpl.create()
+            }
+        }
+        message.reset(tag, level, System.currentTimeMillis(), printer)
+        return message
+    }
+
+    /**
+     * Pushes a message into buffer, possibly evicting an older message if the buffer is full.
+     */
+    fun push(message: LogMessage) {
+        synchronized(buffer) {
+            if (buffer.size == maxLogs) {
+                Log.e(TAG, "LogBuffer $name has exceeded its pool size")
+                buffer.removeFirst()
+            }
+            buffer.add(message as LogMessageImpl)
+            if (logcatEchoTracker.isBufferLoggable(name, message.level) ||
+                    logcatEchoTracker.isTagLoggable(message.tag, message.level)) {
+                echoToLogcat(message)
+            }
+        }
+    }
+
+    /** Converts the entire buffer to a newline-delimited string */
+    fun dump(): String {
+        synchronized(buffer) {
+            val sb = StringBuilder()
+            for (message in buffer) {
+                dumpMessage(message, sb)
+            }
+            return sb.toString()
+        }
+    }
+
+    private fun dumpMessage(message: LogMessage, sb: StringBuilder) {
+        sb.append(DATE_FORMAT.format(message.timestamp))
+                .append(" ").append(message.level)
+                .append(" ").append(message.tag)
+                .append(" ").append(message.printer(message))
+                .append("\n")
+    }
+
+    private fun echoToLogcat(message: LogMessage) {
+        val strMessage = message.printer(message)
+        when (message.level) {
+            LogLevel.VERBOSE -> Log.v(message.tag, strMessage)
+            LogLevel.DEBUG -> Log.d(message.tag, strMessage)
+            LogLevel.INFO -> Log.i(message.tag, strMessage)
+            LogLevel.WARNING -> Log.w(message.tag, strMessage)
+            LogLevel.ERROR -> Log.e(message.tag, strMessage)
+            LogLevel.WTF -> Log.wtf(message.tag, strMessage)
+        }
+    }
+
+    private val onDump = Dumpable { _, pw, _ ->
+        pw.println(dump())
+    }
+}
+
+private const val TAG = "LogBuffer"
+private val DATE_FORMAT = SimpleDateFormat("MM-dd HH:mm:ss.S", Locale.US)
diff --git a/core/java/android/service/controls/actions/CommandAction.aidl b/packages/SystemUI/src/com/android/systemui/log/LogLevel.kt
similarity index 61%
copy from core/java/android/service/controls/actions/CommandAction.aidl
copy to packages/SystemUI/src/com/android/systemui/log/LogLevel.kt
index 7c1ee41..7b9af0f 100644
--- a/core/java/android/service/controls/actions/CommandAction.aidl
+++ b/packages/SystemUI/src/com/android/systemui/log/LogLevel.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,6 +13,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.service.controls.actions;
 
-parcelable CommandAction;
\ No newline at end of file
+package com.android.systemui.log
+
+import android.util.Log
+
+/**
+ * Enum version of @Log.Level
+ */
+enum class LogLevel(@Log.Level val nativeLevel: Int) {
+    VERBOSE(Log.VERBOSE),
+    DEBUG(Log.DEBUG),
+    INFO(Log.INFO),
+    WARNING(Log.WARN),
+    ERROR(Log.ERROR),
+    WTF(Log.ASSERT)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/LogMessage.kt b/packages/SystemUI/src/com/android/systemui/log/LogMessage.kt
new file mode 100644
index 0000000..d971ac5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/LogMessage.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log
+
+/**
+ * Generic data class for storing messages logged to a [LogBuffer]
+ *
+ * Each LogMessage has a few standard fields ([level], [tag], and [timestamp]). The rest are generic
+ * data slots that may or may not be used, depending on the nature of the specific message being
+ * logged.
+ *
+ * When a message is logged, the code doing the logging stores data in one or more of the generic
+ * fields ([str1], [int1], etc). When it comes time to dump the message to logcat/bugreport/etc, the
+ * [printer] function reads the data stored in the generic fields and converts that to a human-
+ * readable string. Thus, for every log type there must be a specialized initializer function that
+ * stores data specific to that log type and a specialized printer function that prints that data.
+ *
+ * See [LogBuffer.log] for more information.
+ */
+interface LogMessage {
+    val level: LogLevel
+    val tag: String
+    val timestamp: Long
+    val printer: LogMessage.() -> String
+
+    var str1: String?
+    var str2: String?
+    var str3: String?
+    var int1: Int
+    var int2: Int
+    var long1: Long
+    var double1: Double
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/LogMessageImpl.kt b/packages/SystemUI/src/com/android/systemui/log/LogMessageImpl.kt
new file mode 100644
index 0000000..32334bc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/LogMessageImpl.kt
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log
+
+/**
+ * Recyclable implementation of [LogMessage].
+ */
+data class LogMessageImpl(
+    override var level: LogLevel,
+    override var tag: String,
+    override var timestamp: Long,
+    override var printer: LogMessage.() -> String,
+    override var str1: String?,
+    override var str2: String?,
+    override var str3: String?,
+    override var int1: Int,
+    override var int2: Int,
+    override var long1: Long,
+    override var double1: Double
+) : LogMessage {
+
+    fun reset(
+        tag: String,
+        level: LogLevel,
+        timestamp: Long,
+        renderer: LogMessage.() -> String
+    ) {
+        this.level = level
+        this.tag = tag
+        this.timestamp = timestamp
+        this.printer = renderer
+        str1 = null
+        str2 = null
+        str3 = null
+        int1 = 0
+        int2 = 0
+        long1 = 0
+        double1 = 0.0
+    }
+
+    companion object Factory {
+        fun create(): LogMessageImpl {
+            return LogMessageImpl(
+                    LogLevel.DEBUG,
+                    DEFAULT_TAG,
+                    0,
+                    DEFAULT_RENDERER,
+                    null,
+                    null,
+                    null,
+                    0,
+                    0,
+                    0,
+                    0.0)
+        }
+    }
+}
+
+private const val DEFAULT_TAG = "UnknownTag"
+private val DEFAULT_RENDERER: LogMessage.() -> String = { "Unknown message: $this" }
diff --git a/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTracker.kt b/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTracker.kt
new file mode 100644
index 0000000..3022f4b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTracker.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log
+
+/**
+ * Keeps track of which [LogBuffer] messages should also appear in logcat.
+ */
+interface LogcatEchoTracker {
+    /**
+     * Whether [bufferName] should echo messages of [level] or higher to logcat.
+     */
+    fun isBufferLoggable(bufferName: String, level: LogLevel): Boolean
+
+    /**
+     * Whether [tagName] should echo messages of [level] or higher to logcat.
+     */
+    fun isTagLoggable(tagName: String, level: LogLevel): Boolean
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerDebug.kt b/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerDebug.kt
new file mode 100644
index 0000000..23942e1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerDebug.kt
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log
+
+import android.content.ContentResolver
+import android.database.ContentObserver
+import android.net.Uri
+import android.os.Handler
+import android.os.Looper
+import android.provider.Settings
+
+/**
+ * Version of [LogcatEchoTracker] for debuggable builds
+ *
+ * The log level of individual buffers or tags can be controlled via global settings:
+ *
+ * ```
+ * # Echo any message to <bufferName> of <level> or higher
+ * $ adb shell settings put global systemui/buffer/<bufferName> <level>
+ *
+ * # Echo any message of <tag> and of <level> or higher
+ * $ adb shell settings put global systemui/tag/<tag> <level>
+ * ```
+ */
+class LogcatEchoTrackerDebug private constructor(
+    private val contentResolver: ContentResolver
+) : LogcatEchoTracker {
+    private val cachedBufferLevels: MutableMap<String, LogLevel> = mutableMapOf()
+    private val cachedTagLevels: MutableMap<String, LogLevel> = mutableMapOf()
+
+    companion object Factory {
+        @JvmStatic
+        fun create(
+            contentResolver: ContentResolver,
+            mainLooper: Looper
+        ): LogcatEchoTrackerDebug {
+            val tracker = LogcatEchoTrackerDebug(contentResolver)
+            tracker.attach(mainLooper)
+            return tracker
+        }
+    }
+
+    private fun attach(mainLooper: Looper) {
+        contentResolver.registerContentObserver(
+                Settings.Global.getUriFor(BUFFER_PATH),
+                true,
+                object : ContentObserver(Handler(mainLooper)) {
+                    override fun onChange(selfChange: Boolean, uri: Uri) {
+                        super.onChange(selfChange, uri)
+                        cachedBufferLevels.clear()
+                    }
+                })
+
+        contentResolver.registerContentObserver(
+                Settings.Global.getUriFor(TAG_PATH),
+                true,
+                object : ContentObserver(Handler(mainLooper)) {
+                    override fun onChange(selfChange: Boolean, uri: Uri) {
+                        super.onChange(selfChange, uri)
+                        cachedTagLevels.clear()
+                    }
+                })
+    }
+
+    /**
+     * Whether [bufferName] should echo messages of [level] or higher to logcat.
+     */
+    @Synchronized
+    override fun isBufferLoggable(bufferName: String, level: LogLevel): Boolean {
+        return level.ordinal >= getLogLevel(bufferName, BUFFER_PATH, cachedBufferLevels).ordinal
+    }
+
+    /**
+     * Whether [tagName] should echo messages of [level] or higher to logcat.
+     */
+    @Synchronized
+    override fun isTagLoggable(tagName: String, level: LogLevel): Boolean {
+        return level >= getLogLevel(tagName, TAG_PATH, cachedTagLevels)
+    }
+
+    private fun getLogLevel(
+        name: String,
+        path: String,
+        cache: MutableMap<String, LogLevel>
+    ): LogLevel {
+        return cache[name] ?: readSetting("$path/$name").also { cache[name] = it }
+    }
+
+    private fun readSetting(path: String): LogLevel {
+        return try {
+            parseProp(Settings.Global.getString(contentResolver, path))
+        } catch (_: Settings.SettingNotFoundException) {
+            DEFAULT_LEVEL
+        }
+    }
+
+    private fun parseProp(propValue: String?): LogLevel {
+        return when (propValue?.toLowerCase()) {
+            "verbose" -> LogLevel.VERBOSE
+            "v" -> LogLevel.VERBOSE
+            "debug" -> LogLevel.DEBUG
+            "d" -> LogLevel.DEBUG
+            "info" -> LogLevel.INFO
+            "i" -> LogLevel.INFO
+            "warning" -> LogLevel.WARNING
+            "warn" -> LogLevel.WARNING
+            "w" -> LogLevel.WARNING
+            "error" -> LogLevel.ERROR
+            "e" -> LogLevel.ERROR
+            "assert" -> LogLevel.WTF
+            "wtf" -> LogLevel.WTF
+            else -> DEFAULT_LEVEL
+        }
+    }
+}
+
+private val DEFAULT_LEVEL = LogLevel.WARNING
+private const val BUFFER_PATH = "systemui/buffer"
+private const val TAG_PATH = "systemui/tag"
diff --git a/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerProd.kt b/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerProd.kt
new file mode 100644
index 0000000..394f624
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerProd.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log
+
+/**
+ * Production version of [LogcatEchoTracker] that isn't configurable.
+ */
+class LogcatEchoTrackerProd : LogcatEchoTracker {
+    override fun isBufferLoggable(bufferName: String, level: LogLevel): Boolean {
+        return level >= LogLevel.WARNING
+    }
+
+    override fun isTagLoggable(tagName: String, level: LogLevel): Boolean {
+        return level >= LogLevel.WARNING
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/DozeLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/DozeLog.java
new file mode 100644
index 0000000..7c5f402
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/DozeLog.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log.dagger;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.android.systemui.log.LogBuffer;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Qualifier;
+
+/** A {@link LogBuffer} for dozing-related messages. */
+@Qualifier
+@Documented
+@Retention(RUNTIME)
+public @interface DozeLog {
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
new file mode 100644
index 0000000..b1990be
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log.dagger;
+
+import android.content.ContentResolver;
+import android.os.Build;
+import android.os.Looper;
+
+import com.android.systemui.DumpController;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.log.LogBuffer;
+import com.android.systemui.log.LogcatEchoTracker;
+import com.android.systemui.log.LogcatEchoTrackerDebug;
+import com.android.systemui.log.LogcatEchoTrackerProd;
+
+import javax.inject.Singleton;
+
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * Dagger module for providing instances of {@link LogBuffer}.
+ */
+@Module
+public class LogModule {
+    /** Provides a logging buffer for doze-related logs. */
+    @Provides
+    @Singleton
+    @DozeLog
+    public static LogBuffer provideDozeLogBuffer(
+            LogcatEchoTrackerDebug bufferFilter,
+            DumpController dumpController) {
+        LogBuffer buffer = new LogBuffer("DozeLog", 100, 10, bufferFilter);
+        buffer.attach(dumpController);
+        return buffer;
+    }
+
+    /** Provides a logging buffer for all logs related to the data layer of notifications. */
+    @Provides
+    @Singleton
+    @NotificationLog
+    public static LogBuffer provideNotificationsLogBuffer(
+            LogcatEchoTracker bufferFilter,
+            DumpController dumpController) {
+        LogBuffer buffer = new LogBuffer("NotifLog2", 1000, 10, bufferFilter);
+        buffer.attach(dumpController);
+        return buffer;
+    }
+
+    /** Allows logging buffers to be tweaked via adb on debug builds but not on prod builds. */
+    @Provides
+    @Singleton
+    public static LogcatEchoTracker provideLogcatEchoTracker(
+            ContentResolver contentResolver,
+            @Main Looper looper) {
+        if (Build.IS_DEBUGGABLE) {
+            return LogcatEchoTrackerDebug.create(contentResolver, looper);
+        } else {
+            return new LogcatEchoTrackerProd();
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLog.java
new file mode 100644
index 0000000..a0b6864
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLog.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log.dagger;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.android.systemui.log.LogBuffer;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Qualifier;
+
+/** A {@link LogBuffer} for notification-related messages. */
+@Qualifier
+@Documented
+@Retention(RUNTIME)
+public @interface NotificationLog {
+}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
index 8e34a90..6f03f18 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
@@ -261,8 +261,6 @@
             mPinnedStackController.startAnimation(destinationBounds, sourceRectHint,
                     -1 /* animationDuration */);
             mLastDestinationBounds.set(destinationBounds);
-            mPinnedStackController.reportBounds(defaultBounds,
-                    getMovementBounds(defaultBounds));
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to start PiP animation from SysUI", e);
         }
@@ -317,7 +315,6 @@
             outBounds.set(postChangeStackBounds);
             mLastDestinationBounds.set(outBounds);
             mPinnedStackController.resetBoundsAnimation(outBounds);
-            mPinnedStackController.reportBounds(outBounds, getMovementBounds(outBounds));
             t.setBounds(pinnedStackInfo.stackToken, outBounds);
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to resize PiP on display rotation", e);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index f39d1ec..e48a23f 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -297,6 +297,13 @@
     }
 
     /**
+     * Sets a customized touch gesture that replaces the default one.
+     */
+    public void setTouchGesture(PipTouchGesture gesture) {
+        mTouchHandler.setTouchGesture(gesture);
+    }
+
+    /**
      * Sets both shelf visibility and its height.
      */
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchGesture.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchGesture.java
index e8e8a4d..72335db 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchGesture.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchGesture.java
@@ -24,19 +24,19 @@
     /**
      * Handle the touch down.
      */
-    void onDown(PipTouchState touchState) {}
+    public void onDown(PipTouchState touchState) {}
 
     /**
      * Handle the touch move, and return whether the event was consumed.
      */
-    boolean onMove(PipTouchState touchState) {
+    public boolean onMove(PipTouchState touchState) {
         return false;
     }
 
     /**
      * Handle the touch up, and return whether the gesture was consumed.
      */
-    boolean onUp(PipTouchState touchState) {
+    public boolean onUp(PipTouchState touchState) {
         return false;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 09f1638..65cc666 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -126,8 +126,8 @@
     // Touch state
     private final PipTouchState mTouchState;
     private final FlingAnimationUtils mFlingAnimationUtils;
-    private final PipTouchGesture[] mGestures;
     private final PipMotionHelper mMotionHelper;
+    private PipTouchGesture mGesture;
 
     // Temp vars
     private final Rect mTmpBounds = new Rect();
@@ -185,9 +185,7 @@
         mSnapAlgorithm = new PipSnapAlgorithm(mContext);
         mFlingAnimationUtils = new FlingAnimationUtils(context.getResources().getDisplayMetrics(),
                 2.5f);
-        mGestures = new PipTouchGesture[] {
-                mDefaultMovementGesture
-        };
+        mGesture = new DefaultPipTouchGesture();
         mMotionHelper = new PipMotionHelper(mContext, mActivityManager, mActivityTaskManager,
                 mMenuController, mSnapAlgorithm, mFlingAnimationUtils);
         mTouchState = new PipTouchState(mViewConfig, mHandler,
@@ -210,6 +208,10 @@
                 this::onAccessibilityShowMenu, mHandler);
     }
 
+    public void setTouchGesture(PipTouchGesture gesture) {
+        mGesture = gesture;
+    }
+
     public void setTouchEnabled(boolean enabled) {
         mTouchState.setAllowTouches(enabled);
     }
@@ -363,17 +365,12 @@
         switch (ev.getAction()) {
             case MotionEvent.ACTION_DOWN: {
                 mMotionHelper.synchronizePinnedStackBounds();
-
-                for (PipTouchGesture gesture : mGestures) {
-                    gesture.onDown(mTouchState);
-                }
+                mGesture.onDown(mTouchState);
                 break;
             }
             case MotionEvent.ACTION_MOVE: {
-                for (PipTouchGesture gesture : mGestures) {
-                    if (gesture.onMove(mTouchState)) {
-                        break;
-                    }
+                if (mGesture.onMove(mTouchState)) {
+                    break;
                 }
 
                 shouldDeliverToMenu = !mTouchState.isDragging();
@@ -384,10 +381,8 @@
                 // dragging (ie. when the IME shows)
                 updateMovementBounds(mMenuState);
 
-                for (PipTouchGesture gesture : mGestures) {
-                    if (gesture.onUp(mTouchState)) {
-                        break;
-                    }
+                if (mGesture.onUp(mTouchState)) {
+                    break;
                 }
 
                 // Fall through to clean up
@@ -591,7 +586,7 @@
     /**
      * Gesture controlling normal movement of the PIP.
      */
-    private PipTouchGesture mDefaultMovementGesture = new PipTouchGesture() {
+    private class DefaultPipTouchGesture extends PipTouchGesture {
         // Whether the PiP was on the left side of the screen at the start of the gesture
         private boolean mStartedOnLeft;
         private final Point mStartPosition = new Point();
@@ -623,7 +618,7 @@
         }
 
         @Override
-        boolean onMove(PipTouchState touchState) {
+        public boolean onMove(PipTouchState touchState) {
             if (!touchState.isUserInteracting()) {
                 return false;
             }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index 411980b..557c64b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -191,6 +191,7 @@
         mTile.setLabel(tile.getLabel());
         mTile.setSubtitle(tile.getSubtitle());
         mTile.setContentDescription(tile.getContentDescription());
+        mTile.setStateDescription(tile.getStateDescription());
         mTile.setState(tile.getState());
     }
 
@@ -345,6 +346,12 @@
             state.contentDescription = state.label;
         }
 
+        if (mTile.getStateDescription() != null) {
+            state.stateDescription = mTile.getStateDescription();
+        } else {
+            state.stateDescription = null;
+        }
+
         if (state instanceof BooleanState) {
             state.expandedAccessibilityClassName = Switch.class.getName();
             ((BooleanState) state).value = (state.state == Tile.STATE_ACTIVE);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
index 8b7f280..fda9e5b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
@@ -65,7 +65,6 @@
     private String mAccessibilityClass;
     private boolean mTileState;
     private boolean mCollapsedView;
-    private boolean mClicked;
     private boolean mShowRippleEffect = true;
 
     private final ImageView mBg;
@@ -234,13 +233,35 @@
         setLongClickable(state.handlesLongClick);
         mIcon.setIcon(state, allowAnimations);
         setContentDescription(state.contentDescription);
+        final StringBuilder stateDescription = new StringBuilder();
+        switch (state.state) {
+            case Tile.STATE_UNAVAILABLE:
+                stateDescription.append(mContext.getString(R.string.tile_unavailable));
+                break;
+            case Tile.STATE_INACTIVE:
+                if (state instanceof QSTile.BooleanState) {
+                    stateDescription.append(mContext.getString(R.string.switch_bar_off));
+                }
+                break;
+            case Tile.STATE_ACTIVE:
+                if (state instanceof QSTile.BooleanState) {
+                    stateDescription.append(mContext.getString(R.string.switch_bar_on));
+                }
+                break;
+            default:
+                break;
+        }
+        if (!TextUtils.isEmpty(state.stateDescription)) {
+            stateDescription.append(", ");
+            stateDescription.append(state.stateDescription);
+        }
+        setStateDescription(stateDescription.toString());
 
         mAccessibilityClass =
                 state.state == Tile.STATE_UNAVAILABLE ? null : state.expandedAccessibilityClassName;
         if (state instanceof QSTile.BooleanState) {
             boolean newState = ((BooleanState) state).value;
             if (mTileState != newState) {
-                mClicked = false;
                 mTileState = newState;
             }
         }
@@ -297,23 +318,10 @@
     }
 
     @Override
-    public boolean performClick() {
-        mClicked = true;
-        return super.performClick();
-    }
-
-    @Override
     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
         super.onInitializeAccessibilityEvent(event);
         if (!TextUtils.isEmpty(mAccessibilityClass)) {
             event.setClassName(mAccessibilityClass);
-            if (Switch.class.getName().equals(mAccessibilityClass)) {
-                boolean b = mClicked ? !mTileState : mTileState;
-                String label = getResources()
-                        .getString(b ? R.string.switch_bar_on : R.string.switch_bar_off);
-                event.setContentDescription(label);
-                event.setChecked(b);
-            }
         }
     }
 
@@ -325,11 +333,6 @@
         if (!TextUtils.isEmpty(mAccessibilityClass)) {
             info.setClassName(mAccessibilityClass);
             if (Switch.class.getName().equals(mAccessibilityClass)) {
-                boolean b = mClicked ? !mTileState : mTileState;
-                String label = getResources()
-                        .getString(b ? R.string.switch_bar_on : R.string.switch_bar_off);
-                info.setText(label);
-                info.setChecked(b);
                 info.setCheckable(true);
                 if (isLongClickable()) {
                     info.addAction(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 9282a2e..361b6c1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -134,25 +134,27 @@
         state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
         state.secondaryLabel = TextUtils.emptyIfNull(
                 getSecondaryLabel(enabled, connecting, connected, state.isTransient));
+        state.contentDescription = state.label;
+        state.stateDescription = "";
         if (enabled) {
             if (connected) {
                 state.icon = new BluetoothConnectedTileIcon();
                 if (!TextUtils.isEmpty(mController.getConnectedDeviceName())) {
                     state.label = mController.getConnectedDeviceName();
                 }
-                state.contentDescription =
+                state.stateDescription =
                         mContext.getString(R.string.accessibility_bluetooth_name, state.label)
                                 + ", " + state.secondaryLabel;
             } else if (state.isTransient) {
                 state.icon = ResourceIcon.get(
                         com.android.internal.R.drawable.ic_bluetooth_transient_animation);
-                state.contentDescription = state.secondaryLabel;
+                state.stateDescription = state.secondaryLabel;
             } else {
                 state.icon =
                         ResourceIcon.get(com.android.internal.R.drawable.ic_qs_bluetooth);
                 state.contentDescription = mContext.getString(
-                        R.string.accessibility_quick_settings_bluetooth) + ","
-                        + mContext.getString(R.string.accessibility_not_connected);
+                        R.string.accessibility_quick_settings_bluetooth);
+                state.stateDescription = mContext.getString(R.string.accessibility_not_connected);
             }
             state.state = Tile.STATE_ACTIVE;
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 0e813d1..58de057 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -183,6 +183,7 @@
     protected void handleUpdateState(BooleanState state, Object arg) {
         state.label = mContext.getString(R.string.quick_settings_cast_title);
         state.contentDescription = state.label;
+        state.stateDescription = "";
         state.value = false;
         final List<CastDevice> devices = mController.getCastDevices();
         boolean connecting = false;
@@ -192,8 +193,9 @@
             if (device.state == CastDevice.STATE_CONNECTED) {
                 state.value = true;
                 state.secondaryLabel = getDeviceName(device);
-                state.contentDescription = state.contentDescription + "," +
-                        mContext.getString(R.string.accessibility_cast_name, state.label);
+                state.stateDescription = state.stateDescription + ","
+                        + mContext.getString(
+                                R.string.accessibility_cast_name, state.label);
                 connecting = false;
                 break;
             } else if (device.state == CastDevice.STATE_CONNECTING) {
@@ -217,9 +219,8 @@
             state.state = Tile.STATE_UNAVAILABLE;
             String noWifi = mContext.getString(R.string.quick_settings_cast_no_wifi);
             state.secondaryLabel = noWifi;
-            state.contentDescription = state.contentDescription + ", " + mContext.getString(
-                    R.string.accessibility_quick_settings_not_available, noWifi);
         }
+        state.stateDescription = state.stateDescription + ", " + state.secondaryLabel;
         mDetailAdapter.updateItems(devices);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 22470c7..d5f86c9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -194,17 +194,13 @@
             state.secondaryLabel = r.getString(R.string.cell_data_off);
         }
 
-
-        // TODO(b/77881974): Instead of switching out the description via a string check for
-        // we need to have two strings provided by the MobileIconGroup.
-        final CharSequence contentDescriptionSuffix;
+        state.contentDescription = state.label;
         if (state.state == Tile.STATE_INACTIVE) {
-            contentDescriptionSuffix = r.getString(R.string.cell_data_off_content_description);
+            // This information is appended later by converting the Tile.STATE_INACTIVE state.
+            state.stateDescription = "";
         } else {
-            contentDescriptionSuffix = state.secondaryLabel;
+            state.stateDescription = state.secondaryLabel;
         }
-
-        state.contentDescription = state.label + ", " + contentDescriptionSuffix;
     }
 
     private CharSequence appendMobileDataType(CharSequence current, CharSequence dataType) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 52d1a5b3..9215da4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -240,6 +240,8 @@
                 zen != Global.ZEN_MODE_OFF, mController.getConfig(), false));
         state.icon = ResourceIcon.get(com.android.internal.R.drawable.ic_qs_dnd);
         checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_ADJUST_VOLUME);
+        // Keeping the secondaryLabel in contentDescription instead of stateDescription is easier
+        // to understand.
         switch (zen) {
             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
                 state.contentDescription =
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index dafdd89..792c364 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -102,14 +102,13 @@
         }
         state.label = mHost.getContext().getString(R.string.quick_settings_flashlight_label);
         state.secondaryLabel = "";
+        state.stateDescription = "";
         if (!mFlashlightController.isAvailable()) {
             state.icon = mIcon;
             state.slash.isSlashed = true;
             state.secondaryLabel = mContext.getString(
                     R.string.quick_settings_flashlight_camera_in_use);
-            state.contentDescription = mContext.getString(
-                    R.string.accessibility_quick_settings_flashlight_unavailable)
-                    + ", " + state.secondaryLabel;
+            state.stateDescription = state.secondaryLabel;
             state.state = Tile.STATE_UNAVAILABLE;
             return;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index 001e094..fd6b936 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -147,6 +147,7 @@
 
         state.secondaryLabel = getSecondaryLabel(
                 isTileActive, isTransient, isDataSaverEnabled, numConnectedDevices);
+        state.stateDescription = state.secondaryLabel;
     }
 
     @Nullable
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index fbdca3b..e617867 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -105,15 +105,8 @@
         }
         state.icon = mIcon;
         state.slash.isSlashed = !state.value;
-        if (locationEnabled) {
-            state.label = mContext.getString(R.string.quick_settings_location_label);
-            state.contentDescription = mContext.getString(
-                    R.string.accessibility_quick_settings_location_on);
-        } else {
-            state.label = mContext.getString(R.string.quick_settings_location_label);
-            state.contentDescription = mContext.getString(
-                    R.string.accessibility_quick_settings_location_off);
-        }
+        state.label = mContext.getString(R.string.quick_settings_location_label);
+        state.contentDescription = state.label;
         state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
         state.expandedAccessibilityClassName = Switch.class.getName();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index b7ce101..6e8dcf3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -195,6 +195,7 @@
         state.activityIn = cb.enabled && cb.activityIn;
         state.activityOut = cb.enabled && cb.activityOut;
         final StringBuffer minimalContentDescription = new StringBuffer();
+        final StringBuffer minimalStateDescription = new StringBuffer();
         final Resources r = mContext.getResources();
         if (isTransient) {
             state.icon = ResourceIcon.get(
@@ -219,13 +220,14 @@
                 mContext.getString(R.string.quick_settings_wifi_label)).append(",");
         if (state.value) {
             if (wifiConnected) {
-                minimalContentDescription.append(cb.wifiSignalContentDescription).append(",");
+                minimalStateDescription.append(cb.wifiSignalContentDescription);
                 minimalContentDescription.append(removeDoubleQuotes(cb.ssid));
                 if (!TextUtils.isEmpty(state.secondaryLabel)) {
                     minimalContentDescription.append(",").append(state.secondaryLabel);
                 }
             }
         }
+        state.stateDescription = minimalStateDescription.toString();
         state.contentDescription = minimalContentDescription.toString();
         state.dualLabelContentDescription = r.getString(
                 R.string.accessibility_quick_settings_open_settings, getTileLabel());
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
index 7853dc3..e54ee51 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
@@ -103,14 +103,11 @@
         state.icon = mIcon;
         if (state.value) {
             state.slash.isSlashed = false;
-            state.contentDescription =  mContext.getString(
-                    R.string.accessibility_quick_settings_work_mode_on);
         } else {
             state.slash.isSlashed = true;
-            state.contentDescription =  mContext.getString(
-                    R.string.accessibility_quick_settings_work_mode_off);
         }
         state.label = mContext.getString(R.string.quick_settings_work_mode_label);
+        state.contentDescription = state.label;
         state.expandedAccessibilityClassName = Switch.class.getName();
         state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 569f660..573ea4d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -29,6 +29,7 @@
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TRACING_ENABLED;
 
 import android.annotation.FloatRange;
 import android.app.ActivityTaskManager;
@@ -38,6 +39,8 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
+import android.graphics.Bitmap;
+import android.graphics.Insets;
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.hardware.input.InputManager;
@@ -55,6 +58,7 @@
 import android.view.accessibility.AccessibilityManager;
 
 import com.android.internal.policy.ScreenDecorationsUtils;
+import com.android.internal.util.ScreenshotHelper;
 import com.android.systemui.Dumpable;
 import com.android.systemui.model.SysUiState;
 import com.android.systemui.pip.PipUI;
@@ -64,6 +68,7 @@
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.NavigationBarController;
 import com.android.systemui.statusbar.phone.NavigationBarFragment;
 import com.android.systemui.statusbar.phone.NavigationBarView;
@@ -115,6 +120,7 @@
     private final DeviceProvisionedController mDeviceProvisionedController;
     private final List<OverviewProxyListener> mConnectionCallbacks = new ArrayList<>();
     private final Intent mQuickStepIntent;
+    private final ScreenshotHelper mScreenshotHelper;
 
     private Region mActiveNavBarRegion;
 
@@ -365,6 +371,13 @@
             }
         }
 
+        @Override
+        public void handleImageAsScreenshot(Bitmap screenImage, Rect locationInScreen,
+                Insets visibleInsets, int taskId) {
+            mScreenshotHelper.provideScreenshot(screenImage, locationInScreen, visibleInsets,
+                    taskId, mHandler, null);
+        }
+
         private boolean verifyCaller(String reason) {
             final int callerId = Binder.getCallingUserHandle().getIdentifier();
             if (callerId != mCurrentBoundedUserId) {
@@ -474,7 +487,8 @@
 
     @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
     @Inject
-    public OverviewProxyService(Context context, DeviceProvisionedController provisionController,
+    public OverviewProxyService(Context context, CommandQueue commandQueue,
+            DeviceProvisionedController provisionController,
             NavigationBarController navBarController, NavigationModeController navModeController,
             NotificationShadeWindowController statusBarWinController, SysUiState sysUiState,
             PipUI pipUI, Optional<Divider> dividerOptional,
@@ -518,6 +532,16 @@
 
         // Listen for status bar state changes
         statusBarWinController.registerCallback(mStatusBarWindowCallback);
+        mScreenshotHelper = new ScreenshotHelper(context);
+
+        // Listen for tracing state changes
+        commandQueue.addCallback(new CommandQueue.Callbacks() {
+            @Override
+            public void onTracingStateChanged(boolean enabled) {
+                mSysUiState.setFlag(SYSUI_STATE_TRACING_ENABLED, enabled)
+                        .commitUpdate(mContext.getDisplayId());
+            }
+        });
     }
 
     public void notifyBackAction(boolean completed, int downX, int downY, boolean isButton,
@@ -561,14 +585,12 @@
 
     private void onStatusBarStateChanged(boolean keyguardShowing, boolean keyguardOccluded,
             boolean bouncerShowing) {
-        int displayId = mContext.getDisplayId();
-
         mSysUiState.setFlag(SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING,
                         keyguardShowing && !keyguardOccluded)
                 .setFlag(SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED,
                         keyguardShowing && keyguardOccluded)
                 .setFlag(SYSUI_STATE_BOUNCER_SHOWING, bouncerShowing)
-                .commitUpdate(displayId);
+                .commitUpdate(mContext.getDisplayId());
     }
 
     /**
@@ -589,10 +611,6 @@
         }
     }
 
-    public float getBackButtonAlpha() {
-        return mNavBarButtonAlpha;
-    }
-
     public void cleanupAfterDeath() {
         if (mInputFocusTransferStarted) {
             mHandler.post(()-> {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 99a9dfe..880b8f8 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -29,6 +29,7 @@
 import android.animation.ValueAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.annotation.Nullable;
+import android.annotation.SuppressLint;
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.app.Notification;
@@ -38,6 +39,7 @@
 import android.content.Intent;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
+import android.graphics.Insets;
 import android.graphics.Outline;
 import android.graphics.PixelFormat;
 import android.graphics.PointF;
@@ -300,8 +302,11 @@
         int width = crop.width();
         int height = crop.height();
 
-        // Take the screenshot
-        mScreenBitmap = SurfaceControl.screenshot(crop, width, height, rot);
+        takeScreenshot(SurfaceControl.screenshot(crop, width, height, rot), finisher, null);
+    }
+
+    private void takeScreenshot(Bitmap screenshot, Consumer<Uri> finisher, Rect screenRect) {
+        mScreenBitmap = screenshot;
         if (mScreenBitmap == null) {
             mNotificationsController.notifyScreenshotError(
                     R.string.screenshot_failed_to_capture_text);
@@ -317,7 +322,8 @@
         mScreenshotLayout.getViewTreeObserver().addOnComputeInternalInsetsListener(this);
 
         // Start the post-screenshot animation
-        startAnimation(finisher, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels);
+        startAnimation(finisher, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels,
+                screenRect);
     }
 
     void takeScreenshot(Consumer<Uri> finisher) {
@@ -327,9 +333,16 @@
                 new Rect(0, 0, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels));
     }
 
+    void handleImageAsScreenshot(Bitmap screenshot, Rect screenshotScreenBounds,
+            Insets visibleInsets, int taskId, Consumer<Uri> finisher) {
+        // TODO use taskId and visibleInsets
+        takeScreenshot(screenshot, finisher, screenshotScreenBounds);
+    }
+
     /**
      * Displays a screenshot selector
      */
+    @SuppressLint("ClickableViewAccessibility")
     void takeScreenshotPartial(final Consumer<Uri> finisher) {
         mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams);
         mScreenshotSelectorView.setOnTouchListener(new View.OnTouchListener() {
@@ -402,7 +415,8 @@
     /**
      * Starts the animation after taking the screenshot
      */
-    private void startAnimation(final Consumer<Uri> finisher, int w, int h) {
+    private void startAnimation(final Consumer<Uri> finisher, int w, int h,
+            @Nullable Rect screenRect) {
         // If power save is on, show a toast so there is some visual indication that a screenshot
         // has been taken.
         PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
@@ -422,7 +436,8 @@
             mScreenshotAnimation.removeAllListeners();
         }
 
-        ValueAnimator screenshotDropInAnim = createScreenshotDropInAnimation();
+        ValueAnimator screenshotDropInAnim = screenRect != null ? createRectAnimation(screenRect)
+                : createScreenshotDropInAnimation();
         ValueAnimator screenshotFadeOutAnim = createScreenshotToCornerAnimation(w, h);
         mScreenshotAnimation = new AnimatorSet();
         mScreenshotAnimation.playSequentially(screenshotDropInAnim, screenshotFadeOutAnim);
@@ -460,6 +475,46 @@
         });
     }
 
+    private ValueAnimator createRectAnimation(Rect rect) {
+        mScreenshotView.setAdjustViewBounds(true);
+        mScreenshotView.setMaxHeight(rect.height());
+        mScreenshotView.setMaxWidth(rect.width());
+
+        final float flashPeakDurationPct = ((float) (SCREENSHOT_FLASH_TO_PEAK_DURATION)
+                / SCREENSHOT_DROP_IN_DURATION);
+        final float flashDurationPct = 2f * flashPeakDurationPct;
+        final Interpolator scaleInterpolator = x -> {
+            // We start scaling when the flash is at it's peak
+            if (x < flashPeakDurationPct) {
+                return 0;
+            }
+            return (x - flashDurationPct) / (1f - flashDurationPct);
+        };
+
+        ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
+        anim.setDuration(SCREENSHOT_DROP_IN_DURATION);
+        anim.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animation) {
+                mBackgroundView.setAlpha(0f);
+                mBackgroundView.setVisibility(View.VISIBLE);
+                mScreenshotView.setAlpha(0f);
+                mScreenshotView.setElevation(0f);
+                mScreenshotView.setTranslationX(0f);
+                mScreenshotView.setTranslationY(0f);
+                mScreenshotView.setScaleX(1f);
+                mScreenshotView.setScaleY(1f);
+                mScreenshotView.setVisibility(View.VISIBLE);
+            }
+        });
+        anim.addUpdateListener(animation -> {
+            float t = (Float) animation.getAnimatedValue();
+            mBackgroundView.setAlpha(scaleInterpolator.getInterpolation(t) * BACKGROUND_ALPHA);
+            mScreenshotView.setAlpha(t);
+        });
+        return anim;
+    }
+
     private ValueAnimator createScreenshotDropInAnimation() {
         final float flashPeakDurationPct = ((float) (SCREENSHOT_FLASH_TO_PEAK_DURATION)
                 / SCREENSHOT_DROP_IN_DURATION);
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshotLegacy.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshotLegacy.java
index a5baa7a..f3614ff 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshotLegacy.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshotLegacy.java
@@ -30,6 +30,7 @@
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Color;
+import android.graphics.Insets;
 import android.graphics.PixelFormat;
 import android.graphics.PointF;
 import android.graphics.Rect;
@@ -205,8 +206,13 @@
         int width = crop.width();
         int height = crop.height();
 
-        // Take the screenshot
-        mScreenBitmap = SurfaceControl.screenshot(crop, width, height, rot);
+        takeScreenshot(SurfaceControl.screenshot(crop, width, height, rot), finisher,
+                statusBarVisible, navBarVisible, null);
+    }
+
+    private void takeScreenshot(Bitmap screenshot, Consumer<Uri> finisher, boolean statusBarVisible,
+            boolean navBarVisible, Rect screenboundsOfBitmap) {
+        mScreenBitmap = screenshot;
         if (mScreenBitmap == null) {
             mNotificationsController.notifyScreenshotError(
                     R.string.screenshot_failed_to_capture_text);
@@ -220,7 +226,7 @@
 
         // Start the post-screenshot animation
         startAnimation(finisher, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels,
-                statusBarVisible, navBarVisible);
+                statusBarVisible, navBarVisible, screenboundsOfBitmap);
     }
 
     void takeScreenshot(Consumer<Uri> finisher, boolean statusBarVisible, boolean navBarVisible) {
@@ -229,6 +235,12 @@
                 new Rect(0, 0, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels));
     }
 
+    void handleImageAsScreenshot(Bitmap screenshot, Rect screenshotScreenBounds,
+            Insets visibleInsets, int taskId, Consumer<Uri> finisher) {
+        // TODO use taskId and visibleInsets
+        takeScreenshot(screenshot, finisher, false, false, screenshotScreenBounds);
+    }
+
     /**
      * Displays a screenshot selector
      */
@@ -302,7 +314,7 @@
      * Starts the animation after taking the screenshot
      */
     private void startAnimation(final Consumer<Uri> finisher, int w, int h,
-            boolean statusBarVisible, boolean navBarVisible) {
+            boolean statusBarVisible, boolean navBarVisible, @Nullable Rect screenBoundsOfBitmap) {
         // If power save is on, show a toast so there is some visual indication that a screenshot
         // has been taken.
         PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
@@ -323,7 +335,8 @@
         }
 
         mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams);
-        ValueAnimator screenshotDropInAnim = createScreenshotDropInAnimation();
+        ValueAnimator screenshotDropInAnim = screenBoundsOfBitmap != null
+                ? createRectAnimation(screenBoundsOfBitmap) : createScreenshotDropInAnimation();
         ValueAnimator screenshotFadeOutAnim =
                 createScreenshotDropOutAnimation(w, h, statusBarVisible, navBarVisible);
         mScreenshotAnimation = new AnimatorSet();
@@ -430,6 +443,53 @@
         return anim;
     }
 
+    /**
+     * If a bitmap was supplied to be used as the screenshot, animated from where that bitmap was
+     * on screen, rather than using the whole screen.
+     */
+    private ValueAnimator createRectAnimation(Rect rect) {
+        mScreenshotView.setAdjustViewBounds(true);
+        mScreenshotView.setMaxHeight(rect.height());
+        mScreenshotView.setMaxWidth(rect.width());
+
+        final float flashPeakDurationPct = ((float) (SCREENSHOT_FLASH_TO_PEAK_DURATION)
+                / SCREENSHOT_DROP_IN_DURATION);
+        final float flashDurationPct = 2f * flashPeakDurationPct;
+        final Interpolator scaleInterpolator = x -> {
+            // We start scaling when the flash is at it's peak
+            if (x < flashPeakDurationPct) {
+                return 0;
+            }
+            return (x - flashDurationPct) / (1f - flashDurationPct);
+        };
+
+        ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
+        anim.setDuration(SCREENSHOT_DROP_IN_DURATION);
+        anim.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animation) {
+                mBackgroundView.setAlpha(0f);
+                mBackgroundView.setVisibility(View.VISIBLE);
+                mScreenshotView.setAlpha(0f);
+                mScreenshotView.setElevation(0f);
+                mScreenshotView.setTranslationX(0f);
+                mScreenshotView.setTranslationY(0f);
+                mScreenshotView.setScaleX(SCREENSHOT_SCALE + mBgPaddingScale);
+                mScreenshotView.setScaleY(SCREENSHOT_SCALE + mBgPaddingScale);
+                mScreenshotView.setVisibility(View.VISIBLE);
+            }
+        });
+        anim.addUpdateListener(animation -> {
+            float t = (Float) animation.getAnimatedValue();
+            float scaleT = (SCREENSHOT_SCALE + mBgPaddingScale)
+                    - scaleInterpolator.getInterpolation(t)
+                    * (SCREENSHOT_SCALE - SCREENSHOT_DROP_IN_MIN_SCALE);
+            mBackgroundView.setAlpha(scaleInterpolator.getInterpolation(t) * BACKGROUND_ALPHA);
+            mScreenshotView.setAlpha(t);
+        });
+        return anim;
+    }
+
     private ValueAnimator createScreenshotDropOutAnimation(int w, int h, boolean statusBarVisible,
             boolean navBarVisible) {
         ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
index 9570b5a..4ac59df 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
@@ -22,6 +22,9 @@
 
 import android.app.Service;
 import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.Insets;
+import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.IBinder;
@@ -85,6 +88,22 @@
                                 finisher, msg.arg1 > 0, msg.arg2 > 0);
                     }
                     break;
+                case WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE:
+                    Bitmap screenshot = msg.getData().getParcelable(
+                            WindowManager.PARCEL_KEY_SCREENSHOT_BITMAP);
+                    Rect screenBounds = msg.getData().getParcelable(
+                            WindowManager.PARCEL_KEY_SCREENSHOT_BOUNDS);
+                    Insets insets = msg.getData().getParcelable(
+                            WindowManager.PARCEL_KEY_SCREENSHOT_INSETS);
+                    int taskId = msg.getData().getInt(WindowManager.PARCEL_KEY_SCREENSHOT_TASK_ID);
+                    if (useCornerFlow) {
+                        mScreenshot.handleImageAsScreenshot(
+                                screenshot, screenBounds, insets, taskId, finisher);
+                    } else {
+                        mScreenshotLegacy.handleImageAsScreenshot(
+                                screenshot, screenBounds, insets, taskId, finisher);
+                    }
+                    break;
                 default:
                     Log.d(TAG, "Invalid screenshot option: " + msg.what);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 7c0f4f9..64f0830 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -25,6 +25,8 @@
 
 import static com.android.systemui.statusbar.phone.StatusBar.ONLY_CORE_APPS;
 
+import android.annotation.Nullable;
+import android.app.ITransientNotificationCallback;
 import android.app.StatusBarManager;
 import android.app.StatusBarManager.Disable2Flags;
 import android.app.StatusBarManager.DisableFlags;
@@ -51,6 +53,7 @@
 import com.android.internal.view.AppearanceRegion;
 import com.android.systemui.statusbar.CommandQueue.Callbacks;
 import com.android.systemui.statusbar.policy.CallbackController;
+import com.android.systemui.tracing.ProtoTracer;
 
 import java.util.ArrayList;
 
@@ -119,6 +122,9 @@
     private static final int MSG_TOP_APP_WINDOW_CHANGED            = 50 << MSG_SHIFT;
     private static final int MSG_SHOW_INATTENTIVE_SLEEP_WARNING    = 51 << MSG_SHIFT;
     private static final int MSG_DISMISS_INATTENTIVE_SLEEP_WARNING = 52 << MSG_SHIFT;
+    private static final int MSG_SHOW_TOAST                        = 53 << MSG_SHIFT;
+    private static final int MSG_HIDE_TOAST                        = 54 << MSG_SHIFT;
+    private static final int MSG_TRACING_STATE_CHANGED             = 55 << MSG_SHIFT;
 
     public static final int FLAG_EXCLUDE_NONE = 0;
     public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -139,6 +145,7 @@
      * event.
      */
     private int mLastUpdatedImeDisplayId = INVALID_DISPLAY;
+    private ProtoTracer mProtoTracer;
 
     /**
      * These methods are called back on the main thread.
@@ -308,9 +315,32 @@
          * due to prolonged user inactivity should be dismissed.
          */
         default void dismissInattentiveSleepWarning(boolean animated) { }
+
+        /**
+         * @see IStatusBar#showToast(String, IBinder, CharSequence, IBinder, int,
+         * ITransientNotificationCallback)
+         */
+        default void showToast(String packageName, IBinder token, CharSequence text,
+                IBinder windowToken, int duration,
+                @Nullable ITransientNotificationCallback callback) { }
+
+        /**
+         * @see IStatusBar#hideToast(String, IBinder) (String, IBinder)
+         */
+        default void hideToast(String packageName, IBinder token) { }
+
+        /**
+         * @param enabled
+         */
+        default void onTracingStateChanged(boolean enabled) { }
     }
 
     public CommandQueue(Context context) {
+        this(context, null);
+    }
+
+    public CommandQueue(Context context, ProtoTracer protoTracer) {
+        mProtoTracer = protoTracer;
         context.getSystemService(DisplayManager.class).registerDisplayListener(this, mHandler);
         // We always have default display.
         setDisabled(DEFAULT_DISPLAY, DISABLE_NONE, DISABLE2_NONE);
@@ -761,6 +791,31 @@
     }
 
     @Override
+    public void showToast(String packageName, IBinder token, CharSequence text,
+            IBinder windowToken, int duration, @Nullable ITransientNotificationCallback callback) {
+        synchronized (mLock) {
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = packageName;
+            args.arg2 = token;
+            args.arg3 = text;
+            args.arg4 = windowToken;
+            args.arg5 = callback;
+            args.argi1 = duration;
+            mHandler.obtainMessage(MSG_SHOW_TOAST, args).sendToTarget();
+        }
+    }
+
+    @Override
+    public void hideToast(String packageName, IBinder token) {
+        synchronized (mLock) {
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = packageName;
+            args.arg2 = token;
+            mHandler.obtainMessage(MSG_HIDE_TOAST, args).sendToTarget();
+        }
+    }
+
+    @Override
     public void onBiometricAuthenticated() {
         synchronized (mLock) {
             mHandler.obtainMessage(MSG_BIOMETRIC_AUTHENTICATED).sendToTarget();
@@ -875,6 +930,26 @@
         }
     }
 
+    @Override
+    public void startTracing() {
+        synchronized (mLock) {
+            if (mProtoTracer != null) {
+                mProtoTracer.start();
+            }
+            mHandler.obtainMessage(MSG_TRACING_STATE_CHANGED, true).sendToTarget();
+        }
+    }
+
+    @Override
+    public void stopTracing() {
+        synchronized (mLock) {
+            if (mProtoTracer != null) {
+                mProtoTracer.stop();
+            }
+            mHandler.obtainMessage(MSG_TRACING_STATE_CHANGED, false).sendToTarget();
+        }
+    }
+
     private final class H extends Handler {
         private H(Looper l) {
             super(l);
@@ -1178,6 +1253,35 @@
                         mCallbacks.get(i).dismissInattentiveSleepWarning((Boolean) msg.obj);
                     }
                     break;
+                case MSG_SHOW_TOAST: {
+                    args = (SomeArgs) msg.obj;
+                    String packageName = (String) args.arg1;
+                    IBinder token = (IBinder) args.arg2;
+                    CharSequence text = (CharSequence) args.arg3;
+                    IBinder windowToken = (IBinder) args.arg4;
+                    ITransientNotificationCallback callback =
+                            (ITransientNotificationCallback) args.arg5;
+                    int duration = args.argi1;
+                    for (Callbacks callbacks : mCallbacks) {
+                        callbacks.showToast(packageName, token, text, windowToken, duration,
+                                callback);
+                    }
+                    break;
+                }
+                case MSG_HIDE_TOAST: {
+                    args = (SomeArgs) msg.obj;
+                    String packageName = (String) args.arg1;
+                    IBinder token = (IBinder) args.arg2;
+                    for (Callbacks callbacks : mCallbacks) {
+                        callbacks.hideToast(packageName, token);
+                    }
+                    break;
+                }
+                case MSG_TRACING_STATE_CHANGED:
+                    for (int i = 0; i < mCallbacks.size(); i++) {
+                        mCallbacks.get(i).onTracingStateChanged((Boolean) msg.obj);
+                    }
+                    break;
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
index ac05c53..6839921 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
@@ -56,7 +56,7 @@
     }
 
     public boolean isNewNotifPipelineEnabled() {
-        return getDeviceConfigFlag("notification.newpipeline.enabled", false);
+        return getDeviceConfigFlag("notification.newpipeline.enabled", true);
     }
 
     public boolean isNewNotifPipelineRenderingEnabled() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarDependenciesModule.java
index ec8dbea..493482a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarDependenciesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarDependenciesModule.java
@@ -19,6 +19,8 @@
 import android.content.Context;
 
 import com.android.systemui.statusbar.notification.row.NotificationRowModule;
+import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.tracing.ProtoTracer;
 
 import javax.inject.Singleton;
 
@@ -35,8 +37,8 @@
      */
     @Provides
     @Singleton
-    public CommandQueue provideCommandQueue(Context context) {
-        return new CommandQueue(context);
+    public CommandQueue provideCommandQueue(Context context, ProtoTracer protoTracer) {
+        return new CommandQueue(context, protoTracer);
     }
 
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
index 56ad0e1..b048d03 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
@@ -44,10 +44,11 @@
 
     /**
      * Should return the "representative entry" for this ListEntry. For NotificationEntries, its
-     * the entry itself. For groups, it should be the summary. This method exists to interface with
+     * the entry itself. For groups, it should be the summary (but if a summary doesn't exist,
+     * this can return null). This method exists to interface with
      * legacy code that expects groups to also be NotificationEntries.
      */
-    public abstract NotificationEntry getRepresentativeEntry();
+    public abstract @Nullable NotificationEntry getRepresentativeEntry();
 
     @Nullable public GroupEntry getParent() {
         return mParent;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
index c488c6b..92927cf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
@@ -44,17 +44,18 @@
 import android.service.notification.NotificationListenerService.RankingMap;
 import android.service.notification.StatusBarNotification;
 import android.util.ArrayMap;
-import android.util.Log;
 
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.systemui.DumpController;
 import com.android.systemui.Dumpable;
+import com.android.systemui.statusbar.FeatureFlags;
 import com.android.systemui.statusbar.notification.collection.coalescer.CoalescedEvent;
 import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer;
 import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer.BatchableNotificationHandler;
 import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener;
 import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionLogger;
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
 import com.android.systemui.util.Assert;
 
@@ -98,6 +99,8 @@
 @Singleton
 public class NotifCollection implements Dumpable {
     private final IStatusBarService mStatusBarService;
+    private final FeatureFlags mFeatureFlags;
+    private final NotifCollectionLogger mLogger;
 
     private final Map<String, NotificationEntry> mNotificationSet = new ArrayMap<>();
     private final Collection<NotificationEntry> mReadOnlyNotificationSet =
@@ -111,10 +114,16 @@
     private boolean mAmDispatchingToOtherCode;
 
     @Inject
-    public NotifCollection(IStatusBarService statusBarService, DumpController dumpController) {
+    public NotifCollection(
+            IStatusBarService statusBarService,
+            DumpController dumpController,
+            FeatureFlags featureFlags,
+            NotifCollectionLogger logger) {
         Assert.isMainThread();
         mStatusBarService = statusBarService;
+        mLogger = logger;
         dumpController.registerDumpable(TAG, this);
+        mFeatureFlags = featureFlags;
     }
 
     /** Initializes the NotifCollection and registers it to receive notification events. */
@@ -184,8 +193,8 @@
     private void onNotificationGroupPosted(List<CoalescedEvent> batch) {
         Assert.isMainThread();
 
-        Log.d(TAG, "POSTED GROUP " + batch.get(0).getSbn().getGroupKey()
-                + " (" + batch.size() + " events)");
+        mLogger.logNotifGroupPosted(batch.get(0).getSbn().getGroupKey(), batch.size());
+
         for (CoalescedEvent event : batch) {
             postNotification(event.getSbn(), event.getRanking(), null);
         }
@@ -198,7 +207,7 @@
             int reason) {
         Assert.isMainThread();
 
-        Log.d(TAG, "REMOVED " + sbn.getKey() + " reason=" + reason);
+        mLogger.logNotifRemoved(sbn.getKey(), reason);
         removeNotification(sbn.getKey(), rankingMap, reason, null);
     }
 
@@ -216,7 +225,7 @@
 
         if (entry == null) {
             // A new notification!
-            Log.d(TAG, "POSTED  " + sbn.getKey());
+            mLogger.logNotifPosted(sbn.getKey());
 
             entry = new NotificationEntry(sbn, ranking);
             mNotificationSet.put(sbn.getKey(), entry);
@@ -228,7 +237,7 @@
 
         } else {
             // Update to an existing entry
-            Log.d(TAG, "UPDATED " + sbn.getKey());
+            mLogger.logNotifUpdated(sbn.getKey());
 
             // Notification is updated so it is essentially re-added and thus alive again.  Don't
             // need to keep its lifetime extended.
@@ -301,9 +310,12 @@
                 // TODO: (b/145659174) update the sbn's overrideGroupKey in
                 //  NotificationEntry.setRanking instead of here once we fully migrate to the
                 //  NewNotifPipeline
-                final String newOverrideGroupKey = ranking.getOverrideGroupKey();
-                if (!Objects.equals(entry.getSbn().getOverrideGroupKey(), newOverrideGroupKey)) {
-                    entry.getSbn().setOverrideGroupKey(newOverrideGroupKey);
+                if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+                    final String newOverrideGroupKey = ranking.getOverrideGroupKey();
+                    if (!Objects.equals(entry.getSbn().getOverrideGroupKey(),
+                            newOverrideGroupKey)) {
+                        entry.getSbn().setOverrideGroupKey(newOverrideGroupKey);
+                    }
                 }
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
index 97f8ec5..9f8f42e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
@@ -32,19 +32,20 @@
 import android.util.ArrayMap;
 import android.util.Pair;
 
+import androidx.annotation.NonNull;
+
 import com.android.systemui.DumpController;
 import com.android.systemui.Dumpable;
 import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener;
 import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeSortListener;
 import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeTransformGroupsListener;
 import com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState;
+import com.android.systemui.statusbar.notification.collection.listbuilder.ShadeListBuilderLogger;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifComparator;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSection;
 import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener;
-import com.android.systemui.statusbar.notification.logging.NotifEvent;
-import com.android.systemui.statusbar.notification.logging.NotifLog;
 import com.android.systemui.util.Assert;
 import com.android.systemui.util.time.SystemClock;
 
@@ -69,7 +70,7 @@
 @Singleton
 public class ShadeListBuilder implements Dumpable {
     private final SystemClock mSystemClock;
-    private final NotifLog mNotifLog;
+    private final ShadeListBuilderLogger mLogger;
 
     private List<ListEntry> mNotifList = new ArrayList<>();
     private List<ListEntry> mNewNotifList = new ArrayList<>();
@@ -98,11 +99,11 @@
     @Inject
     public ShadeListBuilder(
             SystemClock systemClock,
-            NotifLog notifLog,
+            ShadeListBuilderLogger logger,
             DumpController dumpController) {
         Assert.isMainThread();
         mSystemClock = systemClock;
-        mNotifLog = notifLog;
+        mLogger = logger;
         dumpController.registerDumpable(TAG, this);
     }
 
@@ -205,8 +206,7 @@
                     Assert.isMainThread();
                     mPipelineState.requireIsBefore(STATE_BUILD_STARTED);
 
-                    mNotifLog.log(NotifEvent.ON_BUILD_LIST, "Request received from "
-                            + "NotifCollection");
+                    mLogger.logOnBuildList();
                     mAllEntries = entries;
                     buildList();
                 }
@@ -215,21 +215,15 @@
     private void onPreGroupFilterInvalidated(NotifFilter filter) {
         Assert.isMainThread();
 
-        mNotifLog.log(NotifEvent.PRE_GROUP_FILTER_INVALIDATED, String.format(
-                "Filter \"%s\" invalidated; pipeline state is %d",
-                filter.getName(),
-                mPipelineState.getState()));
+        mLogger.logPreGroupFilterInvalidated(filter.getName(), mPipelineState.getState());
 
         rebuildListIfBefore(STATE_PRE_GROUP_FILTERING);
     }
 
-    private void onPromoterInvalidated(NotifPromoter filter) {
+    private void onPromoterInvalidated(NotifPromoter promoter) {
         Assert.isMainThread();
 
-        mNotifLog.log(NotifEvent.PROMOTER_INVALIDATED, String.format(
-                "NotifPromoter \"%s\" invalidated; pipeline state is %d",
-                filter.getName(),
-                mPipelineState.getState()));
+        mLogger.logPromoterInvalidated(promoter.getName(), mPipelineState.getState());
 
         rebuildListIfBefore(STATE_TRANSFORMING);
     }
@@ -237,10 +231,7 @@
     private void onNotifSectionInvalidated(NotifSection section) {
         Assert.isMainThread();
 
-        mNotifLog.log(NotifEvent.SECTION_INVALIDATED, String.format(
-                "Section \"%s\" invalidated; pipeline state is %d",
-                section.getName(),
-                mPipelineState.getState()));
+        mLogger.logNotifSectionInvalidated(section.getName(), mPipelineState.getState());
 
         rebuildListIfBefore(STATE_SORTING);
     }
@@ -248,10 +239,7 @@
     private void onPreRenderFilterInvalidated(NotifFilter filter) {
         Assert.isMainThread();
 
-        mNotifLog.log(NotifEvent.PRE_RENDER_FILTER_INVALIDATED, String.format(
-                "Filter \"%s\" invalidated; pipeline state is %d",
-                filter.getName(),
-                mPipelineState.getState()));
+        mLogger.logPreRenderFilterInvalidated(filter.getName(), mPipelineState.getState());
 
         rebuildListIfBefore(STATE_PRE_RENDER_FILTERING);
     }
@@ -259,10 +247,7 @@
     private void onNotifComparatorInvalidated(NotifComparator comparator) {
         Assert.isMainThread();
 
-        mNotifLog.log(NotifEvent.COMPARATOR_INVALIDATED, String.format(
-                "Comparator \"%s\" invalidated; pipeline state is %d",
-                comparator.getName(),
-                mPipelineState.getState()));
+        mLogger.logNotifComparatorInvalidated(comparator.getName(), mPipelineState.getState());
 
         rebuildListIfBefore(STATE_SORTING);
     }
@@ -288,7 +273,7 @@
      * if we detect that behavior, we should crash instantly.
      */
     private void buildList() {
-        mNotifLog.log(NotifEvent.START_BUILD_LIST, "Run #" + mIterationCount + "...");
+        mLogger.logStartBuildList(mIterationCount);
 
         mPipelineState.requireIsBefore(STATE_BUILD_STARTED);
         mPipelineState.setState(STATE_BUILD_STARTED);
@@ -334,16 +319,16 @@
         freeEmptyGroups();
 
         // Step 6: Dispatch the new list, first to any listeners and then to the view layer
-        mNotifLog.log(NotifEvent.DISPATCH_FINAL_LIST, "List finalized, is:\n"
-                + ListDumper.dumpTree(mNotifList, false, "\t\t"));
+        if (mIterationCount % 10 == 0) {
+            mLogger.logFinalList(mNotifList);
+        }
         dispatchOnBeforeRenderList(mReadOnlyNotifList);
         if (mOnRenderListListener != null) {
             mOnRenderListListener.onRenderList(mReadOnlyNotifList);
         }
 
         // Step 7: We're done!
-        mNotifLog.log(NotifEvent.LIST_BUILD_COMPLETE,
-                "Notif list build #" + mIterationCount + " completed");
+        mLogger.logEndBuildList(mIterationCount);
         mPipelineState.setState(STATE_IDLE);
         mIterationCount++;
     }
@@ -429,11 +414,10 @@
                     if (existingSummary == null) {
                         group.setSummary(entry);
                     } else {
-                        mNotifLog.log(NotifEvent.WARN, String.format(
-                                "Duplicate summary for group '%s': '%s' vs. '%s'",
+                        mLogger.logDuplicateSummary(
                                 group.getKey(),
                                 existingSummary.getKey(),
-                                entry.getKey()));
+                                entry.getKey());
 
                         // Use whichever one was posted most recently
                         if (entry.getSbn().getPostTime()
@@ -452,8 +436,7 @@
 
                 final String topLevelKey = entry.getKey();
                 if (mGroups.containsKey(topLevelKey)) {
-                    mNotifLog.log(NotifEvent.WARN,
-                            "Duplicate non-group top-level key: " + topLevelKey);
+                    mLogger.logDuplicateTopLevelKey(topLevelKey);
                 } else {
                     entry.setParent(ROOT_ENTRY);
                     out.add(entry);
@@ -617,24 +600,22 @@
     private void logParentingChanges() {
         for (NotificationEntry entry : mAllEntries) {
             if (entry.getParent() != entry.getPreviousParent()) {
-                mNotifLog.log(NotifEvent.PARENT_CHANGED, String.format(
-                        "%s: parent changed from %s to %s",
+                mLogger.logParentChanged(
                         entry.getKey(),
                         entry.getPreviousParent() == null
-                                ? "null" : entry.getPreviousParent().getKey(),
+                                ? null : entry.getPreviousParent().getKey(),
                         entry.getParent() == null
-                                ? "null" : entry.getParent().getKey()));
+                                ? null : entry.getParent().getKey());
             }
         }
         for (GroupEntry group : mGroups.values()) {
             if (group.getParent() != group.getPreviousParent()) {
-                mNotifLog.log(NotifEvent.PARENT_CHANGED, String.format(
-                        "%s: parent changed from %s to %s",
+                mLogger.logParentChanged(
                         group.getKey(),
                         group.getPreviousParent() == null
-                                ? "null" : group.getPreviousParent().getKey(),
+                                ? null : group.getPreviousParent().getKey(),
                         group.getParent() == null
-                                ? "null" : group.getParent().getKey()));
+                                ? null : group.getParent().getKey());
             }
         }
     }
@@ -684,23 +665,10 @@
         NotifFilter filter = findRejectingFilter(entry, now, filters);
 
         if (filter != entry.mExcludingFilter) {
-            if (entry.mExcludingFilter == null) {
-                mNotifLog.log(NotifEvent.FILTER_CHANGED, String.format(
-                        "%s: filtered out by '%s'",
-                        entry.getKey(),
-                        filter.getName()));
-            } else if (filter == null) {
-                mNotifLog.log(NotifEvent.FILTER_CHANGED, String.format(
-                        "%s: no longer filtered out (previous filter was '%s')",
-                        entry.getKey(),
-                        entry.mExcludingFilter.getName()));
-            } else {
-                mNotifLog.log(NotifEvent.FILTER_CHANGED, String.format(
-                        "%s: filter changed: '%s' -> '%s'",
-                        entry.getKey(),
-                        entry.mExcludingFilter,
-                        filter));
-            }
+            mLogger.logFilterChanged(
+                    entry.getKey(),
+                    entry.mExcludingFilter != null ? entry.mExcludingFilter.getName() : null,
+                    filter != null ? filter.getName() : null);
 
             // Note that groups and summaries can also be filtered out later if they're part of a
             // malformed group. We currently don't have a great way to track that beyond parenting
@@ -728,23 +696,10 @@
         NotifPromoter promoter = findPromoter(entry);
 
         if (promoter != entry.mNotifPromoter) {
-            if (entry.mNotifPromoter == null) {
-                mNotifLog.log(NotifEvent.PROMOTER_CHANGED, String.format(
-                        "%s: Entry promoted to top level by '%s'",
-                        entry.getKey(),
-                        promoter.getName()));
-            } else if (promoter == null) {
-                mNotifLog.log(NotifEvent.PROMOTER_CHANGED, String.format(
-                        "%s: Entry is no longer promoted to top level (previous promoter was '%s')",
-                        entry.getKey(),
-                        entry.mNotifPromoter.getName()));
-            } else {
-                mNotifLog.log(NotifEvent.PROMOTER_CHANGED, String.format(
-                        "%s: Top-level promoter changed: '%s' -> '%s'",
-                        entry.getKey(),
-                        entry.mNotifPromoter,
-                        promoter));
-            }
+            mLogger.logPromoterChanged(
+                    entry.getKey(),
+                    entry.mNotifPromoter != null ? entry.mNotifPromoter.getName() : null,
+                    promoter != null ? promoter.getName() : null);
             entry.mNotifPromoter = promoter;
         }
 
@@ -767,21 +722,12 @@
         final Integer sectionIndex = sectionWithIndex.second;
 
         if (section != entry.mNotifSection) {
-            if (entry.mNotifSection == null) {
-                mNotifLog.log(NotifEvent.SECTION_CHANGED, String.format(
-                        "%s: sectioned by '%s' [index=%d].",
-                        entry.getKey(),
-                        section.getName(),
-                        sectionIndex));
-            } else {
-                mNotifLog.log(NotifEvent.SECTION_CHANGED, String.format(
-                        "%s: section changed: '%s' [index=%d] -> '%s [index=%d]'.",
-                        entry.getKey(),
-                        entry.mNotifSection,
-                        entry.getSection(),
-                        section,
-                        sectionIndex));
-            }
+            mLogger.logSectionChanged(
+                    entry.getKey(),
+                    entry.mNotifSection != null ? entry.mNotifSection.getName() : null,
+                    entry.getSection(),
+                    section.getName(),
+                    sectionIndex);
 
             entry.mNotifSection = section;
             entry.setSection(sectionIndex);
@@ -826,7 +772,7 @@
     }
 
     @Override
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+    public void dump(@NonNull FileDescriptor fd, PrintWriter pw, @NonNull String[] args) {
         pw.println("\t" + TAG + " shade notifications:");
         if (getShadeList().size() == 0) {
             pw.println("\t\t None");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java
index f589038..98c45ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java
@@ -16,11 +16,6 @@
 
 package com.android.systemui.statusbar.notification.collection.coalescer;
 
-import static com.android.systemui.statusbar.notification.logging.NotifEvent.BATCH_MAX_TIMEOUT;
-import static com.android.systemui.statusbar.notification.logging.NotifEvent.COALESCED_EVENT;
-import static com.android.systemui.statusbar.notification.logging.NotifEvent.EARLY_BATCH_EMIT;
-import static com.android.systemui.statusbar.notification.logging.NotifEvent.EMIT_EVENT_BATCH;
-
 import static java.util.Objects.requireNonNull;
 
 import android.annotation.MainThread;
@@ -35,7 +30,6 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationListener.NotificationHandler;
-import com.android.systemui.statusbar.notification.logging.NotifLog;
 import com.android.systemui.util.concurrency.DelayableExecutor;
 import com.android.systemui.util.time.SystemClock;
 
@@ -71,7 +65,7 @@
 public class GroupCoalescer implements Dumpable {
     private final DelayableExecutor mMainExecutor;
     private final SystemClock mClock;
-    private final NotifLog mLog;
+    private final GroupCoalescerLogger mLogger;
     private final long mMinGroupLingerDuration;
     private final long mMaxGroupLingerDuration;
 
@@ -83,8 +77,9 @@
     @Inject
     public GroupCoalescer(
             @Main DelayableExecutor mainExecutor,
-            SystemClock clock, NotifLog log) {
-        this(mainExecutor, clock, log, MIN_GROUP_LINGER_DURATION, MAX_GROUP_LINGER_DURATION);
+            SystemClock clock,
+            GroupCoalescerLogger logger) {
+        this(mainExecutor, clock, logger, MIN_GROUP_LINGER_DURATION, MAX_GROUP_LINGER_DURATION);
     }
 
     /**
@@ -98,12 +93,12 @@
     GroupCoalescer(
             @Main DelayableExecutor mainExecutor,
             SystemClock clock,
-            NotifLog log,
+            GroupCoalescerLogger logger,
             long minGroupLingerDuration,
             long maxGroupLingerDuration) {
         mMainExecutor = mainExecutor;
         mClock = clock;
-        mLog = log;
+        mLogger = logger;
         mMinGroupLingerDuration = minGroupLingerDuration;
         mMaxGroupLingerDuration = maxGroupLingerDuration;
     }
@@ -129,7 +124,7 @@
             final boolean shouldCoalesce = handleNotificationPosted(sbn, rankingMap);
 
             if (shouldCoalesce) {
-                mLog.log(COALESCED_EVENT, String.format("Coalesced notification %s", sbn.getKey()));
+                mLogger.logEventCoalesced(sbn.getKey());
                 mHandler.onNotificationRankingUpdate(rankingMap);
             } else {
                 mHandler.onNotificationPosted(sbn, rankingMap);
@@ -164,15 +159,11 @@
         final CoalescedEvent event = mCoalescedEvents.get(sbn.getKey());
         final EventBatch batch = mBatches.get(sbn.getGroupKey());
         if (event != null) {
-            mLog.log(EARLY_BATCH_EMIT,
-                    String.format("Modification of %s triggered early emit of batched group %s",
-                            sbn.getKey(), requireNonNull(event.getBatch()).mGroupKey));
+            mLogger.logEarlyEmit(sbn.getKey(), requireNonNull(event.getBatch()).mGroupKey);
             emitBatch(requireNonNull(event.getBatch()));
         } else if (batch != null
                 && mClock.uptimeMillis() - batch.mCreatedTimestamp >= mMaxGroupLingerDuration) {
-            mLog.log(BATCH_MAX_TIMEOUT,
-                    String.format("Modification of %s triggered timeout emit of batched group %s",
-                            sbn.getKey(), batch.mGroupKey));
+            mLogger.logMaxBatchTimeout(sbn.getKey(), batch.mGroupKey);
             emitBatch(batch);
         }
     }
@@ -253,7 +244,7 @@
         }
         events.sort(mEventComparator);
 
-        mLog.log(EMIT_EVENT_BATCH, "Emitting event batch for group " + batch.mGroupKey);
+        mLogger.logEmitBatch(batch.mGroupKey);
 
         mHandler.onNotificationBatchPosted(events);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerLogger.kt
new file mode 100644
index 0000000..6e8788d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerLogger.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.coalescer
+
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
+import com.android.systemui.log.dagger.NotificationLog
+import javax.inject.Inject
+
+class GroupCoalescerLogger @Inject constructor(
+    @NotificationLog private val buffer: LogBuffer
+) {
+    fun logEventCoalesced(key: String) {
+        buffer.log(TAG, LogLevel.INFO, {
+            str1 = key
+        }, {
+            "COALESCED: $str1"
+        })
+    }
+
+    fun logEmitBatch(groupKey: String) {
+        buffer.log(TAG, LogLevel.DEBUG, {
+            str1 = groupKey
+        }, {
+            "Emitting event batch for group $str1"
+        })
+    }
+
+    fun logEarlyEmit(modifiedKey: String, groupKey: String) {
+        buffer.log(TAG, LogLevel.DEBUG, {
+            str1 = modifiedKey
+            str2 = groupKey
+        }, {
+            "Modification of notif $str1 triggered early emit of batched group $str2"
+        })
+    }
+
+    fun logMaxBatchTimeout(modifiedKey: String, groupKey: String) {
+        buffer.log(TAG, LogLevel.INFO, {
+            str1 = modifiedKey
+            str2 = groupKey
+        }, {
+            "Modification of notif $str1 triggered TIMEOUT emit of batched group $str2"
+        })
+    }
+}
+
+private const val TAG = "GroupCoalescer"
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java
index da119c1..854444f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar.notification.collection.coordinator;
 
 import android.app.Notification;
-import android.os.Handler;
 import android.os.UserHandle;
 import android.service.notification.StatusBarNotification;
 import android.util.ArraySet;
@@ -30,6 +29,8 @@
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
+import com.android.systemui.util.Assert;
+import com.android.systemui.util.concurrency.DelayableExecutor;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -47,6 +48,8 @@
  *  frameworks/base/packages/SystemUI/src/com/android/systemui/ForegroundServiceController
  *  frameworks/base/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener
  *  frameworks/base/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender
+ *
+ *  TODO: AppOps stuff should be spun off into its own coordinator
  */
 @Singleton
 public class ForegroundCoordinator implements Coordinator {
@@ -54,7 +57,7 @@
 
     private final ForegroundServiceController mForegroundServiceController;
     private final AppOpsController mAppOpsController;
-    private final Handler mMainHandler;
+    private final DelayableExecutor mMainExecutor;
 
     private NotifPipeline mNotifPipeline;
 
@@ -62,10 +65,10 @@
     public ForegroundCoordinator(
             ForegroundServiceController foregroundServiceController,
             AppOpsController appOpsController,
-            @Main Handler mainHandler) {
+            @Main DelayableExecutor mainExecutor) {
         mForegroundServiceController = foregroundServiceController;
         mAppOpsController = appOpsController;
-        mMainHandler = mainHandler;
+        mMainExecutor = mainExecutor;
     }
 
     @Override
@@ -78,11 +81,11 @@
         // listen for new notifications to add appOps
         mNotifPipeline.addCollectionListener(mNotifCollectionListener);
 
-        // when appOps change, update any relevant notifications to update appOps for
-        mAppOpsController.addCallback(ForegroundServiceController.APP_OPS, this::onAppOpsChanged);
-
         // filter out foreground service notifications that aren't necessary anymore
         mNotifPipeline.addPreGroupFilter(mNotifFilter);
+
+        // when appOps change, update any relevant notifications to update appOps for
+        mAppOpsController.addCallback(ForegroundServiceController.APP_OPS, this::onAppOpsChanged);
     }
 
     /**
@@ -93,7 +96,8 @@
         public boolean shouldFilterOut(NotificationEntry entry, long now) {
             StatusBarNotification sbn = entry.getSbn();
             if (mForegroundServiceController.isDisclosureNotification(sbn)
-                    && !mForegroundServiceController.isDisclosureNeededForUser(sbn.getUserId())) {
+                    && !mForegroundServiceController.isDisclosureNeededForUser(
+                            sbn.getUser().getIdentifier())) {
                 return true;
             }
 
@@ -102,7 +106,7 @@
                         Notification.EXTRA_FOREGROUND_APPS);
                 if (apps != null && apps.length >= 1) {
                     if (!mForegroundServiceController.isSystemAlertWarningNeeded(
-                            sbn.getUserId(), apps[0])) {
+                            sbn.getUser().getIdentifier(), apps[0])) {
                         return true;
                     }
                 }
@@ -119,7 +123,7 @@
             new NotifLifetimeExtender() {
         private static final int MIN_FGS_TIME_MS = 5000;
         private OnEndLifetimeExtensionCallback mEndCallback;
-        private Map<String, Runnable> mEndRunnables = new HashMap<>();
+        private Map<NotificationEntry, Runnable> mEndRunnables = new HashMap<>();
 
         @Override
         public String getName() {
@@ -142,16 +146,18 @@
             final boolean extendLife = currTime - entry.getSbn().getPostTime() < MIN_FGS_TIME_MS;
 
             if (extendLife) {
-                if (!mEndRunnables.containsKey(entry.getKey())) {
-                    final Runnable runnable = new Runnable() {
-                        @Override
-                        public void run() {
-                            mEndCallback.onEndLifetimeExtension(mForegroundLifetimeExtender, entry);
-                        }
+                if (!mEndRunnables.containsKey(entry)) {
+                    final Runnable endExtensionRunnable = () -> {
+                        mEndRunnables.remove(entry);
+                        mEndCallback.onEndLifetimeExtension(
+                                mForegroundLifetimeExtender,
+                                entry);
                     };
-                    mEndRunnables.put(entry.getKey(), runnable);
-                    mMainHandler.postDelayed(runnable,
+
+                    final Runnable cancelRunnable = mMainExecutor.executeDelayed(
+                            endExtensionRunnable,
                             MIN_FGS_TIME_MS - (currTime - entry.getSbn().getPostTime()));
+                    mEndRunnables.put(entry, cancelRunnable);
                 }
             }
 
@@ -160,9 +166,9 @@
 
         @Override
         public void cancelLifetimeExtension(NotificationEntry entry) {
-            if (mEndRunnables.containsKey(entry.getKey())) {
-                Runnable endRunnable = mEndRunnables.remove(entry.getKey());
-                mMainHandler.removeCallbacks(endRunnable);
+            Runnable cancelRunnable = mEndRunnables.remove(entry);
+            if (cancelRunnable != null) {
+                cancelRunnable.run();
             }
         }
     };
@@ -184,25 +190,32 @@
         private void tagForeground(NotificationEntry entry) {
             final StatusBarNotification sbn = entry.getSbn();
             // note: requires that the ForegroundServiceController is updating their appOps first
-            ArraySet<Integer> activeOps = mForegroundServiceController.getAppOps(sbn.getUserId(),
-                    sbn.getPackageName());
+            ArraySet<Integer> activeOps =
+                    mForegroundServiceController.getAppOps(
+                            sbn.getUser().getIdentifier(),
+                            sbn.getPackageName());
             if (activeOps != null) {
-                synchronized (entry.mActiveAppOps) {
-                    entry.mActiveAppOps.clear();
-                    entry.mActiveAppOps.addAll(activeOps);
-                }
+                entry.mActiveAppOps.clear();
+                entry.mActiveAppOps.addAll(activeOps);
             }
         }
     };
 
+    private void onAppOpsChanged(int code, int uid, String packageName, boolean active) {
+        mMainExecutor.execute(() -> handleAppOpsChanged(code, uid, packageName, active));
+    }
+
     /**
      * Update the appOp for the posted notification associated with the current foreground service
+     *
      * @param code code for appOp to add/remove
      * @param uid of user the notification is sent to
      * @param packageName package that created the notification
      * @param active whether the appOpCode is active or not
      */
-    private void onAppOpsChanged(int code, int uid, String packageName, boolean active) {
+    private void handleAppOpsChanged(int code, int uid, String packageName, boolean active) {
+        Assert.isMainThread();
+
         int userId = UserHandle.getUserId(uid);
 
         // Update appOp if there's an associated posted notification:
@@ -214,15 +227,13 @@
                     && uid == entry.getSbn().getUid()
                     && packageName.equals(entry.getSbn().getPackageName())) {
                 boolean changed;
-                synchronized (entry.mActiveAppOps) {
-                    if (active) {
-                        changed = entry.mActiveAppOps.add(code);
-                    } else {
-                        changed = entry.mActiveAppOps.remove(code);
-                    }
+                if (active) {
+                    changed = entry.mActiveAppOps.add(code);
+                } else {
+                    changed = entry.mActiveAppOps.remove(code);
                 }
                 if (changed) {
-                    mMainHandler.post(mNotifFilter::invalidateList);
+                    mNotifFilter.invalidateList();
                 }
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
new file mode 100644
index 0000000..6e15043
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.listbuilder
+
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel.DEBUG
+import com.android.systemui.log.LogLevel.INFO
+import com.android.systemui.log.LogLevel.WARNING
+import com.android.systemui.log.dagger.NotificationLog
+import com.android.systemui.statusbar.notification.collection.GroupEntry
+import com.android.systemui.statusbar.notification.collection.ListEntry
+import javax.inject.Inject
+
+class ShadeListBuilderLogger @Inject constructor(
+    @NotificationLog private val buffer: LogBuffer
+) {
+    fun logOnBuildList() {
+        buffer.log(TAG, INFO, {
+        }, {
+            "Request received from NotifCollection"
+        })
+    }
+
+    fun logStartBuildList(iterationCount: Int) {
+        buffer.log(TAG, INFO, {
+            int1 = iterationCount
+        }, {
+            "Starting to build shade list (run #$int1)"
+        })
+    }
+
+    fun logEndBuildList(iterationCount: Int) {
+        buffer.log(TAG, INFO, {
+            int1 = iterationCount
+        }, {
+            "Finished building shade list (run #$int1)"
+        })
+    }
+
+    fun logPreGroupFilterInvalidated(filterName: String, pipelineState: Int) {
+        buffer.log(TAG, DEBUG, {
+            str1 = filterName
+            int1 = pipelineState
+        }, {
+            """Pre-group NotifFilter "$str1" invalidated; pipeline state is $int1"""
+        })
+    }
+
+    fun logPromoterInvalidated(name: String, pipelineState: Int) {
+        buffer.log(TAG, DEBUG, {
+            str1 = name
+            int1 = pipelineState
+        }, {
+            """NotifPromoter "$str1" invalidated; pipeline state is $int1"""
+        })
+    }
+
+    fun logNotifSectionInvalidated(name: String, pipelineState: Int) {
+        buffer.log(TAG, DEBUG, {
+            str1 = name
+            int1 = pipelineState
+        }, {
+            """NotifSection "$str1" invalidated; pipeline state is $int1"""
+        })
+    }
+
+    fun logNotifComparatorInvalidated(name: String, pipelineState: Int) {
+        buffer.log(TAG, DEBUG, {
+            str1 = name
+            int1 = pipelineState
+        }, {
+            """NotifComparator "$str1" invalidated; pipeline state is $int1"""
+        })
+    }
+
+    fun logPreRenderFilterInvalidated(name: String, pipelineState: Int) {
+        buffer.log(TAG, DEBUG, {
+            str1 = name
+            int1 = pipelineState
+        }, {
+            """Pre-render NotifFilter "$str1" invalidated; pipeline state is $int1"""
+        })
+    }
+
+    fun logDuplicateSummary(groupKey: String, existingKey: String, newKey: String) {
+        buffer.log(TAG, WARNING, {
+            str1 = groupKey
+            str2 = existingKey
+            str3 = newKey
+        }, {
+            """Duplicate summary for group "$str1": "$str2" vs. "$str3""""
+        })
+    }
+
+    fun logDuplicateTopLevelKey(topLevelKey: String) {
+        buffer.log(TAG, WARNING, {
+            str1 = topLevelKey
+        }, {
+            "Duplicate top-level key: $str1"
+        })
+    }
+
+    fun logParentChanged(key: String, prevParent: String?, newParent: String?) {
+        buffer.log(TAG, INFO, {
+            str1 = key
+            str2 = prevParent
+            str3 = newParent
+        }, {
+            "Parent change for $str1: $str2 -> $str3"
+        })
+    }
+
+    fun logFilterChanged(
+        key: String,
+        prevFilter: String?,
+        newFilter: String?
+    ) {
+        buffer.log(TAG, INFO, {
+            str1 = key
+            str2 = prevFilter
+            str3 = newFilter
+        }, {
+            "Filter changed for $str1: $str2 -> $str3"
+        })
+    }
+
+    fun logPromoterChanged(
+        key: String,
+        prevPromoter: String?,
+        newPromoter: String?
+    ) {
+        buffer.log(TAG, INFO, {
+            str1 = key
+            str2 = prevPromoter
+            str3 = newPromoter
+        }, {
+            "Promoter changed for $str1: $str2 -> $str3"
+        })
+    }
+
+    fun logSectionChanged(
+        key: String,
+        prevSection: String?,
+        prevIndex: Int,
+        section: String,
+        index: Int
+    ) {
+        buffer.log(TAG, INFO, {
+            str1 = key
+            str2 = section
+            int1 = index
+            str3 = prevSection
+            int2 = prevIndex
+        }, {
+            if (str3 == null) {
+                "Section assigned for $str1: '$str2' (#$int1)"
+            } else {
+                "Section changed for $str1: '$str3' (#$int2) -> '$str2' (#$int1)"
+            }
+        })
+    }
+
+    fun logFinalList(entries: List<ListEntry>) {
+        buffer.log(TAG, DEBUG, {
+            int1 = entries.size
+        }, {
+            "List is finalized ($int1 top-level entries):"
+        })
+        if (entries.isEmpty()) {
+            buffer.log(TAG, DEBUG, {}, { "(empty list)" })
+        }
+        for (i in entries.indices) {
+            val entry = entries[i]
+            buffer.log(TAG, DEBUG, {
+                int1 = i
+                str1 = entry.key
+            }, {
+                "[$int1] $str1"
+            })
+
+            if (entry is GroupEntry) {
+                entry.summary?.let {
+                    buffer.log(TAG, DEBUG, {
+                        str1 = it.key
+                    }, {
+                        "  [*] $str1 (summary)"
+                    })
+                }
+                for (j in entry.children.indices) {
+                    val child = entry.children[j]
+                    buffer.log(TAG, DEBUG, {
+                        int1 = j
+                        str1 = child.key
+                    }, {
+                        "  [$int1] $str1"
+                    })
+                }
+            }
+        }
+    }
+}
+
+private const val TAG = "ShadeListBuilder"
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
new file mode 100644
index 0000000..bd1bd86
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.notifcollection
+
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
+import com.android.systemui.log.dagger.NotificationLog
+import javax.inject.Inject
+
+class NotifCollectionLogger @Inject constructor(
+    @NotificationLog private val buffer: LogBuffer
+) {
+    fun logNotifPosted(key: String) {
+        buffer.log(TAG, LogLevel.INFO, {
+            str1 = key
+        }, {
+            "POSTED $str1"
+        })
+    }
+
+    fun logNotifGroupPosted(groupKey: String, batchSize: Int) {
+        buffer.log(TAG, LogLevel.INFO, {
+            str1 = groupKey
+            int1 = batchSize
+        }, {
+            "POSTED GROUP $str1 ($int1 events)"
+        })
+    }
+
+    fun logNotifUpdated(key: String) {
+        buffer.log(TAG, LogLevel.INFO, {
+            str1 = key
+        }, {
+            "UPDATED $str1"
+        })
+    }
+
+    fun logNotifRemoved(key: String, reason: Int) {
+        buffer.log(TAG, LogLevel.INFO, {
+            str1 = key
+            int1 = reason
+        }, {
+            "REMOVED $str1 reason=$int1"
+        })
+    }
+}
+
+private const val TAG = "NotifCollection"
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java
index b496116..0d9beae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java
@@ -63,6 +63,10 @@
         }
 
         final NotificationEntry notifEntry = entry.getRepresentativeEntry();
+        if (notifEntry == null) {
+            return false;
+        }
+
         return notifEntry.getRanking().getImportance() >= NotificationManager.IMPORTANCE_DEFAULT
                 || hasHighPriorityCharacteristics(notifEntry)
                 || hasHighPriorityChild(entry);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
index 18c755d..6045524 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
@@ -29,6 +29,7 @@
 import static com.android.systemui.statusbar.notification.row.NotificationConversationInfo.UpdateChannelRunnable.ACTION_HOME;
 import static com.android.systemui.statusbar.notification.row.NotificationConversationInfo.UpdateChannelRunnable.ACTION_MUTE;
 import static com.android.systemui.statusbar.notification.row.NotificationConversationInfo.UpdateChannelRunnable.ACTION_SNOOZE;
+import static com.android.systemui.statusbar.notification.row.NotificationConversationInfo.UpdateChannelRunnable.ACTION_UNBUBBLE;
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
@@ -121,7 +122,7 @@
     boolean mSkipPost = false;
 
     private OnClickListener mOnBubbleClick = v -> {
-        mSelectedAction = ACTION_BUBBLE;
+        mSelectedAction = mStartedAsBubble ? ACTION_UNBUBBLE : ACTION_BUBBLE;
         if (mStartedAsBubble) {
             mBubbleController.onUserDemotedBubbleFromNotification(mEntry);
         } else {
@@ -586,6 +587,7 @@
         static final int ACTION_SNOOZE = 3;
         static final int ACTION_MUTE = 4;
         static final int ACTION_DEMOTE = 5;
+        static final int ACTION_UNBUBBLE = 6;
 
         private final INotificationManager mINotificationManager;
         private final String mAppPkg;
@@ -606,9 +608,17 @@
         @Override
         public void run() {
             try {
+                boolean channelSettingChanged = mAction != ACTION_HOME && mAction != ACTION_SNOOZE;
                 switch (mAction) {
                     case ACTION_BUBBLE:
-                        mChannelToUpdate.setAllowBubbles(!mChannelToUpdate.canBubble());
+                    case ACTION_UNBUBBLE:
+                        boolean canBubble = mAction == ACTION_BUBBLE;
+                        if (mChannelToUpdate.canBubble() != canBubble) {
+                            channelSettingChanged = true;
+                            mChannelToUpdate.setAllowBubbles(canBubble);
+                        } else {
+                            channelSettingChanged = false;
+                        }
                         break;
                     case ACTION_FAVORITE:
                         // TODO: extend beyond DND
@@ -629,7 +639,7 @@
 
                 }
 
-                if (mAction != ACTION_HOME && mAction != ACTION_SNOOZE) {
+                if (channelSettingChanged) {
                     mINotificationManager.updateNotificationChannelForPackage(
                             mAppPkg, mAppUid, mChannelToUpdate);
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
index 6bd122d..db692c8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -54,6 +54,10 @@
 import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.shared.system.SysUiStatsLog;
+import com.android.systemui.shared.tracing.ProtoTraceable;
+import com.android.systemui.tracing.ProtoTracer;
+import com.android.systemui.tracing.nano.EdgeBackGestureHandlerProto;
+import com.android.systemui.tracing.nano.SystemUiTraceProto;
 
 import java.io.PrintWriter;
 import java.util.concurrent.Executor;
@@ -62,7 +66,7 @@
  * Utility class to handle edge swipes for back gesture
  */
 public class EdgeBackGestureHandler implements DisplayListener,
-        PluginListener<NavigationEdgeBackPlugin> {
+        PluginListener<NavigationEdgeBackPlugin>, ProtoTraceable<SystemUiTraceProto> {
 
     private static final String TAG = "EdgeBackGestureHandler";
     private static final int MAX_LONG_PRESS_TIMEOUT = SystemProperties.getInt(
@@ -161,6 +165,7 @@
         mMainExecutor = context.getMainExecutor();
         mOverviewProxyService = overviewProxyService;
         mPluginManager = pluginManager;
+        Dependency.get(ProtoTracer.class).add(this);
 
         // Reduce the default touch slop to ensure that we can intercept the gesture
         // before the app starts to react to it.
@@ -399,6 +404,8 @@
             // forward touch
             mEdgeBackPlugin.onMotionEvent(ev);
         }
+
+        Dependency.get(ProtoTracer.class).update();
     }
 
     @Override
@@ -458,6 +465,14 @@
         pw.println("  mEdgeWidth=" + mEdgeWidth);
     }
 
+    @Override
+    public void writeToProto(SystemUiTraceProto proto) {
+        if (proto.edgeBackGestureHandler == null) {
+            proto.edgeBackGestureHandler = new EdgeBackGestureHandlerProto();
+        }
+        proto.edgeBackGestureHandler.allowGesture = mAllowGesture;
+    }
+
     class SysUiInputEventReceiver extends InputEventReceiver {
         SysUiInputEventReceiver(InputChannel channel, Looper looper) {
             super(channel, looper);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 3e3ef0c..9e64748 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -302,14 +302,14 @@
         mForceNavBarHandleOpaque = DeviceConfig.getBoolean(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 NAV_BAR_HANDLE_FORCE_OPAQUE,
-                /* defaultValue = */ false);
+                /* defaultValue = */ true);
         DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI, mHandler::post,
                 new DeviceConfig.OnPropertiesChangedListener() {
                     @Override
                     public void onPropertiesChanged(DeviceConfig.Properties properties) {
                         if (properties.getKeyset().contains(NAV_BAR_HANDLE_FORCE_OPAQUE)) {
                             mForceNavBarHandleOpaque = properties.getBoolean(
-                                    NAV_BAR_HANDLE_FORCE_OPAQUE, /* defaultValue = */ false);
+                                    NAV_BAR_HANDLE_FORCE_OPAQUE, /* defaultValue = */ true);
                         }
                     }
                 });
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
index d6336ed..826af66 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
@@ -387,7 +387,7 @@
                     Log.d(TAG, "setModeOverlay: overlayPackage=" + overlayPkg
                             + " userId=" + userId);
                 }
-            } catch (RemoteException e) {
+            } catch (SecurityException | IllegalStateException | RemoteException e) {
                 Log.e(TAG, "Failed to enable overlay " + overlayPkg + " for user " + userId);
             }
         });
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 7558022..41d8968 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -37,7 +37,6 @@
 import android.text.format.DateFormat;
 import android.util.Log;
 
-import com.android.internal.telephony.TelephonyIntents;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.broadcast.BroadcastDispatcher;
@@ -174,7 +173,7 @@
         filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
         filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
         filter.addAction(AudioManager.ACTION_HEADSET_PLUG);
-        filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+        filter.addAction(Intent.ACTION_SIM_STATE_CHANGED);
         filter.addAction(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED);
         filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
         filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
@@ -614,7 +613,7 @@
                 case AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION:
                     updateVolumeZen();
                     break;
-                case TelephonyIntents.ACTION_SIM_STATE_CHANGED:
+                case Intent.ACTION_SIM_STATE_CHANGED:
                     // Avoid rebroadcast because SysUI is direct boot aware.
                     if (intent.getBooleanExtra(Intent.EXTRA_REBROADCAST_ON_UNLOCK, false)) {
                         break;
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 d061649..5a7c5c9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
@@ -56,6 +56,7 @@
     private static final int MAX_DOTS = 1;
 
     private int mDotPadding;
+    private int mIconSpacing;
     private int mStaticDotDiameter;
     private int mUnderflowWidth;
     private int mUnderflowStart = 0;
@@ -99,6 +100,7 @@
         mIconDotFrameWidth = getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.status_bar_icon_size);
         mDotPadding = getResources().getDimensionPixelSize(R.dimen.overflow_icon_dot_padding);
+        mIconSpacing = getResources().getDimensionPixelSize(R.dimen.status_bar_system_icon_spacing);
         int radius = getResources().getDimensionPixelSize(R.dimen.overflow_dot_radius);
         mStaticDotDiameter = 2 * radius;
         mUnderflowWidth = mIconDotFrameWidth + (MAX_DOTS - 1) * (mStaticDotDiameter + mDotPadding);
@@ -163,20 +165,21 @@
         // Measure all children so that they report the correct width
         int childWidthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.UNSPECIFIED);
         mNeedsUnderflow = mShouldRestrictIcons && visibleCount > MAX_ICONS;
-        for (int i = 0; i < mMeasureViews.size(); i++) {
+        for (int i = 0; i < visibleCount; i++) {
             // Walking backwards
             View child = mMeasureViews.get(visibleCount - i - 1);
             measureChild(child, childWidthSpec, heightMeasureSpec);
+            int spacing = i == visibleCount - 1 ? 0 : mIconSpacing;
             if (mShouldRestrictIcons) {
                 if (i < maxVisible && trackWidth) {
-                    totalWidth += getViewTotalMeasuredWidth(child);
+                    totalWidth += getViewTotalMeasuredWidth(child) + spacing;
                 } else if (trackWidth) {
                     // We've hit the icon limit; add space for dots
                     totalWidth += mUnderflowWidth;
                     trackWidth = false;
                 }
             } else {
-                totalWidth += getViewTotalMeasuredWidth(child);
+                totalWidth += getViewTotalMeasuredWidth(child) + spacing;
             }
         }
 
@@ -284,11 +287,15 @@
                 continue;
             }
 
+            // Move translationX to the spot within StatusIconContainer's layout to add the view
+            // without cutting off the child view.
+            translationX -= getViewTotalWidth(child);
             childState.visibleState = STATE_ICON;
-            childState.xTranslation = translationX - getViewTotalWidth(child);
+            childState.xTranslation = translationX;
             mLayoutStates.add(0, childState);
 
-            translationX -= getViewTotalWidth(child);
+            // Shift translationX over by mIconSpacing for the next view.
+            translationX -= mIconSpacing;
         }
 
         // Show either 1-MAX_ICONS icons, or (MAX_ICONS - 1) icons + overflow
@@ -306,7 +313,8 @@
                 firstUnderflowIndex = i;
                 break;
             }
-            mUnderflowStart = (int) Math.max(contentStart, state.xTranslation - mUnderflowWidth);
+            mUnderflowStart = (int) Math.max(
+                    contentStart, state.xTranslation - mUnderflowWidth - mIconSpacing);
             visible++;
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 50052b8..6dd1133 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -315,7 +315,7 @@
         filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
         filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
         filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
-        filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+        filter.addAction(Intent.ACTION_SIM_STATE_CHANGED);
         filter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
         filter.addAction(TelephonyManager.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED);
         filter.addAction(Intent.ACTION_SERVICE_STATE);
@@ -524,7 +524,7 @@
                 mConfig = Config.readConfig(mContext);
                 mReceiverHandler.post(this::handleConfigurationChanged);
                 break;
-            case TelephonyIntents.ACTION_SIM_STATE_CHANGED:
+            case Intent.ACTION_SIM_STATE_CHANGED:
                 // Avoid rebroadcast because SysUI is direct boot aware.
                 if (intent.getBooleanExtra(Intent.EXTRA_REBROADCAST_ON_UNLOCK, false)) {
                     break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
index 718522c..6baf36c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -54,7 +54,8 @@
         mWifiTracker.setListening(true);
         mHasMobileData = hasMobileData;
         if (wifiManager != null) {
-            wifiManager.registerTrafficStateCallback(new WifiTrafficStateCallback());
+            wifiManager.registerTrafficStateCallback(context.getMainExecutor(),
+                    new WifiTrafficStateCallback());
         }
         // WiFi only has one state.
         mCurrentState.iconGroup = mLastState.iconGroup = new IconGroup(
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java
index 41e026a..665cb63 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java
@@ -178,7 +178,7 @@
                 } else {
                     mOverlayManager.setEnabled(pkg, false, userHandle);
                 }
-            } catch (IllegalStateException e) {
+            } catch (SecurityException | IllegalStateException e) {
                 Log.e(TAG,
                         String.format("setEnabled failed: %s %s %b", pkg, userHandle, enabled), e);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/toast/ToastUI.java b/packages/SystemUI/src/com/android/systemui/toast/ToastUI.java
new file mode 100644
index 0000000..dea8c5d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/toast/ToastUI.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.toast;
+
+import android.annotation.MainThread;
+import android.annotation.Nullable;
+import android.app.INotificationManager;
+import android.app.ITransientNotificationCallback;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.PixelFormat;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+import android.view.WindowManager;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.android.internal.R;
+import com.android.systemui.SystemUI;
+import com.android.systemui.statusbar.CommandQueue;
+
+import java.util.Objects;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Controls display of text toasts.
+ */
+@Singleton
+public class ToastUI extends SystemUI implements CommandQueue.Callbacks {
+    private static final String TAG = "ToastUI";
+
+    /**
+     * Values taken from {@link Toast}.
+     */
+    private static final long DURATION_SHORT = 4000;
+    private static final long DURATION_LONG = 7000;
+
+    private final CommandQueue mCommandQueue;
+    private final WindowManager mWindowManager;
+    private final INotificationManager mNotificationManager;
+    private final AccessibilityManager mAccessibilityManager;
+    private ToastEntry mCurrentToast;
+
+    @Inject
+    public ToastUI(Context context, CommandQueue commandQueue) {
+        super(context);
+        mCommandQueue = commandQueue;
+        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+        mNotificationManager = INotificationManager.Stub.asInterface(
+                ServiceManager.getService(Context.NOTIFICATION_SERVICE));
+        mAccessibilityManager = AccessibilityManager.getInstance(context);
+    }
+
+    @Override
+    public void start() {
+        mCommandQueue.addCallback(this);
+    }
+
+    @Override
+    @MainThread
+    public void showToast(String packageName, IBinder token, CharSequence text,
+            IBinder windowToken, int duration, @Nullable ITransientNotificationCallback callback) {
+        if (mCurrentToast != null) {
+            hideCurrentToast();
+        }
+        View view = getView(text);
+        LayoutParams params = getLayoutParams(windowToken, duration);
+        mCurrentToast = new ToastEntry(packageName, token, view, windowToken, callback);
+        try {
+            mWindowManager.addView(view, params);
+        } catch (WindowManager.BadTokenException e) {
+            Log.w(TAG, "Error while attempting to show toast from " + packageName, e);
+            return;
+        }
+        trySendAccessibilityEvent(view, packageName);
+        if (callback != null) {
+            try {
+                callback.onToastShown();
+            } catch (RemoteException e) {
+                Log.w(TAG, "Error calling back " + packageName + " to notify onToastShow()", e);
+            }
+        }
+    }
+
+    @Override
+    @MainThread
+    public void hideToast(String packageName, IBinder token) {
+        if (mCurrentToast == null || !Objects.equals(mCurrentToast.packageName, packageName)
+                || !Objects.equals(mCurrentToast.token, token)) {
+            Log.w(TAG, "Attempt to hide non-current toast from package " + packageName);
+            return;
+        }
+        hideCurrentToast();
+    }
+
+    @MainThread
+    private void hideCurrentToast() {
+        if (mCurrentToast.view.getParent() != null) {
+            mWindowManager.removeViewImmediate(mCurrentToast.view);
+        }
+        String packageName = mCurrentToast.packageName;
+        try {
+            mNotificationManager.finishToken(packageName, mCurrentToast.windowToken);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Error finishing toast window token from package " + packageName, e);
+        }
+        if (mCurrentToast.callback != null) {
+            try {
+                mCurrentToast.callback.onToastHidden();
+            } catch (RemoteException e) {
+                Log.w(TAG, "Error calling back " + packageName + " to notify onToastHide()", e);
+            }
+        }
+        mCurrentToast = null;
+    }
+
+    private void trySendAccessibilityEvent(View view, String packageName) {
+        if (!mAccessibilityManager.isEnabled()) {
+            return;
+        }
+        AccessibilityEvent event = AccessibilityEvent.obtain(
+                AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED);
+        event.setClassName(Toast.class.getName());
+        event.setPackageName(packageName);
+        view.dispatchPopulateAccessibilityEvent(event);
+        mAccessibilityManager.sendAccessibilityEvent(event);
+    }
+
+    private View getView(CharSequence text) {
+        View view = LayoutInflater.from(mContext).inflate(
+                R.layout.transient_notification, null);
+        TextView textView = view.findViewById(com.android.internal.R.id.message);
+        textView.setText(text);
+        return view;
+    }
+
+    private LayoutParams getLayoutParams(IBinder windowToken, int duration) {
+        WindowManager.LayoutParams params = new WindowManager.LayoutParams();
+        params.height = WindowManager.LayoutParams.WRAP_CONTENT;
+        params.width = WindowManager.LayoutParams.WRAP_CONTENT;
+        params.format = PixelFormat.TRANSLUCENT;
+        params.windowAnimations = com.android.internal.R.style.Animation_Toast;
+        params.type = WindowManager.LayoutParams.TYPE_TOAST;
+        params.setTitle("Toast");
+        params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
+                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+        Configuration config = mContext.getResources().getConfiguration();
+        int specificGravity = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_toastDefaultGravity);
+        int gravity = Gravity.getAbsoluteGravity(specificGravity, config.getLayoutDirection());
+        params.gravity = gravity;
+        if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) {
+            params.horizontalWeight = 1.0f;
+        }
+        if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.FILL_VERTICAL) {
+            params.verticalWeight = 1.0f;
+        }
+        params.x = 0;
+        params.y = mContext.getResources().getDimensionPixelSize(R.dimen.toast_y_offset);
+        params.verticalMargin = 0;
+        params.horizontalMargin = 0;
+        params.packageName = mContext.getPackageName();
+        params.hideTimeoutMilliseconds =
+                (duration == Toast.LENGTH_LONG) ? DURATION_LONG : DURATION_SHORT;
+        params.token = windowToken;
+        return params;
+    }
+
+    private static class ToastEntry {
+        public final String packageName;
+        public final IBinder token;
+        public final View view;
+        public final IBinder windowToken;
+
+        @Nullable
+        public final ITransientNotificationCallback callback;
+
+        private ToastEntry(String packageName, IBinder token, View view, IBinder windowToken,
+                @Nullable ITransientNotificationCallback callback) {
+            this.packageName = packageName;
+            this.token = token;
+            this.view = view;
+            this.windowToken = windowToken;
+            this.callback = callback;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tracing/ProtoTracer.java b/packages/SystemUI/src/com/android/systemui/tracing/ProtoTracer.java
new file mode 100644
index 0000000..3bef044
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tracing/ProtoTracer.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.tracing;
+
+import static com.android.systemui.tracing.nano.SystemUiTraceFileProto.MAGIC_NUMBER_H;
+import static com.android.systemui.tracing.nano.SystemUiTraceFileProto.MAGIC_NUMBER_L;
+
+import android.content.Context;
+import android.os.SystemClock;
+
+import androidx.annotation.NonNull;
+
+import com.android.systemui.DumpController;
+import com.android.systemui.Dumpable;
+import com.android.systemui.shared.tracing.FrameProtoTracer;
+import com.android.systemui.shared.tracing.FrameProtoTracer.ProtoTraceParams;
+import com.android.systemui.shared.tracing.ProtoTraceable;
+import com.android.systemui.tracing.nano.SystemUiTraceProto;
+import com.android.systemui.tracing.nano.SystemUiTraceEntryProto;
+import com.android.systemui.tracing.nano.SystemUiTraceFileProto;
+
+import com.google.protobuf.nano.MessageNano;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Queue;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Controller for coordinating winscope proto tracing.
+ */
+@Singleton
+public class ProtoTracer implements Dumpable, ProtoTraceParams<MessageNano, SystemUiTraceFileProto,
+        SystemUiTraceEntryProto, SystemUiTraceProto> {
+
+    private static final String TAG = "ProtoTracer";
+    private static final long MAGIC_NUMBER_VALUE = ((long) MAGIC_NUMBER_H << 32) | MAGIC_NUMBER_L;
+
+    private final Context mContext;
+    private final FrameProtoTracer<MessageNano, SystemUiTraceFileProto, SystemUiTraceEntryProto,
+            SystemUiTraceProto> mProtoTracer;
+
+    @Inject
+    public ProtoTracer(Context context, DumpController dumpController) {
+        mContext = context;
+        mProtoTracer = new FrameProtoTracer<>(this);
+        dumpController.registerDumpable(this);
+    }
+
+    @Override
+    public File getTraceFile() {
+        return new File(mContext.getFilesDir(), "sysui_trace.pb");
+    }
+
+    @Override
+    public SystemUiTraceFileProto getEncapsulatingTraceProto() {
+        return new SystemUiTraceFileProto();
+    }
+
+    @Override
+    public SystemUiTraceEntryProto updateBufferProto(SystemUiTraceEntryProto reuseObj,
+            ArrayList<ProtoTraceable<SystemUiTraceProto>> traceables) {
+        SystemUiTraceEntryProto proto = reuseObj != null
+                ? reuseObj
+                : new SystemUiTraceEntryProto();
+        proto.elapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos();
+        proto.systemUi = proto.systemUi != null ? proto.systemUi : new SystemUiTraceProto();
+        for (ProtoTraceable t : traceables) {
+            t.writeToProto(proto.systemUi);
+        }
+        return proto;
+    }
+
+    @Override
+    public byte[] serializeEncapsulatingProto(SystemUiTraceFileProto encapsulatingProto,
+            Queue<SystemUiTraceEntryProto> buffer) {
+        encapsulatingProto.magicNumber = MAGIC_NUMBER_VALUE;
+        encapsulatingProto.entry = buffer.toArray(new SystemUiTraceEntryProto[0]);
+        return MessageNano.toByteArray(encapsulatingProto);
+    }
+
+    @Override
+    public byte[] getProtoBytes(MessageNano proto) {
+        return MessageNano.toByteArray(proto);
+    }
+
+    @Override
+    public int getProtoSize(MessageNano proto) {
+        return proto.getCachedSize();
+    }
+
+    public void start() {
+        mProtoTracer.start();
+    }
+
+    public void stop() {
+        mProtoTracer.stop();
+    }
+
+    public boolean isEnabled() {
+        return mProtoTracer.isEnabled();
+    }
+
+    public void add(ProtoTraceable<SystemUiTraceProto> traceable) {
+        mProtoTracer.add(traceable);
+    }
+
+    public void remove(ProtoTraceable<SystemUiTraceProto> traceable) {
+        mProtoTracer.remove(traceable);
+    }
+
+    public void scheduleFrameUpdate() {
+        mProtoTracer.scheduleFrameUpdate();
+    }
+
+    public void update() {
+        mProtoTracer.update();
+    }
+
+    @Override
+    public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
+        pw.println("ProtoTracer:");
+        pw.print("    "); pw.println("enabled: " + mProtoTracer.isEnabled());
+        pw.print("    "); pw.println("usagePct: " + mProtoTracer.getBufferUsagePct());
+        pw.print("    "); pw.println("file: " + getTraceFile());
+    }
+}
diff --git a/core/java/android/service/controls/actions/CommandAction.aidl b/packages/SystemUI/src/com/android/systemui/tracing/sysui_trace.proto
similarity index 68%
copy from core/java/android/service/controls/actions/CommandAction.aidl
copy to packages/SystemUI/src/com/android/systemui/tracing/sysui_trace.proto
index 7c1ee41..08ae99c 100644
--- a/core/java/android/service/controls/actions/CommandAction.aidl
+++ b/packages/SystemUI/src/com/android/systemui/tracing/sysui_trace.proto
@@ -13,6 +13,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.service.controls.actions;
 
-parcelable CommandAction;
\ No newline at end of file
+syntax = "proto2";
+
+package com.android.systemui.tracing;
+
+option java_multiple_files = true;
+
+message SystemUiTraceProto {
+
+    optional EdgeBackGestureHandlerProto edge_back_gesture_handler = 1;
+}
+
+message EdgeBackGestureHandlerProto {
+
+    optional bool allow_gesture = 1;
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tracing/sysui_trace_file.proto b/packages/SystemUI/src/com/android/systemui/tracing/sysui_trace_file.proto
new file mode 100644
index 0000000..d1523ef
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tracing/sysui_trace_file.proto
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+
+import "frameworks/base/packages/SystemUI/src/com/android/systemui/tracing/sysui_trace.proto";
+
+package com.android.systemui.tracing;
+
+option java_multiple_files = true;
+
+/* represents a file full of system ui trace entries.
+   Encoded, it should start with 0x9 0x53 0x59 0x53 0x55 0x49 0x54 0x52 0x43 (.SYSUITRC), such
+   that they can be easily identified. */
+message SystemUiTraceFileProto {
+
+    /* constant; MAGIC_NUMBER = (long) MAGIC_NUMBER_H << 32 | MagicNumber.MAGIC_NUMBER_L
+       (this is needed because enums have to be 32 bits and there's no nice way to put 64bit
+        constants into .proto files. */
+    enum MagicNumber {
+        INVALID = 0;
+        MAGIC_NUMBER_L = 0x55535953;  /* SYSU (little-endian ASCII) */
+        MAGIC_NUMBER_H = 0x43525449;  /* ITRC (little-endian ASCII) */
+    }
+
+    optional fixed64 magic_number = 1;  /* Must be the first field, set to value in MagicNumber */
+    repeated SystemUiTraceEntryProto entry = 2;
+}
+
+/* one system ui trace entry. */
+message SystemUiTraceEntryProto {
+    /* required: elapsed realtime in nanos since boot of when this entry was logged */
+    optional fixed64 elapsed_realtime_nanos = 1;
+
+    optional SystemUiTraceProto system_ui = 3;
+}
diff --git a/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java b/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java
index 5aba013..adce124 100644
--- a/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java
+++ b/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java
@@ -239,12 +239,12 @@
                 Rect outVisibleInsets, Rect outStableInsets,
                 DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,
                 SurfaceControl outSurfaceControl, InsetsState outInsetsState,
-                Point outSurfaceSize) {
+                Point outSurfaceSize, SurfaceControl outBLASTSurfaceControl) {
             int res = super.relayout(window, seq, attrs, requestedWidth, requestedHeight,
                     viewVisibility, flags, frameNumber, outFrame, outOverscanInsets,
                     outContentInsets, outVisibleInsets, outStableInsets,
                     cutout, mergedConfiguration, outSurfaceControl, outInsetsState,
-                    outSurfaceSize);
+                    outSurfaceSize, outBLASTSurfaceControl);
             if (res != 0) {
                 return res;
             }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index 2c9058a..28f01da 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -282,7 +282,7 @@
                 mRow.getEntry().getKey()));
 
         // Make it look like dismissed notif
-        mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()).setShowInShade(false);
+        mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()).setSuppressNotification(true);
 
         // Now remove the bubble
         mBubbleController.removeBubble(
@@ -372,7 +372,8 @@
 
         // Switch which bubble is expanded
         mBubbleController.selectBubble(mRow.getEntry().getKey());
-        mBubbleController.expandStack();
+        mBubbleData.setExpanded(true);
+        assertEquals(mRow.getEntry(), stackView.getExpandedBubble().getEntry());
         assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
                 mRow.getEntry().getKey()));
 
@@ -571,7 +572,6 @@
         verify(mBubbleStateChangeListener).onHasBubblesChanged(true /* hasBubbles */);
     }
 
-
     @Test
     public void testExpandStackAndSelectBubble_removedFirst() {
         final String key = mRow.getEntry().getKey();
@@ -724,6 +724,52 @@
         assertFalse(intercepted);
     }
 
+    @Test
+    public void testNotifyShadeSuppressionChange_notificationDismiss() {
+        BubbleController.NotificationSuppressionChangedListener listener =
+                mock(BubbleController.NotificationSuppressionChangedListener.class);
+        mBubbleData.setSuppressionChangedListener(listener);
+
+        mEntryListener.onNotificationAdded(mRow.getEntry());
+
+        assertTrue(mBubbleController.hasBubbles());
+        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
+
+        mRemoveInterceptor.onNotificationRemoveRequested(mRow.getEntry().getKey(), REASON_CANCEL);
+
+        // Should update show in shade state
+        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
+
+        // Should notify delegate that shade state changed
+        verify(listener).onBubbleNotificationSuppressionChange(
+                mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()));
+    }
+
+    @Test
+    public void testNotifyShadeSuppressionChange_bubbleExpanded() {
+        BubbleController.NotificationSuppressionChangedListener listener =
+                mock(BubbleController.NotificationSuppressionChangedListener.class);
+        mBubbleData.setSuppressionChangedListener(listener);
+
+        mEntryListener.onNotificationAdded(mRow.getEntry());
+
+        assertTrue(mBubbleController.hasBubbles());
+        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
+
+        mBubbleData.setExpanded(true);
+
+        // Once a bubble is expanded the notif is suppressed
+        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
+
+        // Should notify delegate that shade state changed
+        verify(listener).onBubbleNotificationSuppressionChange(
+                mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()));
+    }
+
     static class TestableBubbleController extends BubbleController {
         // Let's assume surfaces can be synchronized immediately.
         TestableBubbleController(Context context,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
index b09603d..c9f5b40 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
@@ -104,6 +104,9 @@
     @Captor
     private ArgumentCaptor<BubbleData.Update> mUpdateCaptor;
 
+    @Mock
+    private BubbleController.NotificationSuppressionChangedListener mSuppressionListener;
+
     @Before
     public void setUp() throws Exception {
         mNotificationTestHelper = new NotificationTestHelper(mContext, mDependency);
@@ -121,20 +124,20 @@
         modifyRanking(mEntryInterruptive)
                 .setVisuallyInterruptive(true)
                 .build();
-        mBubbleInterruptive = new Bubble(mEntryInterruptive);
+        mBubbleInterruptive = new Bubble(mEntryInterruptive, mSuppressionListener);
 
         ExpandableNotificationRow row = mNotificationTestHelper.createBubble();
         mEntryDismissed = createBubbleEntry(1, "dismissed", "package.d");
         mEntryDismissed.setRow(row);
-        mBubbleDismissed = new Bubble(mEntryDismissed);
+        mBubbleDismissed = new Bubble(mEntryDismissed, mSuppressionListener);
 
-        mBubbleA1 = new Bubble(mEntryA1);
-        mBubbleA2 = new Bubble(mEntryA2);
-        mBubbleA3 = new Bubble(mEntryA3);
-        mBubbleB1 = new Bubble(mEntryB1);
-        mBubbleB2 = new Bubble(mEntryB2);
-        mBubbleB3 = new Bubble(mEntryB3);
-        mBubbleC1 = new Bubble(mEntryC1);
+        mBubbleA1 = new Bubble(mEntryA1, mSuppressionListener);
+        mBubbleA2 = new Bubble(mEntryA2, mSuppressionListener);
+        mBubbleA3 = new Bubble(mEntryA3, mSuppressionListener);
+        mBubbleB1 = new Bubble(mEntryB1, mSuppressionListener);
+        mBubbleB2 = new Bubble(mEntryB2, mSuppressionListener);
+        mBubbleB3 = new Bubble(mEntryB3, mSuppressionListener);
+        mBubbleC1 = new Bubble(mEntryC1, mSuppressionListener);
 
         mBubbleData = new BubbleData(getContext());
 
@@ -237,9 +240,8 @@
                 true /* showInShade */);
         verifyUpdateReceived();
 
-        // Make it look like user swiped away row
-        mEntryDismissed.getRow().dismiss(false /* refocusOnDismiss */);
-        assertThat(mBubbleData.getBubbleWithKey(mBubbleDismissed.getKey()).showInShade()).isFalse();
+        // Suppress the notif / make it look dismissed
+        mBubbleDismissed.setSuppressNotification(true);
 
         mBubbleData.notificationEntryUpdated(mBubbleDismissed, false /* suppressFlyout */,
                 true /* showInShade */);
@@ -257,7 +259,7 @@
      * enforced by expiring the bubble which was least recently updated (lowest timestamp).
      */
     @Test
-    public void test_collapsed_addBubble_atMaxBubbles_expiresOldest() {
+    public void test_collapsed_addBubble_atMaxBubbles_overflowsOldest() {
         // Setup
         sendUpdatedEntryAtTime(mEntryA1, 1000);
         sendUpdatedEntryAtTime(mEntryA2, 2000);
@@ -269,7 +271,10 @@
         // Test
         sendUpdatedEntryAtTime(mEntryC1, 6000);
         verifyUpdateReceived();
+
+        // Verify
         assertBubbleRemoved(mBubbleA1, BubbleController.DISMISS_AGED);
+        assertThat(mBubbleData.getOverflowBubbles()).isEqualTo(ImmutableList.of(mBubbleA1));
     }
 
     /**
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleTest.java
index 02f721c..7f67657 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleTest.java
@@ -16,11 +16,19 @@
 
 package com.android.systemui.bubbles;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
 
 import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
 import android.os.Bundle;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -30,6 +38,7 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
+import com.android.systemui.tests.R;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -46,6 +55,10 @@
 
     private NotificationEntry mEntry;
     private Bundle mExtras;
+    private Bubble mBubble;
+
+    @Mock
+    private BubbleController.NotificationSuppressionChangedListener mSuppressionListener;
 
     @Before
     public void setUp() {
@@ -57,6 +70,15 @@
         mEntry = new NotificationEntryBuilder()
                 .setNotification(mNotif)
                 .build();
+
+        mBubble = new Bubble(mEntry, mSuppressionListener);
+
+        Intent target = new Intent(mContext, BubblesTestActivity.class);
+        Notification.BubbleMetadata metadata = new Notification.BubbleMetadata.Builder()
+                .createIntentBubble(PendingIntent.getActivity(mContext, 0, target, 0),
+                        Icon.createWithResource(mContext, R.drawable.android))
+                .build();
+        mEntry.setBubbleMetadata(metadata);
     }
 
     @Test
@@ -123,4 +145,24 @@
                 BubbleViewInfoTask.extractFlyoutMessage(mContext,
                         mEntry).senderName);
     }
+
+    @Test
+    public void testSuppressionListener_change_notified() {
+        assertThat(mBubble.showInShade()).isTrue();
+
+        mBubble.setSuppressNotification(true);
+
+        assertThat(mBubble.showInShade()).isFalse();
+
+        verify(mSuppressionListener).onBubbleNotificationSuppressionChange(mBubble);
+    }
+
+    @Test
+    public void testSuppressionListener_noChange_doesntNotify() {
+        assertThat(mBubble.showInShade()).isTrue();
+
+        mBubble.setSuppressNotification(false);
+
+        verify(mSuppressionListener, never()).onBubbleNotificationSuppressionChange(any());
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
index a19c299..be86a9c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
@@ -224,8 +224,9 @@
 
     @Test
     fun testRefreshStatus() {
-        val list = listOf(Control.StatefulBuilder(TEST_CONTROL_ID, pendingIntent).build())
-        controller.refreshStatus(TEST_COMPONENT, list)
+        val control = Control.StatefulBuilder(TEST_CONTROL_ID, pendingIntent).build()
+        val list = listOf(control)
+        controller.refreshStatus(TEST_COMPONENT, control)
 
         verify(uiController).onRefreshState(TEST_COMPONENT, list)
     }
@@ -340,7 +341,7 @@
         val newControlInfo = TEST_CONTROL_INFO.copy(controlTitle = TEST_CONTROL_TITLE_2)
         val control = builderFromInfo(newControlInfo).build()
 
-        controller.refreshStatus(TEST_COMPONENT, listOf(control))
+        controller.refreshStatus(TEST_COMPONENT, control)
 
         delayableExecutor.runAllReady()
 
@@ -357,4 +358,4 @@
         controller.clearFavorites()
         assertTrue(controller.getFavoriteControls().isEmpty())
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
index 556bb40..4fc1cca 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
@@ -18,9 +18,12 @@
 
 import android.content.ComponentName
 import android.service.controls.Control
+import android.service.controls.IControlsActionCallback
+import android.service.controls.IControlsLoadCallback
 import android.service.controls.IControlsProvider
-import android.service.controls.IControlsProviderCallback
+import android.service.controls.IControlsSubscriber
 import android.service.controls.actions.ControlAction
+import android.service.controls.actions.ControlActionWrapper
 import android.testing.AndroidTestingRunner
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
@@ -35,7 +38,10 @@
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
 import org.mockito.ArgumentMatchers
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.Captor
 import org.mockito.Mock
 import org.mockito.Mockito.`when`
 import org.mockito.Mockito.verify
@@ -46,14 +52,25 @@
 class ControlsProviderLifecycleManagerTest : SysuiTestCase() {
 
     @Mock
-    private lateinit var serviceCallback: IControlsProviderCallback.Stub
+    private lateinit var actionCallback: IControlsActionCallback.Stub
+    @Mock
+    private lateinit var loadCallback: IControlsLoadCallback.Stub
+    @Mock
+    private lateinit var subscriber: IControlsSubscriber.Stub
     @Mock
     private lateinit var service: IControlsProvider.Stub
 
+    @Captor
+    private lateinit var wrapperCaptor: ArgumentCaptor<ControlActionWrapper>
+
     private val componentName = ComponentName("test.pkg", "test.cls")
     private lateinit var manager: ControlsProviderLifecycleManager
     private lateinit var executor: DelayableExecutor
 
+    companion object {
+        fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
+    }
+
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
@@ -66,7 +83,9 @@
         manager = ControlsProviderLifecycleManager(
                 context,
                 executor,
-                serviceCallback,
+                loadCallback,
+                actionCallback,
+                subscriber,
                 componentName
         )
     }
@@ -94,7 +113,7 @@
         val callback: (List<Control>) -> Unit = {}
         manager.maybeBindAndLoad(callback)
 
-        verify(service).load()
+        verify(service).load(loadCallback)
 
         assertTrue(mContext.isBound(componentName))
         assertEquals(callback, manager.lastLoadCallback)
@@ -110,29 +129,23 @@
     }
 
     @Test
-    fun testUnsubscribe() {
-        manager.bindPermanently()
-        manager.unsubscribe()
-
-        verify(service).unsubscribe()
-    }
-
-    @Test
     fun testMaybeBindAndSubscribe() {
         val list = listOf("TEST_ID")
         manager.maybeBindAndSubscribe(list)
 
         assertTrue(mContext.isBound(componentName))
-        verify(service).subscribe(list)
+        verify(service).subscribe(list, subscriber)
     }
 
     @Test
     fun testMaybeBindAndAction() {
         val controlId = "TEST_ID"
-        val action = ControlAction.UNKNOWN_ACTION
+        val action = ControlAction.ERROR_ACTION
         manager.maybeBindAndSendAction(controlId, action)
 
         assertTrue(mContext.isBound(componentName))
-        verify(service).onAction(controlId, action)
+        verify(service).action(eq(controlId), capture(wrapperCaptor),
+                eq(actionCallback))
+        assertEquals(action, wrapperCaptor.getValue().getWrappedAction())
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderServiceWrapperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderServiceWrapperTest.kt
deleted file mode 100644
index d6993c0..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderServiceWrapperTest.kt
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.controls.controller
-
-import android.os.RemoteException
-import android.service.controls.IControlsProvider
-import android.service.controls.actions.ControlAction
-import android.testing.AndroidTestingRunner
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import org.junit.Assert.assertFalse
-import org.junit.Assert.assertTrue
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito.`when`
-import org.mockito.Mockito.any
-import org.mockito.Mockito.verify
-import org.mockito.MockitoAnnotations
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-class ControlsProviderServiceWrapperTest : SysuiTestCase() {
-
-    @Mock
-    private lateinit var service: IControlsProvider
-
-    private val exception = RemoteException()
-
-    private lateinit var wrapper: ControlsProviderServiceWrapper
-
-    @Before
-    fun setUp() {
-        MockitoAnnotations.initMocks(this)
-
-        wrapper = ControlsProviderServiceWrapper(service)
-    }
-
-    @Test
-    fun testLoad_happyPath() {
-        val result = wrapper.load()
-
-        assertTrue(result)
-        verify(service).load()
-    }
-
-    @Test
-    fun testLoad_error() {
-        `when`(service.load()).thenThrow(exception)
-        val result = wrapper.load()
-
-        assertFalse(result)
-    }
-
-    @Test
-    fun testSubscribe_happyPath() {
-        val list = listOf("TEST_ID")
-        val result = wrapper.subscribe(list)
-
-        assertTrue(result)
-        verify(service).subscribe(list)
-    }
-
-    @Test
-    fun testSubscribe_error() {
-        `when`(service.subscribe(any())).thenThrow(exception)
-
-        val list = listOf("TEST_ID")
-        val result = wrapper.subscribe(list)
-
-        assertFalse(result)
-    }
-
-    @Test
-    fun testUnsubscribe_happyPath() {
-        val result = wrapper.unsubscribe()
-
-        assertTrue(result)
-        verify(service).unsubscribe()
-    }
-
-    @Test
-    fun testUnsubscribe_error() {
-        `when`(service.unsubscribe()).thenThrow(exception)
-        val result = wrapper.unsubscribe()
-
-        assertFalse(result)
-    }
-
-    @Test
-    fun testOnAction_happyPath() {
-        val id = "TEST_ID"
-        val action = ControlAction.UNKNOWN_ACTION
-
-        val result = wrapper.onAction(id, action)
-
-        assertTrue(result)
-        verify(service).onAction(id, action)
-    }
-
-    @Test
-    fun testOnAction_error() {
-        `when`(service.onAction(any(), any())).thenThrow(exception)
-
-        val id = "TEST_ID"
-        val action = ControlAction.UNKNOWN_ACTION
-
-        val result = wrapper.onAction(id, action)
-
-        assertFalse(result)
-    }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ServiceWrapperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ServiceWrapperTest.kt
new file mode 100644
index 0000000..9e7ce06
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ServiceWrapperTest.kt
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.controls.controller
+
+import android.os.RemoteException
+import android.service.controls.IControlsActionCallback
+import android.service.controls.IControlsLoadCallback
+import android.service.controls.IControlsProvider
+import android.service.controls.IControlsSubscriber
+import android.service.controls.IControlsSubscription
+import android.service.controls.actions.ControlAction
+import android.service.controls.actions.ControlActionWrapper
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.any
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class ServiceWrapperTest : SysuiTestCase() {
+
+    @Mock
+    private lateinit var service: IControlsProvider
+
+    @Mock
+    private lateinit var subscription: IControlsSubscription
+
+    @Mock
+    private lateinit var subscriber: IControlsSubscriber
+
+    @Mock
+    private lateinit var loadCallback: IControlsLoadCallback
+
+    @Mock
+    private lateinit var actionCallback: IControlsActionCallback
+
+    @Captor
+    private lateinit var wrapperCaptor: ArgumentCaptor<ControlActionWrapper>
+
+    private val exception = RemoteException()
+
+    private lateinit var wrapper: ServiceWrapper
+
+    companion object {
+        fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
+    }
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+
+        wrapper = ServiceWrapper(service)
+    }
+
+    @Test
+    fun testLoad_happyPath() {
+        val result = wrapper.load(loadCallback)
+
+        assertTrue(result)
+        verify(service).load(loadCallback)
+    }
+
+    @Test
+    fun testLoad_error() {
+        `when`(service.load(any())).thenThrow(exception)
+        val result = wrapper.load(loadCallback)
+
+        assertFalse(result)
+    }
+
+    @Test
+    fun testSubscribe_happyPath() {
+        val list = listOf("TEST_ID")
+        val result = wrapper.subscribe(list, subscriber)
+
+        assertTrue(result)
+        verify(service).subscribe(list, subscriber)
+    }
+
+    @Test
+    fun testSubscribe_error() {
+        `when`(service.subscribe(any(), any())).thenThrow(exception)
+
+        val list = listOf("TEST_ID")
+        val result = wrapper.subscribe(list, subscriber)
+
+        assertFalse(result)
+    }
+
+    @Test
+    fun testCancel_happyPath() {
+        val result = wrapper.cancel(subscription)
+
+        assertTrue(result)
+        verify(subscription).cancel()
+    }
+
+    @Test
+    fun testCancel_error() {
+        `when`(subscription.cancel()).thenThrow(exception)
+        val result = wrapper.cancel(subscription)
+
+        assertFalse(result)
+    }
+
+    @Test
+    fun testOnAction_happyPath() {
+        val id = "TEST_ID"
+        val action = ControlAction.ERROR_ACTION
+
+        val result = wrapper.action(id, action, actionCallback)
+
+        assertTrue(result)
+        verify(service).action(eq(id), capture(wrapperCaptor),
+                eq(actionCallback))
+        assertEquals(action, wrapperCaptor.getValue().getWrappedAction())
+    }
+
+    @Test
+    fun testOnAction_error() {
+        `when`(service.action(any(), any(), any())).thenThrow(exception)
+
+        val id = "TEST_ID"
+        val action = ControlAction.ERROR_ACTION
+
+        val result = wrapper.action(id, action, actionCallback)
+
+        assertFalse(result)
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/pip/PipBoundsHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/pip/PipBoundsHandlerTest.java
new file mode 100644
index 0000000..bc3ce8b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/pip/PipBoundsHandlerTest.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.pip;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+
+import android.content.ComponentName;
+import android.graphics.Rect;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.testing.TestableResources;
+import android.view.DisplayInfo;
+import android.view.Gravity;
+import android.view.IPinnedStackController;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Unit tests against {@link PipBoundsHandler}, including but not limited to:
+ * - default/movement bounds
+ * - save/restore PiP position on application lifecycle
+ * - save/restore PiP position on screen rotation
+ */
+@RunWith(AndroidTestingRunner.class)
+@SmallTest
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+public class PipBoundsHandlerTest extends SysuiTestCase {
+    private static final int ROUNDING_ERROR_MARGIN = 10;
+
+    private PipBoundsHandler mPipBoundsHandler;
+    private DisplayInfo mDefaultDisplayInfo;
+    private Rect mDefaultDisplayRect;
+
+    @Mock
+    private IPinnedStackController mPinnedStackController;
+
+    @Before
+    public void setUp() throws Exception {
+        mPipBoundsHandler = new PipBoundsHandler(mContext);
+        MockitoAnnotations.initMocks(this);
+        initializeMockResources();
+
+        mPipBoundsHandler.onDisplayInfoChanged(mDefaultDisplayInfo);
+        mPipBoundsHandler.setPinnedStackController(mPinnedStackController);
+    }
+
+    private void initializeMockResources() {
+        final TestableResources res = mContext.getOrCreateTestableResources();
+        res.addOverride(
+                com.android.internal.R.dimen.config_pictureInPictureDefaultAspectRatio, 1f);
+        res.addOverride(
+                com.android.internal.R.integer.config_defaultPictureInPictureGravity,
+                Gravity.END | Gravity.BOTTOM);
+        res.addOverride(
+                com.android.internal.R.dimen.default_minimal_size_pip_resizable_task, 100);
+        res.addOverride(
+                com.android.internal.R.string.config_defaultPictureInPictureScreenEdgeInsets,
+                "16x16");
+        res.addOverride(
+                com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio, 0.5f);
+        res.addOverride(
+                com.android.internal.R.dimen.config_pictureInPictureMaxAspectRatio, 2f);
+
+        mDefaultDisplayInfo = new DisplayInfo();
+        mDefaultDisplayInfo.displayId = 1;
+        mDefaultDisplayInfo.logicalWidth = 1000;
+        mDefaultDisplayInfo.logicalHeight = 1500;
+        mDefaultDisplayRect = new Rect(0, 0,
+                mDefaultDisplayInfo.logicalWidth, mDefaultDisplayInfo.logicalHeight);
+    }
+
+    @Test
+    public void setShelfHeight_offsetBounds() throws Exception {
+        final ArgumentCaptor<Rect> destinationBounds = ArgumentCaptor.forClass(Rect.class);
+        final int shelfHeight = 100;
+
+        mPipBoundsHandler.onPrepareAnimation(null, 1f, null);
+
+        verify(mPinnedStackController).startAnimation(
+                destinationBounds.capture(), isNull(), anyInt());
+        final Rect lastPosition = destinationBounds.getValue();
+        // Reset the pinned stack controller since we will do another verify later on
+        reset(mPinnedStackController);
+
+        mPipBoundsHandler.setShelfHeight(true, shelfHeight);
+        mPipBoundsHandler.onPrepareAnimation(null, 1f, null);
+
+        verify(mPinnedStackController).startAnimation(
+                destinationBounds.capture(), isNull(), anyInt());
+        lastPosition.offset(0, -shelfHeight);
+        assertBoundsWithMargin("PiP bounds offset by shelf height",
+                lastPosition, destinationBounds.getValue());
+    }
+
+    @Test
+    public void onImeVisibilityChanged_offsetBounds() throws Exception {
+        final ArgumentCaptor<Rect> destinationBounds = ArgumentCaptor.forClass(Rect.class);
+        final int imeHeight = 100;
+
+        mPipBoundsHandler.onPrepareAnimation(null, 1f, null);
+
+        verify(mPinnedStackController).startAnimation(
+                destinationBounds.capture(), isNull(), anyInt());
+        final Rect lastPosition = destinationBounds.getValue();
+        // Reset the pinned stack controller since we will do another verify later on
+        reset(mPinnedStackController);
+
+        mPipBoundsHandler.onImeVisibilityChanged(true, imeHeight);
+        mPipBoundsHandler.onPrepareAnimation(null, 1f, null);
+
+        verify(mPinnedStackController).startAnimation(
+                destinationBounds.capture(), isNull(), anyInt());
+        lastPosition.offset(0, -imeHeight);
+        assertBoundsWithMargin("PiP bounds offset by IME height",
+                lastPosition, destinationBounds.getValue());
+    }
+
+    @Test
+    public void onPrepareAnimation_startAnimation() throws Exception {
+        final Rect sourceRectHint = new Rect(100, 100, 200, 200);
+        final ArgumentCaptor<Rect> destinationBounds = ArgumentCaptor.forClass(Rect.class);
+
+        mPipBoundsHandler.onPrepareAnimation(sourceRectHint, 1f, null);
+
+        verify(mPinnedStackController).startAnimation(
+                destinationBounds.capture(), eq(sourceRectHint), anyInt());
+        final Rect capturedDestinationBounds = destinationBounds.getValue();
+        assertFalse("Destination bounds is not empty",
+                capturedDestinationBounds.isEmpty());
+        assertBoundsWithMargin("Destination bounds within Display",
+                mDefaultDisplayRect, capturedDestinationBounds);
+    }
+
+    @Test
+    public void onSaveReentryBounds_restoreLastPosition() throws Exception {
+        final ComponentName componentName = new ComponentName(mContext, "component1");
+        final ArgumentCaptor<Rect> destinationBounds = ArgumentCaptor.forClass(Rect.class);
+
+        mPipBoundsHandler.onPrepareAnimation(null, 1f, null);
+
+        verify(mPinnedStackController).startAnimation(
+                destinationBounds.capture(), isNull(), anyInt());
+        final Rect lastPosition = destinationBounds.getValue();
+        lastPosition.offset(0, -100);
+        mPipBoundsHandler.onSaveReentryBounds(componentName, lastPosition);
+        // Reset the pinned stack controller since we will do another verify later on
+        reset(mPinnedStackController);
+
+        mPipBoundsHandler.onPrepareAnimation(null, 1f, null);
+
+        verify(mPinnedStackController).startAnimation(
+                destinationBounds.capture(), isNull(), anyInt());
+        assertBoundsWithMargin("Last position is restored",
+                lastPosition, destinationBounds.getValue());
+    }
+
+    @Test
+    public void onResetReentryBounds_componentMatch_useDefaultBounds() throws Exception {
+        final ComponentName componentName = new ComponentName(mContext, "component1");
+        final ArgumentCaptor<Rect> destinationBounds = ArgumentCaptor.forClass(Rect.class);
+
+        mPipBoundsHandler.onPrepareAnimation(null, 1f, null);
+
+        verify(mPinnedStackController).startAnimation(
+                destinationBounds.capture(), isNull(), anyInt());
+        final Rect defaultBounds = new Rect(destinationBounds.getValue());
+        final Rect newBounds = new Rect(defaultBounds);
+        newBounds.offset(0, -100);
+        mPipBoundsHandler.onSaveReentryBounds(componentName, newBounds);
+        // Reset the pinned stack controller since we will do another verify later on
+        reset(mPinnedStackController);
+
+        mPipBoundsHandler.onResetReentryBounds(componentName);
+        mPipBoundsHandler.onPrepareAnimation(null, 1f, null);
+
+        verify(mPinnedStackController).startAnimation(
+                destinationBounds.capture(), isNull(), anyInt());
+        final Rect actualBounds = destinationBounds.getValue();
+        assertBoundsWithMargin("Use default bounds", defaultBounds, actualBounds);
+    }
+
+    @Test
+    public void onResetReentryBounds_componentMismatch_restoreLastPosition() throws Exception {
+        final ComponentName componentName = new ComponentName(mContext, "component1");
+        final ArgumentCaptor<Rect> destinationBounds = ArgumentCaptor.forClass(Rect.class);
+
+        mPipBoundsHandler.onPrepareAnimation(null, 1f, null);
+
+        verify(mPinnedStackController).startAnimation(
+                destinationBounds.capture(), isNull(), anyInt());
+        final Rect defaultBounds = new Rect(destinationBounds.getValue());
+        final Rect newBounds = new Rect(defaultBounds);
+        newBounds.offset(0, -100);
+        mPipBoundsHandler.onSaveReentryBounds(componentName, newBounds);
+        // Reset the pinned stack controller since we will do another verify later on
+        reset(mPinnedStackController);
+
+        mPipBoundsHandler.onResetReentryBounds(new ComponentName(mContext, "component2"));
+        mPipBoundsHandler.onPrepareAnimation(null, 1f, null);
+
+        verify(mPinnedStackController).startAnimation(
+                destinationBounds.capture(), isNull(), anyInt());
+        final Rect actualBounds = destinationBounds.getValue();
+        assertBoundsWithMargin("Last position is restored", newBounds, actualBounds);
+    }
+
+    private void assertBoundsWithMargin(String msg, Rect expected, Rect actual) {
+        expected.inset(-ROUNDING_ERROR_MARGIN, -ROUNDING_ERROR_MARGIN);
+        assertTrue(msg, expected.contains(actual));
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
index fe8d769..9a7e97b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
@@ -33,6 +33,7 @@
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import static java.util.Objects.requireNonNull;
 
@@ -51,6 +52,7 @@
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.systemui.DumpController;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.FeatureFlags;
 import com.android.systemui.statusbar.RankingBuilder;
 import com.android.systemui.statusbar.notification.collection.NoManSimulator.NotifEvent;
 import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason;
@@ -60,6 +62,7 @@
 import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener;
 import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionLogger;
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
 import com.android.systemui.util.Assert;
 
@@ -83,9 +86,11 @@
 public class NotifCollectionTest extends SysuiTestCase {
 
     @Mock private IStatusBarService mStatusBarService;
+    @Mock private NotifCollectionLogger mLogger;
     @Mock private GroupCoalescer mGroupCoalescer;
     @Spy private RecordingCollectionListener mCollectionListener;
     @Mock private CollectionReadyForBuildListener mBuildListener;
+    @Mock private FeatureFlags mFeatureFlags;
 
     @Spy private RecordingLifetimeExtender mExtender1 = new RecordingLifetimeExtender("Extender1");
     @Spy private RecordingLifetimeExtender mExtender2 = new RecordingLifetimeExtender("Extender2");
@@ -105,7 +110,14 @@
         MockitoAnnotations.initMocks(this);
         Assert.sMainLooper = TestableLooper.get(this).getLooper();
 
-        mCollection = new NotifCollection(mStatusBarService, mock(DumpController.class));
+        when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(true);
+        when(mFeatureFlags.isNewNotifPipelineEnabled()).thenReturn(true);
+
+        mCollection = new NotifCollection(
+                mStatusBarService,
+                mock(DumpController.class),
+                mFeatureFlags,
+                mLogger);
         mCollection.attach(mGroupCoalescer);
         mCollection.addCollectionListener(mCollectionListener);
         mCollection.setBuildListener(mBuildListener);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
index e915be3..18f133f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
@@ -45,12 +45,12 @@
 import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener;
 import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeSortListener;
 import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeTransformGroupsListener;
+import com.android.systemui.statusbar.notification.collection.listbuilder.ShadeListBuilderLogger;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifComparator;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSection;
 import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener;
-import com.android.systemui.statusbar.notification.logging.NotifLog;
 import com.android.systemui.util.Assert;
 import com.android.systemui.util.time.FakeSystemClock;
 
@@ -81,7 +81,7 @@
     private ShadeListBuilder mListBuilder;
     private FakeSystemClock mSystemClock = new FakeSystemClock();
 
-    @Mock private NotifLog mNotifLog;
+    @Mock private ShadeListBuilderLogger mLogger;
     @Mock private NotifCollection mNotifCollection;
     @Spy private OnBeforeTransformGroupsListener mOnBeforeTransformGroupsListener;
     @Spy private OnBeforeSortListener mOnBeforeSortListener;
@@ -103,7 +103,7 @@
         MockitoAnnotations.initMocks(this);
         Assert.sMainLooper = TestableLooper.get(this).getLooper();
 
-        mListBuilder = new ShadeListBuilder(mSystemClock, mNotifLog, mock(DumpController.class));
+        mListBuilder = new ShadeListBuilder(mSystemClock, mLogger, mock(DumpController.class));
         mListBuilder.setOnRenderListListener(mOnRenderListListener);
 
         mListBuilder.attach(mNotifCollection);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerTest.java
index 86c1eb97..ac9a570 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerTest.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.statusbar.notification.collection.coalescer;
 
-import static com.android.internal.util.Preconditions.checkNotNull;
-
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyList;
 import static org.mockito.Mockito.clearInvocations;
@@ -25,6 +23,8 @@
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 
+import static java.util.Objects.requireNonNull;
+
 import android.service.notification.NotificationListenerService.Ranking;
 import android.service.notification.NotificationListenerService.RankingMap;
 import android.service.notification.StatusBarNotification;
@@ -39,7 +39,6 @@
 import com.android.systemui.statusbar.notification.collection.NoManSimulator;
 import com.android.systemui.statusbar.notification.collection.NoManSimulator.NotifEvent;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
-import com.android.systemui.statusbar.notification.logging.NotifLog;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.time.FakeSystemClock;
 
@@ -63,7 +62,7 @@
 
     @Mock private NotificationListener mListenerService;
     @Mock private GroupCoalescer.BatchableNotificationHandler mListener;
-    @Mock private NotifLog mLog;
+    @Mock private GroupCoalescerLogger mLogger;
 
     @Captor private ArgumentCaptor<NotificationHandler> mListenerCaptor;
 
@@ -79,14 +78,14 @@
                 new GroupCoalescer(
                         mExecutor,
                         mClock,
-                        mLog,
+                        mLogger,
                         MIN_LINGER_DURATION,
                         MAX_LINGER_DURATION);
         mCoalescer.setNotificationHandler(mListener);
         mCoalescer.attach(mListenerService);
 
         verify(mListenerService).addNotificationHandler(mListenerCaptor.capture());
-        NotificationHandler serviceListener = checkNotNull(mListenerCaptor.getValue());
+        NotificationHandler serviceListener = requireNonNull(mListenerCaptor.getValue());
         mNoMan.addListener(serviceListener);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinatorTest.java
index 6cc8dd9..eb1af7c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinatorTest.java
@@ -16,20 +16,23 @@
 
 package com.android.systemui.statusbar.notification.collection.coordinator;
 
+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.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.Notification;
 import android.os.Bundle;
-import android.os.Handler;
 import android.os.UserHandle;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
 import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.util.ArraySet;
 
 import androidx.test.filters.SmallTest;
 
@@ -41,36 +44,53 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
+import com.android.systemui.util.Assert;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.List;
+
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
 public class ForegroundCoordinatorTest extends SysuiTestCase {
     private static final String TEST_PKG = "test_pkg";
     private static final int NOTIF_USER_ID = 0;
 
-    @Mock private Handler mMainHandler;
     @Mock private ForegroundServiceController mForegroundServiceController;
     @Mock private AppOpsController mAppOpsController;
     @Mock private NotifPipeline mNotifPipeline;
 
+    @Captor private ArgumentCaptor<AppOpsController.Callback> mAppOpsCaptor;
+
     private NotificationEntry mEntry;
     private Notification mNotification;
     private ForegroundCoordinator mForegroundCoordinator;
     private NotifFilter mForegroundFilter;
+    private AppOpsController.Callback mAppOpsCallback;
     private NotifLifetimeExtender mForegroundNotifLifetimeExtender;
 
+    private FakeSystemClock mClock = new FakeSystemClock();
+    private FakeExecutor mExecutor = new FakeExecutor(mClock);
+
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
-        mForegroundCoordinator = new ForegroundCoordinator(
-                mForegroundServiceController, mAppOpsController, mMainHandler);
+        Assert.sMainLooper = TestableLooper.get(this).getLooper();
+
+        mForegroundCoordinator =
+                new ForegroundCoordinator(
+                        mForegroundServiceController,
+                        mAppOpsController,
+                        mExecutor);
 
         mNotification = new Notification();
         mEntry = new NotificationEntryBuilder()
@@ -86,9 +106,11 @@
         verify(mNotifPipeline, times(1)).addPreGroupFilter(filterCaptor.capture());
         verify(mNotifPipeline, times(1)).addNotificationLifetimeExtender(
                 lifetimeExtenderCaptor.capture());
+        verify(mAppOpsController).addCallback(any(int[].class), mAppOpsCaptor.capture());
 
         mForegroundFilter = filterCaptor.getValue();
         mForegroundNotifLifetimeExtender = lifetimeExtenderCaptor.getValue();
+        mAppOpsCallback = mAppOpsCaptor.getValue();
     }
 
     @Test
@@ -183,4 +205,74 @@
         assertFalse(mForegroundNotifLifetimeExtender
                 .shouldExtendLifetime(mEntry, NotificationListenerService.REASON_CLICK));
     }
+
+    @Test
+    public void testAppOpsAreApplied() {
+        // GIVEN Three current notifications, two with the same key but from different users
+        NotificationEntry entry1 = new NotificationEntryBuilder()
+                .setUser(new UserHandle(NOTIF_USER_ID))
+                .setPkg(TEST_PKG)
+                .setId(1)
+                .build();
+        NotificationEntry entry2 = new NotificationEntryBuilder()
+                .setUser(new UserHandle(NOTIF_USER_ID))
+                .setPkg(TEST_PKG)
+                .setId(2)
+                .build();
+        NotificationEntry entry2Other = new NotificationEntryBuilder()
+                .setUser(new UserHandle(NOTIF_USER_ID + 1))
+                .setPkg(TEST_PKG)
+                .setId(2)
+                .build();
+        when(mNotifPipeline.getActiveNotifs()).thenReturn(List.of(entry1, entry2, entry2Other));
+
+        // GIVEN that entry2 is currently associated with a foreground service
+        when(mForegroundServiceController.getStandardLayoutKey(0, TEST_PKG))
+                .thenReturn(entry2.getKey());
+
+        // WHEN a new app ops code comes in
+        mAppOpsCallback.onActiveStateChanged(47, NOTIF_USER_ID, TEST_PKG, true);
+        mExecutor.runAllReady();
+
+        // THEN entry2's app ops are updated, but no one else's are
+        assertEquals(
+                new ArraySet<>(),
+                entry1.mActiveAppOps);
+        assertEquals(
+                new ArraySet<>(List.of(47)),
+                entry2.mActiveAppOps);
+        assertEquals(
+                new ArraySet<>(),
+                entry2Other.mActiveAppOps);
+    }
+
+    @Test
+    public void testAppOpsAreRemoved() {
+        // GIVEN One notification which is associated with app ops
+        NotificationEntry entry = new NotificationEntryBuilder()
+                .setUser(new UserHandle(NOTIF_USER_ID))
+                .setPkg(TEST_PKG)
+                .setId(2)
+                .build();
+        when(mNotifPipeline.getActiveNotifs()).thenReturn(List.of(entry));
+        when(mForegroundServiceController.getStandardLayoutKey(0, TEST_PKG))
+                .thenReturn(entry.getKey());
+
+        // GIVEN that the notification's app ops are already [47, 33]
+        mAppOpsCallback.onActiveStateChanged(47, NOTIF_USER_ID, TEST_PKG, true);
+        mAppOpsCallback.onActiveStateChanged(33, NOTIF_USER_ID, TEST_PKG, true);
+        mExecutor.runAllReady();
+        assertEquals(
+                new ArraySet<>(List.of(47, 33)),
+                entry.mActiveAppOps);
+
+        // WHEN one of the app ops is removed
+        mAppOpsCallback.onActiveStateChanged(47, NOTIF_USER_ID, TEST_PKG, false);
+        mExecutor.runAllReady();
+
+        // THEN the entry's active app ops are updated as well
+        assertEquals(
+                new ArraySet<>(List.of(33)),
+                entry.mActiveAppOps);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
index 5fc40cc..20a089f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
@@ -58,7 +58,6 @@
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
-import android.util.Slog;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.Button;
@@ -601,6 +600,34 @@
     }
 
     @Test
+    public void testBubble_noChannelChange() throws Exception {
+        mNotificationInfo.bindNotification(
+                mShortcutManager,
+                mLauncherApps,
+                mMockPackageManager,
+                mMockINotificationManager,
+                mVisualStabilityManager,
+                TEST_PACKAGE_NAME,
+                mNotificationChannel,
+                mBubbleEntry,
+                null,
+                null,
+                null,
+                true);
+
+        assertFalse(mBubbleEntry.isBubble());
+        assertTrue(mNotificationChannel.canBubble());
+
+        // Promote it
+        mNotificationInfo.findViewById(R.id.bubble).performClick();
+        mTestableLooper.processAllMessages();
+
+        verify(mBubbleController, times(1)).onUserCreatedBubbleFromNotification(mBubbleEntry);
+        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+                anyString(), anyInt(), any());
+    }
+
+    @Test
     public void testFavorite_favorite() throws Exception {
         mNotificationInfo.bindNotification(
                 mShortcutManager,
diff --git a/packages/Tethering/apex/AndroidManifest.xml b/packages/Tethering/apex/AndroidManifest.xml
index 5c35c51..4aae3cc 100644
--- a/packages/Tethering/apex/AndroidManifest.xml
+++ b/packages/Tethering/apex/AndroidManifest.xml
@@ -20,8 +20,10 @@
   <application android:hasCode="false" />
   <!-- b/145383354: Current minSdk is locked to Q for development cycle, lock it to next version
                     before ship. -->
-  <uses-sdk
+  <!-- TODO: Uncomment this when the R API level is fixed. b/148281152 -->
+  <!--uses-sdk
       android:minSdkVersion="29"
       android:targetSdkVersion="29"
   />
+  -->
 </manifest>
diff --git a/packages/Tethering/common/TetheringLib/Android.bp b/packages/Tethering/common/TetheringLib/Android.bp
index a8d1239..e0adb34d 100644
--- a/packages/Tethering/common/TetheringLib/Android.bp
+++ b/packages/Tethering/common/TetheringLib/Android.bp
@@ -19,7 +19,15 @@
     local_include_dir: "src",
     include_dirs: ["frameworks/base/core/java"], // For framework parcelables.
     srcs: [
-        "src/android/net/*.aidl",
+        // @JavaOnlyStableParcelable aidl declarations must not be listed here, as this would cause
+        // compilation to fail (b/148001843).
+        "src/android/net/IIntResultListener.aidl",
+        "src/android/net/ITetheringConnector.aidl",
+        "src/android/net/ITetheringEventCallback.aidl",
+        "src/android/net/TetheringCallbackStartedParcel.aidl",
+        "src/android/net/TetheringConfigurationParcel.aidl",
+        "src/android/net/TetheringRequestParcel.aidl",
+        "src/android/net/TetherStatesParcel.aidl",
     ],
     backend: {
         ndk: {
@@ -35,6 +43,7 @@
     name: "framework-tethering",
     sdk_version: "system_current",
     srcs: [
+        "src/android/net/TetheredClient.java",
         "src/android/net/TetheringManager.java",
         "src/android/net/TetheringConstants.java",
         ":framework-tethering-annotations",
@@ -63,6 +72,8 @@
 filegroup {
     name: "framework-tethering-srcs",
     srcs: [
+        "src/android/net/TetheredClient.aidl",
+        "src/android/net/TetheredClient.java",
         "src/android/net/TetheringManager.java",
         "src/android/net/TetheringConstants.java",
         "src/android/net/IIntResultListener.aidl",
@@ -70,6 +81,7 @@
         "src/android/net/ITetheringConnector.aidl",
         "src/android/net/TetheringCallbackStartedParcel.aidl",
         "src/android/net/TetheringConfigurationParcel.aidl",
+        "src/android/net/TetheringRequestParcel.aidl",
         "src/android/net/TetherStatesParcel.aidl",
     ],
     path: "src"
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl b/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl
index d30c399..5febe73 100644
--- a/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl
+++ b/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl
@@ -17,6 +17,7 @@
 
 import android.net.IIntResultListener;
 import android.net.ITetheringEventCallback;
+import android.net.TetheringRequestParcel;
 import android.os.ResultReceiver;
 
 /** @hide */
@@ -27,8 +28,8 @@
 
     void setUsbTethering(boolean enable, String callerPkg, IIntResultListener receiver);
 
-    void startTethering(int type, in ResultReceiver receiver, boolean showProvisioningUi,
-            String callerPkg);
+    void startTethering(in TetheringRequestParcel request, String callerPkg,
+            IIntResultListener receiver);
 
     void stopTethering(int type, String callerPkg, IIntResultListener receiver);
 
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl b/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.aidl
similarity index 80%
copy from telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl
copy to packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.aidl
index e9cbd9c..0b279b8 100644
--- a/telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl
+++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.aidl
@@ -1,6 +1,5 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
+/**
+ * Copyright (C) 2020 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package android.net;
 
-package android.telephony.ims;
-
-parcelable RcsMessageQueryParams;
+@JavaOnlyStableParcelable parcelable TetheredClient;
\ No newline at end of file
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.java
new file mode 100644
index 0000000..6514688
--- /dev/null
+++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Information on a tethered downstream client.
+ * @hide
+ */
+@SystemApi
+@TestApi
+public final class TetheredClient implements Parcelable {
+    @NonNull
+    private final MacAddress mMacAddress;
+    @NonNull
+    private final List<AddressInfo> mAddresses;
+    // TODO: use an @IntDef here
+    private final int mTetheringType;
+
+    public TetheredClient(@NonNull MacAddress macAddress,
+            @NonNull Collection<AddressInfo> addresses, int tetheringType) {
+        mMacAddress = macAddress;
+        mAddresses = new ArrayList<>(addresses);
+        mTetheringType = tetheringType;
+    }
+
+    private TetheredClient(@NonNull Parcel in) {
+        this(in.readParcelable(null), in.createTypedArrayList(AddressInfo.CREATOR), in.readInt());
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeParcelable(mMacAddress, flags);
+        dest.writeTypedList(mAddresses);
+        dest.writeInt(mTetheringType);
+    }
+
+    @NonNull
+    public MacAddress getMacAddress() {
+        return mMacAddress;
+    }
+
+    @NonNull
+    public List<AddressInfo> getAddresses() {
+        return new ArrayList<>(mAddresses);
+    }
+
+    public int getTetheringType() {
+        return mTetheringType;
+    }
+
+    /**
+     * Return a new {@link TetheredClient} that has all the attributes of this instance, plus the
+     * {@link AddressInfo} of the provided {@link TetheredClient}.
+     *
+     * <p>Duplicate addresses are removed.
+     * @hide
+     */
+    public TetheredClient addAddresses(@NonNull TetheredClient other) {
+        final HashSet<AddressInfo> newAddresses = new HashSet<>(
+                mAddresses.size() + other.mAddresses.size());
+        newAddresses.addAll(mAddresses);
+        newAddresses.addAll(other.mAddresses);
+        return new TetheredClient(mMacAddress, newAddresses, mTetheringType);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mMacAddress, mAddresses, mTetheringType);
+    }
+
+    @Override
+    public boolean equals(@Nullable Object obj) {
+        if (!(obj instanceof TetheredClient)) return false;
+        final TetheredClient other = (TetheredClient) obj;
+        return mMacAddress.equals(other.mMacAddress)
+                && mAddresses.equals(other.mAddresses)
+                && mTetheringType == other.mTetheringType;
+    }
+
+    /**
+     * Information on an lease assigned to a tethered client.
+     */
+    public static final class AddressInfo implements Parcelable {
+        @NonNull
+        private final LinkAddress mAddress;
+        @Nullable
+        private final String mHostname;
+        // TODO: use LinkAddress expiration time once it is supported
+        private final long mExpirationTime;
+
+        /** @hide */
+        public AddressInfo(@NonNull LinkAddress address, @Nullable String hostname) {
+            this(address, hostname, 0);
+        }
+
+        /** @hide */
+        public AddressInfo(@NonNull LinkAddress address, String hostname, long expirationTime) {
+            this.mAddress = address;
+            this.mHostname = hostname;
+            this.mExpirationTime = expirationTime;
+        }
+
+        private AddressInfo(Parcel in) {
+            this(in.readParcelable(null),  in.readString(), in.readLong());
+        }
+
+        @Override
+        public void writeToParcel(@NonNull Parcel dest, int flags) {
+            dest.writeParcelable(mAddress, flags);
+            dest.writeString(mHostname);
+            dest.writeLong(mExpirationTime);
+        }
+
+        @NonNull
+        public LinkAddress getAddress() {
+            return mAddress;
+        }
+
+        @Nullable
+        public String getHostname() {
+            return mHostname;
+        }
+
+        /** @hide TODO: use expiration time in LinkAddress */
+        public long getExpirationTime() {
+            return mExpirationTime;
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mAddress, mHostname, mExpirationTime);
+        }
+
+        @Override
+        public boolean equals(@Nullable Object obj) {
+            if (!(obj instanceof AddressInfo)) return false;
+            final AddressInfo other = (AddressInfo) obj;
+            // Use .equals() for addresses as all changes, including address expiry changes,
+            // should be included.
+            return other.mAddress.equals(mAddress)
+                    && Objects.equals(mHostname, other.mHostname)
+                    && mExpirationTime == other.mExpirationTime;
+        }
+
+        @NonNull
+        public static final Creator<AddressInfo> CREATOR = new Creator<AddressInfo>() {
+            @NonNull
+            @Override
+            public AddressInfo createFromParcel(@NonNull Parcel in) {
+                return new AddressInfo(in);
+            }
+
+            @NonNull
+            @Override
+            public AddressInfo[] newArray(int size) {
+                return new AddressInfo[size];
+            }
+        };
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @NonNull
+    public static final Creator<TetheredClient> CREATOR = new Creator<TetheredClient>() {
+        @NonNull
+        @Override
+        public TetheredClient createFromParcel(@NonNull Parcel in) {
+            return new TetheredClient(in);
+        }
+
+        @NonNull
+        @Override
+        public TetheredClient[] newArray(int size) {
+            return new TetheredClient[size];
+        }
+    };
+}
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
index e1b9c16..37ce1d57 100644
--- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
+++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
@@ -15,6 +15,7 @@
  */
 package android.net;
 
+import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -30,6 +31,7 @@
 import android.util.Log;
 
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -128,6 +130,18 @@
      */
     public static final int TETHERING_WIFI_P2P = 3;
 
+    /**
+     * Ncm local tethering type.
+     * @see #startTethering(TetheringRequest, Executor, StartTetheringCallback)
+     */
+    public static final int TETHERING_NCM = 4;
+
+    /**
+     * Ethernet tethering type.
+     * @see #startTethering(TetheringRequest, Executor, StartTetheringCallback)
+     */
+    public static final int TETHERING_ETHERNET = 5;
+
     public static final int TETHER_ERROR_NO_ERROR           = 0;
     public static final int TETHER_ERROR_UNKNOWN_IFACE      = 1;
     public static final int TETHER_ERROR_SERVICE_UNAVAIL    = 2;
@@ -326,27 +340,171 @@
     }
 
     /**
+     *  Use with {@link #startTethering} to specify additional parameters when starting tethering.
+     */
+    public static class TetheringRequest {
+        /** A configuration set for TetheringRequest. */
+        private final TetheringRequestParcel mRequestParcel;
+
+        private TetheringRequest(final TetheringRequestParcel request) {
+            mRequestParcel = request;
+        }
+
+        /** Builder used to create TetheringRequest. */
+        public static class Builder {
+            private final TetheringRequestParcel mBuilderParcel;
+
+            /** Default constructor of Builder. */
+            public Builder(final int type) {
+                mBuilderParcel = new TetheringRequestParcel();
+                mBuilderParcel.tetheringType = type;
+                mBuilderParcel.localIPv4Address = null;
+                mBuilderParcel.exemptFromEntitlementCheck = false;
+                mBuilderParcel.showProvisioningUi = true;
+            }
+
+            /**
+             * Configure tethering with static IPv4 assignment (with DHCP disabled).
+             *
+             * @param localIPv4Address The preferred local IPv4 address to use.
+             */
+            @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
+            @NonNull
+            public Builder useStaticIpv4Addresses(@NonNull final LinkAddress localIPv4Address) {
+                mBuilderParcel.localIPv4Address = localIPv4Address;
+                return this;
+            }
+
+            /** Start tethering without entitlement checks. */
+            @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
+            @NonNull
+            public Builder setExemptFromEntitlementCheck(boolean exempt) {
+                mBuilderParcel.exemptFromEntitlementCheck = exempt;
+                return this;
+            }
+
+            /** Start tethering without showing the provisioning UI. */
+            @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
+            @NonNull
+            public Builder setSilentProvisioning(boolean silent) {
+                mBuilderParcel.showProvisioningUi = silent;
+                return this;
+            }
+
+            /** Build {@link TetheringRequest] with the currently set configuration. */
+            @NonNull
+            public TetheringRequest build() {
+                return new TetheringRequest(mBuilderParcel);
+            }
+        }
+
+        /**
+         * Get a TetheringRequestParcel from the configuration
+         * @hide
+         */
+        public TetheringRequestParcel getParcel() {
+            return mRequestParcel;
+        }
+
+        /** String of TetheringRequest detail. */
+        public String toString() {
+            return "TetheringRequest [ type= " + mRequestParcel.tetheringType
+                    + ", localIPv4Address= " + mRequestParcel.localIPv4Address
+                    + ", exemptFromEntitlementCheck= "
+                    + mRequestParcel.exemptFromEntitlementCheck + ", showProvisioningUi= "
+                    + mRequestParcel.showProvisioningUi + " ]";
+        }
+    }
+
+    /**
+     * Callback for use with {@link #startTethering} to find out whether tethering succeeded.
+     */
+    public abstract static class StartTetheringCallback {
+        /**
+         * Called when tethering has been successfully started.
+         */
+        public void onTetheringStarted() {}
+
+        /**
+         * Called when starting tethering failed.
+         *
+         * @param resultCode One of the {@code TETHER_ERROR_*} constants.
+         */
+        public void onTetheringFailed(final int resultCode) {}
+    }
+
+    /**
      * Starts tethering and runs tether provisioning for the given type if needed. If provisioning
      * fails, stopTethering will be called automatically.
-     * @hide
+     *
+     * <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will
+     * fail if a tethering entitlement check is required.
+     *
+     * @param request a {@link TetheringRequest} which can specify the preferred configuration.
+     * @param executor {@link Executor} to specify the thread upon which the callback of
+     *         TetheringRequest will be invoked.
+     * @param callback A callback that will be called to indicate the success status of the
+     *                 tethering start request.
      */
-    // TODO: improve the usage of ResultReceiver, b/145096122
-    public void startTethering(final int type, @NonNull final ResultReceiver receiver,
-            final boolean showProvisioningUi) {
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.TETHER_PRIVILEGED,
+            android.Manifest.permission.WRITE_SETTINGS
+    })
+    public void startTethering(@NonNull final TetheringRequest request,
+            @NonNull final Executor executor, @NonNull final StartTetheringCallback callback) {
         final String callerPkg = mContext.getOpPackageName();
         Log.i(TAG, "startTethering caller:" + callerPkg);
 
+        final IIntResultListener listener = new IIntResultListener.Stub() {
+            @Override
+            public void onResult(final int resultCode) {
+                executor.execute(() -> {
+                    if (resultCode == TETHER_ERROR_NO_ERROR) {
+                        callback.onTetheringStarted();
+                    } else {
+                        callback.onTetheringFailed(resultCode);
+                    }
+                });
+            }
+        };
         try {
-            mConnector.startTethering(type, receiver, showProvisioningUi, callerPkg);
+            mConnector.startTethering(request.getParcel(), callerPkg, listener);
         } catch (RemoteException e) {
             throw new IllegalStateException(e);
         }
     }
 
     /**
+     * Starts tethering and runs tether provisioning for the given type if needed. If provisioning
+     * fails, stopTethering will be called automatically.
+     *
+     * <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will
+     * fail if a tethering entitlement check is required.
+     *
+     * @param type The tethering type, on of the {@code TetheringManager#TETHERING_*} constants.
+     * @param executor {@link Executor} to specify the thread upon which the callback of
+     *         TetheringRequest will be invoked.
+     */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.TETHER_PRIVILEGED,
+            android.Manifest.permission.WRITE_SETTINGS
+    })
+    public void startTethering(int type, @NonNull final Executor executor,
+            @NonNull final StartTetheringCallback callback) {
+        startTethering(new TetheringRequest.Builder(type).build(), executor, callback);
+    }
+
+    /**
      * Stops tethering for the given type. Also cancels any provisioning rechecks for that type if
      * applicable.
+     *
+     * <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will
+     * fail if a tethering entitlement check is required.
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.TETHER_PRIVILEGED,
+            android.Manifest.permission.WRITE_SETTINGS
+    })
     public void stopTethering(final int type) {
         final String callerPkg = mContext.getOpPackageName();
         Log.i(TAG, "stopTethering caller:" + callerPkg);
@@ -386,6 +544,9 @@
      * {@link #TETHER_ERROR_ENTITLEMENT_UNKNOWN} will be returned. If {@code showEntitlementUi} is
      * true, entitlement will be run.
      *
+     * <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will
+     * fail if a tethering entitlement check is required.
+     *
      * @param type the downstream type of tethering. Must be one of {@code #TETHERING_*} constants.
      * @param showEntitlementUi a boolean indicating whether to run UI-based entitlement check.
      * @param executor the executor on which callback will be invoked.
@@ -393,7 +554,10 @@
      *         notify the caller of the result of entitlement check. The listener may be called zero
      *         or one time.
      */
-    @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.TETHER_PRIVILEGED,
+            android.Manifest.permission.WRITE_SETTINGS
+    })
     public void requestLatestTetheringEntitlementResult(int type, boolean showEntitlementUi,
             @NonNull Executor executor,
             @NonNull final OnTetheringEntitlementResultListener listener) {
@@ -502,6 +666,19 @@
          * @param error One of {@code TetheringManager#TETHER_ERROR_*}.
          */
         public void onError(@NonNull String ifName, int error) {}
+
+        /**
+         * Called when the list of tethered clients changes.
+         *
+         * <p>This callback provides best-effort information on connected clients based on state
+         * known to the system, however the list cannot be completely accurate (and should not be
+         * used for security purposes). For example, clients behind a bridge and using static IP
+         * assignments are not visible to the tethering device; or even when using DHCP, such
+         * clients may still be reported by this callback after disconnection as the system cannot
+         * determine if they are still connected.
+         * @param clients The new set of tethered clients; the collection is not ordered.
+         */
+        public void onClientsChanged(@NonNull Collection<TetheredClient> clients) {}
     }
 
     /**
@@ -562,6 +739,7 @@
      * @param executor the executor on which callback will be invoked.
      * @param callback the callback to be called when tethering has change events.
      */
+    @RequiresPermission(Manifest.permission.ACCESS_NETWORK_STATE)
     public void registerTetheringEventCallback(@NonNull Executor executor,
             @NonNull TetheringEventCallback callback) {
         final String callerPkg = mContext.getOpPackageName();
@@ -669,6 +847,10 @@
      *
      * @param callback previously registered callback.
      */
+    @RequiresPermission(anyOf = {
+            Manifest.permission.TETHER_PRIVILEGED,
+            Manifest.permission.ACCESS_NETWORK_STATE
+    })
     public void unregisterTetheringEventCallback(@NonNull final TetheringEventCallback callback) {
         final String callerPkg = mContext.getOpPackageName();
         Log.i(TAG, "unregisterTetheringEventCallback caller:" + callerPkg);
@@ -833,7 +1015,14 @@
 
     /**
      * Stop all active tethering.
+     *
+     * <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will
+     * fail if a tethering entitlement check is required.
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.TETHER_PRIVILEGED,
+            android.Manifest.permission.WRITE_SETTINGS
+    })
     public void stopAllTethering() {
         final String callerPkg = mContext.getOpPackageName();
         Log.i(TAG, "stopAllTethering caller:" + callerPkg);
diff --git a/core/java/android/service/controls/actions/CommandAction.aidl b/packages/Tethering/common/TetheringLib/src/android/net/TetheringRequestParcel.aidl
similarity index 61%
copy from core/java/android/service/controls/actions/CommandAction.aidl
copy to packages/Tethering/common/TetheringLib/src/android/net/TetheringRequestParcel.aidl
index 7c1ee41..bf19d85 100644
--- a/core/java/android/service/controls/actions/CommandAction.aidl
+++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheringRequestParcel.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,6 +13,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.service.controls.actions;
 
-parcelable CommandAction;
\ No newline at end of file
+package android.net;
+
+import android.net.LinkAddress;
+
+/**
+ * Configuration details for requesting tethering.
+ * @hide
+ */
+parcelable TetheringRequestParcel {
+    int tetheringType;
+    LinkAddress localIPv4Address;
+    boolean exemptFromEntitlementCheck;
+    boolean showProvisioningUi;
+}
diff --git a/packages/Tethering/res/values/config.xml b/packages/Tethering/res/values/config.xml
index 19e8d69..c489cbc 100644
--- a/packages/Tethering/res/values/config.xml
+++ b/packages/Tethering/res/values/config.xml
@@ -29,6 +29,12 @@
     </string-array>
 
     <!-- List of regexpressions describing the interface (if any) that represent tetherable
+         NCM interfaces.  If the device doesn't want to support tethering over NCM this should
+         be empty. -->
+    <string-array translatable="false" name="config_tether_ncm_regexs">
+    </string-array>
+
+    <!-- List of regexpressions describing the interface (if any) that represent tetherable
          Wifi interfaces.  If the device doesn't want to support tethering over Wifi this
          should be empty.  An example would be "softap.*" -->
     <string-array translatable="false" name="config_tether_wifi_regexs">
diff --git a/packages/Tethering/res/values/overlayable.xml b/packages/Tethering/res/values/overlayable.xml
index e089d9d..fe025c7 100644
--- a/packages/Tethering/res/values/overlayable.xml
+++ b/packages/Tethering/res/values/overlayable.xml
@@ -17,6 +17,7 @@
     <overlayable name="TetheringConfig">
         <policy type="product|system|vendor">
             <item type="array" name="config_tether_usb_regexs"/>
+            <item type="array" name="config_tether_ncm_regexs" />
             <item type="array" name="config_tether_wifi_regexs"/>
             <item type="array" name="config_tether_wifi_p2p_regexs"/>
             <item type="array" name="config_tether_bluetooth_regexs"/>
diff --git a/packages/Tethering/src/android/net/dhcp/DhcpServerCallbacks.java b/packages/Tethering/src/android/net/dhcp/DhcpServerCallbacks.java
index 7c413779..9fda125 100644
--- a/packages/Tethering/src/android/net/dhcp/DhcpServerCallbacks.java
+++ b/packages/Tethering/src/android/net/dhcp/DhcpServerCallbacks.java
@@ -28,4 +28,9 @@
     public int getInterfaceVersion() {
         return IDhcpServerCallbacks.VERSION;
     }
+
+    @Override
+    public String getInterfaceHash() {
+        return IDhcpServerCallbacks.HASH;
+    }
 }
diff --git a/packages/Tethering/src/android/net/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java
index 0491ad7..f39e7af 100644
--- a/packages/Tethering/src/android/net/ip/IpServer.java
+++ b/packages/Tethering/src/android/net/ip/IpServer.java
@@ -93,6 +93,8 @@
     private static final int WIFI_HOST_IFACE_PREFIX_LENGTH = 24;
     private static final String WIFI_P2P_IFACE_ADDR = "192.168.49.1";
     private static final int WIFI_P2P_IFACE_PREFIX_LENGTH = 24;
+    private static final String ETHERNET_IFACE_ADDR = "192.168.50.1";
+    private static final int ETHERNET_IFACE_PREFIX_LENGTH = 24;
 
     // TODO: have PanService use some visible version of this constant
     private static final String BLUETOOTH_IFACE_ADDR = "192.168.44.1";
@@ -299,6 +301,11 @@
         public int getInterfaceVersion() {
             return this.VERSION;
         }
+
+        @Override
+        public String getInterfaceHash() {
+            return this.HASH;
+        }
     }
 
     private class DhcpServerCallbacksImpl extends DhcpServerCallbacks {
@@ -416,7 +423,8 @@
         final Inet4Address srvAddr;
         int prefixLen = 0;
         try {
-            if (mInterfaceType == TetheringManager.TETHERING_USB) {
+            if (mInterfaceType == TetheringManager.TETHERING_USB
+                    || mInterfaceType == TetheringManager.TETHERING_NCM) {
                 srvAddr = (Inet4Address) parseNumericAddress(USB_NEAR_IFACE_ADDR);
                 prefixLen = USB_PREFIX_LENGTH;
             } else if (mInterfaceType == TetheringManager.TETHERING_WIFI) {
@@ -425,6 +433,10 @@
             } else if (mInterfaceType == TetheringManager.TETHERING_WIFI_P2P) {
                 srvAddr = (Inet4Address) parseNumericAddress(WIFI_P2P_IFACE_ADDR);
                 prefixLen = WIFI_P2P_IFACE_PREFIX_LENGTH;
+            } else if (mInterfaceType == TetheringManager.TETHERING_ETHERNET) {
+                // TODO: randomize address for tethering too, similarly to wifi
+                srvAddr = (Inet4Address) parseNumericAddress(ETHERNET_IFACE_ADDR);
+                prefixLen = ETHERNET_IFACE_PREFIX_LENGTH;
             } else {
                 // BT configures the interface elsewhere: only start DHCP.
                 // TODO: make all tethering types behave the same way, and delete the bluetooth
diff --git a/packages/Tethering/src/android/net/util/BaseNetdUnsolicitedEventListener.java b/packages/Tethering/src/android/net/util/BaseNetdUnsolicitedEventListener.java
index 3218c0b..b1ffdb0 100644
--- a/packages/Tethering/src/android/net/util/BaseNetdUnsolicitedEventListener.java
+++ b/packages/Tethering/src/android/net/util/BaseNetdUnsolicitedEventListener.java
@@ -67,4 +67,9 @@
     public int getInterfaceVersion() {
         return INetdUnsolicitedEventListener.VERSION;
     }
+
+    @Override
+    public String getInterfaceHash() {
+        return INetdUnsolicitedEventListener.HASH;
+    }
 }
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
index 5370145..07abe1a 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
@@ -19,6 +19,7 @@
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.hardware.usb.UsbManager.USB_CONFIGURED;
 import static android.hardware.usb.UsbManager.USB_CONNECTED;
+import static android.hardware.usb.UsbManager.USB_FUNCTION_NCM;
 import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
 import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
@@ -29,7 +30,9 @@
 import static android.net.TetheringManager.EXTRA_AVAILABLE_TETHER;
 import static android.net.TetheringManager.EXTRA_ERRORED_TETHER;
 import static android.net.TetheringManager.TETHERING_BLUETOOTH;
+import static android.net.TetheringManager.TETHERING_ETHERNET;
 import static android.net.TetheringManager.TETHERING_INVALID;
+import static android.net.TetheringManager.TETHERING_NCM;
 import static android.net.TetheringManager.TETHERING_USB;
 import static android.net.TetheringManager.TETHERING_WIFI;
 import static android.net.TetheringManager.TETHERING_WIFI_P2P;
@@ -66,6 +69,8 @@
 import android.content.res.Resources;
 import android.hardware.usb.UsbManager;
 import android.net.ConnectivityManager;
+import android.net.EthernetManager;
+import android.net.IIntResultListener;
 import android.net.INetd;
 import android.net.ITetheringEventCallback;
 import android.net.IpPrefix;
@@ -76,6 +81,7 @@
 import android.net.TetherStatesParcel;
 import android.net.TetheringCallbackStartedParcel;
 import android.net.TetheringConfigurationParcel;
+import android.net.TetheringRequestParcel;
 import android.net.ip.IpServer;
 import android.net.shared.NetdUtils;
 import android.net.util.BaseNetdUnsolicitedEventListener;
@@ -108,6 +114,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.MessageUtils;
@@ -210,6 +217,13 @@
     private boolean mDataSaverEnabled = false;
     private String mWifiP2pTetherInterface = null;
 
+    @GuardedBy("mPublicSync")
+    private EthernetManager.TetheredInterfaceRequest mEthernetIfaceRequest;
+    @GuardedBy("mPublicSync")
+    private String mConfiguredEthernetIface;
+    @GuardedBy("mPublicSync")
+    private EthernetCallback mEthernetCallback;
+
     public Tethering(TetheringDependencies deps) {
         mLog.mark("Tethering.constructed");
         mDeps = deps;
@@ -406,6 +420,8 @@
             return TETHERING_USB;
         } else if (cfg.isBluetooth(iface)) {
             return TETHERING_BLUETOOTH;
+        } else if (cfg.isNcm(iface)) {
+            return TETHERING_NCM;
         }
         return TETHERING_INVALID;
     }
@@ -424,9 +440,10 @@
         }
     }
 
-    void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi) {
-        mEntitlementMgr.startProvisioningIfNeeded(type, showProvisioningUi);
-        enableTetheringInternal(type, true /* enabled */, receiver);
+    void startTethering(final TetheringRequestParcel request, final IIntResultListener listener) {
+        mEntitlementMgr.startProvisioningIfNeeded(request.tetheringType,
+                request.showProvisioningUi);
+        enableTetheringInternal(request.tetheringType, true /* enabled */, listener);
     }
 
     void stopTethering(int type) {
@@ -438,29 +455,40 @@
      * Enables or disables tethering for the given type. If provisioning is required, it will
      * schedule provisioning rechecks for the specified interface.
      */
-    private void enableTetheringInternal(int type, boolean enable, ResultReceiver receiver) {
+    private void enableTetheringInternal(int type, boolean enable,
+            final IIntResultListener listener) {
         int result;
         switch (type) {
             case TETHERING_WIFI:
                 result = setWifiTethering(enable);
-                sendTetherResult(receiver, result);
+                sendTetherResult(listener, result);
                 break;
             case TETHERING_USB:
                 result = setUsbTethering(enable);
-                sendTetherResult(receiver, result);
+                sendTetherResult(listener, result);
                 break;
             case TETHERING_BLUETOOTH:
-                setBluetoothTethering(enable, receiver);
+                setBluetoothTethering(enable, listener);
+                break;
+            case TETHERING_NCM:
+                result = setNcmTethering(enable);
+                sendTetherResult(listener, result);
+                break;
+            case TETHERING_ETHERNET:
+                result = setEthernetTethering(enable);
+                sendTetherResult(listener, result);
                 break;
             default:
                 Log.w(TAG, "Invalid tether type.");
-                sendTetherResult(receiver, TETHER_ERROR_UNKNOWN_IFACE);
+                sendTetherResult(listener, TETHER_ERROR_UNKNOWN_IFACE);
         }
     }
 
-    private void sendTetherResult(ResultReceiver receiver, int result) {
-        if (receiver != null) {
-            receiver.send(result, null);
+    private void sendTetherResult(final IIntResultListener listener, int result) {
+        if (listener != null) {
+            try {
+                listener.onResult(result);
+            } catch (RemoteException e) { }
         }
     }
 
@@ -486,12 +514,12 @@
         return TETHER_ERROR_MASTER_ERROR;
     }
 
-    private void setBluetoothTethering(final boolean enable, final ResultReceiver receiver) {
+    private void setBluetoothTethering(final boolean enable, final IIntResultListener listener) {
         final BluetoothAdapter adapter = mDeps.getBluetoothAdapter();
         if (adapter == null || !adapter.isEnabled()) {
             Log.w(TAG, "Tried to enable bluetooth tethering with null or disabled adapter. null: "
                     + (adapter == null));
-            sendTetherResult(receiver, TETHER_ERROR_SERVICE_UNAVAIL);
+            sendTetherResult(listener, TETHER_ERROR_SERVICE_UNAVAIL);
             return;
         }
 
@@ -520,12 +548,63 @@
                 final int result = (((BluetoothPan) proxy).isTetheringOn() == enable)
                         ? TETHER_ERROR_NO_ERROR
                         : TETHER_ERROR_MASTER_ERROR;
-                sendTetherResult(receiver, result);
+                sendTetherResult(listener, result);
                 adapter.closeProfileProxy(BluetoothProfile.PAN, proxy);
             }
         }, BluetoothProfile.PAN);
     }
 
+    private int setEthernetTethering(final boolean enable) {
+        final EthernetManager em = (EthernetManager) mContext.getSystemService(
+                Context.ETHERNET_SERVICE);
+        synchronized (mPublicSync) {
+            if (enable) {
+                mEthernetCallback = new EthernetCallback();
+                mEthernetIfaceRequest = em.requestTetheredInterface(mEthernetCallback);
+            } else {
+                if (mConfiguredEthernetIface != null) {
+                    stopEthernetTetheringLocked();
+                    mEthernetIfaceRequest.release();
+                }
+                mEthernetCallback = null;
+            }
+        }
+        return TETHER_ERROR_NO_ERROR;
+    }
+
+    private void stopEthernetTetheringLocked() {
+        if (mConfiguredEthernetIface == null) return;
+        changeInterfaceState(mConfiguredEthernetIface, IpServer.STATE_AVAILABLE);
+        stopTrackingInterfaceLocked(mConfiguredEthernetIface);
+        mConfiguredEthernetIface = null;
+    }
+
+    private class EthernetCallback implements EthernetManager.TetheredInterfaceCallback {
+        @Override
+        public void onAvailable(String iface) {
+            synchronized (mPublicSync) {
+                if (this != mEthernetCallback) {
+                    // Ethernet callback arrived after Ethernet tethering stopped. Ignore.
+                    return;
+                }
+                maybeTrackNewInterfaceLocked(iface, TETHERING_ETHERNET);
+                changeInterfaceState(iface, IpServer.STATE_TETHERED);
+                mConfiguredEthernetIface = iface;
+            }
+        }
+
+        @Override
+        public void onUnavailable() {
+            synchronized (mPublicSync) {
+                if (this != mEthernetCallback) {
+                    // onAvailable called after stopping Ethernet tethering.
+                    return;
+                }
+                stopEthernetTetheringLocked();
+            }
+        }
+    }
+
     int tether(String iface) {
         return tether(iface, IpServer.STATE_TETHERED);
     }
@@ -576,6 +655,7 @@
         stopTethering(TETHERING_WIFI_P2P);
         stopTethering(TETHERING_USB);
         stopTethering(TETHERING_BLUETOOTH);
+        stopTethering(TETHERING_ETHERNET);
     }
 
     int getLastTetherError(String iface) {
@@ -799,6 +879,7 @@
             final boolean usbConnected = intent.getBooleanExtra(USB_CONNECTED, false);
             final boolean usbConfigured = intent.getBooleanExtra(USB_CONFIGURED, false);
             final boolean rndisEnabled = intent.getBooleanExtra(USB_FUNCTION_RNDIS, false);
+            final boolean ncmEnabled = intent.getBooleanExtra(USB_FUNCTION_NCM, false);
 
             mLog.log(String.format("USB bcast connected:%s configured:%s rndis:%s",
                     usbConnected, usbConfigured, rndisEnabled));
@@ -826,6 +907,8 @@
                 } else if (usbConfigured && rndisEnabled) {
                     // Tether if rndis is enabled and usb is configured.
                     tetherMatchingInterfaces(IpServer.STATE_TETHERED, TETHERING_USB);
+                } else if (usbConnected && ncmEnabled) {
+                    tetherMatchingInterfaces(IpServer.STATE_LOCAL_ONLY, TETHERING_NCM);
                 }
                 mRndisEnabled = usbConfigured && rndisEnabled;
             }
@@ -1127,6 +1210,16 @@
         return TETHER_ERROR_NO_ERROR;
     }
 
+    private int setNcmTethering(boolean enable) {
+        if (VDBG) Log.d(TAG, "setNcmTethering(" + enable + ")");
+        UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
+        synchronized (mPublicSync) {
+            usbManager.setCurrentFunctions(enable ? UsbManager.FUNCTION_NCM
+                    : UsbManager.FUNCTION_NONE);
+        }
+        return TETHER_ERROR_NO_ERROR;
+    }
+
     // TODO review API - figure out how to delete these entirely.
     String[] getTetheredIfaces() {
         ArrayList<String> list = new ArrayList<String>();
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java
index 068c346..7e9e26f 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java
@@ -83,6 +83,7 @@
     public final String[] tetherableWifiRegexs;
     public final String[] tetherableWifiP2pRegexs;
     public final String[] tetherableBluetoothRegexs;
+    public final String[] tetherableNcmRegexs;
     public final boolean isDunRequired;
     public final boolean chooseUpstreamAutomatically;
     public final Collection<Integer> preferredUpstreamIfaceTypes;
@@ -103,6 +104,7 @@
         Resources res = getResources(ctx, activeDataSubId);
 
         tetherableUsbRegexs = getResourceStringArray(res, R.array.config_tether_usb_regexs);
+        tetherableNcmRegexs = getResourceStringArray(res, R.array.config_tether_ncm_regexs);
         // TODO: Evaluate deleting this altogether now that Wi-Fi always passes
         // us an interface name. Careful consideration needs to be given to
         // implications for Settings and for provisioning checks.
@@ -156,6 +158,11 @@
         return matchesDownstreamRegexs(iface, tetherableBluetoothRegexs);
     }
 
+    /** Check if interface is ncm */
+    public boolean isNcm(String iface) {
+        return matchesDownstreamRegexs(iface, tetherableNcmRegexs);
+    }
+
     /** Check whether no ui entitlement application is available.*/
     public boolean hasMobileHotspotProvisionApp() {
         return !TextUtils.isEmpty(provisioningAppNoUi);
@@ -170,6 +177,7 @@
         dumpStringArray(pw, "tetherableWifiRegexs", tetherableWifiRegexs);
         dumpStringArray(pw, "tetherableWifiP2pRegexs", tetherableWifiP2pRegexs);
         dumpStringArray(pw, "tetherableBluetoothRegexs", tetherableBluetoothRegexs);
+        dumpStringArray(pw, "tetherableNcmRegexs", tetherableNcmRegexs);
 
         pw.print("isDunRequired: ");
         pw.println(isDunRequired);
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
index cb7d392..7dc5c5f 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
@@ -33,6 +33,7 @@
 import android.net.ITetheringEventCallback;
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
+import android.net.TetheringRequestParcel;
 import android.net.dhcp.DhcpServerCallbacks;
 import android.net.dhcp.DhcpServingParamsParcel;
 import android.net.ip.IpServer;
@@ -143,11 +144,11 @@
         }
 
         @Override
-        public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi,
-                String callerPkg) {
-            if (checkAndNotifyCommonError(callerPkg, receiver)) return;
+        public void startTethering(TetheringRequestParcel request, String callerPkg,
+                IIntResultListener listener) {
+            if (checkAndNotifyCommonError(callerPkg, listener)) return;
 
-            mTethering.startTethering(type, receiver, showProvisioningUi);
+            mTethering.startTethering(request, listener);
         }
 
         @Override
diff --git a/packages/Tethering/tests/unit/Android.bp b/packages/Tethering/tests/unit/Android.bp
index 53782fed..13174c5 100644
--- a/packages/Tethering/tests/unit/Android.bp
+++ b/packages/Tethering/tests/unit/Android.bp
@@ -19,6 +19,7 @@
     certificate: "platform",
     srcs: [
         "src/**/*.java",
+        "src/**/*.kt",
     ],
     test_suites: [
         "device-tests",
diff --git a/packages/Tethering/tests/unit/AndroidManifest.xml b/packages/Tethering/tests/unit/AndroidManifest.xml
index 0a1cdd3..530bc07 100644
--- a/packages/Tethering/tests/unit/AndroidManifest.xml
+++ b/packages/Tethering/tests/unit/AndroidManifest.xml
@@ -16,6 +16,8 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.networkstack.tethering.tests.unit">
 
+    <uses-permission android:name="android.permission.TETHER_PRIVILEGED"/>
+
     <application android:debuggable="true">
         <uses-library android:name="android.test.runner" />
     </application>
diff --git a/packages/Tethering/tests/unit/src/android/net/TetheredClientTest.kt b/packages/Tethering/tests/unit/src/android/net/TetheredClientTest.kt
new file mode 100644
index 0000000..83c19ec
--- /dev/null
+++ b/packages/Tethering/tests/unit/src/android/net/TetheredClientTest.kt
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net
+
+import android.net.InetAddresses.parseNumericAddress
+import android.net.TetheredClient.AddressInfo
+import android.net.TetheringManager.TETHERING_BLUETOOTH
+import android.net.TetheringManager.TETHERING_USB
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.testutils.assertParcelSane
+import org.junit.Test
+import org.junit.runner.RunWith
+import kotlin.test.assertEquals
+import kotlin.test.assertNotEquals
+
+private val TEST_MACADDR = MacAddress.fromBytes(byteArrayOf(12, 23, 34, 45, 56, 67))
+private val TEST_OTHER_MACADDR = MacAddress.fromBytes(byteArrayOf(23, 34, 45, 56, 67, 78))
+private val TEST_ADDR1 = LinkAddress(parseNumericAddress("192.168.113.3"), 24)
+private val TEST_ADDR2 = LinkAddress(parseNumericAddress("fe80::1:2:3"), 64)
+private val TEST_ADDRINFO1 = AddressInfo(TEST_ADDR1, "test_hostname")
+private val TEST_ADDRINFO2 = AddressInfo(TEST_ADDR2, null)
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class TetheredClientTest {
+    @Test
+    fun testParceling() {
+        assertParcelSane(makeTestClient(), fieldCount = 3)
+    }
+
+    @Test
+    fun testEquals() {
+        assertEquals(makeTestClient(), makeTestClient())
+
+        // Different mac address
+        assertNotEquals(makeTestClient(), TetheredClient(
+                TEST_OTHER_MACADDR,
+                listOf(TEST_ADDRINFO1, TEST_ADDRINFO2),
+                TETHERING_BLUETOOTH))
+
+        // Different hostname
+        assertNotEquals(makeTestClient(), TetheredClient(
+                TEST_MACADDR,
+                listOf(AddressInfo(TEST_ADDR1, "test_other_hostname"), TEST_ADDRINFO2),
+                TETHERING_BLUETOOTH))
+
+        // Null hostname
+        assertNotEquals(makeTestClient(), TetheredClient(
+                TEST_MACADDR,
+                listOf(AddressInfo(TEST_ADDR1, null), TEST_ADDRINFO2),
+                TETHERING_BLUETOOTH))
+
+        // Missing address
+        assertNotEquals(makeTestClient(), TetheredClient(
+                TEST_MACADDR,
+                listOf(TEST_ADDRINFO2),
+                TETHERING_BLUETOOTH))
+
+        // Different type
+        assertNotEquals(makeTestClient(), TetheredClient(
+                TEST_MACADDR,
+                listOf(TEST_ADDRINFO1, TEST_ADDRINFO2),
+                TETHERING_BLUETOOTH))
+    }
+
+    @Test
+    fun testAddAddresses() {
+        val client1 = TetheredClient(TEST_MACADDR, listOf(TEST_ADDRINFO1), TETHERING_USB)
+        val client2 = TetheredClient(TEST_OTHER_MACADDR, listOf(TEST_ADDRINFO2), TETHERING_USB)
+        assertEquals(TetheredClient(
+                TEST_MACADDR,
+                listOf(TEST_ADDRINFO1, TEST_ADDRINFO2),
+                TETHERING_USB), client1.addAddresses(client2))
+    }
+
+    private fun makeTestClient() = TetheredClient(
+            TEST_MACADDR,
+            listOf(TEST_ADDRINFO1, TEST_ADDRINFO2),
+            TETHERING_BLUETOOTH)
+}
\ No newline at end of file
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
index 9f0d876..4710287 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
@@ -18,6 +18,7 @@
 
 import static android.hardware.usb.UsbManager.USB_CONFIGURED;
 import static android.hardware.usb.UsbManager.USB_CONNECTED;
+import static android.hardware.usb.UsbManager.USB_FUNCTION_NCM;
 import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
 import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
 import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED;
@@ -27,6 +28,7 @@
 import static android.net.TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY;
 import static android.net.TetheringManager.EXTRA_ACTIVE_TETHER;
 import static android.net.TetheringManager.EXTRA_AVAILABLE_TETHER;
+import static android.net.TetheringManager.TETHERING_NCM;
 import static android.net.TetheringManager.TETHERING_USB;
 import static android.net.TetheringManager.TETHERING_WIFI;
 import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
@@ -88,6 +90,7 @@
 import android.net.TetherStatesParcel;
 import android.net.TetheringCallbackStartedParcel;
 import android.net.TetheringConfigurationParcel;
+import android.net.TetheringRequestParcel;
 import android.net.dhcp.DhcpServerCallbacks;
 import android.net.dhcp.DhcpServingParamsParcel;
 import android.net.dhcp.IDhcpServer;
@@ -150,6 +153,7 @@
     private static final String TEST_USB_IFNAME = "test_rndis0";
     private static final String TEST_WLAN_IFNAME = "test_wlan0";
     private static final String TEST_P2P_IFNAME = "test_p2p-p2p0-0";
+    private static final String TEST_NCM_IFNAME = "test_ncm0";
     private static final String TETHERING_NAME = "Tethering";
 
     private static final int DHCPSERVER_START_TIMEOUT_MS = 1000;
@@ -251,9 +255,11 @@
                     ifName.equals(TEST_USB_IFNAME)
                             || ifName.equals(TEST_WLAN_IFNAME)
                             || ifName.equals(TEST_MOBILE_IFNAME)
-                            || ifName.equals(TEST_P2P_IFNAME));
+                            || ifName.equals(TEST_P2P_IFNAME)
+                            || ifName.equals(TEST_NCM_IFNAME));
             final String[] ifaces = new String[] {
-                    TEST_USB_IFNAME, TEST_WLAN_IFNAME, TEST_MOBILE_IFNAME, TEST_P2P_IFNAME};
+                    TEST_USB_IFNAME, TEST_WLAN_IFNAME, TEST_MOBILE_IFNAME, TEST_P2P_IFNAME,
+                    TEST_NCM_IFNAME};
             return new InterfaceParams(ifName, ArrayUtils.indexOf(ifaces, ifName) + IFINDEX_OFFSET,
                     MacAddress.ALL_ZEROS_ADDRESS);
         }
@@ -427,13 +433,16 @@
                 .thenReturn(new String[]{ "test_p2p-p2p\\d-.*" });
         when(mResources.getStringArray(R.array.config_tether_bluetooth_regexs))
                 .thenReturn(new String[0]);
+        when(mResources.getStringArray(R.array.config_tether_ncm_regexs))
+                .thenReturn(new String[] { "test_ncm\\d" });
         when(mResources.getIntArray(R.array.config_tether_upstream_types)).thenReturn(new int[0]);
         when(mResources.getBoolean(R.bool.config_tether_upstream_automatic)).thenReturn(false);
         when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
                 false);
         when(mNetd.interfaceGetList())
                 .thenReturn(new String[] {
-                        TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME, TEST_P2P_IFNAME});
+                        TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME, TEST_P2P_IFNAME,
+                        TEST_NCM_IFNAME});
         when(mResources.getString(R.string.config_wifi_tether_enable)).thenReturn("");
         mInterfaceConfiguration = new InterfaceConfigurationParcel();
         mInterfaceConfiguration.flags = new String[0];
@@ -468,6 +477,16 @@
         return new Tethering(mTetheringDependencies);
     }
 
+    private TetheringRequestParcel createTetheringRquestParcel(final int type) {
+        final TetheringRequestParcel request = new TetheringRequestParcel();
+        request.tetheringType = type;
+        request.localIPv4Address = null;
+        request.exemptFromEntitlementCheck = false;
+        request.showProvisioningUi = false;
+
+        return request;
+    }
+
     @After
     public void tearDown() {
         mServiceContext.unregisterReceiver(mBroadcastReceiver);
@@ -513,11 +532,16 @@
                 P2P_RECEIVER_PERMISSIONS_FOR_BROADCAST);
     }
 
-    private void sendUsbBroadcast(boolean connected, boolean configured, boolean rndisFunction) {
+    private void sendUsbBroadcast(boolean connected, boolean configured, boolean function,
+            int type) {
         final Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
         intent.putExtra(USB_CONNECTED, connected);
         intent.putExtra(USB_CONFIGURED, configured);
-        intent.putExtra(USB_FUNCTION_RNDIS, rndisFunction);
+        if (type == TETHERING_USB) {
+            intent.putExtra(USB_FUNCTION_RNDIS, function);
+        } else {
+            intent.putExtra(USB_FUNCTION_NCM, function);
+        }
         mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
@@ -567,13 +591,22 @@
         verifyNoMoreInteractions(mWifiManager);
     }
 
+    private void prepareNcmTethering() {
+        // Emulate startTethering(TETHERING_NCM) called
+        mTethering.startTethering(createTetheringRquestParcel(TETHERING_NCM), null);
+        mLooper.dispatchAll();
+        verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_NCM);
+
+        mTethering.interfaceStatusChanged(TEST_NCM_IFNAME, true);
+    }
+
     private void prepareUsbTethering(UpstreamNetworkState upstreamState) {
         when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
         when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
                 .thenReturn(upstreamState);
 
         // Emulate pressing the USB tethering button in Settings UI.
-        mTethering.startTethering(TETHERING_USB, null, false);
+        mTethering.startTethering(createTetheringRquestParcel(TETHERING_USB), null);
         mLooper.dispatchAll();
         verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS);
 
@@ -589,7 +622,7 @@
         verifyNoMoreInteractions(mNetd);
 
         // Pretend we then receive USB configured broadcast.
-        sendUsbBroadcast(true, true, true);
+        sendUsbBroadcast(true, true, true, TETHERING_USB);
         mLooper.dispatchAll();
         // Now we should see the start of tethering mechanics (in this case:
         // tetherMatchingInterfaces() which starts by fetching all interfaces).
@@ -680,7 +713,7 @@
 
     private void runUsbTethering(UpstreamNetworkState upstreamState) {
         prepareUsbTethering(upstreamState);
-        sendUsbBroadcast(true, true, true);
+        sendUsbBroadcast(true, true, true, TETHERING_USB);
         mLooper.dispatchAll();
     }
 
@@ -803,6 +836,29 @@
         verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
     }
 
+    private void runNcmTethering() {
+        prepareNcmTethering();
+        sendUsbBroadcast(true, true, true, TETHERING_NCM);
+        mLooper.dispatchAll();
+    }
+
+    @Test
+    public void workingNcmTethering() throws Exception {
+        runNcmTethering();
+
+        verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
+    }
+
+    @Test
+    public void workingNcmTethering_LegacyDhcp() {
+        when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
+                true);
+        sendConfigurationChanged();
+        runNcmTethering();
+
+        verify(mIpServerDependencies, never()).makeDhcpServer(any(), any(), any());
+    }
+
     @Test
     public void workingLocalOnlyHotspotEnrichedApBroadcastWithIfaceChanged() throws Exception {
         workingLocalOnlyHotspotEnrichedApBroadcast(true);
@@ -819,7 +875,7 @@
         when(mWifiManager.startTetheredHotspot(any(SoftApConfiguration.class))).thenReturn(true);
 
         // Emulate pressing the WiFi tethering button.
-        mTethering.startTethering(TETHERING_WIFI, null, false);
+        mTethering.startTethering(createTetheringRquestParcel(TETHERING_WIFI), null);
         mLooper.dispatchAll();
         verify(mWifiManager, times(1)).startTetheredHotspot(null);
         verifyNoMoreInteractions(mWifiManager);
@@ -846,7 +902,7 @@
         when(mWifiManager.startTetheredHotspot(any(SoftApConfiguration.class))).thenReturn(true);
 
         // Emulate pressing the WiFi tethering button.
-        mTethering.startTethering(TETHERING_WIFI, null, false);
+        mTethering.startTethering(createTetheringRquestParcel(TETHERING_WIFI), null);
         mLooper.dispatchAll();
         verify(mWifiManager, times(1)).startTetheredHotspot(null);
         verifyNoMoreInteractions(mWifiManager);
@@ -923,7 +979,7 @@
         doThrow(new RemoteException()).when(mNetd).ipfwdEnableForwarding(TETHERING_NAME);
 
         // Emulate pressing the WiFi tethering button.
-        mTethering.startTethering(TETHERING_WIFI, null, false);
+        mTethering.startTethering(createTetheringRquestParcel(TETHERING_WIFI), null);
         mLooper.dispatchAll();
         verify(mWifiManager, times(1)).startTetheredHotspot(null);
         verifyNoMoreInteractions(mWifiManager);
@@ -1188,7 +1244,7 @@
         tetherState = callback.pollTetherStatesChanged();
         assertArrayEquals(tetherState.availableList, new String[] {TEST_WLAN_IFNAME});
 
-        mTethering.startTethering(TETHERING_WIFI, null, false);
+        mTethering.startTethering(createTetheringRquestParcel(TETHERING_WIFI), null);
         sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
         mLooper.dispatchAll();
         tetherState = callback.pollTetherStatesChanged();
diff --git a/proto/src/task_snapshot.proto b/proto/src/task_snapshot.proto
index 821db86..789019c 100644
--- a/proto/src/task_snapshot.proto
+++ b/proto/src/task_snapshot.proto
@@ -34,4 +34,5 @@
      string top_activity_component = 10;
      float scale = 11;
      int64 id = 12;
+     int32 rotation = 13;
  }
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index 3e74b7a..a5877cc 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -134,6 +134,10 @@
 
     boolean mRequestTouchExplorationMode;
 
+    private boolean mServiceHandlesDoubleTap;
+
+    private boolean mRequestMultiFingerGestures;
+
     boolean mRequestFilterKeyEvents;
 
     boolean mRetrieveInteractiveWindows;
@@ -298,6 +302,10 @@
 
         mRequestTouchExplorationMode = (info.flags
                 & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0;
+        mServiceHandlesDoubleTap = (info.flags
+                & AccessibilityServiceInfo.FLAG_SERVICE_HANDLES_DOUBLE_TAP) != 0;
+        mRequestMultiFingerGestures = (info.flags
+                & AccessibilityServiceInfo.FLAG_REQUEST_MULTI_FINGER_GESTURES) != 0;
         mRequestFilterKeyEvents = (info.flags
                 & AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS) != 0;
         mRetrieveInteractiveWindows = (info.flags
@@ -1689,4 +1697,12 @@
             msg.sendToTarget();
         }
     }
+
+    public boolean isServiceHandlesDoubleTapEnabled() {
+        return mServiceHandlesDoubleTap;
+    }
+
+    public boolean isMultiFingerGesturesEnabled() {
+        return mRequestMultiFingerGestures;
+    }
 }
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 49582a9..efddd86 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -99,9 +99,28 @@
      */
     static final int FLAG_FEATURE_TRIGGERED_SCREEN_MAGNIFIER = 0x00000040;
 
-    static final int FEATURES_AFFECTING_MOTION_EVENTS = FLAG_FEATURE_INJECT_MOTION_EVENTS
-            | FLAG_FEATURE_AUTOCLICK | FLAG_FEATURE_TOUCH_EXPLORATION
-            | FLAG_FEATURE_SCREEN_MAGNIFIER | FLAG_FEATURE_TRIGGERED_SCREEN_MAGNIFIER;
+    /**
+     * Flag for dispatching double tap and double tap and hold to the service.
+     *
+     * @see #setUserAndEnabledFeatures(int, int)
+     */
+    static final int FLAG_SERVICE_HANDLES_DOUBLE_TAP = 0x00000080;
+
+/**
+     * Flag for enabling multi-finger gestures.
+     *
+     * @see #setUserAndEnabledFeatures(int, int)
+     */
+    static final int FLAG_REQUEST_MULTI_FINGER_GESTURES = 0x00000100;
+
+    static final int FEATURES_AFFECTING_MOTION_EVENTS =
+            FLAG_FEATURE_INJECT_MOTION_EVENTS
+                    | FLAG_FEATURE_AUTOCLICK
+                    | FLAG_FEATURE_TOUCH_EXPLORATION
+                    | FLAG_FEATURE_SCREEN_MAGNIFIER
+                    | FLAG_FEATURE_TRIGGERED_SCREEN_MAGNIFIER
+                    | FLAG_SERVICE_HANDLES_DOUBLE_TAP
+                    | FLAG_REQUEST_MULTI_FINGER_GESTURES;
 
     private final Context mContext;
 
@@ -391,6 +410,12 @@
 
             if ((mEnabledFeatures & FLAG_FEATURE_TOUCH_EXPLORATION) != 0) {
                 TouchExplorer explorer = new TouchExplorer(displayContext, mAms);
+                if ((mEnabledFeatures & FLAG_SERVICE_HANDLES_DOUBLE_TAP) != 0) {
+                    explorer.setServiceHandlesDoubleTap(true);
+                }
+                if ((mEnabledFeatures & FLAG_REQUEST_MULTI_FINGER_GESTURES) != 0) {
+                    explorer.setMultiFingerGesturesEnabled(true);
+                }
                 addFirstEventHandler(displayId, explorer);
                 mTouchExplorer.put(displayId, explorer);
             }
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index bcaecea..61e1adf 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1610,6 +1610,12 @@
             if (userState.isHandlingAccessibilityEventsLocked()
                     && userState.isTouchExplorationEnabledLocked()) {
                 flags |= AccessibilityInputFilter.FLAG_FEATURE_TOUCH_EXPLORATION;
+                if (userState.isServiceHandlesDoubleTapEnabledLocked()) {
+                    flags |= AccessibilityInputFilter.FLAG_SERVICE_HANDLES_DOUBLE_TAP;
+                }
+                if (userState.isMultiFingerGesturesEnabledLocked()) {
+                    flags |= AccessibilityInputFilter.FLAG_REQUEST_MULTI_FINGER_GESTURES;
+                }
             }
             if (userState.isFilterKeyEventsEnabledLocked()) {
                 flags |= AccessibilityInputFilter.FLAG_FEATURE_FILTER_KEY_EVENTS;
@@ -1882,26 +1888,32 @@
     }
 
     private void updateTouchExplorationLocked(AccessibilityUserState userState) {
-        boolean enabled = mUiAutomationManager.isTouchExplorationEnabledLocked();
+        boolean touchExplorationEnabled = mUiAutomationManager.isTouchExplorationEnabledLocked();
+        boolean serviceHandlesDoubleTapEnabled = false;
+        boolean requestMultiFingerGestures = false;
         final int serviceCount = userState.mBoundServices.size();
         for (int i = 0; i < serviceCount; i++) {
             AccessibilityServiceConnection service = userState.mBoundServices.get(i);
             if (canRequestAndRequestsTouchExplorationLocked(service, userState)) {
-                enabled = true;
+                touchExplorationEnabled = true;
+                serviceHandlesDoubleTapEnabled = service.isServiceHandlesDoubleTapEnabled();
+                requestMultiFingerGestures = service.isMultiFingerGesturesEnabled();
                 break;
             }
         }
-        if (enabled != userState.isTouchExplorationEnabledLocked()) {
-            userState.setTouchExplorationEnabledLocked(enabled);
+        if (touchExplorationEnabled != userState.isTouchExplorationEnabledLocked()) {
+            userState.setTouchExplorationEnabledLocked(touchExplorationEnabled);
             final long identity = Binder.clearCallingIdentity();
             try {
                 Settings.Secure.putIntForUser(mContext.getContentResolver(),
-                        Settings.Secure.TOUCH_EXPLORATION_ENABLED, enabled ? 1 : 0,
+                        Settings.Secure.TOUCH_EXPLORATION_ENABLED, touchExplorationEnabled ? 1 : 0,
                         userState.mUserId);
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
         }
+        userState.setServiceHandlesDoubleTapLocked(serviceHandlesDoubleTapEnabled);
+        userState.setMultiFingerGesturesLocked(requestMultiFingerGestures);
     }
 
     private boolean readAccessibilityShortcutKeySettingLocked(AccessibilityUserState userState) {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
index ebe2af6..4e7da97 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
@@ -103,6 +103,8 @@
     private boolean mIsPerformGesturesEnabled;
     private boolean mIsTextHighContrastEnabled;
     private boolean mIsTouchExplorationEnabled;
+    private boolean mServiceHandlesDoubleTap;
+    private boolean mRequestMultiFingerGestures;
     private int mUserInteractiveUiTimeout;
     private int mUserNonInteractiveUiTimeout;
     private int mNonInteractiveUiTimeout = 0;
@@ -151,6 +153,8 @@
         mAccessibilityShortcutKeyTargets.clear();
         mAccessibilityButtonTargets.clear();
         mIsTouchExplorationEnabled = false;
+        mServiceHandlesDoubleTap = false;
+        mRequestMultiFingerGestures = false;
         mIsDisplayMagnificationEnabled = false;
         mIsAutoclickEnabled = false;
         mUserNonInteractiveUiTimeout = 0;
@@ -351,6 +355,8 @@
         // Touch exploration relies on enabled accessibility.
         if (a11yEnabled && mIsTouchExplorationEnabled) {
             clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
+            clientState |= AccessibilityManager.STATE_FLAG_DISPATCH_DOUBLE_TAP;
+            clientState |= AccessibilityManager.STATE_FLAG_REQUEST_MULTI_FINGER_GESTURES;
         }
         if (mIsTextHighContrastEnabled) {
             clientState |= AccessibilityManager.STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED;
@@ -431,6 +437,10 @@
         pw.println();
         pw.append("     attributes:{id=").append(String.valueOf(mUserId));
         pw.append(", touchExplorationEnabled=").append(String.valueOf(mIsTouchExplorationEnabled));
+        pw.append(", serviceHandlesDoubleTap=")
+                .append(String.valueOf(mServiceHandlesDoubleTap));
+        pw.append(", requestMultiFingerGestures=")
+                .append(String.valueOf(mRequestMultiFingerGestures));
         pw.append(", displayMagnificationEnabled=").append(String.valueOf(
                 mIsDisplayMagnificationEnabled));
         pw.append(", autoclickEnabled=").append(String.valueOf(mIsAutoclickEnabled));
@@ -675,6 +685,22 @@
         mIsTouchExplorationEnabled = enabled;
     }
 
+    public boolean isServiceHandlesDoubleTapEnabledLocked() {
+        return mServiceHandlesDoubleTap;
+    }
+
+    public void setServiceHandlesDoubleTapLocked(boolean enabled) {
+        mServiceHandlesDoubleTap = enabled;
+    }
+
+    public boolean isMultiFingerGesturesEnabledLocked() {
+        return mRequestMultiFingerGestures;
+    }
+
+    public void setMultiFingerGesturesLocked(boolean enabled) {
+        mRequestMultiFingerGestures = enabled;
+    }
+
     public int getUserInteractiveUiTimeoutLocked() {
         return mUserInteractiveUiTimeout;
     }
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java b/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java
index 50d21ba..b5660ae 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java
@@ -65,6 +65,13 @@
     private final Handler mHandler;
     // Listener to be notified of gesture start and end.
     private Listener mListener;
+    // Whether double tap and double tap and hold will be dispatched to the service or handled in
+    // the framework.
+    private boolean mServiceHandlesDoubleTap = false;
+    // Whether multi-finger gestures are enabled.
+    boolean mMultiFingerGesturesEnabled;
+    // A list of all the multi-finger gestures, for easy adding and removal.
+    private final List<GestureMatcher> mMultiFingerGestures = new ArrayList<>();
     // Shared state information.
     private TouchState mState;
 
@@ -154,18 +161,23 @@
      */
     public interface Listener {
         /**
-         * Called when the user has performed a double tap and then held down the second tap.
+         * When FLAG_SERVICE_HANDLES_DOUBLE_TAP is enabled, this method is not called; double-tap
+         * and hold is dispatched via onGestureCompleted. Otherwise, this method is called when the
+         * user has performed a double tap and then held down the second tap.
          */
         void onDoubleTapAndHold();
 
         /**
-         * Called when the user lifts their finger on the second tap of a double tap.
+         * When FLAG_SERVICE_HANDLES_DOUBLE_TAP is enabled, this method is not called; double-tap is
+         * dispatched via onGestureCompleted. Otherwise, this method is called when the user lifts
+         * their finger on the second tap of a double tap.
+         *
          * @return true if the event is consumed, else false
          */
         boolean onDoubleTap();
 
         /**
-         * Called when the system has decided the event stream is a gesture.
+         * Called when the system has decided the event stream is a potential gesture.
          *
          * @return true if the event is consumed, else false
          */
@@ -193,7 +205,13 @@
     public void onStateChanged(
             int gestureId, int state, MotionEvent event, MotionEvent rawEvent, int policyFlags) {
         if (state == GestureMatcher.STATE_GESTURE_STARTED && !mState.isGestureDetecting()) {
-            mListener.onGestureStarted();
+            if (gestureId == GESTURE_DOUBLE_TAP || gestureId == GESTURE_DOUBLE_TAP_AND_HOLD) {
+                if (mServiceHandlesDoubleTap) {
+                    mListener.onGestureStarted();
+                }
+            } else {
+                mListener.onGestureStarted();
+            }
         } else if (state == GestureMatcher.STATE_GESTURE_COMPLETED) {
             onGestureCompleted(gestureId);
         } else if (state == GestureMatcher.STATE_GESTURE_CANCELED && mState.isGestureDetecting()) {
@@ -217,11 +235,23 @@
         // Gestures that complete on a delay call clear() here.
         switch (gestureId) {
             case GESTURE_DOUBLE_TAP:
-                mListener.onDoubleTap();
+                if (mServiceHandlesDoubleTap) {
+                    AccessibilityGestureEvent gestureEvent =
+                            new AccessibilityGestureEvent(gestureId, event.getDisplayId());
+                    mListener.onGestureCompleted(gestureEvent);
+                } else {
+                    mListener.onDoubleTap();
+                }
                 clear();
                 break;
             case GESTURE_DOUBLE_TAP_AND_HOLD:
-                mListener.onDoubleTapAndHold();
+                if (mServiceHandlesDoubleTap) {
+                    AccessibilityGestureEvent gestureEvent =
+                            new AccessibilityGestureEvent(gestureId, event.getDisplayId());
+                    mListener.onGestureCompleted(gestureEvent);
+                } else {
+                    mListener.onDoubleTapAndHold();
+                }
                 clear();
                 break;
             default:
@@ -231,4 +261,27 @@
                 break;
         }
     }
+
+    public boolean isMultiFingerGesturesEnabled() {
+        return mMultiFingerGesturesEnabled;
+    }
+
+    public void setMultiFingerGesturesEnabled(boolean mode) {
+        if (mMultiFingerGesturesEnabled != mode) {
+            mMultiFingerGesturesEnabled = mode;
+            if (mode) {
+                mGestures.addAll(mMultiFingerGestures);
+            } else {
+                mGestures.removeAll(mMultiFingerGestures);
+            }
+        }
+    }
+
+    public void setServiceHandlesDoubleTap(boolean mode) {
+        mServiceHandlesDoubleTap = mode;
+    }
+
+    public boolean isServiceHandlesDoubleTapEnabled() {
+        return mServiceHandlesDoubleTap;
+    }
 }
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/MultiTap.java b/services/accessibility/java/com/android/server/accessibility/gestures/MultiTap.java
index 4c9e590..386cb06 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/MultiTap.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/MultiTap.java
@@ -70,6 +70,13 @@
         }
         mBaseX = event.getX();
         mBaseY = event.getY();
+        if (mCurrentTaps + 1 == mTargetTaps) {
+            // Start gesture detecting on down of final tap.
+            // Note that if this instance is matching double tap,
+            // and the service is not requesting to handle double tap, GestureManifold will
+            // ignore this.
+            startGesture(event, rawEvent, policyFlags);
+        }
     }
 
     @Override
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
index ba890c5..2cc11c5 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
@@ -254,7 +254,10 @@
         } else if (mState.isDelegating()) {
             handleMotionEventStateDelegating(event, rawEvent, policyFlags);
         } else if (mState.isGestureDetecting()) {
-            // Already handled.
+            // Make sure we don't prematurely get TOUCH_INTERACTION_END
+            // It will be delivered on gesture completion or cancelation.
+            // Note that the delay for sending GESTURE_DETECTION_END remains in place.
+            mSendTouchInteractionEndDelayed.cancel();
         } else {
             Slog.e(LOG_TAG, "Illegal state: " + mState);
                 clear(event, policyFlags);
@@ -331,12 +334,8 @@
 
     @Override
     public boolean onGestureCompleted(AccessibilityGestureEvent gestureEvent) {
-        if (!mState.isGestureDetecting()) {
-            return false;
-        }
-
         endGestureDetection(true);
-
+        mSendTouchInteractionEndDelayed.cancel();
         mAms.onGesture(gestureEvent);
 
         return true;
@@ -516,6 +515,9 @@
                 }
                 break;
             case 2:
+                if (mGestureDetector.isMultiFingerGesturesEnabled()) {
+                    return;
+                }
                 // Make sure we don't have any pending transitions to touch exploration
                 mSendHoverEnterAndMoveDelayed.cancel();
                 mSendHoverExitDelayed.cancel();
@@ -538,6 +540,9 @@
                 }
                 break;
             default:
+                if (mGestureDetector.isMultiFingerGesturesEnabled()) {
+                    return;
+                }
                 // More than two pointers are delegated to the view hierarchy.
                 mState.startDelegating();
                 event = MotionEvent.obtainNoHistory(event);
@@ -583,6 +588,9 @@
                         event, MotionEvent.ACTION_HOVER_MOVE, rawEvent, pointerIdBits, policyFlags);
                 break;
             case 2:
+                if (mGestureDetector.isMultiFingerGesturesEnabled()) {
+                    return;
+                }
                 if (mSendHoverEnterAndMoveDelayed.isPending()) {
                     // We have not started sending events so cancel
                     // scheduled sending events.
@@ -610,6 +618,9 @@
                 }
                 break;
             default:
+                if (mGestureDetector.isMultiFingerGesturesEnabled()) {
+                    return;
+                }
                 // Three or more fingers is  something other than touch exploration.
                 if (mSendHoverEnterAndMoveDelayed.isPending()) {
                     // We have not started sending events so cancel
@@ -632,6 +643,10 @@
      */
     private void handleMotionEventStateDragging(
             MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+        if (mGestureDetector.isMultiFingerGesturesEnabled()) {
+            // Multi-finger gestures conflict with this functionality.
+            return;
+        }
         int pointerIdBits = 0;
         // Clear the dragging pointer id if it's no longer valid.
         if (event.findPointerIndex(mDraggingPointerId) == -1) {
@@ -742,6 +757,10 @@
      */
     private void handleMotionEventStateDelegating(
             MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+        if (mGestureDetector.isMultiFingerGesturesEnabled()) {
+            // Multi-finger gestures conflict with this functionality.
+            return;
+        }
         switch (event.getActionMasked()) {
             case MotionEvent.ACTION_DOWN: {
                 Slog.e(LOG_TAG, "Delegating state can only be reached if "
@@ -875,6 +894,22 @@
     }
 
     /**
+     * Whether to dispatch double tap and double tap and hold to the service rather than handle them
+     * in the framework.
+     */
+    public void setServiceHandlesDoubleTap(boolean mode) {
+        mGestureDetector.setServiceHandlesDoubleTap(mode);
+    }
+
+    /**
+     * This function turns on and off multi-finger gestures. When enabled, multi-finger gestures
+     * will disable delegating and dragging functionality.
+     */
+    public void setMultiFingerGesturesEnabled(boolean enabled) {
+        mGestureDetector.setMultiFingerGesturesEnabled(enabled);
+    }
+
+    /**
      * Class for delayed exiting from gesture detecting mode.
      */
     private final class ExitGestureDetectionModeDelayed implements Runnable {
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
index f69b638..b229e9f 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
@@ -44,6 +44,7 @@
     public void onBootPhase(int phase) {
         if (phase == PHASE_ACTIVITY_MANAGER_READY) {
             mImpl.setSafeMode(isSafeMode());
+            mImpl.systemServicesReady();
         }
     }
 
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 26245b1..97f27ca 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -24,9 +24,11 @@
 
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
 import android.app.AlarmManager;
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
+import android.app.AppOpsManagerInternal;
 import android.app.IApplicationThread;
 import android.app.IServiceConnection;
 import android.app.KeyguardManager;
@@ -232,6 +234,8 @@
     private KeyguardManager mKeyguardManager;
     private DevicePolicyManagerInternal mDevicePolicyManagerInternal;
     private PackageManagerInternal mPackageManagerInternal;
+    private ActivityManagerInternal mActivityManagerInternal;
+    private AppOpsManagerInternal mAppOpsManagerInternal;
 
     private SecurityPolicy mSecurityPolicy;
 
@@ -272,6 +276,11 @@
         LocalServices.addService(AppWidgetManagerInternal.class, new AppWidgetManagerLocal());
     }
 
+    void systemServicesReady() {
+        mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
+        mAppOpsManagerInternal = LocalServices.getService(AppOpsManagerInternal.class);
+    }
+
     private void computeMaximumWidgetBitmapMemory() {
         WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
         Display display = wm.getDefaultDisplay();
@@ -634,8 +643,11 @@
                     final SuspendDialogInfo dialogInfo =
                             mPackageManagerInternal.getSuspendedDialogInfo(providerPackage,
                                     suspendingPackage, providerUserId);
+                    // TODO(b/148035643): Send the original widget intent or ACTION_MAIN as an
+                    // IntentSender to SuspendedAppActivity.
                     onClickIntent = SuspendedAppActivity.createSuspendedAppInterceptIntent(
-                            providerPackage, suspendingPackage, dialogInfo, null, providerUserId);
+                            providerPackage, suspendingPackage, dialogInfo, null, null,
+                            providerUserId);
                 }
             } else if (provider.maskedByQuietProfile) {
                 showBadge = true;
@@ -867,6 +879,8 @@
                     outUpdates.add(updatesMap.valueAt(j));
                 }
             }
+            updateAppOpsLocked(host, true);
+
             // Reset the update counter once all the updates have been calculated
             host.lastWidgetUpdateSequenceNo = updateSequenceNo;
             return new ParceledListSlice<>(outUpdates);
@@ -895,6 +909,7 @@
             if (host != null) {
                 host.callbacks = null;
                 pruneHostLocked(host);
+                updateAppOpsLocked(host, false);
             }
         }
     }
@@ -1952,7 +1967,6 @@
             scheduleNotifyUpdateAppWidgetLocked(widget, widget.getEffectiveViewsLocked());
         }
     }
-
     private void scheduleNotifyAppWidgetViewDataChanged(Widget widget, int viewId) {
         if (viewId == ID_VIEWS_UPDATE || viewId == ID_PROVIDER_CHANGED) {
             // A view id should never collide with these constants but a developer can call this
@@ -3618,6 +3632,26 @@
         return false;
     }
 
+    private void updateAppOpsLocked(Host host, boolean visible) {
+        // The launcher must be at TOP.
+        final int procState = mActivityManagerInternal.getUidProcessState(host.id.uid);
+        if (procState > ActivityManager.PROCESS_STATE_TOP) {
+            return;
+        }
+
+        final List<ResolveInfo> allHomeCandidates = new ArrayList<>();
+        // Default launcher from package manager.
+        final ComponentName defaultLauncher = mPackageManagerInternal
+                .getHomeActivitiesAsUser(allHomeCandidates, UserHandle.getUserId(host.id.uid));
+        // The launcher must be default launcher.
+        if (defaultLauncher == null
+                || !defaultLauncher.getPackageName().equals(host.id.packageName)) {
+            return;
+        }
+
+        mAppOpsManagerInternal.updateAppWidgetVisibility(host.getWidgetUids(), visible);
+    }
+
     private final class CallbackHandler extends Handler {
         public static final int MSG_NOTIFY_UPDATE_APP_WIDGET = 1;
         public static final int MSG_NOTIFY_PROVIDER_CHANGED = 2;
@@ -4099,6 +4133,16 @@
                     PendingHostUpdate.appWidgetRemoved(appWidgetId));
         }
 
+        public SparseArray<String> getWidgetUids() {
+            final SparseArray<String> uids = new SparseArray<>();
+            for (int i = widgets.size() - 1; i >= 0; i--) {
+                final Widget widget = widgets.get(i);
+                final ProviderId providerId = widget.provider.id;
+                uids.put(providerId.uid, providerId.componentName.getPackageName());
+            }
+            return uids;
+        }
+
         @Override
         public String toString() {
             return "Host{" + id + (zombie ? " Z" : "") + '}';
@@ -4853,6 +4897,5 @@
         public void unlockUser(int userId) {
             handleUserUnlocked(userId);
         }
-
     }
 }
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index bf801fc..e28ef0f 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -57,6 +57,7 @@
 import android.service.autofill.FillEventHistory.Event;
 import android.service.autofill.FillResponse;
 import android.service.autofill.IAutoFillService;
+import android.service.autofill.InlineSuggestionRenderService;
 import android.service.autofill.SaveInfo;
 import android.service.autofill.UserData;
 import android.util.ArrayMap;
@@ -117,6 +118,7 @@
     private final LocalLog mUiLatencyHistory;
     private final LocalLog mWtfHistory;
     private final FieldClassificationStrategy mFieldClassificationStrategy;
+    private RemoteInlineSuggestionRenderService mRemoteInlineSuggestionRenderService;
 
     /**
      * Apps disabled by the service; key is package name, value is when they will be enabled again.
@@ -212,6 +214,17 @@
             sendStateToClients(/* resetClient= */ false);
         }
         updateRemoteAugmentedAutofillService();
+
+        final ComponentName componentName = RemoteInlineSuggestionRenderService
+                .getServiceComponentName(getContext());
+        if (componentName != null) {
+            mRemoteInlineSuggestionRenderService = new RemoteInlineSuggestionRenderService(
+                    getContext(), componentName, InlineSuggestionRenderService.SERVICE_INTERFACE,
+                    mUserId, new InlineSuggestionRenderCallbacksImpl(),
+                    mMaster.isBindInstantServiceAllowed(), mMaster.verbose);
+        } else {
+            mRemoteInlineSuggestionRenderService = null;
+        }
         return enabledChanged;
     }
 
@@ -1542,6 +1555,21 @@
         return mFieldClassificationStrategy.getDefaultAlgorithm();
     }
 
+    RemoteInlineSuggestionRenderService getRemoteInlineSuggestionRenderService() {
+        return mRemoteInlineSuggestionRenderService;
+    }
+
+    private class InlineSuggestionRenderCallbacksImpl implements
+            RemoteInlineSuggestionRenderService.InlineSuggestionRenderCallbacks {
+
+        @Override // from InlineSuggestionRenderCallbacksImpl
+        public void onServiceDied(@NonNull RemoteInlineSuggestionRenderService service) {
+            // Don't do anything; eventually the system will bind to it again...
+            Slog.w(TAG, "remote service died: " + service);
+            mRemoteInlineSuggestionRenderService = null;
+        }
+    }
+
     @Override
     public String toString() {
         return "AutofillManagerServiceImpl: [userId=" + mUserId
diff --git a/services/autofill/java/com/android/server/autofill/InlineSuggestionFactory.java b/services/autofill/java/com/android/server/autofill/InlineSuggestionFactory.java
index 5e6f97e..c7be80c 100644
--- a/services/autofill/java/com/android/server/autofill/InlineSuggestionFactory.java
+++ b/services/autofill/java/com/android/server/autofill/InlineSuggestionFactory.java
@@ -20,7 +20,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.slice.Slice;
 import android.content.Context;
 import android.os.RemoteException;
 import android.service.autofill.Dataset;
@@ -123,7 +122,8 @@
         // TODO(b/146453195): fill in the autofill hint properly.
         final InlineSuggestionInfo inlineSuggestionInfo = new InlineSuggestionInfo(
                 inlinePresentation.getInlinePresentationSpec(),
-                InlineSuggestionInfo.SOURCE_PLATFORM, new String[]{""});
+                InlineSuggestionInfo.SOURCE_PLATFORM, new String[]{""},
+                InlineSuggestionInfo.TYPE_SUGGESTION);
         final View.OnClickListener onClickListener = v -> {
             try {
                 client.autofill(sessionId, dataset.getFieldIds(), dataset.getFieldValues());
@@ -132,7 +132,7 @@
             }
         };
         final InlineSuggestion inlineSuggestion = new InlineSuggestion(inlineSuggestionInfo,
-                createInlineContentProvider(inlinePresentation.getSlice(), inlineSuggestionUi,
+                createInlineContentProvider(inlinePresentation, inlineSuggestionUi,
                         onClickListener));
         return inlineSuggestion;
     }
@@ -146,25 +146,28 @@
         // TODO(b/146453195): fill in the autofill hint properly.
         final InlineSuggestionInfo inlineSuggestionInfo = new InlineSuggestionInfo(
                 inlinePresentation.getInlinePresentationSpec(),
-                InlineSuggestionInfo.SOURCE_AUTOFILL, new String[]{""});
+                InlineSuggestionInfo.SOURCE_AUTOFILL, new String[]{""},
+                InlineSuggestionInfo.TYPE_SUGGESTION);
         final View.OnClickListener onClickListener = v -> {
             client.fill(requestId, fieldIndex, dataset);
         };
         final InlineSuggestion inlineSuggestion = new InlineSuggestion(inlineSuggestionInfo,
-                createInlineContentProvider(inlinePresentation.getSlice(), inlineSuggestionUi,
+                createInlineContentProvider(inlinePresentation, inlineSuggestionUi,
                         onClickListener));
         return inlineSuggestion;
     }
 
     private static IInlineContentProvider.Stub createInlineContentProvider(
-            @NonNull Slice slice, @NonNull InlineSuggestionUi inlineSuggestionUi,
+            @NonNull InlinePresentation inlinePresentation,
+            @NonNull InlineSuggestionUi inlineSuggestionUi,
             @Nullable View.OnClickListener onClickListener) {
         return new IInlineContentProvider.Stub() {
             @Override
             public void provideContent(int width, int height,
                     IInlineContentCallback callback) {
                 UiThread.getHandler().post(() -> {
-                    SurfaceControl sc = inlineSuggestionUi.inflate(slice, width, height,
+                    SurfaceControl sc = inlineSuggestionUi.inflate(inlinePresentation, width,
+                            height,
                             onClickListener);
                     try {
                         callback.onContent(sc);
diff --git a/services/autofill/java/com/android/server/autofill/RemoteInlineSuggestionRenderService.java b/services/autofill/java/com/android/server/autofill/RemoteInlineSuggestionRenderService.java
new file mode 100644
index 0000000..f9e08e6
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/RemoteInlineSuggestionRenderService.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.autofill;
+
+import static com.android.server.autofill.Helper.sVerbose;
+
+import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.os.IBinder;
+import android.service.autofill.IInlineSuggestionRenderService;
+import android.service.autofill.IInlineSuggestionUiCallback;
+import android.service.autofill.InlinePresentation;
+import android.service.autofill.InlineSuggestionRenderService;
+import android.util.Slog;
+
+import com.android.internal.infra.AbstractMultiplePendingRequestsRemoteService;
+
+final class RemoteInlineSuggestionRenderService extends
+        AbstractMultiplePendingRequestsRemoteService<RemoteInlineSuggestionRenderService,
+                IInlineSuggestionRenderService> {
+
+    private static final String TAG = "RemoteInlineSuggestionRenderService";
+
+    private final int mIdleUnbindTimeoutMs = 5000;
+
+    RemoteInlineSuggestionRenderService(Context context, ComponentName componentName,
+            String serviceInterface, int userId, InlineSuggestionRenderCallbacks callback,
+            boolean bindInstantServiceAllowed, boolean verbose) {
+        super(context, serviceInterface, componentName, userId, callback,
+                context.getMainThreadHandler(),
+                bindInstantServiceAllowed ? Context.BIND_ALLOW_INSTANT : 0, verbose,
+                /* initialCapacity= */ 2);
+
+        ensureBound();
+    }
+
+    @Override // from AbstractRemoteService
+    protected IInlineSuggestionRenderService getServiceInterface(@NonNull IBinder service) {
+        return IInlineSuggestionRenderService.Stub.asInterface(service);
+    }
+
+    @Override // from AbstractRemoteService
+    protected long getTimeoutIdleBindMillis() {
+        return mIdleUnbindTimeoutMs;
+    }
+
+    @Override // from AbstractRemoteService
+    protected void handleOnConnectedStateChanged(boolean connected) {
+        if (connected && getTimeoutIdleBindMillis() != PERMANENT_BOUND_TIMEOUT_MS) {
+            scheduleUnbind();
+        }
+        super.handleOnConnectedStateChanged(connected);
+    }
+
+    public void ensureBound() {
+        scheduleBind();
+    }
+
+    /**
+     * Called by {@link Session} to generate a call to the
+     * {@link RemoteInlineSuggestionRenderService} to request rendering a slice .
+     */
+    void renderSuggestion(@NonNull IInlineSuggestionUiCallback callback,
+            @NonNull InlinePresentation presentation, int width, int height) {
+        scheduleAsyncRequest((s) -> s.renderSuggestion(callback, presentation, width, height));
+    }
+
+    @Nullable
+    private static ServiceInfo getServiceInfo(Context context) {
+        final String packageName =
+                context.getPackageManager().getServicesSystemSharedLibraryPackageName();
+        if (packageName == null) {
+            Slog.w(TAG, "no external services package!");
+            return null;
+        }
+
+        final Intent intent = new Intent(InlineSuggestionRenderService.SERVICE_INTERFACE);
+        intent.setPackage(packageName);
+        final ResolveInfo resolveInfo = context.getPackageManager().resolveService(intent,
+                PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
+        final ServiceInfo serviceInfo = resolveInfo == null ? null : resolveInfo.serviceInfo;
+        if (resolveInfo == null || serviceInfo == null) {
+            Slog.w(TAG, "No valid components found.");
+            return null;
+        }
+
+        if (!Manifest.permission.BIND_INLINE_SUGGESTION_RENDER_SERVICE
+                .equals(serviceInfo.permission)) {
+            Slog.w(TAG, serviceInfo.name + " does not require permission "
+                    + Manifest.permission.BIND_INLINE_SUGGESTION_RENDER_SERVICE);
+            return null;
+        }
+
+        return serviceInfo;
+    }
+
+    @Nullable
+    public static ComponentName getServiceComponentName(Context context) {
+        final ServiceInfo serviceInfo = getServiceInfo(context);
+        if (serviceInfo == null) return null;
+
+        final ComponentName componentName = new ComponentName(serviceInfo.packageName,
+                serviceInfo.name);
+
+        if (sVerbose) Slog.v(TAG, "getServiceComponentName(): " + componentName);
+        return componentName;
+    }
+
+    interface InlineSuggestionRenderCallbacks
+            extends VultureCallback<RemoteInlineSuggestionRenderService> {
+        // NOTE: so far we don't need to notify the callback implementation
+        // (AutofillManagerServiceImpl) of the request results (success, timeouts, etc..), so this
+        // callback interface is empty.
+    }
+}
diff --git a/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionUi.java b/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionUi.java
index 2460732..2adefea 100644
--- a/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionUi.java
@@ -25,10 +25,17 @@
 import android.app.slice.Slice;
 import android.app.slice.SliceItem;
 import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
 import android.graphics.PixelFormat;
 import android.graphics.drawable.Icon;
+import android.graphics.fonts.SystemFonts;
 import android.os.IBinder;
+import android.service.autofill.InlinePresentation;
+import android.text.TextUtils;
 import android.util.Log;
+import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
 import android.view.SurfaceControl;
 import android.view.SurfaceControlViewHost;
@@ -41,6 +48,8 @@
 import com.android.internal.R;
 
 import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * This is a temporary inline suggestion UI inflater which will be replaced by the ExtServices
@@ -54,6 +63,10 @@
 
     private static final String TAG = "InlineSuggestionUi";
 
+    // The pattern to match the value can be obtained by calling {@code Resources#getResourceName
+    // (int)}. This name is a single string of the form "package:type/entry".
+    private static final Pattern RESOURCE_NAME_PATTERN = Pattern.compile("([^:]+):([^/]+)/(\\S+)");
+
     private final Context mContext;
 
     public InlineSuggestionUi(Context context) {
@@ -65,28 +78,36 @@
      */
     @MainThread
     @Nullable
-    public SurfaceControl inflate(@NonNull Slice slice, int width, int height,
-            @Nullable View.OnClickListener onClickListener) {
+    public SurfaceControl inflate(@NonNull InlinePresentation inlinePresentation, int width,
+            int height, @Nullable View.OnClickListener onClickListener) {
         Log.d(TAG, "Inflating the inline suggestion UI");
 
         //TODO(b/137800469): Pass in inputToken from IME.
         final SurfaceControlViewHost wvr = new SurfaceControlViewHost(mContext,
                 mContext.getDisplay(), (IBinder) null);
         final SurfaceControl sc = wvr.getSurfacePackage().getSurfaceControl();
-        final ViewGroup suggestionView = (ViewGroup) renderSlice(slice);
+
+        Context contextThemeWrapper = getContextThemeWrapper(mContext,
+                inlinePresentation.getInlinePresentationSpec().getStyle());
+        if (contextThemeWrapper == null) {
+            contextThemeWrapper = getDefaultContextThemeWrapper(mContext);
+        }
+        final View suggestionView = renderSlice(inlinePresentation.getSlice(),
+                contextThemeWrapper);
         if (onClickListener != null) {
             suggestionView.setOnClickListener(onClickListener);
         }
 
         WindowManager.LayoutParams lp =
                 new WindowManager.LayoutParams(width, height,
-                        WindowManager.LayoutParams.TYPE_APPLICATION, 0, PixelFormat.TRANSPARENT);
+                        WindowManager.LayoutParams.TYPE_APPLICATION, 0,
+                        PixelFormat.TRANSPARENT);
         wvr.addView(suggestionView, lp);
         return sc;
     }
 
-    private View renderSlice(Slice slice) {
-        final LayoutInflater inflater = LayoutInflater.from(mContext);
+    private static View renderSlice(Slice slice, Context context) {
+        final LayoutInflater inflater = LayoutInflater.from(context);
         final ViewGroup suggestionView =
                 (ViewGroup) inflater.inflate(R.layout.autofill_inline_suggestion, null);
 
@@ -137,4 +158,96 @@
 
         return suggestionView;
     }
+
+    private Context getDefaultContextThemeWrapper(@NonNull Context context) {
+        Resources.Theme theme = context.getResources().newTheme();
+        theme.applyStyle(android.R.style.Theme_AutofillInlineSuggestion, true);
+        return new ContextThemeWrapper(context, theme);
+    }
+
+    /**
+     * Returns a context wrapping the theme in the provided {@code style}, or null if {@code
+     * style} doesn't pass validation.
+     */
+    @Nullable
+    private static Context getContextThemeWrapper(@NonNull Context context,
+            @Nullable String style) {
+        if (style == null) {
+            return null;
+        }
+        Matcher matcher = RESOURCE_NAME_PATTERN.matcher(style);
+        if (!matcher.matches()) {
+            Log.d(TAG, "Can not parse the style=" + style);
+            return null;
+        }
+        String packageName = matcher.group(1);
+        String type = matcher.group(2);
+        String entry = matcher.group(3);
+        if (TextUtils.isEmpty(packageName) || TextUtils.isEmpty(type) || TextUtils.isEmpty(entry)) {
+            Log.d(TAG, "Can not proceed with empty field values in the style=" + style);
+            return null;
+        }
+        Resources resources = null;
+        try {
+            resources = context.getPackageManager().getResourcesForApplication(
+                    packageName);
+        } catch (PackageManager.NameNotFoundException e) {
+            return null;
+        }
+        int resId = resources.getIdentifier(entry, type, packageName);
+        if (resId == Resources.ID_NULL) {
+            return null;
+        }
+        Resources.Theme theme = resources.newTheme();
+        theme.applyStyle(resId, true);
+        if (!validateBaseTheme(theme, resId)) {
+            Log.d(TAG, "Provided theme is not a child of Theme.InlineSuggestion, ignoring it.");
+            return null;
+        }
+        if (!validateFontFamilyForTextViewStyles(theme)) {
+            Log.d(TAG,
+                    "Provided theme specifies a font family that is not system font, ignoring it.");
+            return null;
+        }
+        return new ContextThemeWrapper(context, theme);
+    }
+
+    private static boolean validateFontFamilyForTextViewStyles(Resources.Theme theme) {
+        return validateFontFamily(theme, android.R.attr.autofillInlineSuggestionTitle)
+                && validateFontFamily(theme, android.R.attr.autofillInlineSuggestionSubtitle);
+    }
+
+    private static boolean validateFontFamily(Resources.Theme theme, int styleAttr) {
+        TypedArray ta = null;
+        try {
+            ta = theme.obtainStyledAttributes(null, new int[]{android.R.attr.fontFamily},
+                    styleAttr,
+                    0);
+            if (ta.getIndexCount() == 0) {
+                return true;
+            }
+            String fontFamily = ta.getString(ta.getIndex(0));
+            return SystemFonts.getRawSystemFallbackMap().containsKey(fontFamily);
+        } finally {
+            if (ta != null) {
+                ta.recycle();
+            }
+        }
+    }
+
+    private static boolean validateBaseTheme(Resources.Theme theme, int styleAttr) {
+        TypedArray ta = null;
+        try {
+            ta = theme.obtainStyledAttributes(null,
+                    new int[]{android.R.attr.isAutofillInlineSuggestionTheme}, styleAttr, 0);
+            if (ta.getIndexCount() == 0) {
+                return false;
+            }
+            return ta.getBoolean(ta.getIndex(0), false);
+        } finally {
+            if (ta != null) {
+                ta.recycle();
+            }
+        }
+    }
 }
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index f0fa99a..e3d2dcc 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -186,6 +186,7 @@
                 return;
             }
             mPowerManagerWakeLock.acquire();
+            Slog.v(TAG, "Acquired wakelock:" + mPowerManagerWakeLock.getTag());
         }
 
         /** Releases the {@link PowerManager.WakeLock} if hasn't been quit. */
@@ -195,6 +196,7 @@
                 return;
             }
             mPowerManagerWakeLock.release();
+            Slog.v(TAG, "Released wakelock:" + mPowerManagerWakeLock.getTag());
         }
 
         /**
diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
index 16484df9f..f90d936 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -76,6 +76,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -697,11 +698,7 @@
         mStageName = new File(backupManagerService.getDataDir(), packageName + ".stage");
         mNewStateName = new File(mStateDir, packageName + ".new");
 
-        // don't stage the 'android' package where the wallpaper data lives.  this is
-        // an optimization: we know there's no widget data hosted/published by that
-        // package, and this way we avoid doing a spurious copy of MB-sized wallpaper
-        // data following the download.
-        boolean staging = !packageName.equals(PLATFORM_PACKAGE_NAME);
+        boolean staging = shouldStageBackupData(packageName);
         ParcelFileDescriptor stage;
         File downloadFile = (staging) ? mStageName : mBackupDataName;
         boolean startedAgentRestore = false;
@@ -768,8 +765,7 @@
             startedAgentRestore = true;
             mAgent.doRestoreWithExcludedKeys(mBackupData, appVersionCode, mNewState,
                     mEphemeralOpToken, backupManagerService.getBackupManagerBinder(),
-                    mExcludedKeys.containsKey(packageName)
-                            ? new ArrayList<>(mExcludedKeys.get(packageName)) : null);
+                    new ArrayList<>(getExcludedKeysForPackage(packageName)));
         } catch (Exception e) {
             Slog.e(TAG, "Unable to call app for restore: " + packageName, e);
             EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
@@ -785,9 +781,24 @@
     }
 
     @VisibleForTesting
+    boolean shouldStageBackupData(String packageName) {
+        // Backup data is staged for 2 reasons:
+        // 1. We might need to exclude keys from the data before passing it to the agent
+        // 2. Widget metadata needs to be separated from the rest to be handled separately
+        // But 'android' package doesn't contain widget metadata so we want to skip staging for it
+        // when there are no keys to be excluded either.
+        return !packageName.equals(PLATFORM_PACKAGE_NAME) ||
+                !getExcludedKeysForPackage(PLATFORM_PACKAGE_NAME).isEmpty();
+    }
+
+    private Set<String> getExcludedKeysForPackage(String packageName) {
+        return mExcludedKeys.getOrDefault(packageName, Collections.emptySet());
+    }
+
+    @VisibleForTesting
     void filterExcludedKeys(String packageName, BackupDataInput in, BackupDataOutput out)
             throws Exception {
-        Set<String> excludedKeysForPackage = mExcludedKeys.get(packageName);
+        Set<String> excludedKeysForPackage = getExcludedKeysForPackage(packageName);
 
         byte[] buffer = new byte[8192]; // will grow when needed
         while (in.readNextHeader()) {
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 8eca62a..5602d1a8 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -45,7 +45,12 @@
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.Handler;
 import android.os.IBinder;
+import android.os.ICancellationSignal;
+import android.os.Looper;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ShellCallback;
@@ -55,8 +60,11 @@
 import android.provider.DeviceConfig.Properties;
 import android.provider.Settings;
 import android.service.contentcapture.ActivityEvent.ActivityEventType;
+import android.service.contentcapture.IDataShareCallback;
+import android.service.contentcapture.IDataShareReadAdapter;
 import android.util.ArraySet;
 import android.util.LocalLog;
+import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
@@ -64,7 +72,10 @@
 import android.view.contentcapture.ContentCaptureHelper;
 import android.view.contentcapture.ContentCaptureManager;
 import android.view.contentcapture.DataRemovalRequest;
+import android.view.contentcapture.DataShareRequest;
+import android.view.contentcapture.DataShareWriteAdapter;
 import android.view.contentcapture.IContentCaptureManager;
+import android.view.contentcapture.IDataShareWriteAdapter;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.infra.AbstractRemoteService;
@@ -77,9 +88,17 @@
 import com.android.server.infra.FrameworkResourcesServiceNameResolver;
 
 import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
 
 /**
  * A service used to observe the contents of the screen.
@@ -91,9 +110,13 @@
 public final class ContentCaptureManagerService extends
         AbstractMasterSystemService<ContentCaptureManagerService, ContentCapturePerUserService> {
 
+    private static final String TAG = ContentCaptureManagerService.class.getSimpleName();
     static final String RECEIVER_BUNDLE_EXTRA_SESSIONS = "sessions";
 
     private static final int MAX_TEMP_SERVICE_DURATION_MS = 1_000 * 60 * 2; // 2 minutes
+    private static final int MAX_DATA_SHARE_FILE_DESCRIPTORS_TTL_MS =  1_000 * 60 * 5; // 5 minutes
+    private static final int MAX_CONCURRENT_FILE_SHARING_REQUESTS = 10;
+    private static final int DATA_SHARE_BYTE_BUFFER_LENGTH = 1_024;
 
     private final LocalService mLocalService = new LocalService();
 
@@ -126,6 +149,12 @@
     @GuardedBy("mLock") int mDevCfgLogHistorySize;
     @GuardedBy("mLock") int mDevCfgIdleUnbindTimeoutMs;
 
+    private final Executor mDataShareExecutor = Executors.newCachedThreadPool();
+    private final Handler mHandler = new Handler(Looper.getMainLooper());
+
+    @GuardedBy("mLock")
+    private final Set<String> mPackagesWithShareRequests = new HashSet<>();
+
     final GlobalContentCaptureOptions mGlobalContentCaptureOptions =
             new GlobalContentCaptureOptions();
 
@@ -140,11 +169,11 @@
         setDeviceConfigProperties();
 
         if (mDevCfgLogHistorySize > 0) {
-            if (debug) Slog.d(mTag, "log history size: " + mDevCfgLogHistorySize);
+            if (debug) Slog.d(TAG, "log history size: " + mDevCfgLogHistorySize);
             mRequestsHistory = new LocalLog(mDevCfgLogHistorySize);
         } else {
             if (debug) {
-                Slog.d(mTag, "disabled log history because size is " + mDevCfgLogHistorySize);
+                Slog.d(TAG, "disabled log history because size is " + mDevCfgLogHistorySize);
             }
             mRequestsHistory = null;
         }
@@ -155,7 +184,7 @@
             final boolean disabled = !isEnabledBySettings(userId);
             // Sets which services are disabled by settings
             if (disabled) {
-                Slog.i(mTag, "user " + userId + " disabled by settings");
+                Slog.i(TAG, "user " + userId + " disabled by settings");
                 if (mDisabledBySettings == null) {
                     mDisabledBySettings = new SparseBooleanArray(1);
                 }
@@ -218,7 +247,7 @@
 
     @Override // from AbstractMasterSystemService
     protected void enforceCallingPermissionForManagement() {
-        getContext().enforceCallingPermission(MANAGE_CONTENT_CAPTURE, mTag);
+        getContext().enforceCallingPermission(MANAGE_CONTENT_CAPTURE, TAG);
     }
 
     @Override // from AbstractMasterSystemService
@@ -242,7 +271,7 @@
                         isEnabledBySettings(userId));
                 return;
             default:
-                Slog.w(mTag, "Unexpected property (" + property + "); updating cache instead");
+                Slog.w(TAG, "Unexpected property (" + property + "); updating cache instead");
         }
     }
 
@@ -279,7 +308,7 @@
                     setFineTuneParamsFromDeviceConfig();
                     return;
                 default:
-                    Slog.i(mTag, "Ignoring change on " + key);
+                    Slog.i(TAG, "Ignoring change on " + key);
             }
         }
     }
@@ -306,7 +335,7 @@
                     ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_UNBIND_TIMEOUT,
                     (int) AbstractRemoteService.PERMANENT_BOUND_TIMEOUT_MS);
             if (verbose) {
-                Slog.v(mTag, "setFineTuneParamsFromDeviceConfig(): "
+                Slog.v(TAG, "setFineTuneParamsFromDeviceConfig(): "
                         + "bufferSize=" + mDevCfgMaxBufferSize
                         + ", idleFlush=" + mDevCfgIdleFlushingFrequencyMs
                         + ", textFluxh=" + mDevCfgTextChangeFlushingFrequencyMs
@@ -325,7 +354,7 @@
         verbose = ContentCaptureHelper.sVerbose;
         debug = ContentCaptureHelper.sDebug;
         if (verbose) {
-            Slog.v(mTag, "setLoggingLevelFromDeviceConfig(): level=" + mDevCfgLoggingLevel
+            Slog.v(TAG, "setLoggingLevelFromDeviceConfig(): level=" + mDevCfgLoggingLevel
                     + ", debug=" + debug + ", verbose=" + verbose);
         }
     }
@@ -340,7 +369,7 @@
 
     private void setDisabledByDeviceConfig(@Nullable String explicitlyEnabled) {
         if (verbose) {
-            Slog.v(mTag, "setDisabledByDeviceConfig(): explicitlyEnabled=" + explicitlyEnabled);
+            Slog.v(TAG, "setDisabledByDeviceConfig(): explicitlyEnabled=" + explicitlyEnabled);
         }
         final List<UserInfo> users = getSupportedUsers();
 
@@ -355,17 +384,17 @@
         synchronized (mLock) {
             if (mDisabledByDeviceConfig == newDisabledValue) {
                 if (verbose) {
-                    Slog.v(mTag, "setDisabledByDeviceConfig(): already " + newDisabledValue);
+                    Slog.v(TAG, "setDisabledByDeviceConfig(): already " + newDisabledValue);
                 }
                 return;
             }
             mDisabledByDeviceConfig = newDisabledValue;
 
-            Slog.i(mTag, "setDisabledByDeviceConfig(): set to " + mDisabledByDeviceConfig);
+            Slog.i(TAG, "setDisabledByDeviceConfig(): set to " + mDisabledByDeviceConfig);
             for (int i = 0; i < users.size(); i++) {
                 final int userId = users.get(i).id;
                 boolean disabled = mDisabledByDeviceConfig || isDisabledBySettingsLocked(userId);
-                Slog.i(mTag, "setDisabledByDeviceConfig(): updating service for user "
+                Slog.i(TAG, "setDisabledByDeviceConfig(): updating service for user "
                         + userId + " to " + (disabled ? "'disabled'" : "'enabled'"));
                 updateCachedServiceLocked(userId, disabled);
             }
@@ -381,16 +410,16 @@
             final boolean alreadyEnabled = !mDisabledBySettings.get(userId);
             if (!(enabled ^ alreadyEnabled)) {
                 if (debug) {
-                    Slog.d(mTag, "setContentCaptureFeatureEnabledForUser(): already " + enabled);
+                    Slog.d(TAG, "setContentCaptureFeatureEnabledForUser(): already " + enabled);
                 }
                 return;
             }
             if (enabled) {
-                Slog.i(mTag, "setContentCaptureFeatureEnabled(): enabling service for user "
+                Slog.i(TAG, "setContentCaptureFeatureEnabled(): enabling service for user "
                         + userId);
                 mDisabledBySettings.delete(userId);
             } else {
-                Slog.i(mTag, "setContentCaptureFeatureEnabled(): disabling service for user "
+                Slog.i(TAG, "setContentCaptureFeatureEnabled(): disabling service for user "
                         + userId);
                 mDisabledBySettings.put(userId, true);
             }
@@ -401,7 +430,7 @@
 
     // Called by Shell command.
     void destroySessions(@UserIdInt int userId, @NonNull IResultReceiver receiver) {
-        Slog.i(mTag, "destroySessions() for userId " + userId);
+        Slog.i(TAG, "destroySessions() for userId " + userId);
         enforceCallingPermissionForManagement();
 
         synchronized (mLock) {
@@ -424,7 +453,7 @@
 
     // Called by Shell command.
     void listSessions(int userId, IResultReceiver receiver) {
-        Slog.i(mTag, "listSessions() for userId " + userId);
+        Slog.i(TAG, "listSessions() for userId " + userId);
         enforceCallingPermissionForManagement();
 
         final Bundle resultData = new Bundle();
@@ -471,14 +500,14 @@
         final int callingUid = Binder.getCallingUid();
         final String serviceName = mServiceNameResolver.getServiceName(userId);
         if (serviceName == null) {
-            Slog.e(mTag, methodName + ": called by UID " + callingUid
+            Slog.e(TAG, methodName + ": called by UID " + callingUid
                     + ", but there's no service set for user " + userId);
             return false;
         }
 
         final ComponentName serviceComponent = ComponentName.unflattenFromString(serviceName);
         if (serviceComponent == null) {
-            Slog.w(mTag, methodName + ": invalid service name: " + serviceName);
+            Slog.w(TAG, methodName + ": invalid service name: " + serviceName);
             return false;
         }
 
@@ -489,11 +518,11 @@
         try {
             serviceUid = pm.getPackageUidAsUser(servicePackageName, UserHandle.getCallingUserId());
         } catch (NameNotFoundException e) {
-            Slog.w(mTag, methodName + ": could not verify UID for " + serviceName);
+            Slog.w(TAG, methodName + ": could not verify UID for " + serviceName);
             return false;
         }
         if (callingUid != serviceUid) {
-            Slog.e(mTag, methodName + ": called by UID " + callingUid + ", but service UID is "
+            Slog.e(TAG, methodName + ": called by UID " + callingUid + ", but service UID is "
                     + serviceUid);
             return false;
         }
@@ -516,7 +545,7 @@
             try {
                 result.send(RESULT_CODE_SECURITY_EXCEPTION, bundleFor(e.getMessage()));
             } catch (RemoteException e2) {
-                Slog.w(mTag, "Unable to send security exception (" + e + "): ", e2);
+                Slog.w(TAG, "Unable to send security exception (" + e + "): ", e2);
             }
         }
         return true;
@@ -601,7 +630,7 @@
             try {
                 result.send(RESULT_CODE_OK, bundleFor(connectedServiceComponentName));
             } catch (RemoteException e) {
-                Slog.w(mTag, "Unable to send service component name: " + e);
+                Slog.w(TAG, "Unable to send service component name: " + e);
             }
         }
 
@@ -618,6 +647,35 @@
         }
 
         @Override
+        public void shareData(@NonNull DataShareRequest request,
+                @NonNull ICancellationSignal clientCancellationSignal,
+                @NonNull IDataShareWriteAdapter clientAdapter) {
+            Preconditions.checkNotNull(request);
+            Preconditions.checkNotNull(clientAdapter);
+
+            assertCalledByPackageOwner(request.getPackageName());
+
+            final int userId = UserHandle.getCallingUserId();
+            synchronized (mLock) {
+                final ContentCapturePerUserService service = getServiceForUserLocked(userId);
+
+                if (mPackagesWithShareRequests.size() >= MAX_CONCURRENT_FILE_SHARING_REQUESTS
+                        || mPackagesWithShareRequests.contains(request.getPackageName())) {
+                    try {
+                        clientAdapter.error(DataShareWriteAdapter.ERROR_CONCURRENT_REQUEST);
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "Failed to send error message to client");
+                    }
+                    return;
+                }
+
+                service.onDataSharedLocked(request,
+                        new DataShareCallbackDelegate(request, clientCancellationSignal,
+                                clientAdapter, ContentCaptureManagerService.this));
+            }
+        }
+
+        @Override
         public void isContentCaptureFeatureEnabled(@NonNull IResultReceiver result) {
             boolean enabled;
             synchronized (mLock) {
@@ -632,7 +690,7 @@
             try {
                 result.send(enabled ? RESULT_CODE_TRUE : RESULT_CODE_FALSE, /* resultData= */null);
             } catch (RemoteException e) {
-                Slog.w(mTag, "Unable to send isContentCaptureFeatureEnabled(): " + e);
+                Slog.w(TAG, "Unable to send isContentCaptureFeatureEnabled(): " + e);
             }
         }
 
@@ -652,7 +710,7 @@
             try {
                 result.send(RESULT_CODE_OK, bundleFor(componentName));
             } catch (RemoteException e) {
-                Slog.w(mTag, "Unable to send getServiceSettingsIntent(): " + e);
+                Slog.w(TAG, "Unable to send getServiceSettingsIntent(): " + e);
             }
         }
 
@@ -673,13 +731,13 @@
             try {
                 result.send(RESULT_CODE_OK, bundleFor(conditions));
             } catch (RemoteException e) {
-                Slog.w(mTag, "Unable to send getServiceComponentName(): " + e);
+                Slog.w(TAG, "Unable to send getServiceComponentName(): " + e);
             }
         }
 
         @Override
         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            if (!DumpUtils.checkDumpPermission(getContext(), mTag, pw)) return;
+            if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
 
             boolean showHistory = true;
             if (args != null) {
@@ -692,7 +750,7 @@
                             pw.println("Usage: dumpsys content_capture [--no-history]");
                             return;
                         default:
-                            Slog.w(mTag, "Ignoring invalid dump arg: " + arg);
+                            Slog.w(TAG, "Ignoring invalid dump arg: " + arg);
                     }
                 }
             }
@@ -789,7 +847,7 @@
                     final ComponentName componentName =
                             ComponentName.unflattenFromString(serviceName);
                     if (componentName == null) {
-                        Slog.w(mTag, "setServiceInfo(): invalid name: " + serviceName);
+                        Slog.w(TAG, "setServiceInfo(): invalid name: " + serviceName);
                         mServicePackages.remove(userId);
                     } else {
                         mServicePackages.put(userId, componentName.getPackageName());
@@ -815,7 +873,7 @@
                             && packageName.equals(mServicePackages.get(userId))) {
                         // No components whitelisted either, but let it go because it's the
                         // service's own package
-                        if (verbose) Slog.v(mTag, "getOptionsForPackage() lite for " + packageName);
+                        if (verbose) Slog.v(TAG, "getOptionsForPackage() lite for " + packageName);
                         return new ContentCaptureOptions(mDevCfgLoggingLevel);
                     }
                 }
@@ -824,7 +882,7 @@
             // Restrict what temporary services can whitelist
             if (Build.IS_USER && mServiceNameResolver.isTemporary(userId)) {
                 if (!packageName.equals(mServicePackages.get(userId))) {
-                    Slog.w(mTag, "Ignoring package " + packageName + " while using temporary "
+                    Slog.w(TAG, "Ignoring package " + packageName + " while using temporary "
                             + "service " + mServicePackages.get(userId));
                     return null;
                 }
@@ -833,7 +891,7 @@
             if (!packageWhitelisted && whitelistedComponents == null) {
                 // No can do!
                 if (verbose) {
-                    Slog.v(mTag, "getOptionsForPackage(" + packageName + "): not whitelisted");
+                    Slog.v(TAG, "getOptionsForPackage(" + packageName + "): not whitelisted");
                 }
                 return null;
             }
@@ -842,7 +900,7 @@
                     mDevCfgMaxBufferSize, mDevCfgIdleFlushingFrequencyMs,
                     mDevCfgTextChangeFlushingFrequencyMs, mDevCfgLogHistorySize,
                     whitelistedComponents);
-            if (verbose) Slog.v(mTag, "getOptionsForPackage(" + packageName + "): " + options);
+            if (verbose) Slog.v(TAG, "getOptionsForPackage(" + packageName + "): " + options);
             return options;
         }
 
@@ -860,4 +918,226 @@
             }
         }
     }
+
+    private static class DataShareCallbackDelegate extends IDataShareCallback.Stub {
+
+        @NonNull private final DataShareRequest mDataShareRequest;
+        @NonNull
+        private final WeakReference<ICancellationSignal> mClientCancellationSignalReference;
+        @NonNull private final WeakReference<IDataShareWriteAdapter> mClientAdapterReference;
+        @NonNull private final WeakReference<ContentCaptureManagerService> mParentServiceReference;
+
+        DataShareCallbackDelegate(@NonNull DataShareRequest dataShareRequest,
+                @NonNull ICancellationSignal clientCancellationSignal,
+                @NonNull IDataShareWriteAdapter clientAdapter,
+                ContentCaptureManagerService parentService) {
+            mDataShareRequest = dataShareRequest;
+            mClientCancellationSignalReference = new WeakReference<>(clientCancellationSignal);
+            mClientAdapterReference = new WeakReference<>(clientAdapter);
+            mParentServiceReference = new WeakReference<>(parentService);
+        }
+
+        @Override
+        public void accept(ICancellationSignal serviceCancellationSignal,
+                IDataShareReadAdapter serviceAdapter) throws RemoteException {
+            Slog.i(TAG, "Data share request accepted by Content Capture service");
+
+            final ContentCaptureManagerService parentService = mParentServiceReference.get();
+            final ICancellationSignal clientCancellationSignal =
+                    mClientCancellationSignalReference.get();
+            final IDataShareWriteAdapter clientAdapter = mClientAdapterReference.get();
+            if (parentService == null || clientCancellationSignal == null
+                    || clientAdapter == null) {
+                Slog.w(TAG, "Can't fulfill accept() request, because remote objects have been "
+                        + "GC'ed");
+                return;
+            }
+
+            Pair<ParcelFileDescriptor, ParcelFileDescriptor> clientPipe = createPipe();
+            if (clientPipe == null) {
+                clientAdapter.error(DataShareWriteAdapter.ERROR_UNKNOWN);
+                serviceAdapter.error(DataShareWriteAdapter.ERROR_UNKNOWN);
+                return;
+            }
+
+            ParcelFileDescriptor sourceIn = clientPipe.second;
+            ParcelFileDescriptor sinkIn = clientPipe.first;
+
+            Pair<ParcelFileDescriptor, ParcelFileDescriptor> servicePipe = createPipe();
+            if (servicePipe == null) {
+                bestEffortCloseFileDescriptors(sourceIn, sinkIn);
+
+                clientAdapter.error(DataShareWriteAdapter.ERROR_UNKNOWN);
+                serviceAdapter.error(DataShareWriteAdapter.ERROR_UNKNOWN);
+                return;
+            }
+
+            ParcelFileDescriptor sourceOut = servicePipe.second;
+            ParcelFileDescriptor sinkOut = servicePipe.first;
+
+            ICancellationSignal cancellationSignalTransport =
+                    CancellationSignal.createTransport();
+            parentService.mPackagesWithShareRequests.add(mDataShareRequest.getPackageName());
+
+            clientAdapter.write(sourceIn);
+            serviceAdapter.start(sinkOut, cancellationSignalTransport);
+
+            CancellationSignal cancellationSignal =
+                    CancellationSignal.fromTransport(cancellationSignalTransport);
+
+            cancellationSignal.setOnCancelListener(() -> {
+                try {
+                    clientCancellationSignal.cancel();
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Failed to propagate cancel operation to the caller", e);
+                }
+            });
+
+            // File descriptor received by the client app will be a copy of the current one. Close
+            // the one that belongs to the system server, so there's only 1 open left for the
+            // current pipe.
+            bestEffortCloseFileDescriptor(sourceIn);
+
+            parentService.mDataShareExecutor.execute(() -> {
+                try (InputStream fis =
+                             new ParcelFileDescriptor.AutoCloseInputStream(sinkIn);
+                     OutputStream fos =
+                             new ParcelFileDescriptor.AutoCloseOutputStream(sourceOut)) {
+
+                    byte[] byteBuffer = new byte[DATA_SHARE_BYTE_BUFFER_LENGTH];
+                    while (true) {
+                        int readBytes = fis.read(byteBuffer);
+
+                        if (readBytes == -1) {
+                            break;
+                        }
+
+                        fos.write(byteBuffer, 0 /* offset */, readBytes);
+                    }
+                } catch (IOException e) {
+                    Slog.e(TAG, "Failed to pipe client and service streams", e);
+                }
+            });
+
+            parentService.mHandler.postDelayed(() ->
+                    enforceDataSharingTtl(
+                            sourceIn,
+                            sinkIn,
+                            sourceOut,
+                            sinkOut,
+                            new WeakReference<>(serviceCancellationSignal)),
+                    MAX_DATA_SHARE_FILE_DESCRIPTORS_TTL_MS);
+        }
+
+        @Override
+        public void reject() throws RemoteException {
+            Slog.i(TAG, "Data share request rejected by Content Capture service");
+
+            IDataShareWriteAdapter clientAdapter = mClientAdapterReference.get();
+            if (clientAdapter == null) {
+                Slog.w(TAG, "Can't fulfill reject() request, because remote objects have been "
+                        + "GC'ed");
+                return;
+            }
+
+            clientAdapter.rejected();
+        }
+
+        private void enforceDataSharingTtl(ParcelFileDescriptor sourceIn,
+                ParcelFileDescriptor sinkIn,
+                ParcelFileDescriptor sourceOut,
+                ParcelFileDescriptor sinkOut,
+                WeakReference<ICancellationSignal> serviceCancellationSignalReference) {
+
+            final ContentCaptureManagerService parentService = mParentServiceReference.get();
+            final ICancellationSignal clientCancellationSignal =
+                    mClientCancellationSignalReference.get();
+            final ICancellationSignal serviceCancellationSignal =
+                    serviceCancellationSignalReference.get();
+            if (parentService == null || clientCancellationSignal == null
+                    || serviceCancellationSignal == null) {
+                Slog.w(TAG, "Can't enforce data sharing TTL, because remote objects have been "
+                        + "GC'ed");
+                return;
+            }
+
+            synchronized (parentService.mLock) {
+                parentService.mPackagesWithShareRequests
+                        .remove(mDataShareRequest.getPackageName());
+
+                // Interaction finished successfully <=> all data has been written to Content
+                // Capture Service. If it hasn't been read successfully, service would be able
+                // to signal through the cancellation signal.
+                boolean finishedSuccessfully = !sinkIn.getFileDescriptor().valid()
+                        && !sourceOut.getFileDescriptor().valid();
+
+                if (finishedSuccessfully) {
+                    Slog.i(TAG, "Content capture data sharing session terminated "
+                            + "successfully for package '"
+                            + mDataShareRequest.getPackageName()
+                            + "'");
+                } else {
+                    Slog.i(TAG, "Reached the timeout of Content Capture data sharing session "
+                            + "for package '"
+                            + mDataShareRequest.getPackageName()
+                            + "', terminating the pipe.");
+                }
+
+                // Ensure all the descriptors are closed after the session.
+                bestEffortCloseFileDescriptors(sourceIn, sinkIn, sourceOut, sinkOut);
+
+                if (!finishedSuccessfully) {
+                    try {
+                        clientCancellationSignal.cancel();
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "Failed to cancel() the client operation", e);
+                    }
+                    try {
+                        serviceCancellationSignal.cancel();
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "Failed to cancel() the service operation", e);
+                    }
+                }
+            }
+        }
+
+        private Pair<ParcelFileDescriptor, ParcelFileDescriptor> createPipe() {
+            ParcelFileDescriptor[] fileDescriptors;
+            try {
+                fileDescriptors = ParcelFileDescriptor.createPipe();
+            } catch (IOException e) {
+                Slog.e(TAG, "Failed to create a content capture data-sharing pipe", e);
+                return null;
+            }
+
+            if (fileDescriptors.length != 2) {
+                Slog.e(TAG, "Failed to create a content capture data-sharing pipe, "
+                        + "unexpected number of file descriptors");
+                return null;
+            }
+
+            if (!fileDescriptors[0].getFileDescriptor().valid()
+                    || !fileDescriptors[1].getFileDescriptor().valid()) {
+                Slog.e(TAG, "Failed to create a content capture data-sharing pipe, didn't "
+                        + "receive a pair of valid file descriptors.");
+                return null;
+            }
+
+            return Pair.create(fileDescriptors[0], fileDescriptors[1]);
+        }
+
+        private void bestEffortCloseFileDescriptor(ParcelFileDescriptor fd) {
+            try {
+                fd.close();
+            } catch (IOException e) {
+                Slog.e(TAG, "Failed to close a file descriptor", e);
+            }
+        }
+
+        private void bestEffortCloseFileDescriptors(ParcelFileDescriptor... fds) {
+            for (ParcelFileDescriptor fd : fds) {
+                bestEffortCloseFileDescriptor(fd);
+            }
+        }
+    }
 }
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index a186d4e..0f1122e 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -54,6 +54,7 @@
 import android.service.contentcapture.ContentCaptureServiceInfo;
 import android.service.contentcapture.FlushMetrics;
 import android.service.contentcapture.IContentCaptureServiceCallback;
+import android.service.contentcapture.IDataShareCallback;
 import android.service.contentcapture.SnapshotData;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -63,6 +64,7 @@
 import android.util.StatsLog;
 import android.view.contentcapture.ContentCaptureCondition;
 import android.view.contentcapture.DataRemovalRequest;
+import android.view.contentcapture.DataShareRequest;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.IResultReceiver;
@@ -375,6 +377,16 @@
     }
 
     @GuardedBy("mLock")
+    public void onDataSharedLocked(@NonNull DataShareRequest request,
+            IDataShareCallback.Stub dataShareCallback) {
+        if (!isEnabledLocked()) {
+            return;
+        }
+        assertCallerLocked(request.getPackageName());
+        mRemoteService.onDataShareRequest(request, dataShareCallback);
+    }
+
+    @GuardedBy("mLock")
     @Nullable
     public ComponentName getServiceSettingsActivityLocked() {
         if (mInfo == null) return null;
diff --git a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
index 01d33b0..c16df0f 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
@@ -29,11 +29,13 @@
 import android.service.contentcapture.ActivityEvent;
 import android.service.contentcapture.IContentCaptureService;
 import android.service.contentcapture.IContentCaptureServiceCallback;
+import android.service.contentcapture.IDataShareCallback;
 import android.service.contentcapture.SnapshotData;
 import android.util.Slog;
 import android.util.StatsLog;
 import android.view.contentcapture.ContentCaptureContext;
 import android.view.contentcapture.DataRemovalRequest;
+import android.view.contentcapture.DataShareRequest;
 
 import com.android.internal.infra.AbstractMultiplePendingRequestsRemoteService;
 import com.android.internal.os.IResultReceiver;
@@ -145,6 +147,11 @@
                 mComponentName);
     }
 
+    public void onDataShareRequest(@NonNull DataShareRequest request,
+            @NonNull IDataShareCallback.Stub dataShareCallback) {
+        scheduleAsyncRequest((s) -> s.onDataShared(request, dataShareCallback));
+    }
+
     /**
      * Called by {@link ContentCaptureServerSession} to notify a high-level activity event.
      */
diff --git a/services/core/java/android/app/usage/UsageStatsManagerInternal.java b/services/core/java/android/app/usage/UsageStatsManagerInternal.java
index f3647602..a8be669 100644
--- a/services/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/services/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -16,10 +16,14 @@
 
 package android.app.usage;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.usage.UsageStatsManager.StandbyBuckets;
 import android.content.ComponentName;
+import android.content.LocusId;
 import android.content.res.Configuration;
+import android.os.IBinder;
 import android.os.UserHandle;
 import android.os.UserManager;
 
@@ -111,6 +115,20 @@
     public abstract void reportContentProviderUsage(String name, String pkgName,
             @UserIdInt int userId);
 
+
+    /**
+     * Reports locusId update for a given activity.
+     *
+     * @param activity The component name of the app.
+     * @param userId The user id of who uses the app.
+     * @param locusId The locusId a unique, stable id that identifies this activity.
+     * @param appToken ActivityRecord's appToken.
+     * {@link UsageEvents}
+     * @hide
+     */
+    public abstract void reportLocusUpdate(@NonNull ComponentName activity, @UserIdInt int userId,
+            @Nullable LocusId locusId, @NonNull IBinder appToken);
+
     /**
      * Prepares the UsageStatsService for shutdown.
      */
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index c3cc5de..27b6bfb 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -170,7 +170,7 @@
      * Return a List of all application packages that are installed on the
      * device, for a specific user. If flag GET_UNINSTALLED_PACKAGES has been
      * set, a list of all applications including those deleted with
-     * {@code DONT_DELETE_DATA} (partially installed apps with data directory)
+     * {@code DELETE_KEEP_DATA} (partially installed apps with data directory)
      * will be returned.
      *
      * @param flags Additional option flags to modify the data returned.
@@ -184,7 +184,7 @@
      *         information is retrieved from the list of uninstalled
      *         applications (which includes installed applications as well as
      *         applications with data directory i.e. applications which had been
-     *         deleted with {@code DONT_DELETE_DATA} flag set).
+     *         deleted with {@code DELETE_KEEP_DATA} flag set).
      */
     public abstract List<ApplicationInfo> getInstalledApplications(
             @ApplicationInfoFlags int flags, @UserIdInt int userId, int callingUid);
@@ -252,11 +252,23 @@
             String packageName, int userId);
 
     /**
+     * Do a straight uid lookup for the given package/application in the given user. This enforces
+     * app visibility rules and permissions. Call {@link #getPackageUidInternal} for the internal
+     * implementation.
+     * @deprecated Use {@link PackageManager#getPackageUid(String, int)}
+     * @return The app's uid, or < 0 if the package was not found in that user
+     */
+    @Deprecated
+    public abstract int getPackageUid(String packageName,
+            @PackageInfoFlags int flags, int userId);
+
+    /**
      * Do a straight uid lookup for the given package/application in the given user.
      * @see PackageManager#getPackageUidAsUser(String, int, int)
      * @return The app's uid, or < 0 if the package was not found in that user
+     * TODO(b/148235092): rename this to getPackageUid
      */
-    public abstract int getPackageUid(String packageName,
+    public abstract int getPackageUidInternal(String packageName,
             @PackageInfoFlags int flags, int userId);
 
     /**
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 1c9f5dc..d933e9d 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -64,6 +64,7 @@
 import android.net.ConnectionInfo;
 import android.net.ConnectivityManager;
 import android.net.ICaptivePortal;
+import android.net.IConnectivityDiagnosticsCallback;
 import android.net.IConnectivityManager;
 import android.net.IDnsResolver;
 import android.net.IIpConnectivityMetrics;
@@ -210,6 +211,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Comparator;
 import java.util.ConcurrentModificationException;
 import java.util.HashMap;
@@ -1622,7 +1624,8 @@
         return getNetworkCapabilitiesInternal(getNetworkAgentInfoForNetwork(network));
     }
 
-    private NetworkCapabilities networkCapabilitiesRestrictedForCallerPermissions(
+    @VisibleForTesting
+    NetworkCapabilities networkCapabilitiesRestrictedForCallerPermissions(
             NetworkCapabilities nc, int callerPid, int callerUid) {
         final NetworkCapabilities newNc = new NetworkCapabilities(nc);
         if (!checkSettingsPermission(callerPid, callerUid)) {
@@ -1632,9 +1635,24 @@
         if (newNc.getNetworkSpecifier() != null) {
             newNc.setNetworkSpecifier(newNc.getNetworkSpecifier().redact());
         }
+        newNc.setAdministratorUids(Collections.EMPTY_LIST);
+
+        maybeSanitizeLocationInfoForCaller(newNc, callerUid);
+
         return newNc;
     }
 
+    private void maybeSanitizeLocationInfoForCaller(
+            NetworkCapabilities nc, int callerUid) {
+        // TODO(b/142072839): Conditionally reset the owner UID if the following
+        // conditions are not met:
+        // 1. The destination app is the network owner
+        // 2. The destination app has the ACCESS_COARSE_LOCATION permission granted
+        // if target SDK<29 or otherwise has the ACCESS_FINE_LOCATION permission granted
+        // 3. The user's location toggle is on
+        nc.setOwnerUid(INVALID_UID);
+    }
+
     private LinkProperties linkPropertiesRestrictedForCallerPermissions(
             LinkProperties lp, int callerPid, int callerUid) {
         if (lp == null) return new LinkProperties();
@@ -1662,6 +1680,10 @@
         if (!checkSettingsPermission()) {
             nc.setSingleUid(Binder.getCallingUid());
         }
+        nc.setAdministratorUids(Collections.EMPTY_LIST);
+
+        // Clear owner UID; this can never come from an app.
+        nc.setOwnerUid(INVALID_UID);
     }
 
     private void restrictBackgroundRequestForCaller(NetworkCapabilities nc) {
@@ -2940,6 +2962,11 @@
         public int getInterfaceVersion() {
             return this.VERSION;
         }
+
+        @Override
+        public String getInterfaceHash() {
+            return this.HASH;
+        }
     }
 
     private boolean networkRequiresPrivateDnsValidation(NetworkAgentInfo nai) {
@@ -5798,7 +5825,7 @@
         }
 
         final Set<UidRange> ranges = nai.networkCapabilities.getUids();
-        final int vpnAppUid = nai.networkCapabilities.getEstablishingVpnAppUid();
+        final int vpnAppUid = nai.networkCapabilities.getOwnerUid();
         // TODO: this create a window of opportunity for apps to receive traffic between the time
         // when the old rules are removed and the time when new rules are added. To fix this,
         // make eBPF support two whitelisted interfaces so here new rules can be added before the
@@ -5997,7 +6024,7 @@
         if (nc == null || lp == null) return false;
         return nai.isVPN()
                 && !nai.networkAgentConfig.allowBypass
-                && nc.getEstablishingVpnAppUid() != Process.SYSTEM_UID
+                && nc.getOwnerUid() != Process.SYSTEM_UID
                 && lp.getInterfaceName() != null
                 && (lp.hasIPv4DefaultRoute() || lp.hasIPv6DefaultRoute());
     }
@@ -6045,12 +6072,10 @@
             // TODO Fix this window by computing an accurate diff on Set<UidRange>, so the old range
             // to be removed will never overlap with the new range to be added.
             if (wasFiltering && !prevRanges.isEmpty()) {
-                mPermissionMonitor.onVpnUidRangesRemoved(iface, prevRanges,
-                        prevNc.getEstablishingVpnAppUid());
+                mPermissionMonitor.onVpnUidRangesRemoved(iface, prevRanges, prevNc.getOwnerUid());
             }
             if (shouldFilter && !newRanges.isEmpty()) {
-                mPermissionMonitor.onVpnUidRangesAdded(iface, newRanges,
-                        newNc.getEstablishingVpnAppUid());
+                mPermissionMonitor.onVpnUidRangesAdded(iface, newRanges, newNc.getOwnerUid());
             }
         } catch (Exception e) {
             // Never crash!
@@ -7311,4 +7336,20 @@
             return mTNS;
         }
     }
+
+    @Override
+    public void registerConnectivityDiagnosticsCallback(
+            @NonNull IConnectivityDiagnosticsCallback callback, @NonNull NetworkRequest request) {
+        // TODO(b/146444622): implement register IConnectivityDiagnosticsCallback functionality
+        throw new UnsupportedOperationException(
+                "registerConnectivityDiagnosticsCallback not yet implemented");
+    }
+
+    @Override
+    public void unregisterConnectivityDiagnosticsCallback(
+            @NonNull IConnectivityDiagnosticsCallback callback) {
+        // TODO(b/146444622): implement register IConnectivityDiagnosticsCallback functionality
+        throw new UnsupportedOperationException(
+                "unregisterConnectivityDiagnosticsCallback not yet implemented");
+    }
 }
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 003525c9..f1f2d2a 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -52,6 +52,7 @@
 import android.location.ILocationManager;
 import android.location.Location;
 import android.location.LocationManager;
+import android.location.LocationManagerInternal;
 import android.location.LocationRequest;
 import android.location.LocationTime;
 import android.os.Binder;
@@ -103,6 +104,7 @@
 import com.android.server.location.MockableLocationProvider;
 import com.android.server.location.PassiveProvider;
 import com.android.server.location.UserInfoStore;
+import com.android.server.location.gnss.GnssManagerService;
 import com.android.server.pm.permission.PermissionManagerServiceInternal;
 
 import java.io.ByteArrayOutputStream;
@@ -118,6 +120,7 @@
 import java.util.Map.Entry;
 import java.util.Objects;
 import java.util.Set;
+import java.util.TreeMap;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.TimeUnit;
 
@@ -132,11 +135,12 @@
      */
     public static class Lifecycle extends SystemService {
 
-        private LocationManagerService mService;
+        private final LocationManagerService mService;
 
         public Lifecycle(Context context) {
             super(context);
             mService = new LocationManagerService(context);
+            LocalServices.addService(LocationManagerInternal.class, mService.new LocalService());
         }
 
         @Override
@@ -464,7 +468,7 @@
         mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
 
         for (LocationProviderManager manager : mProviderManagers) {
-            manager.onUseableChangedLocked(userId);
+            manager.onEnabledChangedLocked(userId);
         }
     }
 
@@ -632,10 +636,10 @@
         for (LocationProviderManager manager : mProviderManagers) {
             // update LOCATION_PROVIDERS_ALLOWED for best effort backwards compatibility
             mSettingsStore.setLocationProviderAllowed(manager.getName(),
-                    manager.isUseable(newUserId), newUserId);
+                    manager.isEnabled(newUserId), newUserId);
 
-            manager.onUseableChangedLocked(oldUserId);
-            manager.onUseableChangedLocked(newUserId);
+            manager.onEnabledChangedLocked(oldUserId);
+            manager.onEnabledChangedLocked(newUserId);
         }
     }
 
@@ -649,22 +653,22 @@
         // acquiring mLock makes operations on mProvider atomic, but is otherwise unnecessary
         protected final MockableLocationProvider mProvider;
 
-        // useable state for parent user ids, no entry implies false. location state is only kept
+        // enabled state for parent user ids, no entry implies false. location state is only kept
         // for parent user ids, the location state for a profile user id is assumed to be the same
         // as for the parent. if querying this structure, ensure that the user id being used is a
         // parent id or the results may be incorrect.
         @GuardedBy("mLock")
-        private final SparseArray<Boolean> mUseable;
+        private final SparseArray<Boolean> mEnabled;
 
         private LocationProviderManager(String name) {
             mName = name;
-            mUseable = new SparseArray<>(1);
+            mEnabled = new SparseArray<>(1);
 
             // initialize last since this lets our reference escape
             mProvider = new MockableLocationProvider(mContext, mLock, this);
 
-            // we can assume all users start with unuseable location state since the initial state
-            // of all providers is disabled. no need to initialize mUseable further.
+            // we can assume all users start with disabled location state since the initial state
+            // of all providers is disabled. no need to initialize mEnabled further.
         }
 
         public String getName() {
@@ -692,13 +696,13 @@
             return mProvider.getState().properties;
         }
 
-        public void setMockProviderEnabled(boolean enabled) {
+        public void setMockProviderAllowed(boolean enabled) {
             synchronized (mLock) {
                 if (!mProvider.isMock()) {
                     throw new IllegalArgumentException(mName + " provider is not a test provider");
                 }
 
-                mProvider.setMockProviderEnabled(enabled);
+                mProvider.setMockProviderAllowed(enabled);
             }
         }
 
@@ -759,7 +763,7 @@
                 return;
             }
 
-            if (!GPS_PROVIDER.equals(mName) || !isUseable()) {
+            if (!GPS_PROVIDER.equals(mName) || !isEnabled()) {
                 Slog.w(TAG, "reportLocationBatch() called without user permission");
                 return;
             }
@@ -770,30 +774,33 @@
         @GuardedBy("mLock")
         @Override
         public void onStateChanged(State oldState, State newState) {
-            if (oldState.enabled != newState.enabled) {
+            if (oldState.allowed != newState.allowed) {
                 // it would be more correct to call this for all users, but we know this can
                 // only affect the current user since providers are disabled for non-current
                 // users
-                onUseableChangedLocked(mUserInfoStore.getCurrentUserId());
+                onEnabledChangedLocked(mUserInfoStore.getCurrentUserId());
             }
         }
 
-        public boolean isUseable() {
-            return isUseable(mUserInfoStore.getCurrentUserId());
+        public void requestSetAllowed(boolean allowed) {
+            mProvider.requestSetAllowed(allowed);
         }
 
-        public boolean isUseable(int userId) {
+        public boolean isEnabled() {
+            return isEnabled(mUserInfoStore.getCurrentUserId());
+        }
+
+        public boolean isEnabled(int userId) {
             synchronized (mLock) {
                 // normalize user id to always refer to parent since profile state is always the
                 // same as parent state
                 userId = mUserInfoStore.getParentUserId(userId);
-
-                return mUseable.get(userId, Boolean.FALSE);
+                return mEnabled.get(userId, Boolean.FALSE);
             }
         }
 
         @GuardedBy("mLock")
-        public void onUseableChangedLocked(int userId) {
+        public void onEnabledChangedLocked(int userId) {
             if (userId == UserHandle.USER_NULL) {
                 // only used during initialization - we don't care about the null user
                 return;
@@ -803,36 +810,36 @@
             // as parent state
             userId = mUserInfoStore.getParentUserId(userId);
 
-            // if any property that contributes to "useability" here changes state, it MUST result
-            // in a direct or indrect call to onUseableChangedLocked. this allows the provider to
+            // if any property that contributes to "enabled" here changes state, it MUST result
+            // in a direct or indrect call to onEnabledChangedLocked. this allows the provider to
             // guarantee that it will always eventually reach the correct state.
-            boolean useable = (userId == mUserInfoStore.getCurrentUserId())
-                    && mSettingsStore.isLocationEnabled(userId) && mProvider.getState().enabled;
+            boolean enabled = (userId == mUserInfoStore.getCurrentUserId())
+                    && mSettingsStore.isLocationEnabled(userId) && mProvider.getState().allowed;
 
-            if (useable == isUseable(userId)) {
+            if (enabled == isEnabled(userId)) {
                 return;
             }
 
-            mUseable.put(userId, useable);
+            mEnabled.put(userId, enabled);
 
             if (D) {
-                Log.d(TAG, "[u" + userId + "] " + mName + " provider useable = " + useable);
+                Log.d(TAG, "[u" + userId + "] " + mName + " provider enabled = " + enabled);
             }
 
             // fused and passive provider never get public updates for legacy reasons
             if (!FUSED_PROVIDER.equals(mName) && !PASSIVE_PROVIDER.equals(mName)) {
                 // update LOCATION_PROVIDERS_ALLOWED for best effort backwards compatibility
-                mSettingsStore.setLocationProviderAllowed(mName, useable, userId);
+                mSettingsStore.setLocationProviderAllowed(mName, enabled, userId);
 
                 Intent intent = new Intent(LocationManager.PROVIDERS_CHANGED_ACTION)
                         .putExtra(LocationManager.EXTRA_PROVIDER_NAME, mName)
-                        .putExtra(LocationManager.EXTRA_PROVIDER_ENABLED, useable)
+                        .putExtra(LocationManager.EXTRA_PROVIDER_ENABLED, enabled)
                         .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)
                         .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
                 mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
             }
 
-            if (!useable) {
+            if (!enabled) {
                 // If any provider has been disabled, clear all last locations for all
                 // providers. This is to be on the safe side in case a provider has location
                 // derived from this disabled provider.
@@ -840,7 +847,7 @@
                 mLastLocationCoarseInterval.clear();
             }
 
-            updateProviderUseableLocked(this);
+            updateProviderEnabledLocked(this);
         }
 
         public void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) {
@@ -853,13 +860,7 @@
 
                 pw.increaseIndent();
 
-                boolean useable = isUseable();
-                pw.println("useable=" + useable);
-                if (!useable) {
-                    pw.println("enabled=" + mProvider.getState().enabled);
-                }
-
-                pw.println("properties=" + mProvider.getState().properties);
+                pw.println("enabled=" + isEnabled());
             }
 
             mProvider.dump(fd, pw, args);
@@ -1008,7 +1009,7 @@
                     if (manager == null) {
                         continue;
                     }
-                    if (!manager.isUseable() && !isSettingsExemptLocked(updateRecord)) {
+                    if (!manager.isEnabled() && !isSettingsExemptLocked(updateRecord)) {
                         continue;
                     }
 
@@ -1424,7 +1425,7 @@
                 if (FUSED_PROVIDER.equals(name)) {
                     continue;
                 }
-                if (enabledOnly && !manager.isUseable()) {
+                if (enabledOnly && !manager.isEnabled()) {
                     continue;
                 }
                 if (criteria != null
@@ -1466,8 +1467,8 @@
     }
 
     @GuardedBy("mLock")
-    private void updateProviderUseableLocked(LocationProviderManager manager) {
-        boolean useable = manager.isUseable();
+    private void updateProviderEnabledLocked(LocationProviderManager manager) {
+        boolean enabled = manager.isEnabled();
 
         ArrayList<Receiver> deadReceivers = null;
 
@@ -1485,7 +1486,7 @@
                 }
 
                 // Sends a notification message to the receiver
-                if (!record.mReceiver.callProviderEnabledLocked(manager.getName(), useable)) {
+                if (!record.mReceiver.callProviderEnabledLocked(manager.getName(), enabled)) {
                     if (deadReceivers == null) {
                         deadReceivers = new ArrayList<>();
                     }
@@ -1552,7 +1553,7 @@
                 }
                 final boolean isBatterySaverDisablingLocation = shouldThrottleRequests
                         || (isForegroundOnlyMode && !record.mIsForegroundUid);
-                if (!manager.isUseable() || isBatterySaverDisablingLocation) {
+                if (!manager.isEnabled() || isBatterySaverDisablingLocation) {
                     if (isSettingsExemptLocked(record)) {
                         providerRequest.setLocationSettingsIgnored(true);
                         providerRequest.setLowPowerMode(false);
@@ -1969,7 +1970,7 @@
             oldRecord.disposeLocked(false);
         }
 
-        if (!manager.isUseable() && !isSettingsExemptLocked(record)) {
+        if (!manager.isEnabled() && !isSettingsExemptLocked(record)) {
             // Notify the listener that updates are currently disabled - but only if the request
             // does not ignore location settings
             receiver.callProviderEnabledLocked(name, false);
@@ -2081,7 +2082,7 @@
                     return null;
                 }
 
-                if (!manager.isUseable()) {
+                if (!manager.isEnabled()) {
                     return null;
                 }
 
@@ -2203,7 +2204,7 @@
 
         synchronized (mLock) {
             LocationProviderManager manager = getLocationProviderManager(location.getProvider());
-            if (manager == null || !manager.isUseable()) {
+            if (manager == null || !manager.isEnabled()) {
                 return false;
             }
 
@@ -2490,7 +2491,7 @@
 
         synchronized (mLock) {
             LocationProviderManager manager = getLocationProviderManager(providerName);
-            return manager != null && manager.isUseable(userId);
+            return manager != null && manager.isEnabled(userId);
         }
     }
 
@@ -2548,8 +2549,8 @@
         long now = SystemClock.elapsedRealtime();
 
 
-        // only update last location for locations that come from useable providers
-        if (manager.isUseable()) {
+        // only update last location for locations that come from enabled providers
+        if (manager.isEnabled()) {
             updateLastLocationLocked(location, manager.getName());
         }
 
@@ -2559,7 +2560,7 @@
         if (lastLocationCoarseInterval == null) {
             lastLocationCoarseInterval = new Location(location);
 
-            if (manager.isUseable()) {
+            if (manager.isEnabled()) {
                 mLastLocationCoarseInterval.put(manager.getName(), lastLocationCoarseInterval);
             }
         }
@@ -2592,7 +2593,7 @@
             Receiver receiver = r.mReceiver;
             boolean receiverDead = false;
 
-            if (!manager.isUseable() && !isSettingsExemptLocked(r)) {
+            if (!manager.isEnabled() && !isSettingsExemptLocked(r)) {
                 continue;
             }
 
@@ -2811,7 +2812,7 @@
             throw new IllegalArgumentException("provider doesn't exist: " + provider);
         }
 
-        manager.setMockProviderEnabled(enabled);
+        manager.setMockProviderAllowed(enabled);
     }
 
     @Override
@@ -2886,10 +2887,12 @@
 
             ipw.println("Historical Records by Provider:");
             ipw.increaseIndent();
+            TreeMap<PackageProviderKey, PackageStatistics> sorted = new TreeMap<>();
+            sorted.putAll(mRequestStatistics.statistics);
             for (Map.Entry<PackageProviderKey, PackageStatistics> entry
-                    : mRequestStatistics.statistics.entrySet()) {
+                    : sorted.entrySet()) {
                 PackageProviderKey key = entry.getKey();
-                ipw.println(key.packageName + ": " + key.providerName + ": " + entry.getValue());
+                ipw.println(key.providerName + ": " + key.packageName + ": " + entry.getValue());
             }
             ipw.decreaseIndent();
 
@@ -2943,4 +2946,19 @@
             }
         }
     }
+
+    private class LocalService extends LocationManagerInternal {
+
+        @Override
+        public void requestSetProviderAllowed(String provider, boolean allowed) {
+            Preconditions.checkArgument(provider != null, "invalid null provider");
+
+            synchronized (mLock) {
+                LocationProviderManager manager = getLocationProviderManager(provider);
+                if (manager != null) {
+                    manager.requestSetAllowed(allowed);
+                }
+            }
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 05d8360..9d4c783 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -735,6 +735,11 @@
         public int getInterfaceVersion() {
             return INetdUnsolicitedEventListener.VERSION;
         }
+
+        @Override
+        public String getInterfaceHash() {
+            return INetdUnsolicitedEventListener.HASH;
+        }
     }
 
     //
diff --git a/services/core/java/com/android/server/ServiceWatcher.java b/services/core/java/com/android/server/ServiceWatcher.java
index 8564cb4..14cd3a5 100644
--- a/services/core/java/com/android/server/ServiceWatcher.java
+++ b/services/core/java/com/android/server/ServiceWatcher.java
@@ -167,7 +167,7 @@
 
         @Override
         public String toString() {
-            return component + "@" + version + "[u" + userId + "]";
+            return component.toShortString() + "@" + version + "[u" + userId + "]";
         }
     }
 
@@ -341,7 +341,7 @@
         Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());
 
         if (D) {
-            Log.i(TAG, getLogPrefix() + " connected to " + component);
+            Log.i(TAG, getLogPrefix() + " connected to " + component.toShortString());
         }
 
         mBinder = binder;
@@ -351,11 +351,22 @@
     }
 
     @Override
+    public void onBindingDied(ComponentName component) {
+        Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());
+
+        if (D) {
+            Log.i(TAG, getLogPrefix() + " " + component.toShortString() + " died");
+        }
+
+        onBestServiceChanged(true);
+    }
+
+    @Override
     public final void onServiceDisconnected(ComponentName component) {
         Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());
 
         if (D) {
-            Log.i(TAG, getLogPrefix() + " disconnected from " + component);
+            Log.i(TAG, getLogPrefix() + " disconnected from " + component.toShortString());
         }
 
         mBinder = null;
@@ -383,8 +394,8 @@
     }
 
     /**
-     * Runs the given function asynchronously if currently connected. Suppresses any RemoteException
-     * thrown during execution.
+     * Runs the given function asynchronously if and only if currently connected. Suppresses any
+     * RemoteException thrown during execution.
      */
     public final void runOnBinder(BinderRunner runner) {
         runOnHandler(() -> {
@@ -473,4 +484,9 @@
     private String getLogPrefix() {
         return "[" + mIntent.getAction() + "]";
     }
+
+    @Override
+    public String toString() {
+        return mServiceInfo.toString();
+    }
 }
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 5a56a9f..6bc090a 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -16,6 +16,8 @@
 
 package com.android.server;
 
+import static android.os.VibrationEffect.Composition.PrimitiveEffect;
+
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
@@ -73,8 +75,10 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.LinkedList;
+import java.util.List;
 
 public class VibratorService extends IVibratorService.Stub
         implements InputManager.InputDeviceListener {
@@ -128,10 +132,11 @@
     private final boolean mAllowPriorityVibrationsInLowPowerMode;
     private final boolean mSupportsAmplitudeControl;
     private final boolean mSupportsExternalControl;
+    private final List<Integer> mSupportedEffects;
     private final long mCapabilities;
     private final int mDefaultVibrationAmplitude;
     private final SparseArray<VibrationEffect> mFallbackEffects;
-    private final SparseArray<Integer> mProcStatesCache = new SparseArray();
+    private final SparseArray<Integer> mProcStatesCache = new SparseArray<>();
     private final WorkSource mTmpWorkSource = new WorkSource();
     private final Handler mH = new Handler();
     private final Object mLock = new Object();
@@ -150,7 +155,7 @@
 
     // mInputDeviceVibrators lock should be acquired after mLock, if both are
     // to be acquired
-    private final ArrayList<Vibrator> mInputDeviceVibrators = new ArrayList<Vibrator>();
+    private final ArrayList<Vibrator> mInputDeviceVibrators = new ArrayList<>();
     private boolean mVibrateInputDevicesSetting; // guarded by mInputDeviceVibrators
     private boolean mInputDeviceListenerRegistered; // guarded by mInputDeviceVibrators
 
@@ -171,7 +176,10 @@
     static native void vibratorOff();
     static native boolean vibratorSupportsAmplitudeControl();
     static native void vibratorSetAmplitude(int amplitude);
+    static native int[] vibratorGetSupportedEffects();
     static native long vibratorPerformEffect(long effect, long strength, Vibration vibration);
+    static native void vibratorPerformComposedEffect(
+            VibrationEffect.Composition.PrimitiveEffect[] effect, Vibration vibration);
     static native boolean vibratorSupportsExternalControl();
     static native void vibratorSetExternalControl(boolean enabled);
     static native long vibratorGetCapabilities();
@@ -238,6 +246,8 @@
             }
         }
 
+        // Called by native
+        @SuppressWarnings("unused")
         private void onComplete() {
             synchronized (mLock) {
                 if (this == mCurrentVibration) {
@@ -346,10 +356,11 @@
 
         mSupportsAmplitudeControl = vibratorSupportsAmplitudeControl();
         mSupportsExternalControl = vibratorSupportsExternalControl();
+        mSupportedEffects = asList(vibratorGetSupportedEffects());
         mCapabilities = vibratorGetCapabilities();
 
         mContext = context;
-        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+        PowerManager pm = context.getSystemService(PowerManager.class);
         mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*");
         mWakeLock.setReferenceCounted(true);
 
@@ -510,12 +521,47 @@
     }
 
     @Override // Binder call
+    public boolean[] areEffectsSupported(int[] effectIds) {
+        // Return null to indicate that the HAL doesn't actually tell us what effects are
+        // supported.
+        if (mSupportedEffects == null) {
+            return null;
+        }
+        boolean[] supported = new boolean[effectIds.length];
+        for (int i = 0; i < effectIds.length; i++) {
+            supported[i] = mSupportedEffects.contains(effectIds[i]);
+        }
+        return supported;
+    }
+
+    @Override // Binder call
+    public boolean[] arePrimitivesSupported(int[] primitiveIds) {
+        boolean[] supported = new boolean[primitiveIds.length];
+        if (hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) {
+            Arrays.fill(supported, true);
+        }
+        return supported;
+    }
+
+
+    private static List<Integer> asList(int... vals) {
+        if (vals == null) {
+            return null;
+        }
+        List<Integer> l = new ArrayList<>(vals.length);
+        for (int val : vals) {
+            l.add(val);
+        }
+        return l;
+    }
+
+    @Override // Binder call
     public boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, VibrationEffect effect,
             VibrationAttributes attrs) {
         if (!hasPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)) {
             throw new SecurityException("Requires VIBRATE_ALWAYS_ON permission");
         }
-        if ((mCapabilities & IVibrator.CAP_ALWAYS_ON_CONTROL) == 0) {
+        if (!hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) {
             Slog.e(TAG, "Always-on effects not supported.");
             return false;
         }
@@ -817,6 +863,14 @@
                 if (timeout > 0) {
                     mH.postDelayed(mVibrationEndRunnable, timeout);
                 }
+            } else if (vib.effect instanceof  VibrationEffect.Composed) {
+                Trace.asyncTraceBegin(Trace.TRACE_TAG_VIBRATOR, "vibration", 0);
+                doVibratorComposedEffectLocked(vib);
+                // FIXME: We rely on the completion callback here, but I don't think we require that
+                // devices which support composition also support the completion callback. If we
+                // ever get a device that supports the former but not the latter, then we have no
+                // real way of knowing how long a given effect should last.
+                mH.postDelayed(mVibrationEndRunnable, 10000);
             } else {
                 Slog.e(TAG, "Unknown vibration type, ignoring");
             }
@@ -1148,7 +1202,7 @@
                     }
                 } else {
                     // Note: ordering is important here! Many haptic drivers will reset their
-                    // amplitude when enabled, so we always have to enable frst, then set the
+                    // amplitude when enabled, so we always have to enable first, then set the
                     // amplitude.
                     vibratorOn(millis);
                     doVibratorSetAmplitude(amplitude);
@@ -1201,7 +1255,7 @@
                 long duration = vibratorPerformEffect(prebaked.getId(),
                         prebaked.getEffectStrength(), vib);
                 long timeout = duration;
-                if ((mCapabilities & IVibrator.CAP_PERFORM_CALLBACK) != 0) {
+                if (hasCapability(IVibrator.CAP_PERFORM_CALLBACK)) {
                     timeout *= ASYNC_TIMEOUT_MULTIPLIER;
                 }
                 if (timeout > 0) {
@@ -1229,6 +1283,41 @@
         }
     }
 
+    @GuardedBy("mLock")
+    private void doVibratorComposedEffectLocked(Vibration vib) {
+        Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "doVibratorComposedEffectLocked");
+
+        try {
+            final VibrationEffect.Composed composed = (VibrationEffect.Composed) vib.effect;
+            final boolean usingInputDeviceVibrators;
+            synchronized (mInputDeviceVibrators) {
+                usingInputDeviceVibrators = !mInputDeviceVibrators.isEmpty();
+            }
+            // Input devices don't support composed effect, so skip trying it with them.
+            if (usingInputDeviceVibrators) {
+                return;
+            }
+
+            if (!hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) {
+                return;
+            }
+
+            PrimitiveEffect[] primitiveEffects =
+                    composed.getPrimitiveEffects().toArray(new PrimitiveEffect[0]);
+            vibratorPerformComposedEffect(primitiveEffects, vib);
+
+            // Composed effects don't actually give us an estimated duration, so we just guess here.
+            noteVibratorOnLocked(vib.uid, 10 * primitiveEffects.length);
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
+        }
+
+    }
+
+    private boolean hasCapability(long capability) {
+        return (mCapabilities & capability) == capability;
+    }
+
     private VibrationEffect getFallbackEffect(int effectId) {
         return mFallbackEffects.get(effectId);
     }
@@ -1424,7 +1513,7 @@
                 long[] timings, int[] amplitudes, int startIndex, int repeatIndex) {
             int i = startIndex;
             long timing = 0;
-            while(amplitudes[i] != 0) {
+            while (amplitudes[i] != 0) {
                 timing += timings[i++];
                 if (i >= timings.length) {
                     if (repeatIndex >= 0) {
@@ -1475,18 +1564,14 @@
             } else {
                 pw.println("null");
             }
-            pw.print("  mCurrentExternalVibration=");
-            if (mCurrentExternalVibration != null) {
-                pw.println(mCurrentExternalVibration.toString());
-            } else {
-                pw.println("null");
-            }
+            pw.print("  mCurrentExternalVibration=" + mCurrentExternalVibration);
             pw.println("  mVibratorUnderExternalControl=" + mVibratorUnderExternalControl);
             pw.println("  mLowPowerMode=" + mLowPowerMode);
             pw.println("  mHapticFeedbackIntensity=" + mHapticFeedbackIntensity);
             pw.println("  mNotificationIntensity=" + mNotificationIntensity);
             pw.println("  mRingIntensity=" + mRingIntensity);
-            pw.println("");
+            pw.println("  mSupportedEffects=" + mSupportedEffects);
+            pw.println();
             pw.println("  Previous ring vibrations:");
             for (VibrationInfo info : mPreviousRingVibrations) {
                 pw.print("    ");
@@ -1495,34 +1580,29 @@
 
             pw.println("  Previous notification vibrations:");
             for (VibrationInfo info : mPreviousNotificationVibrations) {
-                pw.print("    ");
-                pw.println(info.toString());
+                pw.println("    " + info);
             }
 
             pw.println("  Previous alarm vibrations:");
             for (VibrationInfo info : mPreviousAlarmVibrations) {
-                pw.print("    ");
-                pw.println(info.toString());
+                pw.println("    " + info);
             }
 
             pw.println("  Previous vibrations:");
             for (VibrationInfo info : mPreviousVibrations) {
-                pw.print("    ");
-                pw.println(info.toString());
+                pw.println("    " + info);
             }
 
             pw.println("  Previous external vibrations:");
             for (ExternalVibration vib : mPreviousExternalVibrations) {
-                pw.print("    ");
-                pw.println(vib.toString());
+                pw.println("    " + vib);
             }
         }
     }
 
     @Override
     public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
-            String[] args, ShellCallback callback, ResultReceiver resultReceiver)
-            throws RemoteException {
+            String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
         new VibratorShellCommand(this).exec(this, in, out, err, args, callback, resultReceiver);
     }
 
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index ac85bf5..ffeea3d 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -17,7 +17,15 @@
 package com.android.server.am;
 
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION;
 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST;
+import static android.os.Process.BLUETOOTH_UID;
+import static android.os.Process.NETWORK_STACK_UID;
+import static android.os.Process.NFC_UID;
+import static android.os.Process.PHONE_UID;
+import static android.os.Process.ROOT_UID;
+import static android.os.Process.SE_UID;
+import static android.os.Process.SYSTEM_UID;
 
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKGROUND_CHECK;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOREGROUND_SERVICE;
@@ -45,6 +53,7 @@
 import android.app.PendingIntent;
 import android.app.Service;
 import android.app.ServiceStartArgs;
+import android.appwidget.AppWidgetManagerInternal;
 import android.content.ComponentName;
 import android.content.ComponentName.WithComponentName;
 import android.content.Context;
@@ -56,6 +65,7 @@
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Build;
@@ -83,6 +93,7 @@
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 import android.webkit.WebViewZygote;
+import android.widget.Toast;
 
 import com.android.internal.R;
 import com.android.internal.app.procstats.ServiceState;
@@ -178,6 +189,8 @@
 
     String mLastAnrDump;
 
+    AppWidgetManagerInternal mAppWidgetManagerInternal;
+
     final Runnable mLastAnrDumpClearer = new Runnable() {
         @Override public void run() {
             synchronized (mAm) {
@@ -274,6 +287,7 @@
 
         static final int MSG_BG_START_TIMEOUT = 1;
         static final int MSG_UPDATE_FOREGROUND_APPS = 2;
+        static final int MSG_ENSURE_NOT_START_BG = 3;
 
         ServiceMap(Looper looper, int userId) {
             super(looper);
@@ -291,6 +305,11 @@
                 case MSG_UPDATE_FOREGROUND_APPS: {
                     updateForegroundApps(this);
                 } break;
+                case MSG_ENSURE_NOT_START_BG: {
+                    synchronized (mAm) {
+                        rescheduleDelayedStartsLocked();
+                    }
+                } break;
             }
         }
 
@@ -298,7 +317,9 @@
             if (mStartingBackground.remove(r)) {
                 if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
                         "No longer background starting: " + r);
-                rescheduleDelayedStartsLocked();
+                removeMessages(MSG_ENSURE_NOT_START_BG);
+                Message msg = obtainMessage(MSG_ENSURE_NOT_START_BG);
+                sendMessage(msg);
             }
             if (mDelayedStartList.remove(r)) {
                 if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "No longer delaying start: " + r);
@@ -371,6 +392,7 @@
     void systemServicesReady() {
         AppStateTracker ast = LocalServices.getService(AppStateTracker.class);
         ast.addListener(new ForcedStandbyListener());
+        mAppWidgetManagerInternal = LocalServices.getService(AppWidgetManagerInternal.class);
     }
 
     ServiceRecord getServiceByNameLocked(ComponentName name, int callingUser) {
@@ -643,8 +665,14 @@
         if (allowBackgroundActivityStarts) {
             r.whitelistBgActivityStartsOnServiceStart();
         }
-
         ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
+
+        if (!r.mAllowWhileInUsePermissionInFgs) {
+            r.mAllowWhileInUsePermissionInFgs =
+                    shouldAllowWhileInUsePermissionInFgsLocked(callingPackage, callingUid,
+                            service, r, allowBackgroundActivityStarts);
+        }
+
         return cmp;
     }
 
@@ -1303,6 +1331,15 @@
                         +  String.format("0x%08X", manifestType)
                         + " in service element of manifest file");
                 }
+                if ((foregroundServiceType & FOREGROUND_SERVICE_TYPE_LOCATION) != 0
+                        && !r.mAllowWhileInUsePermissionInFgs) {
+                    // If the foreground service is not started from TOP process, do not allow it to
+                    // have location capability, this prevents BG started FGS to have while-in-use
+                    // location permission.
+                    Slog.w(TAG,
+                            "BG started FGS can not have location capability: service "
+                                    + r.shortInstanceName);
+                }
             }
             boolean alreadyStartedOp = false;
             boolean stopProcStatsOp = false;
@@ -1661,7 +1698,6 @@
             return -1;
         }
         ServiceRecord s = res.record;
-
         boolean permissionsReviewRequired = false;
 
         // If permissions need a review before any of the app components can run,
@@ -1810,6 +1846,13 @@
                 }
             }
 
+            if (!s.mAllowWhileInUsePermissionInFgs) {
+                final int callingUid = Binder.getCallingUid();
+                s.mAllowWhileInUsePermissionInFgs =
+                        shouldAllowWhileInUsePermissionInFgsLocked(callingPackage, callingUid,
+                                service, s, false);
+            }
+
             if (s.app != null) {
                 if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
                     s.app.treatLikeActivity = true;
@@ -2199,6 +2242,7 @@
                     }
                     r = new ServiceRecord(mAm, ss, className, name, definingPackageName,
                             definingUid, filter, sInfo, callingFromFg, res);
+                    r.mRecentCallingPackage = callingPackage;
                     res.setService(r);
                     smap.mServicesByInstanceName.put(name, r);
                     smap.mServicesByIntent.put(filter, r);
@@ -3065,6 +3109,7 @@
         r.isForeground = false;
         r.foregroundId = 0;
         r.foregroundNoti = null;
+        r.mAllowWhileInUsePermissionInFgs = false;
 
         // Clear start entries.
         r.clearDeliveredStartsLocked();
@@ -4533,4 +4578,109 @@
             }
         }
     }
+
+    /**
+     * Should allow while-in-use permissions in foreground service or not.
+     * while-in-use permissions in FGS started from background might be restricted.
+     * @param callingPackage caller app's package name.
+     * @param callingUid caller app's uid.
+     * @param intent intent to start/bind service.
+     * @param r the service to start.
+     * @return true if allow, false otherwise.
+     */
+    private boolean shouldAllowWhileInUsePermissionInFgsLocked(String callingPackage,
+            int callingUid, Intent intent, ServiceRecord r, boolean allowBackgroundActivityStarts) {
+        // Is the background FGS start restriction turned on?
+        if (!mAm.mConstants.mFlagBackgroundFgsStartRestrictionEnabled) {
+            return true;
+        }
+        // Is the allow activity background start flag on?
+        if (allowBackgroundActivityStarts) {
+            return true;
+        }
+
+        // Is the service in a whitelist?
+        final boolean hasAllowBackgroundActivityStartsToken = r.app != null
+                ? r.app.mAllowBackgroundActivityStartsTokens.contains(r) : false;
+        if (hasAllowBackgroundActivityStartsToken) {
+            return true;
+        }
+
+        boolean isCallerSystem = false;
+        final int callingAppId = UserHandle.getAppId(callingUid);
+        switch (callingAppId) {
+            case ROOT_UID:
+            case SYSTEM_UID:
+            case NFC_UID:
+                isCallerSystem = true;
+                break;
+            default:
+                isCallerSystem = false;
+                break;
+        }
+
+        if (isCallerSystem) {
+            return true;
+        }
+
+        // Is the calling UID at PROCESS_STATE_TOP or above?
+        final boolean isCallingUidTopApp = appIsTopLocked(callingUid);
+        if (isCallingUidTopApp) {
+            return true;
+        }
+        // Does the calling UID have any visible activity?
+        final boolean isCallingUidVisible = mAm.mAtmInternal.isUidForeground(callingUid);
+        if (isCallingUidVisible) {
+            return true;
+        }
+
+        r.mInfoDenyWhileInUsePermissionInFgs =
+                "Background FGS start while-in-use permission restriction [callingPackage: "
+                + callingPackage
+                + "; callingUid: " + callingUid
+                + "; intent: " + intent
+                + "]";
+        return false;
+    }
+
+    // TODO: remove this toast after feature development is done
+    private void showWhileInUsePermissionInFgsBlockedToastLocked(String callingPackage) {
+        final Resources res = mAm.mContext.getResources();
+        final String toastMsg = res.getString(
+                        R.string.allow_while_in_use_permission_in_fgs, callingPackage);
+        mAm.mUiHandler.post(() -> {
+            Toast.makeText(mAm.mContext, toastMsg, Toast.LENGTH_LONG).show();
+        });
+    }
+
+    // TODO: remove this toast after feature development is done
+    // show a toast message to ask user to file a bugreport so we know how many apps are impacted by
+    // the new background started foreground service while-in-use permission restriction.
+    void showWhileInUseDebugToastLocked(int uid, int op, int mode) {
+        StringBuilder sb = new StringBuilder();
+        for (int i = mAm.mProcessList.mLruProcesses.size() - 1; i >= 0; i--) {
+            ProcessRecord pr = mAm.mProcessList.mLruProcesses.get(i);
+            if (pr.uid != uid) {
+                continue;
+            }
+            for (int j = pr.services.size() - 1; j >= 0; j--) {
+                ServiceRecord r = pr.services.valueAt(j);
+                if (!r.isForeground) {
+                    continue;
+                }
+                if (!r.mAllowWhileInUsePermissionInFgs
+                        && r.mInfoDenyWhileInUsePermissionInFgs != null) {
+                    Slog.wtf(TAG, r.mInfoDenyWhileInUsePermissionInFgs
+                            + " affected while-use-permission:" + AppOpsManager.opToPublicName(op));
+                    sb.append(r.mRecentCallingPackage + " ");
+                }
+            }
+        }
+
+        final String callingPackageStr = sb.toString();
+        if (mAm.mConstants.mFlagForegroundServiceStartsLoggingEnabled
+                && !callingPackageStr.isEmpty()) {
+            showWhileInUsePermissionInFgsBlockedToastLocked(callingPackageStr);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index fc4bad7..8451d6b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -131,6 +131,12 @@
     private static final String KEY_DEFAULT_BACKGROUND_ACTIVITY_STARTS_ENABLED =
             "default_background_activity_starts_enabled";
 
+    /**
+     * Default value for mFlagBackgroundFgsStartRestrictionEnabled if not explicitly set in
+     * Settings.Global.
+     */
+    private static final String KEY_DEFAULT_BACKGROUND_FGS_STARTS_RESTRICTION_ENABLED =
+            "default_background_fgs_starts_restriction_enabled";
 
     // Maximum number of cached processes we will allow.
     public int MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES;
@@ -262,6 +268,16 @@
     // If not set explicitly the default is controlled by DeviceConfig.
     volatile boolean mFlagBackgroundActivityStartsEnabled;
 
+    // Indicates whether foreground service starts logging is enabled.
+    // Controlled by Settings.Global.FOREGROUND_SERVICE_STARTS_LOGGING_ENABLED
+    volatile boolean mFlagForegroundServiceStartsLoggingEnabled;
+
+    // Indicates whether the foreground service background start restriction is enabled.
+    // When the restriction is enabled, foreground service started from background will not have
+    // while-in-use permissions like location, camera and microphone. (The foreground service can be
+    // started, the restriction is on while-in-use permissions.)
+    volatile boolean mFlagBackgroundFgsStartRestrictionEnabled;
+
     private final ActivityManagerService mService;
     private ContentResolver mResolver;
     private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -332,6 +348,10 @@
     private static final Uri ACTIVITY_STARTS_LOGGING_ENABLED_URI = Settings.Global.getUriFor(
                 Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED);
 
+    private static final Uri FOREGROUND_SERVICE_STARTS_LOGGING_ENABLED_URI =
+                Settings.Global.getUriFor(
+                        Settings.Global.FOREGROUND_SERVICE_STARTS_LOGGING_ENABLED);
+
     private static final Uri ENABLE_AUTOMATIC_SYSTEM_SERVER_HEAP_DUMPS_URI =
             Settings.Global.getUriFor(Settings.Global.ENABLE_AUTOMATIC_SYSTEM_SERVER_HEAP_DUMPS);
 
@@ -350,6 +370,9 @@
                             case KEY_DEFAULT_BACKGROUND_ACTIVITY_STARTS_ENABLED:
                                 updateBackgroundActivityStarts();
                                 break;
+                            case KEY_DEFAULT_BACKGROUND_FGS_STARTS_RESTRICTION_ENABLED:
+                                updateBackgroundFgsStartsRestriction();
+                                break;
                             case KEY_OOMADJ_UPDATE_POLICY:
                                 updateOomAdjUpdatePolicy();
                                 break;
@@ -388,6 +411,8 @@
         mResolver = resolver;
         mResolver.registerContentObserver(ACTIVITY_MANAGER_CONSTANTS_URI, false, this);
         mResolver.registerContentObserver(ACTIVITY_STARTS_LOGGING_ENABLED_URI, false, this);
+        mResolver.registerContentObserver(FOREGROUND_SERVICE_STARTS_LOGGING_ENABLED_URI,
+                false, this);
         if (mSystemServerAutomaticHeapDumpEnabled) {
             mResolver.registerContentObserver(ENABLE_AUTOMATIC_SYSTEM_SERVER_HEAP_DUMPS_URI,
                     false, this);
@@ -402,6 +427,8 @@
         updateMaxCachedProcesses();
         updateActivityStartsLoggingEnabled();
         updateBackgroundActivityStarts();
+        updateForegroundServiceStartsLoggingEnabled();
+        updateBackgroundFgsStartsRestriction();
         updateOomAdjUpdatePolicy();
         updateImperceptibleKillExemptions();
     }
@@ -426,6 +453,8 @@
             updateConstants();
         } else if (ACTIVITY_STARTS_LOGGING_ENABLED_URI.equals(uri)) {
             updateActivityStartsLoggingEnabled();
+        } else if (FOREGROUND_SERVICE_STARTS_LOGGING_ENABLED_URI.equals(uri)) {
+            updateForegroundServiceStartsLoggingEnabled();
         } else if (ENABLE_AUTOMATIC_SYSTEM_SERVER_HEAP_DUMPS_URI.equals(uri)) {
             updateEnableAutomaticSystemServerHeapDumps();
         }
@@ -522,6 +551,18 @@
                 /*defaultValue*/ false);
     }
 
+    private void updateForegroundServiceStartsLoggingEnabled() {
+        mFlagForegroundServiceStartsLoggingEnabled = Settings.Global.getInt(mResolver,
+                Settings.Global.FOREGROUND_SERVICE_STARTS_LOGGING_ENABLED, 1) == 1;
+    }
+
+    private void updateBackgroundFgsStartsRestriction() {
+        mFlagBackgroundFgsStartRestrictionEnabled = DeviceConfig.getBoolean(
+                DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                KEY_DEFAULT_BACKGROUND_FGS_STARTS_RESTRICTION_ENABLED,
+                /*defaultValue*/ true);
+    }
+
     private void updateOomAdjUpdatePolicy() {
         OOMADJ_UPDATE_QUICK = DeviceConfig.getInt(
                 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
index ed64475..b19a37e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
+++ b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
@@ -50,6 +50,7 @@
     static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
     static final boolean DEBUG_BROADCAST_DEFERRAL = DEBUG_BROADCAST || false;
     static final boolean DEBUG_COMPACTION = DEBUG_ALL || false;
+    static final boolean DEBUG_FREEZER = DEBUG_ALL || false;
     static final boolean DEBUG_LRU = DEBUG_ALL || false;
     static final boolean DEBUG_MU = DEBUG_ALL || false;
     static final boolean DEBUG_NETWORK = DEBUG_ALL || false;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5596b2f..8b547c6 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -199,6 +199,7 @@
 import android.content.IIntentSender;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.LocusId;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ActivityPresentationInfo;
 import android.content.pm.ApplicationInfo;
@@ -1798,7 +1799,7 @@
                 case KILL_APP_ZYGOTE_MSG: {
                     synchronized (ActivityManagerService.this) {
                         final AppZygote appZygote = (AppZygote) msg.obj;
-                        mProcessList.killAppZygoteIfNeededLocked(appZygote);
+                        mProcessList.killAppZygoteIfNeededLocked(appZygote, false /* force */);
                     }
                 } break;
             case CHECK_EXCESSIVE_POWER_USE_MSG: {
@@ -4656,6 +4657,22 @@
     }
 
     @GuardedBy("this")
+    final void forceStopAppZygoteLocked(String packageName, int appId, int userId) {
+        if (packageName == null) {
+            return;
+        }
+        if (appId < 0) {
+            try {
+                appId = UserHandle.getAppId(AppGlobals.getPackageManager()
+                        .getPackageUid(packageName, MATCH_DEBUG_TRIAGED_MISSING, 0));
+            } catch (RemoteException e) {
+            }
+        }
+
+        mProcessList.killAppZygotesLocked(packageName, appId, userId, true /* force */);
+    }
+
+    @GuardedBy("this")
     final boolean forceStopPackageLocked(String packageName, int appId,
             boolean callerWillRestart, boolean purgeCache, boolean doit,
             boolean evenPersistent, boolean uninstalling, int userId, String reason) {
@@ -5779,7 +5796,8 @@
             if (uidRec == null || uidRec.idle) {
                 return false;
             }
-            return uidRec.getCurProcState() <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
+            return uidRec.getCurProcState()
+                    <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
         }
     }
 
@@ -15634,6 +15652,12 @@
                                                 intent.getIntExtra(Intent.EXTRA_UID, -1)),
                                                 false, true, true, false, fullUninstall, userId,
                                                 removed ? "pkg removed" : "pkg changed");
+                                    } else {
+                                        // Kill any app zygotes always, since they can't fork new
+                                        // processes with references to the old code
+                                        forceStopAppZygoteLocked(ssp, UserHandle.getAppId(
+                                                intent.getIntExtra(Intent.EXTRA_UID, -1)),
+                                                userId);
                                     }
                                     final int cmd = killProcess
                                             ? ApplicationThreadConstants.PACKAGE_REMOVED
@@ -19088,6 +19112,28 @@
         public void unregisterProcessObserver(IProcessObserver processObserver) {
             ActivityManagerService.this.unregisterProcessObserver(processObserver);
         }
+
+        @Override
+        public boolean isUidCurrentlyInstrumented(int uid) {
+            synchronized (ActivityManagerService.this) {
+                for (int i = mActiveInstrumentation.size() - 1; i >= 0; i--) {
+                    ActiveInstrumentation activeInst = mActiveInstrumentation.get(i);
+                    if (!activeInst.mFinished && activeInst.mTargetInfo != null
+                            && activeInst.mTargetInfo.uid == uid) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+
+        // TODO: remove this toast after feature development is done
+        @Override
+        public void showWhileInUseDebugToast(int uid, int op, int mode) {
+            synchronized (ActivityManagerService.this) {
+                ActivityManagerService.this.mServices.showWhileInUseDebugToastLocked(uid, op, mode);
+            }
+        }
     }
 
     long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) {
@@ -19642,4 +19688,19 @@
             }
         }
     }
+
+    @Override
+    public void setActivityLocusContext(ComponentName activity, LocusId locusId, IBinder appToken) {
+        final int callingUid = Binder.getCallingUid();
+        final int userId = UserHandle.getCallingUserId();
+        if (getPackageManagerInternalLocked().getPackageUid(activity.getPackageName(),
+                /*flags=*/ 0, userId) != callingUid) {
+            throw new SecurityException("Calling uid " + callingUid + " cannot set locusId"
+                    + "for package " + activity.getPackageName());
+        }
+
+        if (mUsageStatsService != null) {
+            mUsageStatsService.reportLocusUpdate(activity, userId, locusId, appToken);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
index cf996a5..fa91620 100644
--- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
@@ -567,39 +567,41 @@
         final long lastRxMs = mLastInfo.getControllerRxDurationMillis();
         final long lastEnergy = mLastInfo.getControllerEnergyUsedMicroJoules();
 
-        // We will modify the last info object to be the delta, and store the new
-        // WifiActivityEnergyInfo object as our last one.
-        final WifiActivityEnergyInfo delta = mLastInfo;
-        delta.setTimeSinceBootMillis(latest.getTimeSinceBootMillis());
-        delta.setStackState(latest.getStackState());
+        final long deltaTimeSinceBootMillis = latest.getTimeSinceBootMillis();
+        final int deltaStackState = latest.getStackState();
+        final long deltaControllerTxDurationMillis;
+        final long deltaControllerRxDurationMillis;
+        final long deltaControllerScanDurationMillis;
+        final long deltaControllerIdleDurationMillis;
+        final long deltaControllerEnergyUsedMicroJoules;
 
         final long txTimeMs = latest.getControllerTxDurationMillis() - lastTxMs;
         final long rxTimeMs = latest.getControllerRxDurationMillis() - lastRxMs;
         final long idleTimeMs = latest.getControllerIdleDurationMillis() - lastIdleMs;
         final long scanTimeMs = latest.getControllerScanDurationMillis() - lastScanMs;
 
+        final boolean wasReset;
         if (txTimeMs < 0 || rxTimeMs < 0 || scanTimeMs < 0 || idleTimeMs < 0) {
             // The stats were reset by the WiFi system (which is why our delta is negative).
             // Returns the unaltered stats. The total on time should not exceed the time
-            // duartion between reports.
+            // duration between reports.
             final long totalOnTimeMs = latest.getControllerTxDurationMillis()
                     + latest.getControllerRxDurationMillis()
                     + latest.getControllerIdleDurationMillis();
             if (totalOnTimeMs <= timePeriodMs + MAX_WIFI_STATS_SAMPLE_ERROR_MILLIS) {
-                delta.setControllerEnergyUsedMicroJoules(
-                        latest.getControllerEnergyUsedMicroJoules());
-                delta.setControllerRxDurationMillis(latest.getControllerRxDurationMillis());
-                delta.setControllerTxDurationMillis(latest.getControllerTxDurationMillis());
-                delta.setControllerIdleDurationMillis(latest.getControllerIdleDurationMillis());
-                delta.setControllerScanDurationMillis(latest.getControllerScanDurationMillis());
+                deltaControllerEnergyUsedMicroJoules = latest.getControllerEnergyUsedMicroJoules();
+                deltaControllerRxDurationMillis = latest.getControllerRxDurationMillis();
+                deltaControllerTxDurationMillis = latest.getControllerTxDurationMillis();
+                deltaControllerIdleDurationMillis = latest.getControllerIdleDurationMillis();
+                deltaControllerScanDurationMillis = latest.getControllerScanDurationMillis();
             } else {
-                delta.setControllerEnergyUsedMicroJoules(0);
-                delta.setControllerRxDurationMillis(0);
-                delta.setControllerTxDurationMillis(0);
-                delta.setControllerIdleDurationMillis(0);
-                delta.setControllerScanDurationMillis(0);
+                deltaControllerEnergyUsedMicroJoules = 0;
+                deltaControllerRxDurationMillis = 0;
+                deltaControllerTxDurationMillis = 0;
+                deltaControllerIdleDurationMillis = 0;
+                deltaControllerScanDurationMillis = 0;
             }
-            Slog.v(TAG, "WiFi energy data was reset, new WiFi energy data is " + delta);
+            wasReset = true;
         } else {
             final long totalActiveTimeMs = txTimeMs + rxTimeMs;
             long maxExpectedIdleTimeMs;
@@ -634,21 +636,33 @@
                 maxExpectedIdleTimeMs = timePeriodMs - totalActiveTimeMs;
             }
             // These times seem to be the most reliable.
-            delta.setControllerTxDurationMillis(txTimeMs);
-            delta.setControllerRxDurationMillis(rxTimeMs);
-            delta.setControllerScanDurationMillis(scanTimeMs);
+            deltaControllerTxDurationMillis = txTimeMs;
+            deltaControllerRxDurationMillis = rxTimeMs;
+            deltaControllerScanDurationMillis = scanTimeMs;
             // WiFi calculates the idle time as a difference from the on time and the various
             // Rx + Tx times. There seems to be some missing time there because this sometimes
             // becomes negative. Just cap it at 0 and ensure that it is less than the expected idle
             // time from the difference in timestamps.
             // b/21613534
-            delta.setControllerIdleDurationMillis(
-                    Math.min(maxExpectedIdleTimeMs, Math.max(0, idleTimeMs)));
-            delta.setControllerEnergyUsedMicroJoules(
-                    Math.max(0, latest.getControllerEnergyUsedMicroJoules() - lastEnergy));
+            deltaControllerIdleDurationMillis =
+                    Math.min(maxExpectedIdleTimeMs, Math.max(0, idleTimeMs));
+            deltaControllerEnergyUsedMicroJoules =
+                    Math.max(0, latest.getControllerEnergyUsedMicroJoules() - lastEnergy);
+            wasReset = false;
         }
 
         mLastInfo = latest;
+        WifiActivityEnergyInfo delta = new WifiActivityEnergyInfo(
+                deltaTimeSinceBootMillis,
+                deltaStackState,
+                deltaControllerTxDurationMillis,
+                deltaControllerRxDurationMillis,
+                deltaControllerScanDurationMillis,
+                deltaControllerIdleDurationMillis,
+                deltaControllerEnergyUsedMicroJoules);
+        if (wasReset) {
+            Slog.v(TAG, "WiFi energy data was reset, new WiFi energy data is " + delta);
+        }
         return delta;
     }
 }
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 3ca5ebc..6819578 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -19,6 +19,7 @@
 import static android.os.Process.THREAD_PRIORITY_FOREGROUND;
 
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_COMPACTION;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FREEZER;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 
 import android.app.ActivityManager;
@@ -42,6 +43,7 @@
 import com.android.server.ServiceThread;
 
 import java.io.FileOutputStream;
+import java.io.FileReader;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -55,6 +57,7 @@
 
     // Flags stored in the DeviceConfig API.
     @VisibleForTesting static final String KEY_USE_COMPACTION = "use_compaction";
+    @VisibleForTesting static final String KEY_USE_FREEZER = "use_freezer";
     @VisibleForTesting static final String KEY_COMPACT_ACTION_1 = "compact_action_1";
     @VisibleForTesting static final String KEY_COMPACT_ACTION_2 = "compact_action_2";
     @VisibleForTesting static final String KEY_COMPACT_THROTTLE_1 = "compact_throttle_1";
@@ -65,6 +68,8 @@
     @VisibleForTesting static final String KEY_COMPACT_THROTTLE_6 = "compact_throttle_6";
     @VisibleForTesting static final String KEY_COMPACT_STATSD_SAMPLE_RATE =
             "compact_statsd_sample_rate";
+    @VisibleForTesting static final String KEY_FREEZER_STATSD_SAMPLE_RATE =
+            "freeze_statsd_sample_rate";
     @VisibleForTesting static final String KEY_COMPACT_FULL_RSS_THROTTLE_KB =
             "compact_full_rss_throttle_kb";
     @VisibleForTesting static final String KEY_COMPACT_FULL_DELTA_RSS_THROTTLE_KB =
@@ -85,6 +90,7 @@
 
     // Defaults for phenotype flags.
     @VisibleForTesting static final Boolean DEFAULT_USE_COMPACTION = false;
+    @VisibleForTesting static final Boolean DEFAULT_USE_FREEZER = false;
     @VisibleForTesting static final int DEFAULT_COMPACT_ACTION_1 = COMPACT_ACTION_FILE_FLAG;
     @VisibleForTesting static final int DEFAULT_COMPACT_ACTION_2 = COMPACT_ACTION_FULL_FLAG;
     @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_1 = 5_000;
@@ -114,6 +120,13 @@
     static final int COMPACT_PROCESS_BFGS = 4;
     static final int COMPACT_PROCESS_MSG = 1;
     static final int COMPACT_SYSTEM_MSG = 2;
+    static final int SET_FROZEN_PROCESS_MSG = 3;
+
+    //TODO:change this static definition into a configurable flag.
+    static final int FREEZE_TIMEOUT_MS = 500;
+
+    static final int DO_FREEZE = 1;
+    static final int DO_UNFREEZE = 2;
 
     /**
      * This thread must be moved to the system background cpuset.
@@ -144,7 +157,9 @@
                                     || KEY_COMPACT_THROTTLE_4.equals(name)) {
                                 updateCompactionThrottles();
                             } else if (KEY_COMPACT_STATSD_SAMPLE_RATE.equals(name)) {
-                                updateStatsdSampleRate();
+                                updateCompactStatsdSampleRate();
+                            } else if (KEY_FREEZER_STATSD_SAMPLE_RATE.equals(name)) {
+                                updateFreezerStatsdSampleRate();
                             } else if (KEY_COMPACT_FULL_RSS_THROTTLE_KB.equals(name)) {
                                 updateFullRssThrottle();
                             } else if (KEY_COMPACT_FULL_DELTA_RSS_THROTTLE_KB.equals(name)) {
@@ -183,9 +198,11 @@
     @VisibleForTesting volatile long mCompactThrottlePersistent = DEFAULT_COMPACT_THROTTLE_6;
     @GuardedBy("mPhenotypeFlagLock")
     private volatile boolean mUseCompaction = DEFAULT_USE_COMPACTION;
+    private volatile boolean mUseFreezer = DEFAULT_USE_FREEZER;
     private final Random mRandom = new Random();
     @GuardedBy("mPhenotypeFlagLock")
-    @VisibleForTesting volatile float mStatsdSampleRate = DEFAULT_STATSD_SAMPLE_RATE;
+    @VisibleForTesting volatile float mCompactStatsdSampleRate = DEFAULT_STATSD_SAMPLE_RATE;
+    @VisibleForTesting volatile float mFreezerStatsdSampleRate = DEFAULT_STATSD_SAMPLE_RATE;
     @GuardedBy("mPhenotypeFlagLock")
     @VisibleForTesting volatile long mFullAnonRssThrottleKb =
             DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB;
@@ -197,6 +214,7 @@
 
     // Handler on which compaction runs.
     private Handler mCompactionHandler;
+    private Handler mFreezeHandler;
 
     // Maps process ID to last compaction statistics for processes that we've fully compacted. Used
     // when evaluating throttles that we only consider for "full" compaction, so we don't store
@@ -238,10 +256,12 @@
             updateUseCompaction();
             updateCompactionActions();
             updateCompactionThrottles();
-            updateStatsdSampleRate();
+            updateCompactStatsdSampleRate();
+            updateFreezerStatsdSampleRate();
             updateFullRssThrottle();
             updateFullDeltaRssThrottle();
             updateProcStateThrottle();
+            updateUseFreezer();
         }
         Process.setThreadGroupAndCpuset(mCachedAppOptimizerThread.getThreadId(),
                 Process.THREAD_GROUP_SYSTEM);
@@ -256,6 +276,15 @@
         }
     }
 
+    /**
+     * Returns whether freezer is enabled.
+     */
+    public boolean useFreezer() {
+        synchronized (mPhenotypeFlagLock) {
+            return mUseFreezer;
+        }
+    }
+
     @GuardedBy("mAm")
     void dump(PrintWriter pw) {
         pw.println("CachedAppOptimizer settings");
@@ -269,7 +298,7 @@
             pw.println("  " + KEY_COMPACT_THROTTLE_4 + "=" + mCompactThrottleFullFull);
             pw.println("  " + KEY_COMPACT_THROTTLE_5 + "=" + mCompactThrottleBFGS);
             pw.println("  " + KEY_COMPACT_THROTTLE_6 + "=" + mCompactThrottlePersistent);
-            pw.println("  " + KEY_COMPACT_STATSD_SAMPLE_RATE + "=" + mStatsdSampleRate);
+            pw.println("  " + KEY_COMPACT_STATSD_SAMPLE_RATE + "=" + mCompactStatsdSampleRate);
             pw.println("  " + KEY_COMPACT_FULL_RSS_THROTTLE_KB + "="
                     + mFullAnonRssThrottleKb);
             pw.println("  " + KEY_COMPACT_FULL_DELTA_RSS_THROTTLE_KB + "="
@@ -283,6 +312,8 @@
 
             pw.println("  Tracking last compaction stats for " + mLastCompactionStats.size()
                     + " processes.");
+            pw.println(" " + KEY_USE_FREEZER + "=" + mUseFreezer);
+            pw.println("  " + KEY_FREEZER_STATSD_SAMPLE_RATE + "=" + mFreezerStatsdSampleRate);
             if (DEBUG_COMPACTION) {
                 for (Map.Entry<Integer, LastCompactionStats> entry
                         : mLastCompactionStats.entrySet()) {
@@ -356,18 +387,76 @@
 
     /**
      * Reads the flag value from DeviceConfig to determine whether app compaction
-     * should be enabled, and starts the compaction thread if needed.
+     * should be enabled, and starts the freeze/compaction thread if needed.
      */
     @GuardedBy("mPhenotypeFlagLock")
     private void updateUseCompaction() {
         mUseCompaction = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                     KEY_USE_COMPACTION, DEFAULT_USE_COMPACTION);
-        if (mUseCompaction && !mCachedAppOptimizerThread.isAlive()) {
-            mCachedAppOptimizerThread.start();
+
+        if (mUseCompaction) {
+            if (!mCachedAppOptimizerThread.isAlive()) {
+                mCachedAppOptimizerThread.start();
+            }
+
             mCompactionHandler = new MemCompactionHandler();
         }
     }
 
+    /**
+     * Determines whether the freezer is correctly supported by this system
+     */
+    public boolean isFreezerSupported() {
+        boolean supported = false;
+        FileReader fr = null;
+
+        try {
+            fr = new FileReader("/dev/freezer/frozen/freezer.killable");
+            int i = fr.read();
+
+            if ((char) i == '1') {
+                supported = true;
+            } else {
+                Slog.w(TAG_AM, "Freezer killability is turned off, disabling freezer");
+            }
+        } catch (java.io.FileNotFoundException e) {
+            Slog.d(TAG_AM, "Freezer.killable not present, disabling freezer");
+        } catch (Exception e) {
+            Slog.d(TAG_AM, "Unable to read freezer.killable, disabling freezer: " + e.toString());
+        }
+
+        if (fr != null) {
+            try {
+                fr.close();
+            } catch (java.io.IOException e) {
+                Slog.e(TAG_AM, "Exception closing freezer.killable: " + e.toString());
+            }
+        }
+
+        return supported;
+    }
+
+    /**
+     * Reads the flag value from DeviceConfig to determine whether app freezer
+     * should be enabled, and starts the freeze/compaction thread if needed.
+     */
+    @GuardedBy("mPhenotypeFlagLock")
+    private void updateUseFreezer() {
+        if (DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                    KEY_USE_FREEZER, DEFAULT_USE_FREEZER)) {
+            mUseFreezer = isFreezerSupported();
+        }
+
+        if (mUseFreezer) {
+            Slog.d(TAG_AM, "Freezer enabled");
+            if (!mCachedAppOptimizerThread.isAlive()) {
+                mCachedAppOptimizerThread.start();
+            }
+
+            mFreezeHandler = new FreezeHandler();
+        }
+    }
+
     @GuardedBy("mPhenotypeFlagLock")
     private void updateCompactionActions() {
         int compactAction1 = DeviceConfig.getInt(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
@@ -433,10 +522,17 @@
     }
 
     @GuardedBy("mPhenotypeFlagLock")
-    private void updateStatsdSampleRate() {
-        mStatsdSampleRate = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+    private void updateCompactStatsdSampleRate() {
+        mCompactStatsdSampleRate = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                 KEY_COMPACT_STATSD_SAMPLE_RATE, DEFAULT_STATSD_SAMPLE_RATE);
-        mStatsdSampleRate = Math.min(1.0f, Math.max(0.0f, mStatsdSampleRate));
+        mCompactStatsdSampleRate = Math.min(1.0f, Math.max(0.0f, mCompactStatsdSampleRate));
+    }
+
+    @GuardedBy("mPhenotypeFlagLock")
+    private void updateFreezerStatsdSampleRate() {
+        mFreezerStatsdSampleRate = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                KEY_FREEZER_STATSD_SAMPLE_RATE, DEFAULT_STATSD_SAMPLE_RATE);
+        mFreezerStatsdSampleRate = Math.min(1.0f, Math.max(0.0f, mFreezerStatsdSampleRate));
     }
 
     @GuardedBy("mPhenotypeFlagLock")
@@ -507,6 +603,24 @@
         }
     }
 
+    @GuardedBy("mAm")
+    void freezeAppAsync(ProcessRecord app) {
+        mFreezeHandler.removeMessages(SET_FROZEN_PROCESS_MSG, app);
+
+        mFreezeHandler.sendMessageDelayed(
+                mFreezeHandler.obtainMessage(
+                    SET_FROZEN_PROCESS_MSG, DO_FREEZE, 0, app),
+                FREEZE_TIMEOUT_MS);
+    }
+
+    @GuardedBy("mAm")
+    void unfreezeAppAsync(ProcessRecord app) {
+        mFreezeHandler.removeMessages(SET_FROZEN_PROCESS_MSG, app);
+
+        mFreezeHandler.sendMessage(
+                mFreezeHandler.obtainMessage(SET_FROZEN_PROCESS_MSG, DO_UNFREEZE, 0, app));
+    }
+
     private static final class LastCompactionStats {
         private final long[] mRssAfterCompaction;
 
@@ -734,7 +848,7 @@
                         // Note that as above not taking mPhenoTypeFlagLock here to avoid locking
                         // on every single compaction for a flag that will seldom change and the
                         // impact of reading the wrong value here is low.
-                        if (mRandom.nextFloat() < mStatsdSampleRate) {
+                        if (mRandom.nextFloat() < mCompactStatsdSampleRate) {
                             StatsLog.write(StatsLog.APP_COMPACTED, pid, name, pendingAction,
                                     rssBefore[0], rssBefore[1], rssBefore[2], rssBefore[3],
                                     rssAfter[0], rssAfter[1], rssAfter[2], rssAfter[3], time,
@@ -768,4 +882,119 @@
             }
         }
     }
+
+    private final class FreezeHandler extends Handler {
+        private FreezeHandler() {
+            super(mCachedAppOptimizerThread.getLooper());
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            if (msg.what != SET_FROZEN_PROCESS_MSG) {
+                return;
+            }
+
+            if (msg.arg1 == DO_FREEZE) {
+                freezeProcess((ProcessRecord) msg.obj);
+            } else if (msg.arg1 == DO_UNFREEZE) {
+                unfreezeProcess((ProcessRecord) msg.obj);
+            }
+        }
+
+        private void freezeProcess(ProcessRecord proc) {
+            final int pid;
+            final String name;
+            final long unfrozenDuration;
+            final boolean frozen;
+
+            synchronized (mAm) {
+                pid = proc.pid;
+                name = proc.processName;
+
+                if (proc.curAdj <= ProcessList.CACHED_APP_MIN_ADJ) {
+                    if (DEBUG_FREEZER) {
+                        Slog.d(TAG_AM, "Skipping freeze for process " + pid
+                                + " " + name + " (not cached)");
+                    }
+                    return;
+                }
+
+                if (pid == 0 || proc.frozen) {
+                    // Already frozen or not a real process, either one being
+                    // launched or one being killed
+                    return;
+                }
+
+                long unfreezeTime = proc.freezeUnfreezeTime;
+
+                try {
+                    Process.setProcessFrozen(pid, proc.uid, true);
+
+                    proc.freezeUnfreezeTime = SystemClock.uptimeMillis();
+                    proc.frozen = true;
+                } catch (Exception e) {
+                    Slog.w(TAG_AM, "Unable to freeze " + pid + " " + name);
+                }
+
+                unfrozenDuration = proc.freezeUnfreezeTime - unfreezeTime;
+                frozen = proc.frozen;
+            }
+
+            if (frozen) {
+                if (DEBUG_FREEZER) {
+                    Slog.d(TAG_AM, "froze " + pid + " " + name);
+                }
+
+                EventLog.writeEvent(EventLogTags.AM_FREEZE, pid, name);
+            }
+        }
+
+        private void unfreezeProcess(ProcessRecord proc) {
+            final int pid;
+            final String name;
+            final long frozenDuration;
+            final boolean frozen;
+
+            synchronized (mAm) {
+                pid = proc.pid;
+                name = proc.processName;
+
+                if (!proc.frozen) {
+                    if (DEBUG_FREEZER) {
+                        Slog.d(TAG_AM,
+                                "Skipping unfreeze for process " + pid + " "
+                                + name + " (not frozen)");
+                    }
+                    return;
+                }
+
+                if (pid == 0) {
+                    // Not a real process, either being launched or killed
+                    return;
+                }
+
+                long freezeTime = proc.freezeUnfreezeTime;
+
+                try {
+                    Process.setProcessFrozen(proc.pid, proc.uid, false);
+
+                    proc.freezeUnfreezeTime = SystemClock.uptimeMillis();
+                    proc.frozen = false;
+                } catch (Exception e) {
+                    Slog.w(TAG_AM, "Unable to unfreeze " + pid + " " + name);
+                }
+
+                frozenDuration = proc.freezeUnfreezeTime - freezeTime;
+                frozen = proc.frozen;
+            }
+
+            if (!frozen) {
+                if (DEBUG_FREEZER) {
+                    Slog.d(TAG_AM, "unfroze " + pid + " " + name);
+                }
+
+                EventLog.writeEvent(EventLogTags.AM_UNFREEZE, pid, name);
+            }
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index 23674bb..cc5df40 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -88,3 +88,8 @@
 # The task is being compacted
 30063 am_compact (Pid|1|5),(Process Name|3),(Action|3),(BeforeRssTotal|2|2),(BeforeRssFile|2|2),(BeforeRssAnon|2|2),(BeforeRssSwap|2|2),(DeltaRssTotal|2|2),(DeltaRssFile|2|2),(DeltaRssAnon|2|2),(DeltaRssSwap|2|2),(Time|2|3),(LastAction|1|2),(LastActionTimestamp|2|3),(setAdj|1|2),(procState|1|2),(BeforeZRAMFree|2|2),(DeltaZRAMFree|2|2)
 
+# The task is being frozen
+30068 am_freeze (Pid|1|5),(Process Name|3)
+
+# The task is being unfrozen
+30069 am_unfreeze (Pid|1|5),(Process Name|3)
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 0429782..3bd7d5c 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -17,6 +17,7 @@
 package com.android.server.am;
 
 import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL_IMPLICIT;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
@@ -35,9 +36,7 @@
 import static android.app.ActivityManager.PROCESS_STATE_SERVICE;
 import static android.app.ActivityManager.PROCESS_STATE_TOP;
 import static android.app.ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
-import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA;
 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION;
-import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE;
 import static android.os.Process.SCHED_OTHER;
 import static android.os.Process.THREAD_GROUP_BACKGROUND;
 import static android.os.Process.THREAD_GROUP_DEFAULT;
@@ -73,10 +72,10 @@
 import android.app.usage.UsageEvents;
 import android.compat.Compatibility;
 import android.compat.annotation.ChangeId;
+import android.compat.annotation.Disabled;
 import android.compat.annotation.EnabledAfter;
 import android.content.Context;
 import android.content.pm.ServiceInfo;
-import android.os.Build;
 import android.os.Debug;
 import android.os.Handler;
 import android.os.IBinder;
@@ -129,13 +128,30 @@
      * to pass while-in-use capabilities from client process to bound service. In targetSdkVersion
      * R and above, if client is a TOP activity, when this flag is present, bound service gets all
      * while-in-use capabilities; when this flag is not present, bound service gets no while-in-use
-     * capabilitiy from client.
+     * capability from client.
      */
     @ChangeId
     @EnabledAfter(targetSdkVersion=android.os.Build.VERSION_CODES.Q)
     static final long PROCESS_CAPABILITY_CHANGE_ID = 136274596L;
 
     /**
+     * In targetSdkVersion R and above, foreground service has camera and microphone while-in-use
+     * capability only when the {@link android.R.attr#foregroundServiceType} is configured as
+     * {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_CAMERA} and
+     * {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_MICROPHONE} respectively in the
+     * manifest file.
+     * In targetSdkVersion below R, foreground service automatically have camera and microphone
+     * capabilities.
+     */
+    @ChangeId
+    //TODO: change to @EnabledAfter when enforcing the feature.
+    @Disabled
+    static final long CAMERA_MICROPHONE_CAPABILITY_CHANGE_ID = 136219221L;
+
+    //TODO: remove this when development is done.
+    private static final int TEMP_PROCESS_CAPABILITY_FOREGROUND_LOCATION = 1 << 31;
+
+    /**
      * For some direct access we need to power manager.
      */
     PowerManagerInternal mLocalPowerManager;
@@ -1412,6 +1428,7 @@
         }
 
         int capabilityFromFGS = 0; // capability from foreground service.
+        boolean procStateFromFGSClient = false;
         for (int is = app.services.size() - 1;
                 is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
                         || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
@@ -1462,19 +1479,21 @@
 
             if (s.isForeground) {
                 final int fgsType = s.foregroundServiceType;
-                capabilityFromFGS |=
-                        (fgsType & FOREGROUND_SERVICE_TYPE_LOCATION)
-                                != 0 ? PROCESS_CAPABILITY_FOREGROUND_LOCATION : 0;
-                if (s.appInfo.targetSdkVersion < Build.VERSION_CODES.R) {
+                if (s.mAllowWhileInUsePermissionInFgs) {
+                    capabilityFromFGS |=
+                            (fgsType & FOREGROUND_SERVICE_TYPE_LOCATION)
+                                    != 0 ? PROCESS_CAPABILITY_FOREGROUND_LOCATION : 0;
+                } else {
+                    //The FGS has the location capability, but due to FGS BG start restriction it
+                    //lost the capability, use temp location capability to mark this case.
+                    //TODO: remove this block when development is done.
+                    capabilityFromFGS |=
+                            (fgsType & FOREGROUND_SERVICE_TYPE_LOCATION)
+                                    != 0 ? TEMP_PROCESS_CAPABILITY_FOREGROUND_LOCATION : 0;
+                }
+                if (s.mAllowWhileInUsePermissionInFgs) {
                     capabilityFromFGS |= PROCESS_CAPABILITY_FOREGROUND_CAMERA
                             | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
-                } else {
-                    capabilityFromFGS |=
-                            (fgsType & FOREGROUND_SERVICE_TYPE_CAMERA)
-                                    != 0 ? PROCESS_CAPABILITY_FOREGROUND_CAMERA : 0;
-                    capabilityFromFGS |=
-                            (fgsType & FOREGROUND_SERVICE_TYPE_MICROPHONE)
-                                    != 0 ? PROCESS_CAPABILITY_FOREGROUND_MICROPHONE : 0;
                 }
             }
 
@@ -1513,13 +1532,17 @@
                             continue;
                         }
 
+                        int clientAdj = client.getCurRawAdj();
+                        int clientProcState = client.getCurRawProcState();
+
+                        if (clientProcState == PROCESS_STATE_FOREGROUND_SERVICE) {
+                            procStateFromFGSClient = true;
+                        }
+
                         if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) {
                             capability |= client.curCapability;
                         }
 
-                        int clientAdj = client.getCurRawAdj();
-                        int clientProcState = client.getCurRawProcState();
-
                         if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) {
                             // If the other app is cached for any reason, for purposes here
                             // we are going to consider it empty.  The specific cached state
@@ -1941,7 +1964,17 @@
         // apply capability from FGS.
         if (app.hasForegroundServices()) {
             capability |= capabilityFromFGS;
+        } else if (!ActivityManager.isProcStateBackground(procState)) {
+            // procState higher than PROCESS_STATE_TRANSIENT_BACKGROUND implicitly has
+            // camera/microphone capability
+            if (procState == PROCESS_STATE_FOREGROUND_SERVICE && procStateFromFGSClient) {
+                // if the FGS state is passed down from client, do not grant implicit capabilities.
+            } else {
+                //TODO: remove this line when enforcing the feature.
+                capability |= PROCESS_CAPABILITY_ALL_IMPLICIT;
+            }
         }
+
         // TOP process has all capabilities.
         if (procState <= PROCESS_STATE_TOP) {
             capability = PROCESS_CAPABILITY_ALL;
@@ -2173,6 +2206,9 @@
             app.repForegroundActivities = app.hasForegroundActivities();
             changes |= ActivityManagerService.ProcessChangeItem.CHANGE_ACTIVITIES;
         }
+
+        updateAppFreezeStateLocked(app);
+
         if (app.getReportedProcState() != app.getCurProcState()) {
             app.setReportedProcState(app.getCurProcState());
             if (app.thread != null) {
@@ -2489,4 +2525,18 @@
     void dumpCachedAppOptimizerSettings(PrintWriter pw) {
         mCachedAppOptimizer.dump(pw);
     }
+
+    @GuardedBy("mService")
+    void updateAppFreezeStateLocked(ProcessRecord app) {
+        if (!mCachedAppOptimizer.useFreezer()) {
+            return;
+        }
+
+        // Use current adjustment when freezing, set adjustment when unfreezing.
+        if (app.curAdj >= ProcessList.CACHED_APP_MIN_ADJ && !app.frozen) {
+            mCachedAppOptimizer.freezeAppAsync(app);
+        } else if (app.setAdj < ProcessList.CACHED_APP_MIN_ADJ && app.frozen) {
+            mCachedAppOptimizer.unfreezeAppAsync(app);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 38cb501..954be20 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -1551,6 +1551,45 @@
         }
     }
 
+    private int[] computeGidsForProcess(int mountExternal, int uid, int[] permGids) {
+        ArrayList<Integer> gidList = new ArrayList<>(permGids.length + 5);
+
+        final int sharedAppGid = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
+        final int cacheAppGid = UserHandle.getCacheAppGid(UserHandle.getAppId(uid));
+        final int userGid = UserHandle.getUserGid(UserHandle.getUserId(uid));
+
+        // Add shared application and profile GIDs so applications can share some
+        // resources like shared libraries and access user-wide resources
+        for (int permGid : permGids) {
+            gidList.add(permGid);
+        }
+        if (sharedAppGid != UserHandle.ERR_GID) {
+            gidList.add(sharedAppGid);
+        }
+        if (cacheAppGid != UserHandle.ERR_GID) {
+            gidList.add(cacheAppGid);
+        }
+        if (userGid != UserHandle.ERR_GID) {
+            gidList.add(userGid);
+        }
+        if (mountExternal == Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE) {
+            // For DownloadProviders and MTP: To grant access to /sdcard/Android/
+            gidList.add(Process.SDCARD_RW_GID);
+        }
+        if (mountExternal == Zygote.MOUNT_EXTERNAL_PASS_THROUGH) {
+            // For the FUSE daemon: To grant access to the lower filesystem.
+            // EmulatedVolumes: /data/media and /mnt/expand/<volume>/data/media
+            // PublicVolumes: /mnt/media_rw/<volume>
+            gidList.add(Process.MEDIA_RW_GID);
+        }
+
+        int[] gidArray = new int[gidList.size()];
+        for (int i = 0; i < gidArray.length; i++) {
+            gidArray[i] = gidList.get(i);
+        }
+        return gidArray;
+    }
+
     /**
      * @return {@code true} if process start is successful, false otherwise.
      */
@@ -1625,38 +1664,7 @@
                     }
                 }
 
-                int numGids = 3;
-                if (mountExternal == Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE
-                        || app.info.packageName.equals("com.android.externalstorage")) {
-                    numGids++;
-                }
-
-                /*
-                 * Add shared application and profile GIDs so applications can share some
-                 * resources like shared libraries and access user-wide resources
-                 */
-                if (ArrayUtils.isEmpty(permGids)) {
-                    gids = new int[numGids];
-                } else {
-                    gids = new int[permGids.length + numGids];
-                    System.arraycopy(permGids, 0, gids, numGids, permGids.length);
-                }
-                gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
-                gids[1] = UserHandle.getCacheAppGid(UserHandle.getAppId(uid));
-                gids[2] = UserHandle.getUserGid(UserHandle.getUserId(uid));
-
-                if (numGids > 3) {
-                    if (app.info.packageName.equals("com.android.externalstorage")) {
-                        // Allows access to 'unreliable' (USB OTG) volumes via SAF
-                        gids[3] = Process.MEDIA_RW_GID;
-                    } else if (mountExternal == Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE) {
-                        gids[3] = Process.SDCARD_RW_GID;
-                    }
-                }
-
-                // Replace any invalid GIDs
-                if (gids[0] == UserHandle.ERR_GID) gids[0] = gids[2];
-                if (gids[1] == UserHandle.ERR_GID) gids[1] = gids[2];
+                gids = computeGidsForProcess(mountExternal, uid, permGids);
             }
             app.mountMode = mountExternal;
             checkSlow(startTime, "startProcess: building args");
@@ -1875,11 +1883,11 @@
     }
 
     @GuardedBy("mService")
-    public void killAppZygoteIfNeededLocked(AppZygote appZygote) {
+    public void killAppZygoteIfNeededLocked(AppZygote appZygote, boolean force) {
         final ApplicationInfo appInfo = appZygote.getAppInfo();
         ArrayList<ProcessRecord> zygoteProcesses = mAppZygoteProcesses.get(appZygote);
-        if (zygoteProcesses != null && zygoteProcesses.size() == 0) {
-            // Only remove if no longer in use now
+        if (zygoteProcesses != null && (force || zygoteProcesses.size() == 0)) {
+            // Only remove if no longer in use now, or forced kill
             mAppZygotes.remove(appInfo.processName, appInfo.uid);
             mAppZygoteProcesses.remove(appZygote);
             mAppIsolatedUidRangeAllocator.freeUidRangeLocked(appInfo);
@@ -1907,7 +1915,7 @@
                 if (app.removed) {
                     // If we stopped this process because the package hosting it was removed,
                     // there's no point in delaying the app zygote kill.
-                    killAppZygoteIfNeededLocked(appZygote);
+                    killAppZygoteIfNeededLocked(appZygote, false /* force */);
                 } else {
                     Message msg = mService.mHandler.obtainMessage(KILL_APP_ZYGOTE_MSG);
                     msg.obj = appZygote;
@@ -2385,6 +2393,33 @@
     }
 
     @GuardedBy("mService")
+    void killAppZygotesLocked(String packageName, int appId, int userId, boolean force) {
+        // See if there are any app zygotes running for this packageName / UID combination,
+        // and kill it if so.
+        final ArrayList<AppZygote> zygotesToKill = new ArrayList<>();
+        for (SparseArray<AppZygote> appZygotes : mAppZygotes.getMap().values()) {
+            for (int i = 0; i < appZygotes.size(); ++i) {
+                final int appZygoteUid = appZygotes.keyAt(i);
+                if (userId != UserHandle.USER_ALL && UserHandle.getUserId(appZygoteUid) != userId) {
+                    continue;
+                }
+                if (appId >= 0 && UserHandle.getAppId(appZygoteUid) != appId) {
+                    continue;
+                }
+                final AppZygote appZygote = appZygotes.valueAt(i);
+                if (packageName != null
+                        && !packageName.equals(appZygote.getAppInfo().packageName)) {
+                    continue;
+                }
+                zygotesToKill.add(appZygote);
+            }
+        }
+        for (AppZygote appZygote : zygotesToKill) {
+            killAppZygoteIfNeededLocked(appZygote, force);
+        }
+    }
+
+    @GuardedBy("mService")
     final boolean killPackageProcessesLocked(String packageName, int appId,
             int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart,
             boolean doit, boolean evenPersistent, boolean setRemoved, String reason) {
@@ -2461,29 +2496,7 @@
         for (int i=0; i<N; i++) {
             removeProcessLocked(procs.get(i), callerWillRestart, allowRestart, reason);
         }
-        // See if there are any app zygotes running for this packageName / UID combination,
-        // and kill it if so.
-        final ArrayList<AppZygote> zygotesToKill = new ArrayList<>();
-        for (SparseArray<AppZygote> appZygotes : mAppZygotes.getMap().values()) {
-            for (int i = 0; i < appZygotes.size(); ++i) {
-                final int appZygoteUid = appZygotes.keyAt(i);
-                if (userId != UserHandle.USER_ALL && UserHandle.getUserId(appZygoteUid) != userId) {
-                    continue;
-                }
-                if (appId >= 0 && UserHandle.getAppId(appZygoteUid) != appId) {
-                    continue;
-                }
-                final AppZygote appZygote = appZygotes.valueAt(i);
-                if (packageName != null
-                        && !packageName.equals(appZygote.getAppInfo().packageName)) {
-                    continue;
-                }
-                zygotesToKill.add(appZygote);
-            }
-        }
-        for (AppZygote appZygote : zygotesToKill) {
-            killAppZygoteIfNeededLocked(appZygote);
-        }
+        killAppZygotesLocked(packageName, appId, userId, false /* force */);
         mService.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_PROCESS_END);
         return N > 0;
     }
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 0e1e0f9..1e2dd2d 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -163,6 +163,8 @@
     long lastCompactTime;       // The last time that this process was compacted
     int reqCompactAction;       // The most recent compaction action requested for this app.
     int lastCompactAction;      // The most recent compaction action performed for this app.
+    boolean frozen;             // True when the process is frozen.
+    long freezeUnfreezeTime;    // Last time the app was (un)frozen, 0 for never
     private int mCurSchedGroup; // Currently desired scheduling class
     int setSchedGroup;          // Last set to background scheduling class
     int trimMemoryLevel;        // Last selected memory trimming level
@@ -623,7 +625,7 @@
         curAdj = setAdj = verifiedAdj = ProcessList.INVALID_ADJ;
         mPersistent = false;
         removed = false;
-        lastStateTime = lastPssTime = nextPssTime = SystemClock.uptimeMillis();
+        freezeUnfreezeTime = lastStateTime = lastPssTime = nextPssTime = SystemClock.uptimeMillis();
         mWindowProcessController = new WindowProcessController(
                 mService.mActivityTaskManager, info, processName, uid, userId, this, this);
         pkgList.put(_info.packageName, new ProcessStats.ProcessStateHolder(_info.longVersionCode));
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index ad316d5..5d8a0f6 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -135,6 +135,16 @@
     private Runnable mStartedWhitelistingBgActivityStartsCleanUp;
     private ProcessRecord mAppForStartedWhitelistingBgActivityStarts;
 
+    // allow while-in-use permissions in foreground service or not.
+    // while-in-use permissions in FGS started from background might be restricted.
+    boolean mAllowWhileInUsePermissionInFgs;
+    // information string what/why service is denied while-in-use permissions when
+    // foreground service is started from background.
+    // TODO: remove this field after feature development is done
+    String mInfoDenyWhileInUsePermissionInFgs;
+    // the most recent package that start/bind this service.
+    String mRecentCallingPackage;
+
     String stringName;      // caching of toString
 
     private int lastStartId;    // identifier of most recent start request.
@@ -293,6 +303,8 @@
         ProtoUtils.toDuration(proto, ServiceRecordProto.LAST_ACTIVITY_TIME, lastActivity, now);
         ProtoUtils.toDuration(proto, ServiceRecordProto.RESTART_TIME, restartTime, now);
         proto.write(ServiceRecordProto.CREATED_FROM_FG, createdFromFg);
+        proto.write(ServiceRecordProto.ALLOW_WHILE_IN_USE_PERMISSION_IN_FGS,
+                mAllowWhileInUsePermissionInFgs);
 
         if (startRequested || delayedStop || lastStartId != 0) {
             long startToken = proto.start(ServiceRecordProto.START);
@@ -389,6 +401,10 @@
             pw.print(prefix); pw.print("hasStartedWhitelistingBgActivityStarts=");
             pw.println(mHasStartedWhitelistingBgActivityStarts);
         }
+        if (mAllowWhileInUsePermissionInFgs) {
+            pw.print(prefix); pw.print("allowWhileInUsePermissionInFgs=");
+            pw.println(mAllowWhileInUsePermissionInFgs);
+        }
         if (delayed) {
             pw.print(prefix); pw.print("delayed="); pw.println(delayed);
         }
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index afc3d91..c5d6bba 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -1689,6 +1689,9 @@
                     intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
                             | Intent.FLAG_RECEIVER_FOREGROUND);
                     intent.putExtra(Intent.EXTRA_USER_HANDLE, profileUserId);
+                    // Also, add the UserHandle for mainline modules which can't use the @hide
+                    // EXTRA_USER_HANDLE.
+                    intent.putExtra(Intent.EXTRA_USER, UserHandle.of(profileUserId));
                     mInjector.broadcastIntent(intent,
                             null, null, 0, null, null, null, AppOpsManager.OP_NONE,
                             null, false, false, MY_PID, SYSTEM_UID, callingUid, callingPid,
@@ -1705,6 +1708,9 @@
                     intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
                             | Intent.FLAG_RECEIVER_FOREGROUND);
                     intent.putExtra(Intent.EXTRA_USER_HANDLE, profileUserId);
+                    // Also, add the UserHandle for mainline modules which can't use the @hide
+                    // EXTRA_USER_HANDLE.
+                    intent.putExtra(Intent.EXTRA_USER, UserHandle.of(profileUserId));
                     mInjector.broadcastIntent(intent,
                             null, null, 0, null, null, null, AppOpsManager.OP_NONE,
                             null, false, false, MY_PID, SYSTEM_UID, callingUid, callingPid,
@@ -1714,6 +1720,9 @@
                 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
                         | Intent.FLAG_RECEIVER_FOREGROUND);
                 intent.putExtra(Intent.EXTRA_USER_HANDLE, newUserId);
+                // Also, add the UserHandle for mainline modules which can't use the @hide
+                // EXTRA_USER_HANDLE.
+                intent.putExtra(Intent.EXTRA_USER, UserHandle.of(newUserId));
                 mInjector.broadcastIntent(intent,
                         null, null, 0, null, null,
                         new String[] {android.Manifest.permission.MANAGE_USERS},
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 08136a3..1d714a2 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -24,6 +24,7 @@
 import static android.app.AppOpsManager.FILTER_BY_PACKAGE_NAME;
 import static android.app.AppOpsManager.FILTER_BY_UID;
 import static android.app.AppOpsManager.HistoricalOpsRequestFilter;
+import static android.app.AppOpsManager.MODE_ALLOWED;
 import static android.app.AppOpsManager.NoteOpEvent;
 import static android.app.AppOpsManager.OP_CAMERA;
 import static android.app.AppOpsManager.OP_COARSE_LOCATION;
@@ -50,12 +51,14 @@
 import static android.content.Intent.ACTION_PACKAGE_REMOVED;
 import static android.content.Intent.EXTRA_REPLACING;
 import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;
+import static android.os.Process.STATSD_UID;
 
 import android.Manifest;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
 import android.app.ActivityThread;
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
@@ -210,6 +213,9 @@
     private static final int MAX_UNFORWARED_OPS = 10;
     private static final int MAX_UNUSED_POOLED_OBJECTS = 3;
 
+    //TODO: remove this when development is done.
+    private static final int TEMP_PROCESS_CAPABILITY_FOREGROUND_LOCATION = 1 << 31;
+
     Context mContext;
     final AtomicFile mFile;
     final Handler mHandler;
@@ -288,6 +294,8 @@
     @GuardedBy("this")
     private SparseArray<List<Integer>> mSwitchOpToOps;
 
+    private ActivityManagerInternal mActivityManagerInternal;
+
     /**
      * An unsynchronized pool of {@link OpEventProxyInfo} objects.
      */
@@ -423,7 +431,7 @@
     final Constants mConstants;
 
     @VisibleForTesting
-    static final class UidState {
+    final class UidState {
         public final int uid;
 
         public int state = UID_STATE_CACHED;
@@ -431,6 +439,8 @@
         public long pendingStateCommitTime;
         public int capability;
         public int pendingCapability;
+        public boolean appWidgetVisible;
+        public boolean pendingAppWidgetVisible;
 
         public ArrayMap<String, Ops> pkgOps;
         public SparseIntArray opModes;
@@ -439,6 +449,8 @@
         public SparseBooleanArray foregroundOps;
         public boolean hasForegroundWatchers;
 
+        public long lastTimeShowDebugToast;
+
         public UidState(int uid) {
             this.uid = uid;
         }
@@ -457,7 +469,9 @@
 
         int evalMode(int op, int mode) {
             if (mode == AppOpsManager.MODE_FOREGROUND) {
-                if (state <= UID_STATE_TOP) {
+                if (appWidgetVisible) {
+                    return MODE_ALLOWED;
+                } else if (state <= UID_STATE_TOP) {
                     // process is in foreground.
                     return AppOpsManager.MODE_ALLOWED;
                 } else if (state <= AppOpsManager.resolveFirstUnrestrictedUidState(op)) {
@@ -467,14 +481,35 @@
                         case AppOpsManager.OP_COARSE_LOCATION:
                         case AppOpsManager.OP_MONITOR_LOCATION:
                         case AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION:
-                            return ((capability & PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0)
-                                ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED;
+                            if ((capability & PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0) {
+                                return AppOpsManager.MODE_ALLOWED;
+                            } else if ((capability
+                                    & TEMP_PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0) {
+                                // The FGS has the location capability, but due to FGS BG start
+                                // restriction it lost the capability, use temp location capability
+                                // to mark this case.
+                                // TODO change to MODE_IGNORED when enforcing the feature.
+                                maybeShowWhileInUseDebugToast(op, mode);
+                                return AppOpsManager.MODE_ALLOWED;
+                            } else {
+                                return AppOpsManager.MODE_IGNORED;
+                            }
                         case OP_CAMERA:
-                            return ((capability & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0)
-                                    ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED;
+                            if ((capability & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) {
+                                return AppOpsManager.MODE_ALLOWED;
+                            } else {
+                                //TODO change to MODE_IGNORED when enforcing the feature.
+                                maybeShowWhileInUseDebugToast(op, mode);
+                                return AppOpsManager.MODE_ALLOWED;
+                            }
                         case OP_RECORD_AUDIO:
-                            return ((capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0)
-                                    ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED;
+                            if ((capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) {
+                                return AppOpsManager.MODE_ALLOWED;
+                            } else {
+                                //TODO change to MODE_IGNORED when enforcing the feature.
+                                maybeShowWhileInUseDebugToast(op, mode);
+                                return AppOpsManager.MODE_ALLOWED;
+                            }
                         default:
                             return AppOpsManager.MODE_ALLOWED;
                     }
@@ -482,6 +517,27 @@
                     // process is not in foreground.
                     return AppOpsManager.MODE_IGNORED;
                 }
+            } else if (mode == AppOpsManager.MODE_ALLOWED) {
+                switch (op) {
+                    case OP_CAMERA:
+                        if ((capability & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) {
+                            return AppOpsManager.MODE_ALLOWED;
+                        } else {
+                            //TODO change to MODE_IGNORED when enforcing the feature.
+                            maybeShowWhileInUseDebugToast(op, mode);
+                            return AppOpsManager.MODE_ALLOWED;
+                        }
+                    case OP_RECORD_AUDIO:
+                        if ((capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) {
+                            return AppOpsManager.MODE_ALLOWED;
+                        } else {
+                            //TODO change to MODE_IGNORED when enforcing the feature.
+                            maybeShowWhileInUseDebugToast(op, mode);
+                            return AppOpsManager.MODE_ALLOWED;
+                        }
+                    default:
+                        return MODE_ALLOWED;
+                }
             }
             return mode;
         }
@@ -530,6 +586,23 @@
             }
             foregroundOps = which;
         }
+
+        // TODO: remove this toast after feature development is done
+        // If the procstate is foreground service and while-in-use permission is denied, show a
+        // toast message to ask user to file a bugreport so we know how many apps are impacted by
+        // the new background started foreground service while-in-use permission restriction.
+        void maybeShowWhileInUseDebugToast(int op, int mode) {
+            if (state != UID_STATE_FOREGROUND_SERVICE) {
+                return;
+            }
+            final long now = System.currentTimeMillis();
+            if (lastTimeShowDebugToast == 0 ||  now - lastTimeShowDebugToast > 3600000) {
+                lastTimeShowDebugToast = now;
+                mHandler.sendMessage(PooledLambda.obtainMessage(
+                        ActivityManagerInternal::showWhileInUseDebugToast,
+                        mActivityManagerInternal, uid, op, mode));
+            }
+        }
     }
 
     final static class Ops extends SparseArray<Op> {
@@ -1476,6 +1549,7 @@
                         }
                     });
         }
+        mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
     }
 
     public void packageRemoved(int uid, String packageName) {
@@ -1760,6 +1834,15 @@
                 beginTimeMillis, endTimeMillis, flags);
         Objects.requireNonNull(callback, "callback cannot be null");
 
+        ActivityManagerInternal ami = LocalServices.getService(ActivityManagerInternal.class);
+        boolean isCallerInstrumented = ami.isUidCurrentlyInstrumented(Binder.getCallingUid());
+        boolean isCallerStatsCollector = Binder.getCallingUid() == STATSD_UID;
+
+        if (!isCallerStatsCollector && !isCallerInstrumented) {
+            mHandler.post(() -> callback.sendResult(new Bundle()));
+            return;
+        }
+
         mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
                 Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps");
 
@@ -2993,7 +3076,6 @@
             }
             if (DEBUG) Slog.d(TAG, "startOperation: allowing code " + code + " uid " + uid
                     + " package " + resolvedPackageName);
-
             try {
                 featureOp.started(clientId, uidState.state);
             } catch (RemoteException e) {
@@ -3216,7 +3298,9 @@
                 final long firstUnrestrictedUidState = resolveFirstUnrestrictedUidState(code);
                 final boolean resolvedLastFg = uidState.state <= firstUnrestrictedUidState;
                 final boolean resolvedNowFg = uidState.pendingState <= firstUnrestrictedUidState;
-                if (resolvedLastFg == resolvedNowFg) {
+                if (resolvedLastFg == resolvedNowFg
+                        && uidState.capability == uidState.pendingCapability
+                        && uidState.appWidgetVisible == uidState.pendingAppWidgetVisible) {
                     continue;
                 }
                 final ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(code);
@@ -3250,9 +3334,25 @@
         }
         uidState.state = uidState.pendingState;
         uidState.capability = uidState.pendingCapability;
+        uidState.appWidgetVisible = uidState.pendingAppWidgetVisible;
         uidState.pendingStateCommitTime = 0;
     }
 
+    private void updateAppWidgetVisibility(SparseArray<String> uidPackageNames, boolean visible) {
+        synchronized (this) {
+            for (int i = uidPackageNames.size() - 1; i >= 0; i--) {
+                final int uid = uidPackageNames.keyAt(i);
+                final UidState uidState = getUidStateLocked(uid, true);
+                if (uidState != null && (uidState.pendingAppWidgetVisible != visible)) {
+                    uidState.pendingAppWidgetVisible = visible;
+                    if (uidState.pendingAppWidgetVisible != uidState.appWidgetVisible) {
+                        commitUidPendingStateLocked(uidState);
+                    }
+                }
+            }
+        }
+    }
+
     /**
      * Verify that package belongs to uid and return whether the package is privileged.
      *
@@ -4475,8 +4575,6 @@
         pw.println("    Limit output to data associated with the given feature id.");
         pw.println("  --watchers");
         pw.println("    Only output the watcher sections.");
-        pw.println("  --history");
-        pw.println("    Output the historical data.");
     }
 
     private void dumpStatesLocked(@NonNull PrintWriter pw, @Nullable String filterFeatureId,
@@ -4609,6 +4707,7 @@
         int dumpUid = Process.INVALID_UID;
         int dumpMode = -1;
         boolean dumpWatchers = false;
+        // TODO ntmyren: Remove the dumpHistory and dumpFilter
         boolean dumpHistory = false;
         @HistoricalOpsRequestFilter int dumpFilter = 0;
 
@@ -4671,8 +4770,6 @@
                     }
                 } else if ("--watchers".equals(arg)) {
                     dumpWatchers = true;
-                } else if ("--history".equals(arg)) {
-                    dumpHistory = true;
                 } else if (arg.length() > 0 && arg.charAt(0) == '-'){
                     pw.println("Unknown option: " + arg);
                     return;
@@ -5491,5 +5588,11 @@
                 mProfileOwners = owners;
             }
         }
+
+        @Override
+        public void updateAppWidgetVisibility(SparseArray<String> uidPackageNames,
+                boolean visible) {
+            AppOpsService.this.updateAppWidgetVisibility(uidPackageNames, visible);
+        }
     }
 }
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index bb8b12e..4d5af9a 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -16,6 +16,11 @@
 
 package com.android.server.compat;
 
+import static android.Manifest.permission.LOG_COMPAT_CHANGE;
+import static android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG;
+import static android.Manifest.permission.READ_COMPAT_CHANGE_CONFIG;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
 import android.app.ActivityManager;
 import android.app.IActivityManager;
 import android.content.Context;
@@ -68,12 +73,14 @@
 
     @Override
     public void reportChange(long changeId, ApplicationInfo appInfo) {
+        checkCompatChangeLogPermission();
         reportChange(changeId, appInfo.uid,
                 StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__LOGGED);
     }
 
     @Override
     public void reportChangeByPackageName(long changeId, String packageName, int userId) {
+        checkCompatChangeLogPermission();
         ApplicationInfo appInfo = getApplicationInfo(packageName, userId);
         if (appInfo == null) {
             return;
@@ -83,11 +90,13 @@
 
     @Override
     public void reportChangeByUid(long changeId, int uid) {
+        checkCompatChangeLogPermission();
         reportChange(changeId, uid, StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__LOGGED);
     }
 
     @Override
     public boolean isChangeEnabled(long changeId, ApplicationInfo appInfo) {
+        checkCompatChangeReadPermission();
         if (mCompatConfig.isChangeEnabled(changeId, appInfo)) {
             reportChange(changeId, appInfo.uid,
                     StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__ENABLED);
@@ -100,6 +109,7 @@
 
     @Override
     public boolean isChangeEnabledByPackageName(long changeId, String packageName, int userId) {
+        checkCompatChangeReadPermission();
         ApplicationInfo appInfo = getApplicationInfo(packageName, userId);
         if (appInfo == null) {
             return true;
@@ -109,6 +119,7 @@
 
     @Override
     public boolean isChangeEnabledByUid(long changeId, int uid) {
+        checkCompatChangeReadPermission();
         String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
         if (packages == null || packages.length == 0) {
             return true;
@@ -141,6 +152,7 @@
     @Override
     public void setOverrides(CompatibilityChangeConfig overrides, String packageName)
             throws RemoteException, SecurityException {
+        checkCompatChangeOverridePermission();
         mCompatConfig.addOverrides(overrides, packageName);
         killPackage(packageName);
     }
@@ -148,11 +160,13 @@
     @Override
     public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName)
             throws RemoteException, SecurityException {
+        checkCompatChangeOverridePermission();
         mCompatConfig.addOverrides(overrides, packageName);
     }
 
     @Override
     public void clearOverrides(String packageName) throws RemoteException, SecurityException {
+        checkCompatChangeOverridePermission();
         mCompatConfig.removePackageOverrides(packageName);
         killPackage(packageName);
     }
@@ -160,12 +174,14 @@
     @Override
     public void clearOverridesForTest(String packageName)
             throws RemoteException, SecurityException {
+        checkCompatChangeOverridePermission();
         mCompatConfig.removePackageOverrides(packageName);
     }
 
     @Override
     public boolean clearOverride(long changeId, String packageName)
             throws RemoteException, SecurityException {
+        checkCompatChangeOverridePermission();
         boolean existed = mCompatConfig.removeOverride(changeId, packageName);
         killPackage(packageName);
         return existed;
@@ -173,11 +189,13 @@
 
     @Override
     public CompatibilityChangeConfig getAppConfig(ApplicationInfo appInfo) {
+        checkCompatChangeReadPermission();
         return mCompatConfig.getAppConfig(appInfo);
     }
 
     @Override
     public CompatibilityChangeInfo[] listAllChanges() {
+        checkCompatChangeReadPermission();
         return mCompatConfig.dumpChanges();
     }
 
@@ -216,6 +234,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        checkCompatChangeReadPermission();
         if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, "platform_compat", pw)) return;
         mCompatConfig.dumpConfig(pw);
     }
@@ -273,4 +292,25 @@
             Binder.restoreCallingIdentity(identity);
         }
     }
+
+    private void checkCompatChangeLogPermission() throws SecurityException {
+        if (mContext.checkCallingOrSelfPermission(LOG_COMPAT_CHANGE)
+                != PERMISSION_GRANTED) {
+            throw new SecurityException("Cannot log compat change usage");
+        }
+    }
+
+    private void checkCompatChangeReadPermission() throws SecurityException {
+        if (mContext.checkCallingOrSelfPermission(READ_COMPAT_CHANGE_CONFIG)
+                != PERMISSION_GRANTED) {
+            throw new SecurityException("Cannot read compat change");
+        }
+    }
+
+    private void checkCompatChangeOverridePermission() throws SecurityException {
+        if (mContext.checkCallingOrSelfPermission(OVERRIDE_COMPAT_CHANGE_CONFIG)
+                != PERMISSION_GRANTED) {
+            throw new SecurityException("Cannot override compat change");
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
index f2892cc..17e2f69 100644
--- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
+++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
@@ -310,6 +310,11 @@
         return this.VERSION;
     }
 
+    @Override
+    public String getInterfaceHash() {
+        return this.HASH;
+    }
+
     private void addWakeupEvent(WakeupEvent event) {
         String iface = event.iface;
         mWakeupEvents.append(event);
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 0c9abae..423e021 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -954,7 +954,7 @@
         NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig();
         networkAgentConfig.allowBypass = mConfig.allowBypass && !mLockdown;
 
-        mNetworkCapabilities.setEstablishingVpnAppUid(Binder.getCallingUid());
+        mNetworkCapabilities.setOwnerUid(Binder.getCallingUid());
         mNetworkCapabilities.setUids(createUserAndRestrictedProfilesRanges(mUserHandle,
                 mConfig.allowedApplications, mConfig.disallowedApplications));
         long token = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index e7f537b..4ddc391 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -3451,6 +3451,7 @@
                 if (isLoggable) {
                     Slog.v(TAG, "    Dropping sync operation: account doesn't exist.");
                 }
+                Slog.wtf(TAG, "SYNC_OP_STATE_INVALID: account doesn't exist.");
                 return SYNC_OP_STATE_INVALID;
             }
             // Drop this sync request if it isn't syncable.
@@ -3460,12 +3461,14 @@
                     Slog.v(TAG, "    Dropping sync operation: "
                             + "isSyncable == SYNCABLE_NO_ACCOUNT_ACCESS");
                 }
+                Slog.wtf(TAG, "SYNC_OP_STATE_INVALID_NO_ACCOUNT_ACCESS");
                 return SYNC_OP_STATE_INVALID_NO_ACCOUNT_ACCESS;
             }
             if (state == AuthorityInfo.NOT_SYNCABLE) {
                 if (isLoggable) {
                     Slog.v(TAG, "    Dropping sync operation: isSyncable == NOT_SYNCABLE");
                 }
+                Slog.wtf(TAG, "SYNC_OP_STATE_INVALID: NOT_SYNCABLE");
                 return SYNC_OP_STATE_INVALID;
             }
 
@@ -3484,6 +3487,7 @@
                 if (isLoggable) {
                     Slog.v(TAG, "    Dropping sync operation: disallowed by settings/network.");
                 }
+                Slog.wtf(TAG, "SYNC_OP_STATE_INVALID: disallowed by settings/network");
                 return SYNC_OP_STATE_INVALID;
             }
             return SYNC_OP_STATE_VALID;
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index aa39926..6ff2767 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -87,7 +87,7 @@
             }
             BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(
                     luxLevels, brightnessLevelsNits);
-            builder.setShortTermModelTimeout(shortTermModelTimeout);
+            builder.setShortTermModelTimeoutMillis(shortTermModelTimeout);
             builder.setShortTermModelLowerLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO);
             builder.setShortTermModelUpperLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO);
             return new PhysicalMappingStrategy(builder.build(), nitsRange, backlightRange,
@@ -739,10 +739,10 @@
 
         @Override
         public long getShortTermModelTimeout() {
-            if (mConfig.getShortTermModelTimeout() >= 0) {
-                return mConfig.getShortTermModelTimeout();
+            if (mConfig.getShortTermModelTimeoutMillis() >= 0) {
+                return mConfig.getShortTermModelTimeoutMillis();
             } else {
-                return mDefaultConfig.getShortTermModelTimeout();
+                return mDefaultConfig.getShortTermModelTimeoutMillis();
             }
         }
 
diff --git a/services/core/java/com/android/server/incremental/IncrementalManagerService.java b/services/core/java/com/android/server/incremental/IncrementalManagerService.java
index d673ec8..5876d43 100644
--- a/services/core/java/com/android/server/incremental/IncrementalManagerService.java
+++ b/services/core/java/com/android/server/incremental/IncrementalManagerService.java
@@ -134,7 +134,7 @@
 
     // TODO: remove this
     @Override
-    public void newFileForDataLoader(int mountId, long inode, byte[] metadata) {
+    public void newFileForDataLoader(int mountId, byte[] fileId, byte[] metadata) {
         IDataLoader dataLoader = mDataLoaderManager.getDataLoader(mountId);
         if (dataLoader == null) {
             Slog.e(TAG, "Failed to retrieve data loader for ID=" + mountId);
diff --git a/services/core/java/com/android/server/incremental/IncrementalManagerShellCommand.java b/services/core/java/com/android/server/incremental/IncrementalManagerShellCommand.java
index 5c18f58..5161a77 100644
--- a/services/core/java/com/android/server/incremental/IncrementalManagerShellCommand.java
+++ b/services/core/java/com/android/server/incremental/IncrementalManagerShellCommand.java
@@ -16,6 +16,10 @@
 
 package com.android.server.incremental;
 
+import static android.content.pm.InstallationFile.FILE_TYPE_OBB;
+import static android.content.pm.PackageInstaller.LOCATION_DATA_APP;
+import static android.content.pm.PackageInstaller.LOCATION_MEDIA_OBB;
+
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -171,7 +175,9 @@
             session = packageInstaller.openSession(sessionId);
             for (int i = 0; i < numFiles; i++) {
                 InstallationFile file = installationFiles.get(i);
-                session.addFile(file.getName(), file.getSize(), file.getMetadata());
+                final int location = file.getFileType() == FILE_TYPE_OBB ? LOCATION_MEDIA_OBB
+                        : LOCATION_DATA_APP;
+                session.addFile(location, file.getName(), file.getSize(), file.getMetadata(), null);
             }
             session.commit(localReceiver.getIntentSender());
             final Intent result = localReceiver.getResult();
diff --git a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
index 2926ec9..15dd646 100644
--- a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
+++ b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
@@ -17,16 +17,15 @@
 package com.android.server.integrity;
 
 import static android.content.Intent.ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION;
+import static android.content.Intent.EXTRA_LONG_VERSION_CODE;
 import static android.content.Intent.EXTRA_ORIGINATING_UID;
 import static android.content.Intent.EXTRA_PACKAGE_NAME;
-import static android.content.Intent.EXTRA_VERSION_CODE;
 import static android.content.integrity.AppIntegrityManager.EXTRA_STATUS;
 import static android.content.integrity.AppIntegrityManager.STATUS_FAILURE;
 import static android.content.integrity.AppIntegrityManager.STATUS_SUCCESS;
+import static android.content.integrity.IntegrityUtils.getHexDigest;
 import static android.content.pm.PackageManager.EXTRA_VERIFICATION_ID;
 
-import static com.android.server.integrity.IntegrityUtils.getHexDigest;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.BroadcastReceiver;
@@ -47,8 +46,8 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.HandlerThread;
-import android.os.RemoteException;
 import android.util.Slog;
+import android.util.StatsLog;
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
@@ -74,18 +73,29 @@
 
 /** Implementation of {@link AppIntegrityManagerService}. */
 public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub {
+    /**
+     * This string will be used as the "installer" for formula evaluation when the app's installer
+     * cannot be determined.
+     *
+     * <p>This may happen for various reasons. e.g., the installing app's package name may not match
+     * its UID.
+     */
+    private static final String UNKNOWN_INSTALLER = "";
+    /**
+     * This string will be used as the "installer" for formula evaluation when the app is being
+     * installed via ADB.
+     */
+    private static final String ADB_INSTALLER = "adb";
+
     private static final String TAG = "AppIntegrityManagerServiceImpl";
 
     private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
-    private static final char[] HEX_CHARS = "0123456789ABCDEF".toCharArray();
     private static final String PACKAGE_INSTALLER = "com.google.android.packageinstaller";
     private static final String BASE_APK_FILE = "base.apk";
     private static final String ALLOWED_INSTALLERS_METADATA_NAME = "allowed-installers";
     private static final String ALLOWED_INSTALLER_DELIMITER = ",";
     private static final String INSTALLER_PACKAGE_CERT_DELIMITER = "\\|";
 
-    private static final String ADB_INSTALLER = "adb";
-    private static final String UNKNOWN_INSTALLER = "";
     private static final String INSTALLER_CERT_NOT_APPLICABLE = "";
 
     // Access to files inside mRulesDir is protected by mRulesLock;
@@ -147,8 +157,7 @@
 
     @Override
     public void updateRuleSet(
-            String version, ParceledListSlice<Rule> rules, IntentSender statusReceiver)
-            throws RemoteException {
+            String version, ParceledListSlice<Rule> rules, IntentSender statusReceiver) {
         String ruleProvider = getCallerPackageNameOrThrow();
 
         mHandler.post(
@@ -161,6 +170,8 @@
                         success = false;
                     }
 
+                    StatsLog.write(StatsLog.INTEGRITY_RULES_PUSHED, success, ruleProvider, version);
+
                     Intent intent = new Intent();
                     intent.putExtra(EXTRA_STATUS, success ? STATUS_SUCCESS : STATUS_FAILURE);
                     try {
@@ -177,7 +188,7 @@
     }
 
     @Override
-    public String getCurrentRuleSetVersion() throws RemoteException {
+    public String getCurrentRuleSetVersion() {
         getCallerPackageNameOrThrow();
 
         RuleMetadata ruleMetadata = mIntegrityFileManager.readMetadata();
@@ -187,7 +198,7 @@
     }
 
     @Override
-    public String getCurrentRuleSetProvider() throws RemoteException {
+    public String getCurrentRuleSetProvider() {
         getCallerPackageNameOrThrow();
 
         RuleMetadata ruleMetadata = mIntegrityFileManager.readMetadata();
@@ -199,14 +210,6 @@
     private void handleIntegrityVerification(Intent intent) {
         int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1);
 
-        // Fail early if we don't have any rules at all.
-        if (!mIntegrityFileManager.initialized()) {
-            Slog.i(TAG, "Rules not initialized. Skipping integrity check.");
-            mPackageManagerInternal.setIntegrityVerificationResult(
-                    verificationId, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
-            return;
-        }
-
         try {
             Slog.i(TAG, "Received integrity verification intent " + intent.toString());
             Slog.i(TAG, "Extras " + intent.getExtras());
@@ -238,7 +241,7 @@
 
             builder.setPackageName(getPackageNameNormalized(packageName));
             builder.setAppCertificate(appCert == null ? "" : appCert);
-            builder.setVersionCode(intent.getIntExtra(EXTRA_VERSION_CODE, -1));
+            builder.setVersionCode(intent.getLongExtra(EXTRA_LONG_VERSION_CODE, -1));
             builder.setInstallerName(getPackageNameNormalized(installerPackageName));
             builder.setInstallerCertificate(
                     getInstallerCertificateFingerprint(installerPackageName));
@@ -257,7 +260,17 @@
                     "Integrity check result: "
                             + result.getEffect()
                             + " due to "
-                            + result.getRule());
+                            + result.getMatchedRules());
+
+            StatsLog.write(
+                    StatsLog.INTEGRITY_CHECK_RESULT_REPORTED,
+                    packageName,
+                    appCert,
+                    appInstallMetadata.getVersionCode(),
+                    installerPackageName,
+                    result.getLoggingResponse(),
+                    result.isCausedByAppCertRule(),
+                    result.isCausedByInstallerRule());
             mPackageManagerInternal.setIntegrityVerificationResult(
                     verificationId,
                     result.getEffect() == IntegrityCheckResult.Effect.ALLOW
diff --git a/services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java b/services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java
index 07eacbf..79e69e1 100644
--- a/services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java
+++ b/services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java
@@ -19,7 +19,7 @@
 import android.content.integrity.AppInstallMetadata;
 import android.content.integrity.AtomicFormula;
 import android.content.integrity.CompoundFormula;
-import android.content.integrity.Formula;
+import android.content.integrity.IntegrityFormula;
 import android.content.integrity.Rule;
 import android.util.Slog;
 
@@ -65,7 +65,7 @@
      * Load, and match the list of rules against an app install metadata.
      *
      * @param appInstallMetadata Metadata of the app to be installed, and to evaluate the rules
-     *     against.
+     *                           against.
      * @return result of the integrity check
      */
     public IntegrityCheckResult evaluate(
@@ -76,6 +76,11 @@
     }
 
     private List<Rule> loadRules(AppInstallMetadata appInstallMetadata) {
+        if (!mIntegrityFileManager.initialized()) {
+            Slog.w(TAG, "Integrity rule files are not available. Evaluating only manifest rules.");
+            return new ArrayList<>();
+        }
+
         try {
             return mIntegrityFileManager.readRules(appInstallMetadata);
         } catch (Exception e) {
@@ -89,14 +94,14 @@
             return Optional.empty();
         }
 
-        List<Formula> formulas = new ArrayList<>(allowedInstallers.size());
+        List<IntegrityFormula> formulas = new ArrayList<>(allowedInstallers.size());
         allowedInstallers.forEach(
                 (installer, cert) -> {
                     formulas.add(allowedInstallerFormula(installer, cert));
                 });
 
         // We need this special case since OR-formulas require at least two operands.
-        Formula allInstallersFormula =
+        IntegrityFormula allInstallersFormula =
                 formulas.size() == 1
                         ? formulas.get(0)
                         : new CompoundFormula(CompoundFormula.OR, formulas);
@@ -108,7 +113,7 @@
                         Rule.DENY));
     }
 
-    private static Formula allowedInstallerFormula(String installer, String cert) {
+    private static IntegrityFormula allowedInstallerFormula(String installer, String cert) {
         return new CompoundFormula(
                 CompoundFormula.AND,
                 Arrays.asList(
@@ -117,8 +122,7 @@
                                 installer,
                                 /* isHashedValue= */ false),
                         new AtomicFormula.StringAtomicFormula(
-                                AtomicFormula.INSTALLER_CERTIFICATE,
-                                cert,
-                                /* isHashedValue= */ false)));
+                                AtomicFormula.INSTALLER_CERTIFICATE, cert, /* isHashedValue= */
+                                false)));
     }
 }
diff --git a/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java b/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java
index b1c20d2..9d94304 100644
--- a/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java
+++ b/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java
@@ -22,12 +22,11 @@
 import android.annotation.NonNull;
 import android.content.integrity.AppInstallMetadata;
 import android.content.integrity.Rule;
-import android.util.Slog;
 
 import com.android.server.integrity.model.IntegrityCheckResult;
 
-import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * A helper class for evaluating rules against app install metadata to find if there are matching
@@ -35,8 +34,6 @@
  */
 final class RuleEvaluator {
 
-    private static final String TAG = "RuleEvaluator";
-
     /**
      * Match the list of rules against an app install metadata.
      *
@@ -51,30 +48,34 @@
     @NonNull
     static IntegrityCheckResult evaluateRules(
             List<Rule> rules, AppInstallMetadata appInstallMetadata) {
-        List<Rule> matchedRules = new ArrayList<>();
-        for (Rule rule : rules) {
-            if (rule.getFormula().isSatisfied(appInstallMetadata)) {
-                matchedRules.add(rule);
-            }
+
+        // Identify the rules that match the {@code appInstallMetadata}.
+        List<Rule> matchedRules =
+                rules.stream()
+                        .filter(rule -> rule.getFormula().matches(appInstallMetadata))
+                        .collect(Collectors.toList());
+
+        // Identify the matched power allow rules and terminate early if we have any.
+        List<Rule> matchedPowerAllowRules =
+                matchedRules.stream()
+                        .filter(rule -> rule.getEffect() == FORCE_ALLOW)
+                        .collect(Collectors.toList());
+
+        if (!matchedPowerAllowRules.isEmpty()) {
+            return IntegrityCheckResult.allow(matchedPowerAllowRules);
         }
 
-        boolean denied = false;
-        Rule denyRule = null;
-        for (Rule rule : matchedRules) {
-            switch (rule.getEffect()) {
-                case DENY:
-                    if (!denied) {
-                        denied = true;
-                        denyRule = rule;
-                    }
-                    break;
-                case FORCE_ALLOW:
-                    return IntegrityCheckResult.allow(rule);
-                default:
-                    Slog.e(TAG, "Matched an unknown effect rule: " + rule);
-                    return IntegrityCheckResult.allow();
-            }
+        // Identify the matched deny rules.
+        List<Rule> matchedDenyRules =
+                matchedRules.stream()
+                        .filter(rule -> rule.getEffect() == DENY)
+                        .collect(Collectors.toList());
+
+        if (!matchedDenyRules.isEmpty()) {
+            return IntegrityCheckResult.deny(matchedDenyRules);
         }
-        return denied ? IntegrityCheckResult.deny(denyRule) : IntegrityCheckResult.allow();
+
+        // When no rules are denied, return default allow result.
+        return IntegrityCheckResult.allow();
     }
 }
diff --git a/services/core/java/com/android/server/integrity/model/BitOutputStream.java b/services/core/java/com/android/server/integrity/model/BitOutputStream.java
index 7d1bb3f..14b35fd 100644
--- a/services/core/java/com/android/server/integrity/model/BitOutputStream.java
+++ b/services/core/java/com/android/server/integrity/model/BitOutputStream.java
@@ -61,7 +61,7 @@
     /**
      * Set the next bit in the stream to value.
      *
-     * @param value The value to set the bit to.
+     * @param value The value to set the bit to
      */
     public void setNext(boolean value) throws IOException {
         int byteToWrite = mNextBitIndex / BYTE_BITS;
diff --git a/services/core/java/com/android/server/integrity/model/IntegrityCheckResult.java b/services/core/java/com/android/server/integrity/model/IntegrityCheckResult.java
index b3cb31a..d6dd046 100644
--- a/services/core/java/com/android/server/integrity/model/IntegrityCheckResult.java
+++ b/services/core/java/com/android/server/integrity/model/IntegrityCheckResult.java
@@ -18,6 +18,10 @@
 
 import android.annotation.Nullable;
 import android.content.integrity.Rule;
+import android.util.StatsLog;
+
+import java.util.Collections;
+import java.util.List;
 
 /**
  * A class encapsulating the result from the evaluation engine after evaluating rules against app
@@ -34,19 +38,19 @@
     }
 
     private final Effect mEffect;
-    @Nullable private final Rule mRule;
+    private final List<Rule> mRuleList;
 
-    private IntegrityCheckResult(Effect effect, @Nullable Rule rule) {
+    private IntegrityCheckResult(Effect effect, @Nullable List<Rule> ruleList) {
         this.mEffect = effect;
-        this.mRule = rule;
+        this.mRuleList = ruleList;
     }
 
     public Effect getEffect() {
         return mEffect;
     }
 
-    public Rule getRule() {
-        return mRule;
+    public List<Rule> getMatchedRules() {
+        return mRuleList;
     }
 
     /**
@@ -55,7 +59,7 @@
      * @return An evaluation outcome with ALLOW effect and no rule.
      */
     public static IntegrityCheckResult allow() {
-        return new IntegrityCheckResult(Effect.ALLOW, null);
+        return new IntegrityCheckResult(Effect.ALLOW, Collections.emptyList());
     }
 
     /**
@@ -63,17 +67,49 @@
      *
      * @return An evaluation outcome with ALLOW effect and rule causing that effect.
      */
-    public static IntegrityCheckResult allow(Rule rule) {
-        return new IntegrityCheckResult(Effect.ALLOW, rule);
+    public static IntegrityCheckResult allow(List<Rule> ruleList) {
+        return new IntegrityCheckResult(Effect.ALLOW, ruleList);
     }
 
     /**
      * Create a DENY evaluation outcome.
      *
-     * @param rule Rule causing the DENY effect.
+     * @param ruleList All valid rules that cause the DENY effect.
      * @return An evaluation outcome with DENY effect and rule causing that effect.
      */
-    public static IntegrityCheckResult deny(Rule rule) {
-        return new IntegrityCheckResult(Effect.DENY, rule);
+    public static IntegrityCheckResult deny(List<Rule> ruleList) {
+        return new IntegrityCheckResult(Effect.DENY, ruleList);
     }
+
+    /**
+     * Returns the in value of the integrity check result for logging purposes.
+     */
+    public int getLoggingResponse() {
+        if (getEffect() == Effect.DENY) {
+            return StatsLog.INTEGRITY_CHECK_RESULT_REPORTED__RESPONSE__REJECTED;
+        } else if (getEffect() == Effect.ALLOW && getMatchedRules().isEmpty()) {
+            return StatsLog.INTEGRITY_CHECK_RESULT_REPORTED__RESPONSE__ALLOWED;
+        } else if (getEffect() == Effect.ALLOW && !getMatchedRules().isEmpty()) {
+            return StatsLog.INTEGRITY_CHECK_RESULT_REPORTED__RESPONSE__FORCE_ALLOWED;
+        } else {
+            throw new IllegalStateException("IntegrityCheckResult is not valid.");
+        }
+    }
+
+    /**
+     * Returns true when the {@code Effect.DENY} result is caused by an app certificate mismatch.
+     */
+    public boolean isCausedByAppCertRule() {
+        // TODO(b/147095027): implement this.
+        return true;
+    }
+
+    /**
+     * Returns true when the {@code Effect.DENY} result is caused by an installer rule.
+     */
+    public boolean isCausedByInstallerRule() {
+        // TODO(b/147095027): implement this.
+        return true;
+    }
+
 }
diff --git a/services/core/java/com/android/server/integrity/parser/BinaryFileOperations.java b/services/core/java/com/android/server/integrity/parser/BinaryFileOperations.java
index 2c5b7d3..f09e035e 100644
--- a/services/core/java/com/android/server/integrity/parser/BinaryFileOperations.java
+++ b/services/core/java/com/android/server/integrity/parser/BinaryFileOperations.java
@@ -19,7 +19,8 @@
 import static com.android.server.integrity.model.ComponentBitSize.IS_HASHED_BITS;
 import static com.android.server.integrity.model.ComponentBitSize.VALUE_SIZE_BITS;
 
-import com.android.server.integrity.IntegrityUtils;
+import android.content.integrity.IntegrityUtils;
+
 import com.android.server.integrity.model.BitInputStream;
 
 import java.io.IOException;
diff --git a/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java b/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
index 90954ff..4b8efaf 100644
--- a/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
+++ b/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
@@ -35,7 +35,7 @@
 
 import android.content.integrity.AtomicFormula;
 import android.content.integrity.CompoundFormula;
-import android.content.integrity.Formula;
+import android.content.integrity.IntegrityFormula;
 import android.content.integrity.Rule;
 
 import com.android.server.integrity.model.BitInputStream;
@@ -121,7 +121,7 @@
     }
 
     private Rule parseRule(BitInputStream bitInputStream) throws IOException {
-        Formula formula = parseFormula(bitInputStream);
+        IntegrityFormula formula = parseFormula(bitInputStream);
         int effect = bitInputStream.getNext(EFFECT_BITS);
 
         if (bitInputStream.getNext(SIGNAL_BIT) != 1) {
@@ -131,7 +131,7 @@
         return new Rule(formula, effect);
     }
 
-    private Formula parseFormula(BitInputStream bitInputStream) throws IOException {
+    private IntegrityFormula parseFormula(BitInputStream bitInputStream) throws IOException {
         int separator = bitInputStream.getNext(SEPARATOR_BITS);
         switch (separator) {
             case ATOMIC_FORMULA_START:
@@ -148,9 +148,9 @@
 
     private CompoundFormula parseCompoundFormula(BitInputStream bitInputStream) throws IOException {
         int connector = bitInputStream.getNext(CONNECTOR_BITS);
-        List<Formula> formulas = new ArrayList<>();
+        List<IntegrityFormula> formulas = new ArrayList<>();
 
-        Formula parsedFormula = parseFormula(bitInputStream);
+        IntegrityFormula parsedFormula = parseFormula(bitInputStream);
         while (parsedFormula != null) {
             formulas.add(parsedFormula);
             parsedFormula = parseFormula(bitInputStream);
@@ -173,8 +173,11 @@
                 String stringValue = getStringValue(bitInputStream, valueSize, isHashedValue);
                 return new AtomicFormula.StringAtomicFormula(key, stringValue, isHashedValue);
             case AtomicFormula.VERSION_CODE:
-                int intValue = getIntValue(bitInputStream);
-                return new AtomicFormula.IntAtomicFormula(key, operator, intValue);
+                // TODO(b/147880712): temporary hack until our input handles long
+                long upper = getIntValue(bitInputStream);
+                long lower = getIntValue(bitInputStream);
+                long longValue = (upper << 32) | lower;
+                return new AtomicFormula.LongAtomicFormula(key, operator, longValue);
             case AtomicFormula.PRE_INSTALLED:
                 boolean booleanValue = getBooleanValue(bitInputStream);
                 return new AtomicFormula.BooleanAtomicFormula(key, booleanValue);
diff --git a/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java b/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java
index 53b0c2e..f37ca1e 100644
--- a/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java
+++ b/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java
@@ -18,7 +18,7 @@
 
 import android.content.integrity.AtomicFormula;
 import android.content.integrity.CompoundFormula;
-import android.content.integrity.Formula;
+import android.content.integrity.IntegrityFormula;
 import android.content.integrity.Rule;
 import android.util.Xml;
 
@@ -107,7 +107,7 @@
     }
 
     private static Rule parseRule(XmlPullParser parser) throws IOException, XmlPullParserException {
-        Formula formula = null;
+        IntegrityFormula formula = null;
         int effect = Integer.parseInt(extractAttributeValue(parser, EFFECT_ATTRIBUTE).orElse("-1"));
 
         int eventType;
@@ -139,11 +139,11 @@
         return new Rule(formula, effect);
     }
 
-    private static Formula parseCompoundFormula(XmlPullParser parser)
+    private static IntegrityFormula parseCompoundFormula(XmlPullParser parser)
             throws IOException, XmlPullParserException {
         int connector =
                 Integer.parseInt(extractAttributeValue(parser, CONNECTOR_ATTRIBUTE).orElse("-1"));
-        List<Formula> formulas = new ArrayList<>();
+        List<IntegrityFormula> formulas = new ArrayList<>();
 
         int eventType;
         while ((eventType = parser.next()) != XmlPullParser.END_DOCUMENT) {
@@ -175,7 +175,7 @@
         return new CompoundFormula(connector, formulas);
     }
 
-    private static Formula parseAtomicFormula(XmlPullParser parser)
+    private static IntegrityFormula parseAtomicFormula(XmlPullParser parser)
             throws IOException, XmlPullParserException {
         int key = Integer.parseInt(extractAttributeValue(parser, KEY_ATTRIBUTE).orElse("-1"));
         int operator =
@@ -193,7 +193,7 @@
         return constructAtomicFormulaBasedOnKey(key, operator, value, isHashedValue);
     }
 
-    private static Formula constructAtomicFormulaBasedOnKey(
+    private static IntegrityFormula constructAtomicFormulaBasedOnKey(
             @AtomicFormula.Key int key,
             @AtomicFormula.Operator int operator,
             String value,
@@ -208,7 +208,7 @@
             case AtomicFormula.PRE_INSTALLED:
                 return new AtomicFormula.BooleanAtomicFormula(key, Boolean.parseBoolean(value));
             case AtomicFormula.VERSION_CODE:
-                return new AtomicFormula.IntAtomicFormula(key, operator, Integer.parseInt(value));
+                return new AtomicFormula.LongAtomicFormula(key, operator, Integer.parseInt(value));
             default:
                 throw new RuntimeException(String.format("Found unexpected key: %d", key));
         }
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
index f5ed975..d014996 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
@@ -36,11 +36,11 @@
 
 import android.content.integrity.AtomicFormula;
 import android.content.integrity.CompoundFormula;
-import android.content.integrity.Formula;
+import android.content.integrity.IntegrityFormula;
+import android.content.integrity.IntegrityUtils;
 import android.content.integrity.Rule;
 
 import com.android.internal.util.Preconditions;
-import com.android.server.integrity.IntegrityUtils;
 import com.android.server.integrity.model.BitOutputStream;
 import com.android.server.integrity.model.ByteTrackedOutputStream;
 
@@ -192,7 +192,7 @@
         bitOutputStream.setNext();
     }
 
-    private void serializeFormula(Formula formula, BitOutputStream bitOutputStream)
+    private void serializeFormula(IntegrityFormula formula, BitOutputStream bitOutputStream)
             throws IOException {
         if (formula instanceof AtomicFormula) {
             serializeAtomicFormula((AtomicFormula) formula, bitOutputStream);
@@ -212,7 +212,7 @@
 
         bitOutputStream.setNext(SEPARATOR_BITS, COMPOUND_FORMULA_START);
         bitOutputStream.setNext(CONNECTOR_BITS, compoundFormula.getConnector());
-        for (Formula formula : compoundFormula.getFormulas()) {
+        for (IntegrityFormula formula : compoundFormula.getFormulas()) {
             serializeFormula(formula, bitOutputStream);
         }
         bitOutputStream.setNext(SEPARATOR_BITS, COMPOUND_FORMULA_END);
@@ -234,11 +234,14 @@
                     stringAtomicFormula.getValue(),
                     stringAtomicFormula.getIsHashedValue(),
                     bitOutputStream);
-        } else if (atomicFormula.getTag() == AtomicFormula.INT_ATOMIC_FORMULA_TAG) {
-            AtomicFormula.IntAtomicFormula intAtomicFormula =
-                    (AtomicFormula.IntAtomicFormula) atomicFormula;
-            bitOutputStream.setNext(OPERATOR_BITS, intAtomicFormula.getOperator());
-            serializeIntValue(intAtomicFormula.getValue(), bitOutputStream);
+        } else if (atomicFormula.getTag() == AtomicFormula.LONG_ATOMIC_FORMULA_TAG) {
+            AtomicFormula.LongAtomicFormula longAtomicFormula =
+                    (AtomicFormula.LongAtomicFormula) atomicFormula;
+            bitOutputStream.setNext(OPERATOR_BITS, longAtomicFormula.getOperator());
+            // TODO(b/147880712): Temporary hack until we support long values in bitOutputStream
+            long value = longAtomicFormula.getValue();
+            serializeIntValue((int) (value >>> 32), bitOutputStream);
+            serializeIntValue((int) value, bitOutputStream);
         } else if (atomicFormula.getTag() == AtomicFormula.BOOLEAN_ATOMIC_FORMULA_TAG) {
             AtomicFormula.BooleanAtomicFormula booleanAtomicFormula =
                     (AtomicFormula.BooleanAtomicFormula) atomicFormula;
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java b/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java
index 7d9a901..6f7d172 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java
@@ -22,7 +22,7 @@
 
 import android.content.integrity.AtomicFormula;
 import android.content.integrity.CompoundFormula;
-import android.content.integrity.Formula;
+import android.content.integrity.IntegrityFormula;
 import android.content.integrity.Rule;
 
 import java.util.ArrayList;
@@ -76,15 +76,15 @@
         return typeOrganizedRuleMap;
     }
 
-    private static RuleIndexingDetails getIndexingDetails(Formula formula) {
+    private static RuleIndexingDetails getIndexingDetails(IntegrityFormula formula) {
         switch (formula.getTag()) {
-            case Formula.COMPOUND_FORMULA_TAG:
+            case IntegrityFormula.COMPOUND_FORMULA_TAG:
                 return getIndexingDetailsForCompoundFormula((CompoundFormula) formula);
-            case Formula.STRING_ATOMIC_FORMULA_TAG:
+            case IntegrityFormula.STRING_ATOMIC_FORMULA_TAG:
                 return getIndexingDetailsForStringAtomicFormula(
                         (AtomicFormula.StringAtomicFormula) formula);
-            case Formula.INT_ATOMIC_FORMULA_TAG:
-            case Formula.BOOLEAN_ATOMIC_FORMULA_TAG:
+            case IntegrityFormula.LONG_ATOMIC_FORMULA_TAG:
+            case IntegrityFormula.BOOLEAN_ATOMIC_FORMULA_TAG:
                 // Package name and app certificate related formulas are string atomic formulas.
                 return new RuleIndexingDetails(NOT_INDEXED);
             default:
@@ -96,7 +96,7 @@
     private static RuleIndexingDetails getIndexingDetailsForCompoundFormula(
             CompoundFormula compoundFormula) {
         int connector = compoundFormula.getConnector();
-        List<Formula> formulas = compoundFormula.getFormulas();
+        List<IntegrityFormula> formulas = compoundFormula.getFormulas();
 
         switch (connector) {
             case CompoundFormula.AND:
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
index 8f164e6..6e12180 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
@@ -22,7 +22,7 @@
 
 import android.content.integrity.AtomicFormula;
 import android.content.integrity.CompoundFormula;
-import android.content.integrity.Formula;
+import android.content.integrity.IntegrityFormula;
 import android.content.integrity.Rule;
 import android.util.Xml;
 
@@ -128,7 +128,8 @@
         xmlSerializer.endTag(NAMESPACE, RULE_TAG);
     }
 
-    private void serializeFormula(Formula formula, XmlSerializer xmlSerializer) throws IOException {
+    private void serializeFormula(IntegrityFormula formula, XmlSerializer xmlSerializer)
+            throws IOException {
         if (formula instanceof AtomicFormula) {
             serializeAtomicFormula((AtomicFormula) formula, xmlSerializer);
         } else if (formula instanceof CompoundFormula) {
@@ -147,7 +148,7 @@
         xmlSerializer.startTag(NAMESPACE, COMPOUND_FORMULA_TAG);
         serializeAttributeValue(
                 CONNECTOR_ATTRIBUTE, String.valueOf(compoundFormula.getConnector()), xmlSerializer);
-        for (Formula formula : compoundFormula.getFormulas()) {
+        for (IntegrityFormula formula : compoundFormula.getFormulas()) {
             serializeFormula(formula, xmlSerializer);
         }
         xmlSerializer.endTag(NAMESPACE, COMPOUND_FORMULA_TAG);
@@ -171,14 +172,14 @@
                     String.valueOf(
                             ((AtomicFormula.StringAtomicFormula) atomicFormula).getIsHashedValue()),
                     xmlSerializer);
-        } else if (atomicFormula.getTag() == AtomicFormula.INT_ATOMIC_FORMULA_TAG) {
+        } else if (atomicFormula.getTag() == AtomicFormula.LONG_ATOMIC_FORMULA_TAG) {
             serializeAttributeValue(
                     OPERATOR_ATTRIBUTE,
-                    String.valueOf(((AtomicFormula.IntAtomicFormula) atomicFormula).getOperator()),
+                    String.valueOf(((AtomicFormula.LongAtomicFormula) atomicFormula).getOperator()),
                     xmlSerializer);
             serializeAttributeValue(
                     VALUE_ATTRIBUTE,
-                    String.valueOf(((AtomicFormula.IntAtomicFormula) atomicFormula).getValue()),
+                    String.valueOf(((AtomicFormula.LongAtomicFormula) atomicFormula).getValue()),
                     xmlSerializer);
         } else if (atomicFormula.getTag() == AtomicFormula.BOOLEAN_ATOMIC_FORMULA_TAG) {
             serializeAttributeValue(
diff --git a/services/core/java/com/android/server/location/AbstractLocationProvider.java b/services/core/java/com/android/server/location/AbstractLocationProvider.java
index ed6a759..5afa48a 100644
--- a/services/core/java/com/android/server/location/AbstractLocationProvider.java
+++ b/services/core/java/com/android/server/location/AbstractLocationProvider.java
@@ -79,9 +79,9 @@
                 Collections.emptySet());
 
         /**
-         * The provider's enabled state.
+         * The provider's allowed state.
          */
-        public final boolean enabled;
+        public final boolean allowed;
 
         /**
          * The provider's properties.
@@ -93,18 +93,18 @@
          */
         public final Set<String> providerPackageNames;
 
-        private State(boolean enabled, ProviderProperties properties,
+        private State(boolean allowed, ProviderProperties properties,
                 Set<String> providerPackageNames) {
-            this.enabled = enabled;
+            this.allowed = allowed;
             this.properties = properties;
             this.providerPackageNames = Objects.requireNonNull(providerPackageNames);
         }
 
-        private State withEnabled(boolean enabled) {
-            if (enabled == this.enabled) {
+        private State withAllowed(boolean allowed) {
+            if (allowed == this.allowed) {
                 return this;
             } else {
-                return new State(enabled, properties, providerPackageNames);
+                return new State(allowed, properties, providerPackageNames);
             }
         }
 
@@ -112,7 +112,7 @@
             if (properties.equals(this.properties)) {
                 return this;
             } else {
-                return new State(enabled, properties, providerPackageNames);
+                return new State(allowed, properties, providerPackageNames);
             }
         }
 
@@ -120,7 +120,7 @@
             if (providerPackageNames.equals(this.providerPackageNames)) {
                 return this;
             } else {
-                return new State(enabled, properties, providerPackageNames);
+                return new State(allowed, properties, providerPackageNames);
             }
         }
 
@@ -133,13 +133,13 @@
                 return false;
             }
             State state = (State) o;
-            return enabled == state.enabled && properties == state.properties
+            return allowed == state.allowed && properties == state.properties
                     && providerPackageNames.equals(state.providerPackageNames);
         }
 
         @Override
         public int hashCode() {
-            return Objects.hash(enabled, properties, providerPackageNames);
+            return Objects.hash(allowed, properties, providerPackageNames);
         }
     }
 
@@ -259,10 +259,10 @@
     }
 
     /**
-     * The current enabled state of this provider.
+     * The current allowed state of this provider.
      */
-    protected boolean isEnabled() {
-        return mInternalState.get().state.enabled;
+    protected boolean isAllowed() {
+        return mInternalState.get().state.allowed;
     }
 
     /**
@@ -281,10 +281,10 @@
     }
 
     /**
-     * Call this method to report a change in provider enabled/disabled status.
+     * Call this method to report a change in provider allowed status.
      */
-    protected void setEnabled(boolean enabled) {
-        setState(state -> state.withEnabled(enabled));
+    protected void setAllowed(boolean allowed) {
+        setState(state -> state.withAllowed(allowed));
     }
 
     /**
@@ -358,6 +358,19 @@
     protected void onExtraCommand(int uid, int pid, String command, Bundle extras) {}
 
     /**
+     * Requests a provider to enable itself for the given user id.
+     */
+    public final void requestSetAllowed(boolean allowed) {
+        // all calls into the provider must be moved onto the provider thread to prevent deadlock
+        mExecutor.execute(() -> onRequestSetAllowed(allowed));
+    }
+
+    /**
+     * Always invoked on the provider executor.
+     */
+    protected void onRequestSetAllowed(boolean allowed) {}
+
+    /**
      * Dumps debug or log information. May be invoked from any thread.
      */
     public abstract void dump(FileDescriptor fd, PrintWriter pw, String[] args);
diff --git a/services/core/java/com/android/server/location/ContextHubClientBroker.java b/services/core/java/com/android/server/location/ContextHubClientBroker.java
index 45d9bae..e27eb65 100644
--- a/services/core/java/com/android/server/location/ContextHubClientBroker.java
+++ b/services/core/java/com/android/server/location/ContextHubClientBroker.java
@@ -16,6 +16,8 @@
 
 package com.android.server.location;
 
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
 import android.Manifest;
 import android.app.PendingIntent;
 import android.content.Context;
@@ -33,6 +35,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Log;
+import android.util.proto.ProtoOutputStream;
 
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Supplier;
@@ -109,6 +112,11 @@
     private AtomicBoolean mIsPendingIntentCancelled = new AtomicBoolean(false);
 
     /*
+     * True if the application creating the client has the ACCESS_CONTEXT_HUB permission.
+     */
+    private final boolean mHasAccessContextHubPermission;
+
+    /*
      * Helper class to manage registered PendingIntent requests from the client.
      */
     private class PendingIntentRequest {
@@ -165,6 +173,9 @@
         mCallbackInterface = callback;
         mPendingIntentRequest = new PendingIntentRequest();
         mPackage = mContext.getPackageManager().getNameForUid(Binder.getCallingUid());
+
+        mHasAccessContextHubPermission = context.checkCallingPermission(
+            Manifest.permission.ACCESS_CONTEXT_HUB) == PERMISSION_GRANTED;
     }
 
     /* package */ ContextHubClientBroker(
@@ -178,6 +189,9 @@
         mHostEndPointId = hostEndPointId;
         mPendingIntentRequest = new PendingIntentRequest(pendingIntent, nanoAppId);
         mPackage = pendingIntent.getCreatorPackage();
+
+        mHasAccessContextHubPermission = context.checkCallingPermission(
+            Manifest.permission.ACCESS_CONTEXT_HUB) == PERMISSION_GRANTED;
     }
 
     /**
@@ -415,10 +429,12 @@
      */
     private void doSendPendingIntent(PendingIntent pendingIntent, Intent intent) {
         try {
+            String requiredPermission = mHasAccessContextHubPermission
+                    ? Manifest.permission.ACCESS_CONTEXT_HUB
+                    : Manifest.permission.LOCATION_HARDWARE;
             pendingIntent.send(
                     mContext, 0 /* code */, intent, null /* onFinished */, null /* Handler */,
-                    Manifest.permission.LOCATION_HARDWARE /* requiredPermission */,
-                    null /* options */);
+                    requiredPermission, null /* options */);
         } catch (PendingIntent.CanceledException e) {
             mIsPendingIntentCancelled.set(true);
             // The PendingIntent is no longer valid
@@ -449,6 +465,28 @@
         }
     }
 
+    /**
+     * Dump debugging info as ClientBrokerProto
+     *
+     * If the output belongs to a sub message, the caller is responsible for wrapping this function
+     * between {@link ProtoOutputStream#start(long)} and {@link ProtoOutputStream#end(long)}.
+     *
+     * @param proto the ProtoOutputStream to write to
+     */
+    void dump(ProtoOutputStream proto) {
+        proto.write(ClientBrokerProto.ENDPOINT_ID, getHostEndPointId());
+        proto.write(ClientBrokerProto.ATTACHED_CONTEXT_HUB_ID, getAttachedContextHubId());
+        proto.write(ClientBrokerProto.PACKAGE, mPackage);
+        if (mPendingIntentRequest.isValid()) {
+            proto.write(ClientBrokerProto.PENDING_INTENT_REQUEST_VALID, true);
+            proto.write(ClientBrokerProto.NANO_APP_ID, mPendingIntentRequest.getNanoAppId());
+        }
+        proto.write(ClientBrokerProto.HAS_PENDING_INTENT, mPendingIntentRequest.hasPendingIntent());
+        proto.write(ClientBrokerProto.PENDING_INTENT_CANCELLED, isPendingIntentCancelled());
+        proto.write(ClientBrokerProto.REGISTERED, mRegistered);
+
+    }
+
     @Override
     public String toString() {
         String out = "[ContextHubClient ";
diff --git a/services/core/java/com/android/server/location/ContextHubClientManager.java b/services/core/java/com/android/server/location/ContextHubClientManager.java
index 46db8dc..0f70bb8 100644
--- a/services/core/java/com/android/server/location/ContextHubClientManager.java
+++ b/services/core/java/com/android/server/location/ContextHubClientManager.java
@@ -27,10 +27,13 @@
 import android.hardware.location.NanoAppMessage;
 import android.os.RemoteException;
 import android.util.Log;
+import android.util.proto.ProtoOutputStream;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.util.Calendar;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
 import java.util.Iterator;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentLinkedDeque;
@@ -45,6 +48,11 @@
     private static final String TAG = "ContextHubClientManager";
 
     /*
+     * The DateFormat for printing RegistrationRecord.
+     */
+    private static final DateFormat DATE_FORMAT = new SimpleDateFormat("MM/dd HH:mm:ss.SSS");
+
+    /*
      * The maximum host endpoint ID value that a client can be assigned.
      */
     private static final int MAX_CLIENT_ID = 0x7fff;
@@ -123,24 +131,24 @@
     private class RegistrationRecord {
         private final String mBroker;
         private final int mAction;
-        private final String mDate;
+        private final long mTimestamp;
 
         RegistrationRecord(String broker, @Action int action) {
             mBroker = broker;
             mAction = action;
-            Calendar instance = Calendar.getInstance();
-            mDate = String.format("%02d", instance.get(Calendar.MONTH) + 1) // Jan == 0
-                + "/" + String.format("%02d", instance.get(Calendar.DAY_OF_MONTH))
-                + " " + String.format("%02d", instance.get(Calendar.HOUR_OF_DAY))
-                + ":" + String.format("%02d", instance.get(Calendar.MINUTE))
-                + ":" + String.format("%02d", instance.get(Calendar.SECOND))
-                + "." + String.format("%03d", instance.get(Calendar.MILLISECOND));
+            mTimestamp = System.currentTimeMillis();
+        }
+
+        void dump(ProtoOutputStream proto) {
+            proto.write(ClientManagerProto.RegistrationRecord.TIMESTAMP_MS, mTimestamp);
+            proto.write(ClientManagerProto.RegistrationRecord.ACTION, mAction);
+            proto.write(ClientManagerProto.RegistrationRecord.BROKER, mBroker);
         }
 
         @Override
         public String toString() {
             String out = "";
-            out += mDate + " ";
+            out += DATE_FORMAT.format(new Date(mTimestamp)) + " ";
             out += mAction == ACTION_REGISTERED ? "+ " : "- ";
             out += mBroker;
             if (mAction == ACTION_CANCELLED) {
@@ -376,6 +384,28 @@
         return null;
     }
 
+    /**
+     * Dump debugging info as ClientManagerProto
+     *
+     * If the output belongs to a sub message, the caller is responsible for wrapping this function
+     * between {@link ProtoOutputStream#start(long)} and {@link ProtoOutputStream#end(long)}.
+     *
+     * @param proto the ProtoOutputStream to write to
+     */
+    void dump(ProtoOutputStream proto) {
+        for (ContextHubClientBroker broker : mHostEndPointIdToClientMap.values()) {
+            long token = proto.start(ClientManagerProto.CLIENT_BROKERS);
+            broker.dump(proto);
+            proto.end(token);
+        }
+        Iterator<RegistrationRecord> it = mRegistrationRecordDeque.descendingIterator();
+        while (it.hasNext()) {
+            long token = proto.start(ClientManagerProto.REGISTRATION_RECORDS);
+            it.next().dump(proto);
+            proto.end(token);
+        }
+    }
+
     @Override
     public String toString() {
         String out = "";
diff --git a/services/core/java/com/android/server/location/ContextHubService.java b/services/core/java/com/android/server/location/ContextHubService.java
index 787a800..e79eddf 100644
--- a/services/core/java/com/android/server/location/ContextHubService.java
+++ b/services/core/java/com/android/server/location/ContextHubService.java
@@ -43,6 +43,7 @@
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.util.Log;
+import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.util.DumpUtils;
 
@@ -782,6 +783,13 @@
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
+        for (String arg : args) {
+            if ("--proto".equals(arg)) {
+                dump(new ProtoOutputStream(fd));
+                return;
+            }
+        }
+
         pw.println("Dumping ContextHub Service");
 
         pw.println("");
@@ -802,6 +810,20 @@
         // dump eventLog
     }
 
+    private void dump(ProtoOutputStream proto) {
+        mContextHubIdToInfoMap.values().forEach(hubInfo -> {
+            long token = proto.start(ContextHubServiceProto.CONTEXT_HUB_INFO);
+            hubInfo.dump(proto);
+            proto.end(token);
+        });
+
+        long token = proto.start(ContextHubServiceProto.CLIENT_MANAGER);
+        mClientManager.dump(proto);
+        proto.end(token);
+
+        proto.flush();
+    }
+
     private void checkPermissions() {
         ContextHubServiceUtil.checkPermissions(mContext);
     }
diff --git a/services/core/java/com/android/server/location/ContextHubServiceUtil.java b/services/core/java/com/android/server/location/ContextHubServiceUtil.java
index 033437a..76cd9ce 100644
--- a/services/core/java/com/android/server/location/ContextHubServiceUtil.java
+++ b/services/core/java/com/android/server/location/ContextHubServiceUtil.java
@@ -16,6 +16,8 @@
 
 package com.android.server.location;
 
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
 import android.Manifest;
 import android.content.Context;
 import android.hardware.contexthub.V1_0.ContextHub;
@@ -30,11 +32,10 @@
 import android.hardware.location.NanoAppState;
 import android.util.Log;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
-import java.util.ArrayList;
 
 /**
  * A class encapsulating helper functions used by the ContextHubService class
@@ -42,8 +43,7 @@
 /* package */ class ContextHubServiceUtil {
     private static final String TAG = "ContextHubServiceUtil";
     private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE;
-    private static final String ENFORCE_HW_PERMISSION_MESSAGE = "Permission '"
-            + HARDWARE_PERMISSION + "' not granted to access ContextHub Hardware";
+    private static final String CONTEXT_HUB_PERMISSION = Manifest.permission.ACCESS_CONTEXT_HUB;
 
     /**
      * Creates a ConcurrentHashMap of the Context Hub ID to the ContextHubInfo object given an
@@ -200,7 +200,11 @@
      */
     /* package */
     static void checkPermissions(Context context) {
-        context.enforceCallingPermission(HARDWARE_PERMISSION, ENFORCE_HW_PERMISSION_MESSAGE);
+        if (context.checkCallingPermission(HARDWARE_PERMISSION) != PERMISSION_GRANTED
+                && context.checkCallingPermission(CONTEXT_HUB_PERMISSION) != PERMISSION_GRANTED) {
+            throw new SecurityException(
+                "LOCATION_HARDWARE or ACCESS_CONTEXT_HUB permission required to use Context Hub");
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 15cf190..306e1e3 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -729,7 +729,7 @@
                 }, UserHandle.USER_ALL);
 
         setProperties(PROPERTIES);
-        setEnabled(true);
+        setAllowed(true);
     }
 
     /**
diff --git a/services/core/java/com/android/server/location/LocationProviderProxy.java b/services/core/java/com/android/server/location/LocationProviderProxy.java
index 805b018..1dee7a8 100644
--- a/services/core/java/com/android/server/location/LocationProviderProxy.java
+++ b/services/core/java/com/android/server/location/LocationProviderProxy.java
@@ -18,6 +18,8 @@
 
 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
 
+import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
+
 import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Context;
@@ -29,6 +31,7 @@
 import android.util.ArraySet;
 import android.util.Log;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.location.ILocationProvider;
 import com.android.internal.location.ILocationProviderManager;
 import com.android.internal.location.ProviderProperties;
@@ -71,7 +74,7 @@
         @Override
         public void onSetAdditionalProviderPackages(List<String> packageNames) {
             int maxCount = Math.min(MAX_ADDITIONAL_PACKAGES, packageNames.size());
-            ArraySet<String> allPackages = new ArraySet<>(maxCount);
+            ArraySet<String> allPackages = new ArraySet<>(maxCount + 1);
             for (String packageName : packageNames) {
                 if (packageNames.size() >= maxCount) {
                     return;
@@ -86,25 +89,39 @@
                 }
             }
 
-            // add the binder package
-            ComponentName service = mServiceWatcher.getBoundService().component;
-            if (service != null) {
-                allPackages.add(service.getPackageName());
-            }
+            synchronized (mLock) {
+                if (!mBound) {
+                    return;
+                }
 
-            setPackageNames(allPackages);
+                // add the binder package
+                ComponentName service = mServiceWatcher.getBoundService().component;
+                if (service != null) {
+                    allPackages.add(service.getPackageName());
+                }
+
+                setPackageNames(allPackages);
+            }
         }
 
         // executed on binder thread
         @Override
-        public void onSetEnabled(boolean enabled) {
-            setEnabled(enabled);
+        public void onSetAllowed(boolean allowed) {
+            synchronized (mLock) {
+                if (mBound) {
+                    setAllowed(allowed);
+                }
+            }
         }
 
         // executed on binder thread
         @Override
         public void onSetProperties(ProviderProperties properties) {
-            setProperties(properties);
+            synchronized (mLock) {
+                if (mBound) {
+                    setProperties(properties);
+                }
+            }
         }
 
         // executed on binder thread
@@ -114,18 +131,27 @@
         }
     };
 
+    // also used to synchronized any state changes (setEnabled, setProperties, setState, etc)
+    private final Object mLock = new Object();
+
     private final ServiceWatcher mServiceWatcher;
 
-    @Nullable private ProviderRequest mRequest;
+    @GuardedBy("mLock")
+    private boolean mBound;
+    @GuardedBy("mLock")
+    private ProviderRequest mRequest;
 
     private LocationProviderProxy(Context context, String action, int enableOverlayResId,
             int nonOverlayPackageResId) {
-        super(context, FgThread.getExecutor());
+        // safe to use direct executor since none of our callbacks call back into any code above
+        // this provider - they simply forward to the proxy service
+        super(context, DIRECT_EXECUTOR);
 
         mServiceWatcher = new ServiceWatcher(context, FgThread.getHandler(), action, this::onBind,
                 this::onUnbind, enableOverlayResId, nonOverlayPackageResId);
 
-        mRequest = null;
+        mBound = false;
+        mRequest = ProviderRequest.EMPTY_REQUEST;
     }
 
     private boolean register() {
@@ -135,26 +161,35 @@
     private void onBind(IBinder binder) throws RemoteException {
         ILocationProvider provider = ILocationProvider.Stub.asInterface(binder);
 
-        ComponentName service = mServiceWatcher.getBoundService().component;
-        if (service != null) {
-            setPackageNames(Collections.singleton(service.getPackageName()));
-        }
+        synchronized (mLock) {
+            mBound = true;
 
-        provider.setLocationProviderManager(mManager);
+            provider.setLocationProviderManager(mManager);
+            if (!mRequest.equals(ProviderRequest.EMPTY_REQUEST)) {
+                provider.setRequest(mRequest, mRequest.workSource);
+            }
 
-        if (mRequest != null) {
-            provider.setRequest(mRequest, mRequest.workSource);
+            ComponentName service = mServiceWatcher.getBoundService().component;
+            if (service != null) {
+                setPackageNames(Collections.singleton(service.getPackageName()));
+            }
         }
     }
 
     private void onUnbind() {
-        setState(State.EMPTY_STATE);
+        synchronized (mLock) {
+            mBound = false;
+            setState(State.EMPTY_STATE);
+        }
     }
 
     @Override
     public void onSetRequest(ProviderRequest request) {
-        mServiceWatcher.runOnBinder(binder -> {
+        synchronized (mLock) {
             mRequest = request;
+        }
+
+        mServiceWatcher.runOnBinder(binder -> {
             ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
             service.setRequest(request, request.workSource);
         });
@@ -169,7 +204,18 @@
     }
 
     @Override
+    public void onRequestSetAllowed(boolean allowed) {
+        mServiceWatcher.runOnBinder(binder -> {
+            ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
+            service.requestSetAllowed(allowed);
+        });
+    }
+
+    @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("service=" + mServiceWatcher);
+        synchronized (mLock) {
+            pw.println("bound=" + mBound);
+        }
     }
 }
diff --git a/services/core/java/com/android/server/location/LocationRequestStatistics.java b/services/core/java/com/android/server/location/LocationRequestStatistics.java
index 45c8334..b1913389 100644
--- a/services/core/java/com/android/server/location/LocationRequestStatistics.java
+++ b/services/core/java/com/android/server/location/LocationRequestStatistics.java
@@ -92,7 +92,7 @@
     /**
      * A key that holds both package and provider names.
      */
-    public static class PackageProviderKey {
+    public static class PackageProviderKey implements Comparable<PackageProviderKey> {
         /**
          * Name of package requesting location.
          */
@@ -108,6 +108,16 @@
         }
 
         @Override
+        public int compareTo(PackageProviderKey other) {
+            final int providerCompare = providerName.compareTo(other.providerName);
+            if (providerCompare != 0) {
+                return providerCompare;
+            } else {
+                return packageName.compareTo(other.packageName);
+            }
+        }
+
+        @Override
         public boolean equals(Object other) {
             if (!(other instanceof PackageProviderKey)) {
                 return false;
@@ -211,7 +221,7 @@
         void dump(IndentingPrintWriter ipw, long systemElapsedOffsetMillis) {
             StringBuilder s = new StringBuilder();
             long systemTimeMillis = systemElapsedOffsetMillis + mElapsedRealtimeMillis;
-            s.append("At ").append(TimeUtils.formatForLogging(systemTimeMillis)).append(": ")
+            s.append("At ").append(TimeUtils.logTimeOfDay(systemTimeMillis)).append(": ")
                     .append(mIntervalMillis == REQUEST_ENDED_INTERVAL ? "- " : "+ ")
                     .append(String.format("%7s", mProviderName)).append(" request from ")
                     .append(mPackageName);
diff --git a/services/core/java/com/android/server/location/MockProvider.java b/services/core/java/com/android/server/location/MockProvider.java
index 60c9fc1..bcec8b1 100644
--- a/services/core/java/com/android/server/location/MockProvider.java
+++ b/services/core/java/com/android/server/location/MockProvider.java
@@ -42,9 +42,9 @@
         setProperties(properties);
     }
 
-    /** Sets the enabled state of this mock provider. */
-    public void setProviderEnabled(boolean enabled) {
-        setEnabled(enabled);
+    /** Sets the allowed state of this mock provider. */
+    public void setProviderAllowed(boolean allowed) {
+        setAllowed(allowed);
     }
 
     /** Sets the location to report for this mock provider. */
@@ -56,10 +56,15 @@
     }
 
     @Override
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        pw.println("last mock location=" + mLocation);
+    public void onSetRequest(ProviderRequest request) {}
+
+    @Override
+    protected void onRequestSetAllowed(boolean allowed) {
+        setAllowed(allowed);
     }
 
     @Override
-    public void onSetRequest(ProviderRequest request) {}
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("last mock location=" + mLocation);
+    }
 }
diff --git a/services/core/java/com/android/server/location/MockableLocationProvider.java b/services/core/java/com/android/server/location/MockableLocationProvider.java
index f50dfe7..5b4f008 100644
--- a/services/core/java/com/android/server/location/MockableLocationProvider.java
+++ b/services/core/java/com/android/server/location/MockableLocationProvider.java
@@ -170,13 +170,13 @@
     }
 
     /**
-     * Sets the mock provider implementation's enabled state. Will throw an exception if the mock
+     * Sets the mock provider implementation's allowed state. Will throw an exception if the mock
      * provider is not currently the active implementation.
      */
-    public void setMockProviderEnabled(boolean enabled) {
+    public void setMockProviderAllowed(boolean allowed) {
         synchronized (mOwnerLock) {
             Preconditions.checkState(isMock());
-            mMockProvider.setProviderEnabled(enabled);
+            mMockProvider.setProviderAllowed(allowed);
         }
     }
     /**
@@ -233,6 +233,9 @@
         AbstractLocationProvider provider;
         synchronized (mOwnerLock) {
             provider = mProvider;
+            pw.println("allowed=" + getState().allowed);
+            pw.println("properties=" + getState().properties);
+            pw.println("packages=" + getState().providerPackageNames);
             pw.println("request=" + mRequest);
         }
 
diff --git a/services/core/java/com/android/server/location/PassiveProvider.java b/services/core/java/com/android/server/location/PassiveProvider.java
index b338770..ef157a3 100644
--- a/services/core/java/com/android/server/location/PassiveProvider.java
+++ b/services/core/java/com/android/server/location/PassiveProvider.java
@@ -56,7 +56,7 @@
         mReportLocation = false;
 
         setProperties(PROPERTIES);
-        setEnabled(true);
+        setAllowed(true);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/GnssManagerService.java b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
similarity index 97%
rename from services/core/java/com/android/server/GnssManagerService.java
rename to services/core/java/com/android/server/location/gnss/GnssManagerService.java
index 32cdc41..1eb2c52 100644
--- a/services/core/java/com/android/server/GnssManagerService.java
+++ b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server;
+package com.android.server.location.gnss;
 
 import android.Manifest;
 import android.annotation.NonNull;
@@ -45,6 +45,9 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.FgThread;
+import com.android.server.LocationManagerService;
+import com.android.server.LocationManagerServiceUtils;
 import com.android.server.LocationManagerServiceUtils.LinkedListener;
 import com.android.server.LocationManagerServiceUtils.LinkedListenerBase;
 import com.android.server.location.CallerIdentity;
@@ -322,7 +325,7 @@
         synchronized (mGnssBatchingLock) {
             mGnssBatchingCallback = callback;
             mGnssBatchingDeathCallback =
-                    new LocationManagerServiceUtils.LinkedListener<>(
+                    new LinkedListener<>(
                             callback,
                             "BatchedLocationCallback",
                             callerIdentity,
@@ -757,7 +760,10 @@
         }
     }
 
-    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+    /**
+     * Dump for debugging.
+     */
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
         IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
@@ -776,7 +782,7 @@
                     mGnssMeasurementsListeners
                             .values()) {
                 ipw.println(listener + ": " + mLocationManagerService.isThrottlingExemptLocked(
-                        listener.mCallerIdentity));
+                        listener.getCallerIdentity()));
             }
         }
         ipw.decreaseIndent();
@@ -787,7 +793,7 @@
             for (LinkedListenerBase listener :
                     mGnssNavigationMessageListeners.values()) {
                 ipw.println(listener + ": " + mLocationManagerService.isThrottlingExemptLocked(
-                        listener.mCallerIdentity));
+                        listener.getCallerIdentity()));
             }
         }
         ipw.decreaseIndent();
@@ -798,7 +804,7 @@
             for (LinkedListenerBase listener :
                     mGnssStatusListeners.values()) {
                 ipw.println(listener + ": " + mLocationManagerService.isThrottlingExemptLocked(
-                        listener.mCallerIdentity));
+                        listener.getCallerIdentity()));
             }
         }
         ipw.decreaseIndent();
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 1905571..46fb240 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -16,6 +16,7 @@
 
 package com.android.server.media;
 
+import android.annotation.Nullable;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
@@ -92,6 +93,20 @@
             PlaybackState.STATE_CONNECTING,
             PlaybackState.STATE_PLAYING);
 
+    private static final AudioAttributes DEFAULT_ATTRIBUTES =
+            new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build();
+
+    private static int getVolumeStream(@Nullable AudioAttributes attr) {
+        if (attr == null) {
+            return DEFAULT_ATTRIBUTES.getVolumeControlStream();
+        }
+        final int stream = attr.getVolumeControlStream();
+        if (stream == AudioManager.USE_DEFAULT_STREAM_TYPE) {
+            return DEFAULT_ATTRIBUTES.getVolumeControlStream();
+        }
+        return stream;
+    }
+
     private final MessageHandler mHandler;
 
     private final int mOwnerPid;
@@ -162,7 +177,7 @@
         mHandler = new MessageHandler(handlerLooper);
         mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
         mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class);
-        mAudioAttrs = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build();
+        mAudioAttrs = DEFAULT_ATTRIBUTES;
 
         // May throw RemoteException if the session app is killed.
         mSessionCb.mCb.asBinder().linkToDeath(this, 0);
@@ -262,7 +277,7 @@
         }
         if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) {
             // Adjust the volume with a handler not to be blocked by other system service.
-            int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs);
+            int stream = getVolumeStream(mAudioAttrs);
             postAdjustLocalVolume(stream, direction, flags, opPackageName, pid, uid,
                     asSystemService, useSuggested, previousFlagPlaySound);
         } else {
@@ -302,7 +317,7 @@
     private void setVolumeTo(String packageName, String opPackageName, int pid, int uid, int value,
             int flags) {
         if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) {
-            int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs);
+            int stream = getVolumeStream(mAudioAttrs);
             final int volumeValue = value;
             mHandler.post(new Runnable() {
                 @Override
@@ -720,7 +735,7 @@
             volumeType = mVolumeType;
             attributes = mAudioAttrs;
         }
-        int stream = AudioAttributes.toLegacyStreamType(attributes);
+        int stream = getVolumeStream(attributes);
         int max = mAudioManager.getStreamMaxVolume(stream);
         int current = mAudioManager.getStreamVolume(stream);
         return new PlaybackInfo(volumeType, VolumeProvider.VOLUME_CONTROL_ABSOLUTE, max,
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
index 88fc072..feb4f0e 100644
--- a/services/core/java/com/android/server/notification/NotificationDelegate.java
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -48,7 +48,15 @@
             int notificationLocation);
     void onNotificationDirectReplied(String key);
     void onNotificationSettingsViewed(String key);
+    /**
+     * Called when the state of {@link Notification#FLAG_BUBBLE} is changed.
+     */
     void onNotificationBubbleChanged(String key, boolean isBubble);
+    /**
+     * Called when the state of {@link Notification.BubbleMetadata#FLAG_SUPPRESS_NOTIFICATION}
+     * changes.
+     */
+    void onBubbleNotificationSuppressionChanged(String key, boolean isSuppressed);
 
     /**
      * Grant permission to read the specified URI to the package associated with the
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 7cc6732..38ed677 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -117,6 +117,7 @@
 import android.app.IActivityManager;
 import android.app.INotificationManager;
 import android.app.ITransientNotification;
+import android.app.ITransientNotificationCallback;
 import android.app.IUriGrantsManager;
 import android.app.Notification;
 import android.app.NotificationChannel;
@@ -255,6 +256,9 @@
 import com.android.server.lights.LogicalLight;
 import com.android.server.notification.ManagedServices.ManagedServiceInfo;
 import com.android.server.notification.ManagedServices.UserProfiles;
+import com.android.server.notification.toast.CustomToastRecord;
+import com.android.server.notification.toast.TextToastRecord;
+import com.android.server.notification.toast.ToastRecord;
 import com.android.server.pm.PackageManagerService;
 import com.android.server.policy.PhoneWindowManager;
 import com.android.server.statusbar.StatusBarManagerInternal;
@@ -295,8 +299,8 @@
 
 /** {@hide} */
 public class NotificationManagerService extends SystemService {
-    static final String TAG = "NotificationService";
-    static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
+    public static final String TAG = "NotificationService";
+    public static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
     public static final boolean ENABLE_CHILD_NOTIFICATIONS
             = SystemProperties.getBoolean("debug.child_notifs", true);
 
@@ -393,6 +397,7 @@
     private PackageManager mPackageManagerClient;
     AudioManager mAudioManager;
     AudioManagerInternal mAudioManagerInternal;
+    // Can be null for wear
     @Nullable StatusBarManagerInternal mStatusBar;
     Vibrator mVibrator;
     private WindowManagerInternal mWindowManagerInternal;
@@ -513,6 +518,7 @@
     private TriPredicate<String, Integer, String> mAllowedManagedServicePackages;
 
     private final SavePolicyFileRunnable mSavePolicyFile = new SavePolicyFileRunnable();
+    private NotificationRecordLogger mNotificationRecordLogger;
 
     private static class Archive {
         final int mBufferSize;
@@ -849,49 +855,6 @@
         out.endDocument();
     }
 
-    private static final class ToastRecord
-    {
-        public final int pid;
-        public final String pkg;
-        public final IBinder token;
-        public final ITransientNotification callback;
-        public int duration;
-        public int displayId;
-        public Binder windowToken;
-
-        ToastRecord(int pid, String pkg, IBinder token, ITransientNotification callback,
-                int duration, Binder windowToken, int displayId) {
-            this.pid = pid;
-            this.pkg = pkg;
-            this.token = token;
-            this.callback = callback;
-            this.duration = duration;
-            this.windowToken = windowToken;
-            this.displayId = displayId;
-        }
-
-        void update(int duration) {
-            this.duration = duration;
-        }
-
-        void dump(PrintWriter pw, String prefix, DumpFilter filter) {
-            if (filter != null && !filter.matches(pkg)) return;
-            pw.println(prefix + this);
-        }
-
-        @Override
-        public final String toString()
-        {
-            return "ToastRecord{"
-                + Integer.toHexString(System.identityHashCode(this))
-                + " pkg=" + pkg
-                + " token=" + token
-                + " callback=" + callback
-                + " duration=" + duration
-                + "}";
-        }
-    }
-
     @VisibleForTesting
     final NotificationDelegate mNotificationDelegate = new NotificationDelegate() {
 
@@ -1212,6 +1175,34 @@
         }
 
         @Override
+        public void onBubbleNotificationSuppressionChanged(String key, boolean isSuppressed) {
+            synchronized (mNotificationLock) {
+                NotificationRecord r = mNotificationsByKey.get(key);
+                if (r != null) {
+                    Notification.BubbleMetadata data = r.getNotification().getBubbleMetadata();
+                    if (data == null) {
+                        // No data, do nothing
+                        return;
+                    }
+                    boolean currentlySuppressed = data.isNotificationSuppressed();
+                    if (currentlySuppressed == isSuppressed) {
+                        // No changes, do nothing
+                        return;
+                    }
+                    int flags = data.getFlags();
+                    if (isSuppressed) {
+                        flags |= Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
+                    } else {
+                        flags &= ~Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
+                    }
+                    data.setFlags(flags);
+                    mHandler.post(new EnqueueNotificationRunnable(r.getUser().getIdentifier(), r,
+                            true /* isAppForeground */));
+                }
+            }
+        }
+
+        @Override
         /**
          * Grant permission to read the specified URI to the package specified in the
          * NotificationRecord associated with the given key. The callingUid represents the UID of
@@ -1727,7 +1718,14 @@
     }
 
     public NotificationManagerService(Context context) {
+        this(context, new NotificationRecordLoggerImpl());
+    }
+
+    @VisibleForTesting
+    public NotificationManagerService(Context context,
+            NotificationRecordLogger notificationRecordLogger) {
         super(context);
+        mNotificationRecordLogger = notificationRecordLogger;
         Notification.processWhitelistToken = WHITELIST_TOKEN;
     }
 
@@ -2635,6 +2633,19 @@
         return userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId;
     }
 
+    private ToastRecord getToastRecord(int pid, String packageName, IBinder token,
+            @Nullable CharSequence text, @Nullable ITransientNotification callback, int duration,
+            Binder windowToken, int displayId,
+            @Nullable ITransientNotificationCallback textCallback) {
+        if (callback == null) {
+            return new TextToastRecord(this, mStatusBar, pid, packageName, token, text, duration,
+                    windowToken, displayId, textCallback);
+        } else {
+            return new CustomToastRecord(this, pid, packageName, token, callback, duration,
+                    windowToken, displayId);
+        }
+    }
+
     @VisibleForTesting
     NotificationManagerInternal getInternalService() {
         return mInternalService;
@@ -2646,28 +2657,30 @@
         // ============================================================================
 
         @Override
-        public void enqueueTextToast(String pkg, IBinder token, ITransientNotification callback,
-                int duration, int displayId) {
-            enqueueToast(pkg, token, callback, duration, displayId, false);
+        public void enqueueTextToast(String pkg, IBinder token, CharSequence text, int duration,
+                int displayId, @Nullable ITransientNotificationCallback callback) {
+            enqueueToast(pkg, token, text, null, duration, displayId, callback);
         }
 
         @Override
         public void enqueueToast(String pkg, IBinder token, ITransientNotification callback,
                 int duration, int displayId) {
-            enqueueToast(pkg, token, callback, duration, displayId, true);
+            enqueueToast(pkg, token, null, callback, duration, displayId, null);
         }
 
-        private void enqueueToast(String pkg, IBinder token, ITransientNotification callback,
-                int duration, int displayId, boolean isCustomToast) {
+        private void enqueueToast(String pkg, IBinder token, @Nullable CharSequence text,
+                @Nullable ITransientNotification callback, int duration, int displayId,
+                @Nullable ITransientNotificationCallback textCallback) {
             if (DBG) {
-                Slog.i(TAG, "enqueueToast pkg=" + pkg + " callback=" + callback
+                Slog.i(TAG, "enqueueToast pkg=" + pkg + " token=" + token
                         + " duration=" + duration + " displayId=" + displayId);
             }
 
-            if (pkg == null || callback == null || token == null) {
-                Slog.e(TAG, "Not enqueuing toast. pkg=" + pkg + " callback=" + callback + " token="
-                        + token);
-                return ;
+            if (pkg == null || (text == null && callback == null)
+                    || (text != null && callback != null) || token == null) {
+                Slog.e(TAG, "Not enqueuing toast. pkg=" + pkg + " text=" + text + " callback="
+                        + " token=" + token);
+                return;
             }
 
             final int callingUid = Binder.getCallingUid();
@@ -2695,7 +2708,7 @@
                 return;
             }
 
-            if (isCustomToast && !appIsForeground && !isSystemToast) {
+            if (callback != null && !appIsForeground && !isSystemToast) {
                 boolean block;
                 try {
                     block = mPlatformCompat.isChangeEnabledByPackageName(
@@ -2737,28 +2750,28 @@
                             int count = 0;
                             final int N = mToastQueue.size();
                             for (int i=0; i<N; i++) {
-                                 final ToastRecord r = mToastQueue.get(i);
-                                 if (r.pkg.equals(pkg)) {
-                                     count++;
-                                     if (count >= MAX_PACKAGE_NOTIFICATIONS) {
-                                         Slog.e(TAG, "Package has already posted " + count
+                                final ToastRecord r = mToastQueue.get(i);
+                                if (r.pkg.equals(pkg)) {
+                                    count++;
+                                    if (count >= MAX_PACKAGE_NOTIFICATIONS) {
+                                        Slog.e(TAG, "Package has already posted " + count
                                                 + " toasts. Not showing more. Package=" + pkg);
-                                         return;
-                                     }
-                                 }
+                                        return;
+                                    }
+                                }
                             }
                         }
 
                         Binder windowToken = new Binder();
                         mWindowManagerInternal.addWindowToken(windowToken, TYPE_TOAST, displayId);
-                        record = new ToastRecord(callingPid, pkg, token, callback, duration,
-                                windowToken, displayId);
+                        record = getToastRecord(callingPid, pkg, token, text, callback, duration,
+                                windowToken, displayId, textCallback);
                         mToastQueue.add(record);
                         index = mToastQueue.size() - 1;
-                        keepProcessAliveIfNeededLocked(callingPid);
+                        keepProcessAliveForToastIfNeededLocked(callingPid);
                     }
                     // If it's at index 0, it's the current toast.  It doesn't matter if it's
-                    // new or just been updated.  Call back and tell it to show itself.
+                    // new or just been updated, show it.
                     // If the callback fails, this will remove it from the list, so don't
                     // assume that it's valid after this.
                     if (index == 0) {
@@ -6304,9 +6317,11 @@
 
                     mRankingHelper.extractSignals(r);
                     mRankingHelper.sort(mNotificationList);
+                    final int position = mRankingHelper.indexOf(mNotificationList, r);
 
+                    int buzzBeepBlinkLoggingCode = 0;
                     if (!r.isHidden()) {
-                        buzzBeepBlinkLocked(r);
+                        buzzBeepBlinkLoggingCode = buzzBeepBlinkLocked(r);
                     }
 
                     if (notification.getSmallIcon() != null) {
@@ -6346,6 +6361,10 @@
                     }
 
                     maybeRecordInterruptionLocked(r);
+
+                    // Log event to statsd
+                    mNotificationRecordLogger.logNotificationReported(r, old, position,
+                            buzzBeepBlinkLoggingCode);
                 } finally {
                     int N = mEnqueuedNotifications.size();
                     for (int i = 0; i < N; i++) {
@@ -6574,9 +6593,13 @@
 
     @VisibleForTesting
     @GuardedBy("mNotificationLock")
-    void buzzBeepBlinkLocked(NotificationRecord record) {
+    /**
+     * Determine whether this notification should attempt to make noise, vibrate, or flash the LED
+     * @return buzzBeepBlink - bitfield (buzz ? 1 : 0) | (beep ? 2 : 0) | (blink ? 4 : 0)
+     */
+    int buzzBeepBlinkLocked(NotificationRecord record) {
         if (mIsAutomotive && !mNotificationEffectsEnabledForAutomotive) {
-            return;
+            return 0;
         }
         boolean buzz = false;
         boolean beep = false;
@@ -6674,7 +6697,8 @@
         } else if (wasShowLights) {
             updateLightsLocked();
         }
-        if (buzz || beep || blink) {
+        final int buzzBeepBlink = (buzz ? 1 : 0) | (beep ? 2 : 0) | (blink ? 4 : 0);
+        if (buzzBeepBlink > 0) {
             // Ignore summary updates because we don't display most of the information.
             if (record.sbn.isGroup() && record.sbn.getNotification().isGroupSummary()) {
                 if (DEBUG_INTERRUPTIVENESS) {
@@ -6696,10 +6720,11 @@
             MetricsLogger.action(record.getLogMaker()
                     .setCategory(MetricsEvent.NOTIFICATION_ALERT)
                     .setType(MetricsEvent.TYPE_OPEN)
-                    .setSubtype((buzz ? 1 : 0) | (beep ? 2 : 0) | (blink ? 4 : 0)));
+                    .setSubtype(buzzBeepBlink));
             EventLogTags.writeNotificationAlert(key, buzz ? 1 : 0, beep ? 1 : 0, blink ? 1 : 0);
         }
         record.setAudiblyAlerted(buzz || beep);
+        return buzzBeepBlink;
     }
 
     @GuardedBy("mNotificationLock")
@@ -6915,40 +6940,22 @@
     void showNextToastLocked() {
         ToastRecord record = mToastQueue.get(0);
         while (record != null) {
-            if (DBG) Slog.d(TAG, "Show pkg=" + record.pkg + " callback=" + record.callback);
-            try {
-                record.callback.show(record.windowToken);
+            if (record.show()) {
                 scheduleDurationReachedLocked(record);
                 return;
-            } catch (RemoteException e) {
-                Slog.w(TAG, "Object died trying to show notification " + record.callback
-                        + " in package " + record.pkg);
-                // remove it from the list and let the process die
-                int index = mToastQueue.indexOf(record);
-                if (index >= 0) {
-                    mToastQueue.remove(index);
-                }
-                keepProcessAliveIfNeededLocked(record.pid);
-                if (mToastQueue.size() > 0) {
-                    record = mToastQueue.get(0);
-                } else {
-                    record = null;
-                }
             }
+            int index = mToastQueue.indexOf(record);
+            if (index >= 0) {
+                mToastQueue.remove(index);
+            }
+            record = (mToastQueue.size() > 0) ? mToastQueue.get(0) : null;
         }
     }
 
     @GuardedBy("mToastQueue")
     void cancelToastLocked(int index) {
         ToastRecord record = mToastQueue.get(index);
-        try {
-            record.callback.hide();
-        } catch (RemoteException e) {
-            Slog.w(TAG, "Object died trying to hide notification " + record.callback
-                    + " in package " + record.pkg);
-            // don't worry about this, we're about to remove it from
-            // the list anyway
-        }
+        record.hide();
 
         ToastRecord lastToast = mToastQueue.remove(index);
 
@@ -6961,7 +6968,7 @@
         // one way or another.
         scheduleKillTokenTimeout(lastToast);
 
-        keepProcessAliveIfNeededLocked(record.pid);
+        keepProcessAliveForToastIfNeededLocked(record.pid);
         if (mToastQueue.size() > 0) {
             // Show the next one. If the callback fails, this will remove
             // it from the list, so don't assume that the list hasn't changed
@@ -6984,7 +6991,7 @@
     {
         mHandler.removeCallbacksAndMessages(r);
         Message m = Message.obtain(mHandler, MESSAGE_DURATION_REACHED, r);
-        int delay = r.duration == Toast.LENGTH_LONG ? LONG_DELAY : SHORT_DELAY;
+        int delay = r.getDuration() == Toast.LENGTH_LONG ? LONG_DELAY : SHORT_DELAY;
         // Accessibility users may need longer timeout duration. This api compares original delay
         // with user's preference and return longer one. It returns original delay if there's no
         // preference.
@@ -7033,13 +7040,21 @@
         return -1;
     }
 
+    /**
+     * Adjust process {@code pid} importance according to whether it has toasts in the queue or not.
+     */
+    public void keepProcessAliveForToastIfNeeded(int pid) {
+        synchronized (mToastQueue) {
+            keepProcessAliveForToastIfNeededLocked(pid);
+        }
+    }
+
     @GuardedBy("mToastQueue")
-    void keepProcessAliveIfNeededLocked(int pid)
-    {
+    private void keepProcessAliveForToastIfNeededLocked(int pid) {
         int toastCount = 0; // toasts from this pid
         ArrayList<ToastRecord> list = mToastQueue;
-        int N = list.size();
-        for (int i=0; i<N; i++) {
+        int n = list.size();
+        for (int i = 0; i < n; i++) {
             ToastRecord r = list.get(i);
             if (r.pid == pid) {
                 toastCount++;
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 2bea218..660d574 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -675,6 +675,10 @@
         }
     }
 
+    String getAdjustmentIssuer() {
+        return mAdjustmentIssuer;
+    }
+
     public void setIsAppImportanceLocked(boolean isAppImportanceLocked) {
         mIsAppImportanceLocked = isAppImportanceLocked;
         calculateUserSentiment();
@@ -783,10 +787,22 @@
         return mImportance;
     }
 
+    int getInitialImportance() {
+        return stats.naturalImportance;
+    }
+
     public float getRankingScore() {
         return mRankingScore;
     }
 
+    int getImportanceExplanationCode() {
+        return mImportanceExplanationCode;
+    }
+
+    int getInitialImportanceExplanationCode() {
+        return mInitialImportanceExplanationCode;
+    }
+
     public CharSequence getImportanceExplanation() {
         switch (mImportanceExplanationCode) {
             case MetricsEvent.IMPORTANCE_EXPLANATION_UNKNOWN:
diff --git a/services/core/java/com/android/server/notification/NotificationRecordLogger.java b/services/core/java/com/android/server/notification/NotificationRecordLogger.java
new file mode 100644
index 0000000..03929e8
--- /dev/null
+++ b/services/core/java/com/android/server/notification/NotificationRecordLogger.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.notification;
+
+import android.annotation.Nullable;
+import android.app.Notification;
+import android.app.Person;
+import android.os.Bundle;
+
+import com.android.internal.logging.UiEvent;
+import com.android.internal.logging.UiEventLogger;
+
+import java.util.ArrayList;
+import java.util.Objects;
+
+/**
+ * Interface for writing NotificationReported atoms to statsd log.
+ * @hide
+ */
+public interface NotificationRecordLogger {
+
+    /**
+     * Logs a NotificationReported atom reflecting the posting or update of a notification.
+     * @param r The new NotificationRecord. If null, no action is taken.
+     * @param old The previous NotificationRecord.  Null if there was no previous record.
+     * @param position The position at which this notification is ranked.
+     * @param buzzBeepBlink Logging code reflecting whether this notification alerted the user.
+     */
+    void logNotificationReported(@Nullable NotificationRecord r, @Nullable NotificationRecord old,
+            int position, int buzzBeepBlink);
+
+    /**
+     * The UiEvent enums that this class can log.
+     */
+    enum NotificationReportedEvents implements UiEventLogger.UiEventEnum {
+        INVALID(0),
+        @UiEvent(doc = "New notification enqueued to post")
+        NOTIFICATION_POSTED(162),
+        @UiEvent(doc = "Notification substantially updated")
+        NOTIFICATION_UPDATED(163);
+
+        private final int mId;
+        NotificationReportedEvents(int id) {
+            mId = id;
+        }
+        @Override public int getId() {
+            return mId;
+        }
+    }
+
+    /**
+     * A helper for extracting logging information from one or two NotificationRecords.
+     */
+    class NotificationRecordPair {
+        public final NotificationRecord r, old;
+         /**
+         * Construct from one or two NotificationRecords.
+         * @param r The new NotificationRecord.  If null, only shouldLog() method is usable.
+         * @param old The previous NotificationRecord.  Null if there was no previous record.
+         */
+        NotificationRecordPair(@Nullable NotificationRecord r, @Nullable NotificationRecord old) {
+            this.r = r;
+            this.old = old;
+        }
+
+        /**
+         * @return True if old is null, alerted, or important logged fields have changed.
+         */
+        boolean shouldLog(int buzzBeepBlink) {
+            if (r == null) {
+                return false;
+            }
+            if ((old == null) || (buzzBeepBlink > 0)) {
+                return true;
+            }
+
+            return !(Objects.equals(r.sbn.getChannelIdLogTag(), old.sbn.getChannelIdLogTag())
+                    && Objects.equals(r.sbn.getGroupLogTag(), old.sbn.getGroupLogTag())
+                    && (r.sbn.getNotification().isGroupSummary()
+                        == old.sbn.getNotification().isGroupSummary())
+                    && Objects.equals(r.sbn.getNotification().category,
+                        old.sbn.getNotification().category)
+                    && (r.getImportance() == old.getImportance()));
+        }
+
+        NotificationReportedEvents getUiEvent() {
+            return (old != null) ? NotificationReportedEvents.NOTIFICATION_UPDATED :
+                    NotificationReportedEvents.NOTIFICATION_POSTED;
+        }
+
+        /**
+         * @return hash code for the notification style class, or 0 if none exists.
+         */
+        public int getStyle() {
+            return getStyle(r.sbn.getNotification().extras);
+        }
+
+        private int getStyle(@Nullable Bundle extras) {
+            if (extras != null) {
+                String template = extras.getString(Notification.EXTRA_TEMPLATE);
+                if (template != null && !template.isEmpty()) {
+                    return template.hashCode();
+                }
+            }
+            return 0;
+        }
+
+        int getNumPeople() {
+            return getNumPeople(r.sbn.getNotification().extras);
+        }
+
+        private int getNumPeople(@Nullable Bundle extras) {
+            if (extras != null) {
+                ArrayList<Person> people = extras.getParcelableArrayList(
+                        Notification.EXTRA_PEOPLE_LIST);
+                if (people != null && !people.isEmpty()) {
+                    return people.size();
+                }
+            }
+            return 0;
+        }
+
+        int getAssistantHash() {
+            String assistant = r.getAdjustmentIssuer();
+            return (assistant == null) ? 0 : assistant.hashCode();
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java b/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java
new file mode 100644
index 0000000..d637ad5
--- /dev/null
+++ b/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.notification;
+
+import android.util.StatsLog;
+
+/**
+ * Standard implementation of NotificationRecordLogger interface.
+ * @hide
+ */
+public class NotificationRecordLoggerImpl implements NotificationRecordLogger {
+
+    @Override
+    public void logNotificationReported(NotificationRecord r, NotificationRecord old,
+            int position, int buzzBeepBlink) {
+        NotificationRecordPair p = new NotificationRecordPair(r, old);
+        if (!p.shouldLog(buzzBeepBlink)) {
+            return;
+        }
+        StatsLog.write(StatsLog.NOTIFICATION_REPORTED,
+                /* int32 event_id = 1 */ p.getUiEvent().getId(),
+                /* int32 uid = 2 */ r.getUid(),
+                /* string package_name = 3 */ r.sbn.getPackageName(),
+                /* int32 instance_id = 4 */ 0,  // TODO generate and fill instance ids
+                /* int32 notification_id = 5 */ r.sbn.getId(),
+                /* string notification_tag = 6 */ r.sbn.getTag(),
+                /* string channel_id = 7 */ r.sbn.getChannelIdLogTag(),
+                /* string group_id = 8 */ r.sbn.getGroupLogTag(),
+                /* int32 group_instance_id = 9 */ 0, // TODO generate and fill instance ids
+                /* bool is_group_summary = 10 */ r.sbn.getNotification().isGroupSummary(),
+                /* string category = 11 */ r.sbn.getNotification().category,
+                /* int32 style = 12 */ p.getStyle(),
+                /* int32 num_people = 13 */ p.getNumPeople(),
+                /* int32 position = 14 */ position,
+                /* android.stats.sysui.NotificationImportance importance = 15 */ r.getImportance(),
+                /* int32 alerting = 16 */ buzzBeepBlink,
+                /* NotificationImportanceExplanation importance_source = 17 */
+                r.getImportanceExplanationCode(),
+                /* android.stats.sysui.NotificationImportance importance_initial = 18 */
+                r.getInitialImportance(),
+                /* NotificationImportanceExplanation importance_initial_source = 19 */
+                r.getInitialImportanceExplanationCode(),
+                /* android.stats.sysui.NotificationImportance importance_asst = 20 */
+                r.getAssistantImportance(),
+                /* int32 assistant_hash = 21 */ p.getAssistantHash(),
+                /* float assistant_ranking_score = 22 */ 0  // TODO connect up ranking score
+        );
+    }
+
+
+
+
+
+
+}
diff --git a/services/core/java/com/android/server/notification/toast/CustomToastRecord.java b/services/core/java/com/android/server/notification/toast/CustomToastRecord.java
new file mode 100644
index 0000000..aca6f48
--- /dev/null
+++ b/services/core/java/com/android/server/notification/toast/CustomToastRecord.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.notification.toast;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+import static com.android.server.notification.NotificationManagerService.DBG;
+
+import android.app.ITransientNotification;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.server.notification.NotificationManagerService;
+
+/**
+ * Represents a custom toast, a toast whose view is provided by the app.
+ */
+public class CustomToastRecord extends ToastRecord {
+    private static final String TAG = NotificationManagerService.TAG;
+
+    public final ITransientNotification callback;
+
+    public CustomToastRecord(
+            NotificationManagerService notificationManager, int pid, String packageName,
+            IBinder token, ITransientNotification callback, int duration, Binder windowToken,
+            int displayId) {
+        super(notificationManager, pid, packageName, token, duration, windowToken, displayId);
+        this.callback = checkNotNull(callback);
+    }
+
+    @Override
+    public boolean show() {
+        if (DBG) {
+            Slog.d(TAG, "Show pkg=" + pkg + " callback=" + callback);
+        }
+        try {
+            callback.show(windowToken);
+            return true;
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Object died trying to show custom toast " + token + " in package "
+                    + pkg);
+            mNotificationManager.keepProcessAliveForToastIfNeeded(pid);
+            return false;
+        }
+    }
+
+    @Override
+    public void hide() {
+        try {
+            callback.hide();
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Object died trying to hide custom toast " + token + " in package "
+                    + pkg);
+
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "CustomToastRecord{"
+                + Integer.toHexString(System.identityHashCode(this))
+                + " token=" + token
+                + " packageName=" + pkg
+                + " callback=" + callback
+                + " duration=" + getDuration()
+                + "}";
+    }
+}
diff --git a/services/core/java/com/android/server/notification/toast/TextToastRecord.java b/services/core/java/com/android/server/notification/toast/TextToastRecord.java
new file mode 100644
index 0000000..3c231b4
--- /dev/null
+++ b/services/core/java/com/android/server/notification/toast/TextToastRecord.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.notification.toast;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+import static com.android.server.notification.NotificationManagerService.DBG;
+
+import android.annotation.Nullable;
+import android.app.ITransientNotificationCallback;
+import android.os.Binder;
+import android.os.IBinder;
+import android.util.Slog;
+
+import com.android.server.notification.NotificationManagerService;
+import com.android.server.statusbar.StatusBarManagerInternal;
+
+/**
+ * Represents a text toast, a toast rendered by the system that contains only text.
+ */
+public class TextToastRecord extends ToastRecord {
+    private static final String TAG = NotificationManagerService.TAG;
+
+    public final CharSequence text;
+    @Nullable
+    private final StatusBarManagerInternal mStatusBar;
+    @Nullable
+    private final ITransientNotificationCallback mCallback;
+
+    public TextToastRecord(NotificationManagerService notificationManager,
+            @Nullable StatusBarManagerInternal statusBarManager, int pid, String packageName,
+            IBinder token, CharSequence text, int duration, Binder windowToken, int displayId,
+            @Nullable ITransientNotificationCallback callback) {
+        super(notificationManager, pid, packageName, token, duration, windowToken, displayId);
+        mStatusBar = statusBarManager;
+        mCallback = callback;
+        this.text = checkNotNull(text);
+    }
+
+    @Override
+    public boolean show() {
+        if (DBG) {
+            Slog.d(TAG, "Show pkg=" + pkg + " text=" + text);
+        }
+        if (mStatusBar == null) {
+            Slog.w(TAG, "StatusBar not available to show text toast for package " + pkg);
+            return false;
+        }
+        mStatusBar.showToast(pkg, token, text, windowToken, getDuration(), mCallback);
+        return true;
+    }
+
+    @Override
+    public void hide() {
+        // If it's null, show() would have returned false
+        checkNotNull(mStatusBar, "Cannot hide toast that wasn't shown");
+
+        mStatusBar.hideToast(pkg, token);
+    }
+
+    @Override
+    public String toString() {
+        return "TextToastRecord{"
+                + Integer.toHexString(System.identityHashCode(this))
+                + " token=" + token
+                + " packageName=" + pkg
+                + " text=" + text
+                + " duration=" + getDuration()
+                + "}";
+    }
+}
diff --git a/services/core/java/com/android/server/notification/toast/ToastRecord.java b/services/core/java/com/android/server/notification/toast/ToastRecord.java
new file mode 100644
index 0000000..ef75a6f
--- /dev/null
+++ b/services/core/java/com/android/server/notification/toast/ToastRecord.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.notification.toast;
+
+import android.os.Binder;
+import android.os.IBinder;
+
+import com.android.server.notification.NotificationManagerService;
+import com.android.server.notification.NotificationManagerService.DumpFilter;
+
+import java.io.PrintWriter;
+
+/**
+ * Represents a toast, a transient notification.
+ */
+public abstract class ToastRecord {
+    public final int pid;
+    public final String pkg;
+    public final IBinder token;
+    public final int displayId;
+    public final Binder windowToken;
+    protected final NotificationManagerService mNotificationManager;
+    private int mDuration;
+
+    protected ToastRecord(
+            NotificationManagerService notificationManager,
+            int pid, String pkg, IBinder token, int duration,
+            Binder windowToken, int displayId) {
+        this.mNotificationManager = notificationManager;
+        this.pid = pid;
+        this.pkg = pkg;
+        this.token = token;
+        this.windowToken = windowToken;
+        this.displayId = displayId;
+        mDuration = duration;
+    }
+
+    /**
+     * This method is responsible for showing the toast represented by this object.
+     *
+     * @return True if it was successfully shown.
+     */
+    public abstract boolean show();
+
+    /**
+     * This method is responsible for hiding the toast represented by this object.
+     */
+    public abstract void hide();
+
+    /**
+     * Returns the duration of this toast, which can be {@link android.widget.Toast#LENGTH_SHORT}
+     * or {@link android.widget.Toast#LENGTH_LONG}.
+     */
+    public int getDuration() {
+        return mDuration;
+    }
+
+    /**
+     * Updates toast duration.
+     */
+    public void update(int duration) {
+        mDuration = duration;
+    }
+
+    /**
+     * Dumps a textual representation of this object.
+     */
+    public void dump(PrintWriter pw, String prefix, DumpFilter filter) {
+        if (filter != null && !filter.matches(pkg)) {
+            return;
+        }
+        pw.println(prefix + this);
+    }
+}
diff --git a/services/core/java/com/android/server/om/OverlayActorEnforcer.java b/services/core/java/com/android/server/om/OverlayActorEnforcer.java
index ac3bf9a..4c85603 100644
--- a/services/core/java/com/android/server/om/OverlayActorEnforcer.java
+++ b/services/core/java/com/android/server/om/OverlayActorEnforcer.java
@@ -43,6 +43,9 @@
  */
 public class OverlayActorEnforcer {
 
+    // By default, the reason is not logged to prevent leaks of why it failed
+    private static final boolean DEBUG_REASON = false;
+
     private final VerifyCallback mVerifyCallback;
 
     /**
@@ -50,10 +53,6 @@
      */
     static Pair<String, ActorState> getPackageNameForActor(String actorUriString,
             Map<String, Map<String, String>> namedActors) {
-        if (namedActors.isEmpty()) {
-            return Pair.create(null, ActorState.NO_NAMED_ACTORS);
-        }
-
         Uri actorUri = Uri.parse(actorUriString);
 
         String actorScheme = actorUri.getScheme();
@@ -62,6 +61,10 @@
             return Pair.create(null, ActorState.INVALID_OVERLAYABLE_ACTOR_NAME);
         }
 
+        if (namedActors.isEmpty()) {
+            return Pair.create(null, ActorState.NO_NAMED_ACTORS);
+        }
+
         String actorNamespace = actorUri.getAuthority();
         Map<String, String> namespace = namedActors.get(actorNamespace);
         if (namespace == null) {
@@ -92,7 +95,7 @@
         throw new SecurityException("UID" + callingUid + " is not allowed to call "
                 + methodName + " for "
                 + (TextUtils.isEmpty(targetOverlayableName) ? "" : (targetOverlayableName + " in "))
-                + overlayInfo.targetPackageName + " because " + actorState
+                + overlayInfo.targetPackageName + (DEBUG_REASON ? (" because " + actorState) : "")
         );
     }
 
diff --git a/services/core/java/com/android/server/om/TEST_MAPPING b/services/core/java/com/android/server/om/TEST_MAPPING
index 52163a0..75229a1 100644
--- a/services/core/java/com/android/server/om/TEST_MAPPING
+++ b/services/core/java/com/android/server/om/TEST_MAPPING
@@ -7,6 +7,20 @@
           "include-filter": "com.android.server.om."
         }
       ]
+    },
+    {
+      "name": "OverlayDeviceTests"
+    },
+    {
+      "name": "OverlayHostTests"
+    },
+    {
+      "name": "CtsAppSecurityHostTestCases",
+      "options": [
+        {
+          "include-filter": "android.appsecurity.cts.OverlayHostTest"
+        }
+      ]
     }
   ]
 }
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index 78e1719..5c17bec 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -20,10 +20,12 @@
 import static android.provider.DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE;
 
 import android.Manifest;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
 import android.content.pm.parsing.AndroidPackage;
 import android.content.pm.parsing.ComponentParseUtils;
 import android.content.pm.parsing.ComponentParseUtils.ParsedActivity;
@@ -108,6 +110,7 @@
     private final FeatureConfig mFeatureConfig;
 
     private final OverlayReferenceMapper mOverlayReferenceMapper;
+    private PackageParser.SigningDetails mSystemSigningDetails;
 
     AppsFilter(FeatureConfig featureConfig, String[] forceQueryableWhitelist,
             boolean systemAppsQueryable,
@@ -302,8 +305,9 @@
      *                   initiating uid.
      */
     public void grantImplicitAccess(int callingUid, int targetUid) {
-        if (mImplicitlyQueryable.add(targetUid, callingUid) && DEBUG_LOGGING) {
-            Slog.wtf(TAG, "implicit access granted: " + callingUid + " -> " + targetUid);
+        if (targetUid != callingUid
+                && mImplicitlyQueryable.add(targetUid, callingUid) && DEBUG_LOGGING) {
+            Slog.wtf(TAG, "implicit access granted: " + targetUid + " -> " + callingUid);
         }
     }
 
@@ -320,6 +324,17 @@
      */
     public void addPackage(PackageSetting newPkgSetting,
             ArrayMap<String, PackageSetting> existingSettings) {
+        if (Objects.equals("android", newPkgSetting.name)) {
+            // let's set aside the framework signatures
+            mSystemSigningDetails = newPkgSetting.signatures.mSigningDetails;
+            // and since we add overlays before we add the framework, let's revisit already added
+            // packages for signature matches
+            for (PackageSetting setting : existingSettings.values()) {
+                if (isSystemSigned(mSystemSigningDetails, setting)) {
+                    mForceQueryable.add(setting.appId);
+                }
+            }
+        }
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "filter.addPackage");
         try {
             final AndroidPackage newPkg = newPkgSetting.pkg;
@@ -335,7 +350,9 @@
                             || (newPkgSetting.isSystem() && (mSystemAppsQueryable
                             || ArrayUtils.contains(mForceQueryableByDevicePackageNames,
                             newPkg.getPackageName())));
-            if (newIsForceQueryable) {
+            if (newIsForceQueryable
+                    || (mSystemSigningDetails != null
+                            && isSystemSigned(mSystemSigningDetails, newPkgSetting))) {
                 mForceQueryable.add(newPkgSetting.appId);
             }
 
@@ -381,6 +398,12 @@
         }
     }
 
+    private static boolean isSystemSigned(@NonNull PackageParser.SigningDetails sysSigningDetails,
+            PackageSetting pkgSetting) {
+        return pkgSetting.isSystem()
+            && pkgSetting.signatures.mSigningDetails.signaturesMatchExactly(sysSigningDetails);
+    }
+
     /**
      * Removes a package for consideration when filtering visibility between apps.
      *
@@ -511,6 +534,10 @@
                 }
                 return true;
             }
+            if (targetPkg.isStaticSharedLibrary()) {
+                // not an app, this filtering takes place at a higher level
+                return false;
+            }
             final String targetName = targetPkg.getPackageName();
             Trace.beginSection("getAppId");
             final int callingAppId;
@@ -657,7 +684,7 @@
             String description, Throwable throwable) {
         Slog.wtf(TAG,
                 "interaction: " + callingPkgSetting
-                        + " -> " + targetPkgSetting.name + " "
+                        + " -> " + targetPkgSetting + " "
                         + description, throwable);
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 10f46fd..c17ad11 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -402,10 +402,10 @@
         } finally {
             IoUtils.closeQuietly(fis);
         }
-        // After all of the sessions were loaded, they are ready to be sealed and validated
+        // After reboot housekeeping.
         for (int i = 0; i < mSessions.size(); ++i) {
             PackageInstallerSession session = mSessions.valueAt(i);
-            session.sealAndValidateIfNecessary();
+            session.onAfterSessionRead();
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 124bbf5..43ed25f 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -18,6 +18,7 @@
 
 import static android.content.pm.DataLoaderType.INCREMENTAL;
 import static android.content.pm.DataLoaderType.STREAMING;
+import static android.content.pm.PackageInstaller.LOCATION_DATA_APP;
 import static android.content.pm.PackageManager.INSTALL_FAILED_ABORTED;
 import static android.content.pm.PackageManager.INSTALL_FAILED_BAD_SIGNATURE;
 import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
@@ -60,6 +61,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.DataLoaderManager;
 import android.content.pm.DataLoaderParams;
+import android.content.pm.DataLoaderParamsParcel;
 import android.content.pm.FileSystemControlParcel;
 import android.content.pm.IDataLoader;
 import android.content.pm.IDataLoaderStatusListener;
@@ -73,11 +75,13 @@
 import android.content.pm.PackageInstaller.SessionInfo.StagedSessionErrorCode;
 import android.content.pm.PackageInstaller.SessionParams;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageParser;
 import android.content.pm.PackageParser.ApkLite;
 import android.content.pm.PackageParser.PackageLite;
 import android.content.pm.PackageParser.PackageParserException;
 import android.content.pm.dex.DexMetadataHelper;
+import android.content.pm.parsing.AndroidPackage;
 import android.content.pm.parsing.ApkLiteParseUtils;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -99,6 +103,7 @@
 import android.os.incremental.IncrementalFileStorages;
 import android.os.incremental.IncrementalManager;
 import android.os.storage.StorageManager;
+import android.provider.Settings.Secure;
 import android.stats.devicepolicy.DevicePolicyEnums;
 import android.system.ErrnoException;
 import android.system.Int64Ref;
@@ -152,6 +157,7 @@
     private static final int MSG_COMMIT = 1;
     private static final int MSG_ON_PACKAGE_INSTALLED = 2;
     private static final int MSG_SEAL = 3;
+    private static final int MSG_STREAM_AND_VALIDATE = 4;
 
     /** XML constants used for persisting a session */
     static final String TAG_SESSION = "session";
@@ -203,8 +209,10 @@
     private static final String ATTR_DATALOADER_PACKAGE_NAME = "dataLoaderPackageName";
     private static final String ATTR_DATALOADER_CLASS_NAME = "dataLoaderClassName";
     private static final String ATTR_DATALOADER_ARGUMENTS = "dataLoaderArguments";
+    private static final String ATTR_LOCATION = "location";
     private static final String ATTR_LENGTH_BYTES = "lengthBytes";
     private static final String ATTR_METADATA = "metadata";
+    private static final String ATTR_SIGNATURE = "signature";
 
     private static final String PROPERTY_NAME_INHERIT_NATIVE = "pi.inherit_native_on_dont_kill";
     private static final int[] EMPTY_CHILD_SESSION_ARRAY = {};
@@ -303,22 +311,27 @@
     private int mParentSessionId;
 
     static class FileInfo {
+        public final int location;
         public final String name;
         public final Long lengthBytes;
         public final byte[] metadata;
+        public final byte[] signature;
 
-        public static FileInfo added(String name, Long lengthBytes, byte[] metadata) {
-            return new FileInfo(name, lengthBytes, metadata);
+        public static FileInfo added(int location, String name, Long lengthBytes, byte[] metadata,
+                byte[] signature) {
+            return new FileInfo(location, name, lengthBytes, metadata, signature);
         }
 
-        public static FileInfo removed(String name) {
-            return new FileInfo(name, -1L, null);
+        public static FileInfo removed(int location, String name) {
+            return new FileInfo(location, name, -1L, null, null);
         }
 
-        FileInfo(String name, Long lengthBytes, byte[] metadata) {
+        FileInfo(int location, String name, Long lengthBytes, byte[] metadata, byte[] signature) {
+            this.location = location;
             this.name = name;
             this.lengthBytes = lengthBytes;
             this.metadata = metadata;
+            this.signature = signature;
         }
     }
 
@@ -360,10 +373,14 @@
     @GuardedBy("mLock")
     private boolean mVerityFound;
 
+    private boolean mDataLoaderFinished = false;
+
     // TODO(b/146080380): merge file list with Callback installation.
     private IncrementalFileStorages mIncrementalFileStorages;
 
-    private static final FileFilter sAddedFilter = new FileFilter() {
+    private static final String[] EMPTY_STRING_ARRAY = new String[]{};
+
+    private static final FileFilter sAddedApkFilter = new FileFilter() {
         @Override
         public boolean accept(File file) {
             // Installers can't stage directories, so it's fine to ignore
@@ -375,6 +392,16 @@
             return true;
         }
     };
+    private static final FileFilter sAddedFilter = new FileFilter() {
+        @Override
+        public boolean accept(File file) {
+            // Installers can't stage directories, so it's fine to ignore
+            // entries like "lost+found".
+            if (file.isDirectory()) return false;
+            if (file.getName().endsWith(REMOVE_MARKER_EXTENSION)) return false;
+            return true;
+        }
+    };
     private static final FileFilter sRemovedFilter = new FileFilter() {
         @Override
         public boolean accept(File file) {
@@ -391,6 +418,9 @@
                 case MSG_SEAL:
                     handleSeal((IntentSender) msg.obj);
                     break;
+                case MSG_STREAM_AND_VALIDATE:
+                    handleStreamAndValidate();
+                    break;
                 case MSG_COMMIT:
                     handleCommit();
                     break;
@@ -704,7 +734,11 @@
     @GuardedBy("mLock")
     private String[] getNamesLocked() {
         if (!isDataLoaderInstallation()) {
-            return stageDir.list();
+            String[] result = stageDir.list();
+            if (result == null) {
+                result = EMPTY_STRING_ARRAY;
+            }
+            return result;
         }
         return mFiles.stream().map(fileInfo -> fileInfo.name).toArray(String[]::new);
     }
@@ -715,9 +749,9 @@
     }
 
     @GuardedBy("mLock")
-    private File[] getAddedFilesLocked() {
+    private File[] getAddedApksLocked() {
         String[] names = getNamesLocked();
-        return filterFiles(stageDir, names, sAddedFilter);
+        return filterFiles(stageDir, names, sAddedApkFilter);
     }
 
     @GuardedBy("mLock")
@@ -994,11 +1028,7 @@
     }
 
     private void handleSeal(@NonNull IntentSender statusReceiver) {
-        // TODO(b/136132412): update with new APIs
-        if (mIncrementalFileStorages != null) {
-            mIncrementalFileStorages.startLoading();
-        }
-        if (!markAsCommitted(statusReceiver)) {
+        if (!markAsSealed(statusReceiver)) {
             return;
         }
         if (isMultiPackage()) {
@@ -1006,19 +1036,50 @@
             final IntentSender childIntentSender =
                     new ChildStatusIntentReceiver(remainingSessions, statusReceiver)
                             .getIntentSender();
-            boolean commitFailed = false;
+            boolean sealFailed = false;
+            for (int i = mChildSessionIds.size() - 1; i >= 0; --i) {
+                final int childSessionId = mChildSessionIds.keyAt(i);
+                // seal all children, regardless if any of them fail; we'll throw/return
+                // as appropriate once all children have been processed
+                if (!mSessionProvider.getSession(childSessionId)
+                        .markAsSealed(childIntentSender)) {
+                    sealFailed = true;
+                }
+            }
+            if (sealFailed) {
+                return;
+            }
+        }
+
+        dispatchStreamAndValidate();
+    }
+
+    private void dispatchStreamAndValidate() {
+        mHandler.obtainMessage(MSG_STREAM_AND_VALIDATE).sendToTarget();
+    }
+
+    private void handleStreamAndValidate() {
+        // TODO(b/136132412): update with new APIs
+        if (mIncrementalFileStorages != null) {
+            mIncrementalFileStorages.startLoading();
+        }
+
+        boolean commitFailed = !markAsCommitted();
+
+        if (isMultiPackage()) {
             for (int i = mChildSessionIds.size() - 1; i >= 0; --i) {
                 final int childSessionId = mChildSessionIds.keyAt(i);
                 // commit all children, regardless if any of them fail; we'll throw/return
                 // as appropriate once all children have been processed
                 if (!mSessionProvider.getSession(childSessionId)
-                        .markAsCommitted(childIntentSender)) {
+                        .markAsCommitted()) {
                     commitFailed = true;
                 }
             }
-            if (commitFailed) {
-                return;
-            }
+        }
+
+        if (commitFailed) {
+            return;
         }
 
         mHandler.obtainMessage(MSG_COMMIT).sendToTarget();
@@ -1116,6 +1177,28 @@
         }
     }
 
+    /**
+     * Returns whether or not a package can be installed while Secure FRP is enabled.
+     * <p>
+     * Only callers with the INSTALL_PACKAGES permission are allowed to install. However,
+     * prevent the package installer from installing anything because, while it has the
+     * permission, it will allows packages to be installed from anywhere.
+     */
+    private static boolean isSecureFrpInstallAllowed(Context context, int callingUid) {
+        final PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
+        final String[] systemInstaller = pmi.getKnownPackageNames(
+                PackageManagerInternal.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM);
+        final AndroidPackage callingInstaller = pmi.getPackage(callingUid);
+        if (callingInstaller != null
+                && ArrayUtils.contains(systemInstaller, callingInstaller.getPackageName())) {
+            // don't allow the system package installer to install while under secure FRP
+            return false;
+        }
+
+        // require caller to hold the INSTALL_PACKAGES permission
+        return context.checkCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES)
+                == PackageManager.PERMISSION_GRANTED;
+    }
 
     /**
      * Sanity checks to make sure it's ok to commit the session.
@@ -1126,13 +1209,15 @@
             assertPreparedAndNotDestroyedLocked("commit");
             assertNoWriteFileTransfersOpenLocked();
 
-            final boolean enforceInstallPackages = forTransfer
-                    || (android.provider.Settings.Secure.getInt(mContext.getContentResolver(),
-                                android.provider.Settings.Secure.SECURE_FRP_MODE, 0) == 1);
-            if (enforceInstallPackages) {
-                mContext.enforceCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES, null);
+            final boolean isSecureFrpEnabled =
+                    (Secure.getInt(mContext.getContentResolver(), Secure.SECURE_FRP_MODE, 0) == 1);
+            if (isSecureFrpEnabled
+                    && !isSecureFrpInstallAllowed(mContext, Binder.getCallingUid())) {
+                throw new SecurityException("Can't install packages while in secure FRP");
             }
+
             if (forTransfer) {
+                mContext.enforceCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES, null);
                 if (mInstallerUid == mOriginalInstallerUid) {
                     throw new IllegalArgumentException("Session has not been transferred");
                 }
@@ -1145,44 +1230,48 @@
     }
 
     /**
-     * Do everything but actually commit the session. If this was not already called, the session
-     * will be sealed and marked as committed. The caller of this method is responsible for
-     * subsequently submitting this session for processing.
+     * If this was not already called, the session will be sealed.
      *
      * This method may be called multiple times to update the status receiver validate caller
      * permissions.
      */
-    private boolean markAsCommitted(@NonNull IntentSender statusReceiver) {
+    private boolean markAsSealed(@NonNull IntentSender statusReceiver) {
         Objects.requireNonNull(statusReceiver);
 
         List<PackageInstallerSession> childSessions = getChildSessions();
 
-        final boolean wasSealed;
         synchronized (mLock) {
             mRemoteStatusReceiver = statusReceiver;
 
-            // After validations and updating the observer, we can skip re-sealing, etc. because we
-            // have already marked ourselves as committed.
+            // After updating the observer, we can skip re-sealing.
+            if (mSealed) {
+                return true;
+            }
+
+            try {
+                sealLocked(childSessions);
+            } catch (PackageManagerException e) {
+                return false;
+            }
+        }
+
+        // Persist the fact that we've sealed ourselves to prevent
+        // mutations of any hard links we create. We do this without holding
+        // the session lock, since otherwise it's a lock inversion.
+        mCallback.onSessionSealedBlocking(this);
+
+        return true;
+    }
+
+    private boolean markAsCommitted() {
+        synchronized (mLock) {
+            Objects.requireNonNull(mRemoteStatusReceiver);
+
             if (mCommitted) {
                 return true;
             }
 
-            wasSealed = mSealed;
-            try {
-                if (!mSealed) {
-                    sealLocked(childSessions);
-                }
-
-                try {
-                    streamAndValidateLocked();
-                } catch (StreamingException e) {
-                    // In case of streaming failure we don't want to fail or commit the session.
-                    // Just return from this method and allow caller to commit again.
-                    PackageInstallerService.sendPendingStreaming(mContext, mRemoteStatusReceiver,
-                            sessionId, e);
-                    return false;
-                }
-            } catch (PackageManagerException e) {
+            if (!streamAndValidateLocked()) {
                 return false;
             }
 
@@ -1197,12 +1286,6 @@
             mCommitted = true;
         }
 
-        if (!wasSealed) {
-            // Persist the fact that we've sealed ourselves to prevent
-            // mutations of any hard links we create. We do this without holding
-            // the session lock, since otherwise it's a lock inversion.
-            mCallback.onSessionSealedBlocking(this);
-        }
         return true;
     }
 
@@ -1270,17 +1353,6 @@
     }
 
     /**
-     * Convenience wrapper, see {@link #sealLocked(List<PackageInstallerSession>) seal} and
-     * {@link #streamAndValidateLocked()}.
-     */
-    @GuardedBy("mLock")
-    private void sealAndValidateLocked(List<PackageInstallerSession> childSessions)
-            throws PackageManagerException, StreamingException {
-        sealLocked(childSessions);
-        streamAndValidateLocked();
-    }
-
-    /**
      * Seal the session to prevent further modification.
      *
      * <p>The session will be sealed after calling this method even if it failed.
@@ -1313,24 +1385,24 @@
      * Prepare DataLoader and stream content for DataLoader sessions.
      * Validate the contents of all session.
      *
-     * @throws StreamingException if streaming failed.
-     * @throws PackageManagerException if validation failed.
+     * @return false if validation failed.
      */
     @GuardedBy("mLock")
-    private void streamAndValidateLocked()
-            throws PackageManagerException, StreamingException {
+    private boolean streamAndValidateLocked() {
         try {
             // Read transfers from the original owner stay open, but as the session's data cannot
             // be modified anymore, there is no leak of information. For staged sessions, further
             // validation is performed by the staging manager.
             if (!params.isMultiPackage) {
+                if (!prepareDataLoaderLocked()) {
+                    return false;
+                }
+
                 final PackageInfo pkgInfo = mPm.getPackageInfo(
                         params.appPackageName, PackageManager.GET_SIGNATURES
                                 | PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);
 
-                prepareDataLoader();
-
-                if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
+                if (isApexInstallation()) {
                     validateApexInstallLocked();
                 } else {
                     validateApkInstallLocked(pkgInfo);
@@ -1340,15 +1412,16 @@
             if (params.isStaged) {
                 mStagingManager.checkNonOverlappingWithStagedSessions(this);
             }
+
+            return true;
         } catch (PackageManagerException e) {
-            throw onSessionVerificationFailure(e);
-        } catch (StreamingException e) {
-            throw e;
+            onSessionVerificationFailure(e);
         } catch (Throwable e) {
             // Convert all exceptions into package manager exceptions as only those are handled
             // in the code above.
-            throw onSessionVerificationFailure(new PackageManagerException(e));
+            onSessionVerificationFailure(new PackageManagerException(e));
         }
+        return false;
     }
 
     private PackageManagerException onSessionVerificationFailure(PackageManagerException e) {
@@ -1361,15 +1434,15 @@
     }
 
     /**
-     * If session should be sealed, then it's sealed to prevent further modification
-     * and then it's validated.
+     * If session should be sealed, then it's sealed to prevent further modification.
+     * If the session can't be sealed then it's destroyed.
      *
-     * If the session was sealed but something went wrong then it's destroyed.
+     * Additionally for staged APEX sessions read+validate the package and populate req'd fields.
      *
      * <p> This is meant to be called after all of the sessions are loaded and added to
      * PackageInstallerService
      */
-    void sealAndValidateIfNecessary() {
+    void onAfterSessionRead() {
         synchronized (mLock) {
             if (!mShouldBeSealed || isStagedAndInTerminalState()) {
                 return;
@@ -1378,9 +1451,13 @@
         List<PackageInstallerSession> childSessions = getChildSessions();
         synchronized (mLock) {
             try {
-                sealAndValidateLocked(childSessions);
-            } catch (StreamingException e) {
-                Slog.e(TAG, "Streaming failed", e);
+                sealLocked(childSessions);
+
+                if (isApexInstallation()) {
+                    // APEX installations rely on certain fields to be populated after reboot.
+                    // E.g. mPackageName.
+                    validateApexInstallLocked();
+                }
             } catch (PackageManagerException e) {
                 Slog.e(TAG, "Package not valid", e);
             }
@@ -1456,7 +1533,7 @@
             return;
         }
 
-        if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
+        if (isApexInstallation()) {
             destroyInternal();
             dispatchSessionFinished(PackageManager.INSTALL_FAILED_INTERNAL_ERROR,
                     "APEX packages can only be installed using staged sessions.", null);
@@ -1540,7 +1617,7 @@
         }
 
         final IPackageInstallObserver2 localObserver;
-        if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
+        if (isApexInstallation()) {
             localObserver = null;
         } else {
             if (!params.isMultiPackage) {
@@ -1675,6 +1752,13 @@
     }
 
     /**
+     * Returns true if the session is installing an APEX package.
+     */
+    private boolean isApexInstallation() {
+        return (params.installFlags & PackageManager.INSTALL_APEX) != 0;
+    }
+
+    /**
      * Validate apex install.
      * <p>
      * Sets {@link #mResolvedBaseFile} for RollbackManager to use. Sets {@link #mPackageName} for
@@ -1683,7 +1767,7 @@
     @GuardedBy("mLock")
     private void validateApexInstallLocked()
             throws PackageManagerException {
-        final File[] addedFiles = getAddedFilesLocked();
+        final File[] addedFiles = getAddedApksLocked();
         if (ArrayUtils.isEmpty(addedFiles)) {
             throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged");
         }
@@ -1771,7 +1855,7 @@
             }
         }
 
-        final File[] addedFiles = getAddedFilesLocked();
+        final File[] addedFiles = getAddedApksLocked();
         if (ArrayUtils.isEmpty(addedFiles) && removeSplitList.size() == 0) {
             throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged");
         }
@@ -2109,8 +2193,12 @@
     }
 
     String getInstallerPackageName() {
+        return getInstallSource().installerPackageName;
+    }
+
+    InstallSource getInstallSource() {
         synchronized (mLock) {
-            return mInstallSource.installerPackageName;
+            return mInstallSource;
         }
     }
 
@@ -2326,11 +2414,23 @@
     }
 
     @Override
-    public void addFile(String name, long lengthBytes, byte[] metadata) {
+    public DataLoaderParamsParcel getDataLoaderParams() {
+        return params.dataLoaderParams != null ? params.dataLoaderParams.getData() : null;
+    }
+
+    @Override
+    public void addFile(int location, String name, long lengthBytes, byte[] metadata,
+            byte[] signature) {
         if (!isDataLoaderInstallation()) {
             throw new IllegalStateException(
                     "Cannot add files to non-data loader installation session.");
         }
+        if (!isIncrementalInstallation()) {
+            if (location != LOCATION_DATA_APP) {
+                throw new IllegalArgumentException(
+                        "Non-incremental installation only supports /data/app placement: " + name);
+            }
+        }
         // Use installer provided name for now; we always rename later
         if (!FileUtils.isValidExtFilename(name)) {
             throw new IllegalArgumentException("Invalid name: " + name);
@@ -2339,12 +2439,13 @@
         synchronized (mLock) {
             assertCallerIsOwnerOrRootLocked();
             assertPreparedAndNotSealedLocked("addFile");
-            mFiles.add(FileInfo.added(name, lengthBytes, metadata));
+
+            mFiles.add(FileInfo.added(location, name, lengthBytes, metadata, signature));
         }
     }
 
     @Override
-    public void removeFile(String name) {
+    public void removeFile(int location, String name) {
         if (!isDataLoaderInstallation()) {
             throw new IllegalStateException(
                     "Cannot add files to non-data loader installation session.");
@@ -2357,52 +2458,34 @@
             assertCallerIsOwnerOrRootLocked();
             assertPreparedAndNotSealedLocked("removeFile");
 
-            mFiles.add(FileInfo.removed(getRemoveMarkerName(name)));
-        }
-    }
-
-    static class Notificator {
-        private int mValue = 0;
-
-        void setValue(int value) {
-            synchronized (this) {
-                mValue = value;
-                this.notify();
-            }
-        }
-        int waitForValue() {
-            synchronized (this) {
-                while (mValue == 0) {
-                    try {
-                        this.wait();
-                    } catch (InterruptedException e) {
-                        // Happens if someone interrupts your thread.
-                    }
-                }
-                return mValue;
-            }
+            mFiles.add(FileInfo.removed(location, getRemoveMarkerName(name)));
         }
     }
 
     /**
      * Makes sure files are present in staging location.
      */
-    private void prepareDataLoader()
-            throws PackageManagerException, StreamingException {
+    @GuardedBy("mLock")
+    private boolean prepareDataLoaderLocked()
+            throws PackageManagerException {
         if (!isDataLoaderInstallation()) {
-            return;
+            return true;
+        }
+        if (mDataLoaderFinished) {
+            return true;
         }
 
-        List<InstallationFile> addedFiles = mFiles.stream().filter(
+        final List<InstallationFile> addedFiles = mFiles.stream().filter(
                 file -> sAddedFilter.accept(new File(file.name))).map(
                     file -> new InstallationFile(
-                            file.name, file.lengthBytes, file.metadata)).collect(
+                        file.name, file.lengthBytes, file.metadata)).collect(
                 Collectors.toList());
-        List<String> removedFiles = mFiles.stream().filter(
+        final List<String> removedFiles = mFiles.stream().filter(
                 file -> sRemovedFilter.accept(new File(file.name))).map(
                     file -> file.name.substring(
-                            0, file.name.length() - REMOVE_MARKER_EXTENSION.length())).collect(
+                        0, file.name.length() - REMOVE_MARKER_EXTENSION.length())).collect(
                 Collectors.toList());
+
         if (mIncrementalFileStorages != null) {
             for (InstallationFile file : addedFiles) {
                 try {
@@ -2413,46 +2496,73 @@
                             "Failed to add and configure Incremental File: " + file.getName(), ex);
                 }
             }
-            return;
+            return true;
         }
 
-        final FileSystemConnector connector = new FileSystemConnector(addedFiles);
-
-        DataLoaderManager dataLoaderManager = mContext.getSystemService(DataLoaderManager.class);
+        final DataLoaderManager dataLoaderManager = mContext.getSystemService(
+                DataLoaderManager.class);
         if (dataLoaderManager == null) {
             throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
                     "Failed to find data loader manager service");
         }
 
-        // TODO(b/146080380): make this code async.
-        final Notificator created = new Notificator();
-        final Notificator started = new Notificator();
-        final Notificator imageReady = new Notificator();
-
         IDataLoaderStatusListener listener = new IDataLoaderStatusListener.Stub() {
             @Override
             public void onStatusChanged(int dataLoaderId, int status) {
-                switch (status) {
-                    case IDataLoaderStatusListener.DATA_LOADER_CREATED: {
-                        created.setValue(1);
-                        break;
+                try {
+                    if (status == IDataLoaderStatusListener.DATA_LOADER_DESTROYED) {
+                        return;
                     }
-                    case IDataLoaderStatusListener.DATA_LOADER_STARTED: {
-                        started.setValue(1);
-                        break;
+
+                    IDataLoader dataLoader = dataLoaderManager.getDataLoader(dataLoaderId);
+                    if (dataLoader == null) {
+                        mDataLoaderFinished = true;
+                        onSessionVerificationFailure(
+                                new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
+                                        "Failure to obtain data loader"));
+                        return;
                     }
-                    case IDataLoaderStatusListener.DATA_LOADER_IMAGE_READY: {
-                        imageReady.setValue(1);
-                        break;
+
+                    switch (status) {
+                        case IDataLoaderStatusListener.DATA_LOADER_CREATED: {
+                            dataLoader.start();
+                            break;
+                        }
+                        case IDataLoaderStatusListener.DATA_LOADER_STARTED: {
+                            dataLoader.prepareImage(addedFiles, removedFiles);
+                            break;
+                        }
+                        case IDataLoaderStatusListener.DATA_LOADER_IMAGE_READY: {
+                            mDataLoaderFinished = true;
+                            if (hasParentSessionId()) {
+                                mSessionProvider.getSession(
+                                        mParentSessionId).dispatchStreamAndValidate();
+                            } else {
+                                dispatchStreamAndValidate();
+                            }
+                            dataLoader.destroy();
+                            break;
+                        }
+                        case IDataLoaderStatusListener.DATA_LOADER_IMAGE_NOT_READY: {
+                            mDataLoaderFinished = true;
+                            onSessionVerificationFailure(
+                                    new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
+                                            "Failed to prepare image."));
+                            dataLoader.destroy();
+                            break;
+                        }
                     }
-                    case IDataLoaderStatusListener.DATA_LOADER_IMAGE_NOT_READY: {
-                        imageReady.setValue(2);
-                        break;
-                    }
+                } catch (RemoteException e) {
+                    // In case of streaming failure we don't want to fail or commit the session.
+                    // Just return from this method and allow caller to commit again.
+                    PackageInstallerService.sendPendingStreaming(mContext,
+                            mRemoteStatusReceiver,
+                            sessionId, new StreamingException(e));
                 }
             }
         };
 
+        final FileSystemConnector connector = new FileSystemConnector(addedFiles);
         final FileSystemControlParcel control = new FileSystemControlParcel();
         control.callback = connector;
 
@@ -2467,28 +2577,8 @@
             throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
                     "Failed to initialize data loader");
         }
-        created.waitForValue();
 
-        IDataLoader dataLoader = dataLoaderManager.getDataLoader(sessionId);
-        if (dataLoader == null) {
-            throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
-                    "Failure to obtain data loader");
-        }
-
-        try {
-            dataLoader.start();
-            started.waitForValue();
-
-            dataLoader.prepareImage(addedFiles, removedFiles);
-            if (imageReady.waitForValue() == 2) {
-                throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
-                        "Failed to prepare image.");
-            }
-
-            dataLoader.destroy();
-        } catch (RemoteException e) {
-            throw new StreamingException(e);
-        }
+        return false;
     }
 
     @Override
@@ -2892,9 +2982,11 @@
             }
             for (FileInfo fileInfo : mFiles) {
                 out.startTag(null, TAG_SESSION_FILE);
+                writeIntAttribute(out, ATTR_LOCATION, fileInfo.location);
                 writeStringAttribute(out, ATTR_NAME, fileInfo.name);
                 writeLongAttribute(out, ATTR_LENGTH_BYTES, fileInfo.lengthBytes);
                 writeByteArrayAttribute(out, ATTR_METADATA, fileInfo.metadata);
+                writeByteArrayAttribute(out, ATTR_SIGNATURE, fileInfo.signature);
                 out.endTag(null, TAG_SESSION_FILE);
             }
         }
@@ -3025,9 +3117,12 @@
                 childSessionIds.add(readIntAttribute(in, ATTR_SESSION_ID, SessionInfo.INVALID_ID));
             }
             if (TAG_SESSION_FILE.equals(in.getName())) {
-                files.add(new FileInfo(readStringAttribute(in, ATTR_NAME),
+                files.add(new FileInfo(
+                        readIntAttribute(in, ATTR_LOCATION, 0),
+                        readStringAttribute(in, ATTR_NAME),
                         readLongAttribute(in, ATTR_LENGTH_BYTES, -1),
-                        readByteArrayAttribute(in, ATTR_METADATA)));
+                        readByteArrayAttribute(in, ATTR_METADATA),
+                        readByteArrayAttribute(in, ATTR_SIGNATURE)));
             }
         }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index afd9e09..de6b7d5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -27,6 +27,7 @@
 import static android.content.Intent.ACTION_MAIN;
 import static android.content.Intent.CATEGORY_DEFAULT;
 import static android.content.Intent.CATEGORY_HOME;
+import static android.content.Intent.EXTRA_LONG_VERSION_CODE;
 import static android.content.Intent.EXTRA_PACKAGE_NAME;
 import static android.content.Intent.EXTRA_VERSION_CODE;
 import static android.content.pm.PackageManager.CERT_INPUT_RAW_X509;
@@ -124,8 +125,8 @@
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
-import android.app.ApplicationPackageManager;
 import android.app.AppOpsManager;
+import android.app.ApplicationPackageManager;
 import android.app.BroadcastOptions;
 import android.app.IActivityManager;
 import android.app.ResourcesManager;
@@ -386,6 +387,7 @@
 import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -2867,23 +2869,34 @@
                 scanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;
             }
 
+            final int systemParseFlags = mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR;
+            final int systemScanFlags = scanFlags | SCAN_AS_SYSTEM;
+
+            PackageParser packageParser = new PackageParser();
+            packageParser.setSeparateProcesses(mSeparateProcesses);
+            packageParser.setOnlyCoreApps(mOnlyCore);
+            packageParser.setDisplayMetrics(mMetrics);
+            packageParser.setCacheDir(mCacheDir);
+            packageParser.setCallback(mPackageParserCallback);
+
+            ExecutorService executorService = ParallelPackageParser.makeExecutorService();
             // Collect vendor/product/system_ext overlay packages. (Do this before scanning
             // any apps.)
             // For security and version matching reason, only consider overlay packages if they
             // reside in the right directory.
-            final int systemParseFlags = mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR;
-            final int systemScanFlags = scanFlags | SCAN_AS_SYSTEM;
             for (int i = mDirsToScanAsSystem.size() - 1; i >= 0; i--) {
                 final SystemPartition partition = mDirsToScanAsSystem.get(i);
                 if (partition.overlayFolder == null) {
                     continue;
                 }
                 scanDirTracedLI(partition.overlayFolder, systemParseFlags,
-                        systemScanFlags | partition.scanFlag, 0);
+                        systemScanFlags | partition.scanFlag, 0,
+                        packageParser, executorService);
             }
 
             scanDirTracedLI(frameworkDir, systemParseFlags,
-                    systemScanFlags | SCAN_NO_DEX | SCAN_AS_PRIVILEGED, 0);
+                    systemScanFlags | SCAN_NO_DEX | SCAN_AS_PRIVILEGED, 0,
+                    packageParser, executorService);
             if (!mPackages.containsKey("android")) {
                 throw new IllegalStateException(
                         "Failed to load frameworks package; check log for warnings");
@@ -2892,10 +2905,12 @@
                 final SystemPartition partition = mDirsToScanAsSystem.get(i);
                 if (partition.privAppFolder != null) {
                     scanDirTracedLI(partition.privAppFolder, systemParseFlags,
-                            systemScanFlags | SCAN_AS_PRIVILEGED | partition.scanFlag, 0);
+                            systemScanFlags | SCAN_AS_PRIVILEGED | partition.scanFlag, 0,
+                            packageParser, executorService);
                 }
                 scanDirTracedLI(partition.appFolder, systemParseFlags,
-                        systemScanFlags | partition.scanFlag, 0);
+                        systemScanFlags | partition.scanFlag, 0,
+                        packageParser, executorService);
             }
 
 
@@ -2999,8 +3014,18 @@
             if (!mOnlyCore) {
                 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
                         SystemClock.uptimeMillis());
-                scanDirTracedLI(sAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
+                scanDirTracedLI(sAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0,
+                        packageParser, executorService);
 
+            }
+
+            List<Runnable> unfinishedTasks = executorService.shutdownNow();
+            if (!unfinishedTasks.isEmpty()) {
+                throw new IllegalStateException("Not all tasks finished before calling close: "
+                        + unfinishedTasks);
+            }
+
+            if (!mOnlyCore) {
                 // Remove disable package settings for updated system apps that were
                 // removed via an OTA. If the update is no longer present, remove the
                 // app completely. Otherwise, revoke their system privileges.
@@ -4554,7 +4579,10 @@
         flags = updateFlagsForPackage(flags, userId);
         mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                 false /*requireFullPermission*/, false /*checkShell*/, "getPackageUid");
+        return getPackageUidInternal(packageName, flags, userId, callingUid);
+    }
 
+    private int getPackageUidInternal(String packageName, int flags, int userId, int callingUid) {
         // reader
         synchronized (mLock) {
             final AndroidPackage p = mPackages.get(packageName);
@@ -8574,16 +8602,18 @@
         return finalList;
     }
 
-    private void scanDirTracedLI(File scanDir, final int parseFlags, int scanFlags, long currentTime) {
+    private void scanDirTracedLI(File scanDir, final int parseFlags, int scanFlags,
+            long currentTime, PackageParser packageParser, ExecutorService executorService) {
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir [" + scanDir.getAbsolutePath() + "]");
         try {
-            scanDirLI(scanDir, parseFlags, scanFlags, currentTime);
+            scanDirLI(scanDir, parseFlags, scanFlags, currentTime, packageParser, executorService);
         } finally {
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         }
     }
 
-    private void scanDirLI(File scanDir, int parseFlags, int scanFlags, long currentTime) {
+    private void scanDirLI(File scanDir, int parseFlags, int scanFlags, long currentTime,
+            PackageParser packageParser, ExecutorService executorService) {
         final File[] files = scanDir.listFiles();
         if (ArrayUtils.isEmpty(files)) {
             Log.d(TAG, "No files in app dir " + scanDir);
@@ -8594,58 +8624,58 @@
             Log.d(TAG, "Scanning app dir " + scanDir + " scanFlags=" + scanFlags
                     + " flags=0x" + Integer.toHexString(parseFlags));
         }
-        try (ParallelPackageParser parallelPackageParser = new ParallelPackageParser(
-                mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir,
-                mPackageParserCallback)) {
-            // Submit files for parsing in parallel
-            int fileCount = 0;
-            for (File file : files) {
-                final boolean isPackage = (isApkFile(file) || file.isDirectory())
-                        && !PackageInstallerService.isStageName(file.getName());
-                if (!isPackage) {
-                    // Ignore entries which are not packages
-                    continue;
+
+        ParallelPackageParser parallelPackageParser =
+                new ParallelPackageParser(packageParser, executorService);
+
+        // Submit files for parsing in parallel
+        int fileCount = 0;
+        for (File file : files) {
+            final boolean isPackage = (isApkFile(file) || file.isDirectory())
+                    && !PackageInstallerService.isStageName(file.getName());
+            if (!isPackage) {
+                // Ignore entries which are not packages
+                continue;
+            }
+            parallelPackageParser.submit(file, parseFlags);
+            fileCount++;
+        }
+
+        // Process results one by one
+        for (; fileCount > 0; fileCount--) {
+            ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take();
+            Throwable throwable = parseResult.throwable;
+            int errorCode = PackageManager.INSTALL_SUCCEEDED;
+
+            if (throwable == null) {
+                // TODO(toddke): move lower in the scan chain
+                // Static shared libraries have synthetic package names
+                if (parseResult.parsedPackage.isStaticSharedLibrary()) {
+                    renameStaticSharedLibraryPackage(parseResult.parsedPackage);
                 }
-                parallelPackageParser.submit(file, parseFlags);
-                fileCount++;
+                try {
+                    addForInitLI(parseResult.parsedPackage, parseFlags, scanFlags,
+                            currentTime, null);
+                } catch (PackageManagerException e) {
+                    errorCode = e.error;
+                    Slog.w(TAG, "Failed to scan " + parseResult.scanFile + ": " + e.getMessage());
+                }
+            } else if (throwable instanceof PackageParserException) {
+                PackageParserException e = (PackageParserException)
+                        throwable;
+                errorCode = e.error;
+                Slog.w(TAG, "Failed to parse " + parseResult.scanFile + ": " + e.getMessage());
+            } else {
+                throw new IllegalStateException("Unexpected exception occurred while parsing "
+                        + parseResult.scanFile, throwable);
             }
 
-            // Process results one by one
-            for (; fileCount > 0; fileCount--) {
-                ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take();
-                Throwable throwable = parseResult.throwable;
-                int errorCode = PackageManager.INSTALL_SUCCEEDED;
-
-                if (throwable == null) {
-                    // TODO(toddke): move lower in the scan chain
-                    // Static shared libraries have synthetic package names
-                    if (parseResult.parsedPackage.isStaticSharedLibrary()) {
-                        renameStaticSharedLibraryPackage(parseResult.parsedPackage);
-                    }
-                    try {
-                        addForInitLI(parseResult.parsedPackage, parseFlags, scanFlags,
-                                currentTime, null);
-                    } catch (PackageManagerException e) {
-                        errorCode = e.error;
-                        Slog.w(TAG, "Failed to scan " + parseResult.scanFile + ": " + e.getMessage());
-                    }
-                } else if (throwable instanceof PackageParserException) {
-                    PackageParserException e = (PackageParserException)
-                            throwable;
-                    errorCode = e.error;
-                    Slog.w(TAG, "Failed to parse " + parseResult.scanFile + ": " + e.getMessage());
-                } else {
-                    throw new IllegalStateException("Unexpected exception occurred while parsing "
-                            + parseResult.scanFile, throwable);
-                }
-
-                // Delete invalid userdata apps
-                if ((scanFlags & SCAN_AS_SYSTEM) == 0 &&
-                        errorCode != PackageManager.INSTALL_SUCCEEDED) {
-                    logCriticalInfo(Log.WARN,
-                            "Deleting invalid package at " + parseResult.scanFile);
-                    removeCodePathLI(parseResult.scanFile);
-                }
+            // Delete invalid userdata apps
+            if ((scanFlags & SCAN_AS_SYSTEM) == 0
+                    && errorCode != PackageManager.INSTALL_SUCCEEDED) {
+                logCriticalInfo(Log.WARN,
+                        "Deleting invalid package at " + parseResult.scanFile);
+                removeCodePathLI(parseResult.scanFile);
             }
         }
     }
@@ -14375,6 +14405,7 @@
             integrityVerification.putExtra(EXTRA_VERIFICATION_ID, verificationId);
             integrityVerification.putExtra(EXTRA_PACKAGE_NAME, pkgLite.packageName);
             integrityVerification.putExtra(EXTRA_VERSION_CODE, pkgLite.versionCode);
+            integrityVerification.putExtra(EXTRA_LONG_VERSION_CODE, pkgLite.getLongVersionCode());
             populateInstallerExtras(integrityVerification);
 
             // send to integrity component only.
@@ -17699,7 +17730,7 @@
     }
 
     /*
-     * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
+     * This method deletes the package from internal data structures. If the DELETE_KEEP_DATA
      * flag is not set, the data directory is removed as well.
      * make sure this flag is set for partially installed apps. If not its meaningless to
      * delete a partially installed application.
@@ -20211,8 +20242,8 @@
 
         // Disable any carrier apps. We do this very early in boot to prevent the apps from being
         // disabled after already being started.
-        CarrierAppUtils.disableCarrierAppsUntilPrivileged(mContext.getOpPackageName(), this,
-                mPermissionManagerService, UserHandle.USER_SYSTEM, mContext);
+        CarrierAppUtils.disableCarrierAppsUntilPrivileged(
+                mContext.getOpPackageName(), UserHandle.USER_SYSTEM, mContext);
 
         disableSkuSpecificApps();
 
@@ -23098,6 +23129,12 @@
         }
 
         @Override
+        public int getPackageUidInternal(String packageName, int flags, int userId) {
+            return PackageManagerService.this
+                    .getPackageUidInternal(packageName, flags, userId, Process.SYSTEM_UID);
+        }
+
+        @Override
         public ApplicationInfo getApplicationInfo(
                 String packageName, int flags, int filterCallingUid, int userId) {
             return PackageManagerService.this
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 8384006..e7f6b89 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -16,6 +16,7 @@
 
 package com.android.server.pm;
 
+import static android.content.pm.PackageInstaller.LOCATION_DATA_APP;
 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
@@ -2970,7 +2971,7 @@
             // 1. Single file from stdin.
             if (args.isEmpty() || STDIN_PATH.equals(args.get(0))) {
                 String name = "base." + (isApex ? "apex" : "apk");
-                session.addFile(name, sessionSizeBytes, STDIN_PATH_BYTES);
+                session.addFile(LOCATION_DATA_APP, name, sessionSizeBytes, STDIN_PATH_BYTES, null);
                 return 0;
             }
 
@@ -2994,7 +2995,7 @@
                         return 1;
                     }
 
-                    session.addFile(name, sizeBytes, STDIN_PATH_BYTES);
+                    session.addFile(LOCATION_DATA_APP, name, sizeBytes, STDIN_PATH_BYTES, null);
                     continue;
                 }
 
@@ -3004,7 +3005,7 @@
                 String name = new File(inPath).getName();
                 byte[] metadata = inPath.getBytes(StandardCharsets.UTF_8);
 
-                session.addFile(name, -1, metadata);
+                session.addFile(LOCATION_DATA_APP, name, -1, metadata, null);
             }
             return 0;
         } finally {
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java b/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
index a814cb8..5dca9e1 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
@@ -115,8 +115,8 @@
         }
 
         @Override
-        public boolean onPrepareImage(Collection<InstallationFile> addedFiles,
-                Collection<String> removedFiles) {
+        public boolean onPrepareImage(@NonNull Collection<InstallationFile> addedFiles,
+                @NonNull Collection<String> removedFiles) {
             final int commandId = extractShellCommandId(mParams.getArguments());
             if (commandId == INVALID_SHELL_COMMAND_ID) {
                 return false;
@@ -152,6 +152,7 @@
                 }
                 return true;
             } catch (IOException e) {
+                Slog.e(TAG, "Exception while streaming files", e);
                 return false;
             }
         }
diff --git a/services/core/java/com/android/server/pm/ParallelPackageParser.java b/services/core/java/com/android/server/pm/ParallelPackageParser.java
index a506514..448dad0 100644
--- a/services/core/java/com/android/server/pm/ParallelPackageParser.java
+++ b/services/core/java/com/android/server/pm/ParallelPackageParser.java
@@ -22,13 +22,11 @@
 import android.content.pm.parsing.ParsedPackage;
 import android.os.Process;
 import android.os.Trace;
-import android.util.DisplayMetrics;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ConcurrentUtils;
 
 import java.io.File;
-import java.util.List;
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.ExecutorService;
@@ -38,30 +36,27 @@
  * <p>Parsing requests are processed by a thread-pool of {@link #MAX_THREADS}.
  * At any time, at most {@link #QUEUE_CAPACITY} results are kept in RAM</p>
  */
-class ParallelPackageParser implements AutoCloseable {
+class ParallelPackageParser {
 
-    private static final int QUEUE_CAPACITY = 10;
+    private static final int QUEUE_CAPACITY = 30;
     private static final int MAX_THREADS = 4;
 
-    private final String[] mSeparateProcesses;
-    private final boolean mOnlyCore;
-    private final DisplayMetrics mMetrics;
-    private final File mCacheDir;
-    private final PackageParser.Callback mPackageParserCallback;
     private volatile String mInterruptedInThread;
 
     private final BlockingQueue<ParseResult> mQueue = new ArrayBlockingQueue<>(QUEUE_CAPACITY);
 
-    private final ExecutorService mService = ConcurrentUtils.newFixedThreadPool(MAX_THREADS,
-            "package-parsing-thread", Process.THREAD_PRIORITY_FOREGROUND);
+    static ExecutorService makeExecutorService() {
+        return ConcurrentUtils.newFixedThreadPool(MAX_THREADS, "package-parsing-thread",
+                Process.THREAD_PRIORITY_FOREGROUND);
+    }
 
-    ParallelPackageParser(String[] separateProcesses, boolean onlyCoreApps,
-            DisplayMetrics metrics, File cacheDir, PackageParser.Callback callback) {
-        mSeparateProcesses = separateProcesses;
-        mOnlyCore = onlyCoreApps;
-        mMetrics = metrics;
-        mCacheDir = cacheDir;
-        mPackageParserCallback = callback;
+    private final PackageParser mPackageParser;
+
+    private final ExecutorService mExecutorService;
+
+    ParallelPackageParser(PackageParser packageParser, ExecutorService executorService) {
+        mPackageParser = packageParser;
+        mExecutorService = executorService;
     }
 
     static class ParseResult {
@@ -104,18 +99,12 @@
      * @param parseFlags parse flags
      */
     public void submit(File scanFile, int parseFlags) {
-        mService.submit(() -> {
+        mExecutorService.submit(() -> {
             ParseResult pr = new ParseResult();
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parallel parsePackage [" + scanFile + "]");
             try {
-                PackageParser pp = new PackageParser();
-                pp.setSeparateProcesses(mSeparateProcesses);
-                pp.setOnlyCoreApps(mOnlyCore);
-                pp.setDisplayMetrics(mMetrics);
-                pp.setCacheDir(mCacheDir);
-                pp.setCallback(mPackageParserCallback);
                 pr.scanFile = scanFile;
-                pr.parsedPackage = parsePackage(pp, scanFile, parseFlags);
+                pr.parsedPackage = parsePackage(scanFile, parseFlags);
             } catch (Throwable e) {
                 pr.throwable = e;
             } finally {
@@ -134,17 +123,8 @@
     }
 
     @VisibleForTesting
-    protected ParsedPackage parsePackage(PackageParser packageParser, File scanFile,
-            int parseFlags) throws PackageParser.PackageParserException {
-        return packageParser.parseParsedPackage(scanFile, parseFlags, true);
-    }
-
-    @Override
-    public void close() {
-        List<Runnable> unfinishedTasks = mService.shutdownNow();
-        if (!unfinishedTasks.isEmpty()) {
-            throw new IllegalStateException("Not all tasks finished before calling close: "
-                    + unfinishedTasks);
-        }
+    protected ParsedPackage parsePackage(File scanFile, int parseFlags)
+            throws PackageParser.PackageParserException {
+        return mPackageParser.parseParsedPackage(scanFile, parseFlags, true);
     }
 }
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index c3e7f62..7c76656 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -333,8 +333,6 @@
                 KeyEvent.KEYCODE_CALCULATOR, Intent.CATEGORY_APP_CALCULATOR);
     }
 
-    private static final int USER_ACTIVITY_NOTIFICATION_DELAY = 200;
-
     /** Amount of time (in milliseconds) to wait for windows drawn before powering on. */
     static final int WAITING_FOR_DRAWN_TIMEOUT = 1000;
 
@@ -487,7 +485,6 @@
 
     private boolean mPendingKeyguardOccluded;
     private boolean mKeyguardOccludedChanged;
-    private boolean mNotifyUserActivity;
 
     SleepToken mScreenOffSleepToken;
     volatile boolean mKeyguardOccluded;
@@ -627,8 +624,7 @@
     private static final int MSG_LAUNCH_ASSIST = 23;
     private static final int MSG_LAUNCH_ASSIST_LONG_PRESS = 24;
     private static final int MSG_POWER_VERY_LONG_PRESS = 25;
-    private static final int MSG_NOTIFY_USER_ACTIVITY = 26;
-    private static final int MSG_RINGER_TOGGLE_CHORD = 27;
+    private static final int MSG_RINGER_TOGGLE_CHORD = 26;
 
     private class PolicyHandler extends Handler {
         @Override
@@ -708,13 +704,6 @@
                 case MSG_HANDLE_ALL_APPS:
                     launchAllAppsAction();
                     break;
-                case MSG_NOTIFY_USER_ACTIVITY:
-                    removeMessages(MSG_NOTIFY_USER_ACTIVITY);
-                    Intent intent = new Intent(ACTION_USER_ACTIVITY_NOTIFICATION);
-                    intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
-                    mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
-                            android.Manifest.permission.USER_ACTIVITY);
-                    break;
                 case MSG_RINGER_TOGGLE_CHORD:
                     handleRingerChordGesture();
                     break;
@@ -3086,7 +3075,7 @@
                         event.getAction(), fallbackAction.keyCode,
                         event.getRepeatCount(), fallbackAction.metaState,
                         event.getDeviceId(), event.getScanCode(),
-                        flags, event.getSource(), event.getDisplayId(), null);
+                        flags, event.getSource(), event.getDisplayId(), null /* hmac */, null);
 
                 if (!interceptFallback(focusedToken, fallbackEvent, policyFlags)) {
                     fallbackEvent.recycle();
@@ -4892,13 +4881,6 @@
         mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE);
     }
 
-    @Override
-    public void requestUserActivityNotification() {
-        if (!mNotifyUserActivity && !mHandler.hasMessages(MSG_NOTIFY_USER_ACTIVITY)) {
-            mNotifyUserActivity = true;
-        }
-    }
-
     /** {@inheritDoc} */
     @Override
     public void userActivity() {
@@ -4920,12 +4902,6 @@
                 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
             }
         }
-
-        if (mDefaultDisplayPolicy.isAwake() && mNotifyUserActivity) {
-            mHandler.sendEmptyMessageDelayed(MSG_NOTIFY_USER_ACTIVITY,
-                    USER_ACTIVITY_NOTIFICATION_DELAY);
-            mNotifyUserActivity = false;
-        }
     }
 
     class ScreenLockTimeout implements Runnable {
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index c39da5f..e81214e 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -1438,12 +1438,6 @@
     }
 
     /**
-     * Requests that the WindowManager sends
-     * WindowManagerPolicyConstants#ACTION_USER_ACTIVITY_NOTIFICATION on the next user activity.
-     */
-    public void requestUserActivityNotification();
-
-    /**
      * Registers an IDisplayFoldListener.
      */
     default void registerDisplayFoldListener(IDisplayFoldListener listener) {}
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index df8e30f..b45522d 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -62,6 +62,8 @@
 import com.android.server.policy.WindowManagerPolicy;
 import com.android.server.statusbar.StatusBarManagerInternal;
 
+import java.io.PrintWriter;
+
 /**
  * Sends broadcasts about important power state changes.
  * <p>
@@ -123,6 +125,7 @@
     @Nullable private final StatusBarManagerInternal mStatusBarManagerInternal;
     private final TrustManager mTrustManager;
     private final Vibrator mVibrator;
+    private final WakeLockLog mWakeLockLog;
 
     private final NotifierHandler mHandler;
     private final Intent mScreenOnIntent;
@@ -190,6 +193,8 @@
         mShowWirelessChargingAnimationConfig = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_showBuiltinWirelessChargingAnim);
 
+        mWakeLockLog = new WakeLockLog();
+
         // Initialize interactive state for battery stats.
         try {
             mBatteryStats.noteInteractive(true);
@@ -228,6 +233,8 @@
                 // Ignore
             }
         }
+
+        mWakeLockLog.onWakeLockAcquired(tag, ownerUid, flags);
     }
 
     public void onLongPartialWakeLockStart(String tag, int ownerUid, WorkSource workSource,
@@ -338,6 +345,7 @@
                 // Ignore
             }
         }
+        mWakeLockLog.onWakeLockReleased(tag, ownerUid);
     }
 
     private int getBatteryStatsWakeLockMonitorType(int flags) {
@@ -647,6 +655,17 @@
         mHandler.sendMessage(msg);
     }
 
+    /**
+     * Dumps data for bugreports.
+     *
+     * @param pw The stream to print to.
+     */
+    public void dump(PrintWriter pw) {
+        if (mWakeLockLog != null) {
+            mWakeLockLog.dump(pw);
+        }
+    }
+
     private void updatePendingBroadcastLocked() {
         if (!mBroadcastInProgress
                 && mPendingInteractiveState != INTERACTIVE_STATE_UNKNOWN
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 3f3a133..4d13658 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -3810,6 +3810,10 @@
         if (wcd != null) {
             wcd.dump(pw);
         }
+
+        if (mNotifier != null) {
+            mNotifier.dump(pw);
+        }
     }
 
     private void dumpProto(FileDescriptor fd) {
@@ -4268,7 +4272,7 @@
     /**
      * Represents a wake lock that has been acquired by an application.
      */
-    private final class WakeLock implements IBinder.DeathRecipient {
+    /* package */ final class WakeLock implements IBinder.DeathRecipient {
         public final IBinder mLock;
         public int mFlags;
         public String mTag;
diff --git a/services/core/java/com/android/server/power/WakeLockLog.java b/services/core/java/com/android/server/power/WakeLockLog.java
new file mode 100644
index 0000000..d6060fa
--- /dev/null
+++ b/services/core/java/com/android/server/power/WakeLockLog.java
@@ -0,0 +1,1355 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.power;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.PowerManager;
+import android.text.TextUtils;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
+import com.android.internal.os.SomeArgs;
+
+import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.ConcurrentModificationException;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * Simple Log for wake lock events. Optimized to reduce memory usage.
+ *
+ * The wake lock events are ultimately saved in-memory in a pre-allocated byte-based ring-buffer.
+ *
+ * Most of the work of this log happens in the {@link BackgroundThread}.
+ *
+ * The main log is basically just a sequence of the two wake lock events (ACQUIRE and RELEASE).
+ * Each entry in the log stores the following data:
+ *  {
+ *    event type (RELEASE | ACQUIRE),
+ *    time (64-bit from System.currentTimeMillis()),
+ *    wake-lock ID {ownerUID (int) + tag (String)},
+ *    wake-lock flags
+ *  }
+ *
+ * In order to maximize the number of entries that fit into the log, there are various efforts made
+ * to compress what we store; of which two are fairly significant and contribute the most to the
+ * complexity of this code:
+ * A) Relative Time
+ *     - Time in each log entry is stored as an 8-bit value and is relative to the time of the
+ *       previous event. When relative time is too large for 8-bits, we add a third type of event
+ *       called TIME_RESET, which is used to add a new 64-bit reference-time event to the log.
+ *       In practice, TIME_RESETs seem to make up about 10% or less of the total events depending
+ *       on the device usage.
+ * B) Wake-lock tag/ID as indexes
+ *     - Wake locks are often reused many times. To avoid storing large strings in the ring buffer,
+ *       we maintain a {@link TagDatabase} that associates each wakelock tag with an 7-bit index.
+ *       The main log stores only these 7-bit indexes instead of whole strings.
+ *
+ * To make the code a bit more organized, there exists a class {@link EntryByteTranslator} which
+ * uses the tag database, and reference-times to convert between a {@link LogEntry} and the
+ * byte sequence that is ultimately stored in the main log, {@link TheLog}.
+ */
+final class WakeLockLog {
+    private static final String TAG = "PowerManagerService.WLLog";
+
+    private static final boolean DEBUG = false;
+
+    private static final int MSG_ON_WAKE_LOCK_EVENT = 1;
+
+    private static final int TYPE_TIME_RESET = 0x0;
+    private static final int TYPE_ACQUIRE = 0x1;
+    private static final int TYPE_RELEASE = 0x2;
+    private static final int MAX_LOG_ENTRY_BYTE_SIZE = 9;
+    private static final int LOG_SIZE = 1024 * 10;
+    private static final int LOG_SIZE_MIN = MAX_LOG_ENTRY_BYTE_SIZE + 1;
+
+    private static final int TAG_DATABASE_SIZE = 128;
+    private static final int TAG_DATABASE_SIZE_MAX = 128;
+
+    private static final int LEVEL_UNKNOWN = 0;
+    private static final int LEVEL_PARTIAL_WAKE_LOCK = 1;
+    private static final int LEVEL_FULL_WAKE_LOCK = 2;
+    private static final int LEVEL_SCREEN_DIM_WAKE_LOCK = 3;
+    private static final int LEVEL_SCREEN_BRIGHT_WAKE_LOCK = 4;
+    private static final int LEVEL_PROXIMITY_SCREEN_OFF_WAKE_LOCK = 5;
+    private static final int LEVEL_DOZE_WAKE_LOCK = 6;
+    private static final int LEVEL_DRAW_WAKE_LOCK = 7;
+
+    private static final String[] LEVEL_TO_STRING = {
+        "unknown",
+        "partial",
+        "full",
+        "screen-dim",
+        "screen-bright",
+        "prox",
+        "doze",
+        "draw"
+    };
+
+    /**
+     * Flags use the same bit field as the level, so must start at the next available bit
+     * after the largest level.
+     */
+    private static final int FLAG_ON_AFTER_RELEASE = 0x8;
+    private static final int FLAG_ACQUIRE_CAUSES_WAKEUP = 0x10;
+
+    private static final int MASK_LOWER_6_BITS = 0x3F;
+    private static final int MASK_LOWER_7_BITS = 0x7F;
+
+    private static final String[] REDUCED_TAG_PREFIXES =
+            {"*job*/", "*gms_scheduler*/", "IntentOp:"};
+
+    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
+
+    /**
+     * Lock protects WakeLockLock.dump (binder thread) from conflicting with changes to the log
+     * happening on the background thread.
+     */
+    private final Object mLock = new Object();
+
+    private final Injector mInjector;
+    private final TheLog mLog;
+    private final TagDatabase mTagDatabase;
+    private final Handler mHandler;
+    private final SimpleDateFormat mDumpsysDateFormat;
+
+    WakeLockLog() {
+        this(new Injector());
+    }
+
+    @VisibleForTesting
+    WakeLockLog(Injector injector) {
+        mInjector = injector;
+        mHandler = new WakeLockLogHandler(injector.getLooper());
+        mTagDatabase = new TagDatabase(injector);
+        EntryByteTranslator translator = new EntryByteTranslator(mTagDatabase);
+        mLog = new TheLog(injector, translator, mTagDatabase);
+        mDumpsysDateFormat = injector.getDateFormat();
+    }
+
+    /**
+     * Receives notifications of an ACQUIRE wake lock event from PowerManager.
+     *
+     * @param tag The wake lock tag
+     * @param ownerUid The owner UID of the wake lock.
+     * @param flags Flags used for the wake lock.
+     */
+    public void onWakeLockAcquired(String tag, int ownerUid, int flags) {
+        onWakeLockEvent(TYPE_ACQUIRE, tag, ownerUid, flags);
+    }
+
+    /**
+     * Receives notifications of a RELEASE wake lock event from PowerManager.
+     *
+     * @param tag The wake lock tag
+     * @param ownerUid The owner UID of the wake lock.
+     */
+    public void onWakeLockReleased(String tag, int ownerUid) {
+        onWakeLockEvent(TYPE_RELEASE, tag, ownerUid, 0 /* flags */);
+    }
+
+    /**
+     * Dumps all the wake lock data currently saved in the wake lock log to the specified
+     * {@code PrintWriter}.
+     *
+     * @param The {@code PrintWriter} to write to.
+     */
+    public void dump(PrintWriter pw) {
+        dump(pw, false);
+    }
+
+    @VisibleForTesting
+    void dump(PrintWriter pw, boolean includeTagDb) {
+        try {
+            synchronized (mLock) {
+                pw.println("Wake Lock Log");
+                LogEntry tempEntry = new LogEntry();  // Temporary entry for the iterator to reuse.
+                final Iterator<LogEntry> iterator = mLog.getAllItems(tempEntry);
+                int numEvents = 0;
+                int numResets = 0;
+                while (iterator.hasNext()) {
+                    String address = null;
+                    if (DEBUG) {
+                        // Gets the byte index in the log for the current entry.
+                        address = iterator.toString();
+                    }
+                    LogEntry entry = iterator.next();
+                    if (entry != null) {
+                        if (entry.type == TYPE_TIME_RESET) {
+                            numResets++;
+                        } else {
+                            numEvents++;
+                            if (DEBUG) {
+                                pw.print(address);
+                            }
+                            entry.dump(pw, mDumpsysDateFormat);
+                        }
+                    }
+                }
+                pw.println("  -");
+                pw.println("  Events: " + numEvents + ", Time-Resets: " + numResets);
+                pw.println("  Buffer, Bytes used: " + mLog.getUsedBufferSize());
+                if (DEBUG || includeTagDb) {
+                    pw.println("  " + mTagDatabase);
+                }
+            }
+        } catch (Exception e) {
+            pw.println("Exception dumping wake-lock log: " + e.toString());
+        }
+    }
+
+    /**
+     * Adds a new entry to the log based on the specified wake lock parameters.
+     *
+     * Grabs the current time for the event and then posts the rest of the logic (actually
+     * adding it to the log) to a background thread.
+     *
+     * @param eventType The type of event (ACQUIRE, RELEASE);
+     * @param tag The wake lock's identifying tag.
+     * @param ownerUid The owner UID of the wake lock.
+     * @param flags The flags used with the wake lock.
+     */
+    private void onWakeLockEvent(int eventType, String tag, int ownerUid,
+            int flags) {
+        if (tag == null) {
+            Slog.w(TAG, "Insufficient data to log wakelock [tag: " + tag
+                    + ", ownerUid: " + ownerUid
+                    + ", flags: 0x" + Integer.toHexString(flags));
+            return;
+        }
+
+        final long time = mInjector.currentTimeMillis();
+
+        SomeArgs args = SomeArgs.obtain();
+        args.arg1 = tagNameReducer(tag);
+        args.argi1 = eventType;
+        args.argi2 = ownerUid;
+        args.argi3 = eventType == TYPE_ACQUIRE ? translateFlagsFromPowerManager(flags) : 0;
+        args.argi4 = (int) ((time >> 32) & 0xFFFFFFFFL);
+        args.argi5 = (int) (time & 0xFFFFFFFFL);
+        mHandler.obtainMessage(MSG_ON_WAKE_LOCK_EVENT, args).sendToTarget();
+    }
+
+    /**
+     * Handles a new wakelock event in the background thread.
+     *
+     * @param eventType The type of event (ACQUIRE, RELEASE)
+     * @param tag The wake lock's identifying tag.
+     * @param ownerUid The owner UID of the wake lock.
+     * @param flags the flags used with the wake lock.
+     */
+    private void handleWakeLockEventInternal(int eventType, String tag, int ownerUid, int flags,
+            long time) {
+        synchronized (mLock) {
+            final TagData tagData = mTagDatabase.findOrCreateTag(
+                    tag, ownerUid, true /* shouldCreate */);
+            mLog.addEntry(new LogEntry(time, eventType, tagData, flags));
+        }
+    }
+
+    /**
+     * Translates wake lock flags from PowerManager into a redefined set that fits
+     * in the lower 6-bits of the return value. The results are an OR-ed combination of the
+     * flags, {@code WakeLockLog.FLAG_*}, and a log-level, {@code WakeLockLog.LEVEL_*}.
+     *
+     * @param flags Wake lock flags including {@code PowerManager.*_WAKE_LOCK}
+     *              {@link PowerManager.ACQUIRE_CAUSES_WAKEUP}, and
+     *              {@link PowerManager.ON_AFTER_RELEASE}.
+     * @return The compressed flags value.
+     */
+    int translateFlagsFromPowerManager(int flags) {
+        int newFlags = 0;
+        switch(PowerManager.WAKE_LOCK_LEVEL_MASK & flags) {
+            case PowerManager.PARTIAL_WAKE_LOCK:
+                newFlags = LEVEL_PARTIAL_WAKE_LOCK;
+                break;
+            case PowerManager.SCREEN_DIM_WAKE_LOCK:
+                newFlags = LEVEL_SCREEN_DIM_WAKE_LOCK;
+                break;
+            case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
+                newFlags = LEVEL_SCREEN_BRIGHT_WAKE_LOCK;
+                break;
+            case PowerManager.FULL_WAKE_LOCK:
+                newFlags = LEVEL_FULL_WAKE_LOCK;
+                break;
+            case PowerManager.DOZE_WAKE_LOCK:
+                newFlags = LEVEL_DOZE_WAKE_LOCK;
+                break;
+            case PowerManager.DRAW_WAKE_LOCK:
+                newFlags = LEVEL_DRAW_WAKE_LOCK;
+                break;
+            case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
+                newFlags = LEVEL_PROXIMITY_SCREEN_OFF_WAKE_LOCK;
+                break;
+            default:
+                Slog.w(TAG, "Unsupported lock level for logging, flags: " + flags);
+                break;
+        }
+        if ((flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
+            newFlags |= FLAG_ACQUIRE_CAUSES_WAKEUP;
+        }
+        if ((flags & PowerManager.ON_AFTER_RELEASE) != 0) {
+            newFlags |= FLAG_ON_AFTER_RELEASE;
+        }
+        return newFlags;
+    }
+
+    /**
+     * Reduce certain wakelock tags to something smaller.
+     * e.g. "*job* /com.aye.bee.cee/dee.ee.eff.Gee$Eich" -> "*job* /c.a.b.c/d.e.e.Gee$Eich"
+     * This is used to save space when storing the tags in the Tag Database.
+     *
+     * @param tag The tag name to reduce
+     * @return A reduced version of the tag name.
+     */
+    private String tagNameReducer(String tag) {
+        if (tag == null) {
+            return null;
+        }
+
+        String reduciblePrefix = null;
+        for (int tp = 0; tp < REDUCED_TAG_PREFIXES.length; tp++) {
+            if (tag.startsWith(REDUCED_TAG_PREFIXES[tp])) {
+                reduciblePrefix = REDUCED_TAG_PREFIXES[tp];
+                break;
+            }
+        }
+
+        if (reduciblePrefix != null) {
+            final StringBuilder sb = new StringBuilder();
+
+            // add prefix first
+            sb.append(tag.substring(0, reduciblePrefix.length()));
+
+            // Stop looping on final marker
+            final int end = Math.max(tag.lastIndexOf("/"), tag.lastIndexOf("."));
+            boolean printNext = true;
+            int index = sb.length();  // Start looping after the prefix
+            for (; index < end; index++) {
+                char c = tag.charAt(index);
+                boolean isMarker = (c == '.' || c == '/');
+                // We print all markers and the character that follows each marker
+                if (isMarker || printNext) {
+                    sb.append(c);
+                }
+                printNext = isMarker;
+            }
+            sb.append(tag.substring(index));  // append everything that is left
+            return sb.toString();
+        }
+        return tag;
+    }
+
+    /**
+     * Represents a wakelock-event entry in the log.
+     * Holds all the data of a wakelock. The lifetime of this class is fairly short as the data
+     * within this type is eventually written to the log as bytes and the instances discarded until
+     * the log is read again which is fairly infrequent.
+     *
+     * At the time of this writing, this can be one of three types of entries:
+     * 1) Wake lock acquire
+     * 2) Wake lock release
+     * 3) Time reset
+     */
+    static class LogEntry {
+        /**
+         * Type of wake lock from the {@code WakeLockLog.TYPE_*} set.
+         */
+        public int type;
+
+        /**
+         * Time of the wake lock entry as taken from System.currentTimeMillis().
+         */
+        public long time;
+
+        /**
+         * Data about the wake lock tag.
+         */
+        public TagData tag;
+
+        /**
+         * Flags used with the wake lock.
+         */
+        public int flags;
+
+        LogEntry() {}
+
+        LogEntry(long time, int type, TagData tag, int flags) {
+            set(time, type, tag, flags);
+        }
+
+        /**
+         * Sets the values of the log entry.
+         * This is exposed to ease the reuse of {@code LogEntry} instances.
+         *
+         * @param time Time of the entry.
+         * @param type Type of entry.
+         * @param tag Tag data of the wake lock.
+         * @param flags Flags used with the wake lock.
+         */
+        public void set(long time, int type, TagData tag, int flags) {
+            this.time = time;
+            this.type = type;
+            this.tag = tag;
+            this.flags = flags;
+        }
+
+        /**
+         * Dumps this entry to the specified {@link PrintWriter}.
+         *
+         * @param pw The print-writer to dump to.
+         * @param dateFormat The date format to use for outputing times.
+         */
+        public void dump(PrintWriter pw, SimpleDateFormat dateFormat) {
+            pw.println("  " + toStringInternal(dateFormat));
+        }
+
+        /**
+         * Converts the entry to a string.
+         * date - ownerUid - (ACQ|REL) tag [(flags)]
+         * e.g., 1999-01-01 12:01:01.123 - 10012 - ACQ bluetooth_timer (partial)
+         */
+        @Override
+        public String toString() {
+            return toStringInternal(DATE_FORMAT);
+        }
+
+        /**
+         * Converts the entry to a string.
+         * date - ownerUid - (ACQ|REL) tag [(flags)]
+         * e.g., 1999-01-01 12:01:01.123 - 10012 - ACQ bluetooth_timer (partial)
+         *
+         * @param dateFormat The date format to use for outputing times.
+         * @return The string output of this class instance.
+         */
+        private String toStringInternal(SimpleDateFormat dateFormat) {
+            StringBuilder sb = new StringBuilder();
+            if (type == TYPE_TIME_RESET) {
+                return dateFormat.format(new Date(time)) + " - RESET";
+            }
+            sb.append(dateFormat.format(new Date(time)))
+                    .append(" - ")
+                    .append(tag == null ? "---" : tag.ownerUid)
+                    .append(" - ")
+                    .append(type == TYPE_ACQUIRE ? "ACQ" : "REL")
+                    .append(" ")
+                    .append(tag == null ? "UNKNOWN" : tag.tag);
+            if (type == TYPE_ACQUIRE) {
+                sb.append(" (");
+                flagsToString(sb);
+                sb.append(")");
+            }
+            return sb.toString();
+        }
+
+        private void flagsToString(StringBuilder sb) {
+            sb.append(LEVEL_TO_STRING[flags & 0x7]);
+            if ((flags & FLAG_ON_AFTER_RELEASE) == FLAG_ON_AFTER_RELEASE) {
+                sb.append(",on-after-release");
+            }
+            if ((flags & FLAG_ACQUIRE_CAUSES_WAKEUP) == FLAG_ACQUIRE_CAUSES_WAKEUP) {
+                sb.append(",acq-causes-wake");
+            }
+        }
+    }
+
+    /**
+     * Converts between a {@link LogEntry} instance and a byte sequence.
+     *
+     * This is used to convert {@link LogEntry}s to a series of bytes before being written into
+     * the log, and vice-versa when reading from the log.
+     *
+     * This method employs the compression techniques that are mentioned in the header of
+     * {@link WakeLockLog}: Relative-time and Tag-indexing.  Please see the header for the
+     * description of both.
+     *
+     * The specific byte formats used are explained more thoroughly in the method {@link #toBytes}.
+     */
+    static class EntryByteTranslator {
+
+        // Error codes that can be returned when converting to bytes.
+        static final int ERROR_TIME_IS_NEGATIVE = -1;  // Relative time is negative
+        static final int ERROR_TIME_TOO_LARGE = -2;  // Relative time is out of valid range (0-255)
+
+        private final TagDatabase mTagDatabase;
+
+        EntryByteTranslator(TagDatabase tagDatabase) {
+            mTagDatabase = tagDatabase;
+        }
+
+        /**
+         * Translates the specified bytes into a LogEntry instance, if possible.
+         *
+         * See {@link #toBytes} for an explanation of the byte formats.
+         *
+         * @param bytes The bytes to read.
+         * @param timeReference The reference time to use when reading the relative time from the
+         *                      bytes buffer.
+         * @param entryToReuse The entry instance to write to. If null, this method will create a
+         *                     new instance.
+         * @return The converted entry, or null if data is corrupt.
+         */
+        LogEntry fromBytes(byte[] bytes, long timeReference, LogEntry entryToReuse) {
+            if (bytes == null || bytes.length == 0) {
+                return null;
+            }
+
+            // Create an entry if non if passed in to use
+            LogEntry entry = entryToReuse != null ? entryToReuse : new LogEntry();
+
+            int type = (bytes[0] >> 6) & 0x3;
+            if ((type & 0x2) == 0x2) {
+                // As long as the highest order bit of the byte is set, it is a release
+                type = TYPE_RELEASE;
+            }
+            switch (type) {
+                case TYPE_ACQUIRE: {
+                    if (bytes.length < 3) {
+                        break;
+                    }
+
+                    int flags = bytes[0] & MASK_LOWER_6_BITS;
+                    int tagIndex = bytes[1] & MASK_LOWER_7_BITS;
+                    TagData tag = mTagDatabase.getTag(tagIndex);
+                    long time = (bytes[2] & 0xFF) + timeReference;
+                    entry.set(time, TYPE_ACQUIRE, tag, flags);
+                    return entry;
+                }
+                case TYPE_RELEASE: {
+                    if (bytes.length < 2) {
+                        break;
+                    }
+
+                    int flags = 0;
+                    int tagIndex = bytes[0] & MASK_LOWER_7_BITS;
+                    TagData tag = mTagDatabase.getTag(tagIndex);
+                    long time = (bytes[1] & 0xFF) + timeReference;
+                    entry.set(time, TYPE_RELEASE, tag, flags);
+                    return entry;
+                }
+                case TYPE_TIME_RESET: {
+                    if (bytes.length < 9) {
+                        break;
+                    }
+
+                    long time = ((bytes[1] & 0xFFL) << 56)
+                                | ((bytes[2] & 0xFFL) << 48)
+                                | ((bytes[3] & 0xFFL) << 40)
+                                | ((bytes[4] & 0xFFL) << 32)
+                                | ((bytes[5] & 0xFFL) << 24)
+                                | ((bytes[6] & 0xFFL) << 16)
+                                | ((bytes[7] & 0xFFL) << 8)
+                                | (bytes[8] & 0xFFL);
+                    entry.set(time, TYPE_TIME_RESET, null, 0);
+                    return entry;
+                }
+                default:
+                    Slog.w(TAG, "Type not recognized [" + type + "]", new Exception());
+                    break;
+            }
+            return null;
+        }
+
+        /**
+         * Converts and writes the specified entry into the specified byte array.
+         * If the byte array is null or too small, then the method writes nothing, but still returns
+         * the number of bytes necessary to write the entry.
+         *
+         * Byte format used for each type:
+         *
+         * TYPE_RELEASE:
+         *                                        bits
+         *                0      1      2       3       4       5       6       7
+         *   bytes  0  [  1   |            7-bit wake lock tag index                ]
+         *          1  [                 8-bit relative time                        ]
+         *
+         *
+         * TYPE_ACQUIRE:
+         *                                        bits
+         *                0      1      2       3       4       5       6       7
+         *          0  [  0      1   |            wake lock flags                   ]
+         *  bytes   1  [unused|         7-bit wake lock tag index                   ]
+         *          2  [                 8-bit relative time                        ]
+         *
+         *
+         * TYPE_TIME_RESET:
+         *                                        bits
+         *                0      1      2       3       4       5       6       7
+         *          0  [  0      0   |            unused                            ]
+         *  bytes 1-9  [                  64-bit reference-time                     ]
+         *
+         * @param entry The entry to convert/write
+         * @param bytes The buffer to write to, or null to just return the necessary bytes.
+         * @param timeReference The reference-time used to calculate relative time of the entry.
+         * @return The number of bytes written to buffer, or required to write to the buffer.
+         */
+        int toBytes(LogEntry entry, byte[] bytes, long timeReference) {
+            int sizeNeeded = -1;
+            switch (entry.type) {
+                case TYPE_ACQUIRE: {
+                    sizeNeeded = 3;
+                    if (bytes != null && bytes.length >= sizeNeeded) {
+                        int relativeTime = getRelativeTime(timeReference, entry.time);
+                        if (relativeTime < 0) {
+                            // Negative relative time indicates error code
+                            return relativeTime;
+                        }
+                        bytes[0] = (byte) ((TYPE_ACQUIRE << 6)
+                                | (entry.flags & MASK_LOWER_6_BITS));
+                        bytes[1] = (byte) mTagDatabase.getTagIndex(entry.tag);
+                        bytes[2] = (byte) (relativeTime & 0xFF);  // Lower 8 bits of the time
+                        if (DEBUG) {
+                            Slog.d(TAG, "ACQ - Setting bytes: " + Arrays.toString(bytes));
+                        }
+                    }
+                    break;
+                }
+                case TYPE_RELEASE: {
+                    sizeNeeded = 2;
+                    if (bytes != null && bytes.length >= sizeNeeded) {
+                        int relativeTime = getRelativeTime(timeReference, entry.time);
+                        if (relativeTime < 0) {
+                            // Negative relative time indicates error code
+                            return relativeTime;
+                        }
+                        bytes[0] = (byte) (0x80 | mTagDatabase.getTagIndex(entry.tag));
+                        bytes[1] = (byte) (relativeTime & 0xFF);  // Lower 8 bits of the time
+                        if (DEBUG) {
+                            Slog.d(TAG, "REL - Setting bytes: " + Arrays.toString(bytes));
+                        }
+                    }
+                    break;
+                }
+                case TYPE_TIME_RESET: {
+                    sizeNeeded = 9;
+                    long time = entry.time;
+                    if (bytes != null && bytes.length >= sizeNeeded) {
+                        bytes[0] = (TYPE_TIME_RESET << 6);
+                        bytes[1] = (byte) ((time >> 56) & 0xFF);
+                        bytes[2] = (byte) ((time >> 48) & 0xFF);
+                        bytes[3] = (byte) ((time >> 40) & 0xFF);
+                        bytes[4] = (byte) ((time >> 32) & 0xFF);
+                        bytes[5] = (byte) ((time >> 24) & 0xFF);
+                        bytes[6] = (byte) ((time >> 16) & 0xFF);
+                        bytes[7] = (byte) ((time >> 8) & 0xFF);
+                        bytes[8] = (byte) (time & 0xFF);
+                    }
+                    break;
+                }
+                default:
+                    throw new RuntimeException("Unknown type " +  entry);
+            }
+
+            return sizeNeeded;
+        }
+
+        /**
+         * Calculates the relative time between the specified time and timeReference.  The relative
+         * time is expected to be non-negative and fit within 8-bits (values between 0-255). If the
+         * relative time is outside of that range an error code will be returned instead.
+         *
+         * @param time
+         * @param timeReference
+         * @return The relative time between time and timeReference, or an error code.
+         */
+        private int getRelativeTime(long timeReference, long time) {
+            if (time < timeReference) {
+                if (DEBUG) {
+                    Slog.w(TAG, "ERROR_TIME_IS_NEGATIVE");
+                }
+                return ERROR_TIME_IS_NEGATIVE;
+            }
+            long relativeTime = time - timeReference;
+            if (relativeTime > 255) {
+                if (DEBUG) {
+                    Slog.w(TAG, "ERROR_TIME_TOO_LARGE");
+                }
+                return ERROR_TIME_TOO_LARGE;
+            }
+            return (int) relativeTime;
+        }
+    }
+
+    /**
+     * Main implementation of the ring buffer used to store the log entries.  This class takes
+     * {@link LogEntry} instances and adds them to the ring buffer, utilizing
+     * {@link EntryByteTranslator} to convert byte {@link LogEntry} to bytes within the buffer.
+     *
+     * This class also implements the logic around TIME_RESET events. Since the LogEntries store
+     * their time (8-bit) relative to the previous event, this class can add {@link TYPE_TIME_RESET}
+     * LogEntries as necessary to allow a LogEntry's relative time to fit within that range.
+     */
+    static class TheLog {
+        private final EntryByteTranslator mTranslator;
+
+        /**
+         * Temporary buffer used when converting a new entry to bytes for writing to the buffer.
+         * Allocating once allows us to avoid allocating a buffer with each write.
+         */
+        private final byte[] mTempBuffer = new byte[MAX_LOG_ENTRY_BYTE_SIZE];
+
+        /**
+         * Second temporary buffer used when reading and writing bytes from the buffer.
+         * A second temporary buffer is necessary since additional items can be read concurrently
+         * from {@link mTempBuffer}. E.g., Adding an entry to a full buffer requires removing
+         * other entries from the buffer.
+         */
+        private final byte[] mReadWriteTempBuffer = new byte[MAX_LOG_ENTRY_BYTE_SIZE];
+
+        /**
+         * Main log buffer.
+         */
+        private final byte[] mBuffer;
+
+        /**
+         * Start index of the ring buffer.
+         */
+        private int mStart = 0;
+
+        /**
+         * Current end index of the ring buffer.
+         */
+        private int mEnd = 0;
+
+        /**
+         * Start time of the entries in the buffer. The first item stores an 8-bit time that is
+         * relative to this value.
+         */
+        private long mStartTime = 0;
+
+        /**
+         * The time of the last entry in the buffer. Reading the time from the last entry to
+         * calculate the relative time of a new one is sufficiently hard to prefer saving the value
+         * here instead.
+         */
+        private long mLatestTime = 0;
+
+        /**
+         * Counter for number of changes (adds or removes) that have been done to the buffer.
+         */
+        private long mChangeCount = 0;
+
+        private final TagDatabase mTagDatabase;
+
+        TheLog(Injector injector, EntryByteTranslator translator, TagDatabase tagDatabase) {
+            final int logSize = Math.max(injector.getLogSize(), LOG_SIZE_MIN);
+            mBuffer = new byte[logSize];
+
+            mTranslator = translator;
+            mTagDatabase = tagDatabase;
+
+            // Register to be notified when an older tag is removed from the TagDatabase to make
+            // room for a new entry.
+            mTagDatabase.setCallback(new TagDatabase.Callback() {
+                @Override public void onIndexRemoved(int index) {
+                    removeTagIndex(index);
+                }
+            });
+        }
+
+        /**
+         * Returns the amount of space being used in the ring buffer (in bytes).
+         *
+         * @return Used buffer size in bytes.
+         */
+        int getUsedBufferSize() {
+            return mBuffer.length - getAvailableSpace();
+        }
+
+        /**
+         * Adds the specified {@link LogEntry} to the log by converting it to bytes and writing
+         * those bytes to the buffer.
+         *
+         * This method can have side effects of removing old values from the ring buffer and
+         * adding an extra TIME_RESET entry if necessary.
+         */
+        void addEntry(LogEntry entry) {
+            if (isBufferEmpty()) {
+                // First item being added, do initialization.
+                mStartTime = mLatestTime = entry.time;
+            }
+
+            int size = mTranslator.toBytes(entry, mTempBuffer, mLatestTime);
+            if (size == EntryByteTranslator.ERROR_TIME_IS_NEGATIVE) {
+                return;  // Wholly unexpected circumstance...just break out now.
+            } else if (size == EntryByteTranslator.ERROR_TIME_TOO_LARGE) {
+                // The relative time between the last entry and this new one is too large
+                // to fit in our byte format...we need to create a new Time-Reset event and add
+                // that to the log first.
+                addEntry(new LogEntry(entry.time, TYPE_TIME_RESET, null, 0));
+                size = mTranslator.toBytes(entry, mTempBuffer, mLatestTime);
+            }
+
+            if (size > MAX_LOG_ENTRY_BYTE_SIZE || size <= 0) {
+                Slog.w(TAG, "Log entry size is out of expected range: " + size);
+                return;
+            }
+
+            // In case the buffer is full or nearly full, ensure there is a proper amount of space
+            // for the new entry.
+            if (!makeSpace(size)) {
+                return;  // Doesn't fit
+            }
+
+            if (DEBUG) {
+                Slog.d(TAG, "Wrote New Entry @(" + mEnd + ") [" + entry + "] as "
+                        + Arrays.toString(mTempBuffer));
+            }
+            // Set the bytes and update our end index & timestamp.
+            writeBytesAt(mEnd, mTempBuffer, size);
+            if (DEBUG) {
+                Slog.d(TAG, "Read written Entry @(" + mEnd + ") ["
+                        + readEntryAt(mEnd, mLatestTime, null));
+            }
+            mEnd = (mEnd + size) % mBuffer.length;
+            mLatestTime = entry.time;
+
+            TagDatabase.updateTagTime(entry.tag, entry.time);
+            mChangeCount++;
+        }
+
+        /**
+         * Returns an {@link Iterator} of {@link LogEntry}s for all the entries in the log.
+         *
+         * If the log is modified while the entries are being read, the iterator will throw a
+         * {@link ConcurrentModificationExceptoin}.
+         *
+         * @param tempEntry A temporary {@link LogEntry} instance to use so that new instances
+         *                  aren't allocated with every call to {@code Iterator.next}.
+         */
+        Iterator<LogEntry> getAllItems(final LogEntry tempEntry) {
+            return new Iterator<LogEntry>() {
+                private int mCurrent = mStart;  // Current read position in the log.
+                private long mCurrentTimeReference = mStartTime;  // Current time-reference to use.
+                private final long mChangeValue = mChangeCount;  // Used to track if buffer changed.
+
+                /**
+                 * @return True if there are more elements to iterate through, false otherwise.\
+                 * @throws ConcurrentModificationException if the buffer contents change.
+                 */
+                @Override
+                public boolean hasNext() {
+                    checkState();
+                    return mCurrent != mEnd;
+                }
+
+                /**
+                 * Returns the next element in the iterator.
+                 *
+                 * @return The next entry in the iterator
+                 * @throws NoSuchElementException if iterator reaches the end.
+                 * @throws ConcurrentModificationException if buffer contents change.
+                 */
+                @Override
+                public LogEntry next() {
+                    checkState();
+
+                    if (!hasNext()) {
+                        throw new NoSuchElementException("No more entries left.");
+                    }
+
+                    LogEntry entry = readEntryAt(mCurrent, mCurrentTimeReference, tempEntry);
+                    int size = mTranslator.toBytes(entry, null, mStartTime);
+                    mCurrent = (mCurrent + size) % mBuffer.length;
+                    mCurrentTimeReference = entry.time;
+
+                    return entry;
+                }
+
+                @Override public String toString() {
+                    return "@" + mCurrent;
+                }
+
+                /**
+                 * @throws ConcurrentModificationException if the underlying buffer has changed
+                 * since this iterator was instantiated.
+                 */
+                private void checkState() {
+                    if (mChangeValue != mChangeCount) {
+                        throw new ConcurrentModificationException("Buffer modified, old change: "
+                                + mChangeValue + ", new change: " + mChangeCount);
+                    }
+                }
+            };
+        }
+
+        /**
+         * Cleans up old tag index references from the entire log.
+         * Called when an older wakelock tag is removed from the tag database. This happens
+         * when the database needed additional room for newer tags.
+         *
+         * This is a fairly expensive operation.  Reads all the entries from the buffer, which can
+         * be around 1500 for a 10Kb buffer. It will write back any entries that use the tag as
+         * well, but that's not many of them. Commonly-used tags dont ever make it to this part.
+         *
+         * If necessary, in the future we can keep track of the number of tag-users the same way we
+         * keep track of a tag's last-used-time to stop having to do this for old tags that dont
+         * have entries in the logs any more. Light testing has shown that for a 10Kb
+         * buffer, there are about 5 or fewer (of 1500) entries with "UNKNOWN" tag...which means
+         * this operation does happen, but not very much.
+         *
+         * @param tagIndex The index of the tag, as stored in the log
+         */
+        private void removeTagIndex(int tagIndex) {
+            if (isBufferEmpty()) {
+                return;
+            }
+
+            int readIndex = mStart;
+            long timeReference = mStartTime;
+            final LogEntry reusableEntryInstance = new LogEntry();
+            while (readIndex != mEnd) {
+                LogEntry entry = readEntryAt(readIndex, timeReference, reusableEntryInstance);
+                if (DEBUG) {
+                    Slog.d(TAG, "Searching to remove tags @ " + readIndex + ": " + entry);
+                }
+                if (entry == null) {
+                    Slog.w(TAG, "Entry is unreadable - Unexpected @ " + readIndex);
+                    break;  // cannot continue if entries are now corrupt
+                }
+                if (entry.tag != null && entry.tag.index == tagIndex) {
+                    // We found an entry that uses the tag being removed. Re-write the
+                    // entry back without a tag.
+                    entry.tag = null;  // remove the tag, and write it back
+                    writeEntryAt(readIndex, entry, timeReference);
+                    if (DEBUG) {
+                        Slog.d(TAG, "Remove tag index: " + tagIndex + " @ " + readIndex);
+                    }
+                }
+                timeReference = entry.time;
+                int entryByteSize = mTranslator.toBytes(entry, null, 0L);
+                readIndex = (readIndex + entryByteSize) % mBuffer.length;
+            }
+        }
+
+        /**
+         * Removes entries from the buffer until the specified amount of space is available for use.
+         *
+         * @param spaceNeeded The number of bytes needed in the buffer.
+         * @return True if there is space enough in the buffer, false otherwise.
+         */
+        private boolean makeSpace(int spaceNeeded) {
+            // Test the size of the buffer can fit it first, so that we dont loop forever in the
+            // following while loop.
+            if (mBuffer.length < spaceNeeded + 1) {
+                return false;
+            }
+
+            // We check spaceNeeded + 1 so that mStart + mEnd aren't equal.  We use them being equal
+            // to mean that the buffer is empty...so avoid that.
+            while (getAvailableSpace() < (spaceNeeded + 1)) {
+                removeOldestItem();
+            }
+            return true;
+        }
+
+        /**
+         * Returns the available space of the ring buffer.
+         */
+        private int getAvailableSpace() {
+            return mEnd > mStart ? mBuffer.length - (mEnd - mStart) :
+                    (mEnd < mStart ? mStart - mEnd :
+                     mBuffer.length);
+        }
+
+        /**
+         * Removes the oldest item from the buffer if the buffer is not empty.
+         */
+        private void removeOldestItem() {
+            if (isBufferEmpty()) {
+                // No items to remove
+                return;
+            }
+
+            // Copy the contents of the start of the buffer to our temporary buffer.
+            LogEntry entry = readEntryAt(mStart, mStartTime, null);
+            if (DEBUG) {
+                Slog.d(TAG, "Removing oldest item at @ " + mStart + ", found: " + entry);
+            }
+            int size = mTranslator.toBytes(entry, null, mStartTime);
+            mStart = (mStart + size) % mBuffer.length;
+            mStartTime = entry.time;  // new start time
+            mChangeCount++;
+        }
+
+        /**
+         * Returns true if the buffer is currently unused (contains zero entries).
+         *
+         * @return True if empty, false otherwise.
+         */
+        private boolean isBufferEmpty() {
+            return mStart == mEnd;
+        }
+
+        /**
+         * Reads an entry from the specified index in the buffer.
+         *
+         * @param index Index into the buffer from which to read.
+         * @param timeReference Reference time to use when creating the {@link LogEntry}.
+         * @param entryToSet Temporary entry to use instead of allocating a new one.
+         * @return the log-entry instance that was read.
+         */
+        private LogEntry readEntryAt(int index, long timeReference, LogEntry entryToSet) {
+            for (int i = 0; i < MAX_LOG_ENTRY_BYTE_SIZE; i++) {
+                int indexIntoMainBuffer = (index + i) % mBuffer.length;
+                if (indexIntoMainBuffer == mEnd) {
+                    break;
+                }
+                mReadWriteTempBuffer[i] = mBuffer[indexIntoMainBuffer];
+            }
+            return mTranslator.fromBytes(mReadWriteTempBuffer, timeReference, entryToSet);
+        }
+
+        /**
+         * Write a specified {@link LogEntry} to the buffer at the specified index.
+         *
+         * @param index Index in which to write in the buffer.
+         * @param entry The entry to write into the buffer.
+         * @param timeReference The reference time to use when calculating the relative time.
+         */
+        private void writeEntryAt(int index, LogEntry entry, long timeReference) {
+            int size = mTranslator.toBytes(entry, mReadWriteTempBuffer, timeReference);
+            if (size > 0) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Writing Entry (" + index + ") [" + entry + "] as "
+                            + Arrays.toString(mReadWriteTempBuffer));
+                }
+                writeBytesAt(index, mReadWriteTempBuffer, size);
+            }
+        }
+
+        /**
+         * Write the specified bytes into the buffer at the specified index.
+         * Handling wrap-around calculation for the ring-buffer.
+         *
+         * @param index The index from which to start writing.
+         * @param buffer The buffer of bytes to be written.
+         * @param size The amount of bytes to write from {@code buffer} to the log.
+         */
+        private void writeBytesAt(int index, byte[] buffer, int size) {
+            for (int i = 0; i < size; i++) {
+                int indexIntoMainBuffer = (index + i) % mBuffer.length;
+                mBuffer[indexIntoMainBuffer] = buffer[i];
+            }
+            if (DEBUG) {
+                Slog.d(TAG, "Write Byte: " + Arrays.toString(buffer));
+            }
+        }
+    }
+
+    /**
+     * An in-memory database of wake lock {@link TagData}. All tags stored in the database are given
+     * a 7-bit index. This index is then used by {@link TheLog} when translating {@link LogEntry}
+     * instanced into bytes.
+     *
+     * If a new tag is added when the database is full, the oldest tag is removed. The oldest tag
+     * is calcualted using {@link TagData.lastUsedTime}.
+     */
+    static class TagDatabase {
+        private final int mInvalidIndex;
+        private final TagData[] mArray;
+        private Callback mCallback;
+
+        TagDatabase(Injector injector) {
+            int size = Math.min(injector.getTagDatabaseSize(), TAG_DATABASE_SIZE_MAX);
+
+            // Largest possible index used as "INVALID", hence the (size - 1) sizing.
+            mArray = new TagData[size - 1];
+            mInvalidIndex = size - 1;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            sb.append("Tag Database: size(").append(mArray.length).append(")");
+            int entries = 0;
+            int byteEstimate = 0;
+            int tagSize = 0;
+            int tags = 0;
+            for (int i = 0; i < mArray.length; i++) {
+                byteEstimate += 8;  // reference pointer
+                TagData data = mArray[i];
+                if (data != null) {
+                    entries++;
+                    byteEstimate += data.getByteSize();
+                    if (data.tag != null) {
+                        tags++;
+                        tagSize += data.tag.length();
+                    }
+                }
+            }
+            sb.append(", entries: ").append(entries);
+            sb.append(", Bytes used: ").append(byteEstimate);
+            if (DEBUG) {
+                sb.append(", Avg tag size: ").append(tagSize / tags);
+                sb.append("\n    ").append(Arrays.toString(mArray));
+            }
+            return sb.toString();
+        }
+
+        /**
+         * Sets the callback.
+         *
+         * @param callback The callback to set.
+         */
+        public void setCallback(Callback callback) {
+            mCallback = callback;
+        }
+
+        /**
+         * Returns the tag corresponding to the specified index.
+         *
+         * @param index The index to search for.
+         */
+        public TagData getTag(int index) {
+            if (index < 0 || index >= mArray.length || index == mInvalidIndex) {
+                return null;
+            }
+            return mArray[index];
+        }
+
+        /**
+         * Returns an existing tag for the specified wake lock tag + ownerUid.
+         *
+         * @param tag The wake lock tag.
+         * @param ownerUid The wake lock's ownerUid.
+         * @return the TagData instance.
+         */
+        public TagData getTag(String tag, int ownerUid) {
+            return findOrCreateTag(tag, ownerUid, false /* shouldCreate */);
+        }
+
+        /**
+         * Returns the index for the corresponding tag.
+         *
+         * @param tagData The tag-data to search for.
+         * @return the corresponding index, or mInvalidIndex of none is found.
+         */
+        public int getTagIndex(TagData tagData) {
+            return tagData == null ? mInvalidIndex : tagData.index;
+        }
+
+        /**
+         * Returns a tag instance for the specified wake lock tag and ownerUid. If the data
+         * does not exist in the database, it will be created if so specified by
+         * {@code shouldCreate}.
+         *
+         * @param tagStr The wake lock's tag.
+         * @param ownerUid The wake lock's owner Uid.
+         * @param shouldCreate True when the tag should be created if it doesn't already exist.
+         * @return The tag-data instance that was found or created.
+         */
+        public TagData findOrCreateTag(String tagStr, int ownerUid, boolean shouldCreate) {
+            int firstAvailable = -1;
+            TagData oldest = null;
+            int oldestIndex = -1;
+
+            // Loop through and find the tag to be used.
+            TagData tag = new TagData(tagStr, ownerUid);
+            for (int i = 0; i < mArray.length; i++) {
+                TagData current = mArray[i];
+                if (tag.equals(current)) {
+                    // found it
+                    return current;
+                } else if (!shouldCreate) {
+                    continue;
+                } else if (current != null) {
+                    // See if this entry is the oldest entry, in case
+                    // we need to replace it.
+                    if (oldest == null || current.lastUsedTime < oldest.lastUsedTime) {
+                        oldestIndex = i;
+                        oldest = current;
+                    }
+                } else if (firstAvailable == -1) {
+                    firstAvailable = i;
+                }
+            }
+
+            // Item not found, and we shouldn't create one.
+            if (!shouldCreate) {
+                return null;
+            }
+
+            // If we need to remove an index, report to listeners that we are removing an index.
+            boolean useOldest = firstAvailable == -1;
+            if (useOldest && mCallback != null) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Removing tag index: " + oldestIndex + " = " + oldest);
+                }
+                mCallback.onIndexRemoved(oldestIndex);
+            }
+            setToIndex(tag, firstAvailable != -1 ? firstAvailable : oldestIndex);
+            return tag;
+        }
+
+        /**
+         * Updates the last-used-time of the specified tag.
+         *
+         * @param tag The tag to update.
+         * @param time The new last-used-time for the tag.
+         */
+        public static void updateTagTime(TagData tag, long time) {
+            if (tag != null) {
+                tag.lastUsedTime = time;
+            }
+        }
+
+        /**
+         * Sets a specified tag to the specified index.
+         */
+        private void setToIndex(TagData tag, int index) {
+            if (index < 0 || index >= mArray.length) {
+                return;
+            }
+            TagData current = mArray[index];
+            if (current != null) {
+                // clean up the reference in the TagData instance first.
+                current.index = mInvalidIndex;
+
+                if (DEBUG) {
+                    Slog.d(TAG, "Replaced tag " + current.tag + " from index " + index + " with tag"
+                            + tag);
+                }
+            }
+
+            mArray[index] = tag;
+            tag.index = index;
+        }
+
+        /**
+         * Callback on which to be notified of changes to {@link TagDatabase}.
+         */
+        interface Callback {
+
+            /**
+             * Handles removals of TagData indexes.
+             *
+             * @param index the index being removed.
+             */
+            void onIndexRemoved(int index);
+        }
+    }
+
+    /**
+     * This class represents unique wake lock tags that are stored in {@link TagDatabase}.
+     * Contains both the wake lock tag data (tag + ownerUid) as well as index and last-used
+     * time data as it relates to the tag-database.
+     */
+    static class TagData {
+        public String tag;  // Wake lock tag
+        public int ownerUid;  // Wake lock owner Uid
+        public int index;  // Index of the tag in the tag-database
+        public long lastUsedTime;  // Last time that this entry was used
+
+        TagData(String tag, int ownerUid) {
+            this.tag = tag;
+            this.ownerUid = ownerUid;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o instanceof TagData) {
+                TagData other = (TagData) o;
+                return TextUtils.equals(tag, other.tag) && ownerUid == other.ownerUid;
+            }
+            return false;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            if (DEBUG) {
+                sb.append("(").append(index).append(")");
+            }
+            return "[" + ownerUid + " ; " + tag + "]";
+        }
+
+        /**
+         * Returns an estimate of the number of bytes used by each instance of this class.
+         * Used for debug purposes.
+         *
+         * @return the size of this tag-data.
+         */
+        int getByteSize() {
+            int bytes = 0;
+            bytes += 8;  // tag reference-pointer;
+            bytes += tag == null ? 0 : tag.length() * 2;
+            bytes += 4;  // ownerUid
+            bytes += 4;  // index
+            bytes += 8;  // lastUsedTime
+            return bytes;
+        }
+    }
+
+    /**
+     * Injector used by {@link WakeLockLog} for testing purposes.
+     */
+    public static class Injector {
+        public Looper getLooper() {
+            return BackgroundThread.get().getLooper();
+        }
+
+        public int getTagDatabaseSize() {
+            return TAG_DATABASE_SIZE;
+        }
+
+        public int getLogSize() {
+            return LOG_SIZE;
+        }
+
+        public long currentTimeMillis() {
+            return System.currentTimeMillis();
+        }
+
+        public SimpleDateFormat getDateFormat() {
+            return DATE_FORMAT;
+        }
+    }
+
+    private class WakeLockLogHandler extends Handler {
+        WakeLockLogHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message message) {
+            switch(message.what) {
+                case MSG_ON_WAKE_LOCK_EVENT:
+                    final SomeArgs args = (SomeArgs) message.obj;
+                    final String tag = (String) args.arg1;
+                    final int eventType = args.argi1;
+                    final int ownerUid = args.argi2;
+                    final int flags = args.argi3;
+                    final long time = (((long) args.argi4) << 32) + (args.argi5 & 0xFFFFFFFFL);
+                    args.recycle();
+                    handleWakeLockEventInternal(eventType, tag, ownerUid, flags, time);
+                    break;
+                default:
+                    break;
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/protolog/ProtoLogImpl.java b/services/core/java/com/android/server/protolog/ProtoLogImpl.java
index 1653b3d..c9d42c8 100644
--- a/services/core/java/com/android/server/protolog/ProtoLogImpl.java
+++ b/services/core/java/com/android/server/protolog/ProtoLogImpl.java
@@ -38,7 +38,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.protolog.common.IProtoLogGroup;
 import com.android.server.protolog.common.LogDataType;
-import com.android.server.utils.TraceBuffer;
+import com.android.internal.util.TraceBuffer;
 import com.android.server.wm.ProtoLogGroup;
 
 import java.io.File;
diff --git a/services/core/java/com/android/server/rollback/Rollback.java b/services/core/java/com/android/server/rollback/Rollback.java
index 5c0dd9a..cb583cd 100644
--- a/services/core/java/com/android/server/rollback/Rollback.java
+++ b/services/core/java/com/android/server/rollback/Rollback.java
@@ -179,6 +179,13 @@
     private final IntArray mTokens = new IntArray();
 
     /**
+     * Session ids for all packages in the install. For multi-package sessions, this is the list
+     * of child session ids. For normal sessions, this list is a single element with the normal
+     * session id.
+     */
+    private final int[] mPackageSessionIds;
+
+    /**
      * Constructs a new, empty Rollback instance.
      *
      * @param rollbackId the id of the rollback.
@@ -186,9 +193,10 @@
      * @param stagedSessionId the session id if this is a staged rollback, -1 otherwise.
      * @param userId the user that performed the install with rollback enabled.
      * @param installerPackageName the installer package name from the original install session.
+     * @param packageSessionIds the session ids for all packages in the install.
      */
     Rollback(int rollbackId, File backupDir, int stagedSessionId, int userId,
-            String installerPackageName) {
+            String installerPackageName, int[] packageSessionIds) {
         this.info = new RollbackInfo(rollbackId,
                 /* packages */ new ArrayList<>(),
                 /* isStaged */ stagedSessionId != -1,
@@ -200,6 +208,12 @@
         mStagedSessionId = stagedSessionId;
         mState = ROLLBACK_STATE_ENABLING;
         mTimestamp = Instant.now();
+        mPackageSessionIds = packageSessionIds != null ? packageSessionIds : new int[0];
+    }
+
+    Rollback(int rollbackId, File backupDir, int stagedSessionId, int userId,
+             String installerPackageName) {
+        this(rollbackId, backupDir, stagedSessionId, userId, installerPackageName, null);
     }
 
     /**
@@ -217,6 +231,11 @@
         mState = state;
         mApkSessionId = apkSessionId;
         mRestoreUserDataInProgress = restoreUserDataInProgress;
+        // TODO(b/120200473): Include this field during persistence. This field will be used to
+        // decide which rollback to expire when ACTION_PACKAGE_REPLACED is received. Note persisting
+        // this field is not backward compatible. We won't fix b/120200473 until S to minimize the
+        // impact.
+        mPackageSessionIds = new int[0];
     }
 
     /**
@@ -793,6 +812,25 @@
         }
     }
 
+    /**
+     * Returns true if this rollback contains the provided {@code packageSessionId}.
+     */
+    boolean containsSessionId(int packageSessionId) {
+        for (int id : mPackageSessionIds) {
+            if (id == packageSessionId) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns the number of package session ids in this rollback.
+     */
+    int getPackageSessionIdCount() {
+        return mPackageSessionIds.length;
+    }
+
     static String rollbackStateToString(@RollbackState int state) {
         switch (state) {
             case Rollback.ROLLBACK_STATE_ENABLING: return "enabling";
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index de48939..4bab224 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -1238,7 +1238,8 @@
         // equal to the number of sessions we are installing, to ensure we didn't skip enabling
         // of any sessions. If we successfully enable an apex, then we can assume we enabled
         // rollback for the embedded apk-in-apex, if any.
-        if (rollback.getPackageCount(0 /*flags*/) != newRollback.getPackageSessionIdCount()) {
+        // TODO: add a helper instead of exposing 2 methods from Rollback
+        if (rollback.getPackageCount(0 /*flags*/) != rollback.getPackageSessionIdCount()) {
             Slog.e(TAG, "Failed to enable rollback for all packages in session.");
             rollback.delete(mAppDataRollbackHelper);
             return null;
@@ -1343,13 +1344,6 @@
         public final Rollback rollback;
 
         /**
-         * Session ids for all packages in the install. For multi-package sessions, this is the list
-         * of child session ids. For normal sessions, this list is a single element with the normal
-         * session id.
-         */
-        private final int[] mPackageSessionIds;
-
-        /**
          * The number of sessions in the install which are notified with success by
          * {@link PackageInstaller.SessionCallback#onFinished(int, boolean)}.
          * This NewRollback will be enabled only after all child sessions finished with success.
@@ -1359,28 +1353,8 @@
 
         private final Object mNewRollbackLock = new Object();
 
-        NewRollback(Rollback rollback, int[] packageSessionIds) {
+        NewRollback(Rollback rollback) {
             this.rollback = rollback;
-            this.mPackageSessionIds = packageSessionIds;
-        }
-
-        /**
-         * Returns true if this NewRollback contains the provided {@code packageSessionId}.
-         */
-        boolean containsSessionId(int packageSessionId) {
-            for (int id : mPackageSessionIds) {
-                if (id == packageSessionId) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        /**
-         * Returns the number of package session ids in this NewRollback.
-         */
-        int getPackageSessionIdCount() {
-            return mPackageSessionIds.length;
         }
 
         /**
@@ -1390,7 +1364,7 @@
          */
         boolean notifySessionWithSuccess() {
             synchronized (mNewRollbackLock) {
-                return ++mNumPackageSessionsWithSuccess == mPackageSessionIds.length;
+                return ++mNumPackageSessionsWithSuccess == rollback.getPackageSessionIdCount();
             }
         }
     }
@@ -1414,14 +1388,6 @@
                     + " user=" + userId + " installer=" + installerPackageName);
         }
 
-        if (parentSession.isStaged()) {
-            rollback = mRollbackStore.createStagedRollback(rollbackId, parentSessionId, userId,
-                    installerPackageName);
-        } else {
-            rollback = mRollbackStore.createNonStagedRollback(rollbackId, userId,
-                    installerPackageName);
-        }
-
         int[] packageSessionIds;
         if (parentSession.isMultiPackage()) {
             packageSessionIds = parentSession.getChildSessionIds();
@@ -1429,7 +1395,15 @@
             packageSessionIds = new int[]{parentSessionId};
         }
 
-        return new NewRollback(rollback, packageSessionIds);
+        if (parentSession.isStaged()) {
+            rollback = mRollbackStore.createStagedRollback(rollbackId, parentSessionId, userId,
+                    installerPackageName, packageSessionIds);
+        } else {
+            rollback = mRollbackStore.createNonStagedRollback(rollbackId, userId,
+                    installerPackageName, packageSessionIds);
+        }
+
+        return new NewRollback(rollback);
     }
 
     /**
@@ -1443,7 +1417,7 @@
         // We expect mNewRollbacks to be a very small list; linear search
         // should be plenty fast.
         for (NewRollback newRollback: mNewRollbacks) {
-            if (newRollback.containsSessionId(packageSessionId)) {
+            if (newRollback.rollback.containsSessionId(packageSessionId)) {
                 return newRollback;
             }
         }
diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java
index bbcd0de..4f89482 100644
--- a/services/core/java/com/android/server/rollback/RollbackStore.java
+++ b/services/core/java/com/android/server/rollback/RollbackStore.java
@@ -204,6 +204,13 @@
         return new Rollback(rollbackId, backupDir, -1, userId, installerPackageName);
     }
 
+    Rollback createNonStagedRollback(int rollbackId, int userId, String installerPackageName,
+            int[] packageSessionIds) {
+        File backupDir = new File(mRollbackDataDir, Integer.toString(rollbackId));
+        return new Rollback(rollbackId, backupDir, -1, userId, installerPackageName,
+                packageSessionIds);
+    }
+
     /**
      * Creates a new Rollback instance for a staged rollback with
      * backupDir assigned.
@@ -215,6 +222,17 @@
     }
 
     /**
+     * TODO: Now we have 4 factory methods for creating Rollback objects which is verbose and
+     * cumbersome. Need to merge them for simplicity.
+     */
+    Rollback createStagedRollback(int rollbackId, int stagedSessionId, int userId,
+            String installerPackageName, int[] packageSessionIds) {
+        File backupDir = new File(mRollbackDataDir, Integer.toString(rollbackId));
+        return new Rollback(rollbackId, backupDir, stagedSessionId, userId, installerPackageName,
+                packageSessionIds);
+    }
+
+    /**
      * Creates a backup copy of an apk or apex for a package.
      * For packages containing splits, this method should be called for each
      * of the package's split apks in addition to the base apk.
diff --git a/services/core/java/com/android/server/stats/pull/ProcfsMemoryUtil.java b/services/core/java/com/android/server/stats/pull/ProcfsMemoryUtil.java
index 638dfd2..67677c6 100644
--- a/services/core/java/com/android/server/stats/pull/ProcfsMemoryUtil.java
+++ b/services/core/java/com/android/server/stats/pull/ProcfsMemoryUtil.java
@@ -19,8 +19,7 @@
 
 import android.annotation.Nullable;
 import android.os.Process;
-
-import java.util.function.BiConsumer;
+import android.util.SparseArray;
 
 public final class ProcfsMemoryUtil {
     private static final int[] CMDLINE_OUT = new int[] { PROC_OUT_STRING };
@@ -71,19 +70,25 @@
         return cmdline[0];
     }
 
-    public static void forEachPid(BiConsumer<Integer, String> func) {
+    /**
+     * Scans all /proc/pid/cmdline entries and returns a mapping between pid and cmdline.
+     */
+    public static SparseArray<String> getProcessCmdlines() {
         int[] pids = new int[1024];
         pids = Process.getPids("/proc", pids);
+
+        SparseArray<String> cmdlines = new SparseArray<>(pids.length);
         for (int pid : pids) {
             if (pid < 0) {
-                return;
+                break;
             }
             String cmdline = readCmdlineFromProcfs(pid);
             if (cmdline.isEmpty()) {
                 continue;
             }
-            func.accept(pid, cmdline);
+            cmdlines.append(pid, cmdline);
         }
+        return cmdlines;
     }
 
     public static final class MemorySnapshot {
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index a0e6be4..3aa51fb 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -20,7 +20,6 @@
 import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
 import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;
 import static android.os.Debug.getIonHeapsSizeKb;
-import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
 import static android.os.Process.getUidForPid;
 import static android.os.storage.VolumeInfo.TYPE_PRIVATE;
 import static android.os.storage.VolumeInfo.TYPE_PUBLIC;
@@ -28,15 +27,12 @@
 import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
 import static com.android.server.stats.pull.IonMemoryUtil.readProcessSystemIonHeapSizesFromDebugfs;
 import static com.android.server.stats.pull.IonMemoryUtil.readSystemIonHeapSizeFromDebugfs;
-import static com.android.server.stats.pull.ProcfsMemoryUtil.forEachPid;
+import static com.android.server.stats.pull.ProcfsMemoryUtil.getProcessCmdlines;
 import static com.android.server.stats.pull.ProcfsMemoryUtil.readCmdlineFromProcfs;
 import static com.android.server.stats.pull.ProcfsMemoryUtil.readMemorySnapshotFromProcfs;
 
-import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManagerInternal;
-import android.app.AlarmManager;
-import android.app.AlarmManager.OnAlarmListener;
 import android.app.AppOpsManager;
 import android.app.AppOpsManager.HistoricalOps;
 import android.app.AppOpsManager.HistoricalOpsRequest;
@@ -49,10 +45,7 @@
 import android.bluetooth.BluetoothActivityEnergyInfo;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.UidTraffic;
-import android.content.BroadcastReceiver;
 import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -74,23 +67,14 @@
 import android.os.Bundle;
 import android.os.CoolingDevice;
 import android.os.Environment;
-import android.os.FileUtils;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.IPullAtomCallback;
-import android.os.IStatsCompanionService;
-import android.os.IStatsd;
 import android.os.IStoraged;
 import android.os.IThermalEventListener;
 import android.os.IThermalService;
-import android.os.Looper;
 import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.StatFs;
-import android.os.StatsLogEventWrapper;
 import android.os.SynchronousResultReceiver;
 import android.os.SystemClock;
 import android.os.SystemProperties;
@@ -109,6 +93,7 @@
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.Slog;
+import android.util.SparseArray;
 import android.util.StatsEvent;
 import android.util.StatsLog;
 import android.util.proto.ProtoOutputStream;
@@ -134,7 +119,6 @@
 import com.android.internal.os.PowerProfile;
 import com.android.internal.os.ProcessCpuTracker;
 import com.android.internal.os.StoragedUidIoStatsReader;
-import com.android.internal.util.DumpUtils;
 import com.android.server.BinderCallsStatsService;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
@@ -147,8 +131,6 @@
 import com.android.server.storage.DiskStatsFileLogger;
 import com.android.server.storage.DiskStatsLoggingService;
 
-import com.google.android.collect.Sets;
-
 import libcore.io.IoUtils;
 
 import org.json.JSONArray;
@@ -156,20 +138,15 @@
 import org.json.JSONObject;
 
 import java.io.File;
-import java.io.FileDescriptor;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.MissingResourceException;
-import java.util.Objects;
 import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.CompletableFuture;
@@ -187,11 +164,24 @@
     private static final String TAG = "StatsPullAtomService";
     private static final boolean DEBUG = true;
 
+    /**
+     * Lowest available uid for apps.
+     *
+     * <p>Used to quickly discard memory snapshots of the zygote forks from native process
+     * measurements.
+     */
+    private static final int MIN_APP_UID = 10_000;
+
     private static final String RESULT_RECEIVER_CONTROLLER_KEY = "controller_activity";
     /**
      * How long to wait on an individual subsystem to return its stats.
      */
     private static final long EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS = 2000;
+    private static final long NS_PER_SEC = 1000000000;
+    private static final long MILLI_AMP_HR_TO_NANO_AMP_SECS = 1_000_000L * 3600L;
+
+    private static final int MAX_BATTERY_STATS_HELPER_FREQUENCY_MS = 1000;
+    private static final int CPU_TIME_PER_THREAD_FREQ_MAX_NUM_FREQUENCIES = 8;
 
     private final Object mNetworkStatsLock = new Object();
     @GuardedBy("mNetworkStatsLock")
@@ -213,22 +203,223 @@
     @GuardedBy("mProcessStatsLock")
     private IProcessStats mProcessStatsService;
 
+    private final Object mCpuTrackerLock = new Object();
+    @GuardedBy("mCpuTrackerLock")
+    private ProcessCpuTracker mProcessCpuTracker;
+
+    private final Object mDebugElapsedClockLock = new Object();
+    @GuardedBy("mDebugElapsedClockLock")
+    private long mDebugElapsedClockPreviousValue = 0;
+    @GuardedBy("mDebugElapsedClockLock")
+    private long mDebugElapsedClockPullCount = 0;
+
+    private final Object mDebugFailingElapsedClockLock = new Object();
+    @GuardedBy("mDebugFailingElapsedClockLock")
+    private long mDebugFailingElapsedClockPreviousValue = 0;
+    @GuardedBy("mDebugFailingElapsedClockLock")
+    private long mDebugFailingElapsedClockPullCount = 0;
+
     private final Context mContext;
     private StatsManager mStatsManager;
     private StorageManager mStorageManager;
+    private WifiManager mWifiManager;
+    private TelephonyManager mTelephony;
+
+    private KernelWakelockReader mKernelWakelockReader;
+    private KernelWakelockStats mTmpWakelockStats;
+
+    private StoragedUidIoStatsReader mStoragedUidIoStatsReader;
+
+    private KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
+    // Disables throttler on CPU time readers.
+    private KernelCpuUidUserSysTimeReader mCpuUidUserSysTimeReader;
+    private KernelCpuUidFreqTimeReader mCpuUidFreqTimeReader;
+    private KernelCpuUidActiveTimeReader mCpuUidActiveTimeReader;
+    private KernelCpuUidClusterTimeReader mCpuUidClusterTimeReader;
+
+    private File mBaseDir;
+
+    @Nullable
+    private KernelCpuThreadReaderDiff mKernelCpuThreadReader;
+
+    private BatteryStatsHelper mBatteryStatsHelper = null;
+    private long mBatteryStatsHelperTimestampMs = -MAX_BATTERY_STATS_HELPER_FREQUENCY_MS;
+
+    private StatsPullAtomCallbackImpl mStatsCallbackImpl;
 
     public StatsPullAtomService(Context context) {
         super(context);
         mContext = context;
     }
 
+    /**
+     * Use of this StatsPullAtomCallbackImpl means we avoid one class per tagId, which we would
+     * get if we used lambdas.
+     *
+     * The pull methods are intentionally left to be package private to avoid the creation
+     * of synthetic methods to save unnecessary bytecode.
+     */
+    private class StatsPullAtomCallbackImpl implements StatsManager.StatsPullAtomCallback {
+        @Override
+        public int onPullAtom(int atomTag, List<StatsEvent> data) {
+            switch(atomTag) {
+                case StatsLog.WIFI_BYTES_TRANSFER:
+                    return pullWifiBytesTransfer(atomTag, data);
+                case StatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG:
+                    return pullWifiBytesTransferBackground(atomTag, data);
+                case StatsLog.MOBILE_BYTES_TRANSFER:
+                    return pullMobileBytesTransfer(atomTag, data);
+                case StatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG:
+                    return pullMobileBytesTransferBackground(atomTag, data);
+                case StatsLog.BLUETOOTH_BYTES_TRANSFER:
+                    return pullBluetoothBytesTransfer(atomTag, data);
+                case StatsLog.KERNEL_WAKELOCK:
+                    return pullKernelWakelock(atomTag, data);
+                case StatsLog.CPU_TIME_PER_FREQ:
+                    return pullCpuTimePerFreq(atomTag, data);
+                case StatsLog.CPU_TIME_PER_UID:
+                    return pullCpuTimePerUid(atomTag, data);
+                case StatsLog.CPU_TIME_PER_UID_FREQ:
+                    return pullCpuTimeperUidFreq(atomTag, data);
+                case StatsLog.CPU_ACTIVE_TIME:
+                    return pullCpuActiveTime(atomTag, data);
+                case StatsLog.CPU_CLUSTER_TIME:
+                    return pullCpuClusterTime(atomTag, data);
+                case StatsLog.WIFI_ACTIVITY_INFO:
+                    return pullWifiActivityInfo(atomTag, data);
+                case StatsLog.MODEM_ACTIVITY_INFO:
+                    return pullModemActivityInfo(atomTag, data);
+                case StatsLog.BLUETOOTH_ACTIVITY_INFO:
+                    return pullBluetoothActivityInfo(atomTag, data);
+                case StatsLog.SYSTEM_ELAPSED_REALTIME:
+                    return pullSystemElapsedRealtime(atomTag, data);
+                case StatsLog.SYSTEM_UPTIME:
+                    return pullSystemUptime(atomTag, data);
+                case StatsLog.PROCESS_MEMORY_STATE:
+                    return pullProcessMemoryState(atomTag, data);
+                case StatsLog.PROCESS_MEMORY_HIGH_WATER_MARK:
+                    return pullProcessMemoryHighWaterMark(atomTag, data);
+                case StatsLog.PROCESS_MEMORY_SNAPSHOT:
+                    return pullProcessMemorySnapshot(atomTag, data);
+                case StatsLog.SYSTEM_ION_HEAP_SIZE:
+                    return pullSystemIonHeapSize(atomTag, data);
+                case StatsLog.ION_HEAP_SIZE:
+                    return pullIonHeapSize(atomTag, data);
+                case StatsLog.PROCESS_SYSTEM_ION_HEAP_SIZE:
+                    return pullProcessSystemIonHeapSize(atomTag, data);
+                case StatsLog.TEMPERATURE:
+                    return pullTemperature(atomTag, data);
+                case StatsLog.COOLING_DEVICE:
+                    return pullCooldownDevice(atomTag, data);
+                case StatsLog.BINDER_CALLS:
+                    return pullBinderCallsStats(atomTag, data);
+                case StatsLog.BINDER_CALLS_EXCEPTIONS:
+                    return pullBinderCallsStatsExceptions(atomTag, data);
+                case StatsLog.LOOPER_STATS:
+                    return pullLooperStats(atomTag, data);
+                case StatsLog.DISK_STATS:
+                    return pullDiskStats(atomTag, data);
+                case StatsLog.DIRECTORY_USAGE:
+                    return pullDirectoryUsage(atomTag, data);
+                case StatsLog.APP_SIZE:
+                    return pullAppSize(atomTag, data);
+                case StatsLog.CATEGORY_SIZE:
+                    return pullCategorySize(atomTag, data);
+                case StatsLog.NUM_FINGERPRINTS_ENROLLED:
+                    return pullNumBiometricsEnrolled(
+                            BiometricsProtoEnums.MODALITY_FINGERPRINT, atomTag, data);
+                case StatsLog.NUM_FACES_ENROLLED:
+                    return pullNumBiometricsEnrolled(
+                            BiometricsProtoEnums.MODALITY_FACE, atomTag, data);
+                case StatsLog.PROC_STATS:
+                    return pullProcStats(ProcessStats.REPORT_ALL, atomTag, data);
+                case StatsLog.PROC_STATS_PKG_PROC:
+                    return pullProcStats(ProcessStats.REPORT_PKG_PROC_STATS, atomTag, data);
+                case StatsLog.DISK_IO:
+                    return pullDiskIO(atomTag, data);
+                case StatsLog.POWER_PROFILE:
+                    return pullPowerProfile(atomTag, data);
+                case StatsLog.PROCESS_CPU_TIME:
+                    return pullProcessCpuTime(atomTag, data);
+                case StatsLog.CPU_TIME_PER_THREAD_FREQ:
+                    return pullCpuTimePerThreadFreq(atomTag, data);
+                case StatsLog.DEVICE_CALCULATED_POWER_USE:
+                    return pullDeviceCalculatedPowerUse(atomTag, data);
+                case StatsLog.DEVICE_CALCULATED_POWER_BLAME_UID:
+                    return pullDeviceCalculatedPowerBlameUid(atomTag, data);
+                case StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER:
+                    return pullDeviceCalculatedPowerBlameOther(atomTag, data);
+                case StatsLog.DEBUG_ELAPSED_CLOCK:
+                    return pullDebugElapsedClock(atomTag, data);
+                case StatsLog.DEBUG_FAILING_ELAPSED_CLOCK:
+                    return pullDebugFailingElapsedClock(atomTag, data);
+                case StatsLog.BUILD_INFORMATION:
+                    return pullBuildInformation(atomTag, data);
+                case StatsLog.ROLE_HOLDER:
+                    return pullRoleHolder(atomTag, data);
+                case StatsLog.DANGEROUS_PERMISSION_STATE:
+                    return pullDangerousPermissionState(atomTag, data);
+                case StatsLog.TIME_ZONE_DATA_INFO:
+                    return pullTimeZoneDataInfo(atomTag, data);
+                case StatsLog.EXTERNAL_STORAGE_INFO:
+                    return pullExternalStorageInfo(atomTag, data);
+                case StatsLog.APPS_ON_EXTERNAL_STORAGE_INFO:
+                    return pullAppsOnExternalStorageInfo(atomTag, data);
+                case StatsLog.FACE_SETTINGS:
+                    return pullFaceSettings(atomTag, data);
+                case StatsLog.APP_OPS:
+                    return pullAppOps(atomTag, data);
+                case StatsLog.NOTIFICATION_REMOTE_VIEWS:
+                    return pullNotificationRemoteViews(atomTag, data);
+                case StatsLog.DANGEROUS_PERMISSION_STATE_SAMPLED:
+                    return pullDangerousPermissionState(atomTag, data);
+                default:
+                    throw new UnsupportedOperationException("Unknown tagId=" + atomTag);
+            }
+        }
+    }
+
     @Override
     public void onStart() {
+        // no op
+    }
+
+    @Override
+    public void onBootPhase(int phase) {
+        super.onBootPhase(phase);
+        if (phase == PHASE_SYSTEM_SERVICES_READY) {
+            BackgroundThread.getHandler().post(() -> {
+                initializePullersState();
+                registerAllPullers();
+                registerEventListeners();
+            });
+        }
+    }
+
+    void initializePullersState() {
+        // Get Context Managers
         mStatsManager = (StatsManager) mContext.getSystemService(Context.STATS_MANAGER);
         mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
         mTelephony = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
         mStorageManager = (StorageManager) mContext.getSystemService(StorageManager.class);
 
+        // Initialize DiskIO
+        mStoragedUidIoStatsReader = new StoragedUidIoStatsReader();
+
+        // Initialize PROC_STATS
+        // TODO (b/148402814): Change this directory to stats_pull.
+        mBaseDir = new File(SystemServiceManager.ensureSystemDir(), "stats_companion");
+
+        // Disables throttler on CPU time readers.
+        mCpuUidUserSysTimeReader = new KernelCpuUidUserSysTimeReader(false);
+        mCpuUidFreqTimeReader = new KernelCpuUidFreqTimeReader(false);
+        mCpuUidActiveTimeReader = new KernelCpuUidActiveTimeReader(false);
+        mCpuUidClusterTimeReader = new KernelCpuUidClusterTimeReader(false);
+
+        // Initialize state for KERNEL_WAKELOCK
+        mKernelWakelockReader = new KernelWakelockReader();
+        mTmpWakelockStats = new KernelWakelockStats();
+
         // Initialize state for CPU_TIME_PER_FREQ atom
         PowerProfile powerProfile = new PowerProfile(mContext);
         final int numClusters = powerProfile.getNumCpuClusters();
@@ -249,13 +440,23 @@
         mBaseDir.mkdirs();
     }
 
-    @Override
-    public void onBootPhase(int phase) {
-        super.onBootPhase(phase);
-        if (phase == PHASE_SYSTEM_SERVICES_READY) {
-            BackgroundThread.getHandler().post(() -> {
-                registerAllPullers();
-            });
+    void registerEventListeners() {
+        final ConnectivityManager connectivityManager =
+                (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+        // Default NetworkRequest should cover all transport types.
+        final NetworkRequest request = new NetworkRequest.Builder().build();
+        connectivityManager.registerNetworkCallback(request, new ConnectivityStatsCallback());
+
+        // Enable push notifications of throttling from vendor thermal
+        // management subsystem via thermalservice.
+        IThermalService thermalService = getIThermalService();
+        if (thermalService != null) {
+            try {
+                thermalService.registerThermalEventListener(new ThermalEventListener());
+                Slog.i(TAG, "register thermal listener successfully");
+            } catch (RemoteException e) {
+                Slog.i(TAG, "failed to register thermal listener");
+            }
         }
     }
 
@@ -263,6 +464,7 @@
         if (DEBUG) {
             Slog.d(TAG, "Registering all pullers with statsd");
         }
+        mStatsCallbackImpl = new StatsPullAtomCallbackImpl();
         registerWifiBytesTransfer();
         registerWifiBytesTransferBackground();
         registerMobileBytesTransfer();
@@ -279,11 +481,6 @@
         registerBluetoothActivityInfo();
         registerSystemElapsedRealtime();
         registerSystemUptime();
-        registerRemainingBatteryCapacity();
-        registerFullBatteryCapacity();
-        registerBatteryVoltage();
-        registerBatteryLevel();
-        registerBatteryCycleCount();
         registerProcessMemoryState();
         registerProcessMemoryHighWaterMark();
         registerProcessMemorySnapshot();
@@ -444,11 +641,11 @@
                 tagId,
                 metadata,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullWifiBytesTransfer(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullWifiBytesTransfer(int atomTag, List<StatsEvent> pulledData) {
+    int pullWifiBytesTransfer(int atomTag, List<StatsEvent> pulledData) {
         INetworkStatsService networkStatsService = getINetworkStatsService();
         if (networkStatsService == null) {
             Slog.e(TAG, "NetworkStats Service is not available!");
@@ -456,7 +653,7 @@
         }
         long token = Binder.clearCallingIdentity();
         try {
-            // TODO: Consider caching the following call to get BatteryStatsInternal.
+            // TODO(b/148402814): Consider caching the following call to get BatteryStatsInternal.
             BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
             String[] ifaces = bs.getWifiIfaces();
             if (ifaces.length == 0) {
@@ -536,11 +733,11 @@
                 tagId,
                 metadata,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullWifiBytesTransferBackground(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullWifiBytesTransferBackground(int atomTag, List<StatsEvent> pulledData) {
+    int pullWifiBytesTransferBackground(int atomTag, List<StatsEvent> pulledData) {
         INetworkStatsService networkStatsService = getINetworkStatsService();
         if (networkStatsService == null) {
             Slog.e(TAG, "NetworkStats Service is not available!");
@@ -574,11 +771,11 @@
                 tagId,
                 metadata,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullMobileBytesTransfer(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullMobileBytesTransfer(int atomTag, List<StatsEvent> pulledData) {
+    int pullMobileBytesTransfer(int atomTag, List<StatsEvent> pulledData) {
         INetworkStatsService networkStatsService = getINetworkStatsService();
         if (networkStatsService == null) {
             Slog.e(TAG, "NetworkStats Service is not available!");
@@ -612,11 +809,11 @@
                 tagId,
                 metadata,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullMobileBytesTransferBackground(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullMobileBytesTransferBackground(int atomTag, List<StatsEvent> pulledData) {
+    int pullMobileBytesTransferBackground(int atomTag, List<StatsEvent> pulledData) {
         INetworkStatsService networkStatsService = getINetworkStatsService();
         if (networkStatsService == null) {
             Slog.e(TAG, "NetworkStats Service is not available!");
@@ -650,7 +847,7 @@
                 tagId,
                 metadata,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullBluetoothBytesTransfer(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
@@ -697,7 +894,7 @@
         }
     }
 
-    private int pullBluetoothBytesTransfer(int atomTag, List<StatsEvent> pulledData) {
+    int pullBluetoothBytesTransfer(int atomTag, List<StatsEvent> pulledData) {
         BluetoothActivityEnergyInfo info = fetchBluetoothData();
         if (info == null || info.getUidTraffic() == null) {
             return StatsManager.PULL_SKIP;
@@ -714,20 +911,17 @@
         return StatsManager.PULL_SUCCESS;
     }
 
-    private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader();
-    private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
-
     private void registerKernelWakelock() {
         int tagId = StatsLog.KERNEL_WAKELOCK;
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 /* PullAtomMetadata */ null,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullKernelWakelock(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullKernelWakelock(int atomTag, List<StatsEvent> pulledData) {
+    int pullKernelWakelock(int atomTag, List<StatsEvent> pulledData) {
         final KernelWakelockStats wakelockStats =
                 mKernelWakelockReader.readKernelWakelockStats(mTmpWakelockStats);
         for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
@@ -745,17 +939,6 @@
         return StatsManager.PULL_SUCCESS;
     }
 
-    private KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
-    // Disables throttler on CPU time readers.
-    private KernelCpuUidUserSysTimeReader mCpuUidUserSysTimeReader =
-            new KernelCpuUidUserSysTimeReader(false);
-    private KernelCpuUidFreqTimeReader mCpuUidFreqTimeReader =
-            new KernelCpuUidFreqTimeReader(false);
-    private KernelCpuUidActiveTimeReader mCpuUidActiveTimeReader =
-            new KernelCpuUidActiveTimeReader(false);
-    private KernelCpuUidClusterTimeReader mCpuUidClusterTimeReader =
-            new KernelCpuUidClusterTimeReader(false);
-
     private void registerCpuTimePerFreq() {
         int tagId = StatsLog.CPU_TIME_PER_FREQ;
         PullAtomMetadata metadata = new PullAtomMetadata.Builder()
@@ -765,11 +948,11 @@
                 tagId,
                 metadata,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullCpuTimePerFreq(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullCpuTimePerFreq(int atomTag, List<StatsEvent> pulledData) {
+    int pullCpuTimePerFreq(int atomTag, List<StatsEvent> pulledData) {
         for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
             long[] clusterTimeMs = mKernelCpuSpeedReaders[cluster].readAbsolute();
             if (clusterTimeMs != null) {
@@ -796,11 +979,11 @@
                 tagId,
                 metadata,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullCpuTimePerUid(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullCpuTimePerUid(int atomTag, List<StatsEvent> pulledData) {
+    int pullCpuTimePerUid(int atomTag, List<StatsEvent> pulledData) {
         mCpuUidUserSysTimeReader.readAbsolute((uid, timesUs) -> {
             long userTimeUs = timesUs[0], systemTimeUs = timesUs[1];
             StatsEvent e = StatsEvent.newBuilder()
@@ -825,11 +1008,11 @@
                 tagId,
                 metadata,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullCpuTimeperUidFreq(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullCpuTimeperUidFreq(int atomTag, List<StatsEvent> pulledData) {
+    int pullCpuTimeperUidFreq(int atomTag, List<StatsEvent> pulledData) {
         mCpuUidFreqTimeReader.readAbsolute((uid, cpuFreqTimeMs) -> {
             for (int freqIndex = 0; freqIndex < cpuFreqTimeMs.length; ++freqIndex) {
                 if (cpuFreqTimeMs[freqIndex] != 0) {
@@ -857,11 +1040,11 @@
                 tagId,
                 metadata,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullCpuActiveTime(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullCpuActiveTime(int atomTag, List<StatsEvent> pulledData) {
+    int pullCpuActiveTime(int atomTag, List<StatsEvent> pulledData) {
         mCpuUidActiveTimeReader.readAbsolute((uid, cpuActiveTimesMs) -> {
             StatsEvent e = StatsEvent.newBuilder()
                     .setAtomId(atomTag)
@@ -884,11 +1067,11 @@
                 tagId,
                 metadata,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullCpuClusterTime(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullCpuClusterTime(int atomTag, List<StatsEvent> pulledData) {
+    int pullCpuClusterTime(int atomTag, List<StatsEvent> pulledData) {
         mCpuUidClusterTimeReader.readAbsolute((uid, cpuClusterTimesMs) -> {
             for (int i = 0; i < cpuClusterTimesMs.length; i++) {
                 StatsEvent e = StatsEvent.newBuilder()
@@ -908,15 +1091,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullWifiActivityInfo(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private WifiManager mWifiManager;
-    private TelephonyManager mTelephony;
-
-    private int pullWifiActivityInfo(int atomTag, List<StatsEvent> pulledData) {
+    int pullWifiActivityInfo(int atomTag, List<StatsEvent> pulledData) {
         long token = Binder.clearCallingIdentity();
         try {
             SynchronousResultReceiver wifiReceiver = new SynchronousResultReceiver("wifi");
@@ -963,12 +1143,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullModemActivityInfo(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullModemActivityInfo(int atomTag, List<StatsEvent> pulledData) {
+    int pullModemActivityInfo(int atomTag, List<StatsEvent> pulledData) {
         long token = Binder.clearCallingIdentity();
         try {
             SynchronousResultReceiver modemReceiver = new SynchronousResultReceiver("telephony");
@@ -1002,11 +1182,11 @@
                 tagId,
                 /* metadata */ null,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullBluetoothActivityInfo(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullBluetoothActivityInfo(int atomTag, List<StatsEvent> pulledData) {
+    int pullBluetoothActivityInfo(int atomTag, List<StatsEvent> pulledData) {
         BluetoothActivityEnergyInfo info = fetchBluetoothData();
         if (info == null) {
             return StatsManager.PULL_SKIP;
@@ -1024,23 +1204,21 @@
         return StatsManager.PULL_SUCCESS;
     }
 
-    private static final long NS_PER_SEC = 1000000000;
-
     private void registerSystemElapsedRealtime() {
         int tagId = StatsLog.SYSTEM_ELAPSED_REALTIME;
-        PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
                 .setCoolDownNs(NS_PER_SEC)
                 .setTimeoutNs(NS_PER_SEC / 2)
                 .build();
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 metadata,
-                (atomTag, data) -> pullSystemElapsedRealtime(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullSystemElapsedRealtime(int atomTag, List<StatsEvent> pulledData) {
+    int pullSystemElapsedRealtime(int atomTag, List<StatsEvent> pulledData) {
         StatsEvent e = StatsEvent.newBuilder()
                 .setAtomId(atomTag)
                 .writeLong(SystemClock.elapsedRealtime())
@@ -1055,11 +1233,11 @@
                 tagId,
                 null, // use default PullAtomMetadata values
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullSystemUptime(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullSystemUptime(int atomTag, List<StatsEvent> pulledData) {
+    int pullSystemUptime(int atomTag, List<StatsEvent> pulledData) {
         StatsEvent e = StatsEvent.newBuilder()
                 .setAtomId(atomTag)
                 .writeLong(SystemClock.elapsedRealtime())
@@ -1068,60 +1246,20 @@
         return StatsManager.PULL_SUCCESS;
     }
 
-    private void registerRemainingBatteryCapacity() {
-        // No op.
-    }
-
-    private void pullRemainingBatteryCapacity() {
-        // No op.
-    }
-
-    private void registerFullBatteryCapacity() {
-        // No op.
-    }
-
-    private void pullFullBatteryCapacity() {
-        // No op.
-    }
-
-    private void registerBatteryVoltage() {
-        // No op.
-    }
-
-    private void pullBatteryVoltage() {
-        // No op.
-    }
-
-    private void registerBatteryLevel() {
-        // No op.
-    }
-
-    private void pullBatteryLevel() {
-        // No op.
-    }
-
-    private void registerBatteryCycleCount() {
-        // No op.
-    }
-
-    private void pullBatteryCycleCount() {
-        // No op.
-    }
-
     private void registerProcessMemoryState() {
         int tagId = StatsLog.PROCESS_MEMORY_STATE;
-        PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
                 .setAdditiveFields(new int[] {4, 5, 6, 7, 8})
                 .build();
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 metadata,
-                (atomTag, data) -> pullProcessMemoryState(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullProcessMemoryState(int atomTag, List<StatsEvent> pulledData) {
+    int pullProcessMemoryState(int atomTag, List<StatsEvent> pulledData) {
         List<ProcessMemoryState> processMemoryStates =
                 LocalServices.getService(ActivityManagerInternal.class)
                         .getMemoryStateForProcesses();
@@ -1150,45 +1288,6 @@
         return StatsManager.PULL_SUCCESS;
     }
 
-    /**
-     * Which native processes to snapshot memory for.
-     *
-     * <p>Processes are matched by their cmdline in procfs. Example: cat /proc/pid/cmdline returns
-     * /system/bin/statsd for the stats daemon.
-     */
-    private static final Set<String> MEMORY_INTERESTING_NATIVE_PROCESSES = Sets.newHashSet(
-            "/system/bin/statsd",  // Stats daemon.
-            "/system/bin/surfaceflinger",
-            "/system/bin/apexd",  // APEX daemon.
-            "/system/bin/audioserver",
-            "/system/bin/cameraserver",
-            "/system/bin/drmserver",
-            "/system/bin/healthd",
-            "/system/bin/incidentd",
-            "/system/bin/installd",
-            "/system/bin/lmkd",  // Low memory killer daemon.
-            "/system/bin/logd",
-            "media.codec",
-            "media.extractor",
-            "media.metrics",
-            "/system/bin/mediadrmserver",
-            "/system/bin/mediaserver",
-            "/system/bin/performanced",
-            "/system/bin/tombstoned",
-            "/system/bin/traced",  // Perfetto.
-            "/system/bin/traced_probes",  // Perfetto.
-            "webview_zygote",
-            "zygote",
-            "zygote64");
-
-    /**
-     * Lowest available uid for apps.
-     *
-     * <p>Used to quickly discard memory snapshots of the zygote forks from native process
-     * measurements.
-     */
-    private static final int MIN_APP_UID = 10_000;
-
     private static boolean isAppUid(int uid) {
         return uid >= MIN_APP_UID;
     }
@@ -1198,12 +1297,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullProcessMemoryHighWaterMark(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullProcessMemoryHighWaterMark(int atomTag, List<StatsEvent> pulledData) {
+    int pullProcessMemoryHighWaterMark(int atomTag, List<StatsEvent> pulledData) {
         List<ProcessMemoryState> managedProcessList =
                 LocalServices.getService(ActivityManagerInternal.class)
                         .getMemoryStateForProcesses();
@@ -1222,30 +1321,25 @@
                     .build();
             pulledData.add(e);
         }
-        forEachPid((pid, cmdLine) -> {
-            if (!MEMORY_INTERESTING_NATIVE_PROCESSES.contains(cmdLine)) {
-                return;
-            }
-            final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(pid);
-            if (snapshot == null) {
-                return;
-            }
-            // Sometimes we get here a process that is not included in the whitelist. It comes
-            // from forking the zygote for an app. We can ignore that sample because this process
-            // is collected by ProcessMemoryState.
-            if (isAppUid(snapshot.uid)) {
-                return;
+        // Complement the data with native system processes
+        SparseArray<String> processCmdlines = getProcessCmdlines();
+        managedProcessList.forEach(managedProcess -> processCmdlines.delete(managedProcess.pid));
+        int size = processCmdlines.size();
+        for (int i = 0; i < size; ++i) {
+            final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(processCmdlines.keyAt(i));
+            if (snapshot == null || isAppUid(snapshot.uid)) {
+                continue;
             }
             StatsEvent e = StatsEvent.newBuilder()
                     .setAtomId(atomTag)
                     .writeInt(snapshot.uid)
-                    .writeString(cmdLine)
+                    .writeString(processCmdlines.valueAt(i))
                     // RSS high-water mark in bytes.
                     .writeLong(snapshot.rssHighWaterMarkInKilobytes * 1024L)
                     .writeInt(snapshot.rssHighWaterMarkInKilobytes)
                     .build();
             pulledData.add(e);
-        });
+        }
         // Invoke rss_hwm_reset binary to reset RSS HWM counters for all processes.
         SystemProperties.set("sys.rss_hwm_reset.on", "1");
         return StatsManager.PULL_SUCCESS;
@@ -1256,12 +1350,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullProcessMemorySnapshot(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullProcessMemorySnapshot(int atomTag, List<StatsEvent> pulledData) {
+    int pullProcessMemorySnapshot(int atomTag, List<StatsEvent> pulledData) {
         List<ProcessMemoryState> managedProcessList =
                 LocalServices.getService(ActivityManagerInternal.class)
                         .getMemoryStateForProcesses();
@@ -1271,6 +1365,7 @@
                 continue;
             }
             StatsEvent e = StatsEvent.newBuilder()
+                    .setAtomId(atomTag)
                     .writeInt(managedProcess.uid)
                     .writeString(managedProcess.processName)
                     .writeInt(managedProcess.pid)
@@ -1282,24 +1377,22 @@
                     .build();
             pulledData.add(e);
         }
-        forEachPid((pid, cmdLine) -> {
-            if (!MEMORY_INTERESTING_NATIVE_PROCESSES.contains(cmdLine)) {
-                return;
-            }
+        // Complement the data with native system processes. Given these measurements can be taken
+        // in response to LMKs happening, we want to first collect the managed app stats (to
+        // maximize the probability that a heavyweight process will be sampled before it dies).
+        SparseArray<String> processCmdlines = getProcessCmdlines();
+        managedProcessList.forEach(managedProcess -> processCmdlines.delete(managedProcess.pid));
+        int size = processCmdlines.size();
+        for (int i = 0; i < size; ++i) {
+            int pid = processCmdlines.keyAt(i);
             final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(pid);
-            if (snapshot == null) {
-                return;
-            }
-            // Sometimes we get here a process that is not included in the whitelist. It comes
-            // from forking the zygote for an app. We can ignore that sample because this process
-            // is collected by ProcessMemoryState.
-            if (isAppUid(snapshot.uid)) {
-                return;
+            if (snapshot == null || isAppUid(snapshot.uid)) {
+                continue;
             }
             StatsEvent e = StatsEvent.newBuilder()
                     .setAtomId(atomTag)
                     .writeInt(snapshot.uid)
-                    .writeString(cmdLine)
+                    .writeString(processCmdlines.valueAt(i))
                     .writeInt(pid)
                     .writeInt(-1001)  // Placeholder for native processes, OOM_SCORE_ADJ_MIN - 1.
                     .writeInt(snapshot.rssInKilobytes)
@@ -1308,7 +1401,7 @@
                     .writeInt(snapshot.anonRssInKilobytes + snapshot.swapInKilobytes)
                     .build();
             pulledData.add(e);
-        });
+        }
         return StatsManager.PULL_SUCCESS;
     }
 
@@ -1317,12 +1410,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullSystemIonHeapSize(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullSystemIonHeapSize(int atomTag, List<StatsEvent> pulledData) {
+    int pullSystemIonHeapSize(int atomTag, List<StatsEvent> pulledData) {
         final long systemIonHeapSizeInBytes = readSystemIonHeapSizeFromDebugfs();
         StatsEvent e = StatsEvent.newBuilder()
                 .setAtomId(atomTag)
@@ -1338,11 +1431,11 @@
                 tagId,
                 /* PullAtomMetadata */ null,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullIonHeapSize(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullIonHeapSize(int atomTag, List<StatsEvent> pulledData) {
+    int pullIonHeapSize(int atomTag, List<StatsEvent> pulledData) {
         int ionHeapSizeInKilobytes = (int) getIonHeapsSizeKb();
         StatsEvent e = StatsEvent.newBuilder()
               .setAtomId(atomTag)
@@ -1357,12 +1450,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullProcessSystemIonHeapSize(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullProcessSystemIonHeapSize(int atomTag, List<StatsEvent> pulledData) {
+    int pullProcessSystemIonHeapSize(int atomTag, List<StatsEvent> pulledData) {
         List<IonAllocations> result = readProcessSystemIonHeapSizesFromDebugfs();
         for (IonAllocations allocations : result) {
             StatsEvent e = StatsEvent.newBuilder()
@@ -1383,12 +1476,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullTemperature(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullTemperature(int atomTag, List<StatsEvent> pulledData) {
+    int pullTemperature(int atomTag, List<StatsEvent> pulledData) {
         IThermalService thermalService = getIThermalService();
         if (thermalService == null) {
             return StatsManager.PULL_SKIP;
@@ -1421,12 +1514,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullCooldownDevice(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullCooldownDevice(int atomTag, List<StatsEvent> pulledData) {
+    int pullCooldownDevice(int atomTag, List<StatsEvent> pulledData) {
         IThermalService thermalService = getIThermalService();
         if (thermalService == null) {
             return StatsManager.PULL_SKIP;
@@ -1455,18 +1548,18 @@
 
     private void registerBinderCallsStats() {
         int tagId = StatsLog.BINDER_CALLS;
-        PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
                 .setAdditiveFields(new int[] {4, 5, 6, 8, 12})
                 .build();
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 metadata,
-                (atomTag, data) -> pullBinderCallsStats(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullBinderCallsStats(int atomTag, List<StatsEvent> pulledData) {
+    int pullBinderCallsStats(int atomTag, List<StatsEvent> pulledData) {
         BinderCallsStatsService.Internal binderStats =
                 LocalServices.getService(BinderCallsStatsService.Internal.class);
         if (binderStats == null) {
@@ -1504,12 +1597,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullBinderCallsStatsExceptions(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullBinderCallsStatsExceptions(int atomTag, List<StatsEvent> pulledData) {
+    int pullBinderCallsStatsExceptions(int atomTag, List<StatsEvent> pulledData) {
         BinderCallsStatsService.Internal binderStats =
                 LocalServices.getService(BinderCallsStatsService.Internal.class);
         if (binderStats == null) {
@@ -1533,18 +1626,18 @@
 
     private void registerLooperStats() {
         int tagId = StatsLog.LOOPER_STATS;
-        PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
                 .setAdditiveFields(new int[] {5, 6, 7, 8, 9})
                 .build();
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 metadata,
-                (atomTag, data) -> pullLooperStats(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullLooperStats(int atomTag, List<StatsEvent> pulledData) {
+    int pullLooperStats(int atomTag, List<StatsEvent> pulledData) {
         LooperStats looperStats = LocalServices.getService(LooperStats.class);
         if (looperStats == null) {
             return StatsManager.PULL_SKIP;
@@ -1581,12 +1674,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullDiskStats(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullDiskStats(int atomTag, List<StatsEvent> pulledData) {
+    int pullDiskStats(int atomTag, List<StatsEvent> pulledData) {
         // Run a quick-and-dirty performance test: write 512 bytes
         byte[] junk = new byte[512];
         for (int i = 0; i < junk.length; i++) junk[i] = (byte) i;  // Write nonzero bytes
@@ -1647,12 +1740,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullDirectoryUsage(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullDirectoryUsage(int atomTag, List<StatsEvent> pulledData) {
+    int pullDirectoryUsage(int atomTag, List<StatsEvent> pulledData) {
         StatFs statFsData = new StatFs(Environment.getDataDirectory().getAbsolutePath());
         StatFs statFsSystem = new StatFs(Environment.getRootDirectory().getAbsolutePath());
         StatFs statFsCache = new StatFs(Environment.getDownloadCacheDirectory().getAbsolutePath());
@@ -1688,12 +1781,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullAppSize(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullAppSize(int atomTag, List<StatsEvent> pulledData) {
+    int pullAppSize(int atomTag, List<StatsEvent> pulledData) {
         try {
             String jsonStr = IoUtils.readFileAsString(DiskStatsLoggingService.DUMPSYS_CACHE_PATH);
             JSONObject json = new JSONObject(jsonStr);
@@ -1732,12 +1825,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullCategorySize(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullCategorySize(int atomTag, List<StatsEvent> pulledData) {
+    int pullCategorySize(int atomTag, List<StatsEvent> pulledData) {
         try {
             String jsonStr = IoUtils.readFileAsString(DiskStatsLoggingService.DUMPSYS_CACHE_PATH);
             JSONObject json = new JSONObject(jsonStr);
@@ -1835,9 +1928,8 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullNumBiometricsEnrolled(
-                        BiometricsProtoEnums.MODALITY_FINGERPRINT, atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
@@ -1846,9 +1938,8 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullNumBiometricsEnrolled(
-                        BiometricsProtoEnums.MODALITY_FACE, atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
@@ -1900,15 +1991,13 @@
         return StatsManager.PULL_SUCCESS;
     }
 
-    private File mBaseDir = new File(SystemServiceManager.ensureSystemDir(), "stats_companion");
-
     private void registerProcStats() {
         int tagId = StatsLog.PROC_STATS;
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullProcStats(ProcessStats.REPORT_ALL, atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
@@ -1917,8 +2006,8 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullProcStats(ProcessStats.REPORT_PKG_PROC_STATS, atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
@@ -1981,25 +2070,21 @@
         return 0;
     }
 
-
-    private StoragedUidIoStatsReader mStoragedUidIoStatsReader =
-            new StoragedUidIoStatsReader();
-
     private void registerDiskIO() {
         int tagId = StatsLog.DISK_IO;
-        PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
                 .setAdditiveFields(new int[] {2, 3, 4, 5, 6, 7, 8, 9, 10, 11})
                 .setCoolDownNs(3 * NS_PER_SEC)
                 .build();
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 metadata,
-                (atomTag, data) -> pullDiskIO(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullDiskIO(int atomTag, List<StatsEvent> pulledData) {
+    int pullDiskIO(int atomTag, List<StatsEvent> pulledData) {
         mStoragedUidIoStatsReader.readAbsolute((uid, fgCharsRead, fgCharsWrite, fgBytesRead,
                 fgBytesWrite, bgCharsRead, bgCharsWrite, bgBytesRead, bgBytesWrite,
                 fgFsync, bgFsync) -> {
@@ -2028,11 +2113,11 @@
                 tagId,
                 /* PullAtomMetadata */ null,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullPowerProfile(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullPowerProfile(int atomTag, List<StatsEvent> pulledData) {
+    int pullPowerProfile(int atomTag, List<StatsEvent> pulledData) {
         PowerProfile powerProfile = new PowerProfile(mContext);
         ProtoOutputStream proto = new ProtoOutputStream();
         powerProfile.dumpDebug(proto);
@@ -2045,25 +2130,21 @@
         return StatsManager.PULL_SUCCESS;
     }
 
-    private final Object mCpuTrackerLock = new Object();
-    @GuardedBy("mCpuTrackerLock")
-    private ProcessCpuTracker mProcessCpuTracker;
-
     private void registerProcessCpuTime() {
         int tagId = StatsLog.PROCESS_CPU_TIME;
         // Min cool-down is 5 sec, in line with what ActivityManagerService uses.
-        PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
                 .setCoolDownNs(5 * NS_PER_SEC)
                 .build();
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 metadata,
-                (atomTag, data) -> pullProcessCpuTime(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullProcessCpuTime(int atomTag, List<StatsEvent> pulledData) {
+    int pullProcessCpuTime(int atomTag, List<StatsEvent> pulledData) {
         synchronized (mCpuTrackerLock) {
             if (mProcessCpuTracker == null) {
                 mProcessCpuTracker = new ProcessCpuTracker(false);
@@ -2085,24 +2166,20 @@
         return StatsManager.PULL_SUCCESS;
     }
 
-    @Nullable
-    private KernelCpuThreadReaderDiff mKernelCpuThreadReader;
-    private static final int CPU_TIME_PER_THREAD_FREQ_MAX_NUM_FREQUENCIES = 8;
-
     private void registerCpuTimePerThreadFreq() {
         int tagId = StatsLog.CPU_TIME_PER_THREAD_FREQ;
-        PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
                 .setAdditiveFields(new int[] {7, 9, 11, 13, 15, 17, 19, 21})
                 .build();
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 metadata,
-                (atomTag, data) -> pullCpuTimePerThreadFreq(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullCpuTimePerThreadFreq(int atomTag, List<StatsEvent> pulledData) {
+    int pullCpuTimePerThreadFreq(int atomTag, List<StatsEvent> pulledData) {
         if (this.mKernelCpuThreadReader == null) {
             Slog.e(TAG, "mKernelCpuThreadReader is null");
             return StatsManager.PULL_SKIP;
@@ -2159,12 +2236,6 @@
         return StatsManager.PULL_SUCCESS;
     }
 
-    // TODO: move to top of file when all migrations are complete
-    private BatteryStatsHelper mBatteryStatsHelper = null;
-    private static final int MAX_BATTERY_STATS_HELPER_FREQUENCY_MS = 1000;
-    private long mBatteryStatsHelperTimestampMs = -MAX_BATTERY_STATS_HELPER_FREQUENCY_MS;
-    private static final long MILLI_AMP_HR_TO_NANO_AMP_SECS = 1_000_000L * 3600L;
-
     private BatteryStatsHelper getBatteryStatsHelper() {
         if (mBatteryStatsHelper == null) {
             final long callingToken = Binder.clearCallingIdentity();
@@ -2196,12 +2267,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullDeviceCalculatedPowerUse(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullDeviceCalculatedPowerUse(int atomTag, List<StatsEvent> pulledData) {
+    int pullDeviceCalculatedPowerUse(int atomTag, List<StatsEvent> pulledData) {
         BatteryStatsHelper bsHelper = getBatteryStatsHelper();
         StatsEvent e = StatsEvent.newBuilder()
                 .setAtomId(atomTag)
@@ -2216,12 +2287,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullDeviceCalculatedPowerBlameUid(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullDeviceCalculatedPowerBlameUid(int atomTag, List<StatsEvent> pulledData) {
+    int pullDeviceCalculatedPowerBlameUid(int atomTag, List<StatsEvent> pulledData) {
         final List<BatterySipper> sippers = getBatteryStatsHelper().getUsageList();
         if (sippers == null) {
             return StatsManager.PULL_SKIP;
@@ -2246,12 +2317,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullDeviceCalculatedPowerBlameOther(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullDeviceCalculatedPowerBlameOther(int atomTag, List<StatsEvent> pulledData) {
+    int pullDeviceCalculatedPowerBlameOther(int atomTag, List<StatsEvent> pulledData) {
         final List<BatterySipper> sippers = getBatteryStatsHelper().getUsageList();
         if (sippers == null) {
             return StatsManager.PULL_SKIP;
@@ -2274,24 +2345,20 @@
         return StatsManager.PULL_SUCCESS;
     }
 
-    private final Object mDebugElapsedClockLock = new Object();
-    private long mDebugElapsedClockPreviousValue = 0;
-    private long mDebugElapsedClockPullCount = 0;
-
     private void registerDebugElapsedClock() {
         int tagId = StatsLog.DEBUG_ELAPSED_CLOCK;
-        PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
                 .setAdditiveFields(new int[] {1, 2, 3, 4})
                 .build();
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 metadata,
-                (atomTag, data) -> pullDebugElapsedClock(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullDebugElapsedClock(int atomTag, List<StatsEvent> pulledData) {
+    int pullDebugElapsedClock(int atomTag, List<StatsEvent> pulledData) {
         final long elapsedMillis = SystemClock.elapsedRealtime();
 
         synchronized (mDebugElapsedClockLock) {
@@ -2329,24 +2396,20 @@
         return StatsManager.PULL_SUCCESS;
     }
 
-    private final Object mDebugFailingElapsedClockLock = new Object();
-    private long mDebugFailingElapsedClockPreviousValue = 0;
-    private long mDebugFailingElapsedClockPullCount = 0;
-
     private void registerDebugFailingElapsedClock() {
         int tagId = StatsLog.DEBUG_FAILING_ELAPSED_CLOCK;
-        PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
                 .setAdditiveFields(new int[] {1, 2, 3, 4})
                 .build();
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 metadata,
-                (atomTag, data) -> pullDebugFailingElapsedClock(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullDebugFailingElapsedClock(int atomTag, List<StatsEvent> pulledData) {
+    int pullDebugFailingElapsedClock(int atomTag, List<StatsEvent> pulledData) {
         final long elapsedMillis = SystemClock.elapsedRealtime();
 
         synchronized (mDebugFailingElapsedClockLock) {
@@ -2380,11 +2443,11 @@
                 tagId,
                 null, // use default PullAtomMetadata values
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullBuildInformation(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullBuildInformation(int atomTag, List<StatsEvent> pulledData) {
+    int pullBuildInformation(int atomTag, List<StatsEvent> pulledData) {
         StatsEvent e = StatsEvent.newBuilder()
                 .setAtomId(atomTag)
                 .writeString(Build.FINGERPRINT)
@@ -2406,13 +2469,13 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullRoleHolder(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
     // Add a RoleHolder atom for each package that holds a role.
-    private int pullRoleHolder(int atomTag, List<StatsEvent> pulledData) {
+    int pullRoleHolder(int atomTag, List<StatsEvent> pulledData) {
         long callingToken = Binder.clearCallingIdentity();
         try {
             PackageManager pm = mContext.getPackageManager();
@@ -2464,12 +2527,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullDangerousPermissionState(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullDangerousPermissionState(int atomTag, List<StatsEvent> pulledData) {
+    int pullDangerousPermissionState(int atomTag, List<StatsEvent> pulledData) {
         final long token = Binder.clearCallingIdentity();
         Set<Integer> reportedUids = new HashSet<>();
         try {
@@ -2550,12 +2613,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullTimeZoneDataInfo(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullTimeZoneDataInfo(int atomTag, List<StatsEvent> pulledData) {
+    int pullTimeZoneDataInfo(int atomTag, List<StatsEvent> pulledData) {
         String tzDbVersion = "Unknown";
         try {
             tzDbVersion = android.icu.util.TimeZone.getTZDataVersion();
@@ -2577,12 +2640,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullExternalStorageInfo(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullExternalStorageInfo(int atomTag, List<StatsEvent> pulledData) {
+    int pullExternalStorageInfo(int atomTag, List<StatsEvent> pulledData) {
         if (mStorageManager == null) {
             return StatsManager.PULL_SKIP;
         }
@@ -2627,12 +2690,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullAppsOnExternalStorageInfo(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullAppsOnExternalStorageInfo(int atomTag, List<StatsEvent> pulledData) {
+    int pullAppsOnExternalStorageInfo(int atomTag, List<StatsEvent> pulledData) {
         if (mStorageManager == null) {
             return StatsManager.PULL_SKIP;
         }
@@ -2683,12 +2746,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullFaceSettings(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullFaceSettings(int atomTag, List<StatsEvent> pulledData) {
+    int pullFaceSettings(int atomTag, List<StatsEvent> pulledData) {
         final long callingToken = Binder.clearCallingIdentity();
         try {
             List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
@@ -2737,13 +2800,13 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullAppOps(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
 
     }
 
-    private int pullAppOps(int atomTag, List<StatsEvent> pulledData) {
+    int pullAppOps(int atomTag, List<StatsEvent> pulledData) {
         final long token = Binder.clearCallingIdentity();
         try {
             AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
@@ -2848,12 +2911,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullNotificationRemoteViews(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullNotificationRemoteViews(int atomTag, List<StatsEvent> pulledData) {
+    int pullNotificationRemoteViews(int atomTag, List<StatsEvent> pulledData) {
         INotificationManager notificationManagerService = getINotificationManagerService();
         if (notificationManagerService == null) {
             return StatsManager.PULL_SKIP;
@@ -2892,8 +2955,33 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullDangerousPermissionState(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
+
+
+    // Thermal event received from vendor thermal management subsystem
+    private static final class ThermalEventListener extends IThermalEventListener.Stub {
+        @Override
+        public void notifyThrottling(Temperature temp) {
+            StatsLog.write(StatsLog.THERMAL_THROTTLING_SEVERITY_STATE_CHANGED, temp.getType(),
+                    temp.getName(), (int) (temp.getValue() * 10), temp.getStatus());
+        }
+    }
+
+    private static final class ConnectivityStatsCallback extends
+            ConnectivityManager.NetworkCallback {
+        @Override
+        public void onAvailable(Network network) {
+            StatsLog.write(StatsLog.CONNECTIVITY_STATE_CHANGED, network.netId,
+                    StatsLog.CONNECTIVITY_STATE_CHANGED__STATE__CONNECTED);
+        }
+
+        @Override
+        public void onLost(Network network) {
+            StatsLog.write(StatsLog.CONNECTIVITY_STATE_CHANGED, network.netId,
+                    StatsLog.CONNECTIVITY_STATE_CHANGED__STATE__DISCONNECTED);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index 95ffd8f..d88dccb 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -16,7 +16,10 @@
 
 package com.android.server.statusbar;
 
+import android.annotation.Nullable;
+import android.app.ITransientNotificationCallback;
 import android.os.Bundle;
+import android.os.IBinder;
 import android.view.InsetsState.InternalInsetsType;
 import android.view.WindowInsetsController.Appearance;
 
@@ -123,4 +126,15 @@
 
     /** @see com.android.internal.statusbar.IStatusBar#abortTransient */
     void abortTransient(int displayId, @InternalInsetsType int[] types);
+
+    /**
+     * @see com.android.internal.statusbar.IStatusBar#showToast(String, IBinder, CharSequence,
+     * IBinder, int, ITransientNotificationCallback)
+     */
+    void showToast(String packageName, IBinder token, CharSequence text,
+            IBinder windowToken, int duration,
+            @Nullable ITransientNotificationCallback textCallback);
+
+    /** @see com.android.internal.statusbar.IStatusBar#hideToast(String, IBinder)  */
+    void hideToast(String packageName, IBinder token);
 }
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 870c81f..9a30f1d 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -21,6 +21,7 @@
 
 import android.annotation.Nullable;
 import android.app.ActivityThread;
+import android.app.ITransientNotificationCallback;
 import android.app.Notification;
 import android.app.StatusBarManager;
 import android.content.ComponentName;
@@ -78,7 +79,6 @@
 
     private final Context mContext;
 
-    private final WindowManagerService mWindowManager;
     private Handler mHandler = new Handler();
     private NotificationDelegate mNotificationDelegate;
     private volatile IStatusBar mBar;
@@ -92,6 +92,7 @@
     private final Object mLock = new Object();
     private final DeathRecipient mDeathRecipient = new DeathRecipient();
     private int mCurrentUserId;
+    private boolean mTracingEnabled;
 
     private SparseArray<UiState> mDisplayUiState = new SparseArray<>();
 
@@ -175,11 +176,10 @@
     }
 
     /**
-     * Construct the service, add the status bar view to the window manager
+     * Construct the service
      */
-    public StatusBarManagerService(Context context, WindowManagerService windowManager) {
+    public StatusBarManagerService(Context context) {
         mContext = context;
-        mWindowManager = windowManager;
 
         LocalServices.addService(StatusBarManagerInternal.class, mInternalService);
         LocalServices.addService(GlobalActionsProvider.class, mGlobalActionsProvider);
@@ -500,6 +500,26 @@
                 } catch (RemoteException ex) { }
             }
         }
+
+        @Override
+        public void showToast(String packageName, IBinder token, CharSequence text,
+                IBinder windowToken, int duration,
+                @Nullable ITransientNotificationCallback callback) {
+            if (mBar != null) {
+                try {
+                    mBar.showToast(packageName, token, text, windowToken, duration, callback);
+                } catch (RemoteException ex) { }
+            }
+        }
+
+        @Override
+        public void hideToast(String packageName, IBinder token) {
+            if (mBar != null) {
+                try {
+                    mBar.hideToast(packageName, token);
+                } catch (RemoteException ex) { }
+            }
+        }
     };
 
     private final GlobalActionsProvider mGlobalActionsProvider = new GlobalActionsProvider() {
@@ -699,6 +719,31 @@
         }
     }
 
+    @Override
+    public void startTracing() {
+        if (mBar != null) {
+            try {
+                mBar.startTracing();
+                mTracingEnabled = true;
+            } catch (RemoteException ex) {}
+        }
+    }
+
+    @Override
+    public void stopTracing() {
+        if (mBar != null) {
+            try {
+                mTracingEnabled = false;
+                mBar.stopTracing();
+            } catch (RemoteException ex) {}
+        }
+    }
+
+    @Override
+    public boolean isTracing() {
+        return mTracingEnabled;
+    }
+
     // TODO(b/117478341): make it aware of multi-display if needed.
     @Override
     public void disable(int what, IBinder token, String pkg) {
@@ -1343,6 +1388,17 @@
     }
 
     @Override
+    public void onBubbleNotificationSuppressionChanged(String key, boolean isNotifSuppressed) {
+        enforceStatusBarService();
+        long identity = Binder.clearCallingIdentity();
+        try {
+            mNotificationDelegate.onBubbleNotificationSuppressionChanged(key, isNotifSuppressed);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
     public void grantInlineReplyUriPermission(String key, Uri uri, UserHandle user,
             String packageName) {
         enforceStatusBarService();
diff --git a/services/core/java/com/android/server/statusbar/StatusBarShellCommand.java b/services/core/java/com/android/server/statusbar/StatusBarShellCommand.java
index d7f86cd..a79c19f 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarShellCommand.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarShellCommand.java
@@ -72,6 +72,8 @@
                     return runDisableForSetup();
                 case "send-disable-flag":
                     return runSendDisableFlag();
+                case "tracing":
+                    return runTracing();
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -185,6 +187,18 @@
         return 0;
     }
 
+    private int runTracing() {
+        switch (getNextArg()) {
+            case "start":
+                mInterface.startTracing();
+                break;
+            case "stop":
+                mInterface.stopTracing();
+                break;
+        }
+        return 0;
+    }
+
     @Override
     public void onHelp() {
         final PrintWriter pw = getOutPrintWriter();
@@ -233,6 +247,9 @@
         pw.println("        clock               - disable clock appearing in status bar");
         pw.println("        notification-icons  - disable notification icons from status bar");
         pw.println("");
+        pw.println("  tracing (start | stop)");
+        pw.println("    Start or stop SystemUI tracing");
+        pw.println("");
     }
 
     /**
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index e8704ab..4f010d5 100755
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -1681,7 +1681,8 @@
         }
 
         @Override
-        public void startRecording(IBinder sessionToken, @Nullable Uri programUri, int userId) {
+        public void startRecording(IBinder sessionToken, @Nullable Uri programUri,
+                @Nullable Bundle params, int userId) {
             final int callingUid = Binder.getCallingUid();
             final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
                     userId, "startRecording");
@@ -1690,7 +1691,7 @@
                 synchronized (mLock) {
                     try {
                         getSessionLocked(sessionToken, callingUid, resolvedUserId).startRecording(
-                                programUri);
+                                programUri, params);
                     } catch (RemoteException | SessionNotFoundException e) {
                         Slog.e(TAG, "error in startRecording", e);
                     }
diff --git a/services/core/java/com/android/server/utils/TraceBuffer.java b/services/core/java/com/android/server/utils/TraceBuffer.java
deleted file mode 100644
index 0567960..0000000
--- a/services/core/java/com/android/server/utils/TraceBuffer.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.utils;
-
-import android.util.proto.ProtoOutputStream;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayDeque;
-import java.util.Arrays;
-import java.util.Queue;
-
-/**
- * Buffer used for tracing and logging.
- */
-public class TraceBuffer {
-    private final Object mBufferLock = new Object();
-
-    private final Queue<ProtoOutputStream> mBuffer = new ArrayDeque<>();
-    private int mBufferUsedSize;
-    private int mBufferCapacity;
-
-    public TraceBuffer(int bufferCapacity) {
-        mBufferCapacity = bufferCapacity;
-        resetBuffer();
-    }
-
-    public int getAvailableSpace() {
-        return mBufferCapacity - mBufferUsedSize;
-    }
-
-    /**
-     * Returns buffer size.
-     */
-    public int size() {
-        return mBuffer.size();
-    }
-
-    public void setCapacity(int capacity) {
-        mBufferCapacity = capacity;
-    }
-
-    /**
-     * Inserts the specified element into this buffer.
-     *
-     * @param proto the element to add
-     * @throws IllegalStateException if the element cannot be added because it is larger
-     *                               than the buffer size.
-     */
-    public void add(ProtoOutputStream proto) {
-        int protoLength = proto.getRawSize();
-        if (protoLength > mBufferCapacity) {
-            throw new IllegalStateException("Trace object too large for the buffer. Buffer size:"
-                    + mBufferCapacity + " Object size: " + protoLength);
-        }
-        synchronized (mBufferLock) {
-            discardOldest(protoLength);
-            mBuffer.add(proto);
-            mBufferUsedSize += protoLength;
-            mBufferLock.notify();
-        }
-    }
-
-    boolean contains(byte[] other) {
-        return mBuffer.stream()
-                .anyMatch(p -> Arrays.equals(p.getBytes(), other));
-    }
-
-    /**
-     * Writes the trace buffer to disk inside the encapsulatingProto..
-     */
-    public void writeTraceToFile(File traceFile, ProtoOutputStream encapsulatingProto)
-            throws IOException {
-        synchronized (mBufferLock) {
-            traceFile.delete();
-            try (OutputStream os = new FileOutputStream(traceFile)) {
-                traceFile.setReadable(true /* readable */, false /* ownerOnly */);
-                os.write(encapsulatingProto.getBytes());
-                for (ProtoOutputStream protoOutputStream : mBuffer) {
-                    encapsulatingProto = protoOutputStream;
-                    byte[] protoBytes = encapsulatingProto.getBytes();
-                    os.write(protoBytes);
-                }
-                os.flush();
-            }
-        }
-    }
-
-    /**
-     * Checks if the element can be added to the buffer. The element is already certain to be
-     * smaller than the overall buffer size.
-     *
-     * @param protoLength byte array representation of the Proto object to add
-     */
-    private void discardOldest(int protoLength) {
-        long availableSpace = getAvailableSpace();
-
-        while (availableSpace < protoLength) {
-
-            ProtoOutputStream item = mBuffer.poll();
-            if (item == null) {
-                throw new IllegalStateException("No element to discard from buffer");
-            }
-            mBufferUsedSize -= item.getRawSize();
-            availableSpace = getAvailableSpace();
-        }
-    }
-
-    /**
-     * Removes all elements form the buffer
-     */
-    public void resetBuffer() {
-        synchronized (mBufferLock) {
-            mBuffer.clear();
-            mBufferUsedSize = 0;
-        }
-    }
-
-    @VisibleForTesting
-    int getBufferSize() {
-        return mBufferUsedSize;
-    }
-
-    /**
-     * Returns the buffer status in human-readable form.
-     */
-    public String getStatus() {
-        synchronized (mBufferLock) {
-            return "Buffer size: "
-                    + mBufferCapacity
-                    + " bytes"
-                    + "\n"
-                    + "Buffer usage: "
-                    + mBufferUsedSize
-                    + " bytes"
-                    + "\n"
-                    + "Elements in the buffer: "
-                    + mBuffer.size();
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 36e9775..2115f7c 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -3433,6 +3433,9 @@
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
+        pw.print("mDefaultWallpaperComponent="); pw.println(mDefaultWallpaperComponent);
+        pw.print("mImageWallpaper="); pw.println(mImageWallpaper);
+
         synchronized (mLock) {
             pw.println("System wallpaper state:");
             for (int i = 0; i < mWallpaperMap.size(); i++) {
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateService.java b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
index 0abe68f..8130546 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateService.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
@@ -22,6 +22,7 @@
 import android.content.IntentFilter;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.os.Binder;
 import android.os.PatternMatcher;
 import android.os.Process;
@@ -34,6 +35,7 @@
 import android.webkit.WebViewProviderResponse;
 
 import com.android.internal.util.DumpUtils;
+import com.android.server.LocalServices;
 import com.android.server.SystemService;
 
 import java.io.FileDescriptor;
@@ -191,7 +193,26 @@
                 throw new IllegalStateException("Cannot create a WebView from the SystemServer");
             }
 
-            return WebViewUpdateService.this.mImpl.waitForAndGetProvider();
+            final WebViewProviderResponse webViewProviderResponse =
+                    WebViewUpdateService.this.mImpl.waitForAndGetProvider();
+            if (webViewProviderResponse.packageInfo != null) {
+                grantVisibilityToCaller(
+                        webViewProviderResponse.packageInfo.packageName, Binder.getCallingUid());
+            }
+            return webViewProviderResponse;
+        }
+
+        /**
+         * Grants app visibility of the webViewPackageName to the currently bound caller.
+         * @param webViewPackageName
+         */
+        private void grantVisibilityToCaller(String webViewPackageName, int callingUid) {
+            final PackageManagerInternal pmInternal = LocalServices.getService(
+                    PackageManagerInternal.class);
+            final int webviewUid = pmInternal.getPackageUidInternal(
+                    webViewPackageName, 0, UserHandle.getUserId(callingUid));
+            pmInternal.grantImplicitAccess(UserHandle.getUserId(callingUid), null, webviewUid,
+                    UserHandle.getAppId(callingUid));
         }
 
         /**
@@ -231,13 +252,18 @@
 
         @Override // Binder call
         public String getCurrentWebViewPackageName() {
-            PackageInfo pi = WebViewUpdateService.this.mImpl.getCurrentWebViewPackage();
+            PackageInfo pi = getCurrentWebViewPackage();
             return pi == null ? null : pi.packageName;
         }
 
         @Override // Binder call
         public PackageInfo getCurrentWebViewPackage() {
-            return WebViewUpdateService.this.mImpl.getCurrentWebViewPackage();
+            final PackageInfo currentWebViewPackage =
+                    WebViewUpdateService.this.mImpl.getCurrentWebViewPackage();
+            if (currentWebViewPackage != null) {
+                grantVisibilityToCaller(currentWebViewPackage.packageName, Binder.getCallingUid());
+            }
+            return currentWebViewPackage;
         }
 
         @Override // Binder call
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index d1c8448..f8f286a 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -94,7 +94,6 @@
 import static android.os.Process.SYSTEM_UID;
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.view.Display.COLOR_MODE_DEFAULT;
-import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.Surface.ROTATION_270;
 import static android.view.Surface.ROTATION_90;
@@ -113,16 +112,36 @@
 import static android.view.WindowManager.TRANSIT_UNSET;
 import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
 
-import static com.android.server.am.ActivityRecordProto.APP_WINDOW_TOKEN;
-import static com.android.server.am.ActivityRecordProto.FRONT_OF_TASK;
-import static com.android.server.am.ActivityRecordProto.IDENTIFIER;
-import static com.android.server.am.ActivityRecordProto.PROC_ID;
-import static com.android.server.am.ActivityRecordProto.STATE;
-import static com.android.server.am.ActivityRecordProto.TRANSLUCENT;
-import static com.android.server.am.ActivityRecordProto.VISIBLE;
-import static com.android.server.am.ActivityRecordProto.VISIBLE_REQUESTED;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static com.android.server.wm.ActivityRecordProto.ALL_DRAWN;
+import static com.android.server.wm.ActivityRecordProto.APP_STOPPED;
+import static com.android.server.wm.ActivityRecordProto.CLIENT_VISIBLE;
+import static com.android.server.wm.ActivityRecordProto.DEFER_HIDING_CLIENT;
+import static com.android.server.wm.ActivityRecordProto.FILLS_PARENT;
+import static com.android.server.wm.ActivityRecordProto.FRONT_OF_TASK;
+import static com.android.server.wm.ActivityRecordProto.FROZEN_BOUNDS;
+import static com.android.server.wm.ActivityRecordProto.IDENTIFIER;
+import static com.android.server.wm.ActivityRecordProto.IS_ANIMATING;
+import static com.android.server.wm.ActivityRecordProto.IS_WAITING_FOR_TRANSITION_START;
+import static com.android.server.wm.ActivityRecordProto.LAST_ALL_DRAWN;
+import static com.android.server.wm.ActivityRecordProto.LAST_SURFACE_SHOWING;
+import static com.android.server.wm.ActivityRecordProto.NAME;
+import static com.android.server.wm.ActivityRecordProto.NUM_DRAWN_WINDOWS;
+import static com.android.server.wm.ActivityRecordProto.NUM_INTERESTING_WINDOWS;
+import static com.android.server.wm.ActivityRecordProto.PROC_ID;
+import static com.android.server.wm.ActivityRecordProto.REPORTED_DRAWN;
+import static com.android.server.wm.ActivityRecordProto.REPORTED_VISIBLE;
+import static com.android.server.wm.ActivityRecordProto.STARTING_DISPLAYED;
+import static com.android.server.wm.ActivityRecordProto.STARTING_MOVED;
+import static com.android.server.wm.ActivityRecordProto.STARTING_WINDOW;
+import static com.android.server.wm.ActivityRecordProto.STATE;
+import static com.android.server.wm.ActivityRecordProto.THUMBNAIL;
+import static com.android.server.wm.ActivityRecordProto.TRANSLUCENT;
+import static com.android.server.wm.ActivityRecordProto.VISIBLE;
+import static com.android.server.wm.ActivityRecordProto.VISIBLE_REQUESTED;
+import static com.android.server.wm.ActivityRecordProto.VISIBLE_SET_FROM_TRANSFERRED_STARTING_WINDOW;
+import static com.android.server.wm.ActivityRecordProto.WINDOW_TOKEN;
 import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED;
 import static com.android.server.wm.ActivityStack.ActivityState.DESTROYING;
 import static com.android.server.wm.ActivityStack.ActivityState.FINISHING;
@@ -168,27 +187,6 @@
 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
 import static com.android.server.wm.ActivityTaskManagerService.getInputDispatchingTimeoutLocked;
-import static com.android.server.wm.AppWindowTokenProto.ALL_DRAWN;
-import static com.android.server.wm.AppWindowTokenProto.APP_STOPPED;
-import static com.android.server.wm.AppWindowTokenProto.CLIENT_VISIBLE;
-import static com.android.server.wm.AppWindowTokenProto.DEFER_HIDING_CLIENT;
-import static com.android.server.wm.AppWindowTokenProto.FILLS_PARENT;
-import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS;
-import static com.android.server.wm.AppWindowTokenProto.IS_ANIMATING;
-import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
-import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN;
-import static com.android.server.wm.AppWindowTokenProto.LAST_SURFACE_SHOWING;
-import static com.android.server.wm.AppWindowTokenProto.NAME;
-import static com.android.server.wm.AppWindowTokenProto.NUM_DRAWN_WINDOWS;
-import static com.android.server.wm.AppWindowTokenProto.NUM_INTERESTING_WINDOWS;
-import static com.android.server.wm.AppWindowTokenProto.REPORTED_DRAWN;
-import static com.android.server.wm.AppWindowTokenProto.REPORTED_VISIBLE;
-import static com.android.server.wm.AppWindowTokenProto.STARTING_DISPLAYED;
-import static com.android.server.wm.AppWindowTokenProto.STARTING_MOVED;
-import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
-import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
-import static com.android.server.wm.AppWindowTokenProto.VISIBLE_SET_FROM_TRANSFERRED_STARTING_WINDOW;
-import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN;
 import static com.android.server.wm.IdentifierProto.HASH_CODE;
 import static com.android.server.wm.IdentifierProto.TITLE;
 import static com.android.server.wm.IdentifierProto.USER_ID;
@@ -495,7 +493,7 @@
                                         // process that it is hidden.
     private boolean mLastDeferHidingClient; // If true we will defer setting mClientVisible to false
                                            // and reporting to the client that it is hidden.
-    boolean sleeping;       // have we told the activity to sleep?
+    private boolean mSetToSleep; // have we told the activity to sleep?
     boolean nowVisible;     // is this activity's window visible?
     boolean mDrawn;          // is this activity's window drawn?
     boolean mClientVisibilityDeferred;// was the visibility change message to client deferred?
@@ -613,6 +611,7 @@
 
     private boolean mLastContainsShowWhenLockedWindow;
     private boolean mLastContainsDismissKeyguardWindow;
+    private boolean mLastContainsTurnScreenOnWindow;
 
     /**
      * A flag to determine if this AR is in the process of closing or entering PIP. This is needed
@@ -895,7 +894,7 @@
                 pw.print(" finishing="); pw.println(finishing);
         pw.print(prefix); pw.print("keysPaused="); pw.print(keysPaused);
                 pw.print(" inHistory="); pw.print(inHistory);
-                pw.print(" sleeping="); pw.print(sleeping);
+        pw.print(" setToSleep="); pw.print(mSetToSleep);
                 pw.print(" idle="); pw.print(idle);
                 pw.print(" mStartingWindowState=");
                 pw.println(startingWindowStateToString(mStartingWindowState));
@@ -1627,7 +1626,12 @@
         requestedVrComponent = (aInfo.requestedVrComponent == null) ?
                 null : ComponentName.unflattenFromString(aInfo.requestedVrComponent);
 
-        lockTaskLaunchMode = getLockTaskLaunchMode(aInfo, options);
+        lockTaskLaunchMode = aInfo.lockTaskLaunchMode;
+        if (info.applicationInfo.isPrivilegedApp()
+                && (lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_ALWAYS
+                || lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_NEVER)) {
+            lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_DEFAULT;
+        }
 
         if (options != null) {
             pendingOptions = options;
@@ -1635,25 +1639,13 @@
             if (usageReport != null) {
                 appTimeTracker = new AppTimeTracker(usageReport);
             }
-            // Gets launch display id from options. It returns INVALID_DISPLAY if not set.
-            mHandoverLaunchDisplayId = options.getLaunchDisplayId();
-        }
-    }
-
-    static int getLockTaskLaunchMode(ActivityInfo aInfo, @Nullable ActivityOptions options) {
-        int lockTaskLaunchMode = aInfo.lockTaskLaunchMode;
-        if (aInfo.applicationInfo.isPrivilegedApp()
-                && (lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_ALWAYS
-                || lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_NEVER)) {
-            lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_DEFAULT;
-        }
-        if (options != null) {
-            final boolean useLockTask = options.getLockTaskMode();
+            final boolean useLockTask = pendingOptions.getLockTaskMode();
             if (useLockTask && lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_DEFAULT) {
                 lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
             }
+            // Gets launch display id from options. It returns INVALID_DISPLAY if not set.
+            mHandoverLaunchDisplayId = options.getLaunchDisplayId();
         }
-        return lockTaskLaunchMode;
     }
 
     @Override
@@ -2661,7 +2653,6 @@
 
         // Make sure the record is cleaned out of other places.
         mStackSupervisor.mStoppingActivities.remove(this);
-        mStackSupervisor.mGoingToSleepActivities.remove(this);
 
         final ActivityStack stack = getRootTask();
         final DisplayContent display = getDisplay();
@@ -3364,6 +3355,7 @@
         }
         mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
         mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
+        mLastContainsTurnScreenOnWindow = containsTurnScreenOnWindow();
     }
 
     boolean containsDismissKeyguardWindow() {
@@ -4362,6 +4354,15 @@
                 || state5 == mState;
     }
 
+    /**
+     * Returns {@code true} if the Activity is in one of the specified states.
+     */
+    boolean isState(ActivityState state1, ActivityState state2, ActivityState state3,
+            ActivityState state4, ActivityState state5, ActivityState state6) {
+        return state1 == mState || state2 == mState || state3 == mState || state4 == mState
+                || state5 == mState || state6 == mState;
+    }
+
     void destroySurfaces() {
         destroySurfaces(false /*cleanupOnResume*/);
     }
@@ -4451,20 +4452,26 @@
             return false;
         }
 
-        // Whether the activity is on the sleeping display.
-        // TODO(b/129750406): This should be applied for the default display, too.
-        final boolean isDisplaySleeping = getDisplay().isSleeping()
-                && getDisplayId() != DEFAULT_DISPLAY;
-        // Whether this activity is the top activity of this stack.
-        final boolean isTop = this == stack.getTopNonFinishingActivity();
-        // Exclude the case where this is the top activity in a pinned stack.
-        final boolean isTopNotPinnedStack = stack.isAttached()
-                && stack.getDisplay().isTopNotPinnedStack(stack);
+        // Check if the activity is on a sleeping display, and if it can turn it ON.
+        if (getDisplay().isSleeping()) {
+            final boolean canTurnScreenOn = !mSetToSleep || canTurnScreenOn()
+                    || canShowWhenLocked() || containsDismissKeyguardWindow();
+            if (!canTurnScreenOn) {
+                return false;
+            }
+        }
+
         // Now check whether it's really visible depending on Keyguard state, and update
         // {@link ActivityStack} internal states.
+        // Inform the method if this activity is the top activity of this stack, but exclude the
+        // case where this is the top activity in a pinned stack.
+        final boolean isTop = this == stack.getTopNonFinishingActivity();
+        final boolean isTopNotPinnedStack = stack.isAttached()
+                && stack.getDisplay().isTopNotPinnedStack(stack);
         final boolean visibleIgnoringDisplayStatus = stack.checkKeyguardVisibility(this,
                 visibleIgnoringKeyguard, isTop && isTopNotPinnedStack);
-        return visibleIgnoringDisplayStatus && !isDisplaySleeping;
+
+        return visibleIgnoringDisplayStatus;
     }
 
     boolean shouldBeVisible() {
@@ -4496,7 +4503,7 @@
                 stack.mUndrawnActivitiesBelowTopTranslucent.add(this);
             }
             setVisibility(true);
-            sleeping = false;
+            mSetToSleep = false;
             app.postPendingUiCleanMsg(true);
             if (reportToClient) {
                 mClientVisibilityDeferred = false;
@@ -4506,7 +4513,6 @@
             }
             // The activity may be waiting for stop, but that is no longer appropriate for it.
             mStackSupervisor.mStoppingActivities.remove(this);
-            mStackSupervisor.mGoingToSleepActivities.remove(this);
         } catch (Exception e) {
             // Just skip on any failure; we'll make it visible when it next restarts.
             Slog.w(TAG, "Exception thrown making visible: " + intent.getComponent(), e);
@@ -5452,25 +5458,8 @@
         return mVisibleRequested || nowVisible || mState == PAUSING || mState == RESUMED;
     }
 
-    void setSleeping(boolean _sleeping) {
-        setSleeping(_sleeping, false);
-    }
-
-    void setSleeping(boolean _sleeping, boolean force) {
-        if (!force && sleeping == _sleeping) {
-            return;
-        }
-        if (attachedToProcess()) {
-            try {
-                app.getThread().scheduleSleeping(appToken, _sleeping);
-                if (_sleeping && !mStackSupervisor.mGoingToSleepActivities.contains(this)) {
-                    mStackSupervisor.mGoingToSleepActivities.add(this);
-                }
-                sleeping = _sleeping;
-            } catch (RemoteException e) {
-                Slog.w(TAG, "Exception thrown when sleeping: " + intent.getComponent(), e);
-            }
-        }
+    void setSleeping(boolean sleeping) {
+        mSetToSleep = sleeping;
     }
 
     static int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
@@ -7413,7 +7402,22 @@
     }
 
     boolean getTurnScreenOnFlag() {
-        return mTurnScreenOn;
+        return mTurnScreenOn || containsTurnScreenOnWindow();
+    }
+
+    private boolean containsTurnScreenOnWindow() {
+        // When we are relaunching, it is possible for us to be unfrozen before our previous
+        // windows have been added back. Using the cached value ensures that our previous
+        // showWhenLocked preference is honored until relaunching is complete.
+        if (isRelaunching()) {
+            return mLastContainsTurnScreenOnWindow;
+        }
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            if ((mChildren.get(i).mAttrs.flags & LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
+                return true;
+            }
+        }
+        return false;
     }
 
     /**
@@ -7491,7 +7495,36 @@
      * {@code ActivityRecordProto} is the outer-most proto data.
      */
     void dumpDebug(ProtoOutputStream proto) {
-        dumpDebug(proto, APP_WINDOW_TOKEN, WindowTraceLogLevel.ALL);
+        writeNameToProto(proto, NAME);
+        super.dumpDebug(proto, WINDOW_TOKEN, WindowTraceLogLevel.ALL);
+        proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
+        proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
+        proto.write(IS_ANIMATING, isAnimating());
+        if (mThumbnail != null) {
+            mThumbnail.dumpDebug(proto, THUMBNAIL);
+        }
+        proto.write(FILLS_PARENT, mOccludesParent);
+        proto.write(APP_STOPPED, mAppStopped);
+        proto.write(VISIBLE_REQUESTED, mVisibleRequested);
+        proto.write(CLIENT_VISIBLE, mClientVisible);
+        proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
+        proto.write(REPORTED_DRAWN, reportedDrawn);
+        proto.write(REPORTED_VISIBLE, reportedVisible);
+        proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
+        proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
+        proto.write(ALL_DRAWN, allDrawn);
+        proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
+        if (startingWindow != null) {
+            startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
+        }
+        proto.write(STARTING_DISPLAYED, startingDisplayed);
+        proto.write(STARTING_MOVED, startingMoved);
+        proto.write(VISIBLE_SET_FROM_TRANSFERRED_STARTING_WINDOW,
+                mVisibleSetFromTransferredStartingWindow);
+        for (Rect bounds : mFrozenBounds) {
+            bounds.dumpDebug(proto, FROZEN_BOUNDS);
+        }
+
         writeIdentifierToProto(proto, IDENTIFIER);
         proto.write(STATE, mState.toString());
         proto.write(VISIBLE_REQUESTED, mVisibleRequested);
@@ -7531,7 +7564,7 @@
         }
         proto.write(FILLS_PARENT, mOccludesParent);
         proto.write(APP_STOPPED, mAppStopped);
-        proto.write(com.android.server.wm.AppWindowTokenProto.VISIBLE_REQUESTED, mVisibleRequested);
+        proto.write(VISIBLE_REQUESTED, mVisibleRequested);
         proto.write(CLIENT_VISIBLE, mClientVisible);
         proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
         proto.write(REPORTED_DRAWN, reportedDrawn);
@@ -7550,7 +7583,7 @@
         for (Rect bounds : mFrozenBounds) {
             bounds.dumpDebug(proto, FROZEN_BOUNDS);
         }
-        proto.write(com.android.server.wm.AppWindowTokenProto.VISIBLE, mVisible);
+        proto.write(VISIBLE, mVisible);
         proto.end(token);
     }
 
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 942be84..ddf0117 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -660,6 +660,8 @@
 
         super.onConfigurationChanged(newParentConfig);
 
+        updateTaskOrganizerState();
+
         // Only need to update surface size here since the super method will handle updating
         // surface position.
         updateSurfaceSize(getPendingTransaction());
@@ -762,6 +764,22 @@
         }
     }
 
+    void updateTaskOrganizerState() {
+        if (!isRootTask()) {
+            return;
+        }
+
+        final int windowingMode = getWindowingMode();
+        /*
+         * Different windowing modes may be managed by different task organizers. If
+         * getTaskOrganizer returns null, we still call setTaskOrganizer to
+         * make sure we clear it.
+         */
+        final ITaskOrganizer org =
+            mWmService.mAtmService.mTaskOrganizerController.getTaskOrganizer(windowingMode);
+        setTaskOrganizer(org);
+    }
+
     @Override
     public void setWindowingMode(int windowingMode) {
         // Calling Task#setWindowingMode() for leaf task since this is the a specialization of
@@ -774,15 +792,6 @@
         setWindowingMode(windowingMode, false /* animate */, false /* showRecents */,
                 false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */,
                 false /* creating */);
-        windowingMode = getWindowingMode();
-        /*
-         * Different windowing modes may be managed by different task organizers. If
-         * getTaskOrganizer returns null, we still call transferToTaskOrganizer to
-         * make sure we clear it.
-         */
-        final ITaskOrganizer org =
-            mWmService.mAtmService.mTaskOrganizerController.getTaskOrganizer(windowingMode);
-        transferToTaskOrganizer(org);
     }
 
     /**
@@ -1263,6 +1272,8 @@
     void awakeFromSleepingLocked() {
         // Ensure activities are no longer sleeping.
         forAllActivities((Consumer<ActivityRecord>) (r) -> r.setSleeping(false));
+        ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
+                false /* preserveWindows */);
         if (mPausingActivity != null) {
             Slog.d(TAG, "awakeFromSleepingLocked: previously pausing activity didn't pause");
             mPausingActivity.activityPaused(true);
@@ -1312,13 +1323,6 @@
                 mStackSupervisor.scheduleIdle();
                 shouldSleep = false;
             }
-
-            if (containsActivityFromStack(mStackSupervisor.mGoingToSleepActivities)) {
-                // Still need to tell some activities to sleep; can't sleep yet.
-                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still need to sleep "
-                        + mStackSupervisor.mGoingToSleepActivities.size() + " activities");
-                shouldSleep = false;
-            }
         }
 
         if (shouldSleep) {
@@ -1329,16 +1333,18 @@
     }
 
     void goToSleep() {
-        // Ensure visibility without updating configuration, as activities are about to sleep.
-        ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, !PRESERVE_WINDOWS);
-
-        // Make sure any paused or stopped but visible activities are now sleeping.
-        // This ensures that the activity's onStop() is called.
+        // Make sure all visible activities are now sleeping. This will update the activity's
+        // visibility and onStop() will be called.
         forAllActivities((r) -> {
-            if (r.isState(STARTED, STOPPING, STOPPED, PAUSED, PAUSING)) {
+            if (r.isState(STARTED, RESUMED, PAUSING, PAUSED, STOPPING, STOPPED)) {
                 r.setSleeping(true);
             }
         });
+
+        // Ensure visibility after updating sleep states without updating configuration,
+        // as activities are about to be sent to sleep.
+        ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
+                !PRESERVE_WINDOWS);
     }
 
     private boolean containsActivityFromStack(List<ActivityRecord> rs) {
@@ -1586,24 +1592,6 @@
         return topActivity != null && topActivity.mVisibleRequested;
     }
 
-    private static void transferSingleTaskToOrganizer(Task tr, ITaskOrganizer organizer) {
-        tr.setTaskOrganizer(organizer);
-    }
-
-    /**
-     * Transfer control of the leashes and IWindowContainers to the given ITaskOrganizer.
-     * This will (or shortly there-after) invoke the taskAppeared callbacks.
-     * If the tasks had a previous TaskOrganizer, setTaskOrganizer will take care of
-     * emitting the taskVanished callbacks.
-     */
-    void transferToTaskOrganizer(ITaskOrganizer organizer) {
-        final PooledConsumer c = PooledLambda.obtainConsumer(
-                ActivityStack::transferSingleTaskToOrganizer,
-                PooledLambda.__(Task.class), organizer);
-        forAllTasks(c, true /* traverseTopToBottom */, this);
-        c.recycle();
-    }
-
     /**
      * Returns true if the stack should be visible.
      *
@@ -2040,8 +2028,17 @@
             return false;
         }
 
-        // If we are sleeping, and there is no resumed activity, and the top
-        // activity is paused, well that is the state we want.
+        // If we are currently pausing an activity, then don't do anything until that is done.
+        final boolean allPausedComplete = mRootWindowContainer.allPausedActivitiesComplete();
+        if (!allPausedComplete) {
+            if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) {
+                Slog.v(TAG_PAUSE, "resumeTopActivityLocked: Skip resume: some activity pausing.");
+            }
+            return false;
+        }
+
+        // If we are sleeping, and there is no resumed activity, and the top activity is paused,
+        // well that is the state we want.
         if (shouldSleepOrShutDownActivities()
                 && mLastPausedActivity == next
                 && mRootWindowContainer.allPausedActivitiesComplete()) {
@@ -2082,8 +2079,7 @@
         // The activity may be waiting for stop, but that is no longer
         // appropriate for it.
         mStackSupervisor.mStoppingActivities.remove(next);
-        mStackSupervisor.mGoingToSleepActivities.remove(next);
-        next.sleeping = false;
+        next.setSleeping(false);
 
         if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);
 
@@ -2352,7 +2348,7 @@
                 EventLogTags.writeWmResumeActivity(next.mUserId, System.identityHashCode(next),
                         next.getTask().mTaskId, next.shortComponentName);
 
-                next.sleeping = false;
+                next.setSleeping(false);
                 mAtmService.getAppWarningsLocked().onResumeActivity(next);
                 next.app.setPendingUiCleanAndForceProcessStateUpTo(mAtmService.mTopProcessState);
                 next.clearOptionsLocked();
@@ -3985,6 +3981,10 @@
      * Used to make room for shadows in the pinned windowing mode.
      */
     int getStackOutset() {
+        // If we are drawing shadows on the task then don't outset the stack.
+        if (mWmService.mRenderShadowsInCompositor) {
+            return 0;
+        }
         DisplayContent displayContent = getDisplayContent();
         if (inPinnedWindowingMode() && displayContent != null) {
             final DisplayMetrics displayMetrics = displayContent.getDisplayMetrics();
@@ -4034,7 +4034,9 @@
     @Override
     void onDisplayChanged(DisplayContent dc) {
         super.onDisplayChanged(dc);
-        updateSurfaceBounds();
+        if (isRootTask()) {
+            updateSurfaceBounds();
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 2c0f3e6..362e781 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -285,9 +285,6 @@
      * settle down before doing so.  It contains ActivityRecord objects. */
     final ArrayList<ActivityRecord> mFinishingActivities = new ArrayList<>();
 
-    /** List of activities that are in the process of going to sleep. */
-    final ArrayList<ActivityRecord> mGoingToSleepActivities = new ArrayList<>();
-
     /** List of activities whose multi-window mode changed that we need to report to the
      * application */
     private final ArrayList<ActivityRecord> mMultiWindowModeChangedActivities = new ArrayList<>();
@@ -881,7 +878,7 @@
                 }
                 mService.getPackageManagerInternalLocked().notifyPackageUse(
                         r.intent.getComponent().getPackageName(), NOTIFY_PACKAGE_USE_ACTIVITY);
-                r.sleeping = false;
+                r.setSleeping(false);
                 r.forceNewConfig = false;
                 mService.getAppWarningsLocked().onStartActivity(r);
                 r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
@@ -1239,7 +1236,8 @@
         final PackageInfo packageInfo;
         try {
             packageInfo = mService.mContext.getPackageManager()
-                    .getPackageInfo(callingPackage, PackageManager.GET_PERMISSIONS);
+                    .getPackageInfoAsUser(callingPackage, PackageManager.GET_PERMISSIONS,
+                            UserHandle.getUserId(callingUid));
         } catch (PackageManager.NameNotFoundException e) {
             Slog.i(TAG, "Cannot find package info for " + callingPackage);
             return ACTIVITY_RESTRICTION_NONE;
@@ -1991,16 +1989,6 @@
         }
     }
 
-    void activitySleptLocked(ActivityRecord r) {
-        mGoingToSleepActivities.remove(r);
-        final ActivityStack s = r.getRootTask();
-        if (s != null) {
-            s.checkReadyForSleep();
-        } else {
-            checkReadyForSleepLocked(true);
-        }
-    }
-
     void checkReadyForSleepLocked(boolean allowDelay) {
         if (!mService.isSleepingOrShuttingDownLocked()) {
             // Do not care.
@@ -2137,7 +2125,6 @@
 
     void removeHistoryRecords(WindowProcessController app) {
         removeHistoryRecords(mStoppingActivities, app, "mStoppingActivities");
-        removeHistoryRecords(mGoingToSleepActivities, app, "mGoingToSleepActivities");
         removeHistoryRecords(mFinishingActivities, app, "mFinishingActivities");
     }
 
@@ -2474,7 +2461,10 @@
         if (r != null) {
             r.finishRelaunching();
             if (r.getRootTask().shouldSleepOrShutDownActivities()) {
-                r.setSleeping(true, true);
+                // Activity is always relaunched to either resumed or paused state. If it was
+                // relaunched while hidden (by keyguard or smth else), it should be stopped.
+                r.getStack().ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
+                        false /* preserveWindows */);
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
index d61d29d..2fb0ac5 100644
--- a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
@@ -52,7 +52,6 @@
 import android.os.UserManager;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.app.BlockedAppActivity;
 import com.android.internal.app.HarmfulAppWarningActivity;
 import com.android.internal.app.SuspendedAppActivity;
 import com.android.internal.app.UnlaunchableAppActivity;
@@ -167,9 +166,6 @@
             // no user action can undo this.
             return true;
         }
-        if (interceptLockTaskModeViolationPackageIfNeeded()) {
-            return true;
-        }
         if (interceptHarmfulAppIfNeeded()) {
             // If the app has a "harmful app" warning associated with it, we should ask to uninstall
             // before issuing the work challenge.
@@ -178,6 +174,11 @@
         return interceptWorkProfileChallengeIfNeeded();
     }
 
+    private boolean hasCrossProfileAnimation() {
+        return mActivityOptions != null
+                && mActivityOptions.getAnimationType() == ANIM_OPEN_CROSS_PROFILE_APPS;
+    }
+
     /**
      * If the activity option is the {@link ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} one,
      * defer the animation until the original intent is started.
@@ -185,8 +186,7 @@
      * @return the activity option used to start the original intent.
      */
     private Bundle deferCrossProfileAppsAnimationIfNecessary() {
-        if (mActivityOptions != null
-                && mActivityOptions.getAnimationType() == ANIM_OPEN_CROSS_PROFILE_APPS) {
+        if (hasCrossProfileAnimation()) {
             mActivityOptions = null;
             return ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle();
         }
@@ -255,28 +255,13 @@
         }
         final SuspendDialogInfo dialogInfo = pmi.getSuspendedDialogInfo(suspendedPackage,
                 suspendingPackage, mUserId);
+        final Bundle crossProfileOptions = hasCrossProfileAnimation()
+                ? ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle()
+                : null;
+        final IntentSender target = createIntentSenderForOriginalIntent(mCallingUid,
+                FLAG_IMMUTABLE);
         mIntent = SuspendedAppActivity.createSuspendedAppInterceptIntent(suspendedPackage,
-                suspendingPackage, dialogInfo, deferCrossProfileAppsAnimationIfNecessary(),
-                mUserId);
-        mCallingPid = mRealCallingPid;
-        mCallingUid = mRealCallingUid;
-        mResolvedType = null;
-        mRInfo = mSupervisor.resolveIntent(mIntent, mResolvedType, mUserId, 0, mRealCallingUid);
-        mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags, null /*profilerInfo*/);
-        return true;
-    }
-
-    private boolean interceptLockTaskModeViolationPackageIfNeeded() {
-        if (mAInfo == null || mAInfo.applicationInfo == null) {
-            return false;
-        }
-        LockTaskController controller = mService.getLockTaskController();
-        String packageName = mAInfo.applicationInfo.packageName;
-        int lockTaskLaunchMode = ActivityRecord.getLockTaskLaunchMode(mAInfo, mActivityOptions);
-        if (controller.isActivityAllowed(mUserId, packageName, lockTaskLaunchMode)) {
-            return false;
-        }
-        mIntent = BlockedAppActivity.createIntent(mUserId, mAInfo.applicationInfo.packageName);
+                suspendingPackage, dialogInfo, crossProfileOptions, target, mUserId);
         mCallingPid = mRealCallingPid;
         mCallingUid = mRealCallingUid;
         mResolvedType = null;
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 26812f4..9e3292b 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1595,11 +1595,11 @@
                 mRootWindowContainer.resumeFocusedStacksTopActivities(
                         mTargetStack, mStartActivity, mOptions);
             }
-        } else if (mStartActivity != null) {
-            mSupervisor.mRecentTasks.add(mStartActivity.getTask());
         }
         mRootWindowContainer.updateUserStack(mStartActivity.mUserId, mTargetStack);
 
+        // Update the recent tasks list immediately when the activity starts
+        mSupervisor.mRecentTasks.add(mStartActivity.getTask());
         mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(),
                 preferredWindowingMode, mPreferredDisplayId, mTargetStack);
 
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 31b7c68..976fbdb 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -1043,6 +1043,7 @@
     public final int startActivities(IApplicationThread caller, String callingPackage,
             Intent[] intents, String[] resolvedTypes, IBinder resultTo, Bundle bOptions,
             int userId) {
+        assertPackageMatchesCallingUid(callingPackage);
         final String reason = "startActivities";
         enforceNotIsolatedCaller(reason);
         userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, reason);
@@ -1062,10 +1063,11 @@
                 true /*validateIncomingUser*/);
     }
 
-    int startActivityAsUser(IApplicationThread caller, String callingPackage,
+    private int startActivityAsUser(IApplicationThread caller, String callingPackage,
             Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
             int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
             boolean validateIncomingUser) {
+        assertPackageMatchesCallingUid(callingPackage);
         enforceNotIsolatedCaller("startActivityAsUser");
 
         userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
@@ -1238,6 +1240,7 @@
     public final WaitResult startActivityAndWait(IApplicationThread caller, String callingPackage,
             Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
             int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
+        assertPackageMatchesCallingUid(callingPackage);
         final WaitResult res = new WaitResult();
         enforceNotIsolatedCaller("startActivityAndWait");
         userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
@@ -1263,6 +1266,7 @@
     public final int startActivityWithConfig(IApplicationThread caller, String callingPackage,
             Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
             int startFlags, Configuration config, Bundle bOptions, int userId) {
+        assertPackageMatchesCallingUid(callingPackage);
         enforceNotIsolatedCaller("startActivityWithConfig");
         userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                 "startActivityWithConfig");
@@ -1447,6 +1451,7 @@
             Intent intent, String resolvedType, IVoiceInteractionSession session,
             IVoiceInteractor interactor, int startFlags, ProfilerInfo profilerInfo,
             Bundle bOptions, int userId) {
+        assertPackageMatchesCallingUid(callingPackage);
         mAmInternal.enforceCallingPermission(BIND_VOICE_INTERACTION, "startVoiceActivity()");
         if (session == null || interactor == null) {
             throw new NullPointerException("null session or interactor");
@@ -1470,6 +1475,7 @@
     @Override
     public int startAssistantActivity(String callingPackage, int callingPid, int callingUid,
             Intent intent, String resolvedType, Bundle bOptions, int userId) {
+        assertPackageMatchesCallingUid(callingPackage);
         mAmInternal.enforceCallingPermission(BIND_VOICE_INTERACTION, "startAssistantActivity()");
         userId = handleIncomingUser(callingPid, callingUid, userId, "startAssistantActivity");
 
@@ -1825,21 +1831,6 @@
         Binder.restoreCallingIdentity(origId);
     }
 
-    public final void activitySlept(IBinder token) {
-        if (DEBUG_ALL) Slog.v(TAG, "Activity slept: token=" + token);
-
-        final long origId = Binder.clearCallingIdentity();
-
-        synchronized (mGlobalLock) {
-            final ActivityRecord r = ActivityRecord.isInStackLocked(token);
-            if (r != null) {
-                mStackSupervisor.activitySleptLocked(r);
-            }
-        }
-
-        Binder.restoreCallingIdentity(origId);
-    }
-
     @Override
     public void setRequestedOrientation(IBinder token, int requestedOrientation) {
         synchronized (mGlobalLock) {
@@ -2391,15 +2382,9 @@
     void moveTaskToFrontLocked(@Nullable IApplicationThread appThread,
             @Nullable String callingPackage, int taskId, int flags, SafeActivityOptions options,
             boolean fromRecents) {
-
         final int callingPid = Binder.getCallingPid();
         final int callingUid = Binder.getCallingUid();
-        if (!isSameApp(callingUid, callingPackage)) {
-            String msg = "Permission Denial: moveTaskToFrontLocked() from pid="
-                    + Binder.getCallingPid() + " as package " + callingPackage;
-            Slog.w(TAG, msg);
-            throw new SecurityException(msg);
-        }
+        assertPackageMatchesCallingUid(callingPackage);
         if (!checkAppSwitchAllowedLocked(callingPid, callingUid, -1, -1, "Task to front")) {
             SafeActivityOptions.abort(options);
             return;
@@ -2451,7 +2436,7 @@
     /**
      * Return true if callingUid is system, or packageName belongs to that callingUid.
      */
-    boolean isSameApp(int callingUid, @Nullable String packageName) {
+    private boolean isSameApp(int callingUid, @Nullable String packageName) {
         try {
             if (callingUid != 0 && callingUid != SYSTEM_UID) {
                 if (packageName == null) {
@@ -2468,6 +2453,21 @@
         return true;
     }
 
+    /**
+     * Checks that the provided package name matches the current calling UID, throws a security
+     * exception if it doesn't.
+     */
+    void assertPackageMatchesCallingUid(@Nullable String packageName) {
+        final int callingUid = Binder.getCallingUid();
+        if (isSameApp(callingUid, packageName)) {
+            return;
+        }
+        final String msg = "Permission Denial: package=" + packageName
+                + " does not belong to uid=" + callingUid;
+        Slog.w(TAG, msg);
+        throw new SecurityException(msg);
+    }
+
     boolean checkAppSwitchAllowedLocked(int sourcePid, int sourceUid,
             int callingPid, int callingUid, String name) {
         if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
@@ -3033,6 +3033,7 @@
     @Override
     public List<IBinder> getAppTasks(String callingPackage) {
         int callingUid = Binder.getCallingUid();
+        assertPackageMatchesCallingUid(callingPackage);
         long ident = Binder.clearCallingIdentity();
         try {
             synchronized (mGlobalLock) {
@@ -3303,7 +3304,7 @@
         }
     }
 
-    private int sanitizeAndApplyChange(ConfigurationContainer container,
+    private int sanitizeAndApplyChange(WindowContainer container,
             WindowContainerTransaction.Change change) {
         if (!(container instanceof Task || container instanceof ActivityStack)) {
             throw new RuntimeException("Invalid token in task transaction");
@@ -3347,13 +3348,13 @@
         }
     }
 
-    private int applyWindowContainerChange(ConfigurationContainer cc,
+    private int applyWindowContainerChange(WindowContainer wc,
             WindowContainerTransaction.Change c) {
-        int effects = sanitizeAndApplyChange(cc, c);
+        int effects = sanitizeAndApplyChange(wc, c);
 
         Rect enterPipBounds = c.getEnterPipBounds();
         if (enterPipBounds != null) {
-            Task tr = (Task) cc;
+            Task tr = (Task) wc;
             mStackSupervisor.updatePictureInPictureMode(tr,
                     enterPipBounds, true);
         }
@@ -3378,17 +3379,14 @@
                     while (entries.hasNext()) {
                         final Map.Entry<IBinder, WindowContainerTransaction.Change> entry =
                                 entries.next();
-                        final ConfigurationContainer cc =
-                                ConfigurationContainer.RemoteToken.fromBinder(
-                                        entry.getKey()).getContainer();
-                        int containerEffect = applyWindowContainerChange(cc, entry.getValue());
+                        final WindowContainer wc = WindowContainer.RemoteToken.fromBinder(
+                                entry.getKey()).getContainer();
+                        int containerEffect = applyWindowContainerChange(wc, entry.getValue());
                         effects |= containerEffect;
                         // Lifecycle changes will trigger ensureConfig for everything.
                         if ((effects & TRANSACT_EFFECTS_LIFECYCLE) == 0
                                 && (containerEffect & TRANSACT_EFFECTS_CLIENT_CONFIG) != 0) {
-                            if (cc instanceof WindowContainer) {
-                                haveConfigChanges.add((WindowContainer) cc);
-                            }
+                            haveConfigChanges.add(wc);
                         }
                     }
                     if ((effects & TRANSACT_EFFECTS_LIFECYCLE) != 0) {
@@ -6332,6 +6330,7 @@
                 SafeActivityOptions options, int userId, boolean validateIncomingUser,
                 PendingIntentRecord originatingPendingIntent,
                 boolean allowBackgroundActivityStart) {
+            assertPackageMatchesCallingUid(callingPackage);
             synchronized (mGlobalLock) {
                 return getActivityStartController().startActivitiesInPackage(uid, realCallingPid,
                         realCallingUid, callingPackage, intents, resolvedTypes, resultTo, options,
@@ -6347,6 +6346,7 @@
                 int userId, Task inTask, String reason, boolean validateIncomingUser,
                 PendingIntentRecord originatingPendingIntent,
                 boolean allowBackgroundActivityStart) {
+            assertPackageMatchesCallingUid(callingPackage);
             synchronized (mGlobalLock) {
                 return getActivityStartController().startActivityInPackage(uid, realCallingPid,
                         realCallingUid, callingPackage, intent, resolvedType, resultTo, resultWho,
diff --git a/services/core/java/com/android/server/wm/AppTaskImpl.java b/services/core/java/com/android/server/wm/AppTaskImpl.java
index 357f9e5..16a7564 100644
--- a/services/core/java/com/android/server/wm/AppTaskImpl.java
+++ b/services/core/java/com/android/server/wm/AppTaskImpl.java
@@ -27,7 +27,6 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.UserHandle;
-import android.util.Slog;
 
 /**
  * An implementation of IAppTask, that allows an app to manage its own tasks via
@@ -97,12 +96,7 @@
         // Will bring task to front if it already has a root activity.
         final int callingPid = Binder.getCallingPid();
         final int callingUid = Binder.getCallingUid();
-        if (!mService.isSameApp(callingUid, callingPackage)) {
-            String msg = "Permission Denial: moveToFront() from pid="
-                    + Binder.getCallingPid() + " as package " + callingPackage;
-            Slog.w(TAG, msg);
-            throw new SecurityException(msg);
-        }
+        mService.assertPackageMatchesCallingUid(callingPackage);
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized (mService.mGlobalLock) {
@@ -134,6 +128,7 @@
     public int startActivity(IBinder whoThread, String callingPackage,
             Intent intent, String resolvedType, Bundle bOptions) {
         checkCaller();
+        mService.assertPackageMatchesCallingUid(callingPackage);
 
         int callingUser = UserHandle.getCallingUserId();
         Task task;
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index 7b23e2d..9bd380a 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -39,15 +39,11 @@
 import android.content.res.Configuration;
 import android.graphics.Point;
 import android.graphics.Rect;
-import android.os.IBinder;
 import android.util.proto.ProtoOutputStream;
-import android.view.IWindowContainer;
-import android.view.SurfaceControl;
 
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 
 /**
@@ -104,12 +100,6 @@
     static final int BOUNDS_CHANGE_SIZE = 1 << 1;
 
     /**
-     * Used as a unique, cross-process identifier for this Container. It also serves a minimal
-     * interface to other processes.
-     */
-    RemoteToken mRemoteToken = null;
-
-    /**
      * Returns full configuration applied to this configuration container.
      * This method should be used for getting settings applied in each particular level of the
      * hierarchy.
@@ -629,21 +619,6 @@
         return mFullConfiguration.windowConfiguration.isAlwaysOnTop();
     }
 
-    /**
-     * Returns {@code true} if this container is focusable. Generally, if a parent is not focusable,
-     * this will not be focusable either.
-     */
-    boolean isFocusable() {
-        // TODO(split): Move this to WindowContainer once Split-screen is based on a WindowContainer
-        //              like DisplayArea vs. TaskTiles.
-        ConfigurationContainer parent = getParent();
-        return parent == null || parent.isFocusable();
-    }
-
-    boolean setFocusable(boolean focusable) {
-        return false;
-    }
-
     boolean hasChild() {
         return getChildCount() > 0;
     }
@@ -654,40 +629,4 @@
 
     abstract protected ConfigurationContainer getParent();
 
-    // TODO: Consider moving to WindowContainer once hierarchies and Task/Stack are merged.
-    static class RemoteToken extends IWindowContainer.Stub {
-        final WeakReference<ConfigurationContainer> mWeakRef;
-
-        RemoteToken(ConfigurationContainer container) {
-            mWeakRef = new WeakReference<>(container);
-        }
-
-        ConfigurationContainer getContainer() {
-            return mWeakRef.get();
-        }
-
-        static RemoteToken fromBinder(IBinder binder) {
-            return (RemoteToken) binder;
-        }
-
-        @Override
-        public SurfaceControl getLeash() {
-            throw new RuntimeException("Not implemented");
-        }
-
-        @Override
-        public String toString() {
-            StringBuilder sb = new StringBuilder(128);
-            sb.append("RemoteToken{");
-            sb.append(Integer.toHexString(System.identityHashCode(this)));
-            sb.append(' ');
-            sb.append(mWeakRef.get());
-            sb.append('}');
-            return sb.toString();
-        }
-    }
-
-    RemoteToken getRemoteToken() {
-        return mRemoteToken;
-    }
 }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 825f93c..c50048e 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -112,7 +112,6 @@
 import static com.android.server.wm.DisplayContentProto.IME_WINDOWS;
 import static com.android.server.wm.DisplayContentProto.OPENING_APPS;
 import static com.android.server.wm.DisplayContentProto.OVERLAY_WINDOWS;
-import static com.android.server.wm.DisplayContentProto.PINNED_STACK_CONTROLLER;
 import static com.android.server.wm.DisplayContentProto.ROTATION;
 import static com.android.server.wm.DisplayContentProto.SCREEN_ROTATION_ANIMATION;
 import static com.android.server.wm.DisplayContentProto.STACKS;
@@ -2099,6 +2098,7 @@
      * the above app windows specify orientation, the orientation is computed from the child window
      * container, e.g. {@link AppWindowToken#getOrientation(int)}.
      */
+    @ScreenOrientation
     @Override
     int getOrientation() {
         final WindowManagerPolicy policy = mWmService.mPolicy;
@@ -2778,7 +2778,6 @@
             stack.dumpDebugInnerStackOnly(proto, STACKS, logLevel);
         }
         mDividerControllerLocked.dumpDebug(proto, DOCKED_STACK_DIVIDER_CONTROLLER);
-        mPinnedStackControllerLocked.dumpDebug(proto, PINNED_STACK_CONTROLLER);
         for (int i = mAboveAppWindowsContainers.getChildCount() - 1; i >= 0; --i) {
             final WindowToken windowToken = mAboveAppWindowsContainers.getChildAt(i);
             windowToken.dumpDebug(proto, ABOVE_APP_WINDOWS, logLevel);
@@ -3116,6 +3115,8 @@
             }
         }
 
+        onWindowFocusChanged(oldFocus, newFocus);
+
         int focusChanged = getDisplayPolicy().focusChangedLw(oldFocus, newFocus);
 
         if (imWindowChanged && oldFocus != mInputMethodWindow) {
@@ -3158,6 +3159,20 @@
         return true;
     }
 
+    private static void onWindowFocusChanged(WindowState oldFocus, WindowState newFocus) {
+        final Task focusedTask = newFocus != null ? newFocus.getTask() : null;
+        final Task unfocusedTask = oldFocus != null ? oldFocus.getTask() : null;
+        if (focusedTask == unfocusedTask) {
+            return;
+        }
+        if (focusedTask != null) {
+            focusedTask.onWindowFocusChanged(true /* hasFocus */);
+        }
+        if (unfocusedTask != null) {
+            unfocusedTask.onWindowFocusChanged(false /* hasFocus */);
+        }
+    }
+
     /**
      * Set the new focused app to this display.
      *
@@ -4715,7 +4730,7 @@
             // exists so it get's layered above the starting window.
             if (imeTarget != null && !(imeTarget.mActivityRecord != null
                     && imeTarget.mActivityRecord.hasStartingWindow()) && (
-                    !(imeTarget.inSplitScreenWindowingMode()
+                    !(imeTarget.inMultiWindowMode()
                             || imeTarget.mToken.isAppTransitioning()) && (
                             imeTarget.getSurfaceControl() != null))) {
                 mImeWindowsContainers.assignRelativeLayer(t, imeTarget.getSurfaceControl(),
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index e975bb6..c6ccd4a 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -1014,8 +1014,19 @@
                 mNavigationBarController.setWindow(win);
                 mNavigationBarController.setOnBarVisibilityChangedListener(
                         mNavBarVisibilityListener, true);
-                mDisplayContent.setInsetProvider(ITYPE_NAVIGATION_BAR,
-                        win, null /* frameProvider */);
+                mDisplayContent.setInsetProvider(ITYPE_NAVIGATION_BAR, win,
+                        (displayFrames, windowState, inOutFrame) -> {
+
+                            // In Gesture Nav, navigation bar frame is larger than frame to
+                            // calculate inset.
+                            if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
+                                sTmpRect.set(displayFrames.mUnrestricted);
+                                sTmpRect.intersectUnchecked(displayFrames.mDisplayCutoutSafe);
+                                inOutFrame.top = sTmpRect.bottom
+                                        - getNavigationBarHeight(displayFrames.mRotation,
+                                                mDisplayContent.getConfiguration().uiMode);
+                            }
+                        });
                 mDisplayContent.setInsetProvider(ITYPE_BOTTOM_GESTURES, win,
                         (displayFrames, windowState, inOutFrame) -> {
                             inOutFrame.top -= mBottomGestureAdditionalInset;
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index f90f224..da77314 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -1001,18 +1001,22 @@
      * Given an orientation constant, returns the appropriate surface rotation, taking into account
      * sensors, docking mode, rotation lock, and other factors.
      *
-     * @param orientation An orientation constant, such as
-     *                    {@link ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE}.
+     * @param orientation  An orientation constant, such as
+     *                     {@link ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE}.
      * @param lastRotation The most recently used rotation.
      * @return The surface rotation to use.
      */
     @VisibleForTesting
-    int rotationForOrientation(int orientation, int lastRotation) {
-        ProtoLog.v(WM_DEBUG_ORIENTATION, "rotationForOrientation(orient=%d, last=%d); user=%d %s",
-                    orientation, lastRotation, mUserRotation,
-                    mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
-                            ? "USER_ROTATION_LOCKED" : ""
-                        );
+    @Surface.Rotation
+    int rotationForOrientation(@ScreenOrientation int orientation,
+            @Surface.Rotation int lastRotation) {
+        ProtoLog.v(WM_DEBUG_ORIENTATION,
+                "rotationForOrientation(orient=%s (%d), last=%s (%d)); user=%s (%d) %s",
+                ActivityInfo.screenOrientationToString(orientation), orientation,
+                Surface.rotationToString(lastRotation), lastRotation,
+                Surface.rotationToString(mUserRotation), mUserRotation,
+                mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
+                        ? "USER_ROTATION_LOCKED" : "");
 
         if (isFixedToUserRotation()) {
             return mUserRotation;
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 4c5914b..faa6e52 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -161,7 +161,13 @@
 
     void onDisplayRemoved() {
         mHandler.removeCallbacks(mUpdateInputWindows);
-        mService.mInputManager.onDisplayRemoved(mDisplayId);
+        mHandler.post(() -> {
+            // Make sure any pending setInputWindowInfo transactions are completed. That prevents
+            // the timing of updating input info of removed display after cleanup.
+            mService.mTransactionFactory.get().syncInputWindows().apply();
+            // It calls InputDispatcher::setInputWindows directly.
+            mService.mInputManager.onDisplayRemoved(mDisplayId);
+        });
         mDisplayRemoved = true;
     }
 
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index 5a591ec..2bb58dd 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -233,7 +233,7 @@
             // window crop of the surface controls (including the leash) until the client finishes
             // drawing the new frame of the new orientation. Although we cannot defer the reparent
             // operation, it is fine, because reparent won't cause any visual effect.
-            final SurfaceControl barrier = mWin.mWinAnimator.mSurfaceController.mSurfaceControl;
+            final SurfaceControl barrier = mWin.getDeferTransactionBarrier();
             t.deferTransactionUntil(mWin.getSurfaceControl(), barrier, frameNumber);
             t.deferTransactionUntil(leash, barrier, frameNumber);
         }
diff --git a/services/core/java/com/android/server/wm/LockTaskController.java b/services/core/java/com/android/server/wm/LockTaskController.java
index 33b0453..02413bb 100644
--- a/services/core/java/com/android/server/wm/LockTaskController.java
+++ b/services/core/java/com/android/server/wm/LockTaskController.java
@@ -23,8 +23,6 @@
 import static android.content.Context.DEVICE_POLICY_SERVICE;
 import static android.content.Context.STATUS_BAR_SERVICE;
 import static android.content.Intent.ACTION_CALL_EMERGENCY;
-import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
-import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
 import static android.os.UserHandle.USER_ALL;
 import static android.os.UserHandle.USER_CURRENT;
 import static android.telecom.TelecomManager.EMERGENCY_DIALER_COMPONENT;
@@ -341,20 +339,6 @@
                 & DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD) != 0;
     }
 
-    boolean isActivityAllowed(int userId, String packageName, int lockTaskLaunchMode) {
-        if (mLockTaskModeState != LOCK_TASK_MODE_LOCKED) {
-            return true;
-        }
-        switch (lockTaskLaunchMode) {
-            case LOCK_TASK_LAUNCH_MODE_ALWAYS:
-                return true;
-            case LOCK_TASK_LAUNCH_MODE_NEVER:
-                return false;
-            default:
-        }
-        return isPackageWhitelisted(userId, packageName);
-    }
-
     private boolean isEmergencyCallTask(Task task) {
         final Intent intent = task.intent;
         if (intent == null) {
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index 1d5b5d1..668b609 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -18,8 +18,6 @@
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 
-import static com.android.server.wm.PinnedStackControllerProto.DEFAULT_BOUNDS;
-import static com.android.server.wm.PinnedStackControllerProto.MOVEMENT_BOUNDS;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
@@ -34,7 +32,6 @@
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.util.Slog;
-import android.util.proto.ProtoOutputStream;
 import android.view.DisplayInfo;
 import android.view.IPinnedStackController;
 import android.view.IPinnedStackListener;
@@ -97,11 +94,6 @@
     // Temp vars for calculation
     private final DisplayMetrics mTmpMetrics = new DisplayMetrics();
 
-    // TODO(b/141200935): remove this when we have default/movement bounds tests in SysUI.
-    // Keep record of the default and movement bounds
-    private final Rect mLastReportedDefaultBounds = new Rect();
-    private final Rect mLastReportedMovementBounds = new Rect();
-
     /**
      * The callback object passed to listeners for them to notify the controller of state changes.
      */
@@ -143,14 +135,6 @@
                 }
             }
         }
-
-        @Override
-        public void reportBounds(Rect defaultBounds, Rect movementBounds) {
-            synchronized (mService.mGlobalLock) {
-                mLastReportedDefaultBounds.set(defaultBounds);
-                mLastReportedMovementBounds.set(movementBounds);
-            }
-        }
     }
 
     /**
@@ -421,8 +405,6 @@
 
     void dump(String prefix, PrintWriter pw) {
         pw.println(prefix + "PinnedStackController");
-        pw.println(prefix + "  mLastReportedDefaultBounds=" + mLastReportedDefaultBounds);
-        pw.println(prefix + "  mLastReportedMovementBounds=" + mLastReportedMovementBounds);
         pw.println(prefix + "  mDefaultAspectRatio=" + mDefaultAspectRatio);
         pw.println(prefix + "  mIsImeShowing=" + mIsImeShowing);
         pw.println(prefix + "  mImeHeight=" + mImeHeight);
@@ -443,11 +425,4 @@
         }
         pw.println(prefix + "  mDisplayInfo=" + mDisplayInfo);
     }
-
-    void dumpDebug(ProtoOutputStream proto, long fieldId) {
-        final long token = proto.start(fieldId);
-        mLastReportedDefaultBounds.dumpDebug(proto, DEFAULT_BOUNDS);
-        mLastReportedMovementBounds.dumpDebug(proto, MOVEMENT_BOUNDS);
-        proto.end(token);
-    }
 }
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index 292e8aa..a9dc36d 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -173,6 +173,9 @@
     private final ArrayList<Task> mTasks = new ArrayList<>();
     private final ArrayList<Callbacks> mCallbacks = new ArrayList<>();
 
+    /** The non-empty tasks that are removed from recent tasks (see {@link #removeForAddTask}). */
+    private final ArrayList<Task> mHiddenTasks = new ArrayList<>();
+
     // These values are generally loaded from resources, but can be set dynamically in the tests
     private boolean mHasVisibleRecentTasks;
     private int mGlobalMaxNumTasks;
@@ -1024,6 +1027,12 @@
     void add(Task task) {
         if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "add: task=" + task);
 
+        // Clean up the hidden tasks when going to home because the user may not be unable to return
+        // to the task from recents.
+        if (!mHiddenTasks.isEmpty() && task.isActivityTypeHome()) {
+            removeUnreachableHiddenTasks(task.getWindowingMode());
+        }
+
         final boolean isAffiliated = task.mAffiliatedTaskId != task.mTaskId
                 || task.mNextAffiliateTaskId != INVALID_TASK_ID
                 || task.mPrevAffiliateTaskId != INVALID_TASK_ID;
@@ -1390,6 +1399,28 @@
         return display.getIndexOf(stack) < display.getIndexOf(display.getRootHomeTask());
     }
 
+    /** Remove the tasks that user may not be able to return. */
+    private void removeUnreachableHiddenTasks(int windowingMode) {
+        for (int i = mHiddenTasks.size() - 1; i >= 0; i--) {
+            final Task hiddenTask = mHiddenTasks.get(i);
+            if (!hiddenTask.hasChild()) {
+                // The task was removed by other path.
+                mHiddenTasks.remove(i);
+                continue;
+            }
+            if (hiddenTask.getWindowingMode() != windowingMode
+                    || hiddenTask.getTopVisibleActivity() != null) {
+                // The task may be reachable from the back stack of other windowing mode or it is
+                // currently in use. Keep the task in the hidden list to avoid losing track, e.g.
+                // after dismissing primary split screen.
+                continue;
+            }
+            mHiddenTasks.remove(i);
+            mSupervisor.removeTask(hiddenTask, false /* killProcess */,
+                    !REMOVE_FROM_RECENTS, "remove-hidden-task");
+        }
+    }
+
     /**
      * If needed, remove oldest existing entries in recents that are for the same kind
      * of task as the given one.
@@ -1406,6 +1437,14 @@
         // callbacks here.
         final Task removedTask = mTasks.remove(removeIndex);
         if (removedTask != task) {
+            // The added task is in recents so it is not hidden.
+            mHiddenTasks.remove(task);
+            if (removedTask.hasChild()) {
+                // A non-empty task is replaced by a new task. Because the removed task is no longer
+                // managed by the recent tasks list, add it to the hidden list to prevent the task
+                // from becoming dangling.
+                mHiddenTasks.add(removedTask);
+            }
             notifyTaskRemoved(removedTask, false /* wasTrimmed */, false /* killProcess */);
             if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "Trimming task=" + removedTask
                     + " for addition of task=" + task);
@@ -1662,6 +1701,9 @@
         pw.println("mFreezeTaskListReordering=" + mFreezeTaskListReordering);
         pw.println("mFreezeTaskListReorderingPendingTimeout="
                 + mService.mH.hasCallbacks(mResetFreezeTaskListOnTimeoutRunnable));
+        if (!mHiddenTasks.isEmpty()) {
+            pw.println("mHiddenTasks=" + mHiddenTasks);
+        }
         if (mTasks.isEmpty()) {
             return;
         }
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 0b54245..e6fd512 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -164,7 +164,6 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
@@ -2348,18 +2347,6 @@
                     }
                 }
             }
-
-            if (displayShouldSleep || mStackSupervisor.mGoingToSleepActivities.isEmpty()) {
-                continue;
-            }
-            // The display is awake now, so clean up the going to sleep list.
-            for (Iterator<ActivityRecord> it =
-                    mStackSupervisor.mGoingToSleepActivities.iterator(); it.hasNext(); ) {
-                final ActivityRecord r = it.next();
-                if (r.getDisplayId() == display.mDisplayId) {
-                    it.remove();
-                }
-            }
         }
     }
 
@@ -3578,9 +3565,6 @@
         printed |= dumpHistoryList(fd, pw, mStackSupervisor.mStoppingActivities, "  ",
                 "Stop", false, !dumpAll,
                 false, dumpPackage, true, "  Activities waiting to stop:", null);
-        printed |= dumpHistoryList(fd, pw, mStackSupervisor.mGoingToSleepActivities,
-                "  ", "Sleep", false, !dumpAll,
-                false, dumpPackage, true, "  Activities waiting to sleep:", null);
 
         return printed;
     }
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index bfb69172..e7aca89 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -370,6 +370,11 @@
             }
         }
 
+        ProtoLog.d(WM_DEBUG_ORIENTATION, "Start rotation animation. customAnim=%s, "
+                        + "mCurRotation=%s, mOriginalRotation=%s",
+                customAnim, Surface.rotationToString(mCurRotation),
+                Surface.rotationToString(mOriginalRotation));
+
         mRotateExitAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
         mRotateExitAnimation.restrictDuration(maxAnimationDuration);
         mRotateExitAnimation.scaleCurrentDuration(animationScale);
diff --git a/services/core/java/com/android/server/wm/SeamlessRotator.java b/services/core/java/com/android/server/wm/SeamlessRotator.java
index ba31818..c621c48 100644
--- a/services/core/java/com/android/server/wm/SeamlessRotator.java
+++ b/services/core/java/com/android/server/wm/SeamlessRotator.java
@@ -101,9 +101,9 @@
         t.setPosition(win.mSurfaceControl, win.mLastSurfacePosition.x, win.mLastSurfacePosition.y);
         if (win.mWinAnimator.mSurfaceController != null && !timeout) {
             t.deferTransactionUntil(win.mSurfaceControl,
-                    win.mWinAnimator.mSurfaceController.mSurfaceControl, win.getFrameNumber());
+                    win.getDeferTransactionBarrier(), win.getFrameNumber());
             t.deferTransactionUntil(win.mWinAnimator.mSurfaceController.mSurfaceControl,
-                    win.mWinAnimator.mSurfaceController.mSurfaceControl, win.getFrameNumber());
+                    win.getDeferTransactionBarrier(), win.getFrameNumber());
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 5babdaf..de7f9e4 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -191,7 +191,7 @@
             Rect outStableInsets, Rect outBackdropFrame,
             DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,
             SurfaceControl outSurfaceControl, InsetsState outInsetsState,
-            Point outSurfaceSize) {
+            Point outSurfaceSize, SurfaceControl outBLASTSurfaceControl) {
         if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from "
                 + Binder.getCallingPid());
         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag);
@@ -199,7 +199,8 @@
                 requestedWidth, requestedHeight, viewFlags, flags, frameNumber,
                 outFrame, outContentInsets, outVisibleInsets,
                 outStableInsets, outBackdropFrame, cutout,
-                mergedConfiguration, outSurfaceControl, outInsetsState, outSurfaceSize);
+                mergedConfiguration, outSurfaceControl, outInsetsState, outSurfaceSize,
+                outBLASTSurfaceControl);
         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
         if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to "
                 + Binder.getCallingPid());
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 917b437..36cae1f 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -16,13 +16,13 @@
 
 package com.android.server.wm;
 
-import static android.app.ActivityTaskManager.INVALID_STACK_ID;
 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 import static android.app.ActivityTaskManager.RESIZE_MODE_FORCED;
 import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM;
 import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
 import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
@@ -59,6 +59,8 @@
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.SurfaceControl.METADATA_TASK_ID;
 
+import static com.android.internal.policy.DecorView.DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP;
+import static com.android.internal.policy.DecorView.DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
 import static com.android.server.am.TaskRecordProto.ACTIVITIES;
 import static com.android.server.am.TaskRecordProto.ACTIVITY_TYPE;
 import static com.android.server.am.TaskRecordProto.FULLSCREEN;
@@ -88,7 +90,7 @@
 import static com.android.server.wm.ActivityTaskManagerService.TAG_STACK;
 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
-import static com.android.server.wm.TaskProto.APP_WINDOW_TOKENS;
+import static com.android.server.wm.TaskProto.ACTIVITY;
 import static com.android.server.wm.TaskProto.DISPLAYED_BOUNDS;
 import static com.android.server.wm.TaskProto.FILLS_PARENT;
 import static com.android.server.wm.TaskProto.SURFACE_HEIGHT;
@@ -99,6 +101,7 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.WindowManagerService.dipToPixel;
 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
 
 import static java.lang.Integer.MAX_VALUE;
@@ -210,6 +213,8 @@
     static final int PERSIST_TASK_VERSION = 1;
 
     static final int INVALID_MIN_SIZE = -1;
+    private float mShadowRadius = 0;
+    private final Rect mLastSurfaceCrop = new Rect();
 
     /**
      * The modes to control how the stack is moved to the front when calling {@link Task#reparent}.
@@ -362,6 +367,7 @@
      * Display rotation as of the last time {@link #setBounds(Rect)} was called or this task was
      * moved to a new display.
      */
+    @Surface.Rotation
     private int mRotation;
 
     // For comparison with DisplayContent bounds.
@@ -496,7 +502,7 @@
     }
 
     class TaskToken extends RemoteToken {
-        TaskToken(ConfigurationContainer container) {
+        TaskToken(WindowContainer container) {
             super(container);
         }
 
@@ -1869,6 +1875,7 @@
         super.onConfigurationChanged(newParentConfig);
         if (wasInMultiWindowMode != inMultiWindowMode()) {
             mStackSupervisor.scheduleUpdateMultiWindowMode(this);
+            updateShadowsRadius(isFocused(), getPendingTransaction());
         }
 
         // If the configuration supports persistent bounds (eg. Freeform), keep track of the
@@ -2527,18 +2534,36 @@
                 ? getStack().getDisplayContent() : null;
         if (displayContent != null) {
             rotation = displayContent.getDisplayInfo().rotation;
-        } else if (bounds == null) {
-            return super.setBounds(bounds);
         }
 
         final int boundsChange = super.setBounds(bounds);
-
         mRotation = rotation;
-
         updateSurfacePosition();
         return boundsChange;
     }
 
+    private void updateSurfaceCrop() {
+        // Only update the crop if we are drawing shadows on the task.
+        if (mSurfaceControl == null || !mWmService.mRenderShadowsInCompositor) {
+            return;
+        }
+
+        if (inSplitScreenWindowingMode()) {
+            // inherit crop from parent
+            mTmpRect.setEmpty();
+        } else {
+            getBounds(mTmpRect);
+        }
+
+        mTmpRect.offsetTo(0, 0);
+        if (mLastSurfaceCrop.equals(mTmpRect)) {
+            return;
+        }
+
+        getPendingTransaction().setWindowCrop(mSurfaceControl, mTmpRect);
+        mLastSurfaceCrop.set(mTmpRect);
+    }
+
     @Override
     public boolean onDescendantOrientationChanged(IBinder freezeDisplayToken,
             ConfigurationContainer requestingContainer) {
@@ -2724,6 +2749,7 @@
             boolean[] foundTop = { false };
             final PooledConsumer c = PooledLambda.obtainConsumer(Task::getMaxVisibleBounds,
                     PooledLambda.__(ActivityRecord.class), out, foundTop);
+            forAllActivities(c);
             c.recycle();
             if (foundTop[0]) {
                 return;
@@ -3126,6 +3152,9 @@
         } else {
             mTmpDimBoundsRect.offsetTo(0, 0);
         }
+
+        updateSurfaceCrop();
+
         if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) {
             scheduleAnimation();
         }
@@ -3142,7 +3171,7 @@
         super.dumpDebug(proto, WINDOW_CONTAINER, logLevel);
         proto.write(TaskProto.ID, mTaskId);
         forAllActivities((r) -> {
-            r.dumpDebug(proto, APP_WINDOW_TOKENS, logLevel);
+            r.dumpDebug(proto, ACTIVITY);
         });
         proto.write(FILLS_PARENT, matchParentBounds());
         getBounds().dumpDebug(proto, TaskProto.BOUNDS);
@@ -3835,9 +3864,8 @@
     }
 
     boolean isControlledByTaskOrganizer() {
-        // TODO(b/147849315): Clean-up relationship between task-org and task-hierarchy. Ideally
-        //  we only give control of the root task.
-        return getTopMostTask().mTaskOrganizer != null;
+        final Task rootTask = getRootTask();
+        return rootTask == this && rootTask.mTaskOrganizer != null;
     }
 
     @Override
@@ -3909,20 +3937,57 @@
         super.getRelativeDisplayedPosition(outPos);
     }
 
-    @Override
-    public void setWindowingMode(int windowingMode) {
-        super.setWindowingMode(windowingMode);
-        windowingMode = getWindowingMode();
-
-        // TODO(b/147849315): Clean-up relationship between task-org and task-hierarchy. Ideally
-        //  we only give control of the root task.
-        // Different windowing modes may be managed by different task organizers. If
-        // getTaskOrganizer returns null, we still call transferToTaskOrganizer to make sure we
-        // clear it.
-        if (!isRootTask()) {
-            final ITaskOrganizer org =
-                    mAtmService.mTaskOrganizerController.getTaskOrganizer(windowingMode);
-            setTaskOrganizer(org);
+    /**
+     * @return true if the task is currently focused.
+     */
+    private boolean isFocused() {
+        if (mDisplayContent == null || mDisplayContent.mCurrentFocus == null) {
+            return false;
         }
+        return mDisplayContent.mCurrentFocus.getTask() == this;
+    }
+
+    /**
+     * @return the desired shadow radius in pixels for the current task.
+     */
+    private float getShadowRadius(boolean taskIsFocused) {
+        if (mDisplayContent == null) {
+            return 0;
+        }
+
+        if (inPinnedWindowingMode()) {
+            return dipToPixel(PINNED_WINDOWING_MODE_ELEVATION_IN_DIP,
+                    mDisplayContent.getDisplayMetrics());
+        }
+        if (inFreeformWindowingMode()) {
+            final int elevation = taskIsFocused
+                    ? DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP : DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
+            return dipToPixel(elevation, mDisplayContent.getDisplayMetrics());
+        }
+
+        // For all other windowing modes, do not draw a shadow.
+        return 0;
+    }
+
+    /**
+     * Update the length of the shadow if needed based on windowing mode and task focus state.
+     */
+    private void updateShadowsRadius(boolean taskIsFocused,
+            SurfaceControl.Transaction pendingTransaction) {
+        if (!mWmService.mRenderShadowsInCompositor) return;
+
+        final float newShadowRadius = getShadowRadius(taskIsFocused);
+        if (mShadowRadius != newShadowRadius) {
+            mShadowRadius = newShadowRadius;
+            pendingTransaction.setShadowRadius(getSurfaceControl(), mShadowRadius);
+        }
+    }
+
+    /**
+     * Called on the task of a window which gained or lost focus.
+     * @param hasFocus
+     */
+    void onWindowFocusChanged(boolean hasFocus) {
+        updateShadowsRadius(hasFocus, getPendingTransaction());
     }
 }
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 4cb5de4..10d6823 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -343,6 +343,7 @@
         builder.setPixelFormat(pixelFormat);
         builder.setIsTranslucent(isTranslucent);
         builder.setOrientation(activity.getTask().getConfiguration().orientation);
+        builder.setRotation(activity.getTask().getDisplayContent().getRotation());
         builder.setWindowingMode(task.getWindowingMode());
         builder.setSystemUiVisibility(getSystemUiVisibility(task));
         return true;
@@ -492,7 +493,8 @@
         return new TaskSnapshot(
                 System.currentTimeMillis() /* id */,
                 topChild.mActivityComponent, hwBitmap.createGraphicBufferHandle(),
-                hwBitmap.getColorSpace(), topChild.getTask().getConfiguration().orientation,
+                hwBitmap.getColorSpace(), mainWindow.getConfiguration().orientation,
+                mainWindow.getWindowConfiguration().getRotation(),
                 getInsets(mainWindow), ActivityManager.isLowRamDeviceStatic() /* reduced */,
                 mFullSnapshotScale, false /* isRealSnapshot */, task.getWindowingMode(),
                 getSystemUiVisibility(task), false);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
index 22c1ea5..6e9986f 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
@@ -102,8 +102,8 @@
             // For legacy snapshots, restore the scale based on the reduced resolution state
             final float legacyScale = reducedResolution ? mPersister.getReducedScale() : 1f;
             final float scale = Float.compare(proto.scale, 0f) != 0 ? proto.scale : legacyScale;
-            return new TaskSnapshot(proto.id, topActivityComponent, buffer,
-                    hwBitmap.getColorSpace(), proto.orientation,
+            return new TaskSnapshot(proto.id, topActivityComponent, buffer, hwBitmap.getColorSpace(),
+                    proto.orientation, proto.rotation,
                     new Rect(proto.insetLeft, proto.insetTop, proto.insetRight, proto.insetBottom),
                     reducedResolution, scale, proto.isRealSnapshot, proto.windowingMode,
                     proto.systemUiVisibility, proto.isTranslucent);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index 38a7000..ee5098b 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -52,7 +52,6 @@
     private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskSnapshotPersister" : TAG_WM;
     private static final String SNAPSHOTS_DIRNAME = "snapshots";
     private static final String REDUCED_POSTFIX = "_reduced";
-    private static final float REDUCED_SCALE = .5f;
     private static final float LOW_RAM_REDUCED_SCALE = .8f;
     static final boolean DISABLE_FULL_SIZED_BITMAPS = ActivityManager.isLowRamDeviceStatic();
     private static final long DELAY_MS = 100;
@@ -84,8 +83,13 @@
 
     TaskSnapshotPersister(WindowManagerService service, DirectoryResolver resolver) {
         mDirectoryResolver = resolver;
-        mReducedScale = ActivityManager.isLowRamDeviceStatic()
-                ? LOW_RAM_REDUCED_SCALE : REDUCED_SCALE;
+
+        if (ActivityManager.isLowRamDeviceStatic()) {
+            mReducedScale = LOW_RAM_REDUCED_SCALE;
+        } else {
+            mReducedScale = service.mContext.getResources().getFloat(
+                    com.android.internal.R.dimen.config_reducedTaskSnapshotScale);
+        }
         mUse16BitFormat = service.mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_use16BitTaskSnapshotPixelFormat);
     }
@@ -338,6 +342,7 @@
         boolean writeProto() {
             final TaskSnapshotProto proto = new TaskSnapshotProto();
             proto.orientation = mSnapshot.getOrientation();
+            proto.rotation = mSnapshot.getRotation();
             proto.insetLeft = mSnapshot.getContentInsets().left;
             proto.insetTop = mSnapshot.getContentInsets().top;
             proto.insetRight = mSnapshot.getContentInsets().right;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 57de753..e47eaee 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -116,7 +116,11 @@
     private static final String TAG = TAG_WITH_CLASS_NAME ? "SnapshotStartingWindow" : TAG_WM;
     private static final int MSG_REPORT_DRAW = 0;
     private static final String TITLE_FORMAT = "SnapshotStartingWindow for taskId=%s";
-    private static final Point sSurfaceSize = new Point(); //tmp var for unused relayout param
+
+    //tmp vars for unused relayout params
+    private static final Point sTmpSurfaceSize = new Point();
+    private static final SurfaceControl sTmpSurfaceControl = new SurfaceControl();
+
     private final Window mWindow;
     private final Surface mSurface;
     private SurfaceControl mSurfaceControl;
@@ -230,7 +234,7 @@
             session.relayout(window, window.mSeq, layoutParams, -1, -1, View.VISIBLE, 0, -1,
                     tmpFrame, tmpContentInsets, tmpRect, tmpStableInsets, tmpRect,
                     tmpCutout, tmpMergedConfiguration, surfaceControl, mTmpInsetsState,
-                    sSurfaceSize);
+                    sTmpSurfaceSize, sTmpSurfaceControl);
         } catch (RemoteException e) {
             // Local call.
         }
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 1c876d9..015b92c 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -61,6 +61,7 @@
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 import android.view.DisplayInfo;
+import android.view.IWindowContainer;
 import android.view.MagnificationSpec;
 import android.view.RemoteAnimationTarget;
 import android.view.SurfaceControl;
@@ -75,6 +76,7 @@
 import com.android.server.wm.SurfaceAnimator.Animatable;
 
 import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.LinkedList;
@@ -249,6 +251,12 @@
 
     private boolean mIsFocusable = true;
 
+    /**
+     * Used as a unique, cross-process identifier for this Container. It also serves a minimal
+     * interface to other processes.
+     */
+    RemoteToken mRemoteToken = null;
+
     WindowContainer(WindowManagerService wms) {
         mWmService = wms;
         mPendingTransaction = wms.mTransactionFactory.get();
@@ -860,13 +868,16 @@
         return false;
     }
 
-    @Override
+    /**
+     * Returns {@code true} if this container is focusable. Generally, if a parent is not focusable,
+     * this will not be focusable either.
+     */
     boolean isFocusable() {
-        return super.isFocusable() && mIsFocusable;
+        final WindowContainer parent = getParent();
+        return (parent == null || parent.isFocusable()) && mIsFocusable;
     }
 
     /** Set whether this container or its children can be focusable */
-    @Override
     boolean setFocusable(boolean focusable) {
         if (mIsFocusable == focusable) {
             return false;
@@ -1068,8 +1079,9 @@
             if (wc.fillsParent() || orientation != SCREEN_ORIENTATION_UNSPECIFIED) {
                 // Use the orientation if the container fills its parent or requested an explicit
                 // orientation that isn't SCREEN_ORIENTATION_UNSPECIFIED.
-                ProtoLog.v(WM_DEBUG_ORIENTATION, "%s is requesting orientation %d (%s)", toString(),
-                        orientation, ActivityInfo.screenOrientationToString(orientation));
+                ProtoLog.v(WM_DEBUG_ORIENTATION, "%s is requesting orientation %d (%s)",
+                        wc.toString(), orientation,
+                        ActivityInfo.screenOrientationToString(orientation));
                 return orientation;
             }
         }
@@ -2259,4 +2271,40 @@
     ActivityRecord asActivityRecord() {
         return null;
     }
+
+    RemoteToken getRemoteToken() {
+        return mRemoteToken;
+    }
+
+    static class RemoteToken extends IWindowContainer.Stub {
+        final WeakReference<WindowContainer> mWeakRef;
+
+        RemoteToken(WindowContainer container) {
+            mWeakRef = new WeakReference<>(container);
+        }
+
+        WindowContainer getContainer() {
+            return mWeakRef.get();
+        }
+
+        static RemoteToken fromBinder(IBinder binder) {
+            return (RemoteToken) binder;
+        }
+
+        @Override
+        public SurfaceControl getLeash() {
+            throw new RuntimeException("Not implemented");
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder(128);
+            sb.append("RemoteToken{");
+            sb.append(Integer.toHexString(System.identityHashCode(this)));
+            sb.append(' ');
+            sb.append(mWeakRef.get());
+            sb.append('}');
+            return sb.toString();
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 8d4ad28..2c6c756 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -39,6 +39,7 @@
 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_SIZECOMPAT_FREEFORM;
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS;
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES;
+import static android.provider.Settings.Global.DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.WindowManager.DOCKED_INVALID;
@@ -122,6 +123,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.app.ActivityManager;
 import android.app.ActivityManager.TaskSnapshot;
 import android.app.ActivityManagerInternal;
@@ -420,6 +422,11 @@
     int mVr2dDisplayId = INVALID_DISPLAY;
     boolean mVrModeEnabled = false;
 
+    /* If true, shadows drawn around the window will be rendered by the system compositor. If
+     * false, shadows will be drawn by the client by setting an elevation on the root view and
+     * the contents will be inset by the shadow radius. */
+    boolean mRenderShadowsInCompositor = false;
+
     /**
      * Tracks a map of input tokens to info that is used to decide whether to intercept
      * a key event.
@@ -721,6 +728,8 @@
                 DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES);
         private final Uri mSizeCompatFreeformUri = Settings.Global.getUriFor(
                 DEVELOPMENT_ENABLE_SIZECOMPAT_FREEFORM);
+        private final Uri mRenderShadowsInCompositorUri = Settings.Global.getUriFor(
+                DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR);
 
         public SettingsObserver() {
             super(new Handler());
@@ -743,6 +752,8 @@
             resolver.registerContentObserver(mForceResizableUri, false, this, UserHandle.USER_ALL);
             resolver.registerContentObserver(mSizeCompatFreeformUri, false, this,
                     UserHandle.USER_ALL);
+            resolver.registerContentObserver(mRenderShadowsInCompositorUri, false, this,
+                    UserHandle.USER_ALL);
         }
 
         @Override
@@ -781,6 +792,11 @@
                 return;
             }
 
+            if (mRenderShadowsInCompositorUri.equals(uri)) {
+                setShadowRenderer();
+                return;
+            }
+
             @UpdateAnimationScaleMode
             final int mode;
             if (mWindowAnimationScaleUri.equals(uri)) {
@@ -862,6 +878,11 @@
         }
     }
 
+    private void setShadowRenderer() {
+        mRenderShadowsInCompositor = Settings.Global.getInt(mContext.getContentResolver(),
+                DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR, 0) != 0;
+    }
+
     PowerManager mPowerManager;
     PowerManagerInternal mPowerManagerInternal;
 
@@ -1248,6 +1269,7 @@
         float[] spotColor = {0.f, 0.f, 0.f, spotShadowAlpha};
         SurfaceControl.setGlobalShadowSettings(ambientColor, spotColor, lightY, lightZ,
                 lightRadius);
+        setShadowRenderer();
     }
 
     /**
@@ -2049,7 +2071,7 @@
             Rect outVisibleInsets, Rect outStableInsets, Rect outBackdropFrame,
             DisplayCutout.ParcelableWrapper outCutout, MergedConfiguration mergedConfiguration,
             SurfaceControl outSurfaceControl, InsetsState outInsetsState,
-            Point outSurfaceSize) {
+            Point outSurfaceSize, SurfaceControl outBLASTSurfaceControl) {
         int result = 0;
         boolean configChanged;
         final int pid = Binder.getCallingPid();
@@ -2216,7 +2238,8 @@
                 result = win.relayoutVisibleWindow(result, attrChanges);
 
                 try {
-                    result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);
+                    result = createSurfaceControl(outSurfaceControl, outBLASTSurfaceControl,
+                            result, win, winAnimator);
                 } catch (Exception e) {
                     displayContent.getInputMonitor().updateInputWindowsLw(true /*force*/);
 
@@ -2248,6 +2271,7 @@
                     // surface, let the client use that, but don't create new surface at this point.
                     Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: getSurface");
                     winAnimator.mSurfaceController.getSurfaceControl(outSurfaceControl);
+                    winAnimator.mSurfaceController.getBLASTSurfaceControl(outBLASTSurfaceControl);
                     Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
                 } else {
                     if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Releasing surface in: " + win);
@@ -2429,7 +2453,8 @@
     }
 
     private int createSurfaceControl(SurfaceControl outSurfaceControl,
-            int result, WindowState win, WindowStateAnimator winAnimator) {
+            SurfaceControl outBLASTSurfaceControl, int result,
+            WindowState win, WindowStateAnimator winAnimator) {
         if (!win.mHasSurface) {
             result |= RELAYOUT_RES_SURFACE_CHANGED;
         }
@@ -2443,6 +2468,7 @@
         }
         if (surfaceController != null) {
             surfaceController.getSurfaceControl(outSurfaceControl);
+            surfaceController.getBLASTSurfaceControl(outBLASTSurfaceControl);
             ProtoLog.i(WM_SHOW_TRANSACTIONS, "OUT SURFACE %s: copied", outSurfaceControl);
 
         } else {
@@ -2996,7 +3022,13 @@
         }
     }
 
-    void showGlobalActions() {
+    @RequiresPermission(Manifest.permission.INTERNAL_SYSTEM_WINDOW)
+    @Override
+    public void showGlobalActions() {
+        if (!checkCallingPermission(Manifest.permission.INTERNAL_SYSTEM_WINDOW,
+                "showGlobalActions()")) {
+            throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
+        }
         mPolicy.showGlobalActions();
     }
 
@@ -7004,15 +7036,6 @@
         mPolicy.registerShortcutKey(shortcutCode, shortcutKeyReceiver);
     }
 
-    @Override
-    public void requestUserActivityNotification() {
-        if (!checkCallingPermission(android.Manifest.permission.USER_ACTIVITY,
-                "requestUserActivityNotification()")) {
-            throw new SecurityException("Requires USER_ACTIVITY permission");
-        }
-        mPolicy.requestUserActivityNotification();
-    }
-
     private final class LocalService extends WindowManagerInternal {
 
         @Override
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 73984fd..b9694c3 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -5616,4 +5616,8 @@
     boolean isNonToastWindowVisibleForPid(int pid) {
         return mSession.mPid == pid && isNonToastOrStarting() && isVisibleNow();
     }
+
+    SurfaceControl getDeferTransactionBarrier() {
+        return mWinAnimator.getDeferTransactionBarrier();
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 069ee4f..9552df7 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1010,7 +1010,7 @@
                         // the WS position is reset (so the stack position is shown) at the same
                         // time that the buffer size changes.
                         setOffsetPositionForStackResize(false);
-                        mSurfaceController.deferTransactionUntil(mSurfaceController.mSurfaceControl,
+                        mSurfaceController.deferTransactionUntil(mWin.getDeferTransactionBarrier(),
                                 mWin.getFrameNumber());
                     } else {
                         final ActivityStack stack = mWin.getRootTask();
@@ -1041,7 +1041,7 @@
         // comes in at the new size (normally position and crop are unfrozen).
         // deferTransactionUntil accomplishes this for us.
         if (wasForceScaled && !mForceScaleUntilResize) {
-            mSurfaceController.deferTransactionUntil(mSurfaceController.mSurfaceControl,
+            mSurfaceController.deferTransactionUntil(mWin.getDeferTransactionBarrier(),
                     mWin.getFrameNumber());
             mSurfaceController.forceScaleableInTransaction(false);
         }
@@ -1518,4 +1518,11 @@
     void setOffsetPositionForStackResize(boolean offsetPositionForStackResize) {
         mOffsetPositionForStackResize = offsetPositionForStackResize;
     }
+
+    SurfaceControl getDeferTransactionBarrier() {
+        if (!hasSurface()) {
+            return null;
+        }
+        return mSurfaceController.getDeferTransactionBarrier();
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 5b8015b..383c0d9 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -51,6 +51,11 @@
 
     SurfaceControl mSurfaceControl;
 
+    /**
+     * WM only uses for deferred transactions.
+     */
+    SurfaceControl mBLASTSurfaceControl;
+
     // Should only be set from within setShown().
     private boolean mSurfaceShown = false;
     private float mSurfaceX = 0;
@@ -110,13 +115,22 @@
                 .setMetadata(METADATA_WINDOW_TYPE, windowType)
                 .setMetadata(METADATA_OWNER_UID, ownerUid);
 
-        if ((win.getAttrs().privateFlags &
-                WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST) != 0) {
+        final boolean useBLAST = (win.getAttrs().privateFlags &
+                WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST) != 0;
+        if (useBLAST) {
             b.setContainerLayer();
         }
 
-
         mSurfaceControl = b.build();
+
+        if (useBLAST) {
+            mBLASTSurfaceControl = win.makeSurface()
+                .setParent(mSurfaceControl)
+                .setName("BLAST Adapter Layer")
+                .setBLASTLayer()
+                .build();
+        }
+
         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
     }
 
@@ -168,6 +182,9 @@
         } finally {
             setShown(false);
             mSurfaceControl = null;
+            if (mBLASTSurfaceControl != null) {
+                mBLASTSurfaceControl.release();
+            }
         }
     }
 
@@ -474,6 +491,12 @@
         outSurfaceControl.copyFrom(mSurfaceControl);
     }
 
+    void getBLASTSurfaceControl(SurfaceControl outSurfaceControl) {
+        if (mBLASTSurfaceControl != null) {
+            outSurfaceControl.copyFrom(mBLASTSurfaceControl);
+        }
+    }
+
     int getLayer() {
         return mSurfaceLayer;
     }
@@ -510,6 +533,13 @@
         return mSurfaceH;
     }
 
+    SurfaceControl getDeferTransactionBarrier() {
+        if (mBLASTSurfaceControl != null) {
+            return mBLASTSurfaceControl;
+        }
+        return mSurfaceControl;
+    }
+
     void dumpDebug(ProtoOutputStream proto, long fieldId) {
         final long token = proto.start(fieldId);
         proto.write(SHOWN, mSurfaceShown);
diff --git a/services/core/java/com/android/server/wm/WindowTracing.java b/services/core/java/com/android/server/wm/WindowTracing.java
index 0be90fc..ba3dc60 100644
--- a/services/core/java/com/android/server/wm/WindowTracing.java
+++ b/services/core/java/com/android/server/wm/WindowTracing.java
@@ -35,7 +35,7 @@
 import android.view.Choreographer;
 
 import com.android.server.protolog.ProtoLogImpl;
-import com.android.server.utils.TraceBuffer;
+import com.android.internal.util.TraceBuffer;
 
 import java.io.File;
 import java.io.IOException;
@@ -64,7 +64,7 @@
 
     private final Object mEnabledLock = new Object();
     private final File mTraceFile;
-    private final com.android.server.utils.TraceBuffer mBuffer;
+    private final TraceBuffer mBuffer;
     private final Choreographer.FrameCallback mFrameCallback = (frameTimeNanos) ->
             log("onFrame" /* where */);
 
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 77d814e..4a2636e 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -14,6 +14,7 @@
 
     srcs: [
         ":graphicsstats_proto",
+        ":lib_alarmManagerService_native",
         "BroadcastRadio/JavaRef.cpp",
         "BroadcastRadio/NativeCallbackThread.cpp",
         "BroadcastRadio/BroadcastRadioService.cpp",
@@ -21,7 +22,6 @@
         "BroadcastRadio/TunerCallback.cpp",
         "BroadcastRadio/convert.cpp",
         "BroadcastRadio/regions.cpp",
-        "com_android_server_AlarmManagerService.cpp",
         "com_android_server_am_BatteryStatsService.cpp",
         "com_android_server_connectivity_Vpn.cpp",
         "com_android_server_ConsumerIrService.cpp",
@@ -182,3 +182,10 @@
         "com_android_server_net_NetworkStatsFactory.cpp",
     ],
 }
+
+filegroup {
+    name: "lib_alarmManagerService_native",
+    srcs: [
+        "com_android_server_AlarmManagerService.cpp",
+    ],
+}
diff --git a/services/core/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_VibratorService.cpp
index 6811e6d..5a8e25e4 100644
--- a/services/core/jni/com_android_server_VibratorService.cpp
+++ b/services/core/jni/com_android_server_VibratorService.cpp
@@ -49,6 +49,12 @@
 
 static jmethodID sMethodIdOnComplete;
 
+static struct {
+    jfieldID id;
+    jfieldID scale;
+    jfieldID delay;
+} gPrimitiveClassInfo;
+
 static_assert(static_cast<uint8_t>(V1_0::EffectStrength::LIGHT) ==
                 static_cast<uint8_t>(aidl::EffectStrength::LIGHT));
 static_assert(static_cast<uint8_t>(V1_0::EffectStrength::MEDIUM) ==
@@ -333,6 +339,21 @@
     }
 }
 
+static jintArray vibratorGetSupportedEffects(JNIEnv *env, jclass) {
+    if (auto hal = getHal<aidl::IVibrator>()) {
+        std::vector<aidl::Effect> supportedEffects;
+        if (!hal->call(&aidl::IVibrator::getSupportedEffects, &supportedEffects).isOk()) {
+            return nullptr;
+        }
+        jintArray arr = env->NewIntArray(supportedEffects.size());
+        env->SetIntArrayRegion(arr, 0, supportedEffects.size(),
+                reinterpret_cast<jint*>(supportedEffects.data()));
+        return arr;
+    } else {
+        return nullptr;
+    }
+}
+
 static jlong vibratorPerformEffect(JNIEnv* env, jclass, jlong effect, jlong strength,
                                    jobject vibration) {
     if (auto hal = getHal<aidl::IVibrator>()) {
@@ -398,6 +419,37 @@
     return -1;
 }
 
+static aidl::CompositeEffect effectFromJavaPrimitive(JNIEnv* env, jobject primitive) {
+    aidl::CompositeEffect effect;
+    effect.primitive = static_cast<aidl::CompositePrimitive>(
+            env->GetIntField(primitive, gPrimitiveClassInfo.id));
+    effect.scale = static_cast<float>(env->GetFloatField(primitive, gPrimitiveClassInfo.scale));
+    effect.delayMs = static_cast<int>(env->GetIntField(primitive, gPrimitiveClassInfo.delay));
+    return effect;
+}
+
+static void vibratorPerformComposedEffect(JNIEnv* env, jclass, jobjectArray composition,
+                                   jobject vibration) {
+    auto hal = getHal<aidl::IVibrator>();
+    if (!hal) {
+        return;
+    }
+    size_t size = env->GetArrayLength(composition);
+    std::vector<aidl::CompositeEffect> effects;
+    for (size_t i = 0; i < size; i++) {
+        jobject element = env->GetObjectArrayElement(composition, i);
+        effects.push_back(effectFromJavaPrimitive(env, element));
+    }
+    sp<AidlVibratorCallback> effectCallback = new AidlVibratorCallback(env, vibration);
+
+    auto status = hal->call(&aidl::IVibrator::compose, effects, effectCallback);
+    if (!status.isOk()) {
+        if (status.exceptionCode() != binder::Status::EX_UNSUPPORTED_OPERATION) {
+            ALOGE("Failed to play haptic effect composition");
+        }
+    }
+}
+
 static jlong vibratorGetCapabilities(JNIEnv*, jclass) {
     if (auto hal = getHal<aidl::IVibrator>()) {
         int32_t cap = 0;
@@ -433,7 +485,12 @@
     { "vibratorSupportsAmplitudeControl", "()Z", (void*)vibratorSupportsAmplitudeControl},
     { "vibratorSetAmplitude", "(I)V", (void*)vibratorSetAmplitude},
     { "vibratorPerformEffect", "(JJLcom/android/server/VibratorService$Vibration;)J",
-        (void*)vibratorPerformEffect},
+            (void*)vibratorPerformEffect},
+    { "vibratorPerformComposedEffect",
+            "([Landroid/os/VibrationEffect$Composition$PrimitiveEffect;Lcom/android/server/VibratorService$Vibration;)V",
+            (void*)vibratorPerformComposedEffect},
+    { "vibratorGetSupportedEffects", "()[I",
+            (void*)vibratorGetSupportedEffects},
     { "vibratorSupportsExternalControl", "()Z", (void*)vibratorSupportsExternalControl},
     { "vibratorSetExternalControl", "(Z)V", (void*)vibratorSetExternalControl},
     { "vibratorGetCapabilities", "()J", (void*)vibratorGetCapabilities},
@@ -441,11 +498,15 @@
     { "vibratorAlwaysOnDisable", "(J)V", (void*)vibratorAlwaysOnDisable},
 };
 
-int register_android_server_VibratorService(JNIEnv *env)
-{
+int register_android_server_VibratorService(JNIEnv *env) {
     sMethodIdOnComplete = GetMethodIDOrDie(env,
             FindClassOrDie(env, "com/android/server/VibratorService$Vibration"),
             "onComplete", "()V");
+    jclass primitiveClass = FindClassOrDie(env,
+            "android/os/VibrationEffect$Composition$PrimitiveEffect");
+    gPrimitiveClassInfo.id = GetFieldIDOrDie(env, primitiveClass, "id", "I");
+    gPrimitiveClassInfo.scale = GetFieldIDOrDie(env, primitiveClass, "scale", "F");
+    gPrimitiveClassInfo.delay = GetFieldIDOrDie(env, primitiveClass, "delay", "I");
     return jniRegisterNativeMethods(env, "com/android/server/VibratorService",
             method_table, NELEM(method_table));
 }
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index c0891d7..212a3a6 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -312,7 +312,6 @@
     void updateInactivityTimeoutLocked();
     void handleInterceptActions(jint wmActions, nsecs_t when, uint32_t& policyFlags);
     void ensureSpriteControllerLocked();
-    const DisplayViewport* findDisplayViewportLocked(int32_t displayId);
     int32_t getPointerDisplayId();
     void updatePointerDisplayLocked();
     static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
@@ -390,16 +389,6 @@
     return false;
 }
 
-const DisplayViewport* NativeInputManager::findDisplayViewportLocked(int32_t displayId)
-        REQUIRES(mLock) {
-    for (const DisplayViewport& v : mLocked.viewports) {
-        if (v.displayId == displayId) {
-            return &v;
-        }
-    }
-    return nullptr;
-}
-
 void NativeInputManager::setDisplayViewports(JNIEnv* env, jobjectArray viewportObjArray) {
     std::vector<DisplayViewport> viewports;
 
@@ -547,6 +536,8 @@
 
         outConfig->setDisplayViewports(mLocked.viewports);
 
+        outConfig->defaultPointerDisplayId = mLocked.pointerDisplayId;
+
         outConfig->disabledDevices = mLocked.disabledInputDevices;
     } // release lock
 }
@@ -564,8 +555,6 @@
         updateInactivityTimeoutLocked();
     }
 
-    updatePointerDisplayLocked();
-
     return controller;
 }
 
@@ -580,23 +569,6 @@
     return pointerDisplayId;
 }
 
-void NativeInputManager::updatePointerDisplayLocked() REQUIRES(mLock) {
-    ATRACE_CALL();
-
-    sp<PointerController> controller = mLocked.pointerController.promote();
-    if (controller != nullptr) {
-        const DisplayViewport* viewport = findDisplayViewportLocked(mLocked.pointerDisplayId);
-        if (viewport == nullptr) {
-            ALOGW("Can't find pointer display viewport, fallback to default display.");
-            viewport = findDisplayViewportLocked(ADISPLAY_ID_DEFAULT);
-        }
-
-        if (viewport != nullptr) {
-            controller->setDisplayViewport(*viewport);
-        }
-    }
-}
-
 void NativeInputManager::ensureSpriteControllerLocked() REQUIRES(mLock) {
     if (mLocked.spriteController == nullptr) {
         JNIEnv* env = jniEnv();
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 00436bb..12de20c 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -28,6 +28,7 @@
 #include <android/hardware/gnss/2.0/IGnssMeasurement.h>
 #include <android/hardware/gnss/2.1/IGnssMeasurement.h>
 #include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrections.h>
+#include <android/hardware/gnss/measurement_corrections/1.1/IMeasurementCorrections.h>
 #include <android/hardware/gnss/visibility_control/1.0/IGnssVisibilityControl.h>
 #include <nativehelper/JNIHelp.h>
 #include "jni.h"
@@ -88,6 +89,9 @@
 static jmethodID method_correctionsGetVerPosUncMeters;
 static jmethodID method_correctionsGetToaGpsNanosecondsOfWeek;
 static jmethodID method_correctionsGetSingleSatCorrectionList;
+static jmethodID method_correctionsHasEnvironmentBearing;
+static jmethodID method_correctionsGetEnvironmentBearingDegrees;
+static jmethodID method_correctionsGetEnvironmentBearingUncertaintyDegrees;
 static jmethodID method_listSize;
 static jmethodID method_correctionListGet;
 static jmethodID method_correctionSatFlags;
@@ -142,7 +146,9 @@
 
 using android::hardware::gnss::V2_0::ElapsedRealtimeFlags;
 
-using android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections;
+using MeasurementCorrections_V1_0 = android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections;
+using MeasurementCorrections_V1_1 = android::hardware::gnss::measurement_corrections::V1_1::MeasurementCorrections;
+
 using android::hardware::gnss::measurement_corrections::V1_0::SingleSatCorrection;
 using android::hardware::gnss::measurement_corrections::V1_0::ReflectingPlane;
 
@@ -184,7 +190,8 @@
 using IGnssBatchingCallback_V1_0 = android::hardware::gnss::V1_0::IGnssBatchingCallback;
 using IGnssBatchingCallback_V2_0 = android::hardware::gnss::V2_0::IGnssBatchingCallback;
 
-using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections;
+using IMeasurementCorrections_V1_0 = android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections;
+using IMeasurementCorrections_V1_1 = android::hardware::gnss::measurement_corrections::V1_1::IMeasurementCorrections;
 using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrectionsCallback;
 using android::hardware::gnss::measurement_corrections::V1_0::GnssSingleSatCorrectionFlags;
 
@@ -231,7 +238,8 @@
 sp<IGnssMeasurement_V2_0> gnssMeasurementIface_V2_0 = nullptr;
 sp<IGnssMeasurement_V2_1> gnssMeasurementIface_V2_1 = nullptr;
 sp<IGnssNavigationMessage> gnssNavigationMessageIface = nullptr;
-sp<IMeasurementCorrections> gnssCorrectionsIface = nullptr;
+sp<IMeasurementCorrections_V1_0> gnssCorrectionsIface_V1_0 = nullptr;
+sp<IMeasurementCorrections_V1_1> gnssCorrectionsIface_V1_1 = nullptr;
 sp<IGnssVisibilityControl> gnssVisibilityControlIface = nullptr;
 
 #define WAKE_LOCK_NAME  "GPS"
@@ -1208,6 +1216,22 @@
     translateSingleGnssMeasurement(&(measurement_V2_1->v2_0), object);
 
     SET(BasebandCn0DbHz, measurement_V2_1->basebandCN0DbHz);
+
+    if (measurement_V2_1->flags & GnssMeasurementFlags::HAS_RECEIVER_ISB) {
+        SET(ReceiverInterSignalBiasNs, measurement_V2_1->receiverInterSignalBiasNs);
+    }
+
+    if (measurement_V2_1->flags & GnssMeasurementFlags::HAS_RECEIVER_ISB_UNCERTAINTY) {
+        SET(ReceiverInterSignalBiasUncertaintyNs, measurement_V2_1->receiverInterSignalBiasUncertaintyNs);
+    }
+
+    if (measurement_V2_1->flags & GnssMeasurementFlags::HAS_SATELLITE_ISB) {
+        SET(SatelliteInterSignalBiasNs, measurement_V2_1->satelliteInterSignalBiasNs);
+    }
+
+    if (measurement_V2_1->flags & GnssMeasurementFlags::HAS_SATELLITE_ISB_UNCERTAINTY) {
+        SET(SatelliteInterSignalBiasUncertaintyNs, measurement_V2_1->satelliteInterSignalBiasUncertaintyNs);
+    }
 }
 
 template<class T>
@@ -1253,6 +1277,19 @@
 
 template<>
 void GnssMeasurementCallback::translateGnssClock(
+       JavaObject& object, const IGnssMeasurementCallback_V2_1::GnssClock& clock) {
+    JNIEnv* env = getJniEnv();
+    SET(ReferenceConstellationTypeForIsb,
+            static_cast<int32_t>(clock.referenceSignalTypeForIsb.constellation));
+    SET(ReferenceCarrierFrequencyHzForIsb, clock.referenceSignalTypeForIsb.carrierFrequencyHz);
+    SET(ReferenceCodeTypeForIsb,
+            env->NewStringUTF(clock.referenceSignalTypeForIsb.codeType.c_str()));
+
+    translateGnssClock(object, clock.v1_0);
+}
+
+template<>
+void GnssMeasurementCallback::translateGnssClock(
        JavaObject& object, const IGnssMeasurementCallback_V2_0::GnssData& data) {
     auto elapsedRealtime = data.elapsedRealtime;
     uint16_t flags = static_cast<uint16_t>(elapsedRealtime.flags);
@@ -1265,6 +1302,20 @@
     translateGnssClock(object, data.clock);
 }
 
+template<>
+void GnssMeasurementCallback::translateGnssClock(
+       JavaObject& object, const IGnssMeasurementCallback_V2_1::GnssData& data) {
+    auto elapsedRealtime = data.elapsedRealtime;
+    uint16_t flags = static_cast<uint16_t>(elapsedRealtime.flags);
+    if (flags & ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) {
+        SET(ElapsedRealtimeNanos, static_cast<uint64_t>(elapsedRealtime.timestampNs));
+    }
+    if (flags & ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS) {
+        SET(ElapsedRealtimeUncertaintyNanos, static_cast<double>(elapsedRealtime.timeUncertaintyNs));
+    }
+    translateGnssClock(object, data.clock);
+}
+
 template<class T>
 jobjectArray GnssMeasurementCallback::translateAllGnssMeasurements(JNIEnv* env,
         const T* measurements,
@@ -1692,6 +1743,13 @@
     method_correctionsGetSingleSatCorrectionList = env->GetMethodID(
             measCorrClass, "getSingleSatelliteCorrectionList", "()Ljava/util/List;");
 
+    method_correctionsHasEnvironmentBearing = env->GetMethodID(
+            measCorrClass, "hasEnvironmentBearing", "()Z");
+    method_correctionsGetEnvironmentBearingDegrees = env->GetMethodID(
+            measCorrClass, "getEnvironmentBearingDegrees", "()F");
+    method_correctionsGetEnvironmentBearingUncertaintyDegrees = env->GetMethodID(
+            measCorrClass, "getEnvironmentBearingUncertaintyDegrees", "()F");
+
     jclass corrListClass = env->FindClass("java/util/List");
     method_listSize = env->GetMethodID(corrListClass, "size", "()I");
     method_correctionListGet = env->GetMethodID(corrListClass, "get", "(I)Ljava/lang/Object;");
@@ -1874,12 +1932,20 @@
          }
     }
 
-    if (gnssHal_V2_0 != nullptr) {
+    if (gnssHal_V2_1 != nullptr) {
+        auto gnssCorrections = gnssHal_V2_1->getExtensionMeasurementCorrections_1_1();
+        if (!gnssCorrections.isOk()) {
+            ALOGD("Unable to get a handle to GnssMeasurementCorrections 1.1 interface");
+        } else {
+            gnssCorrectionsIface_V1_1 = gnssCorrections;
+            gnssCorrectionsIface_V1_0 = gnssCorrectionsIface_V1_1;
+        }
+    } else if (gnssHal_V2_0 != nullptr) {
         auto gnssCorrections = gnssHal_V2_0->getExtensionMeasurementCorrections();
         if (!gnssCorrections.isOk()) {
             ALOGD("Unable to get a handle to GnssMeasurementCorrections interface");
         } else {
-            gnssCorrectionsIface = gnssCorrections;
+            gnssCorrectionsIface_V1_0 = gnssCorrections;
         }
     }
 
@@ -2110,11 +2176,18 @@
     }
 
     // Set IMeasurementCorrections.hal callback.
-    if (gnssCorrectionsIface != nullptr) {
+    if (gnssCorrectionsIface_V1_1 != nullptr) {
+            sp<IMeasurementCorrectionsCallback> gnssCorrectionsIfaceCbIface =
+                    new MeasurementCorrectionsCallback();
+            result = gnssCorrectionsIface_V1_1->setCallback(gnssCorrectionsIfaceCbIface);
+            checkHidlReturn(result, "IMeasurementCorrections 1.1 setCallback() failed.");
+    } else if (gnssCorrectionsIface_V1_0 != nullptr) {
         sp<IMeasurementCorrectionsCallback> gnssCorrectionsIfaceCbIface =
                 new MeasurementCorrectionsCallback();
-        result = gnssCorrectionsIface->setCallback(gnssCorrectionsIfaceCbIface);
-        checkHidlReturn(result, "IMeasurementCorrections setCallback() failed.");
+        result = gnssCorrectionsIface_V1_0->setCallback(gnssCorrectionsIfaceCbIface);
+        checkHidlReturn(result, "IMeasurementCorrections 1.0 setCallback() failed.");
+    } else {
+        ALOGI("Unable to find IMeasurementCorrections.");
     }
 
     return JNI_TRUE;
@@ -2717,7 +2790,7 @@
 static jboolean
     android_location_GnssMeasurementCorrectionsProvider_is_measurement_corrections_supported(
     JNIEnv* env, jclass clazz) {
-    if (gnssCorrectionsIface != nullptr) {
+    if (gnssCorrectionsIface_V1_0 != nullptr || gnssCorrectionsIface_V1_1 != nullptr) {
         return JNI_TRUE;
     }
 
@@ -2730,24 +2803,12 @@
         jobject obj /* clazz*/,
         jobject correctionsObj) {
 
-    if (gnssCorrectionsIface == nullptr) {
+    if (gnssCorrectionsIface_V1_0 == nullptr && gnssCorrectionsIface_V1_1 == nullptr) {
         ALOGW("Trying to inject GNSS measurement corrections on a chipset that does not"
             " support them.");
         return JNI_FALSE;
     }
 
-    jdouble latitudeDegreesCorr = env->CallDoubleMethod(
-        correctionsObj, method_correctionsGetLatitudeDegrees);
-    jdouble longitudeDegreesCorr = env->CallDoubleMethod(
-        correctionsObj, method_correctionsGetLongitudeDegrees);
-    jdouble altitudeDegreesCorr = env->CallDoubleMethod(
-        correctionsObj, method_correctionsGetAltitudeMeters);
-    jdouble horizontalPositionUncertaintyMeters = env->CallDoubleMethod(
-        correctionsObj, method_correctionsGetHorPosUncMeters);
-    jdouble verticalPositionUncertaintyMeters = env->CallDoubleMethod(
-            correctionsObj, method_correctionsGetVerPosUncMeters);
-    jlong toaGpsNanosOfWeek = env->CallLongMethod(
-        correctionsObj, method_correctionsGetToaGpsNanosecondsOfWeek);
     jobject singleSatCorrectionList = env->CallObjectMethod(correctionsObj,
         method_correctionsGetSingleSatCorrectionList);
 
@@ -2816,7 +2877,21 @@
         };
         list[i] = singleSatCorrection;
     }
-    MeasurementCorrections measurementCorrections = {
+
+    jdouble latitudeDegreesCorr = env->CallDoubleMethod(
+        correctionsObj, method_correctionsGetLatitudeDegrees);
+    jdouble longitudeDegreesCorr = env->CallDoubleMethod(
+        correctionsObj, method_correctionsGetLongitudeDegrees);
+    jdouble altitudeDegreesCorr = env->CallDoubleMethod(
+        correctionsObj, method_correctionsGetAltitudeMeters);
+    jdouble horizontalPositionUncertaintyMeters = env->CallDoubleMethod(
+        correctionsObj, method_correctionsGetHorPosUncMeters);
+    jdouble verticalPositionUncertaintyMeters = env->CallDoubleMethod(
+            correctionsObj, method_correctionsGetVerPosUncMeters);
+    jlong toaGpsNanosOfWeek = env->CallLongMethod(
+        correctionsObj, method_correctionsGetToaGpsNanosecondsOfWeek);
+
+    MeasurementCorrections_V1_0 measurementCorrections_1_0 = {
         .latitudeDegrees = latitudeDegreesCorr,
         .longitudeDegrees = longitudeDegreesCorr,
         .altitudeMeters = altitudeDegreesCorr,
@@ -2826,8 +2901,28 @@
         .satCorrections = list,
     };
 
-    auto result = gnssCorrectionsIface->setCorrections(measurementCorrections);
-    return checkHidlReturn(result, "IMeasurementCorrections setCorrections() failed.");
+    if (gnssCorrectionsIface_V1_1 != nullptr) {
+
+        jboolean hasEnvironmentBearingCorr = env->CallBooleanMethod(
+            correctionsObj, method_correctionsHasEnvironmentBearing);
+        jfloat environmentBearingDegreesCorr = env->CallFloatMethod(
+            correctionsObj, method_correctionsGetEnvironmentBearingDegrees);
+        jfloat environmentBearingUncertaintyDegreesCorr = env->CallFloatMethod(
+            correctionsObj, method_correctionsGetEnvironmentBearingUncertaintyDegrees);
+
+        MeasurementCorrections_V1_1 measurementCorrections_1_1 = {
+            .v1_0 = measurementCorrections_1_0,
+            .hasEnvironmentBearing = static_cast<bool>(hasEnvironmentBearingCorr),
+            .environmentBearingDegrees = environmentBearingDegreesCorr,
+            .environmentBearingUncertaintyDegrees = environmentBearingUncertaintyDegreesCorr,
+        };
+
+        auto result = gnssCorrectionsIface_V1_1->setCorrections_1_1(measurementCorrections_1_1);
+        return checkHidlReturn(result, "IMeasurementCorrections 1.1 setCorrections() failed.");
+    }
+
+    auto result = gnssCorrectionsIface_V1_0->setCorrections(measurementCorrections_1_0);
+    return checkHidlReturn(result, "IMeasurementCorrections 1.0 setCorrections() failed.");
 }
 
 static jboolean android_location_GnssNavigationMessageProvider_is_navigation_message_supported(
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
index 43ee97d..9b85a7b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
@@ -75,4 +75,11 @@
 
     public void setPersonalAppsSuspended(ComponentName admin, boolean suspended) {
     }
+
+    public void setManagedProfileMaximumTimeOff(ComponentName admin, long timeoutMs) {
+    }
+
+    public long getManagedProfileMaximumTimeOff(ComponentName admin) {
+        return 0;
+    }
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 0171582..d7ea2f5 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -67,6 +67,9 @@
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+import static android.app.admin.DevicePolicyManager.PERSONAL_APPS_NOT_SUSPENDED;
+import static android.app.admin.DevicePolicyManager.PERSONAL_APPS_SUSPENDED_EXPLICITLY;
+import static android.app.admin.DevicePolicyManager.PERSONAL_APPS_SUSPENDED_PROFILE_TIMEOUT;
 import static android.app.admin.DevicePolicyManager.PRIVATE_DNS_MODE_OFF;
 import static android.app.admin.DevicePolicyManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
 import static android.app.admin.DevicePolicyManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
@@ -177,6 +180,7 @@
 import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.location.LocationManager;
+import android.location.LocationManagerInternal;
 import android.media.AudioManager;
 import android.media.IAudioService;
 import android.net.ConnectivityManager;
@@ -315,7 +319,6 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Function;
-import java.util.stream.Collectors;
 
 /**
  * Implementation of the device policy APIs.
@@ -378,16 +381,21 @@
 
     private static final String TAG_SECONDARY_LOCK_SCREEN = "secondary-lock-screen";
 
-    private static final String TAG_PERSONAL_APPS_SUSPENDED = "personal-apps-suspended";
+    private static final String TAG_APPS_SUSPENDED = "apps-suspended";
 
     private static final int REQUEST_EXPIRE_PASSWORD = 5571;
 
+    private static final int REQUEST_PROFILE_OFF_DEADLINE = 5572;
+
     private static final long MS_PER_DAY = TimeUnit.DAYS.toMillis(1);
 
     private static final long EXPIRATION_GRACE_PERIOD_MS = 5 * MS_PER_DAY; // 5 days, in ms
 
-    private static final String ACTION_EXPIRED_PASSWORD_NOTIFICATION
-            = "com.android.server.ACTION_EXPIRED_PASSWORD_NOTIFICATION";
+    private static final String ACTION_EXPIRED_PASSWORD_NOTIFICATION =
+            "com.android.server.ACTION_EXPIRED_PASSWORD_NOTIFICATION";
+
+    private static final String ACTION_PROFILE_OFF_DEADLINE =
+            "com.android.server.ACTION_PROFILE_OFF_DEADLINE";
 
     private static final String ATTR_PERMISSION_PROVIDER = "permission-provider";
     private static final String ATTR_SETUP_COMPLETE = "setup-complete";
@@ -799,9 +807,9 @@
 
         long mPasswordTokenHandle = 0;
 
-        // Flag reflecting the current state of the personal apps suspension. This flag should
-        // only be written AFTER all the needed apps were suspended or unsuspended.
-        boolean mPersonalAppsSuspended = false;
+        // Whether user's apps are suspended. This flag should only be written AFTER all the needed
+        // apps were suspended or unsuspended.
+        boolean mAppsSuspended = false;
 
         public DevicePolicyData(int userHandle) {
             mUserHandle = userHandle;
@@ -848,7 +856,7 @@
                         RemoteBugreportUtils.NOTIFICATION_ID,
                         RemoteBugreportUtils.buildNotification(mContext,
                                 DevicePolicyManager.NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED),
-                                UserHandle.ALL);
+                        UserHandle.ALL);
             }
             if (Intent.ACTION_BOOT_COMPLETED.equals(action)
                     || ACTION_EXPIRED_PASSWORD_NOTIFICATION.equals(action)) {
@@ -895,12 +903,20 @@
                 handlePackagesChanged(null /* check all admins */, userHandle);
             } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
                 sendDeviceOwnerUserCommand(DeviceAdminReceiver.ACTION_USER_STOPPED, userHandle);
+                if (isManagedProfile(userHandle)) {
+                    Slog.d(LOG_TAG, "Managed profile was stopped");
+                    updatePersonalAppSuspension(userHandle, false /* profileIsOn */);
+                }
             } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
                 sendDeviceOwnerUserCommand(DeviceAdminReceiver.ACTION_USER_SWITCHED, userHandle);
             } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
                 synchronized (getLockObject()) {
                     maybeSendAdminEnabledBroadcastLocked(userHandle);
                 }
+                if (isManagedProfile(userHandle)) {
+                    Slog.d(LOG_TAG, "Managed profile became unlocked");
+                    updatePersonalAppSuspension(userHandle, true /* profileIsOn */);
+                }
             } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
                 handlePackagesChanged(null /* check all admins */, userHandle);
             } else if (Intent.ACTION_PACKAGE_CHANGED.equals(action)
@@ -918,8 +934,15 @@
                 // (ACTION_DATE_CHANGED), or when manual clock adjustment is made
                 // (ACTION_TIME_CHANGED)
                 updateSystemUpdateFreezePeriodsRecord(/* saveIfChanged */ true);
+            } else if (ACTION_PROFILE_OFF_DEADLINE.equals(action)) {
+                Slog.i(LOG_TAG, "Profile off deadline alarm was triggered");
+                final int userId = getManagedUserId(UserHandle.USER_SYSTEM);
+                if (userId >= 0) {
+                    updatePersonalAppSuspension(userId, mUserManager.isUserUnlocked(userId));
+                } else {
+                    Slog.wtf(LOG_TAG, "Got deadline alarm for nonexistent profile");
+                }
             }
-
         }
 
         private void sendDeviceOwnerUserCommand(String action, int userHandle) {
@@ -1033,6 +1056,8 @@
         private static final String TAG_FACTORY_RESET_PROTECTION_POLICY =
                 "factory_reset_protection_policy";
         private static final String TAG_SUSPEND_PERSONAL_APPS = "suspend-personal-apps";
+        private static final String TAG_PROFILE_MAXIMUM_TIME_OFF = "profile-max-time-off";
+        private static final String TAG_PROFILE_OFF_DEADLINE = "profile-off-deadline";
 
         DeviceAdminInfo info;
 
@@ -1157,6 +1182,11 @@
 
         // Whether the admin explicitly requires personal apps to be suspended
         boolean mSuspendPersonalApps = false;
+        // Maximum time the profile owned by this admin can be off.
+        long mProfileMaximumTimeOff = 0;
+        // Time by which the profile should be turned on according to System.currentTimeMillis().
+        long mProfileOffDeadline = 0;
+
 
         ActiveAdmin(DeviceAdminInfo _info, boolean parent) {
             info = _info;
@@ -1391,6 +1421,12 @@
             if (mSuspendPersonalApps) {
                 writeAttributeValueToXml(out, TAG_SUSPEND_PERSONAL_APPS, mSuspendPersonalApps);
             }
+            if (mProfileMaximumTimeOff != 0) {
+                writeAttributeValueToXml(out, TAG_PROFILE_MAXIMUM_TIME_OFF, mProfileMaximumTimeOff);
+            }
+            if (mProfileMaximumTimeOff != 0) {
+                writeAttributeValueToXml(out, TAG_PROFILE_OFF_DEADLINE, mProfileOffDeadline);
+            }
         }
 
         void writeTextToXml(XmlSerializer out, String tag, String text) throws IOException {
@@ -1630,6 +1666,12 @@
                 } else if (TAG_SUSPEND_PERSONAL_APPS.equals(tag)) {
                     mSuspendPersonalApps = Boolean.parseBoolean(
                             parser.getAttributeValue(null, ATTR_VALUE));
+                } else if (TAG_PROFILE_MAXIMUM_TIME_OFF.equals(tag)) {
+                    mProfileMaximumTimeOff =
+                            Long.parseLong(parser.getAttributeValue(null, ATTR_VALUE));
+                } else if (TAG_PROFILE_OFF_DEADLINE.equals(tag)) {
+                    mProfileOffDeadline =
+                            Long.parseLong(parser.getAttributeValue(null, ATTR_VALUE));
                 } else {
                     Slog.w(LOG_TAG, "Unknown admin tag: " + tag);
                     XmlUtils.skipCurrentTag(parser);
@@ -1855,7 +1897,13 @@
                 pw.println(mCrossProfileCalendarPackages);
             }
             pw.print("mCrossProfilePackages=");
-            pw.println(mCrossProfilePackages);
+                pw.println(mCrossProfilePackages);
+            pw.print("mSuspendPersonalApps=");
+                pw.println(mSuspendPersonalApps);
+            pw.print("mProfileMaximumTimeOff=");
+                pw.println(mProfileMaximumTimeOff);
+            pw.print("mProfileOffDeadline=");
+                pw.println(mProfileOffDeadline);
         }
     }
 
@@ -2049,6 +2097,10 @@
             return mContext.getSystemService(LocationManager.class);
         }
 
+        LocationManagerInternal getLocationManagerInternal() {
+            return LocalServices.getService(LocationManagerInternal.class);
+        }
+
         IWindowManager getIWindowManager() {
             return IWindowManager.Stub
                     .asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));
@@ -2373,12 +2425,14 @@
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_BOOT_COMPLETED);
         filter.addAction(ACTION_EXPIRED_PASSWORD_NOTIFICATION);
+        filter.addAction(ACTION_PROFILE_OFF_DEADLINE);
         filter.addAction(Intent.ACTION_USER_ADDED);
         filter.addAction(Intent.ACTION_USER_REMOVED);
         filter.addAction(Intent.ACTION_USER_STARTED);
         filter.addAction(Intent.ACTION_USER_STOPPED);
         filter.addAction(Intent.ACTION_USER_SWITCHED);
         filter.addAction(Intent.ACTION_USER_UNLOCKED);
+        filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
         filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
         mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler);
         filter = new IntentFilter();
@@ -3436,11 +3490,10 @@
                 out.endTag(null, TAG_PROTECTED_PACKAGES);
             }
 
-            if (policy.mPersonalAppsSuspended) {
-                out.startTag(null, TAG_PERSONAL_APPS_SUSPENDED);
-                out.attribute(null, ATTR_VALUE,
-                        Boolean.toString(policy.mPersonalAppsSuspended));
-                out.endTag(null, TAG_PERSONAL_APPS_SUSPENDED);
+            if (policy.mAppsSuspended) {
+                out.startTag(null, TAG_APPS_SUSPENDED);
+                out.attribute(null, ATTR_VALUE, Boolean.toString(policy.mAppsSuspended));
+                out.endTag(null, TAG_APPS_SUSPENDED);
             }
 
             out.endTag(null, "policies");
@@ -3659,8 +3712,8 @@
                     policy.mOwnerInstalledCaCerts.add(parser.getAttributeValue(null, ATTR_ALIAS));
                 } else if (TAG_PROTECTED_PACKAGES.equals(tag)) {
                     policy.mProtectedPackages.add(parser.getAttributeValue(null, ATTR_NAME));
-                } else if (TAG_PERSONAL_APPS_SUSPENDED.equals(tag)) {
-                    policy.mPersonalAppsSuspended =
+                } else if (TAG_APPS_SUSPENDED.equals(tag)) {
+                    policy.mAppsSuspended =
                             Boolean.parseBoolean(parser.getAttributeValue(null, ATTR_VALUE));
                 } else {
                     Slog.w(LOG_TAG, "Unknown tag: " + tag);
@@ -3802,7 +3855,10 @@
                 synchronized (getLockObject()) {
                     maybeMigrateToProfileOnOrganizationOwnedDeviceLocked();
                 }
-                checkPackageSuspensionOnBoot();
+                final int userId = getManagedUserId(UserHandle.USER_SYSTEM);
+                if (userId >= 0) {
+                    updatePersonalAppSuspension(userId, false /* running */);
+                }
                 break;
             case SystemService.PHASE_BOOT_COMPLETED:
                 ensureDeviceOwnerUserStarted(); // TODO Consider better place to do this.
@@ -3810,34 +3866,6 @@
         }
     }
 
-    private void checkPackageSuspensionOnBoot() {
-        int profileUserId = UserHandle.USER_NULL;
-        final boolean shouldSuspend;
-        synchronized (getLockObject()) {
-            for (final int userId : mOwners.getProfileOwnerKeys()) {
-                if (mOwners.isProfileOwnerOfOrganizationOwnedDevice(userId)) {
-                    profileUserId = userId;
-                    break;
-                }
-            }
-
-            if (profileUserId == UserHandle.USER_NULL) {
-                shouldSuspend = false;
-            } else {
-                shouldSuspend = getProfileOwnerAdminLocked(profileUserId).mSuspendPersonalApps;
-            }
-        }
-
-        final boolean suspended = getUserData(UserHandle.USER_SYSTEM).mPersonalAppsSuspended;
-        if (suspended != shouldSuspend) {
-            suspendPersonalAppsInternal(shouldSuspend, UserHandle.USER_SYSTEM);
-        }
-
-        if (shouldSuspend) {
-            sendPersonalAppsSuspendedNotification(profileUserId);
-        }
-    }
-
     private void onLockSettingsReady() {
         getUserData(UserHandle.USER_SYSTEM);
         loadOwners();
@@ -3950,13 +3978,11 @@
     @Override
     void handleUnlockUser(int userId) {
         startOwnerService(userId, "unlock-user");
-        maybeUpdatePersonalAppsSuspendedNotification(userId);
     }
 
     @Override
     void handleStopUser(int userId) {
         stopOwnerService(userId, "stop-user");
-        maybeUpdatePersonalAppsSuspendedNotification(userId);
     }
 
     private void startOwnerService(int userId, String actionForLog) {
@@ -9427,10 +9453,8 @@
             pw.println();
             pw.increaseIndent();
             pw.print("mPasswordOwner="); pw.println(policy.mPasswordOwner);
-            pw.decreaseIndent();
-            pw.println();
-            pw.increaseIndent();
             pw.print("mProtectedPackages="); pw.println(policy.mProtectedPackages);
+            pw.print("mAppsSuspended="); pw.println(policy.mAppsSuspended);
             pw.decreaseIndent();
         }
     }
@@ -10737,30 +10761,35 @@
 
     @Override
     public boolean setApplicationHidden(ComponentName who, String callerPackage, String packageName,
-            boolean hidden) {
-        int callingUserId = UserHandle.getCallingUserId();
-        boolean result = false;
+            boolean hidden, boolean parent) {
+        final int userId = parent ? getProfileParentId(UserHandle.getCallingUserId())
+                : UserHandle.getCallingUserId();
+        boolean result;
+
         synchronized (getLockObject()) {
             // Ensure the caller is a DO/PO or a package access delegate.
             enforceCanManageScope(who, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER,
                     DELEGATION_PACKAGE_ACCESS);
 
-            long id = mInjector.binderClearCallingIdentity();
-            try {
-                result = mIPackageManager
-                        .setApplicationHiddenSettingAsUser(packageName, hidden, callingUserId);
-            } catch (RemoteException re) {
-                // shouldn't happen
-                Slog.e(LOG_TAG, "Failed to setApplicationHiddenSetting", re);
-            } finally {
-                mInjector.binderRestoreCallingIdentity(id);
+            if (parent) {
+                getActiveAdminForCallerLocked(who,
+                        DeviceAdminInfo.USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER, parent);
+                // Ensure the package provided is a system package, this is to ensure that this
+                // API cannot be used to leak if certain non-system package exists in the person
+                // profile.
+                mInjector.binderWithCleanCallingIdentity(() ->
+                        enforcePackageIsSystemPackage(packageName, hidden, userId));
             }
+
+            result = mInjector.binderWithCleanCallingIdentity(() -> mIPackageManager
+                    .setApplicationHiddenSettingAsUser(packageName, hidden, userId));
         }
         final boolean isDelegate = (who == null);
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_APPLICATION_HIDDEN)
                 .setAdmin(callerPackage)
                 .setBoolean(isDelegate)
+                .setBoolean(parent)
                 .setStrings(packageName, hidden ? "hidden" : "not_hidden")
                 .write();
         return result;
@@ -10768,24 +10797,40 @@
 
     @Override
     public boolean isApplicationHidden(ComponentName who, String callerPackage,
-            String packageName) {
-        int callingUserId = UserHandle.getCallingUserId();
+            String packageName, boolean parent) {
+        final int userId = parent ? getProfileParentId(UserHandle.getCallingUserId())
+                : UserHandle.getCallingUserId();
+
         synchronized (getLockObject()) {
             // Ensure the caller is a DO/PO or a package access delegate.
             enforceCanManageScope(who, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER,
                     DELEGATION_PACKAGE_ACCESS);
 
-            long id = mInjector.binderClearCallingIdentity();
-            try {
-                return mIPackageManager.getApplicationHiddenSettingAsUser(
-                        packageName, callingUserId);
-            } catch (RemoteException re) {
-                // shouldn't happen
-                Slog.e(LOG_TAG, "Failed to getApplicationHiddenSettingAsUser", re);
-            } finally {
-                mInjector.binderRestoreCallingIdentity(id);
+            if (parent) {
+                getActiveAdminForCallerLocked(who,
+                        DeviceAdminInfo.USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER, parent);
+                // Ensure the package provided is a system package.
+                mInjector.binderWithCleanCallingIdentity(() ->
+                        enforcePackageIsSystemPackage(packageName, false, userId));
             }
-            return false;
+
+            return mInjector.binderWithCleanCallingIdentity(
+                    () -> mIPackageManager.getApplicationHiddenSettingAsUser(packageName, userId));
+        }
+    }
+
+    private void enforcePackageIsSystemPackage(String packageName, boolean hidden, int userId)
+            throws RemoteException {
+        int flags = PackageManager.MATCH_SYSTEM_ONLY;
+        // If the package is currently hidden then it is considered uninstalled and
+        // the MATCH_UNINSTALLED_PACKAGES flag has to be added.
+        if (!hidden) {
+            flags |= PackageManager.MATCH_UNINSTALLED_PACKAGES;
+        }
+        PackageInfo packageInfo = mIPackageManager.getPackageInfo(packageName, flags, userId);
+        if (packageInfo == null || !packageInfo.applicationInfo.isSystemApp()) {
+            throw new IllegalArgumentException(
+                    "The provided package is not a system package");
         }
     }
 
@@ -11513,6 +11558,17 @@
     }
 
     @Override
+    public void requestSetLocationProviderAllowed(ComponentName who, String provider,
+            boolean providerAllowed) {
+        Objects.requireNonNull(who, "ComponentName is null");
+        enforceDeviceOwner(who);
+
+        mInjector.binderWithCleanCallingIdentity(
+                () -> mInjector.getLocationManagerInternal().requestSetProviderAllowed(provider,
+                        providerAllowed));
+    }
+
+    @Override
     public boolean setTime(ComponentName who, long millis) {
         Objects.requireNonNull(who, "ComponentName is null in setTime");
         enforceDeviceOwnerOrProfileOwnerOnOrganizationOwnedDevice(who);
@@ -12190,7 +12246,8 @@
                     LocalDate.now());
         }
         synchronized (getLockObject()) {
-            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+            getActiveAdminForCallerLocked(who,
+                    DeviceAdminInfo.USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER);
             if (policy == null) {
                 mOwners.clearSystemUpdatePolicy();
             } else {
@@ -12199,9 +12256,9 @@
             }
             mOwners.writeDeviceOwner();
         }
-        mContext.sendBroadcastAsUser(
+        mInjector.binderWithCleanCallingIdentity(() -> mContext.sendBroadcastAsUser(
                 new Intent(DevicePolicyManager.ACTION_SYSTEM_UPDATE_POLICY_CHANGED),
-                UserHandle.SYSTEM);
+                UserHandle.SYSTEM));
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_SYSTEM_UPDATE_POLICY)
                 .setAdmin(who)
@@ -14863,7 +14920,7 @@
                 .setAdmin(admin)
                 .setBoolean(isDeviceAB())
                 .write();
-        enforceDeviceOwner(admin);
+        enforceDeviceOwnerOrProfileOwnerOnOrganizationOwnedDevice(admin);
         mInjector.binderWithCleanCallingIdentity(() -> {
             UpdateInstaller updateInstaller;
             if (isDeviceAB()) {
@@ -15250,10 +15307,20 @@
                     false /* parent */);
             // DO shouldn't be able to use this method.
             enforceProfileOwnerOfOrganizationOwnedDevice(admin);
-            if (admin.mSuspendPersonalApps) {
-                return DevicePolicyManager.PERSONAL_APPS_SUSPENDED_EXPLICITLY;
+            final DevicePolicyData userData =
+                    getUserData(getProfileParentId(mInjector.userHandleGetCallingUserId()));
+            if (!userData.mAppsSuspended) {
+                return PERSONAL_APPS_NOT_SUSPENDED;
             } else {
-                return DevicePolicyManager.PERSONAL_APPS_NOT_SUSPENDED;
+                int reasons = PERSONAL_APPS_NOT_SUSPENDED;
+                if (admin.mSuspendPersonalApps) {
+                    reasons |= PERSONAL_APPS_SUSPENDED_EXPLICITLY;
+                }
+                final long deadline = admin.mProfileOffDeadline;
+                if (deadline != 0 && System.currentTimeMillis() > deadline) {
+                    reasons |= PERSONAL_APPS_SUSPENDED_PROFILE_TIMEOUT;
+                }
+                return reasons;
             }
         }
     }
@@ -15267,26 +15334,112 @@
                     false /* parent */);
             // DO shouldn't be able to use this method.
             enforceProfileOwnerOfOrganizationOwnedDevice(admin);
+            enforceHandlesCheckPolicyComplianceIntent(callingUserId, admin.info.getPackageName());
+            boolean shouldSaveSettings = false;
             if (admin.mSuspendPersonalApps != suspended) {
                 admin.mSuspendPersonalApps = suspended;
+                shouldSaveSettings = true;
+            }
+            if (admin.mProfileOffDeadline != 0) {
+                admin.mProfileOffDeadline = 0;
+                shouldSaveSettings = true;
+            }
+            if (shouldSaveSettings) {
                 saveSettingsLocked(callingUserId);
             }
         }
 
-        if (getUserData(UserHandle.USER_SYSTEM).mPersonalAppsSuspended == suspended) {
-            // Admin request matches current state, nothing to do.
-            return;
+        mInjector.binderWithCleanCallingIdentity(
+                () -> applyPersonalAppsSuspension(callingUserId, suspended));
+    }
+
+    /**
+     * Checks whether there is a policy that requires personal apps to be suspended and if so,
+     * applies it.
+     * @param running whether the profile is currently considered running.
+     */
+    private void updatePersonalAppSuspension(int profileUserId, boolean running) {
+        final boolean shouldSuspend;
+        synchronized (getLockObject()) {
+            final ActiveAdmin profileOwner = getProfileOwnerAdminLocked(profileUserId);
+            if (profileOwner != null) {
+                final boolean deadlineReached =
+                        updateProfileOffDeadlineLocked(profileUserId, profileOwner, running);
+                shouldSuspend = deadlineReached || profileOwner.mSuspendPersonalApps;
+                Slog.d(LOG_TAG, String.format(
+                        "Should personal use be suspended: %b; explicit: %b; timeout: %b",
+                        shouldSuspend, profileOwner.mSuspendPersonalApps, deadlineReached));
+            } else {
+                shouldSuspend = false;
+            }
         }
 
-        suspendPersonalAppsInternal(suspended, UserHandle.USER_SYSTEM);
+        applyPersonalAppsSuspension(profileUserId, shouldSuspend);
+    }
 
-        mInjector.binderWithCleanCallingIdentity(() -> {
-            if (suspended) {
-                sendPersonalAppsSuspendedNotification(callingUserId);
-            } else {
-                clearPersonalAppsSuspendedNotification(callingUserId);
-            }
-        });
+    /**
+     * Checks work profile time off policy, scheduling personal apps suspension via alarm if
+     * necessary.
+     * @return whether the apps should be suspended based on maximum time off policy.
+     */
+    private boolean updateProfileOffDeadlineLocked(
+            int profileUserId, ActiveAdmin profileOwner, boolean unlocked) {
+        final long now = System.currentTimeMillis();
+        if (profileOwner.mProfileOffDeadline != 0 && now > profileOwner.mProfileOffDeadline) {
+            // Profile off deadline is already reached.
+            Slog.i(LOG_TAG, "Profile off deadline has been reached.");
+            return true;
+        }
+        boolean shouldSaveSettings = false;
+        if (profileOwner.mProfileOffDeadline != 0
+                && (profileOwner.mProfileMaximumTimeOff == 0 || unlocked)) {
+            // There is a deadline but either there is no policy or the profile is unlocked -> clear
+            // the deadline.
+            Slog.i(LOG_TAG, "Profile off deadline is reset to zero");
+            profileOwner.mProfileOffDeadline = 0;
+            shouldSaveSettings = true;
+        } else if (profileOwner.mProfileOffDeadline == 0
+                && (profileOwner.mProfileMaximumTimeOff != 0 && !unlocked)) {
+            // There profile is locked and there is a policy, but the deadline is not set -> set the
+            // deadline.
+            Slog.i(LOG_TAG, "Profile off deadline is set.");
+            profileOwner.mProfileOffDeadline = now + profileOwner.mProfileMaximumTimeOff;
+            shouldSaveSettings = true;
+        }
+
+        updateProfileOffAlarm(profileOwner.mProfileOffDeadline);
+
+        if (shouldSaveSettings) {
+            saveSettingsLocked(profileUserId);
+        }
+        return false;
+    }
+
+    private void updateProfileOffAlarm(long profileOffDeadline) {
+        final AlarmManager am = mInjector.getAlarmManager();
+        final PendingIntent pi = PendingIntent.getBroadcast(mContext, REQUEST_PROFILE_OFF_DEADLINE,
+                new Intent(ACTION_PROFILE_OFF_DEADLINE),
+                PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);
+        am.cancel(pi);
+        if (profileOffDeadline != 0) {
+            Slog.i(LOG_TAG, "Profile off deadline alarm is set.");
+            am.set(AlarmManager.RTC, profileOffDeadline, pi);
+        } else {
+            Slog.i(LOG_TAG, "Profile off deadline alarm is removed.");
+        }
+    }
+
+    private void applyPersonalAppsSuspension(int profileUserId, boolean shouldSuspend) {
+        final boolean suspended = getUserData(UserHandle.USER_SYSTEM).mAppsSuspended;
+        if (suspended != shouldSuspend) {
+            suspendPersonalAppsInternal(shouldSuspend, UserHandle.USER_SYSTEM);
+        }
+
+        if (shouldSuspend) {
+            sendPersonalAppsSuspendedNotification(profileUserId);
+        } else {
+            clearPersonalAppsSuspendedNotification();
+        }
     }
 
     private void suspendPersonalAppsInternal(boolean suspended, int userId) {
@@ -15310,21 +15463,12 @@
         });
 
         synchronized (getLockObject()) {
-            getUserData(userId).mPersonalAppsSuspended = suspended;
+            getUserData(userId).mAppsSuspended = suspended;
             saveSettingsLocked(userId);
         }
     }
 
-    private void maybeUpdatePersonalAppsSuspendedNotification(int profileUserId) {
-        // TODO(b/147414651): Unless updated, the notification stops working after turning the
-        //  profile off and back on, so it has to be updated more often than necessary.
-        if (getUserData(UserHandle.USER_SYSTEM).mPersonalAppsSuspended
-                && getProfileParentId(profileUserId) == UserHandle.USER_SYSTEM) {
-            sendPersonalAppsSuspendedNotification(profileUserId);
-        }
-    }
-
-    private void clearPersonalAppsSuspendedNotification(int userId) {
+    private void clearPersonalAppsSuspendedNotification() {
         mInjector.binderWithCleanCallingIdentity(() ->
                 mInjector.getNotificationManager().cancel(
                         SystemMessage.NOTE_PERSONAL_APPS_SUSPENDED));
@@ -15358,4 +15502,48 @@
         mInjector.getNotificationManager().notify(
                 SystemMessage.NOTE_PERSONAL_APPS_SUSPENDED, notification);
     }
+
+    @Override
+    public void setManagedProfileMaximumTimeOff(ComponentName who, long timeoutMs) {
+        final int userId = mInjector.userHandleGetCallingUserId();
+        synchronized (getLockObject()) {
+            final ActiveAdmin admin = getActiveAdminForCallerLocked(who,
+                    DeviceAdminInfo.USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER,
+                    false /* parent */);
+            // DO shouldn't be able to use this method.
+            enforceProfileOwnerOfOrganizationOwnedDevice(admin);
+            enforceHandlesCheckPolicyComplianceIntent(userId, admin.info.getPackageName());
+            if (admin.mProfileMaximumTimeOff == timeoutMs) {
+                return;
+            }
+            admin.mProfileMaximumTimeOff = timeoutMs;
+            saveSettingsLocked(userId);
+        }
+
+        mInjector.binderWithCleanCallingIdentity(
+                () -> updatePersonalAppSuspension(userId, mUserManager.isUserUnlocked()));
+    }
+
+    void enforceHandlesCheckPolicyComplianceIntent(@UserIdInt int userId, String packageName) {
+        mInjector.binderWithCleanCallingIdentity(() -> {
+            final Intent intent = new Intent(DevicePolicyManager.ACTION_CHECK_POLICY_COMPLIANCE);
+            intent.setPackage(packageName);
+            final List<ResolveInfo> handlers = mInjector.getPackageManager()
+                    .queryIntentActivitiesAsUser(intent, /* flags= */ 0, userId);
+            Preconditions.checkState(!handlers.isEmpty(),
+                    "Admin doesn't handle " + DevicePolicyManager.ACTION_CHECK_POLICY_COMPLIANCE);
+        });
+    }
+
+    @Override
+    public long getManagedProfileMaximumTimeOff(ComponentName who) {
+        synchronized (getLockObject()) {
+            final ActiveAdmin admin = getActiveAdminForCallerLocked(who,
+                    DeviceAdminInfo.USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER,
+                    false /* parent */);
+            // DO shouldn't be able to use this method.
+            enforceProfileOwnerOfOrganizationOwnedDevice(admin);
+            return admin.mProfileMaximumTimeOff;
+        }
+    }
 }
diff --git a/services/incremental/Android.bp b/services/incremental/Android.bp
index ddf4dd5..323e7f1 100644
--- a/services/incremental/Android.bp
+++ b/services/incremental/Android.bp
@@ -47,6 +47,8 @@
     shared_libs: [
         "libandroidfw",
         "libbinder",
+        "libcrypto",
+        "libcutils",
         "libincfs",
         "liblog",
         "libz",
diff --git a/services/incremental/BinderIncrementalService.cpp b/services/incremental/BinderIncrementalService.cpp
index bb26c1f..f1b637f 100644
--- a/services/incremental/BinderIncrementalService.cpp
+++ b/services/incremental/BinderIncrementalService.cpp
@@ -46,10 +46,10 @@
     return incfs::enabled();
 }
 
-static bool incFsVersionValid(const sp<IVold>& vold) {
-    int version = -1;
-    auto status = vold->incFsVersion(&version);
-    if (!status.isOk() || version <= 0) {
+static bool incFsValid(const sp<IVold>& vold) {
+    bool enabled = false;
+    auto status = vold->incFsEnabled(&enabled);
+    if (!status.isOk() || !enabled) {
         return false;
     }
     return true;
@@ -74,7 +74,7 @@
         return nullptr;
     }
     sp<IVold> vold = interface_cast<IVold>(voldBinder);
-    if (!incFsVersionValid(vold)) {
+    if (!incFsValid(vold)) {
         return nullptr;
     }
 
@@ -86,6 +86,7 @@
     sp<ProcessState> ps(ProcessState::self());
     ps->startThreadPool();
     ps->giveThreadPoolName();
+    // sm->addService increments the reference count, and now we're OK with returning the pointer.
     return self.get();
 }
 
@@ -107,9 +108,9 @@
     return ok();
 }
 
-binder::Status BinderIncrementalService::createStorage(
-        const std::string& path, const DataLoaderParamsParcel& params,
-        int32_t createMode, int32_t* _aidl_return) {
+binder::Status BinderIncrementalService::createStorage(const std::string& path,
+                                                       const DataLoaderParamsParcel& params,
+                                                       int32_t createMode, int32_t* _aidl_return) {
     *_aidl_return =
             mImpl.createStorage(path, const_cast<DataLoaderParamsParcel&&>(params),
                                 android::incremental::IncrementalService::CreateOptions(
@@ -129,10 +130,10 @@
 }
 
 binder::Status BinderIncrementalService::makeBindMount(int32_t storageId,
-                                                       const std::string& pathUnderStorage,
+                                                       const std::string& sourcePath,
                                                        const std::string& targetFullPath,
                                                        int32_t bindType, int32_t* _aidl_return) {
-    *_aidl_return = mImpl.bind(storageId, pathUnderStorage, targetFullPath,
+    *_aidl_return = mImpl.bind(storageId, sourcePath, targetFullPath,
                                android::incremental::IncrementalService::BindKind(bindType));
     return ok();
 }
@@ -149,75 +150,127 @@
     return ok();
 }
 
-binder::Status BinderIncrementalService::makeDirectory(int32_t storageId,
-                                                       const std::string& pathUnderStorage,
+binder::Status BinderIncrementalService::makeDirectory(int32_t storageId, const std::string& path,
                                                        int32_t* _aidl_return) {
-    auto inode = mImpl.makeDir(storageId, pathUnderStorage);
-    *_aidl_return = inode < 0 ? inode : 0;
+    *_aidl_return = mImpl.makeDir(storageId, path);
     return ok();
 }
 
-binder::Status BinderIncrementalService::makeDirectories(int32_t storageId,
-                                                         const std::string& pathUnderStorage,
-                                                         int32_t* _aidl_return) {
-    auto inode = mImpl.makeDirs(storageId, pathUnderStorage);
-    *_aidl_return = inode < 0 ? inode : 0;
-    return ok();
+static std::tuple<int, incfs::FileId, incfs::NewFileParams> toMakeFileParams(
+        const android::os::incremental::IncrementalNewFileParams& params) {
+    incfs::FileId id;
+    if (params.fileId.empty()) {
+        if (params.metadata.empty()) {
+            return {EINVAL, {}, {}};
+        }
+        id = IncrementalService::idFromMetadata(params.metadata);
+    } else if (params.fileId.size() != sizeof(id)) {
+        return {EINVAL, {}, {}};
+    } else {
+        memcpy(&id, params.fileId.data(), sizeof(id));
+    }
+    incfs::NewFileParams nfp;
+    nfp.size = params.size;
+    nfp.metadata = {(const char*)params.metadata.data(), (IncFsSize)params.metadata.size()};
+    if (!params.signature) {
+        nfp.verification = {};
+    } else {
+        nfp.verification.hashAlgorithm = IncFsHashAlgortithm(params.signature->hashAlgorithm);
+        nfp.verification.rootHash = {(const char*)params.signature->rootHash.data(),
+                                     (IncFsSize)params.signature->rootHash.size()};
+        nfp.verification.additionalData = {(const char*)params.signature->additionalData.data(),
+                                           (IncFsSize)params.signature->additionalData.size()};
+        nfp.verification.signature = {(const char*)params.signature->signature.data(),
+                                      (IncFsSize)params.signature->signature.size()};
+    }
+    return {0, id, nfp};
 }
 
-binder::Status BinderIncrementalService::makeFile(int32_t storageId,
-                                                  const std::string& pathUnderStorage, int64_t size,
-                                                  const std::vector<uint8_t>& metadata,
-                                                  int32_t* _aidl_return) {
-    auto inode = mImpl.makeFile(storageId, pathUnderStorage, size,
-                                {(const char*)metadata.data(), metadata.size()}, {});
-    *_aidl_return = inode < 0 ? inode : 0;
+binder::Status BinderIncrementalService::makeFile(
+        int32_t storageId, const std::string& path,
+        const ::android::os::incremental::IncrementalNewFileParams& params, int32_t* _aidl_return) {
+    auto [err, fileId, nfp] = toMakeFileParams(params);
+    if (err) {
+        *_aidl_return = err;
+        return ok();
+    }
+
+    *_aidl_return = mImpl.makeFile(storageId, path, 0555, fileId, nfp);
     return ok();
 }
-binder::Status BinderIncrementalService::makeFileFromRange(
-        int32_t storageId, const std::string& pathUnderStorage,
-        const std::string& sourcePathUnderStorage, int64_t start, int64_t end,
-        int32_t* _aidl_return) {
-    // TODO(b/136132412): implement this
-    *_aidl_return = -1;
-    return ok();
-}
-binder::Status BinderIncrementalService::makeLink(int32_t sourceStorageId,
-                                                  const std::string& relativeSourcePath,
-                                                  int32_t destStorageId,
-                                                  const std::string& relativeDestPath,
-                                                  int32_t* _aidl_return) {
-    auto sourceInode = mImpl.nodeFor(sourceStorageId, relativeSourcePath);
-    auto [targetParentInode, name] = mImpl.parentAndNameFor(destStorageId, relativeDestPath);
-    *_aidl_return = mImpl.link(sourceStorageId, sourceInode, targetParentInode, name);
-    return ok();
-}
-binder::Status BinderIncrementalService::unlink(int32_t storageId,
-                                                const std::string& pathUnderStorage,
-                                                int32_t* _aidl_return) {
-    auto [parentNode, name] = mImpl.parentAndNameFor(storageId, pathUnderStorage);
-    *_aidl_return = mImpl.unlink(storageId, parentNode, name);
-    return ok();
-}
-binder::Status BinderIncrementalService::isFileRangeLoaded(int32_t storageId,
-                                                           const std::string& relativePath,
+binder::Status BinderIncrementalService::makeFileFromRange(int32_t storageId,
+                                                           const std::string& targetPath,
+                                                           const std::string& sourcePath,
                                                            int64_t start, int64_t end,
-                                                           bool* _aidl_return) {
+                                                           int32_t* _aidl_return) {
+    // TODO(b/136132412): implement this
+    *_aidl_return = ENOSYS; // not implemented
+    return ok();
+}
+
+binder::Status BinderIncrementalService::makeLink(int32_t sourceStorageId,
+                                                  const std::string& sourcePath,
+                                                  int32_t destStorageId,
+                                                  const std::string& destPath,
+                                                  int32_t* _aidl_return) {
+    *_aidl_return = mImpl.link(sourceStorageId, sourcePath, destStorageId, destPath);
+    return ok();
+}
+
+binder::Status BinderIncrementalService::unlink(int32_t storageId, const std::string& path,
+                                                int32_t* _aidl_return) {
+    *_aidl_return = mImpl.unlink(storageId, path);
+    return ok();
+}
+
+binder::Status BinderIncrementalService::isFileRangeLoaded(int32_t storageId,
+                                                           const std::string& path, int64_t start,
+                                                           int64_t end, bool* _aidl_return) {
+    // TODO: implement
     *_aidl_return = false;
     return ok();
 }
-binder::Status BinderIncrementalService::getFileMetadata(int32_t storageId,
-                                                         const std::string& relativePath,
+
+binder::Status BinderIncrementalService::getMetadataByPath(int32_t storageId,
+                                                           const std::string& path,
+                                                           std::vector<uint8_t>* _aidl_return) {
+    auto fid = mImpl.nodeFor(storageId, path);
+    if (fid != kIncFsInvalidFileId) {
+        auto metadata = mImpl.getMetadata(storageId, fid);
+        _aidl_return->assign(metadata.begin(), metadata.end());
+    }
+    return ok();
+}
+
+static FileId toFileId(const std::vector<uint8_t>& id) {
+    FileId fid;
+    memcpy(&fid, id.data(), id.size());
+    return fid;
+}
+
+binder::Status BinderIncrementalService::getMetadataById(int32_t storageId,
+                                                         const std::vector<uint8_t>& id,
                                                          std::vector<uint8_t>* _aidl_return) {
-    auto inode = mImpl.nodeFor(storageId, relativePath);
-    auto metadata = mImpl.getMetadata(storageId, inode);
+    if (id.size() != sizeof(incfs::FileId)) {
+        return ok();
+    }
+    auto fid = toFileId(id);
+    auto metadata = mImpl.getMetadata(storageId, fid);
     _aidl_return->assign(metadata.begin(), metadata.end());
     return ok();
 }
+
+binder::Status BinderIncrementalService::makeDirectories(int32_t storageId, const std::string& path,
+                                                         int32_t* _aidl_return) {
+    *_aidl_return = mImpl.makeDirs(storageId, path);
+    return ok();
+}
+
 binder::Status BinderIncrementalService::startLoading(int32_t storageId, bool* _aidl_return) {
     *_aidl_return = mImpl.startLoading(storageId);
     return ok();
 }
+
 } // namespace android::os::incremental
 
 jlong Incremental_IncrementalService_Start() {
diff --git a/services/incremental/BinderIncrementalService.h b/services/incremental/BinderIncrementalService.h
index 37c9661d..a94a75a 100644
--- a/services/incremental/BinderIncrementalService.h
+++ b/services/incremental/BinderIncrementalService.h
@@ -37,38 +37,39 @@
     void onSystemReady();
     void onInvalidStorage(int mountId);
 
-    binder::Status openStorage(const std::string &path, int32_t *_aidl_return) final;
-    binder::Status createStorage(
-            const std::string &path,
-            const ::android::content::pm::DataLoaderParamsParcel &params,
-            int32_t createMode, int32_t *_aidl_return) final;
-    binder::Status createLinkedStorage(const std::string &path, int32_t otherStorageId,
-                                       int32_t createMode, int32_t *_aidl_return) final;
-    binder::Status makeBindMount(int32_t storageId, const std::string &pathUnderStorage,
-                                 const std::string &targetFullPath, int32_t bindType,
-                                 int32_t *_aidl_return) final;
-    binder::Status deleteBindMount(int32_t storageId, const std::string &targetFullPath,
-                                   int32_t *_aidl_return) final;
+    binder::Status openStorage(const std::string& path, int32_t* _aidl_return) final;
+    binder::Status createStorage(const std::string& path,
+                                 const ::android::content::pm::DataLoaderParamsParcel& params,
+                                 int32_t createMode, int32_t* _aidl_return) final;
+    binder::Status createLinkedStorage(const std::string& path, int32_t otherStorageId,
+                                       int32_t createMode, int32_t* _aidl_return) final;
+    binder::Status makeBindMount(int32_t storageId, const std::string& sourcePath,
+                                 const std::string& targetFullPath, int32_t bindType,
+                                 int32_t* _aidl_return) final;
+    binder::Status deleteBindMount(int32_t storageId, const std::string& targetFullPath,
+                                   int32_t* _aidl_return) final;
+    binder::Status makeDirectory(int32_t storageId, const std::string& path,
+                                 int32_t* _aidl_return) final;
+    binder::Status makeDirectories(int32_t storageId, const std::string& path,
+                                   int32_t* _aidl_return) final;
+    binder::Status makeFile(int32_t storageId, const std::string& path,
+                            const ::android::os::incremental::IncrementalNewFileParams& params,
+                            int32_t* _aidl_return) final;
+    binder::Status makeFileFromRange(int32_t storageId, const std::string& targetPath,
+                                     const std::string& sourcePath, int64_t start, int64_t end,
+                                     int32_t* _aidl_return) final;
+    binder::Status makeLink(int32_t sourceStorageId, const std::string& sourcePath,
+                            int32_t destStorageId, const std::string& destPath,
+                            int32_t* _aidl_return) final;
+    binder::Status unlink(int32_t storageId, const std::string& path, int32_t* _aidl_return) final;
+    binder::Status isFileRangeLoaded(int32_t storageId, const std::string& path, int64_t start,
+                                     int64_t end, bool* _aidl_return) final;
+    binder::Status getMetadataByPath(int32_t storageId, const std::string& path,
+                                     std::vector<uint8_t>* _aidl_return) final;
+    binder::Status getMetadataById(int32_t storageId, const std::vector<uint8_t>& id,
+                                   std::vector<uint8_t>* _aidl_return) final;
+    binder::Status startLoading(int32_t storageId, bool* _aidl_return) final;
     binder::Status deleteStorage(int32_t storageId) final;
-    binder::Status makeDirectory(int32_t storageId, const std::string &pathUnderStorage,
-                                 int32_t *_aidl_return) final;
-    binder::Status makeDirectories(int32_t storageId, const std::string &pathUnderStorage,
-                                   int32_t *_aidl_return) final;
-    binder::Status makeFile(int32_t storageId, const std::string &pathUnderStorage, int64_t size,
-                            const std::vector<uint8_t> &metadata, int32_t *_aidl_return) final;
-    binder::Status makeFileFromRange(int32_t storageId, const std::string &pathUnderStorage,
-                                     const std::string &sourcePathUnderStorage, int64_t start,
-                                     int64_t end, int32_t *_aidl_return);
-    binder::Status makeLink(int32_t sourceStorageId, const std::string &relativeSourcePath,
-                            int32_t destStorageId, const std::string &relativeDestPath,
-                            int32_t *_aidl_return) final;
-    binder::Status unlink(int32_t storageId, const std::string &pathUnderStorage,
-                          int32_t *_aidl_return) final;
-    binder::Status isFileRangeLoaded(int32_t storageId, const std::string &relativePath,
-                                     int64_t start, int64_t end, bool *_aidl_return) final;
-    binder::Status getFileMetadata(int32_t storageId, const std::string &relativePath,
-                                   std::vector<uint8_t> *_aidl_return) final;
-    binder::Status startLoading(int32_t storageId, bool *_aidl_return) final;
 
 private:
     android::incremental::IncrementalService mImpl;
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index afce260..414c66c 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -30,6 +30,8 @@
 #include <binder/BinderService.h>
 #include <binder/ParcelFileDescriptor.h>
 #include <binder/Status.h>
+
+#include <openssl/sha.h>
 #include <sys/stat.h>
 #include <uuid/uuid.h>
 #include <zlib.h>
@@ -55,7 +57,6 @@
 struct Constants {
     static constexpr auto backing = "backing_store"sv;
     static constexpr auto mount = "mount"sv;
-    static constexpr auto image = "incfs.img"sv;
     static constexpr auto storagePrefix = "st"sv;
     static constexpr auto mountpointMdPrefix = ".mountpoint."sv;
     static constexpr auto infoMdName = ".info"sv;
@@ -70,7 +71,7 @@
 bool mkdirOrLog(std::string_view name, int mode = 0770, bool allowExisting = true) {
     auto cstr = path::c_str(name);
     if (::mkdir(cstr, mode)) {
-        if (errno != EEXIST) {
+        if (!allowExisting || errno != EEXIST) {
             PLOG(level) << "Can't create directory '" << name << '\'';
             return false;
         }
@@ -80,6 +81,11 @@
             return false;
         }
     }
+    if (::chmod(cstr, mode)) {
+        PLOG(level) << "Changing permission failed for '" << name << '\'';
+        return false;
+    }
+
     return true;
 }
 
@@ -106,7 +112,7 @@
     for (int counter = 0; counter < 1000;
          mountKey.resize(prefixSize), base::StringAppendF(&mountKey, "%d", counter++)) {
         auto mountRoot = path::join(incrementalDir, mountKey);
-        if (mkdirOrLog(mountRoot, 0770, false)) {
+        if (mkdirOrLog(mountRoot, 0777, false)) {
             return {mountKey, mountRoot};
         }
     }
@@ -116,11 +122,7 @@
 template <class ProtoMessage, class Control>
 static ProtoMessage parseFromIncfs(const IncFsWrapper* incfs, Control&& control,
                                    std::string_view path) {
-    struct stat st;
-    if (::stat(path::c_str(path), &st)) {
-        return {};
-    }
-    auto md = incfs->getMetadata(control, st.st_ino);
+    auto md = incfs->getMetadata(control, path);
     ProtoMessage message;
     return message.ParseFromArray(md.data(), md.size()) ? message : ProtoMessage{};
 }
@@ -161,35 +163,66 @@
 }
 
 auto IncrementalService::IncFsMount::makeStorage(StorageId id) -> StorageMap::iterator {
-    metadata::Storage st;
-    st.set_id(id);
-    auto metadata = st.SerializeAsString();
-
     std::string name;
     for (int no = nextStorageDirNo.fetch_add(1, std::memory_order_relaxed), i = 0;
          i < 1024 && no >= 0; no = nextStorageDirNo.fetch_add(1, std::memory_order_relaxed), ++i) {
         name.clear();
-        base::StringAppendF(&name, "%.*s%d", int(constants().storagePrefix.size()),
-                            constants().storagePrefix.data(), no);
-        if (auto node =
-                    incrementalService.mIncFs->makeDir(control, name, INCFS_ROOT_INODE, metadata);
-            node >= 0) {
+        base::StringAppendF(&name, "%.*s_%d_%d", int(constants().storagePrefix.size()),
+                            constants().storagePrefix.data(), id, no);
+        auto fullName = path::join(root, constants().mount, name);
+        if (auto err = incrementalService.mIncFs->makeDir(control, fullName); !err) {
             std::lock_guard l(lock);
-            return storages.insert_or_assign(id, Storage{std::move(name), node}).first;
+            return storages.insert_or_assign(id, Storage{std::move(fullName)}).first;
+        } else if (err != EEXIST) {
+            LOG(ERROR) << __func__ << "(): failed to create dir |" << fullName << "| " << err;
+            break;
         }
     }
     nextStorageDirNo = 0;
     return storages.end();
 }
 
+static std::unique_ptr<DIR, decltype(&::closedir)> openDir(const char* path) {
+    return {::opendir(path), ::closedir};
+}
+
+static int rmDirContent(const char* path) {
+    auto dir = openDir(path);
+    if (!dir) {
+        return -EINVAL;
+    }
+    while (auto entry = ::readdir(dir.get())) {
+        if (entry->d_name == "."sv || entry->d_name == ".."sv) {
+            continue;
+        }
+        auto fullPath = android::base::StringPrintf("%s/%s", path, entry->d_name);
+        if (entry->d_type == DT_DIR) {
+            if (const auto err = rmDirContent(fullPath.c_str()); err != 0) {
+                PLOG(WARNING) << "Failed to delete " << fullPath << " content";
+                return err;
+            }
+            if (const auto err = ::rmdir(fullPath.c_str()); err != 0) {
+                PLOG(WARNING) << "Failed to rmdir " << fullPath;
+                return err;
+            }
+        } else {
+            if (const auto err = ::unlink(fullPath.c_str()); err != 0) {
+                PLOG(WARNING) << "Failed to delete " << fullPath;
+                return err;
+            }
+        }
+    }
+    return 0;
+}
+
 void IncrementalService::IncFsMount::cleanupFilesystem(std::string_view root) {
-    ::unlink(path::join(root, constants().backing, constants().image).c_str());
+    rmDirContent(path::join(root, constants().backing).c_str());
     ::rmdir(path::join(root, constants().backing).c_str());
     ::rmdir(path::join(root, constants().mount).c_str());
     ::rmdir(path::c_str(root));
 }
 
-IncrementalService::IncrementalService(const ServiceManagerWrapper& sm, std::string_view rootDir)
+IncrementalService::IncrementalService(ServiceManagerWrapper&& sm, std::string_view rootDir)
       : mVold(sm.getVoldService()),
         mIncrementalManager(sm.getIncrementalManager()),
         mIncFs(sm.getIncFs()),
@@ -205,6 +238,23 @@
     // mountExistingImages();
 }
 
+FileId IncrementalService::idFromMetadata(std::span<const uint8_t> metadata) {
+    incfs::FileId id = {};
+    if (size_t(metadata.size()) <= sizeof(id)) {
+        memcpy(&id, metadata.data(), metadata.size());
+    } else {
+        uint8_t buffer[SHA_DIGEST_LENGTH];
+        static_assert(sizeof(buffer) >= sizeof(id));
+
+        SHA_CTX ctx;
+        SHA1_Init(&ctx);
+        SHA1_Update(&ctx, metadata.data(), metadata.size());
+        SHA1_Final(buffer, &ctx);
+        memcpy(&id, buffer, sizeof(id));
+    }
+    return id;
+}
+
 IncrementalService::~IncrementalService() = default;
 
 std::optional<std::future<void>> IncrementalService::onSystemReady() {
@@ -300,26 +350,36 @@
             std::unique_ptr<std::string, decltype(firstCleanup)>(&mountRoot, firstCleanup);
 
     auto mountTarget = path::join(mountRoot, constants().mount);
-    if (!mkdirOrLog(path::join(mountRoot, constants().backing)) || !mkdirOrLog(mountTarget)) {
+    const auto backing = path::join(mountRoot, constants().backing);
+    if (!mkdirOrLog(backing, 0777) || !mkdirOrLog(mountTarget)) {
         return kInvalidStorageId;
     }
 
-    const auto image = path::join(mountRoot, constants().backing, constants().image);
     IncFsMount::Control control;
     {
         std::lock_guard l(mMountOperationLock);
         IncrementalFileSystemControlParcel controlParcel;
-        auto status = mVold->mountIncFs(image, mountTarget, incfs::truncate, &controlParcel);
+
+        if (auto err = rmDirContent(backing.c_str())) {
+            LOG(ERROR) << "Coudn't clean the backing directory " << backing << ": " << err;
+            return kInvalidStorageId;
+        }
+        if (!mkdirOrLog(path::join(backing, ".index"), 0777)) {
+            return kInvalidStorageId;
+        }
+        auto status = mVold->mountIncFs(backing, mountTarget, 0, &controlParcel);
         if (!status.isOk()) {
             LOG(ERROR) << "Vold::mountIncFs() failed: " << status.toString8();
             return kInvalidStorageId;
         }
-        if (!controlParcel.cmd || !controlParcel.log) {
+        if (controlParcel.cmd.get() < 0 || controlParcel.pendingReads.get() < 0 ||
+            controlParcel.log.get() < 0) {
             LOG(ERROR) << "Vold::mountIncFs() returned invalid control parcel.";
             return kInvalidStorageId;
         }
-        control.cmdFd = controlParcel.cmd->release();
-        control.logFd = controlParcel.log->release();
+        control.cmd = controlParcel.cmd.release().release();
+        control.pendingReads = controlParcel.pendingReads.release().release();
+        control.logs = controlParcel.log.release().release();
     }
 
     std::unique_lock l(mLock);
@@ -344,7 +404,7 @@
 
     const auto storageIt = ifs->makeStorage(ifs->mountId);
     if (storageIt == ifs->storages.end()) {
-        LOG(ERROR) << "Can't create default storage directory";
+        LOG(ERROR) << "Can't create a default storage directory";
         return kInvalidStorageId;
     }
 
@@ -359,9 +419,12 @@
         m.mutable_loader()->release_arguments();
         m.mutable_loader()->release_class_name();
         m.mutable_loader()->release_package_name();
-        if (auto err = mIncFs->makeFile(ifs->control, constants().infoMdName, INCFS_ROOT_INODE, 0,
-                                        metadata);
-            err < 0) {
+        if (auto err =
+                    mIncFs->makeFile(ifs->control,
+                                     path::join(ifs->root, constants().mount,
+                                                constants().infoMdName),
+                                     0777, idFromMetadata(metadata),
+                                     {.metadata = {metadata.data(), (IncFsSize)metadata.size()}})) {
             LOG(ERROR) << "Saving mount metadata failed: " << -err;
             return kInvalidStorageId;
         }
@@ -369,8 +432,8 @@
 
     const auto bk =
             (options & CreateOptions::PermanentBind) ? BindKind::Permanent : BindKind::Temporary;
-    if (auto err = addBindMount(*ifs, storageIt->first, std::string(storageIt->second.name),
-                                std::move(mountNorm), bk, l);
+    if (auto err = addBindMount(*ifs, storageIt->first, storageIt->second.name,
+                                std::string(storageIt->second.name), std::move(mountNorm), bk, l);
         err < 0) {
         LOG(ERROR) << "adding bind mount failed: " << -err;
         return kInvalidStorageId;
@@ -419,8 +482,9 @@
 
     const auto bk =
             (options & CreateOptions::PermanentBind) ? BindKind::Permanent : BindKind::Temporary;
-    if (auto err = addBindMount(*ifs, storageIt->first, std::string(storageIt->second.name),
-                                path::normalize(mountPoint), bk, l);
+    if (auto err = addBindMount(*ifs, storageIt->first, storageIt->second.name,
+                                std::string(storageIt->second.name), path::normalize(mountPoint),
+                                bk, l);
         err < 0) {
         LOG(ERROR) << "bindMount failed with error: " << err;
         return kInvalidStorageId;
@@ -492,40 +556,36 @@
     return findStorageId(path::normalize(pathInMount));
 }
 
-Inode IncrementalService::nodeFor(StorageId storage, std::string_view subpath) const {
+FileId IncrementalService::nodeFor(StorageId storage, std::string_view subpath) const {
     const auto ifs = getIfs(storage);
     if (!ifs) {
-        return -1;
+        return kIncFsInvalidFileId;
     }
     std::unique_lock l(ifs->lock);
     auto storageIt = ifs->storages.find(storage);
     if (storageIt == ifs->storages.end()) {
-        return -1;
+        return kIncFsInvalidFileId;
     }
     if (subpath.empty() || subpath == "."sv) {
-        return storageIt->second.node;
+        return kIncFsInvalidFileId;
     }
     auto path = path::join(ifs->root, constants().mount, storageIt->second.name, subpath);
     l.unlock();
-    struct stat st;
-    if (::stat(path.c_str(), &st)) {
-        return -1;
-    }
-    return st.st_ino;
+    return mIncFs->getFileId(ifs->control, path);
 }
 
-std::pair<Inode, std::string_view> IncrementalService::parentAndNameFor(
+std::pair<FileId, std::string_view> IncrementalService::parentAndNameFor(
         StorageId storage, std::string_view subpath) const {
     auto name = path::basename(subpath);
     if (name.empty()) {
-        return {-1, {}};
+        return {kIncFsInvalidFileId, {}};
     }
     auto dir = path::dirname(subpath);
     if (dir.empty() || dir == "/"sv) {
-        return {-1, {}};
+        return {kIncFsInvalidFileId, {}};
     }
-    auto inode = nodeFor(storage, dir);
-    return {inode, name};
+    auto id = nodeFor(storage, dir);
+    return {id, name};
 }
 
 IncrementalService::IfsMountPtr IncrementalService::getIfs(StorageId storage) const {
@@ -542,8 +602,8 @@
     return it->second;
 }
 
-int IncrementalService::bind(StorageId storage, std::string_view sourceSubdir,
-                             std::string_view target, BindKind kind) {
+int IncrementalService::bind(StorageId storage, std::string_view source, std::string_view target,
+                             BindKind kind) {
     if (!isValidMountTarget(target)) {
         return -EINVAL;
     }
@@ -552,15 +612,20 @@
     if (!ifs) {
         return -EINVAL;
     }
+    auto normSource = path::normalize(source);
+
     std::unique_lock l(ifs->lock);
     const auto storageInfo = ifs->storages.find(storage);
     if (storageInfo == ifs->storages.end()) {
         return -EINVAL;
     }
-    auto source = path::join(storageInfo->second.name, sourceSubdir);
+    if (!path::startsWith(normSource, storageInfo->second.name)) {
+        return -EINVAL;
+    }
     l.unlock();
     std::unique_lock l2(mLock, std::defer_lock);
-    return addBindMount(*ifs, storage, std::move(source), path::normalize(target), kind, l2);
+    return addBindMount(*ifs, storage, storageInfo->second.name, std::move(normSource),
+                        path::normalize(target), kind, l2);
 }
 
 int IncrementalService::unbind(StorageId storage, std::string_view target) {
@@ -599,90 +664,72 @@
         ifs->bindPoints.erase(bindIt);
         l2.unlock();
         if (!savedFile.empty()) {
-            mIncFs->unlink(ifs->control, INCFS_ROOT_INODE, savedFile);
+            mIncFs->unlink(ifs->control, path::join(ifs->root, constants().mount, savedFile));
         }
     }
     return 0;
 }
 
-Inode IncrementalService::makeFile(StorageId storageId, std::string_view pathUnderStorage,
-                                   long size, std::string_view metadata,
-                                   std::string_view signature) {
-    (void)signature;
-    auto [parentInode, name] = parentAndNameFor(storageId, pathUnderStorage);
-    if (parentInode < 0) {
-        return -EINVAL;
-    }
-    if (auto ifs = getIfs(storageId)) {
-        auto inode = mIncFs->makeFile(ifs->control, name, parentInode, size, metadata);
-        if (inode < 0) {
-            return inode;
+int IncrementalService::makeFile(StorageId storage, std::string_view path, int mode, FileId id,
+                                 incfs::NewFileParams params) {
+    if (auto ifs = getIfs(storage)) {
+        auto err = mIncFs->makeFile(ifs->control, path, mode, id, params);
+        if (err) {
+            return err;
         }
-        auto metadataBytes = std::vector<uint8_t>();
-        if (metadata.data() != nullptr && metadata.size() > 0) {
-            metadataBytes.insert(metadataBytes.end(), &metadata.data()[0],
-                                 &metadata.data()[metadata.size()]);
+        std::vector<uint8_t> metadataBytes;
+        if (params.metadata.data && params.metadata.size > 0) {
+            metadataBytes.assign(params.metadata.data, params.metadata.data + params.metadata.size);
         }
-        mIncrementalManager->newFileForDataLoader(ifs->mountId, inode, metadataBytes);
-        return inode;
+        mIncrementalManager->newFileForDataLoader(ifs->mountId, id, metadataBytes);
+        return 0;
     }
     return -EINVAL;
 }
 
-Inode IncrementalService::makeDir(StorageId storageId, std::string_view pathUnderStorage,
-                                  std::string_view metadata) {
-    auto [parentInode, name] = parentAndNameFor(storageId, pathUnderStorage);
-    if (parentInode < 0) {
-        return -EINVAL;
-    }
+int IncrementalService::makeDir(StorageId storageId, std::string_view path, int mode) {
     if (auto ifs = getIfs(storageId)) {
-        return mIncFs->makeDir(ifs->control, name, parentInode, metadata);
+        return mIncFs->makeDir(ifs->control, path, mode);
     }
     return -EINVAL;
 }
 
-Inode IncrementalService::makeDirs(StorageId storageId, std::string_view pathUnderStorage,
-                                   std::string_view metadata) {
+int IncrementalService::makeDirs(StorageId storageId, std::string_view path, int mode) {
     const auto ifs = getIfs(storageId);
     if (!ifs) {
         return -EINVAL;
     }
-    std::string_view parentDir(pathUnderStorage);
-    auto p = parentAndNameFor(storageId, pathUnderStorage);
-    std::stack<std::string> pathsToCreate;
-    while (p.first < 0) {
-        parentDir = path::dirname(parentDir);
-        pathsToCreate.emplace(parentDir);
-        p = parentAndNameFor(storageId, parentDir);
+
+    auto err = mIncFs->makeDir(ifs->control, path, mode);
+    if (err == -EEXIST) {
+        return 0;
+    } else if (err != -ENOENT) {
+        return err;
     }
-    Inode inode;
-    while (!pathsToCreate.empty()) {
-        p = parentAndNameFor(storageId, pathsToCreate.top());
-        pathsToCreate.pop();
-        inode = mIncFs->makeDir(ifs->control, p.second, p.first, metadata);
-        if (inode < 0) {
-            return inode;
-        }
+    if (auto err = makeDirs(storageId, path::dirname(path), mode)) {
+        return err;
     }
-    return mIncFs->makeDir(ifs->control, path::basename(pathUnderStorage), inode, metadata);
+    return mIncFs->makeDir(ifs->control, path, mode);
 }
 
-int IncrementalService::link(StorageId storage, Inode item, Inode newParent,
-                             std::string_view newName) {
-    if (auto ifs = getIfs(storage)) {
-        return mIncFs->link(ifs->control, item, newParent, newName);
+int IncrementalService::link(StorageId sourceStorageId, std::string_view oldPath,
+                             StorageId destStorageId, std::string_view newPath) {
+    if (auto ifsSrc = getIfs(sourceStorageId), ifsDest = getIfs(destStorageId);
+        ifsSrc && ifsSrc == ifsDest) {
+        return mIncFs->link(ifsSrc->control, oldPath, newPath);
     }
     return -EINVAL;
 }
 
-int IncrementalService::unlink(StorageId storage, Inode parent, std::string_view name) {
+int IncrementalService::unlink(StorageId storage, std::string_view path) {
     if (auto ifs = getIfs(storage)) {
-        return mIncFs->unlink(ifs->control, parent, name);
+        return mIncFs->unlink(ifs->control, path);
     }
     return -EINVAL;
 }
 
-int IncrementalService::addBindMount(IncFsMount& ifs, StorageId storage, std::string&& sourceSubdir,
+int IncrementalService::addBindMount(IncFsMount& ifs, StorageId storage,
+                                     std::string_view storageRoot, std::string&& source,
                                      std::string&& target, BindKind kind,
                                      std::unique_lock<std::mutex>& mainLock) {
     if (!isValidMountTarget(target)) {
@@ -694,30 +741,30 @@
         metadata::BindPoint bp;
         bp.set_storage_id(storage);
         bp.set_allocated_dest_path(&target);
-        bp.set_allocated_source_subdir(&sourceSubdir);
+        bp.set_source_subdir(std::string(path::relativize(storageRoot, source)));
         const auto metadata = bp.SerializeAsString();
-        bp.release_source_subdir();
         bp.release_dest_path();
         mdFileName = makeBindMdName();
-        auto node = mIncFs->makeFile(ifs.control, mdFileName, INCFS_ROOT_INODE, 0, metadata);
-        if (node < 0) {
+        auto node =
+                mIncFs->makeFile(ifs.control, path::join(ifs.root, constants().mount, mdFileName),
+                                 0444, idFromMetadata(metadata),
+                                 {.metadata = {metadata.data(), (IncFsSize)metadata.size()}});
+        if (node) {
             return int(node);
         }
     }
 
-    return addBindMountWithMd(ifs, storage, std::move(mdFileName), std::move(sourceSubdir),
+    return addBindMountWithMd(ifs, storage, std::move(mdFileName), std::move(source),
                               std::move(target), kind, mainLock);
 }
 
 int IncrementalService::addBindMountWithMd(IncrementalService::IncFsMount& ifs, StorageId storage,
-                                           std::string&& metadataName, std::string&& sourceSubdir,
+                                           std::string&& metadataName, std::string&& source,
                                            std::string&& target, BindKind kind,
                                            std::unique_lock<std::mutex>& mainLock) {
-    LOG(INFO) << "Adding bind mount: " << sourceSubdir << " -> " << target;
     {
-        auto path = path::join(ifs.root, constants().mount, sourceSubdir);
         std::lock_guard l(mMountOperationLock);
-        const auto status = mVold->bindMount(path, target);
+        const auto status = mVold->bindMount(source, target);
         if (!status.isOk()) {
             LOG(ERROR) << "Calling Vold::bindMount() failed: " << status.toString8();
             return status.exceptionCode() == binder::Status::EX_SERVICE_SPECIFIC
@@ -736,12 +783,12 @@
     const auto [it, _] =
             ifs.bindPoints.insert_or_assign(target,
                                             IncFsMount::Bind{storage, std::move(metadataName),
-                                                             std::move(sourceSubdir), kind});
+                                                             std::move(source), kind});
     mBindsByPath[std::move(target)] = it;
     return 0;
 }
 
-RawMetadata IncrementalService::getMetadata(StorageId storage, Inode node) const {
+RawMetadata IncrementalService::getMetadata(StorageId storage, FileId node) const {
     const auto ifs = getIfs(storage);
     if (!ifs) {
         return {};
@@ -831,21 +878,18 @@
     LOG(INFO) << "Trying to mount: " << key;
 
     auto mountTarget = path::join(root, constants().mount);
-    const auto image = path::join(root, constants().backing, constants().image);
+    const auto backing = path::join(root, constants().backing);
 
     IncFsMount::Control control;
     IncrementalFileSystemControlParcel controlParcel;
-    auto status = mVold->mountIncFs(image, mountTarget, 0, &controlParcel);
+    auto status = mVold->mountIncFs(backing, mountTarget, 0, &controlParcel);
     if (!status.isOk()) {
         LOG(ERROR) << "Vold::mountIncFs() failed: " << status.toString8();
         return false;
     }
-    if (controlParcel.cmd) {
-        control.cmdFd = controlParcel.cmd->release();
-    }
-    if (controlParcel.log) {
-        control.logFd = controlParcel.log->release();
-    }
+    control.cmd = controlParcel.cmd.release().release();
+    control.pendingReads = controlParcel.pendingReads.release().release();
+    control.logs = controlParcel.log.release().release();
 
     auto ifs = std::make_shared<IncFsMount>(std::string(root), -1, std::move(control), *this);
 
@@ -860,8 +904,7 @@
     mNextId = std::max(mNextId, ifs->mountId + 1);
 
     std::vector<std::pair<std::string, metadata::BindPoint>> bindPoints;
-    auto d = std::unique_ptr<DIR, decltype(&::closedir)>(::opendir(path::c_str(mountTarget)),
-                                                         ::closedir);
+    auto d = openDir(path::c_str(mountTarget));
     while (auto e = ::readdir(d.get())) {
         if (e->d_type == DT_REG) {
             auto name = std::string_view(e->d_name);
@@ -874,7 +917,7 @@
                 if (bindPoints.back().second.dest_path().empty() ||
                     bindPoints.back().second.source_subdir().empty()) {
                     bindPoints.pop_back();
-                    mIncFs->unlink(ifs->control, INCFS_ROOT_INODE, name);
+                    mIncFs->unlink(ifs->control, path::join(ifs->root, constants().mount, name));
                 }
             }
         } else if (e->d_type == DT_DIR) {
@@ -891,9 +934,7 @@
                                  << " for mount " << root;
                     continue;
                 }
-                ifs->storages.insert_or_assign(md.id(),
-                                               IncFsMount::Storage{std::string(name),
-                                                                   Inode(e->d_ino)});
+                ifs->storages.insert_or_assign(md.id(), IncFsMount::Storage{std::string(name)});
                 mNextId = std::max(mNextId, md.id() + 1);
             }
         }
@@ -973,10 +1014,10 @@
     }
     FileSystemControlParcel fsControlParcel;
     fsControlParcel.incremental = std::make_unique<IncrementalFileSystemControlParcel>();
-    fsControlParcel.incremental->cmd =
-            std::make_unique<os::ParcelFileDescriptor>(base::unique_fd(::dup(ifs.control.cmdFd)));
-    fsControlParcel.incremental->log =
-            std::make_unique<os::ParcelFileDescriptor>(base::unique_fd(::dup(ifs.control.logFd)));
+    fsControlParcel.incremental->cmd.reset(base::unique_fd(::dup(ifs.control.cmd)));
+    fsControlParcel.incremental->pendingReads.reset(
+            base::unique_fd(::dup(ifs.control.pendingReads)));
+    fsControlParcel.incremental->log.reset(base::unique_fd(::dup(ifs.control.logs)));
     sp<IncrementalDataLoaderListener> listener = new IncrementalDataLoaderListener(*this);
     bool created = false;
     auto status = mIncrementalManager->prepareDataLoader(ifs.mountId, fsControlParcel, *dlp,
diff --git a/services/incremental/IncrementalService.h b/services/incremental/IncrementalService.h
index a03ffa0..ca5e4db 100644
--- a/services/incremental/IncrementalService.h
+++ b/services/incremental/IncrementalService.h
@@ -52,16 +52,16 @@
 
 using MountId = int;
 using StorageId = int;
-using Inode = incfs::Inode;
+using FileId = incfs::FileId;
 using BlockIndex = incfs::BlockIndex;
 using RawMetadata = incfs::RawMetadata;
 using Clock = std::chrono::steady_clock;
 using TimePoint = std::chrono::time_point<Clock>;
 using Seconds = std::chrono::seconds;
 
-class IncrementalService {
+class IncrementalService final {
 public:
-    explicit IncrementalService(const ServiceManagerWrapper& sm, std::string_view rootDir);
+    explicit IncrementalService(ServiceManagerWrapper&& sm, std::string_view rootDir);
 
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
@@ -85,6 +85,11 @@
         Permanent = 1,
     };
 
+    static FileId idFromMetadata(std::span<const uint8_t> metadata);
+    static inline FileId idFromMetadata(std::span<const char> metadata) {
+        return idFromMetadata({(const uint8_t*)metadata.data(), metadata.size()});
+    }
+
     std::optional<std::future<void>> onSystemReady();
 
     StorageId createStorage(std::string_view mountPoint,
@@ -92,30 +97,31 @@
                             CreateOptions options = CreateOptions::Default);
     StorageId createLinkedStorage(std::string_view mountPoint, StorageId linkedStorage,
                                   CreateOptions options = CreateOptions::Default);
-    StorageId openStorage(std::string_view pathInMount);
+    StorageId openStorage(std::string_view path);
 
-    Inode nodeFor(StorageId storage, std::string_view subpath) const;
-    std::pair<Inode, std::string_view> parentAndNameFor(StorageId storage,
-                                                        std::string_view subpath) const;
+    FileId nodeFor(StorageId storage, std::string_view path) const;
+    std::pair<FileId, std::string_view> parentAndNameFor(StorageId storage,
+                                                         std::string_view path) const;
 
-    int bind(StorageId storage, std::string_view subdir, std::string_view target, BindKind kind);
+    int bind(StorageId storage, std::string_view source, std::string_view target, BindKind kind);
     int unbind(StorageId storage, std::string_view target);
     void deleteStorage(StorageId storage);
 
-    Inode makeFile(StorageId storage, std::string_view name, long size, std::string_view metadata,
-                   std::string_view signature);
-    Inode makeDir(StorageId storage, std::string_view name, std::string_view metadata = {});
-    Inode makeDirs(StorageId storage, std::string_view name, std::string_view metadata = {});
+    int makeFile(StorageId storage, std::string_view path, int mode, FileId id,
+                 incfs::NewFileParams params);
+    int makeDir(StorageId storage, std::string_view path, int mode = 0555);
+    int makeDirs(StorageId storage, std::string_view path, int mode = 0555);
 
-    int link(StorageId storage, Inode item, Inode newParent, std::string_view newName);
-    int unlink(StorageId storage, Inode parent, std::string_view name);
+    int link(StorageId sourceStorageId, std::string_view oldPath, StorageId destStorageId,
+             std::string_view newPath);
+    int unlink(StorageId storage, std::string_view path);
 
-    bool isRangeLoaded(StorageId storage, Inode file, std::pair<BlockIndex, BlockIndex> range) {
+    bool isRangeLoaded(StorageId storage, FileId file, std::pair<BlockIndex, BlockIndex> range) {
         return false;
     }
 
-    RawMetadata getMetadata(StorageId storage, Inode node) const;
-    std::string getSigngatureData(StorageId storage, Inode node) const { return {}; }
+    RawMetadata getMetadata(StorageId storage, FileId node) const;
+    std::string getSignatureData(StorageId storage, FileId node) const;
 
     std::vector<std::string> listFiles(StorageId storage) const;
     bool startLoading(StorageId storage) const;
@@ -142,19 +148,9 @@
 
         struct Storage {
             std::string name;
-            Inode node;
         };
 
-        struct Control {
-            operator IncFsControl() const { return {cmdFd, logFd}; }
-            void reset() {
-                cmdFd.reset();
-                logFd.reset();
-            }
-
-            base::unique_fd cmdFd;
-            base::unique_fd logFd;
-        };
+        using Control = incfs::UniqueControl;
 
         using BindMap = std::map<std::string, Bind>;
         using StorageMap = std::unordered_map<StorageId, Storage>;
@@ -196,11 +192,12 @@
 
     IfsMountPtr getIfs(StorageId storage) const;
     const IfsMountPtr& getIfsLocked(StorageId storage) const;
-    int addBindMount(IncFsMount& ifs, StorageId storage, std::string&& sourceSubdir,
-                     std::string&& target, BindKind kind, std::unique_lock<std::mutex>& mainLock);
+    int addBindMount(IncFsMount& ifs, StorageId storage, std::string_view storageRoot,
+                     std::string&& source, std::string&& target, BindKind kind,
+                     std::unique_lock<std::mutex>& mainLock);
 
     int addBindMountWithMd(IncFsMount& ifs, StorageId storage, std::string&& metadataName,
-                           std::string&& sourceSubdir, std::string&& target, BindKind kind,
+                           std::string&& source, std::string&& target, BindKind kind,
                            std::unique_lock<std::mutex>& mainLock);
 
     bool prepareDataLoader(IncFsMount& ifs, DataLoaderParamsParcel* params);
@@ -212,10 +209,9 @@
     MountMap::iterator getStorageSlotLocked();
 
     // Member variables
-    // These are shared pointers for the sake of unit testing
-    std::shared_ptr<VoldServiceWrapper> mVold;
-    std::shared_ptr<IncrementalManagerWrapper> mIncrementalManager;
-    std::shared_ptr<IncFsWrapper> mIncFs;
+    std::unique_ptr<VoldServiceWrapper> mVold;
+    std::unique_ptr<IncrementalManagerWrapper> mIncrementalManager;
+    std::unique_ptr<IncFsWrapper> mIncFs;
     const std::string mIncrementalDir;
 
     mutable std::mutex mLock;
diff --git a/services/incremental/ServiceWrappers.cpp b/services/incremental/ServiceWrappers.cpp
index a79b26a..5d978a1 100644
--- a/services/incremental/ServiceWrappers.cpp
+++ b/services/incremental/ServiceWrappers.cpp
@@ -16,14 +16,8 @@
 
 #include "ServiceWrappers.h"
 
-#include <android-base/strings.h>
-#include <android-base/unique_fd.h>
-#include <binder/IServiceManager.h>
 #include <utils/String16.h>
 
-#include <string>
-#include <string_view>
-
 using namespace std::literals;
 
 namespace android::os::incremental {
@@ -31,37 +25,38 @@
 static constexpr auto kVoldServiceName = "vold"sv;
 static constexpr auto kIncrementalManagerName = "incremental"sv;
 
-RealServiceManager::RealServiceManager(const sp<IServiceManager>& serviceManager)
-      : mServiceManager(serviceManager) {}
+RealServiceManager::RealServiceManager(sp<IServiceManager> serviceManager)
+      : mServiceManager(std::move(serviceManager)) {}
 
 template <class INTERFACE>
 sp<INTERFACE> RealServiceManager::getRealService(std::string_view serviceName) const {
-    sp<IBinder> binder = mServiceManager->getService(String16(serviceName.data()));
-    if (binder == 0) {
-        return 0;
+    sp<IBinder> binder =
+            mServiceManager->getService(String16(serviceName.data(), serviceName.size()));
+    if (!binder) {
+        return nullptr;
     }
     return interface_cast<INTERFACE>(binder);
 }
 
-std::shared_ptr<VoldServiceWrapper> RealServiceManager::getVoldService() const {
+std::unique_ptr<VoldServiceWrapper> RealServiceManager::getVoldService() {
     sp<os::IVold> vold = RealServiceManager::getRealService<os::IVold>(kVoldServiceName);
     if (vold != 0) {
-        return std::make_shared<RealVoldService>(vold);
+        return std::make_unique<RealVoldService>(vold);
     }
     return nullptr;
 }
 
-std::shared_ptr<IncrementalManagerWrapper> RealServiceManager::getIncrementalManager() const {
+std::unique_ptr<IncrementalManagerWrapper> RealServiceManager::getIncrementalManager() {
     sp<IIncrementalManager> manager =
             RealServiceManager::getRealService<IIncrementalManager>(kIncrementalManagerName);
-    if (manager != 0) {
-        return std::make_shared<RealIncrementalManager>(manager);
+    if (manager) {
+        return std::make_unique<RealIncrementalManager>(manager);
     }
     return nullptr;
 }
 
-std::shared_ptr<IncFsWrapper> RealServiceManager::getIncFs() const {
-    return std::make_shared<RealIncFs>();
+std::unique_ptr<IncFsWrapper> RealServiceManager::getIncFs() {
+    return std::make_unique<RealIncFs>();
 }
 
 } // namespace android::os::incremental
diff --git a/services/incremental/ServiceWrappers.h b/services/incremental/ServiceWrappers.h
index 5704582..ae3739d 100644
--- a/services/incremental/ServiceWrappers.h
+++ b/services/incremental/ServiceWrappers.h
@@ -26,6 +26,7 @@
 #include <binder/IServiceManager.h>
 #include <incfs.h>
 
+#include <memory>
 #include <string>
 #include <string_view>
 
@@ -36,10 +37,12 @@
 
 // --- Wrapper interfaces ---
 
+using MountId = int32_t;
+
 class VoldServiceWrapper {
 public:
-    virtual ~VoldServiceWrapper(){};
-    virtual binder::Status mountIncFs(const std::string& imagePath, const std::string& targetDir,
+    virtual ~VoldServiceWrapper() = default;
+    virtual binder::Status mountIncFs(const std::string& backingPath, const std::string& targetDir,
                                       int32_t flags,
                                       IncrementalFileSystemControlParcel* _aidl_return) const = 0;
     virtual binder::Status unmountIncFs(const std::string& dir) const = 0;
@@ -49,52 +52,52 @@
 
 class IncrementalManagerWrapper {
 public:
-    virtual ~IncrementalManagerWrapper() {}
-    virtual binder::Status prepareDataLoader(
-            int32_t mountId, const FileSystemControlParcel& control,
-            const DataLoaderParamsParcel& params,
-            const sp<IDataLoaderStatusListener>& listener,
-            bool* _aidl_return) const = 0;
-    virtual binder::Status startDataLoader(int32_t mountId, bool* _aidl_return) const = 0;
-    virtual binder::Status destroyDataLoader(int32_t mountId) const = 0;
-    virtual binder::Status newFileForDataLoader(int32_t mountId, int64_t inode,
-                                                const ::std::vector<uint8_t>& metadata) const = 0;
-    virtual binder::Status showHealthBlockedUI(int32_t mountId) const = 0;
+    virtual ~IncrementalManagerWrapper() = default;
+    virtual binder::Status prepareDataLoader(MountId mountId,
+                                             const FileSystemControlParcel& control,
+                                             const DataLoaderParamsParcel& params,
+                                             const sp<IDataLoaderStatusListener>& listener,
+                                             bool* _aidl_return) const = 0;
+    virtual binder::Status startDataLoader(MountId mountId, bool* _aidl_return) const = 0;
+    virtual binder::Status destroyDataLoader(MountId mountId) const = 0;
+    virtual binder::Status newFileForDataLoader(MountId mountId, FileId fileid,
+                                                const std::vector<uint8_t>& metadata) const = 0;
+    virtual binder::Status showHealthBlockedUI(MountId mountId) const = 0;
 };
 
 class IncFsWrapper {
 public:
-    virtual ~IncFsWrapper() {}
-    virtual Inode makeFile(Control control, std::string_view name, Inode parent, Size size,
-                           std::string_view metadata) const = 0;
-    virtual Inode makeDir(Control control, std::string_view name, Inode parent,
-                          std::string_view metadata, int mode = 0555) const = 0;
-    virtual RawMetadata getMetadata(Control control, Inode inode) const = 0;
-    virtual ErrorCode link(Control control, Inode item, Inode targetParent,
-                           std::string_view name) const = 0;
-    virtual ErrorCode unlink(Control control, Inode parent, std::string_view name) const = 0;
-    virtual ErrorCode writeBlocks(Control control, const incfs_new_data_block blocks[],
-                                  int blocksCount) const = 0;
+    virtual ~IncFsWrapper() = default;
+    virtual ErrorCode makeFile(Control control, std::string_view path, int mode, FileId id,
+                               NewFileParams params) const = 0;
+    virtual ErrorCode makeDir(Control control, std::string_view path, int mode = 0555) const = 0;
+    virtual RawMetadata getMetadata(Control control, FileId fileid) const = 0;
+    virtual RawMetadata getMetadata(Control control, std::string_view path) const = 0;
+    virtual FileId getFileId(Control control, std::string_view path) const = 0;
+    virtual ErrorCode link(Control control, std::string_view from, std::string_view to) const = 0;
+    virtual ErrorCode unlink(Control control, std::string_view path) const = 0;
+    virtual base::unique_fd openWrite(Control control, FileId id) const = 0;
+    virtual ErrorCode writeBlocks(std::span<const DataBlock> blocks) const = 0;
 };
 
 class ServiceManagerWrapper {
 public:
-    virtual ~ServiceManagerWrapper() {}
-    virtual std::shared_ptr<VoldServiceWrapper> getVoldService() const = 0;
-    virtual std::shared_ptr<IncrementalManagerWrapper> getIncrementalManager() const = 0;
-    virtual std::shared_ptr<IncFsWrapper> getIncFs() const = 0;
+    virtual ~ServiceManagerWrapper() = default;
+    virtual std::unique_ptr<VoldServiceWrapper> getVoldService() = 0;
+    virtual std::unique_ptr<IncrementalManagerWrapper> getIncrementalManager() = 0;
+    virtual std::unique_ptr<IncFsWrapper> getIncFs() = 0;
 };
 
 // --- Real stuff ---
 
 class RealVoldService : public VoldServiceWrapper {
 public:
-    RealVoldService(const sp<os::IVold> vold) : mInterface(vold) {}
+    RealVoldService(const sp<os::IVold> vold) : mInterface(std::move(vold)) {}
     ~RealVoldService() = default;
-    binder::Status mountIncFs(const std::string& imagePath, const std::string& targetDir,
+    binder::Status mountIncFs(const std::string& backingPath, const std::string& targetDir,
                               int32_t flags,
                               IncrementalFileSystemControlParcel* _aidl_return) const override {
-        return mInterface->mountIncFs(imagePath, targetDir, flags, _aidl_return);
+        return mInterface->mountIncFs(backingPath, targetDir, flags, _aidl_return);
     }
     binder::Status unmountIncFs(const std::string& dir) const override {
         return mInterface->unmountIncFs(dir);
@@ -113,24 +116,26 @@
     RealIncrementalManager(const sp<os::incremental::IIncrementalManager> manager)
           : mInterface(manager) {}
     ~RealIncrementalManager() = default;
-    binder::Status prepareDataLoader(
-            int32_t mountId, const FileSystemControlParcel& control,
-            const DataLoaderParamsParcel& params,
-            const sp<IDataLoaderStatusListener>& listener,
-            bool* _aidl_return) const override {
+    binder::Status prepareDataLoader(MountId mountId, const FileSystemControlParcel& control,
+                                     const DataLoaderParamsParcel& params,
+                                     const sp<IDataLoaderStatusListener>& listener,
+                                     bool* _aidl_return) const override {
         return mInterface->prepareDataLoader(mountId, control, params, listener, _aidl_return);
     }
-    binder::Status startDataLoader(int32_t mountId, bool* _aidl_return) const override {
+    binder::Status startDataLoader(MountId mountId, bool* _aidl_return) const override {
         return mInterface->startDataLoader(mountId, _aidl_return);
     }
-    binder::Status destroyDataLoader(int32_t mountId) const override {
+    binder::Status destroyDataLoader(MountId mountId) const override {
         return mInterface->destroyDataLoader(mountId);
     }
-    binder::Status newFileForDataLoader(int32_t mountId, int64_t inode,
-                                        const ::std::vector<uint8_t>& metadata) const override {
-        return mInterface->newFileForDataLoader(mountId, inode, metadata);
+    binder::Status newFileForDataLoader(MountId mountId, FileId fileid,
+                                        const std::vector<uint8_t>& metadata) const override {
+        return mInterface->newFileForDataLoader(mountId,
+                                                {(const uint8_t*)fileid.data,
+                                                 (const uint8_t*)fileid.data + sizeof(fileid.data)},
+                                                metadata);
     }
-    binder::Status showHealthBlockedUI(int32_t mountId) const override {
+    binder::Status showHealthBlockedUI(MountId mountId) const override {
         return mInterface->showHealthBlockedUI(mountId);
     }
 
@@ -140,11 +145,11 @@
 
 class RealServiceManager : public ServiceManagerWrapper {
 public:
-    RealServiceManager(const sp<IServiceManager>& serviceManager);
+    RealServiceManager(sp<IServiceManager> serviceManager);
     ~RealServiceManager() = default;
-    std::shared_ptr<VoldServiceWrapper> getVoldService() const override;
-    std::shared_ptr<IncrementalManagerWrapper> getIncrementalManager() const override;
-    std::shared_ptr<IncFsWrapper> getIncFs() const override;
+    std::unique_ptr<VoldServiceWrapper> getVoldService() override;
+    std::unique_ptr<IncrementalManagerWrapper> getIncrementalManager() override;
+    std::unique_ptr<IncFsWrapper> getIncFs() override;
 
 private:
     template <class INTERFACE>
@@ -156,27 +161,33 @@
 public:
     RealIncFs() = default;
     ~RealIncFs() = default;
-    Inode makeFile(Control control, std::string_view name, Inode parent, Size size,
-                   std::string_view metadata) const override {
-        return incfs::makeFile(control, name, parent, size, metadata);
+    ErrorCode makeFile(Control control, std::string_view path, int mode, FileId id,
+                       NewFileParams params) const override {
+        return incfs::makeFile(control, path, mode, id, params);
     }
-    Inode makeDir(Control control, std::string_view name, Inode parent, std::string_view metadata,
-                  int mode) const override {
-        return incfs::makeDir(control, name, parent, metadata, mode);
+    ErrorCode makeDir(Control control, std::string_view path, int mode) const override {
+        return incfs::makeDir(control, path, mode);
     }
-    RawMetadata getMetadata(Control control, Inode inode) const override {
-        return incfs::getMetadata(control, inode);
+    RawMetadata getMetadata(Control control, FileId fileid) const override {
+        return incfs::getMetadata(control, fileid);
     }
-    ErrorCode link(Control control, Inode item, Inode targetParent,
-                   std::string_view name) const override {
-        return incfs::link(control, item, targetParent, name);
+    RawMetadata getMetadata(Control control, std::string_view path) const override {
+        return incfs::getMetadata(control, path);
     }
-    ErrorCode unlink(Control control, Inode parent, std::string_view name) const override {
-        return incfs::unlink(control, parent, name);
+    FileId getFileId(Control control, std::string_view path) const override {
+        return incfs::getFileId(control, path);
     }
-    ErrorCode writeBlocks(Control control, const incfs_new_data_block blocks[],
-                          int blocksCount) const override {
-        return incfs::writeBlocks(control, blocks, blocksCount);
+    ErrorCode link(Control control, std::string_view from, std::string_view to) const override {
+        return incfs::link(control, from, to);
+    }
+    ErrorCode unlink(Control control, std::string_view path) const override {
+        return incfs::unlink(control, path);
+    }
+    base::unique_fd openWrite(Control control, FileId id) const override {
+        return base::unique_fd{incfs::openWrite(control, id)};
+    }
+    ErrorCode writeBlocks(std::span<const DataBlock> blocks) const override {
+        return incfs::writeBlocks(blocks);
     }
 };
 
diff --git a/services/incremental/path.cpp b/services/incremental/path.cpp
index c529d61..0d86f2a 100644
--- a/services/incremental/path.cpp
+++ b/services/incremental/path.cpp
@@ -44,16 +44,45 @@
                                         PathCharsLess());
 }
 
+static void preparePathComponent(std::string_view path, bool trimFront) {
+    if (trimFront) {
+        while (!path.empty() && path.front() == '/') {
+            path.remove_prefix(1);
+        }
+    }
+    while (!path.empty() && path.back() == '/') {
+        path.remove_suffix(1);
+    }
+}
+
 void details::append_next_path(std::string& target, std::string_view path) {
+    preparePathComponent(path, true);
     if (path.empty()) {
         return;
     }
-    if (!target.empty()) {
+    if (!target.empty() && !target.ends_with('/')) {
         target.push_back('/');
     }
     target += path;
 }
 
+std::string_view relativize(std::string_view parent, std::string_view nested) {
+    if (!nested.starts_with(parent)) {
+        return nested;
+    }
+    if (nested.size() == parent.size()) {
+        return {};
+    }
+    if (nested[parent.size()] != '/') {
+        return nested;
+    }
+    auto relative = nested.substr(parent.size());
+    while (relative.front() == '/') {
+        relative.remove_prefix(1);
+    }
+    return relative;
+}
+
 bool isAbsolute(std::string_view path) {
     return !path.empty() && path[0] == '/';
 }
diff --git a/services/incremental/path.h b/services/incremental/path.h
index a1f4b8e..3e5fd21 100644
--- a/services/incremental/path.h
+++ b/services/incremental/path.h
@@ -67,6 +67,20 @@
     return {sv};
 }
 
+std::string_view relativize(std::string_view parent, std::string_view nested);
+inline std::string_view relativize(const char* parent, const char* nested) {
+    return relativize(std::string_view(parent), std::string_view(nested));
+}
+inline std::string_view relativize(std::string_view parent, const char* nested) {
+    return relativize(parent, std::string_view(nested));
+}
+inline std::string_view relativize(const char* parent, std::string_view nested) {
+    return relativize(std::string_view(parent), nested);
+}
+
+std::string_view relativize(std::string&& parent, std::string_view nested) = delete;
+std::string_view relativize(std::string_view parent, std::string&& nested) = delete;
+
 bool isAbsolute(std::string_view path);
 std::string normalize(std::string_view path);
 std::string_view dirname(std::string_view path);
diff --git a/services/incremental/test/IncrementalServiceTest.cpp b/services/incremental/test/IncrementalServiceTest.cpp
index ca1e1a9..2826818 100644
--- a/services/incremental/test/IncrementalServiceTest.cpp
+++ b/services/incremental/test/IncrementalServiceTest.cpp
@@ -46,7 +46,7 @@
 class MockVoldService : public VoldServiceWrapper {
 public:
     MOCK_CONST_METHOD4(mountIncFs,
-                       binder::Status(const std::string& imagePath, const std::string& targetDir,
+                       binder::Status(const std::string& backingPath, const std::string& targetDir,
                                       int32_t flags,
                                       IncrementalFileSystemControlParcel* _aidl_return));
     MOCK_CONST_METHOD1(unmountIncFs, binder::Status(const std::string& dir));
@@ -77,22 +77,20 @@
     binder::Status getInvalidControlParcel(const std::string& imagePath,
                                            const std::string& targetDir, int32_t flags,
                                            IncrementalFileSystemControlParcel* _aidl_return) {
-        _aidl_return->cmd = nullptr;
-        _aidl_return->log = nullptr;
+        _aidl_return = {};
         return binder::Status::ok();
     }
     binder::Status incFsSuccess(const std::string& imagePath, const std::string& targetDir,
                                 int32_t flags, IncrementalFileSystemControlParcel* _aidl_return) {
-        _aidl_return->cmd = std::make_unique<os::ParcelFileDescriptor>(std::move(cmdFd));
-        _aidl_return->log = std::make_unique<os::ParcelFileDescriptor>(std::move(logFd));
+        _aidl_return->pendingReads.reset(base::unique_fd(dup(STDIN_FILENO)));
+        _aidl_return->cmd.reset(base::unique_fd(dup(STDIN_FILENO)));
+        _aidl_return->log.reset(base::unique_fd(dup(STDIN_FILENO)));
         return binder::Status::ok();
     }
 
 private:
     TemporaryFile cmdFile;
     TemporaryFile logFile;
-    base::unique_fd cmdFd;
-    base::unique_fd logFd;
 };
 
 class MockIncrementalManager : public IncrementalManagerWrapper {
@@ -105,7 +103,7 @@
     MOCK_CONST_METHOD2(startDataLoader, binder::Status(int32_t mountId, bool* _aidl_return));
     MOCK_CONST_METHOD1(destroyDataLoader, binder::Status(int32_t mountId));
     MOCK_CONST_METHOD3(newFileForDataLoader,
-                       binder::Status(int32_t mountId, int64_t inode,
+                       binder::Status(int32_t mountId, FileId fileId,
                                       const ::std::vector<uint8_t>& metadata));
     MOCK_CONST_METHOD1(showHealthBlockedUI, binder::Status(int32_t mountId));
 
@@ -152,23 +150,21 @@
 class MockIncFs : public IncFsWrapper {
 public:
     MOCK_CONST_METHOD5(makeFile,
-                       Inode(Control control, std::string_view name, Inode parent, Size size,
-                             std::string_view metadata));
-    MOCK_CONST_METHOD5(makeDir,
-                       Inode(Control control, std::string_view name, Inode parent,
-                             std::string_view metadata, int mode));
-    MOCK_CONST_METHOD2(getMetadata, RawMetadata(Control control, Inode inode));
-    MOCK_CONST_METHOD4(link,
-                       ErrorCode(Control control, Inode item, Inode targetParent,
-                                 std::string_view name));
-    MOCK_CONST_METHOD3(unlink, ErrorCode(Control control, Inode parent, std::string_view name));
-    MOCK_CONST_METHOD3(writeBlocks,
-                       ErrorCode(Control control, const incfs_new_data_block blocks[],
-                                 int blocksCount));
+                       ErrorCode(Control control, std::string_view path, int mode, FileId id,
+                                 NewFileParams params));
+    MOCK_CONST_METHOD3(makeDir, ErrorCode(Control control, std::string_view path, int mode));
+    MOCK_CONST_METHOD2(getMetadata, RawMetadata(Control control, FileId fileid));
+    MOCK_CONST_METHOD2(getMetadata, RawMetadata(Control control, std::string_view path));
+    MOCK_CONST_METHOD2(getFileId, FileId(Control control, std::string_view path));
+    MOCK_CONST_METHOD3(link,
+                       ErrorCode(Control control, std::string_view from, std::string_view to));
+    MOCK_CONST_METHOD2(unlink, ErrorCode(Control control, std::string_view path));
+    MOCK_CONST_METHOD2(openWrite, base::unique_fd(Control control, FileId id));
+    MOCK_CONST_METHOD1(writeBlocks, ErrorCode(std::span<const DataBlock> blocks));
 
     void makeFileFails() { ON_CALL(*this, makeFile(_, _, _, _, _)).WillByDefault(Return(-1)); }
     void makeFileSuccess() { ON_CALL(*this, makeFile(_, _, _, _, _)).WillByDefault(Return(0)); }
-    RawMetadata getMountInfoMetadata(Control control, Inode inode) {
+    RawMetadata getMountInfoMetadata(Control control, std::string_view path) {
         metadata::Mount m;
         m.mutable_storage()->set_id(100);
         m.mutable_loader()->set_package_name("com.test");
@@ -176,15 +172,15 @@
         const auto metadata = m.SerializeAsString();
         m.mutable_loader()->release_arguments();
         m.mutable_loader()->release_package_name();
-        return std::vector<char>(metadata.begin(), metadata.end());
+        return {metadata.begin(), metadata.end()};
     }
-    RawMetadata getStorageMetadata(Control control, Inode inode) {
+    RawMetadata getStorageMetadata(Control control, std::string_view path) {
         metadata::Storage st;
         st.set_id(100);
         auto metadata = st.SerializeAsString();
-        return std::vector<char>(metadata.begin(), metadata.end());
+        return {metadata.begin(), metadata.end()};
     }
-    RawMetadata getBindPointMetadata(Control control, Inode inode) {
+    RawMetadata getBindPointMetadata(Control control, std::string_view path) {
         metadata::BindPoint bp;
         std::string destPath = "dest";
         std::string srcPath = "src";
@@ -200,40 +196,41 @@
 
 class MockServiceManager : public ServiceManagerWrapper {
 public:
-    MockServiceManager(std::shared_ptr<MockVoldService> vold,
-                       std::shared_ptr<MockIncrementalManager> manager,
-                       std::shared_ptr<MockIncFs> incfs)
-          : mVold(vold), mIncrementalManager(manager), mIncFs(incfs) {}
-    std::shared_ptr<VoldServiceWrapper> getVoldService() const override { return mVold; }
-    std::shared_ptr<IncrementalManagerWrapper> getIncrementalManager() const override {
-        return mIncrementalManager;
+    MockServiceManager(std::unique_ptr<MockVoldService> vold,
+                       std::unique_ptr<MockIncrementalManager> manager,
+                       std::unique_ptr<MockIncFs> incfs)
+          : mVold(std::move(vold)),
+            mIncrementalManager(std::move(manager)),
+            mIncFs(std::move(incfs)) {}
+    std::unique_ptr<VoldServiceWrapper> getVoldService() final { return std::move(mVold); }
+    std::unique_ptr<IncrementalManagerWrapper> getIncrementalManager() final {
+        return std::move(mIncrementalManager);
     }
-    std::shared_ptr<IncFsWrapper> getIncFs() const override { return mIncFs; }
+    std::unique_ptr<IncFsWrapper> getIncFs() final { return std::move(mIncFs); }
 
 private:
-    std::shared_ptr<MockVoldService> mVold;
-    std::shared_ptr<MockIncrementalManager> mIncrementalManager;
-    std::shared_ptr<MockIncFs> mIncFs;
+    std::unique_ptr<MockVoldService> mVold;
+    std::unique_ptr<MockIncrementalManager> mIncrementalManager;
+    std::unique_ptr<MockIncFs> mIncFs;
 };
 
 // --- IncrementalServiceTest ---
 
-static Inode inode(std::string_view path) {
-    struct stat st;
-    if (::stat(path::c_str(path), &st)) {
-        return -1;
-    }
-    return st.st_ino;
-}
-
 class IncrementalServiceTest : public testing::Test {
 public:
     void SetUp() override {
-        mVold = std::make_shared<NiceMock<MockVoldService>>();
-        mIncrementalManager = std::make_shared<NiceMock<MockIncrementalManager>>();
-        mIncFs = std::make_shared<NiceMock<MockIncFs>>();
-        MockServiceManager serviceManager = MockServiceManager(mVold, mIncrementalManager, mIncFs);
-        mIncrementalService = std::make_unique<IncrementalService>(serviceManager, mRootDir.path);
+        auto vold = std::make_unique<NiceMock<MockVoldService>>();
+        mVold = vold.get();
+        auto incrementalManager = std::make_unique<NiceMock<MockIncrementalManager>>();
+        mIncrementalManager = incrementalManager.get();
+        auto incFs = std::make_unique<NiceMock<MockIncFs>>();
+        mIncFs = incFs.get();
+        mIncrementalService =
+                std::make_unique<IncrementalService>(MockServiceManager(std::move(vold),
+                                                                        std::move(
+                                                                                incrementalManager),
+                                                                        std::move(incFs)),
+                                                     mRootDir.path);
         mDataLoaderParcel.packageName = "com.test";
         mDataLoaderParcel.arguments = "uri";
         mIncrementalService->onSystemReady();
@@ -252,20 +249,18 @@
         const auto mountPointsFile = rootDir + "/dir1/mount/.mountpoint.abcd";
         ASSERT_TRUE(base::WriteStringToFile("info", mountInfoFile));
         ASSERT_TRUE(base::WriteStringToFile("mounts", mountPointsFile));
-        ASSERT_GE(inode(mountInfoFile), 0);
-        ASSERT_GE(inode(mountPointsFile), 0);
-        ON_CALL(*mIncFs, getMetadata(_, inode(mountInfoFile)))
-                .WillByDefault(Invoke(mIncFs.get(), &MockIncFs::getMountInfoMetadata));
-        ON_CALL(*mIncFs, getMetadata(_, inode(mountPointsFile)))
-                .WillByDefault(Invoke(mIncFs.get(), &MockIncFs::getBindPointMetadata));
-        ON_CALL(*mIncFs, getMetadata(_, inode(rootDir + "/dir1/mount/st0")))
-                .WillByDefault(Invoke(mIncFs.get(), &MockIncFs::getStorageMetadata));
+        ON_CALL(*mIncFs, getMetadata(_, std::string_view(mountInfoFile)))
+                .WillByDefault(Invoke(mIncFs, &MockIncFs::getMountInfoMetadata));
+        ON_CALL(*mIncFs, getMetadata(_, std::string_view(mountPointsFile)))
+                .WillByDefault(Invoke(mIncFs, &MockIncFs::getBindPointMetadata));
+        ON_CALL(*mIncFs, getMetadata(_, std::string_view(rootDir + "/dir1/mount/st0")))
+                .WillByDefault(Invoke(mIncFs, &MockIncFs::getStorageMetadata));
     }
 
 protected:
-    std::shared_ptr<NiceMock<MockVoldService>> mVold;
-    std::shared_ptr<NiceMock<MockIncFs>> mIncFs;
-    std::shared_ptr<NiceMock<MockIncrementalManager>> mIncrementalManager;
+    NiceMock<MockVoldService>* mVold;
+    NiceMock<MockIncFs>* mIncFs;
+    NiceMock<MockIncrementalManager>* mIncrementalManager;
     std::unique_ptr<IncrementalService> mIncrementalService;
     TemporaryDir mRootDir;
     DataLoaderParamsParcel mDataLoaderParcel;
@@ -412,12 +407,12 @@
             mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                IncrementalService::CreateOptions::CreateNew);
     std::string_view dir_path("test");
-    EXPECT_CALL(*mIncFs, makeDir(_, dir_path, _, _, _));
-    int fileIno = mIncrementalService->makeDir(storageId, dir_path, "");
-    ASSERT_GE(fileIno, 0);
+    EXPECT_CALL(*mIncFs, makeDir(_, dir_path, _));
+    auto res = mIncrementalService->makeDir(storageId, dir_path, 0555);
+    ASSERT_EQ(res, 0);
 }
 
-TEST_F(IncrementalServiceTest, testMakeDirectoryNoParent) {
+TEST_F(IncrementalServiceTest, testMakeDirectoryNested) {
     mVold->mountIncFsSuccess();
     mIncFs->makeFileSuccess();
     mVold->bindMountSuccess();
@@ -427,13 +422,15 @@
     int storageId =
             mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                IncrementalService::CreateOptions::CreateNew);
-    std::string_view first("first");
-    std::string_view second("second");
+    auto first = "first"sv;
+    auto second = "second"sv;
     std::string dir_path = std::string(first) + "/" + std::string(second);
-    EXPECT_CALL(*mIncFs, makeDir(_, first, _, _, _)).Times(0);
-    EXPECT_CALL(*mIncFs, makeDir(_, second, _, _, _)).Times(0);
-    int fileIno = mIncrementalService->makeDir(storageId, dir_path, "");
-    ASSERT_LT(fileIno, 0);
+    EXPECT_CALL(*mIncFs, makeDir(_, first, _)).Times(0);
+    EXPECT_CALL(*mIncFs, makeDir(_, second, _)).Times(0);
+    EXPECT_CALL(*mIncFs, makeDir(_, std::string_view(dir_path), _)).Times(1);
+
+    auto res = mIncrementalService->makeDir(storageId, dir_path, 0555);
+    ASSERT_EQ(res, 0);
 }
 
 TEST_F(IncrementalServiceTest, testMakeDirectories) {
@@ -446,16 +443,18 @@
     int storageId =
             mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                IncrementalService::CreateOptions::CreateNew);
-    std::string_view first("first");
-    std::string_view second("second");
-    std::string_view third("third");
+    auto first = "first"sv;
+    auto second = "second"sv;
+    auto third = "third"sv;
     InSequence seq;
-    EXPECT_CALL(*mIncFs, makeDir(_, first, _, _, _));
-    EXPECT_CALL(*mIncFs, makeDir(_, second, _, _, _));
-    EXPECT_CALL(*mIncFs, makeDir(_, third, _, _, _));
-    std::string dir_path =
-            std::string(first) + "/" + std::string(second) + "/" + std::string(third);
-    int fileIno = mIncrementalService->makeDirs(storageId, dir_path, "");
-    ASSERT_GE(fileIno, 0);
+    auto parent_path = std::string(first) + "/" + std::string(second);
+    auto dir_path = parent_path + "/" + std::string(third);
+    EXPECT_CALL(*mIncFs, makeDir(_, std::string_view(dir_path), _)).WillOnce(Return(-ENOENT));
+    EXPECT_CALL(*mIncFs, makeDir(_, std::string_view(parent_path), _)).WillOnce(Return(-ENOENT));
+    EXPECT_CALL(*mIncFs, makeDir(_, first, _)).WillOnce(Return(0));
+    EXPECT_CALL(*mIncFs, makeDir(_, std::string_view(parent_path), _)).WillOnce(Return(0));
+    EXPECT_CALL(*mIncFs, makeDir(_, std::string_view(dir_path), _)).WillOnce(Return(0));
+    auto res = mIncrementalService->makeDirs(storageId, dir_path, 0555);
+    ASSERT_EQ(res, 0);
 }
 } // namespace android::os::incremental
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 258d762..4f5c1ab 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1327,7 +1327,7 @@
             if (!isWatch) {
                 t.traceBegin("StartStatusBarManagerService");
                 try {
-                    statusBar = new StatusBarManagerService(context, wm);
+                    statusBar = new StatusBarManagerService(context);
                     ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar);
                 } catch (Throwable e) {
                     reportWtf("starting StatusBarManagerService", e);
@@ -1724,9 +1724,11 @@
             mSystemServiceManager.startService(SensorNotificationService.class);
             t.traceEnd();
 
-            t.traceBegin("StartContextHubSystemService");
-            mSystemServiceManager.startService(ContextHubSystemService.class);
-            t.traceEnd();
+            if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_CONTEXTHUB)) {
+                t.traceBegin("StartContextHubSystemService");
+                mSystemServiceManager.startService(ContextHubSystemService.class);
+                t.traceEnd();
+            }
 
             t.traceBegin("StartDiskStatsService");
             try {
diff --git a/services/net/java/android/net/IpMemoryStore.java b/services/net/java/android/net/IpMemoryStore.java
index 6f91e00..dcefb53 100644
--- a/services/net/java/android/net/IpMemoryStore.java
+++ b/services/net/java/android/net/IpMemoryStore.java
@@ -52,6 +52,11 @@
                     public int getInterfaceVersion() {
                         return this.VERSION;
                     }
+
+                    @Override
+                    public String getInterfaceHash() {
+                        return this.HASH;
+                    }
                 });
     }
 
diff --git a/services/net/java/android/net/ip/IpClientUtil.java b/services/net/java/android/net/ip/IpClientUtil.java
index 7f723b1..a3618b4 100644
--- a/services/net/java/android/net/ip/IpClientUtil.java
+++ b/services/net/java/android/net/ip/IpClientUtil.java
@@ -189,6 +189,11 @@
         public int getInterfaceVersion() {
             return this.VERSION;
         }
+
+        @Override
+        public String getInterfaceHash() {
+            return this.HASH;
+        }
     }
 
     /**
diff --git a/services/people/java/com/android/server/people/PeopleService.java b/services/people/java/com/android/server/people/PeopleService.java
index 9569c6e..2d18a29 100644
--- a/services/people/java/com/android/server/people/PeopleService.java
+++ b/services/people/java/com/android/server/people/PeopleService.java
@@ -16,6 +16,7 @@
 
 package com.android.server.people;
 
+import android.annotation.NonNull;
 import android.app.prediction.AppPredictionContext;
 import android.app.prediction.AppPredictionSessionId;
 import android.app.prediction.AppTarget;
@@ -29,6 +30,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.SystemService;
+import com.android.server.people.data.DataManager;
 
 import java.util.List;
 import java.util.Map;
@@ -41,6 +43,8 @@
 
     private static final String TAG = "PeopleService";
 
+    private final DataManager mDataManager;
+
     /**
      * Initializes the system service.
      *
@@ -48,6 +52,15 @@
      */
     public PeopleService(Context context) {
         super(context);
+
+        mDataManager = new DataManager(context);
+    }
+
+    @Override
+    public void onBootPhase(int phase) {
+        if (phase == PHASE_SYSTEM_SERVICES_READY) {
+            mDataManager.initialize();
+        }
     }
 
     @Override
@@ -55,6 +68,16 @@
         publishLocalService(PeopleServiceInternal.class, new LocalService());
     }
 
+    @Override
+    public void onUnlockUser(@NonNull TargetUser targetUser) {
+        mDataManager.onUserUnlocked(targetUser.getUserIdentifier());
+    }
+
+    @Override
+    public void onStopUser(@NonNull TargetUser targetUser) {
+        mDataManager.onUserStopped(targetUser.getUserIdentifier());
+    }
+
     @VisibleForTesting
     final class LocalService extends PeopleServiceInternal {
 
@@ -63,7 +86,7 @@
         @Override
         public void onCreatePredictionSession(AppPredictionContext context,
                 AppPredictionSessionId sessionId) {
-            mSessions.put(sessionId, new SessionInfo(context));
+            mSessions.put(sessionId, new SessionInfo(context, mDataManager));
         }
 
         @Override
diff --git a/services/people/java/com/android/server/people/SessionInfo.java b/services/people/java/com/android/server/people/SessionInfo.java
index df7cedf..eb08e03 100644
--- a/services/people/java/com/android/server/people/SessionInfo.java
+++ b/services/people/java/com/android/server/people/SessionInfo.java
@@ -24,6 +24,7 @@
 import android.os.RemoteException;
 import android.util.Slog;
 
+import com.android.server.people.data.DataManager;
 import com.android.server.people.prediction.ConversationPredictor;
 
 import java.util.List;
@@ -37,9 +38,9 @@
     private final RemoteCallbackList<IPredictionCallback> mCallbacks =
             new RemoteCallbackList<>();
 
-    SessionInfo(AppPredictionContext predictionContext) {
+    SessionInfo(AppPredictionContext predictionContext, DataManager dataManager) {
         mConversationPredictor = new ConversationPredictor(predictionContext,
-                this::updatePredictions);
+                this::updatePredictions, dataManager);
     }
 
     void addCallback(IPredictionCallback callback) {
diff --git a/services/people/java/com/android/server/people/data/AggregateEventHistoryImpl.java b/services/people/java/com/android/server/people/data/AggregateEventHistoryImpl.java
new file mode 100644
index 0000000..4ac346b
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/AggregateEventHistoryImpl.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.people.data;
+
+import android.annotation.NonNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/** An {@link EventHistory} that aggregates multiple {@link EventHistory}.  */
+class AggregateEventHistoryImpl implements EventHistory {
+
+    private final List<EventHistory> mEventHistoryList = new ArrayList<>();
+
+    @NonNull
+    @Override
+    public EventIndex getEventIndex(int eventType) {
+        for (EventHistory eventHistory : mEventHistoryList) {
+            EventIndex eventIndex = eventHistory.getEventIndex(eventType);
+            if (!eventIndex.isEmpty()) {
+                return eventIndex;
+            }
+        }
+        return EventIndex.EMPTY;
+    }
+
+    @NonNull
+    @Override
+    public EventIndex getEventIndex(Set<Integer> eventTypes) {
+        EventIndex merged = new EventIndex();
+        for (EventHistory eventHistory : mEventHistoryList) {
+            EventIndex eventIndex = eventHistory.getEventIndex(eventTypes);
+            if (!eventIndex.isEmpty()) {
+                merged = EventIndex.combine(merged, eventIndex);
+            }
+        }
+        return merged;
+    }
+
+    @NonNull
+    @Override
+    public List<Event> queryEvents(Set<Integer> eventTypes, long startTime, long endTime) {
+        List<Event> results = new ArrayList<>();
+        for (EventHistory eventHistory : mEventHistoryList) {
+            EventIndex eventIndex = eventHistory.getEventIndex(eventTypes);
+            if (eventIndex.isEmpty()) {
+                continue;
+            }
+            List<Event> queryResults = eventHistory.queryEvents(eventTypes, startTime, endTime);
+            results = combineEventLists(results, queryResults);
+        }
+        return results;
+    }
+
+    void addEventHistory(EventHistory eventHistory) {
+        mEventHistoryList.add(eventHistory);
+    }
+
+    /**
+     * Combines the sorted events (in chronological order) from the given 2 lists {@code lhs}
+     * and {@code rhs} and preserves the order.
+     */
+    private List<Event> combineEventLists(List<Event> lhs, List<Event> rhs) {
+        List<Event> results = new ArrayList<>();
+        int i = 0, j = 0;
+        while (i < lhs.size() && j < rhs.size()) {
+            if (lhs.get(i).getTimestamp() < rhs.get(j).getTimestamp()) {
+                results.add(lhs.get(i++));
+            } else {
+                results.add(rhs.get(j++));
+            }
+        }
+        if (i < lhs.size()) {
+            results.addAll(lhs.subList(i, lhs.size()));
+        } else if (j < rhs.size()) {
+            results.addAll(rhs.subList(j, rhs.size()));
+        }
+        return results;
+    }
+}
diff --git a/services/people/java/com/android/server/people/data/ContactsQueryHelper.java b/services/people/java/com/android/server/people/data/ContactsQueryHelper.java
new file mode 100644
index 0000000..8a3a44a
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/ContactsQueryHelper.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.people.data;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.WorkerThread;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.Contacts;
+import android.text.TextUtils;
+import android.util.Slog;
+
+/** A helper class that queries the Contacts database. */
+class ContactsQueryHelper {
+
+    private static final String TAG = "ContactsQueryHelper";
+
+    private final Context mContext;
+    private Uri mContactUri;
+    private boolean mIsStarred;
+    private String mPhoneNumber;
+    private long mLastUpdatedTimestamp;
+
+    ContactsQueryHelper(Context context) {
+        mContext = context;
+    }
+
+    /**
+     * Queries the Contacts database with the given contact URI and returns whether the query runs
+     * successfully.
+     */
+    @WorkerThread
+    boolean query(@NonNull String contactUri) {
+        if (TextUtils.isEmpty(contactUri)) {
+            return false;
+        }
+        Uri uri = Uri.parse(contactUri);
+        if ("tel".equals(uri.getScheme())) {
+            return queryWithPhoneNumber(uri.getSchemeSpecificPart());
+        } else if ("mailto".equals(uri.getScheme())) {
+            return queryWithEmail(uri.getSchemeSpecificPart());
+        } else if (contactUri.startsWith(Contacts.CONTENT_LOOKUP_URI.toString())) {
+            return queryWithUri(uri);
+        }
+        return false;
+    }
+
+    /** Queries the Contacts database and read the most recently updated contact. */
+    @WorkerThread
+    boolean querySince(long sinceTime) {
+        final String[] projection = new String[] {
+                Contacts._ID, Contacts.LOOKUP_KEY, Contacts.STARRED, Contacts.HAS_PHONE_NUMBER,
+                Contacts.CONTACT_LAST_UPDATED_TIMESTAMP };
+        String selection = Contacts.CONTACT_LAST_UPDATED_TIMESTAMP + " > ?";
+        String[] selectionArgs = new String[] {Long.toString(sinceTime)};
+        return queryContact(Contacts.CONTENT_URI, projection, selection, selectionArgs);
+    }
+
+    @Nullable
+    Uri getContactUri() {
+        return mContactUri;
+    }
+
+    boolean isStarred() {
+        return mIsStarred;
+    }
+
+    @Nullable
+    String getPhoneNumber() {
+        return mPhoneNumber;
+    }
+
+    long getLastUpdatedTimestamp() {
+        return mLastUpdatedTimestamp;
+    }
+
+    private boolean queryWithPhoneNumber(String phoneNumber) {
+        Uri phoneUri = Uri.withAppendedPath(
+                ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
+        return queryWithUri(phoneUri);
+    }
+
+    private boolean queryWithEmail(String email) {
+        Uri emailUri = Uri.withAppendedPath(
+                ContactsContract.CommonDataKinds.Email.CONTENT_LOOKUP_URI, Uri.encode(email));
+        return queryWithUri(emailUri);
+    }
+
+    private boolean queryWithUri(@NonNull Uri uri) {
+        final String[] projection = new String[] {
+                Contacts._ID, Contacts.LOOKUP_KEY, Contacts.STARRED, Contacts.HAS_PHONE_NUMBER };
+        return queryContact(uri, projection, /* selection= */ null, /* selectionArgs= */ null);
+    }
+
+    private boolean queryContact(@NonNull Uri uri, @NonNull String[] projection,
+            @Nullable String selection, @Nullable String[] selectionArgs) {
+        long contactId;
+        String lookupKey = null;
+        boolean hasPhoneNumber = false;
+        boolean found = false;
+        try (Cursor cursor = mContext.getContentResolver().query(
+                uri, projection, selection, selectionArgs, /* sortOrder= */ null)) {
+            if (cursor == null) {
+                Slog.w(TAG, "Cursor is null when querying contact.");
+                return false;
+            }
+            while (cursor.moveToNext()) {
+                // Contact ID
+                int idIndex = cursor.getColumnIndex(Contacts._ID);
+                contactId = cursor.getLong(idIndex);
+
+                // Lookup key
+                int lookupKeyIndex = cursor.getColumnIndex(Contacts.LOOKUP_KEY);
+                lookupKey = cursor.getString(lookupKeyIndex);
+
+                mContactUri = Contacts.getLookupUri(contactId, lookupKey);
+
+                // Starred
+                int starredIndex = cursor.getColumnIndex(Contacts.STARRED);
+                mIsStarred = cursor.getInt(starredIndex) != 0;
+
+                // Has phone number
+                int hasPhoneNumIndex = cursor.getColumnIndex(Contacts.HAS_PHONE_NUMBER);
+                hasPhoneNumber = cursor.getInt(hasPhoneNumIndex) != 0;
+
+                // Last updated timestamp
+                int lastUpdatedTimestampIndex = cursor.getColumnIndex(
+                        Contacts.CONTACT_LAST_UPDATED_TIMESTAMP);
+                if (lastUpdatedTimestampIndex >= 0) {
+                    mLastUpdatedTimestamp = cursor.getLong(lastUpdatedTimestampIndex);
+                }
+
+                found = true;
+            }
+        }
+        if (found && lookupKey != null && hasPhoneNumber) {
+            return queryPhoneNumber(lookupKey);
+        }
+        return found;
+    }
+
+    private boolean queryPhoneNumber(String lookupKey) {
+        String[] projection = new String[] {
+                ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER };
+        String selection = Contacts.LOOKUP_KEY + " = ?";
+        String[] selectionArgs = new String[] { lookupKey };
+        try (Cursor cursor = mContext.getContentResolver().query(
+                ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projection, selection,
+                selectionArgs, /* sortOrder= */ null)) {
+            if (cursor == null) {
+                Slog.w(TAG, "Cursor is null when querying contact phone number.");
+                return false;
+            }
+            while (cursor.moveToNext()) {
+                // Phone number
+                int phoneNumIdx = cursor.getColumnIndex(
+                        ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER);
+                if (phoneNumIdx >= 0) {
+                    mPhoneNumber = cursor.getString(phoneNumIdx);
+                }
+            }
+        }
+        return true;
+    }
+}
diff --git a/services/people/java/com/android/server/people/data/ConversationInfo.java b/services/people/java/com/android/server/people/data/ConversationInfo.java
new file mode 100644
index 0000000..bb97533
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/ConversationInfo.java
@@ -0,0 +1,372 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.people.data;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.LocusId;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutInfo.ShortcutFlags;
+import android.net.Uri;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * Represents a conversation that is provided by the app based on {@link ShortcutInfo}.
+ */
+public class ConversationInfo {
+
+    private static final int FLAG_VIP = 1;
+
+    private static final int FLAG_NOTIFICATION_SILENCED = 1 << 1;
+
+    private static final int FLAG_BUBBLED = 1 << 2;
+
+    private static final int FLAG_PERSON_IMPORTANT = 1 << 3;
+
+    private static final int FLAG_PERSON_BOT = 1 << 4;
+
+    private static final int FLAG_CONTACT_STARRED = 1 << 5;
+
+    private static final int FLAG_DEMOTED = 1 << 6;
+
+    @IntDef(flag = true, prefix = {"FLAG_"}, value = {
+            FLAG_VIP,
+            FLAG_NOTIFICATION_SILENCED,
+            FLAG_BUBBLED,
+            FLAG_PERSON_IMPORTANT,
+            FLAG_PERSON_BOT,
+            FLAG_CONTACT_STARRED,
+            FLAG_DEMOTED,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface ConversationFlags {
+    }
+
+    @NonNull
+    private String mShortcutId;
+
+    @Nullable
+    private LocusId mLocusId;
+
+    @Nullable
+    private Uri mContactUri;
+
+    @Nullable
+    private String mContactPhoneNumber;
+
+    @Nullable
+    private String mNotificationChannelId;
+
+    @ShortcutFlags
+    private int mShortcutFlags;
+
+    @ConversationFlags
+    private int mConversationFlags;
+
+    private ConversationInfo(Builder builder) {
+        mShortcutId = builder.mShortcutId;
+        mLocusId = builder.mLocusId;
+        mContactUri = builder.mContactUri;
+        mContactPhoneNumber = builder.mContactPhoneNumber;
+        mNotificationChannelId = builder.mNotificationChannelId;
+        mShortcutFlags = builder.mShortcutFlags;
+        mConversationFlags = builder.mConversationFlags;
+    }
+
+    @NonNull
+    public String getShortcutId() {
+        return mShortcutId;
+    }
+
+    @Nullable
+    LocusId getLocusId() {
+        return mLocusId;
+    }
+
+    /** The URI to look up the entry in the contacts data provider. */
+    @Nullable
+    Uri getContactUri() {
+        return mContactUri;
+    }
+
+    /** The phone number of the associated contact. */
+    @Nullable
+    String getContactPhoneNumber() {
+        return mContactPhoneNumber;
+    }
+
+    /**
+     * ID of the {@link android.app.NotificationChannel} where the notifications for this
+     * conversation are posted.
+     */
+    @Nullable
+    String getNotificationChannelId() {
+        return mNotificationChannelId;
+    }
+
+    /** Whether the shortcut for this conversation is set long-lived by the app. */
+    public boolean isShortcutLongLived() {
+        return hasShortcutFlags(ShortcutInfo.FLAG_LONG_LIVED);
+    }
+
+    /** Whether this conversation is marked as VIP by the user. */
+    public boolean isVip() {
+        return hasConversationFlags(FLAG_VIP);
+    }
+
+    /** Whether the notifications for this conversation should be silenced. */
+    public boolean isNotificationSilenced() {
+        return hasConversationFlags(FLAG_NOTIFICATION_SILENCED);
+    }
+
+    /** Whether the notifications for this conversation should show in bubbles. */
+    public boolean isBubbled() {
+        return hasConversationFlags(FLAG_BUBBLED);
+    }
+
+    /**
+     * Whether this conversation is demoted by the user. New notifications for the demoted
+     * conversation will not show in the conversation space.
+     */
+    public boolean isDemoted() {
+        return hasConversationFlags(FLAG_DEMOTED);
+    }
+
+    /** Whether the associated person is marked as important by the app. */
+    public boolean isPersonImportant() {
+        return hasConversationFlags(FLAG_PERSON_IMPORTANT);
+    }
+
+    /** Whether the associated person is marked as a bot by the app. */
+    public boolean isPersonBot() {
+        return hasConversationFlags(FLAG_PERSON_BOT);
+    }
+
+    /** Whether the associated contact is marked as starred by the user. */
+    public boolean isContactStarred() {
+        return hasConversationFlags(FLAG_CONTACT_STARRED);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof ConversationInfo)) {
+            return false;
+        }
+        ConversationInfo other = (ConversationInfo) obj;
+        return Objects.equals(mShortcutId, other.mShortcutId)
+                && Objects.equals(mLocusId, other.mLocusId)
+                && Objects.equals(mContactUri, other.mContactUri)
+                && Objects.equals(mContactPhoneNumber, other.mContactPhoneNumber)
+                && Objects.equals(mNotificationChannelId, other.mNotificationChannelId)
+                && mShortcutFlags == other.mShortcutFlags
+                && mConversationFlags == other.mConversationFlags;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mShortcutId, mLocusId, mContactUri, mContactPhoneNumber,
+                mNotificationChannelId, mShortcutFlags, mConversationFlags);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("ConversationInfo {");
+        sb.append("shortcutId=").append(mShortcutId);
+        sb.append(", locusId=").append(mLocusId);
+        sb.append(", contactUri=").append(mContactUri);
+        sb.append(", phoneNumber=").append(mContactPhoneNumber);
+        sb.append(", notificationChannelId=").append(mNotificationChannelId);
+        sb.append(", shortcutFlags=0x").append(Integer.toHexString(mShortcutFlags));
+        sb.append(" [");
+        if (isShortcutLongLived()) {
+            sb.append("Liv");
+        }
+        sb.append("]");
+        sb.append(", conversationFlags=0x").append(Integer.toHexString(mConversationFlags));
+        sb.append(" [");
+        if (isVip()) {
+            sb.append("Vip");
+        }
+        if (isNotificationSilenced()) {
+            sb.append("Sil");
+        }
+        if (isBubbled()) {
+            sb.append("Bub");
+        }
+        if (isDemoted()) {
+            sb.append("Dem");
+        }
+        if (isPersonImportant()) {
+            sb.append("Imp");
+        }
+        if (isPersonBot()) {
+            sb.append("Bot");
+        }
+        if (isContactStarred()) {
+            sb.append("Sta");
+        }
+        sb.append("]}");
+        return sb.toString();
+    }
+
+    private boolean hasShortcutFlags(@ShortcutFlags int flags) {
+        return (mShortcutFlags & flags) == flags;
+    }
+
+    private boolean hasConversationFlags(@ConversationFlags int flags) {
+        return (mConversationFlags & flags) == flags;
+    }
+
+    /**
+     * Builder class for {@link ConversationInfo} objects.
+     */
+    static class Builder {
+
+        private String mShortcutId;
+
+        @Nullable
+        private LocusId mLocusId;
+
+        @Nullable
+        private Uri mContactUri;
+
+        @Nullable
+        private String mContactPhoneNumber;
+
+        @Nullable
+        private String mNotificationChannelId;
+
+        @ShortcutFlags
+        private int mShortcutFlags;
+
+        @ConversationFlags
+        private int mConversationFlags;
+
+        Builder() {
+        }
+
+        Builder(@NonNull ConversationInfo conversationInfo) {
+            if (mShortcutId == null) {
+                mShortcutId = conversationInfo.mShortcutId;
+            } else {
+                Preconditions.checkArgument(mShortcutId.equals(conversationInfo.mShortcutId));
+            }
+            mLocusId = conversationInfo.mLocusId;
+            mContactUri = conversationInfo.mContactUri;
+            mContactPhoneNumber = conversationInfo.mContactPhoneNumber;
+            mNotificationChannelId = conversationInfo.mNotificationChannelId;
+            mShortcutFlags = conversationInfo.mShortcutFlags;
+            mConversationFlags = conversationInfo.mConversationFlags;
+        }
+
+        Builder setShortcutId(@NonNull String shortcutId) {
+            mShortcutId = shortcutId;
+            return this;
+        }
+
+        Builder setLocusId(LocusId locusId) {
+            mLocusId = locusId;
+            return this;
+        }
+
+        Builder setContactUri(Uri contactUri) {
+            mContactUri = contactUri;
+            return this;
+        }
+
+        Builder setContactPhoneNumber(String phoneNumber) {
+            mContactPhoneNumber = phoneNumber;
+            return this;
+        }
+
+        Builder setNotificationChannelId(String notificationChannelId) {
+            mNotificationChannelId = notificationChannelId;
+            return this;
+        }
+
+        Builder setShortcutFlags(@ShortcutFlags int shortcutFlags) {
+            mShortcutFlags = shortcutFlags;
+            return this;
+        }
+
+        Builder setConversationFlags(@ConversationFlags int conversationFlags) {
+            mConversationFlags = conversationFlags;
+            return this;
+        }
+
+        Builder setVip(boolean value) {
+            return setConversationFlag(FLAG_VIP, value);
+        }
+
+        Builder setNotificationSilenced(boolean value) {
+            return setConversationFlag(FLAG_NOTIFICATION_SILENCED, value);
+        }
+
+        Builder setBubbled(boolean value) {
+            return setConversationFlag(FLAG_BUBBLED, value);
+        }
+
+        Builder setDemoted(boolean value) {
+            return setConversationFlag(FLAG_DEMOTED, value);
+        }
+
+        Builder setPersonImportant(boolean value) {
+            return setConversationFlag(FLAG_PERSON_IMPORTANT, value);
+        }
+
+        Builder setPersonBot(boolean value) {
+            return setConversationFlag(FLAG_PERSON_BOT, value);
+        }
+
+        Builder setContactStarred(boolean value) {
+            return setConversationFlag(FLAG_CONTACT_STARRED, value);
+        }
+
+        private Builder setConversationFlag(@ConversationFlags int flags, boolean value) {
+            if (value) {
+                return addConversationFlags(flags);
+            } else {
+                return removeConversationFlags(flags);
+            }
+        }
+
+        private Builder addConversationFlags(@ConversationFlags int flags) {
+            mConversationFlags |= flags;
+            return this;
+        }
+
+        private Builder removeConversationFlags(@ConversationFlags int flags) {
+            mConversationFlags &= ~flags;
+            return this;
+        }
+
+        ConversationInfo build() {
+            Objects.requireNonNull(mShortcutId);
+            return new ConversationInfo(this);
+        }
+    }
+}
diff --git a/services/people/java/com/android/server/people/data/ConversationStore.java b/services/people/java/com/android/server/people/data/ConversationStore.java
new file mode 100644
index 0000000..f17e1b9
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/ConversationStore.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.people.data;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.LocusId;
+import android.net.Uri;
+import android.util.ArrayMap;
+
+import java.util.Map;
+import java.util.function.Consumer;
+
+/** The store that stores and accesses the conversations data for a package. */
+class ConversationStore {
+
+    // Shortcut ID -> Conversation Info
+    private final Map<String, ConversationInfo> mConversationInfoMap = new ArrayMap<>();
+
+    // Locus ID -> Shortcut ID
+    private final Map<LocusId, String> mLocusIdToShortcutIdMap = new ArrayMap<>();
+
+    // Contact URI -> Shortcut ID
+    private final Map<Uri, String> mContactUriToShortcutIdMap = new ArrayMap<>();
+
+    // Phone Number -> Shortcut ID
+    private final Map<String, String> mPhoneNumberToShortcutIdMap = new ArrayMap<>();
+
+    void addOrUpdate(@NonNull ConversationInfo conversationInfo) {
+        mConversationInfoMap.put(conversationInfo.getShortcutId(), conversationInfo);
+
+        LocusId locusId = conversationInfo.getLocusId();
+        if (locusId != null) {
+            mLocusIdToShortcutIdMap.put(locusId, conversationInfo.getShortcutId());
+        }
+
+        Uri contactUri = conversationInfo.getContactUri();
+        if (contactUri != null) {
+            mContactUriToShortcutIdMap.put(contactUri, conversationInfo.getShortcutId());
+        }
+
+        String phoneNumber = conversationInfo.getContactPhoneNumber();
+        if (phoneNumber != null) {
+            mPhoneNumberToShortcutIdMap.put(phoneNumber, conversationInfo.getShortcutId());
+        }
+    }
+
+    void deleteConversation(@NonNull String shortcutId) {
+        ConversationInfo conversationInfo = mConversationInfoMap.remove(shortcutId);
+        if (conversationInfo == null) {
+            return;
+        }
+
+        LocusId locusId = conversationInfo.getLocusId();
+        if (locusId != null) {
+            mLocusIdToShortcutIdMap.remove(locusId);
+        }
+
+        Uri contactUri = conversationInfo.getContactUri();
+        if (contactUri != null) {
+            mContactUriToShortcutIdMap.remove(contactUri);
+        }
+
+        String phoneNumber = conversationInfo.getContactPhoneNumber();
+        if (phoneNumber != null) {
+            mPhoneNumberToShortcutIdMap.remove(phoneNumber);
+        }
+    }
+
+    void forAllConversations(@NonNull Consumer<ConversationInfo> consumer) {
+        for (ConversationInfo ci : mConversationInfoMap.values()) {
+            consumer.accept(ci);
+        }
+    }
+
+    @Nullable
+    ConversationInfo getConversation(@Nullable String shortcutId) {
+        return shortcutId != null ? mConversationInfoMap.get(shortcutId) : null;
+    }
+
+    @Nullable
+    ConversationInfo getConversationByLocusId(@NonNull LocusId locusId) {
+        return getConversation(mLocusIdToShortcutIdMap.get(locusId));
+    }
+
+    @Nullable
+    ConversationInfo getConversationByContactUri(@NonNull Uri contactUri) {
+        return getConversation(mContactUriToShortcutIdMap.get(contactUri));
+    }
+
+    @Nullable
+    ConversationInfo getConversationByPhoneNumber(@NonNull String phoneNumber) {
+        return getConversation(mPhoneNumberToShortcutIdMap.get(phoneNumber));
+    }
+}
diff --git a/services/people/java/com/android/server/people/data/DataManager.java b/services/people/java/com/android/server/people/data/DataManager.java
new file mode 100644
index 0000000..13cce41
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/DataManager.java
@@ -0,0 +1,559 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.people.data;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.annotation.WorkerThread;
+import android.app.Notification;
+import android.app.Person;
+import android.app.prediction.AppTarget;
+import android.app.prediction.AppTargetEvent;
+import android.app.usage.UsageEvents;
+import android.app.usage.UsageStatsManagerInternal;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.LauncherApps.ShortcutQuery;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
+import android.content.pm.ShortcutManager.ShareShortcutInfo;
+import android.content.pm.ShortcutServiceInternal;
+import android.content.pm.UserInfo;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.ContactsContract.Contacts;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.StatusBarNotification;
+import android.telecom.TelecomManager;
+import android.text.TextUtils;
+import android.text.format.DateUtils;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.app.ChooserActivity;
+import com.android.internal.os.BackgroundThread;
+import com.android.internal.telephony.SmsApplication;
+import com.android.server.LocalServices;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+
+/**
+ * A class manages the lifecycle of the conversations and associated data, and exposes the methods
+ * to access the data in People Service and other system services.
+ */
+public class DataManager {
+
+    private static final String PLATFORM_PACKAGE_NAME = "android";
+    private static final int MY_UID = Process.myUid();
+    private static final int MY_PID = Process.myPid();
+    private static final long USAGE_STATS_QUERY_MAX_EVENT_AGE_MS = DateUtils.DAY_IN_MILLIS;
+    private static final long USAGE_STATS_QUERY_INTERVAL_SEC = 120L;
+
+    private final Context mContext;
+    private final Injector mInjector;
+    private final ScheduledExecutorService mUsageStatsQueryExecutor;
+
+    private final SparseArray<UserData> mUserDataArray = new SparseArray<>();
+    private final SparseArray<BroadcastReceiver> mBroadcastReceivers = new SparseArray<>();
+    private final SparseArray<ContentObserver> mContactsContentObservers = new SparseArray<>();
+    private final SparseArray<ScheduledFuture<?>> mUsageStatsQueryFutures = new SparseArray<>();
+    private final SparseArray<NotificationListenerService> mNotificationListeners =
+            new SparseArray<>();
+
+    private ShortcutServiceInternal mShortcutServiceInternal;
+    private UsageStatsManagerInternal mUsageStatsManagerInternal;
+    private ShortcutManager mShortcutManager;
+    private UserManager mUserManager;
+
+    public DataManager(Context context) {
+        mContext = context;
+        mInjector = new Injector();
+        mUsageStatsQueryExecutor = mInjector.createScheduledExecutor();
+    }
+
+    @VisibleForTesting
+    DataManager(Context context, Injector injector) {
+        mContext = context;
+        mInjector = injector;
+        mUsageStatsQueryExecutor = mInjector.createScheduledExecutor();
+    }
+
+    /** Initialization. Called when the system services are up running. */
+    public void initialize() {
+        mShortcutServiceInternal = LocalServices.getService(ShortcutServiceInternal.class);
+        mUsageStatsManagerInternal = LocalServices.getService(UsageStatsManagerInternal.class);
+        mShortcutManager = mContext.getSystemService(ShortcutManager.class);
+        mUserManager = mContext.getSystemService(UserManager.class);
+
+        mShortcutServiceInternal.addListener(new ShortcutServiceListener());
+    }
+
+    /** This method is called when a user is unlocked. */
+    public void onUserUnlocked(int userId) {
+        UserData userData = mUserDataArray.get(userId);
+        if (userData == null) {
+            userData = new UserData(userId);
+            mUserDataArray.put(userId, userData);
+        }
+        userData.setUserUnlocked();
+        updateDefaultDialer(userData);
+        updateDefaultSmsApp(userData);
+
+        ScheduledFuture<?> scheduledFuture = mUsageStatsQueryExecutor.scheduleAtFixedRate(
+                new UsageStatsQueryRunnable(userId), 1L, USAGE_STATS_QUERY_INTERVAL_SEC,
+                TimeUnit.SECONDS);
+        mUsageStatsQueryFutures.put(userId, scheduledFuture);
+
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(TelecomManager.ACTION_DEFAULT_DIALER_CHANGED);
+        intentFilter.addAction(SmsApplication.ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL);
+        BroadcastReceiver broadcastReceiver = new PerUserBroadcastReceiver(userId);
+        mBroadcastReceivers.put(userId, broadcastReceiver);
+        mContext.registerReceiverAsUser(
+                broadcastReceiver, UserHandle.of(userId), intentFilter, null, null);
+
+        ContentObserver contactsContentObserver = new ContactsContentObserver(
+                BackgroundThread.getHandler());
+        mContactsContentObservers.put(userId, contactsContentObserver);
+        mContext.getContentResolver().registerContentObserver(
+                Contacts.CONTENT_URI, /* notifyForDescendants= */ true,
+                contactsContentObserver, userId);
+
+        NotificationListener notificationListener = new NotificationListener();
+        mNotificationListeners.put(userId, notificationListener);
+        try {
+            notificationListener.registerAsSystemService(mContext,
+                    new ComponentName(PLATFORM_PACKAGE_NAME, getClass().getSimpleName()),
+                    UserHandle.myUserId());
+        } catch (RemoteException e) {
+            // Should never occur for local calls.
+        }
+    }
+
+    /** This method is called when a user is stopped. */
+    public void onUserStopped(int userId) {
+        if (mUserDataArray.indexOfKey(userId) >= 0) {
+            mUserDataArray.get(userId).setUserStopped();
+        }
+        if (mUsageStatsQueryFutures.indexOfKey(userId) >= 0) {
+            mUsageStatsQueryFutures.valueAt(userId).cancel(true);
+        }
+        if (mBroadcastReceivers.indexOfKey(userId) >= 0) {
+            mContext.unregisterReceiver(mBroadcastReceivers.get(userId));
+        }
+        if (mContactsContentObservers.indexOfKey(userId) >= 0) {
+            mContext.getContentResolver().unregisterContentObserver(
+                    mContactsContentObservers.get(userId));
+        }
+        if (mNotificationListeners.indexOfKey(userId) >= 0) {
+            try {
+                mNotificationListeners.get(userId).unregisterAsSystemService();
+            } catch (RemoteException e) {
+                // Should never occur for local calls.
+            }
+        }
+    }
+
+    /**
+     * Iterates through all the {@link PackageData}s owned by the unlocked users who are in the
+     * same profile group as the calling user.
+     */
+    public void forAllPackages(Consumer<PackageData> consumer) {
+        List<UserInfo> users = mUserManager.getEnabledProfiles(mInjector.getCallingUserId());
+        for (UserInfo userInfo : users) {
+            UserData userData = getUnlockedUserData(userInfo.id);
+            if (userData != null) {
+                userData.forAllPackages(consumer);
+            }
+        }
+    }
+
+    /** Gets the {@link ShortcutInfo} for the given shortcut ID. */
+    @Nullable
+    public ShortcutInfo getShortcut(@NonNull String packageName, @UserIdInt int userId,
+            @NonNull String shortcutId) {
+        List<ShortcutInfo> shortcuts = getShortcuts(packageName, userId,
+                Collections.singletonList(shortcutId));
+        if (shortcuts != null && !shortcuts.isEmpty()) {
+            return shortcuts.get(0);
+        }
+        return null;
+    }
+
+    /**
+     * Gets the conversation {@link ShareShortcutInfo}s from all packages owned by the calling user
+     * that match the specified {@link IntentFilter}.
+     */
+    public List<ShareShortcutInfo> getConversationShareTargets(
+            @NonNull IntentFilter intentFilter) {
+        List<ShareShortcutInfo> shareShortcuts = mShortcutManager.getShareTargets(intentFilter);
+        List<ShareShortcutInfo> result = new ArrayList<>();
+        for (ShareShortcutInfo shareShortcut : shareShortcuts) {
+            ShortcutInfo si = shareShortcut.getShortcutInfo();
+            if (getConversationInfo(si.getPackage(), si.getUserId(), si.getId()) != null) {
+                result.add(shareShortcut);
+            }
+        }
+        return result;
+    }
+
+    /** Reports the {@link AppTargetEvent} from App Prediction Manager. */
+    public void reportAppTargetEvent(@NonNull AppTargetEvent event,
+            @Nullable IntentFilter intentFilter) {
+        AppTarget appTarget = event.getTarget();
+        ShortcutInfo shortcutInfo = appTarget != null ? appTarget.getShortcutInfo() : null;
+        if (shortcutInfo == null || event.getAction() != AppTargetEvent.ACTION_LAUNCH) {
+            return;
+        }
+        PackageData packageData = getPackageData(appTarget.getPackageName(),
+                appTarget.getUser().getIdentifier());
+        if (packageData == null) {
+            return;
+        }
+        if (ChooserActivity.LAUNCH_LOCATON_DIRECT_SHARE.equals(event.getLaunchLocation())) {
+            String mimeType = intentFilter != null ? intentFilter.getDataType(0) : null;
+            String shortcutId = shortcutInfo.getId();
+            if (packageData.getConversationStore().getConversation(shortcutId) == null
+                    || TextUtils.isEmpty(mimeType)) {
+                return;
+            }
+            EventHistoryImpl eventHistory =
+                    packageData.getEventStore().getOrCreateShortcutEventHistory(
+                            shortcutInfo.getId());
+            @Event.EventType int eventType;
+            if (mimeType.startsWith("text/")) {
+                eventType = Event.TYPE_SHARE_TEXT;
+            } else if (mimeType.startsWith("image/")) {
+                eventType = Event.TYPE_SHARE_IMAGE;
+            } else if (mimeType.startsWith("video/")) {
+                eventType = Event.TYPE_SHARE_VIDEO;
+            } else {
+                eventType = Event.TYPE_SHARE_OTHER;
+            }
+            eventHistory.addEvent(new Event(System.currentTimeMillis(), eventType));
+        }
+    }
+
+    /** Gets a list of {@link ShortcutInfo}s with the given shortcut IDs. */
+    private List<ShortcutInfo> getShortcuts(
+            @NonNull String packageName, @UserIdInt int userId,
+            @Nullable List<String> shortcutIds) {
+        @ShortcutQuery.QueryFlags int queryFlags = ShortcutQuery.FLAG_MATCH_DYNAMIC
+                | ShortcutQuery.FLAG_MATCH_PINNED | ShortcutQuery.FLAG_MATCH_PINNED_BY_ANY_LAUNCHER;
+        return mShortcutServiceInternal.getShortcuts(
+                mInjector.getCallingUserId(), /*callingPackage=*/ PLATFORM_PACKAGE_NAME,
+                /*changedSince=*/ 0, packageName, shortcutIds, /*componentName=*/ null, queryFlags,
+                userId, MY_PID, MY_UID);
+    }
+
+    @Nullable
+    private UserData getUnlockedUserData(int userId) {
+        UserData userData = mUserDataArray.get(userId);
+        return userData != null && userData.isUnlocked() ? userData : null;
+    }
+
+    @Nullable
+    private PackageData getPackageData(@NonNull String packageName, int userId) {
+        UserData userData = getUnlockedUserData(userId);
+        return userData != null ? userData.getPackageData(packageName) : null;
+    }
+
+    @Nullable
+    private ConversationInfo getConversationInfo(@NonNull String packageName, @UserIdInt int userId,
+            @NonNull String shortcutId) {
+        PackageData packageData = getPackageData(packageName, userId);
+        return packageData != null ? packageData.getConversationStore().getConversation(shortcutId)
+                : null;
+    }
+
+    private void updateDefaultDialer(@NonNull UserData userData) {
+        TelecomManager telecomManager = mContext.getSystemService(TelecomManager.class);
+        String defaultDialer = telecomManager != null
+                ? telecomManager.getDefaultDialerPackage(userData.getUserId()) : null;
+        userData.setDefaultDialer(defaultDialer);
+    }
+
+    private void updateDefaultSmsApp(@NonNull UserData userData) {
+        ComponentName component = SmsApplication.getDefaultSmsApplicationAsUser(
+                mContext, /* updateIfNeeded= */ false, userData.getUserId());
+        String defaultSmsApp = component != null ? component.getPackageName() : null;
+        userData.setDefaultSmsApp(defaultSmsApp);
+    }
+
+    @Nullable
+    private EventHistoryImpl getEventHistoryIfEligible(StatusBarNotification sbn) {
+        Notification notification = sbn.getNotification();
+        String shortcutId = notification.getShortcutId();
+        if (shortcutId == null) {
+            return null;
+        }
+        PackageData packageData = getPackageData(sbn.getPackageName(),
+                sbn.getUser().getIdentifier());
+        if (packageData == null
+                || packageData.getConversationStore().getConversation(shortcutId) == null) {
+            return null;
+        }
+        return packageData.getEventStore().getOrCreateShortcutEventHistory(shortcutId);
+    }
+
+    @VisibleForTesting
+    @WorkerThread
+    void onShortcutAddedOrUpdated(@NonNull ShortcutInfo shortcutInfo) {
+        if (shortcutInfo.getPersons() == null || shortcutInfo.getPersons().length == 0) {
+            return;
+        }
+        UserData userData = getUnlockedUserData(shortcutInfo.getUserId());
+        if (userData == null) {
+            return;
+        }
+        PackageData packageData = userData.getOrCreatePackageData(shortcutInfo.getPackage());
+        ConversationStore conversationStore = packageData.getConversationStore();
+        ConversationInfo oldConversationInfo =
+                conversationStore.getConversation(shortcutInfo.getId());
+        ConversationInfo.Builder builder = oldConversationInfo != null
+                ? new ConversationInfo.Builder(oldConversationInfo)
+                : new ConversationInfo.Builder();
+
+        builder.setShortcutId(shortcutInfo.getId());
+        builder.setLocusId(shortcutInfo.getLocusId());
+        builder.setShortcutFlags(shortcutInfo.getFlags());
+
+        Person person = shortcutInfo.getPersons()[0];
+        builder.setPersonImportant(person.isImportant());
+        builder.setPersonBot(person.isBot());
+        String contactUri = person.getUri();
+        if (contactUri != null) {
+            ContactsQueryHelper helper = mInjector.createContactsQueryHelper(mContext);
+            if (helper.query(contactUri)) {
+                builder.setContactUri(helper.getContactUri());
+                builder.setContactStarred(helper.isStarred());
+                builder.setContactPhoneNumber(helper.getPhoneNumber());
+            }
+        } else {
+            builder.setContactUri(null);
+            builder.setContactPhoneNumber(null);
+            builder.setContactStarred(false);
+        }
+
+        conversationStore.addOrUpdate(builder.build());
+    }
+
+    @VisibleForTesting
+    @WorkerThread
+    void queryUsageStatsService(@UserIdInt int userId, long currentTime, long lastQueryTime) {
+        UsageEvents usageEvents = mUsageStatsManagerInternal.queryEventsForUser(
+                userId, lastQueryTime, currentTime, false);
+        if (usageEvents == null) {
+            return;
+        }
+        while (usageEvents.hasNextEvent()) {
+            UsageEvents.Event e = new UsageEvents.Event();
+            usageEvents.getNextEvent(e);
+
+            String packageName = e.getPackageName();
+            PackageData packageData = getPackageData(packageName, userId);
+            if (packageData == null) {
+                continue;
+            }
+            if (e.getEventType() == UsageEvents.Event.SHORTCUT_INVOCATION) {
+                String shortcutId = e.getShortcutId();
+                if (packageData.getConversationStore().getConversation(shortcutId) != null) {
+                    EventHistoryImpl eventHistory =
+                            packageData.getEventStore().getOrCreateShortcutEventHistory(
+                                    shortcutId);
+                    eventHistory.addEvent(
+                            new Event(e.getTimeStamp(), Event.TYPE_SHORTCUT_INVOCATION));
+                }
+            }
+        }
+    }
+
+    @VisibleForTesting
+    ContentObserver getContactsContentObserverForTesting(@UserIdInt int userId) {
+        return mContactsContentObservers.get(userId);
+    }
+
+    @VisibleForTesting
+    NotificationListenerService getNotificationListenerServiceForTesting(@UserIdInt int userId) {
+        return mNotificationListeners.get(userId);
+    }
+
+    /** Observer that observes the changes in the Contacts database. */
+    private class ContactsContentObserver extends ContentObserver {
+
+        private long mLastUpdatedTimestamp;
+
+        private ContactsContentObserver(Handler handler) {
+            super(handler);
+            mLastUpdatedTimestamp = System.currentTimeMillis();
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri, @UserIdInt int userId) {
+            ContactsQueryHelper helper = mInjector.createContactsQueryHelper(mContext);
+            if (!helper.querySince(mLastUpdatedTimestamp)) {
+                return;
+            }
+            Uri contactUri = helper.getContactUri();
+
+            final ConversationSelector conversationSelector = new ConversationSelector();
+            UserData userData = getUnlockedUserData(userId);
+            if (userData == null) {
+                return;
+            }
+            userData.forAllPackages(packageData -> {
+                ConversationInfo ci =
+                        packageData.getConversationStore().getConversationByContactUri(contactUri);
+                if (ci != null) {
+                    conversationSelector.mConversationStore =
+                            packageData.getConversationStore();
+                    conversationSelector.mConversationInfo = ci;
+                }
+            });
+            if (conversationSelector.mConversationInfo == null) {
+                return;
+            }
+
+            ConversationInfo.Builder builder =
+                    new ConversationInfo.Builder(conversationSelector.mConversationInfo);
+            builder.setContactStarred(helper.isStarred());
+            builder.setContactPhoneNumber(helper.getPhoneNumber());
+            conversationSelector.mConversationStore.addOrUpdate(builder.build());
+            mLastUpdatedTimestamp = helper.getLastUpdatedTimestamp();
+        }
+
+        private class ConversationSelector {
+            private ConversationStore mConversationStore = null;
+            private ConversationInfo mConversationInfo = null;
+        }
+    }
+
+    /** Listener for the shortcut data changes. */
+    private class ShortcutServiceListener implements
+            ShortcutServiceInternal.ShortcutChangeListener {
+
+        @Override
+        public void onShortcutChanged(@NonNull String packageName, int userId) {
+            BackgroundThread.getExecutor().execute(() -> {
+                List<ShortcutInfo> shortcuts = getShortcuts(packageName, userId,
+                        /*shortcutIds=*/ null);
+                for (ShortcutInfo shortcut : shortcuts) {
+                    onShortcutAddedOrUpdated(shortcut);
+                }
+            });
+        }
+    }
+
+    /** Listener for the notifications and their settings changes. */
+    private class NotificationListener extends NotificationListenerService {
+
+        @Override
+        public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap,
+                int reason) {
+            if (reason != REASON_CLICK) {
+                return;
+            }
+            EventHistoryImpl eventHistory = getEventHistoryIfEligible(sbn);
+            if (eventHistory == null) {
+                return;
+            }
+            long currentTime = System.currentTimeMillis();
+            eventHistory.addEvent(new Event(currentTime, Event.TYPE_NOTIFICATION_OPENED));
+        }
+    }
+
+    /**
+     * A {@link Runnable} that queries the Usage Stats Service for recent events for a specified
+     * user.
+     */
+    private class UsageStatsQueryRunnable implements Runnable {
+
+        private final int mUserId;
+        private long mLastQueryTime;
+
+        private UsageStatsQueryRunnable(int userId) {
+            mUserId = userId;
+            mLastQueryTime = System.currentTimeMillis() - USAGE_STATS_QUERY_MAX_EVENT_AGE_MS;
+        }
+
+        @Override
+        public void run() {
+            long currentTime = System.currentTimeMillis();
+            queryUsageStatsService(mUserId, currentTime, mLastQueryTime);
+            mLastQueryTime = currentTime;
+        }
+    }
+
+    /** A {@link BroadcastReceiver} that receives the intents for a specified user. */
+    private class PerUserBroadcastReceiver extends BroadcastReceiver {
+
+        private final int mUserId;
+
+        private PerUserBroadcastReceiver(int userId) {
+            mUserId = userId;
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            UserData userData = getUnlockedUserData(mUserId);
+            if (userData == null) {
+                return;
+            }
+            if (TelecomManager.ACTION_DEFAULT_DIALER_CHANGED.equals(intent.getAction())) {
+                String defaultDialer = intent.getStringExtra(
+                        TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME);
+                userData.setDefaultDialer(defaultDialer);
+            } else if (SmsApplication.ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL.equals(
+                    intent.getAction())) {
+                updateDefaultSmsApp(userData);
+            }
+        }
+    }
+
+    @VisibleForTesting
+    static class Injector {
+
+        ScheduledExecutorService createScheduledExecutor() {
+            return Executors.newSingleThreadScheduledExecutor();
+        }
+
+        ContactsQueryHelper createContactsQueryHelper(Context context) {
+            return new ContactsQueryHelper(context);
+        }
+
+        int getCallingUserId() {
+            return Binder.getCallingUserHandle().getIdentifier();
+        }
+    }
+}
diff --git a/services/people/java/com/android/server/people/data/Event.java b/services/people/java/com/android/server/people/data/Event.java
new file mode 100644
index 0000000..c2364a2
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/Event.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.people.data;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.text.format.DateFormat;
+import android.util.ArraySet;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Set;
+
+/** An event representing the interaction with a specific conversation or app. */
+public class Event {
+
+    public static final int TYPE_SHORTCUT_INVOCATION = 1;
+
+    public static final int TYPE_NOTIFICATION_POSTED = 2;
+
+    public static final int TYPE_NOTIFICATION_OPENED = 3;
+
+    public static final int TYPE_SHARE_TEXT = 4;
+
+    public static final int TYPE_SHARE_IMAGE = 5;
+
+    public static final int TYPE_SHARE_VIDEO = 6;
+
+    public static final int TYPE_SHARE_OTHER = 7;
+
+    public static final int TYPE_SMS_OUTGOING = 8;
+
+    public static final int TYPE_SMS_INCOMING = 9;
+
+    public static final int TYPE_CALL_OUTGOING = 10;
+
+    public static final int TYPE_CALL_INCOMING = 11;
+
+    public static final int TYPE_CALL_MISSED = 12;
+
+    @IntDef(prefix = { "TYPE_" }, value = {
+            TYPE_SHORTCUT_INVOCATION,
+            TYPE_NOTIFICATION_POSTED,
+            TYPE_NOTIFICATION_OPENED,
+            TYPE_SHARE_TEXT,
+            TYPE_SHARE_IMAGE,
+            TYPE_SHARE_VIDEO,
+            TYPE_SHARE_OTHER,
+            TYPE_SMS_OUTGOING,
+            TYPE_SMS_INCOMING,
+            TYPE_CALL_OUTGOING,
+            TYPE_CALL_INCOMING,
+            TYPE_CALL_MISSED,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface EventType {}
+
+    public static final Set<Integer> NOTIFICATION_EVENT_TYPES = new ArraySet<>();
+    public static final Set<Integer> SHARE_EVENT_TYPES = new ArraySet<>();
+    public static final Set<Integer> SMS_EVENT_TYPES = new ArraySet<>();
+    public static final Set<Integer> CALL_EVENT_TYPES = new ArraySet<>();
+    public static final Set<Integer> ALL_EVENT_TYPES = new ArraySet<>();
+
+    static {
+        NOTIFICATION_EVENT_TYPES.add(TYPE_NOTIFICATION_POSTED);
+        NOTIFICATION_EVENT_TYPES.add(TYPE_NOTIFICATION_OPENED);
+
+        SHARE_EVENT_TYPES.add(TYPE_SHARE_TEXT);
+        SHARE_EVENT_TYPES.add(TYPE_SHARE_IMAGE);
+        SHARE_EVENT_TYPES.add(TYPE_SHARE_VIDEO);
+        SHARE_EVENT_TYPES.add(TYPE_SHARE_OTHER);
+
+        SMS_EVENT_TYPES.add(TYPE_SMS_INCOMING);
+        SMS_EVENT_TYPES.add(TYPE_SMS_OUTGOING);
+
+        CALL_EVENT_TYPES.add(TYPE_CALL_INCOMING);
+        CALL_EVENT_TYPES.add(TYPE_CALL_OUTGOING);
+        CALL_EVENT_TYPES.add(TYPE_CALL_MISSED);
+
+        ALL_EVENT_TYPES.add(TYPE_SHORTCUT_INVOCATION);
+        ALL_EVENT_TYPES.addAll(NOTIFICATION_EVENT_TYPES);
+        ALL_EVENT_TYPES.addAll(SHARE_EVENT_TYPES);
+        ALL_EVENT_TYPES.addAll(SMS_EVENT_TYPES);
+        ALL_EVENT_TYPES.addAll(CALL_EVENT_TYPES);
+    }
+
+    private final long mTimestamp;
+
+    private final int mType;
+
+    private final CallDetails mCallDetails;
+
+    Event(long timestamp, @EventType int type) {
+        mTimestamp = timestamp;
+        mType = type;
+        mCallDetails = null;
+    }
+
+    private Event(@NonNull Builder builder) {
+        mTimestamp = builder.mTimestamp;
+        mType = builder.mType;
+        mCallDetails = builder.mCallDetails;
+    }
+
+    public long getTimestamp() {
+        return mTimestamp;
+    }
+
+    public @EventType int getType() {
+        return mType;
+    }
+
+    /**
+     * Gets the {@link CallDetails} of the event. It is only available if the event type is one of
+     * {@code CALL_EVENT_TYPES}, otherwise, it's always {@code null}.
+     */
+    @Nullable
+    public CallDetails getCallDetails() {
+        return mCallDetails;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("Event {");
+        sb.append("timestamp=").append(DateFormat.format("yyyy-MM-dd HH:mm:ss", mTimestamp));
+        sb.append(", type=").append(mType);
+        if (mCallDetails != null) {
+            sb.append(", callDetails=").append(mCallDetails);
+        }
+        sb.append("}");
+        return sb.toString();
+    }
+
+    /** Type-specific details of a call event. */
+    public static class CallDetails {
+
+        private final long mDurationSeconds;
+
+        CallDetails(long durationSeconds) {
+            mDurationSeconds = durationSeconds;
+        }
+
+        public long getDurationSeconds() {
+            return mDurationSeconds;
+        }
+
+        @Override
+        public String toString() {
+            return "CallDetails {durationSeconds=" + mDurationSeconds + "}";
+        }
+    }
+
+    /** Builder class for {@link Event} objects. */
+    static class Builder {
+
+        private final long mTimestamp;
+
+        private final int mType;
+
+        private CallDetails mCallDetails;
+
+        Builder(long timestamp, @EventType int type) {
+            mTimestamp = timestamp;
+            mType = type;
+        }
+
+        Builder setCallDetails(CallDetails callDetails) {
+            Preconditions.checkArgument(CALL_EVENT_TYPES.contains(mType));
+            mCallDetails = callDetails;
+            return this;
+        }
+
+        Event build() {
+            return new Event(this);
+        }
+    }
+}
diff --git a/services/people/java/com/android/server/people/data/EventHistory.java b/services/people/java/com/android/server/people/data/EventHistory.java
new file mode 100644
index 0000000..5b11fd0
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/EventHistory.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.people.data;
+
+import android.annotation.NonNull;
+
+import java.util.List;
+import java.util.Set;
+
+/** The interface for querying the event time distribution and details. */
+public interface EventHistory {
+
+    /** Gets the {@link EventIndex} for the specified event type. */
+    @NonNull
+    EventIndex getEventIndex(@Event.EventType int eventType);
+
+    /** Gets the combined {@link EventIndex} for a set of event types. */
+    @NonNull
+    EventIndex getEventIndex(Set<Integer> eventTypes);
+
+    /**
+     * Returns a {@link List} of {@link Event}s those timestamps are between the specified {@code
+     * fromTimestamp}, inclusive, and {@code toTimestamp} exclusive, and match the specified event
+     * types.
+     *
+     * @return a list of matched events in chronological order.
+     */
+    @NonNull
+    List<Event> queryEvents(Set<Integer> eventTypes, long fromTimestamp, long toTimestamp);
+}
diff --git a/services/people/java/com/android/server/people/data/EventHistoryImpl.java b/services/people/java/com/android/server/people/data/EventHistoryImpl.java
new file mode 100644
index 0000000..6b6bd7e
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/EventHistoryImpl.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.people.data;
+
+import android.annotation.NonNull;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.List;
+import java.util.Set;
+
+class EventHistoryImpl implements EventHistory {
+
+    private final Injector mInjector;
+
+    // Event Type -> Event Index
+    private final SparseArray<EventIndex> mEventIndexArray = new SparseArray<>();
+
+    private final EventList mRecentEvents = new EventList();
+
+    EventHistoryImpl() {
+        mInjector = new Injector();
+    }
+
+    @VisibleForTesting
+    EventHistoryImpl(Injector injector) {
+        mInjector = injector;
+    }
+
+    @Override
+    @NonNull
+    public EventIndex getEventIndex(@Event.EventType int eventType) {
+        EventIndex eventIndex = mEventIndexArray.get(eventType);
+        return eventIndex != null ? new EventIndex(eventIndex) : mInjector.createEventIndex();
+    }
+
+    @Override
+    @NonNull
+    public EventIndex getEventIndex(Set<Integer> eventTypes) {
+        EventIndex combined = mInjector.createEventIndex();
+        for (@Event.EventType int eventType : eventTypes) {
+            EventIndex eventIndex = mEventIndexArray.get(eventType);
+            if (eventIndex != null) {
+                combined = EventIndex.combine(combined, eventIndex);
+            }
+        }
+        return combined;
+    }
+
+    @Override
+    @NonNull
+    public List<Event> queryEvents(Set<Integer> eventTypes, long startTime, long endTime) {
+        return mRecentEvents.queryEvents(eventTypes, startTime, endTime);
+    }
+
+    void addEvent(Event event) {
+        EventIndex eventIndex = mEventIndexArray.get(event.getType());
+        if (eventIndex == null) {
+            eventIndex = mInjector.createEventIndex();
+            mEventIndexArray.put(event.getType(), eventIndex);
+        }
+        eventIndex.addEvent(event.getTimestamp());
+        mRecentEvents.add(event);
+    }
+
+    @VisibleForTesting
+    static class Injector {
+
+        EventIndex createEventIndex() {
+            return new EventIndex();
+        }
+    }
+}
diff --git a/services/people/java/com/android/server/people/data/EventIndex.java b/services/people/java/com/android/server/people/data/EventIndex.java
new file mode 100644
index 0000000..b74a3fa
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/EventIndex.java
@@ -0,0 +1,377 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.people.data;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.text.format.DateFormat;
+import android.util.Range;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.temporal.ChronoUnit;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.TimeZone;
+import java.util.function.Function;
+
+/**
+ * The index of {@link Event}s. It is used for quickly looking up the time distribution of
+ * {@link Event}s based on {@code Event#getTimestamp()}.
+ *
+ * <p>The 64-bits {code long} is used as the bitmap index. Each bit is to denote whether there are
+ * any events in a specified time slot. The least significant bit is for the most recent time slot.
+ * And the most significant bit is for the oldest time slot.
+ *
+ * <p>Multiple {code long}s are used to index the events in different time grains. For the recent
+ * events, the fine-grained bitmap index can provide the narrower time range. For the older events,
+ * the coarse-grained bitmap index can cover longer period but can only provide wider time range.
+ *
+ * <p>E.g. the below chart shows how the bitmap indexes index the events in the past 24 hours:
+ * <pre>
+ * 2020/1/3                                                             2020/1/4
+ *   0:00        4:00        8:00       12:00       16:00       20:00        0:00
+ *  --+-----------------------------------------------------------------------+-  1 day per bit
+ *  --+-----------+-----------+-----------+-----------+-----------+-----------+-  4 hours per bit
+ *  --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-  1 hour per bit
+ *                                                                     +++++++++  2 minutes per bit
+ *  </pre>
+ */
+public class EventIndex {
+
+    private static final int LONG_SIZE_BITS = 64;
+
+    private static final int TIME_SLOT_ONE_DAY = 0;
+
+    private static final int TIME_SLOT_FOUR_HOURS = 1;
+
+    private static final int TIME_SLOT_ONE_HOUR = 2;
+
+    private static final int TIME_SLOT_TWO_MINUTES = 3;
+
+    @IntDef(prefix = {"TIME_SLOT_"}, value = {
+            TIME_SLOT_ONE_DAY,
+            TIME_SLOT_FOUR_HOURS,
+            TIME_SLOT_ONE_HOUR,
+            TIME_SLOT_TWO_MINUTES,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface TimeSlotType {
+    }
+
+    private static final int TIME_SLOT_TYPES_COUNT = 4;
+
+    static final EventIndex EMPTY = new EventIndex();
+
+    private static final List<Function<Long, Range<Long>>> TIME_SLOT_FACTORIES =
+            Collections.unmodifiableList(
+                    Arrays.asList(
+                            EventIndex::createOneDayLongTimeSlot,
+                            EventIndex::createFourHoursLongTimeSlot,
+                            EventIndex::createOneHourLongTimeSlot,
+                            EventIndex::createTwoMinutesLongTimeSlot
+                    )
+            );
+
+    /** Combines the two {@link EventIndex} objects and returns the combined result. */
+    static EventIndex combine(EventIndex lhs, EventIndex rhs) {
+        EventIndex older = lhs.mLastUpdatedTime < rhs.mLastUpdatedTime ? lhs : rhs;
+        EventIndex younger = lhs.mLastUpdatedTime >= rhs.mLastUpdatedTime ? lhs : rhs;
+
+        EventIndex combined = new EventIndex(older);
+        combined.updateEventBitmaps(younger.mLastUpdatedTime);
+
+        for (int slotType = 0; slotType < TIME_SLOT_TYPES_COUNT; slotType++) {
+            combined.mEventBitmaps[slotType] |= younger.mEventBitmaps[slotType];
+        }
+        return combined;
+    }
+
+    private final long[] mEventBitmaps;
+
+    private long mLastUpdatedTime;
+
+    private final Object mLock = new Object();
+
+    private final Injector mInjector;
+
+    EventIndex() {
+        mInjector = new Injector();
+        mEventBitmaps = new long[]{0L, 0L, 0L, 0L};
+        mLastUpdatedTime = mInjector.currentTimeMillis();
+    }
+
+    EventIndex(EventIndex from) {
+        mInjector = new Injector();
+        mEventBitmaps = Arrays.copyOf(from.mEventBitmaps, TIME_SLOT_TYPES_COUNT);
+        mLastUpdatedTime = from.mLastUpdatedTime;
+    }
+
+    @VisibleForTesting
+    EventIndex(Injector injector) {
+        mInjector = injector;
+        mEventBitmaps = new long[]{0L, 0L, 0L, 0L};
+        mLastUpdatedTime = mInjector.currentTimeMillis();
+    }
+
+    /**
+     * Gets the most recent active time slot. A time slot is active if there is at least one event
+     * occurred in that time slot.
+     */
+    @Nullable
+    public Range<Long> getMostRecentActiveTimeSlot() {
+        synchronized (mLock) {
+            for (int slotType = TIME_SLOT_TYPES_COUNT - 1; slotType >= 0; slotType--) {
+                if (mEventBitmaps[slotType] == 0L) {
+                    continue;
+                }
+                Range<Long> lastTimeSlot =
+                        TIME_SLOT_FACTORIES.get(slotType).apply(mLastUpdatedTime);
+                int numberOfTrailingZeros = Long.numberOfTrailingZeros(mEventBitmaps[slotType]);
+                long offset = getDuration(lastTimeSlot) * numberOfTrailingZeros;
+                return Range.create(lastTimeSlot.getLower() - offset,
+                        lastTimeSlot.getUpper() - offset);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Gets the active time slots. A time slot is active if there is at least one event occurred
+     * in that time slot.
+     *
+     * @return active time slots in chronological order.
+     */
+    @NonNull
+    public List<Range<Long>> getActiveTimeSlots() {
+        List<Range<Long>> activeTimeSlots = new ArrayList<>();
+        synchronized (mLock) {
+            for (int slotType = 0; slotType < TIME_SLOT_TYPES_COUNT; slotType++) {
+                activeTimeSlots = combineTimeSlotLists(activeTimeSlots,
+                        getActiveTimeSlotsForType(slotType));
+            }
+        }
+        Collections.reverse(activeTimeSlots);
+        return activeTimeSlots;
+    }
+
+    /** Returns whether this {@link EventIndex} instance is empty. */
+    public boolean isEmpty() {
+        synchronized (mLock) {
+            for (int slotType = 0; slotType < TIME_SLOT_TYPES_COUNT; slotType++) {
+                if (mEventBitmaps[slotType] != 0L) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Adds an event to this index with the given event time. Before the new event is recorded, the
+     * index is updated first with the current timestamp.
+     */
+    void addEvent(long eventTime) {
+        if (EMPTY == this) {
+            throw new IllegalStateException("EMPTY instance is immutable");
+        }
+        synchronized (mLock) {
+            long currentTime = mInjector.currentTimeMillis();
+            updateEventBitmaps(currentTime);
+            for (int slotType = 0; slotType < TIME_SLOT_TYPES_COUNT; slotType++) {
+                int offset = diffTimeSlots(slotType, eventTime, currentTime);
+                if (offset < LONG_SIZE_BITS) {
+                    mEventBitmaps[slotType] |= (1L << offset);
+                }
+            }
+        }
+    }
+
+    /** Updates to make all bitmaps up to date. */
+    void update() {
+        updateEventBitmaps(mInjector.currentTimeMillis());
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("EventIndex {");
+        sb.append("perDayEventBitmap=0b");
+        sb.append(Long.toBinaryString(mEventBitmaps[TIME_SLOT_ONE_DAY]));
+        sb.append(", perFourHoursEventBitmap=0b");
+        sb.append(Long.toBinaryString(mEventBitmaps[TIME_SLOT_FOUR_HOURS]));
+        sb.append(", perHourEventBitmap=0b");
+        sb.append(Long.toBinaryString(mEventBitmaps[TIME_SLOT_ONE_HOUR]));
+        sb.append(", perTwoMinutesEventBitmap=0b");
+        sb.append(Long.toBinaryString(mEventBitmaps[TIME_SLOT_TWO_MINUTES]));
+        sb.append(", lastUpdatedTime=");
+        sb.append(DateFormat.format("yyyy-MM-dd HH:mm:ss", mLastUpdatedTime));
+        sb.append("}");
+        return sb.toString();
+    }
+
+    /** Shifts the event bitmaps to make them up-to-date. */
+    private void updateEventBitmaps(long currentTimeMillis) {
+        for (int slotType = 0; slotType < TIME_SLOT_TYPES_COUNT; slotType++) {
+            int offset = diffTimeSlots(slotType, mLastUpdatedTime, currentTimeMillis);
+            if (offset < LONG_SIZE_BITS) {
+                mEventBitmaps[slotType] <<= offset;
+            } else {
+                mEventBitmaps[slotType] = 0L;
+            }
+        }
+        mLastUpdatedTime = currentTimeMillis;
+    }
+
+    private static LocalDateTime toLocalDateTime(long epochMilli) {
+        return LocalDateTime.ofInstant(
+                Instant.ofEpochMilli(epochMilli), TimeZone.getDefault().toZoneId());
+    }
+
+    private static long toEpochMilli(LocalDateTime localDateTime) {
+        return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
+    }
+
+    private static long getDuration(Range<Long> timeSlot) {
+        return timeSlot.getUpper() - timeSlot.getLower();
+    }
+
+    /**
+     * Finds the time slots for the given two timestamps and returns the distance (in the number
+     * of time slots) between these two time slots.
+     */
+    private static int diffTimeSlots(@TimeSlotType int timeSlotType, long fromTime, long toTime) {
+        Function<Long, Range<Long>> timeSlotFactory = TIME_SLOT_FACTORIES.get(timeSlotType);
+        Range<Long> fromSlot = timeSlotFactory.apply(fromTime);
+        Range<Long> toSlot = timeSlotFactory.apply(toTime);
+        return (int) ((toSlot.getLower() - fromSlot.getLower()) / getDuration(fromSlot));
+    }
+
+    /**
+     * Returns the active time slots for a specified type. The returned time slots are in
+     * reverse-chronological order.
+     */
+    private List<Range<Long>> getActiveTimeSlotsForType(@TimeSlotType int timeSlotType) {
+        long eventBitmap = mEventBitmaps[timeSlotType];
+        Range<Long> latestTimeSlot = TIME_SLOT_FACTORIES.get(timeSlotType).apply(mLastUpdatedTime);
+        long startTime = latestTimeSlot.getLower();
+        final long duration = getDuration(latestTimeSlot);
+        List<Range<Long>> timeSlots = new ArrayList<>();
+        while (eventBitmap != 0) {
+            int trailingZeros = Long.numberOfTrailingZeros(eventBitmap);
+            if (trailingZeros > 0) {
+                startTime -= duration * trailingZeros;
+                eventBitmap >>>= trailingZeros;
+            }
+            if (eventBitmap != 0) {
+                timeSlots.add(Range.create(startTime, startTime + duration));
+                startTime -= duration;
+                eventBitmap >>>= 1;
+            }
+        }
+        return timeSlots;
+    }
+
+    /**
+     * Combines two lists of time slots into one. If one longer time slot covers one or multiple
+     * shorter time slots, the smaller time slot(s) will be added to the result and the longer one
+     * will be dropped. This ensures the returned list does not contain any overlapping time slots.
+     */
+    private static List<Range<Long>> combineTimeSlotLists(List<Range<Long>> longerSlots,
+            List<Range<Long>> shorterSlots) {
+        List<Range<Long>> result = new ArrayList<>();
+        int i = 0;
+        int j = 0;
+        while (i < longerSlots.size() && j < shorterSlots.size()) {
+            Range<Long> longerSlot = longerSlots.get(i);
+            Range<Long> shorterSlot = shorterSlots.get(j);
+            if (longerSlot.contains(shorterSlot)) {
+                result.add(shorterSlot);
+                i++;
+                j++;
+            } else if (longerSlot.getLower() < shorterSlot.getLower()) {
+                result.add(shorterSlot);
+                j++;
+            } else {
+                result.add(longerSlot);
+                i++;
+            }
+        }
+        if (i < longerSlots.size()) {
+            result.addAll(longerSlots.subList(i, longerSlots.size()));
+        } else if (j < shorterSlots.size()) {
+            result.addAll(shorterSlots.subList(j, shorterSlots.size()));
+        }
+        return result;
+    }
+
+    /**
+     * Finds and creates the time slot (duration = 1 day) that the given time falls into.
+     */
+    @NonNull
+    private static Range<Long> createOneDayLongTimeSlot(long time) {
+        LocalDateTime beginTime = toLocalDateTime(time).truncatedTo(ChronoUnit.DAYS);
+        return Range.create(toEpochMilli(beginTime), toEpochMilli(beginTime.plusDays(1)));
+    }
+
+    /**
+     * Finds and creates the time slot (duration = 4 hours) that the given time falls into.
+     */
+    @NonNull
+    private static Range<Long> createFourHoursLongTimeSlot(long time) {
+        int hourOfDay = toLocalDateTime(time).getHour();
+        LocalDateTime beginTime =
+                toLocalDateTime(time).truncatedTo(ChronoUnit.HOURS).minusHours(hourOfDay % 4);
+        return Range.create(toEpochMilli(beginTime), toEpochMilli(beginTime.plusHours(4)));
+    }
+
+    /**
+     * Finds and creates the time slot (duration = 1 hour) that the given time falls into.
+     */
+    @NonNull
+    private static Range<Long> createOneHourLongTimeSlot(long time) {
+        LocalDateTime beginTime = toLocalDateTime(time).truncatedTo(ChronoUnit.HOURS);
+        return Range.create(toEpochMilli(beginTime), toEpochMilli(beginTime.plusHours(1)));
+    }
+
+    /**
+     * Finds and creates the time slot (duration = 2 minutes) that the given time falls into.
+     */
+    @NonNull
+    private static Range<Long> createTwoMinutesLongTimeSlot(long time) {
+        int minuteOfHour = toLocalDateTime(time).getMinute();
+        LocalDateTime beginTime = toLocalDateTime(time).truncatedTo(
+                ChronoUnit.MINUTES).minusMinutes(minuteOfHour % 2);
+        return Range.create(toEpochMilli(beginTime), toEpochMilli(beginTime.plusMinutes(2)));
+    }
+
+    @VisibleForTesting
+    static class Injector {
+        /** This should be the only way to get the current timestamp in {@code EventIndex}. */
+        long currentTimeMillis() {
+            return System.currentTimeMillis();
+        }
+    }
+}
diff --git a/services/people/java/com/android/server/people/data/EventList.java b/services/people/java/com/android/server/people/data/EventList.java
new file mode 100644
index 0000000..b267d66
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/EventList.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.people.data;
+
+import android.annotation.NonNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/** A container that holds a list of {@link Event}s in chronological order. */
+class EventList {
+
+    private final List<Event> mEvents = new ArrayList<>();
+
+    /**
+     * Adds an event to the list unless there is an existing event with the same timestamp and
+     * type.
+     */
+    void add(@NonNull Event event) {
+        int index = firstIndexOnOrAfter(event.getTimestamp());
+        if (index < mEvents.size()
+                && mEvents.get(index).getTimestamp() == event.getTimestamp()
+                && isDuplicate(event, index)) {
+            return;
+        }
+        mEvents.add(index, event);
+    }
+
+    /**
+     * Returns a {@link List} of {@link Event}s whose timestamps are between the specified {@code
+     * fromTimestamp}, inclusive, and {@code toTimestamp} exclusive, and match the specified event
+     * types.
+     *
+     * @return a {@link List} of matched {@link Event}s in chronological order.
+     */
+    @NonNull
+    List<Event> queryEvents(@NonNull Set<Integer> eventTypes, long fromTimestamp,
+            long toTimestamp) {
+        int fromIndex = firstIndexOnOrAfter(fromTimestamp);
+        if (fromIndex == mEvents.size()) {
+            return new ArrayList<>();
+        }
+        int toIndex = firstIndexOnOrAfter(toTimestamp);
+        if (toIndex < fromIndex) {
+            return new ArrayList<>();
+        }
+        List<Event> result = new ArrayList<>();
+        for (int i = fromIndex; i < toIndex; i++) {
+            Event e = mEvents.get(i);
+            if (eventTypes.contains(e.getType())) {
+                result.add(e);
+            }
+        }
+        return result;
+    }
+
+    /** Returns the first index whose timestamp is greater or equal to the provided timestamp. */
+    private int firstIndexOnOrAfter(long timestamp) {
+        int result = mEvents.size();
+        int low = 0;
+        int high = mEvents.size() - 1;
+        while (low <= high) {
+            int mid = (low + high) >>> 1;
+            if (mEvents.get(mid).getTimestamp() >= timestamp) {
+                high = mid - 1;
+                result = mid;
+            } else {
+                low = mid + 1;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Checks whether the {@link Event} is duplicate with one of the existing events. The checking
+     * starts from the {@code startIndex}.
+     */
+    private boolean isDuplicate(Event event, int startIndex) {
+        int size = mEvents.size();
+        int index = startIndex;
+        while (index < size && mEvents.get(index).getTimestamp() <= event.getTimestamp()) {
+            if (mEvents.get(index++).getType() == event.getType()) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/services/people/java/com/android/server/people/data/EventStore.java b/services/people/java/com/android/server/people/data/EventStore.java
new file mode 100644
index 0000000..d6b7a86
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/EventStore.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.people.data;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.LocusId;
+import android.util.ArrayMap;
+
+import java.util.Map;
+
+/** The store that stores and accesses the events data for a package. */
+class EventStore {
+
+    private final EventHistoryImpl mPackageEventHistory = new EventHistoryImpl();
+
+    // Shortcut ID -> Event History
+    private final Map<String, EventHistoryImpl> mShortcutEventHistoryMap = new ArrayMap<>();
+
+    // Locus ID -> Event History
+    private final Map<LocusId, EventHistoryImpl> mLocusEventHistoryMap = new ArrayMap<>();
+
+    // Phone Number -> Event History
+    private final Map<String, EventHistoryImpl> mCallEventHistoryMap = new ArrayMap<>();
+
+    // Phone Number -> Event History
+    private final Map<String, EventHistoryImpl> mSmsEventHistoryMap = new ArrayMap<>();
+
+    /** Gets the package level {@link EventHistory}. */
+    @NonNull
+    EventHistory getPackageEventHistory() {
+        return mPackageEventHistory;
+    }
+
+    /** Gets the {@link EventHistory} for the specified {@code shortcutId} if exists. */
+    @Nullable
+    EventHistory getShortcutEventHistory(String shortcutId) {
+        return mShortcutEventHistoryMap.get(shortcutId);
+    }
+
+    /** Gets the {@link EventHistory} for the specified {@code locusId} if exists. */
+    @Nullable
+    EventHistory getLocusEventHistory(LocusId locusId) {
+        return mLocusEventHistoryMap.get(locusId);
+    }
+
+    /** Gets the phone call {@link EventHistory} for the specified {@code phoneNumber} if exists. */
+    @Nullable
+    EventHistory getCallEventHistory(String phoneNumber) {
+        return mCallEventHistoryMap.get(phoneNumber);
+    }
+
+    /** Gets the SMS {@link EventHistory} for the specified {@code phoneNumber} if exists. */
+    @Nullable
+    EventHistory getSmsEventHistory(String phoneNumber) {
+        return mSmsEventHistoryMap.get(phoneNumber);
+    }
+
+    /**
+     * Gets the {@link EventHistoryImpl} for the specified {@code shortcutId} or creates a new
+     * instance and put it into the store if not exists. The caller needs to verify if a
+     * conversation with this shortcut ID exists before calling this method.
+     */
+    @NonNull
+    EventHistoryImpl getOrCreateShortcutEventHistory(String shortcutId) {
+        return mShortcutEventHistoryMap.computeIfAbsent(shortcutId, key -> new EventHistoryImpl());
+    }
+
+    /**
+     * Gets the {@link EventHistoryImpl} for the specified {@code locusId} or creates a new
+     * instance and put it into the store if not exists. The caller needs to ensure a conversation
+     * with this locus ID exists before calling this method.
+     */
+    @NonNull
+    EventHistoryImpl getOrCreateLocusEventHistory(LocusId locusId) {
+        return mLocusEventHistoryMap.computeIfAbsent(locusId, key -> new EventHistoryImpl());
+    }
+
+    /**
+     * Gets the {@link EventHistoryImpl} for the specified {@code phoneNumber} for call events
+     * or creates a new instance and put it into the store if not exists. The caller needs to ensure
+     * a conversation with this phone number exists and this package is the default dialer
+     * before calling this method.
+     */
+    @NonNull
+    EventHistoryImpl getOrCreateCallEventHistory(String phoneNumber) {
+        return mCallEventHistoryMap.computeIfAbsent(phoneNumber, key -> new EventHistoryImpl());
+    }
+
+    /**
+     * Gets the {@link EventHistoryImpl} for the specified {@code phoneNumber} for SMS events
+     * or creates a new instance and put it into the store if not exists. The caller needs to ensure
+     * a conversation with this phone number exists and this package is the default SMS app
+     * before calling this method.
+     */
+    @NonNull
+    EventHistoryImpl getOrCreateSmsEventHistory(String phoneNumber) {
+        return mSmsEventHistoryMap.computeIfAbsent(phoneNumber, key -> new EventHistoryImpl());
+    }
+}
diff --git a/services/people/java/com/android/server/people/data/PackageData.java b/services/people/java/com/android/server/people/data/PackageData.java
new file mode 100644
index 0000000..9c22a7f
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/PackageData.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.people.data;
+
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
+import android.content.LocusId;
+import android.text.TextUtils;
+
+import java.util.function.Consumer;
+
+/** The data associated with a package. */
+public class PackageData {
+
+    @NonNull
+    private final String mPackageName;
+
+    private final @UserIdInt int mUserId;
+
+    @NonNull
+    private final ConversationStore mConversationStore;
+
+    @NonNull
+    private final EventStore mEventStore;
+
+    private boolean mIsDefaultDialer;
+
+    private boolean mIsDefaultSmsApp;
+
+    PackageData(@NonNull String packageName, @UserIdInt int userId) {
+        mPackageName = packageName;
+        mUserId = userId;
+        mConversationStore = new ConversationStore();
+        mEventStore = new EventStore();
+    }
+
+    @NonNull
+    public String getPackageName() {
+        return mPackageName;
+    }
+
+    public @UserIdInt int getUserId() {
+        return mUserId;
+    }
+
+    /** Iterates over all the conversations in this package. */
+    public void forAllConversations(@NonNull Consumer<ConversationInfo> consumer) {
+        mConversationStore.forAllConversations(consumer);
+    }
+
+    @NonNull
+    public EventHistory getPackageLevelEventHistory() {
+        return getEventStore().getPackageEventHistory();
+    }
+
+    /**
+     * Gets the combined {@link EventHistory} for a given shortcut ID. This returned {@link
+     * EventHistory} has events of all types, no matter whether they're annotated with shortcut ID,
+     * Locus ID, or phone number etc.
+     */
+    @NonNull
+    public EventHistory getEventHistory(@NonNull String shortcutId) {
+        AggregateEventHistoryImpl result = new AggregateEventHistoryImpl();
+
+        ConversationInfo conversationInfo = mConversationStore.getConversation(shortcutId);
+        if (conversationInfo == null) {
+            return result;
+        }
+
+        EventHistory shortcutEventHistory = getEventStore().getShortcutEventHistory(shortcutId);
+        if (shortcutEventHistory != null) {
+            result.addEventHistory(shortcutEventHistory);
+        }
+
+        LocusId locusId = conversationInfo.getLocusId();
+        if (locusId != null) {
+            EventHistory locusEventHistory = getEventStore().getLocusEventHistory(locusId);
+            if (locusEventHistory != null) {
+                result.addEventHistory(locusEventHistory);
+            }
+        }
+
+        String phoneNumber = conversationInfo.getContactPhoneNumber();
+        if (TextUtils.isEmpty(phoneNumber)) {
+            return result;
+        }
+        if (isDefaultDialer()) {
+            EventHistory callEventHistory = getEventStore().getCallEventHistory(phoneNumber);
+            if (callEventHistory != null) {
+                result.addEventHistory(callEventHistory);
+            }
+        }
+        if (isDefaultSmsApp()) {
+            EventHistory smsEventHistory = getEventStore().getSmsEventHistory(phoneNumber);
+            if (smsEventHistory != null) {
+                result.addEventHistory(smsEventHistory);
+            }
+        }
+        return result;
+    }
+
+    public boolean isDefaultDialer() {
+        return mIsDefaultDialer;
+    }
+
+    public boolean isDefaultSmsApp() {
+        return mIsDefaultSmsApp;
+    }
+
+    @NonNull
+    ConversationStore getConversationStore() {
+        return mConversationStore;
+    }
+
+    @NonNull
+    EventStore getEventStore() {
+        return mEventStore;
+    }
+
+    void setIsDefaultDialer(boolean value) {
+        mIsDefaultDialer = value;
+    }
+
+    void setIsDefaultSmsApp(boolean value) {
+        mIsDefaultSmsApp = value;
+    }
+
+    void onDestroy() {
+        // TODO: STOPSHIP: Implements this method for the case of package being uninstalled.
+    }
+}
diff --git a/services/people/java/com/android/server/people/data/UserData.java b/services/people/java/com/android/server/people/data/UserData.java
new file mode 100644
index 0000000..2c16059
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/UserData.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.people.data;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+
+import java.util.Map;
+import java.util.function.Consumer;
+
+/** The data associated with a user profile. */
+class UserData {
+
+    private final @UserIdInt int mUserId;
+
+    private boolean mIsUnlocked;
+
+    private Map<String, PackageData> mPackageDataMap = new ArrayMap<>();
+
+    UserData(@UserIdInt int userId) {
+        mUserId = userId;
+    }
+
+    @UserIdInt int getUserId() {
+        return mUserId;
+    }
+
+    void forAllPackages(@NonNull Consumer<PackageData> consumer) {
+        for (PackageData packageData : mPackageDataMap.values()) {
+            consumer.accept(packageData);
+        }
+    }
+
+    void setUserUnlocked() {
+        mIsUnlocked = true;
+    }
+
+    void setUserStopped() {
+        mIsUnlocked = false;
+    }
+
+    boolean isUnlocked() {
+        return mIsUnlocked;
+    }
+
+    /**
+     * Gets the {@link PackageData} for the specified {@code packageName} if exists; otherwise
+     * creates a new instance and returns it.
+     */
+    @NonNull
+    PackageData getOrCreatePackageData(String packageName) {
+        return mPackageDataMap.computeIfAbsent(
+                packageName, key -> new PackageData(packageName, mUserId));
+    }
+
+    /**
+     * Gets the {@link PackageData} for the specified {@code packageName} if exists; otherwise
+     * returns {@code null}.
+     */
+    @Nullable
+    PackageData getPackageData(@NonNull String packageName) {
+        return mPackageDataMap.get(packageName);
+    }
+
+    void setDefaultDialer(@Nullable String packageName) {
+        for (PackageData packageData : mPackageDataMap.values()) {
+            if (packageData.isDefaultDialer()) {
+                packageData.setIsDefaultDialer(false);
+            }
+            if (TextUtils.equals(packageName, packageData.getPackageName())) {
+                packageData.setIsDefaultDialer(true);
+            }
+        }
+    }
+
+    void setDefaultSmsApp(@Nullable String packageName) {
+        for (PackageData packageData : mPackageDataMap.values()) {
+            if (packageData.isDefaultSmsApp()) {
+                packageData.setIsDefaultSmsApp(false);
+            }
+            if (TextUtils.equals(packageName, packageData.getPackageName())) {
+                packageData.setIsDefaultSmsApp(true);
+            }
+        }
+    }
+}
diff --git a/services/people/java/com/android/server/people/prediction/ConversationData.java b/services/people/java/com/android/server/people/prediction/ConversationData.java
new file mode 100644
index 0000000..0cc7633
--- /dev/null
+++ b/services/people/java/com/android/server/people/prediction/ConversationData.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.people.prediction;
+
+import android.annotation.NonNull;
+
+import com.android.server.people.data.ConversationInfo;
+import com.android.server.people.data.EventHistory;
+
+/** The conversation data which is used for scoring and then ranking the conversations. */
+class ConversationData {
+
+    private final String mPackageName;
+    private final int mUserId;
+    private final ConversationInfo mConversationInfo;
+    private final EventHistory mEventHistory;
+
+    ConversationData(@NonNull String packageName, int userId,
+            @NonNull ConversationInfo conversationInfo, @NonNull EventHistory eventHistory) {
+        mPackageName = packageName;
+        mUserId = userId;
+        mConversationInfo = conversationInfo;
+        mEventHistory = eventHistory;
+    }
+
+    String getPackageName() {
+        return mPackageName;
+    }
+
+    int getUserId() {
+        return mUserId;
+    }
+
+    ConversationInfo getConversationInfo() {
+        return mConversationInfo;
+    }
+
+    EventHistory getEventHistory() {
+        return mEventHistory;
+    }
+}
diff --git a/services/people/java/com/android/server/people/prediction/ConversationPredictor.java b/services/people/java/com/android/server/people/prediction/ConversationPredictor.java
index de71d29..ed8a56b 100644
--- a/services/people/java/com/android/server/people/prediction/ConversationPredictor.java
+++ b/services/people/java/com/android/server/people/prediction/ConversationPredictor.java
@@ -17,12 +17,20 @@
 package com.android.server.people.prediction;
 
 import android.annotation.MainThread;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.prediction.AppPredictionContext;
 import android.app.prediction.AppTarget;
 import android.app.prediction.AppTargetEvent;
 import android.app.prediction.AppTargetId;
+import android.content.IntentFilter;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager.ShareShortcutInfo;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.app.ChooserActivity;
+import com.android.server.people.data.DataManager;
+import com.android.server.people.data.EventHistory;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -35,15 +43,28 @@
  */
 public class ConversationPredictor {
 
+    private static final String UI_SURFACE_SHARE = "share";
+
     private final AppPredictionContext mPredictionContext;
     private final Consumer<List<AppTarget>> mUpdatePredictionsMethod;
+    private final DataManager mDataManager;
     private final ExecutorService mCallbackExecutor;
+    @Nullable
+    private final IntentFilter mIntentFilter;
 
-    public ConversationPredictor(AppPredictionContext predictionContext,
-            Consumer<List<AppTarget>> updatePredictionsMethod) {
+    public ConversationPredictor(@NonNull AppPredictionContext predictionContext,
+            @NonNull Consumer<List<AppTarget>> updatePredictionsMethod,
+            @NonNull DataManager dataManager) {
         mPredictionContext = predictionContext;
         mUpdatePredictionsMethod = updatePredictionsMethod;
+        mDataManager = dataManager;
         mCallbackExecutor = Executors.newSingleThreadExecutor();
+        if (UI_SURFACE_SHARE.equals(mPredictionContext.getUiSurface())) {
+            mIntentFilter = mPredictionContext.getExtras().getParcelable(
+                    ChooserActivity.APP_PREDICTION_INTENT_FILTER_KEY);
+        } else {
+            mIntentFilter = null;
+        }
     }
 
     /**
@@ -51,14 +72,14 @@
      */
     @MainThread
     public void onAppTargetEvent(AppTargetEvent event) {
+        mDataManager.reportAppTargetEvent(event, mIntentFilter);
     }
 
     /**
      * Called by the client app to indicate a particular location has been shown to the user.
      */
     @MainThread
-    public void onLaunchLocationShown(String launchLocation, List<AppTargetId> targetIds) {
-    }
+    public void onLaunchLocationShown(String launchLocation, List<AppTargetId> targetIds) {}
 
     /**
      * Called by the client app to request sorting of the provided targets based on the prediction
@@ -74,8 +95,44 @@
      */
     @MainThread
     public void onRequestPredictionUpdate() {
-        List<AppTarget> targets = new ArrayList<>();
-        mCallbackExecutor.execute(() -> mUpdatePredictionsMethod.accept(targets));
+        // TODO: Re-route the call to different ranking classes for different surfaces.
+        mCallbackExecutor.execute(() -> {
+            List<AppTarget> targets = new ArrayList<>();
+            if (mIntentFilter != null) {
+                List<ShareShortcutInfo> shareShortcuts =
+                        mDataManager.getConversationShareTargets(mIntentFilter);
+                for (ShareShortcutInfo shareShortcut : shareShortcuts) {
+                    ShortcutInfo shortcutInfo = shareShortcut.getShortcutInfo();
+                    AppTargetId appTargetId = new AppTargetId(shortcutInfo.getId());
+                    String shareTargetClass = shareShortcut.getTargetComponent().getClassName();
+                    targets.add(new AppTarget.Builder(appTargetId, shortcutInfo)
+                            .setClassName(shareTargetClass)
+                            .build());
+                }
+            } else {
+                List<ConversationData> conversationDataList = new ArrayList<>();
+                mDataManager.forAllPackages(packageData ->
+                        packageData.forAllConversations(conversationInfo -> {
+                            EventHistory eventHistory = packageData.getEventHistory(
+                                    conversationInfo.getShortcutId());
+                            ConversationData conversationData = new ConversationData(
+                                    packageData.getPackageName(), packageData.getUserId(),
+                                    conversationInfo, eventHistory);
+                            conversationDataList.add(conversationData);
+                        }));
+                for (ConversationData conversationData : conversationDataList) {
+                    String shortcutId = conversationData.getConversationInfo().getShortcutId();
+                    ShortcutInfo shortcut = mDataManager.getShortcut(
+                            conversationData.getPackageName(), conversationData.getUserId(),
+                            shortcutId);
+                    if (shortcut != null) {
+                        AppTargetId appTargetId = new AppTargetId(shortcut.getId());
+                        targets.add(new AppTarget.Builder(appTargetId, shortcut).build());
+                    }
+                }
+            }
+            mUpdatePredictionsMethod.accept(targets);
+        });
     }
 
     @VisibleForTesting
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
index f037692..1985513 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
@@ -120,7 +120,7 @@
                 CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_3);
         assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleFullFull).isEqualTo(
                 CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_4);
-        assertThat(mCachedAppOptimizerUnderTest.mStatsdSampleRate).isEqualTo(
+        assertThat(mCachedAppOptimizerUnderTest.mCompactStatsdSampleRate).isEqualTo(
                 CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE);
         assertThat(mCachedAppOptimizerUnderTest.mFullAnonRssThrottleKb).isEqualTo(
                 CachedAppOptimizer.DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB);
@@ -209,7 +209,7 @@
                 CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_5 + 1);
         assertThat(mCachedAppOptimizerUnderTest.mCompactThrottlePersistent).isEqualTo(
                 CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_6 + 1);
-        assertThat(mCachedAppOptimizerUnderTest.mStatsdSampleRate).isEqualTo(
+        assertThat(mCachedAppOptimizerUnderTest.mCompactStatsdSampleRate).isEqualTo(
                 CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE + 0.1f);
         assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleBFGS).isEqualTo(
                 CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_5 + 1);
@@ -472,7 +472,7 @@
     public void statsdSampleRate_listensToDeviceConfigChanges() throws InterruptedException {
         mCachedAppOptimizerUnderTest.init();
 
-        // When we override mStatsdSampleRate with a reasonable value ...
+        // When we override mCompactStatsdSampleRate with a reasonable value ...
         mCountDown = new CountDownLatch(1);
         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                 CachedAppOptimizer.KEY_COMPACT_STATSD_SAMPLE_RATE,
@@ -480,7 +480,7 @@
         assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
 
         // Then that override is reflected in the compactor.
-        assertThat(mCachedAppOptimizerUnderTest.mStatsdSampleRate).isEqualTo(
+        assertThat(mCachedAppOptimizerUnderTest.mCompactStatsdSampleRate).isEqualTo(
                 CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE + 0.1f);
     }
 
@@ -489,14 +489,14 @@
             throws InterruptedException {
         mCachedAppOptimizerUnderTest.init();
 
-        // When we override mStatsdSampleRate with an unreasonable value ...
+        // When we override mCompactStatsdSampleRate with an unreasonable value ...
         mCountDown = new CountDownLatch(1);
         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                 CachedAppOptimizer.KEY_COMPACT_STATSD_SAMPLE_RATE, "foo", false);
         assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
 
         // Then that override is reflected in the compactor.
-        assertThat(mCachedAppOptimizerUnderTest.mStatsdSampleRate).isEqualTo(
+        assertThat(mCachedAppOptimizerUnderTest.mCompactStatsdSampleRate).isEqualTo(
                 CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE);
     }
 
@@ -505,7 +505,7 @@
             throws InterruptedException {
         mCachedAppOptimizerUnderTest.init();
 
-        // When we override mStatsdSampleRate with an value outside of [0..1]...
+        // When we override mCompactStatsdSampleRate with an value outside of [0..1]...
         mCountDown = new CountDownLatch(1);
         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                 CachedAppOptimizer.KEY_COMPACT_STATSD_SAMPLE_RATE,
@@ -513,7 +513,7 @@
         assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
 
         // Then the values is capped in the range.
-        assertThat(mCachedAppOptimizerUnderTest.mStatsdSampleRate).isEqualTo(0.0f);
+        assertThat(mCachedAppOptimizerUnderTest.mCompactStatsdSampleRate).isEqualTo(0.0f);
 
         mCountDown = new CountDownLatch(1);
         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
@@ -522,7 +522,7 @@
         assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
 
         // Then the values is capped in the range.
-        assertThat(mCachedAppOptimizerUnderTest.mStatsdSampleRate).isEqualTo(1.0f);
+        assertThat(mCachedAppOptimizerUnderTest.mCompactStatsdSampleRate).isEqualTo(1.0f);
     }
 
     @Test
diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
index 067f23a..155de3b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
@@ -283,6 +283,8 @@
     }
 
 
+    /*
+    TODO ntmyren: re enable when we have time to rewrite test.
     @Test
     public void testPackageRemovedHistoricalOps() throws InterruptedException {
         mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
@@ -321,6 +323,7 @@
         assertThat(latchRef.get().getCount()).isEqualTo(0);
         assertThat(resultOpsRef.get().isEmpty()).isTrue();
     }
+     */
 
     @Test
     public void testUidRemoved() {
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
index 1c88c40..e724e60 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
@@ -20,6 +20,7 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -27,6 +28,9 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+import static com.android.server.job.JobSchedulerService.FREQUENT_INDEX;
+import static com.android.server.job.JobSchedulerService.RARE_INDEX;
+import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
@@ -568,6 +572,48 @@
         assertFalse(controller.isStandbyExceptionRequestedLocked(UID_RED));
     }
 
+    @Test
+    public void testRestrictedJobTracking() {
+        final JobStatus networked = createJobStatus(createJob()
+                .setEstimatedNetworkBytes(DataUnit.MEBIBYTES.toBytes(1), 0)
+                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_CELLULAR), UID_RED);
+        final JobStatus unnetworked = createJobStatus(createJob(), UID_BLUE);
+        networked.setStandbyBucket(FREQUENT_INDEX);
+        unnetworked.setStandbyBucket(FREQUENT_INDEX);
+
+        final Network cellularNet = new Network(101);
+        final NetworkCapabilities cellularCaps =
+                createCapabilities().addTransportType(TRANSPORT_CELLULAR);
+        reset(mConnManager);
+        answerNetwork(UID_RED, cellularNet, cellularCaps);
+        answerNetwork(UID_BLUE, cellularNet, cellularCaps);
+
+        final ConnectivityController controller = new ConnectivityController(mService);
+        controller.maybeStartTrackingJobLocked(networked, null);
+        controller.maybeStartTrackingJobLocked(unnetworked, null);
+
+        assertTrue(networked.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+        assertFalse(unnetworked.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+
+        networked.setStandbyBucket(RESTRICTED_INDEX);
+        unnetworked.setStandbyBucket(RESTRICTED_INDEX);
+        controller.startTrackingRestrictedJobLocked(networked);
+        controller.startTrackingRestrictedJobLocked(unnetworked);
+        assertFalse(networked.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+        // Unnetworked shouldn't be affected by ConnectivityController since it doesn't have a
+        // connectivity constraint.
+        assertFalse(unnetworked.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+
+        networked.setStandbyBucket(RARE_INDEX);
+        unnetworked.setStandbyBucket(RARE_INDEX);
+        controller.stopTrackingRestrictedJobLocked(networked);
+        controller.stopTrackingRestrictedJobLocked(unnetworked);
+        assertTrue(networked.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+        // Unnetworked shouldn't be affected by ConnectivityController since it doesn't have a
+        // connectivity constraint.
+        assertFalse(unnetworked.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+    }
+
     private void answerNetwork(int uid, Network net, NetworkCapabilities caps) {
         when(mConnManager.getActiveNetworkForUid(eq(uid))).thenReturn(net);
         when(mConnManager.getNetworkCapabilities(eq(net))).thenReturn(caps);
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index d2ddff3..b7c9001 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -66,6 +66,8 @@
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
     <uses-permission android:name="android.permission.SUSPEND_APPS"/>
     <uses-permission android:name="android.permission.CONTROL_KEYGUARD"/>
+    <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"/>
+    <uses-permission android:name="android.permission.LOG_COMPAT_CHANGE"/>
     <uses-permission android:name="android.permission.MANAGE_BIND_INSTANT_SERVICE"/>
     <uses-permission android:name="android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS" />
     <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
diff --git a/services/tests/servicestests/src/com/android/server/WatchdogDiagnosticsTest.java b/services/tests/servicestests/src/com/android/server/WatchdogDiagnosticsTest.java
index 4d229ef..625766a 100644
--- a/services/tests/servicestests/src/com/android/server/WatchdogDiagnosticsTest.java
+++ b/services/tests/servicestests/src/com/android/server/WatchdogDiagnosticsTest.java
@@ -157,6 +157,8 @@
             String expected =
                     "TestThread2 annotated stack trace:\n" +
                     "    at java.lang.Object.wait(Native Method)\n" +
+                    "    at java.lang.Object.wait(Object.java:442)\n" +
+                    "    at java.lang.Object.wait(Object.java:568)\n" +
                     "    at com.android.server.WatchdogDiagnosticsTest$TestThread2.y(" +
                             "WatchdogDiagnosticsTest.java:91)\n" +
                     "    - locked <HASH> (a java.lang.String)\n" +
diff --git a/services/tests/servicestests/src/com/android/server/backup/restore/PerformUnifiedRestoreTaskTest.java b/services/tests/servicestests/src/com/android/server/backup/restore/PerformUnifiedRestoreTaskTest.java
index 6359edf..3d22043 100644
--- a/services/tests/servicestests/src/com/android/server/backup/restore/PerformUnifiedRestoreTaskTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/restore/PerformUnifiedRestoreTaskTest.java
@@ -20,7 +20,6 @@
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
 
-import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.when;
 
@@ -55,6 +54,8 @@
     private static final String INCLUDED_KEY = "included_key";
     private static final String EXCLUDED_KEY_1 = "excluded_key_1";
     private static final String EXCLUDED_KEY_2 = "excluded_key_2";
+    private static final String SYSTEM_PACKAGE_NAME = "android";
+    private static final String NON_SYSTEM_PACKAGE_NAME = "package";
 
     @Mock private BackupDataInput mBackupDataInput;
     @Mock private BackupDataOutput mBackupDataOutput;
@@ -98,9 +99,6 @@
                         return null;
                     }
                 });
-
-        mRestoreTask = new PerformUnifiedRestoreTask(Collections.singletonMap(
-                PACKAGE_NAME, mExcludedkeys));
     }
 
     private void populateTestData() {
@@ -116,6 +114,8 @@
 
     @Test
     public void testFilterExcludedKeys() throws Exception {
+        mRestoreTask = new PerformUnifiedRestoreTask(Collections.singletonMap(
+                PACKAGE_NAME, mExcludedkeys));
         mRestoreTask.filterExcludedKeys(PACKAGE_NAME, mBackupDataInput, mBackupDataOutput);
 
         // Verify only the correct were written into BackupDataOutput object.
@@ -123,4 +123,34 @@
         allowedBackupKeys.removeAll(mExcludedkeys);
         assertEquals(allowedBackupKeys, mBackupDataDump);
     }
+
+    @Test
+    public void testStageBackupData_stageForNonSystemPackageWithKeysToExclude() {
+        mRestoreTask = new PerformUnifiedRestoreTask(Collections.singletonMap(
+                PACKAGE_NAME, mExcludedkeys));
+
+        assertTrue(mRestoreTask.shouldStageBackupData(NON_SYSTEM_PACKAGE_NAME));
+    }
+
+    @Test
+    public void testStageBackupData_stageForNonSystemPackageWithNoKeysToExclude() {
+        mRestoreTask = new PerformUnifiedRestoreTask(Collections.emptyMap());
+
+        assertTrue(mRestoreTask.shouldStageBackupData(NON_SYSTEM_PACKAGE_NAME));
+    }
+
+    @Test
+    public void testStageBackupData_doNotStageForSystemPackageWithNoKeysToExclude() {
+        mRestoreTask = new PerformUnifiedRestoreTask(Collections.emptyMap());
+
+        assertFalse(mRestoreTask.shouldStageBackupData(SYSTEM_PACKAGE_NAME));
+    }
+
+    @Test
+    public void testStageBackupData_stageForSystemPackageWithKeysToExclude() {
+        mRestoreTask = new PerformUnifiedRestoreTask(Collections.singletonMap(
+                PACKAGE_NAME, mExcludedkeys));
+
+        assertTrue(mRestoreTask.shouldStageBackupData(NON_SYSTEM_PACKAGE_NAME));
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 8f1d0f7..def5b61 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -2183,6 +2183,63 @@
         assertThat(actualAccounts).containsExactlyElementsIn(expectedAccounts);
     }
 
+    public void testSetApplicationHiddenWithDO() throws Exception {
+        mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+        setupDeviceOwner();
+        mContext.packageName = admin1.getPackageName();
+        setUpPackageManagerForAdmin(admin1, mContext.binder.callingUid);
+
+        String packageName = "com.google.android.test";
+
+        dpm.setApplicationHidden(admin1, packageName, true);
+        verify(getServices().ipackageManager).setApplicationHiddenSettingAsUser(packageName,
+                true, UserHandle.USER_SYSTEM);
+
+        dpm.setApplicationHidden(admin1, packageName, false);
+        verify(getServices().ipackageManager).setApplicationHiddenSettingAsUser(packageName,
+                false, UserHandle.USER_SYSTEM);
+
+        verify(getServices().ipackageManager, never()).getPackageInfo(packageName,
+                PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
+        verify(getServices().ipackageManager, never()).getPackageInfo(packageName,
+                PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.MATCH_SYSTEM_ONLY,
+                UserHandle.USER_SYSTEM);
+    }
+
+    public void testSetApplicationHiddenWithPOOfOrganizationOwnedDevice() throws Exception {
+        final int MANAGED_PROFILE_USER_ID = DpmMockContext.CALLER_USER_HANDLE;
+        final int MANAGED_PROFILE_ADMIN_UID =
+                UserHandle.getUid(MANAGED_PROFILE_USER_ID, DpmMockContext.SYSTEM_UID);
+        mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
+
+        addManagedProfile(admin1, MANAGED_PROFILE_ADMIN_UID, admin1);
+        configureProfileOwnerOfOrgOwnedDevice(admin1, DpmMockContext.CALLER_USER_HANDLE);
+        mContext.packageName = admin1.getPackageName();
+        setUpPackageManagerForAdmin(admin1, mContext.binder.callingUid);
+
+        String packageName = "com.google.android.test";
+
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.applicationInfo = new ApplicationInfo();
+        packageInfo.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
+        when(getServices().userManager.getProfileParent(MANAGED_PROFILE_USER_ID))
+                .thenReturn(new UserInfo(UserHandle.USER_SYSTEM, "user system", 0));
+        when(getServices().ipackageManager.getPackageInfo(packageName,
+                PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM)).thenReturn(
+                packageInfo);
+        when(getServices().ipackageManager.getPackageInfo(packageName,
+                PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.MATCH_SYSTEM_ONLY,
+                UserHandle.USER_SYSTEM)).thenReturn(packageInfo);
+
+        parentDpm.setApplicationHidden(admin1, packageName, true);
+        verify(getServices().ipackageManager).setApplicationHiddenSettingAsUser(packageName,
+                true, UserHandle.USER_SYSTEM);
+
+        parentDpm.setApplicationHidden(admin1, packageName, false);
+        verify(getServices().ipackageManager).setApplicationHiddenSettingAsUser(packageName,
+                false, UserHandle.USER_SYSTEM);
+    }
+
     public void testGetMacAddress() throws Exception {
         mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
         mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
diff --git a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
index a6af9a9..49ad866 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
@@ -32,11 +32,9 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.doThrow;
 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 static org.mockito.internal.verification.VerificationModeFactory.times;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -57,10 +55,8 @@
 import android.os.Message;
 
 import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.R;
-import com.android.server.LocalServices;
 import com.android.server.integrity.engine.RuleEvaluationEngine;
 import com.android.server.integrity.model.IntegrityCheckResult;
 import com.android.server.testutils.TestUtils;
@@ -68,6 +64,7 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnit;
@@ -81,7 +78,7 @@
 import java.util.Map;
 
 /** Unit test for {@link com.android.server.integrity.AppIntegrityManagerServiceImpl} */
-@RunWith(AndroidJUnit4.class)
+@RunWith(JUnit4.class)
 public class AppIntegrityManagerServiceImplTest {
     private static final String TEST_APP_PATH =
             "/data/local/tmp/AppIntegrityManagerServiceTestApp.apk";
@@ -91,8 +88,10 @@
     private static final String TEST_FRAMEWORK_PACKAGE = "com.android.frameworks.servicestests";
 
     private static final String PACKAGE_NAME = "com.test.app";
-    private static final int VERSION_CODE = 100;
+
+    private static final long VERSION_CODE = 100;
     private static final String INSTALLER = "com.long.random.test.installer.name";
+
     // These are obtained by running the test and checking logcat.
     private static final String APP_CERT =
             "301AA3CB081134501C45F1422ABC66C24224FD5DED5FDC8F17E697176FD866AA";
@@ -108,7 +107,8 @@
             "play_store_cert";
     private static final String ADB_CERT = "";
 
-    @org.junit.Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
+    @org.junit.Rule
+    public MockitoRule mMockitoRule = MockitoJUnit.rule();
 
     @Mock PackageManagerInternal mPackageManagerInternal;
     @Mock Context mMockContext;
@@ -144,36 +144,16 @@
         when(mIntegrityFileManager.initialized()).thenReturn(true);
     }
 
-    // This is not a test of the class, but more of a safeguard that we don't block any install in
-    // the default case. This is needed because we don't have any emergency kill switch to disable
-    // this component.
-    @Test
-    public void default_allow() throws Exception {
-        LocalServices.removeServiceForTest(PackageManagerInternal.class);
-        LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternal);
-        mService = AppIntegrityManagerServiceImpl.create(mMockContext);
-        ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
-                ArgumentCaptor.forClass(BroadcastReceiver.class);
-        verify(mMockContext, times(2))
-                .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any());
-        Intent intent = makeVerificationIntent();
-
-        broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent);
-
-        // Since we are not mocking handler in this case, we must wait.
-        // 2 seconds should be a sensible timeout.
-        Thread.sleep(2000);
-        verify(mPackageManagerInternal)
-                .setIntegrityVerificationResult(
-                        1, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
-    }
+    // TODO(b/148370598): Implement a test to validate that allow response is retuned when the test
+    //    request times out.
 
     @Test
     public void updateRuleSet_notAuthorized() throws Exception {
         makeUsSystemApp();
         Rule rule =
                 new Rule(
-                        new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
+                        new AtomicFormula.BooleanAtomicFormula(
+                                AtomicFormula.PRE_INSTALLED, true),
                         Rule.DENY);
         TestUtils.assertExpectException(
                 SecurityException.class,
@@ -191,7 +171,8 @@
         whitelistUsAsRuleProvider();
         Rule rule =
                 new Rule(
-                        new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
+                        new AtomicFormula.BooleanAtomicFormula(
+                                AtomicFormula.PRE_INSTALLED, true),
                         Rule.DENY);
         TestUtils.assertExpectException(
                 SecurityException.class,
@@ -210,7 +191,8 @@
         makeUsSystemApp();
         Rule rule =
                 new Rule(
-                        new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
+                        new AtomicFormula.BooleanAtomicFormula(
+                                AtomicFormula.PRE_INSTALLED, true),
                         Rule.DENY);
 
         // no SecurityException
@@ -346,10 +328,11 @@
         when(mRuleEvaluationEngine.evaluate(any(), any()))
                 .thenReturn(
                         IntegrityCheckResult.deny(
-                                new Rule(
-                                        new AtomicFormula.BooleanAtomicFormula(
-                                                AtomicFormula.PRE_INSTALLED, false),
-                                        Rule.DENY)));
+                                Arrays.asList(
+                                        new Rule(
+                                                new AtomicFormula.BooleanAtomicFormula(
+                                                        AtomicFormula.PRE_INSTALLED, false),
+                                                Rule.DENY))));
         Intent intent = makeVerificationIntent();
 
         broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent);
@@ -375,10 +358,10 @@
         broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent);
         runJobInHandler();
 
+        // The evaluation will still run since we still evaluate manifest based rules.
         verify(mPackageManagerInternal)
                 .setIntegrityVerificationResult(
                         1, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
-        verify(mSpyPackageManager, never()).getPackageArchiveInfo(any(), anyInt());
     }
 
     @Test
@@ -426,8 +409,8 @@
 
     private Intent makeVerificationIntent() throws Exception {
         PackageInfo packageInfo =
-                mRealContext.getPackageManager().getPackageInfo(TEST_FRAMEWORK_PACKAGE,
-                        PackageManager.GET_SIGNATURES);
+                mRealContext.getPackageManager()
+                        .getPackageInfo(TEST_FRAMEWORK_PACKAGE, PackageManager.GET_SIGNATURES);
         doReturn(packageInfo)
                 .when(mSpyPackageManager)
                 .getPackageInfo(eq(INSTALLER), anyInt());
@@ -447,7 +430,7 @@
         intent.putExtra(
                 EXTRA_VERIFICATION_INSTALLER_UID,
                 mMockContext.getPackageManager().getPackageUid(installer, /* flags= */ 0));
-        intent.putExtra(Intent.EXTRA_VERSION_CODE, VERSION_CODE);
+        intent.putExtra(Intent.EXTRA_LONG_VERSION_CODE, VERSION_CODE);
         return intent;
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java b/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java
index a1810b9..86daf69 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java
@@ -22,7 +22,7 @@
 
 import android.content.integrity.AppInstallMetadata;
 import android.content.integrity.AtomicFormula;
-import android.content.integrity.AtomicFormula.IntAtomicFormula;
+import android.content.integrity.AtomicFormula.LongAtomicFormula;
 import android.content.integrity.AtomicFormula.StringAtomicFormula;
 import android.content.integrity.CompoundFormula;
 import android.content.integrity.Rule;
@@ -116,7 +116,8 @@
         Rule packageCertRule = getAppCertificateIndexedRule(packageCert);
         Rule versionCodeRule =
                 new Rule(
-                        new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.LE, version),
+                        new LongAtomicFormula(
+                                AtomicFormula.VERSION_CODE, AtomicFormula.EQ, version),
                         Rule.DENY);
         Rule randomRule =
                 new Rule(
@@ -127,9 +128,9 @@
                                                 AtomicFormula.PACKAGE_NAME,
                                                 "abc",
                                                 /* isHashedValue= */ false),
-                                        new IntAtomicFormula(
+                                        new LongAtomicFormula(
                                                 AtomicFormula.VERSION_CODE,
-                                                AtomicFormula.LE,
+                                                AtomicFormula.EQ,
                                                 version))),
                         Rule.DENY);
 
@@ -201,21 +202,22 @@
     private Rule getPackageNameIndexedRule(String packageName) {
         return new Rule(
                 new StringAtomicFormula(
-                        AtomicFormula.PACKAGE_NAME, packageName, /* isHashedValue= */ false),
+                        AtomicFormula.PACKAGE_NAME, packageName, /* isHashedValue= */false),
                 Rule.DENY);
     }
 
     private Rule getAppCertificateIndexedRule(String appCertificate) {
         return new Rule(
                 new StringAtomicFormula(
-                        AtomicFormula.APP_CERTIFICATE, appCertificate, /* isHashedValue= */ false),
+                        AtomicFormula.APP_CERTIFICATE,
+                        appCertificate, /* isHashedValue= */ false),
                 Rule.DENY);
     }
 
     private Rule getInstallerCertificateRule(String installerCert) {
         return new Rule(
                 new StringAtomicFormula(
-                        AtomicFormula.INSTALLER_NAME, installerCert, /* isHashedValue= */ false),
+                        AtomicFormula.INSTALLER_NAME, installerCert, /* isHashedValue= */false),
                 Rule.DENY);
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/integrity/IntegrityUtilsTest.java b/services/tests/servicestests/src/com/android/server/integrity/IntegrityUtilsTest.java
deleted file mode 100644
index ac7f8f9..0000000
--- a/services/tests/servicestests/src/com/android/server/integrity/IntegrityUtilsTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.integrity;
-
-import static com.android.server.integrity.IntegrityUtils.getBytesFromHexDigest;
-import static com.android.server.integrity.IntegrityUtils.getHexDigest;
-import static com.android.server.testutils.TestUtils.assertExpectException;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/** Unit test for {@link com.android.server.integrity.IntegrityUtils} */
-@RunWith(AndroidJUnit4.class)
-public class IntegrityUtilsTest {
-
-    private static final String HEX_DIGEST = "1234567890ABCDEF";
-    private static final byte[] BYTES =
-            new byte[] {0x12, 0x34, 0x56, 0x78, (byte) 0x90, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF};
-
-    @Test
-    public void testGetBytesFromHexDigest() {
-        assertArrayEquals(BYTES, getBytesFromHexDigest(HEX_DIGEST));
-    }
-
-    @Test
-    public void testGetHexDigest() {
-        assertEquals(HEX_DIGEST, getHexDigest(BYTES));
-    }
-
-    @Test
-    public void testInvalidHexDigest() {
-        assertExpectException(
-                IllegalArgumentException.class,
-                "must have even length",
-                () -> getBytesFromHexDigest("ABC"));
-
-        assertExpectException(
-                IllegalArgumentException.class,
-                "Invalid hex char",
-                () -> getBytesFromHexDigest("GH"));
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluationEngineTest.java b/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluationEngineTest.java
index d386487..26b2096 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluationEngineTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluationEngineTest.java
@@ -16,12 +16,12 @@
 
 package com.android.server.integrity.engine;
 
-import static org.junit.Assert.assertEquals;
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.when;
 
 import android.content.integrity.AppInstallMetadata;
-import android.content.integrity.Rule;
 
 import com.android.server.integrity.IntegrityFileManager;
 import com.android.server.integrity.model.IntegrityCheckResult;
@@ -36,7 +36,6 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 
 @RunWith(JUnit4.class)
@@ -50,7 +49,8 @@
     private static final String RANDOM_INSTALLER = "random";
     private static final String RANDOM_INSTALLER_CERT = "random_cert";
 
-    @Mock private IntegrityFileManager mIntegrityFileManager;
+    @Mock
+    private IntegrityFileManager mIntegrityFileManager;
 
     private RuleEvaluationEngine mEngine;
 
@@ -67,33 +67,28 @@
     public void testAllowedInstallers_empty() {
         Map<String, String> allowedInstallers = Collections.emptyMap();
 
-        assertEquals(
-                IntegrityCheckResult.Effect.ALLOW,
-                mEngine.evaluate(
-                                getAppInstallMetadataBuilder()
-                                        .setInstallerName(INSTALLER_1)
-                                        .setInstallerCertificate(INSTALLER_1_CERT)
-                                        .build(),
-                                allowedInstallers)
-                        .getEffect());
-        assertEquals(
-                IntegrityCheckResult.Effect.ALLOW,
-                mEngine.evaluate(
-                                getAppInstallMetadataBuilder()
-                                        .setInstallerName(INSTALLER_2)
-                                        .setInstallerCertificate(INSTALLER_2_CERT)
-                                        .build(),
-                                allowedInstallers)
-                        .getEffect());
-        assertEquals(
-                IntegrityCheckResult.Effect.ALLOW,
-                mEngine.evaluate(
-                                getAppInstallMetadataBuilder()
-                                        .setInstallerName(RANDOM_INSTALLER)
-                                        .setInstallerCertificate(RANDOM_INSTALLER_CERT)
-                                        .build(),
-                                allowedInstallers)
-                        .getEffect());
+        AppInstallMetadata appInstallMetadata1 =
+                getAppInstallMetadataBuilder()
+                        .setInstallerName(INSTALLER_1)
+                        .setInstallerCertificate(INSTALLER_1_CERT)
+                        .build();
+        AppInstallMetadata appInstallMetadata2 =
+                getAppInstallMetadataBuilder()
+                        .setInstallerName(INSTALLER_2)
+                        .setInstallerCertificate(INSTALLER_2_CERT)
+                        .build();
+        AppInstallMetadata appInstallMetadata3 =
+                getAppInstallMetadataBuilder()
+                        .setInstallerName(RANDOM_INSTALLER)
+                        .setInstallerCertificate(RANDOM_INSTALLER_CERT)
+                        .build();
+
+        assertThat(mEngine.evaluate(appInstallMetadata1, allowedInstallers).getEffect())
+                .isEqualTo(IntegrityCheckResult.Effect.ALLOW);
+        assertThat(mEngine.evaluate(appInstallMetadata2, allowedInstallers).getEffect())
+                .isEqualTo(IntegrityCheckResult.Effect.ALLOW);
+        assertThat(mEngine.evaluate(appInstallMetadata3, allowedInstallers).getEffect())
+                .isEqualTo(IntegrityCheckResult.Effect.ALLOW);
     }
 
     @Test
@@ -101,87 +96,100 @@
         Map<String, String> allowedInstallers =
                 Collections.singletonMap(INSTALLER_1, INSTALLER_1_CERT);
 
-        assertEquals(
-                IntegrityCheckResult.Effect.ALLOW,
-                mEngine.evaluate(
-                                getAppInstallMetadataBuilder()
-                                        .setInstallerName(INSTALLER_1)
-                                        .setInstallerCertificate(INSTALLER_1_CERT)
-                                        .build(),
-                                allowedInstallers)
-                        .getEffect());
-        assertEquals(
-                IntegrityCheckResult.Effect.DENY,
-                mEngine.evaluate(
-                                getAppInstallMetadataBuilder()
-                                        .setInstallerName(RANDOM_INSTALLER)
-                                        .setInstallerCertificate(INSTALLER_1_CERT)
-                                        .build(),
-                                allowedInstallers)
-                        .getEffect());
-        assertEquals(
-                IntegrityCheckResult.Effect.DENY,
-                mEngine.evaluate(
-                                getAppInstallMetadataBuilder()
-                                        .setInstallerName(INSTALLER_1)
-                                        .setInstallerCertificate(RANDOM_INSTALLER_CERT)
-                                        .build(),
-                                allowedInstallers)
-                        .getEffect());
-        assertEquals(
-                IntegrityCheckResult.Effect.DENY,
-                mEngine.evaluate(
-                                getAppInstallMetadataBuilder()
-                                        .setInstallerName(RANDOM_INSTALLER)
-                                        .setInstallerCertificate(RANDOM_INSTALLER_CERT)
-                                        .build(),
-                                allowedInstallers)
-                        .getEffect());
+        AppInstallMetadata appInstallMetadata1 =
+                getAppInstallMetadataBuilder()
+                        .setInstallerName(INSTALLER_1)
+                        .setInstallerCertificate(INSTALLER_1_CERT)
+                        .build();
+        assertThat(mEngine.evaluate(appInstallMetadata1, allowedInstallers).getEffect())
+                .isEqualTo(IntegrityCheckResult.Effect.ALLOW);
+
+        AppInstallMetadata appInstallMetadata2 =
+                getAppInstallMetadataBuilder()
+                        .setInstallerName(RANDOM_INSTALLER)
+                        .setInstallerCertificate(INSTALLER_1_CERT)
+                        .build();
+        assertThat(mEngine.evaluate(appInstallMetadata2, allowedInstallers).getEffect())
+                .isEqualTo(IntegrityCheckResult.Effect.DENY);
+
+        AppInstallMetadata appInstallMetadata3 =
+                getAppInstallMetadataBuilder()
+                        .setInstallerName(INSTALLER_1)
+                        .setInstallerCertificate(RANDOM_INSTALLER_CERT)
+                        .build();
+        assertThat(mEngine.evaluate(appInstallMetadata3, allowedInstallers).getEffect())
+                .isEqualTo(IntegrityCheckResult.Effect.DENY);
+
+        AppInstallMetadata appInstallMetadata4 =
+                getAppInstallMetadataBuilder()
+                        .setInstallerName(INSTALLER_1)
+                        .setInstallerCertificate(RANDOM_INSTALLER_CERT)
+                        .build();
+        assertThat(mEngine.evaluate(appInstallMetadata4, allowedInstallers).getEffect())
+                .isEqualTo(IntegrityCheckResult.Effect.DENY);
     }
 
     @Test
     public void testAllowedInstallers_multipleElement() {
-        List<Rule> rules = new ArrayList<>();
         Map<String, String> allowedInstallers = new HashMap<>(2);
         allowedInstallers.put(INSTALLER_1, INSTALLER_1_CERT);
         allowedInstallers.put(INSTALLER_2, INSTALLER_2_CERT);
 
-        assertEquals(
-                IntegrityCheckResult.Effect.ALLOW,
-                mEngine.evaluate(
-                                getAppInstallMetadataBuilder()
-                                        .setInstallerName(INSTALLER_1)
-                                        .setInstallerCertificate(INSTALLER_1_CERT)
-                                        .build(),
-                                allowedInstallers)
-                        .getEffect());
-        assertEquals(
-                IntegrityCheckResult.Effect.ALLOW,
-                mEngine.evaluate(
-                                getAppInstallMetadataBuilder()
-                                        .setInstallerName(INSTALLER_2)
-                                        .setInstallerCertificate(INSTALLER_2_CERT)
-                                        .build(),
-                                allowedInstallers)
-                        .getEffect());
-        assertEquals(
-                IntegrityCheckResult.Effect.DENY,
-                mEngine.evaluate(
-                                getAppInstallMetadataBuilder()
-                                        .setInstallerName(INSTALLER_1)
-                                        .setInstallerCertificate(INSTALLER_2_CERT)
-                                        .build(),
-                                allowedInstallers)
-                        .getEffect());
-        assertEquals(
-                IntegrityCheckResult.Effect.DENY,
-                mEngine.evaluate(
-                                getAppInstallMetadataBuilder()
-                                        .setInstallerName(INSTALLER_2)
-                                        .setInstallerCertificate(INSTALLER_1_CERT)
-                                        .build(),
-                                allowedInstallers)
-                        .getEffect());
+        AppInstallMetadata appInstallMetadata1 =
+                getAppInstallMetadataBuilder()
+                        .setInstallerName(INSTALLER_1)
+                        .setInstallerCertificate(INSTALLER_1_CERT)
+                        .build();
+        assertThat(mEngine.evaluate(appInstallMetadata1, allowedInstallers).getEffect())
+                .isEqualTo(IntegrityCheckResult.Effect.ALLOW);
+
+        AppInstallMetadata appInstallMetadata2 =
+                getAppInstallMetadataBuilder()
+                        .setInstallerName(INSTALLER_2)
+                        .setInstallerCertificate(INSTALLER_2_CERT)
+                        .build();
+        assertThat(mEngine.evaluate(appInstallMetadata2, allowedInstallers).getEffect())
+                .isEqualTo(IntegrityCheckResult.Effect.ALLOW);
+
+        AppInstallMetadata appInstallMetadata3 =
+                getAppInstallMetadataBuilder()
+                        .setInstallerName(INSTALLER_1)
+                        .setInstallerCertificate(INSTALLER_2_CERT)
+                        .build();
+        assertThat(mEngine.evaluate(appInstallMetadata3, allowedInstallers).getEffect())
+                .isEqualTo(IntegrityCheckResult.Effect.DENY);
+
+        AppInstallMetadata appInstallMetadata4 =
+                getAppInstallMetadataBuilder()
+                        .setInstallerName(INSTALLER_2)
+                        .setInstallerCertificate(INSTALLER_1_CERT)
+                        .build();
+        assertThat(mEngine.evaluate(appInstallMetadata4, allowedInstallers).getEffect())
+                .isEqualTo(IntegrityCheckResult.Effect.DENY);
+    }
+
+    @Test
+    public void manifestBasedRuleEvaluationWorksEvenWhenIntegrityFilesAreUnavailable() {
+        when(mIntegrityFileManager.initialized()).thenReturn(false);
+
+        Map<String, String> allowedInstallers =
+                Collections.singletonMap(INSTALLER_1, INSTALLER_1_CERT);
+
+        AppInstallMetadata appInstallMetadata1 =
+                getAppInstallMetadataBuilder()
+                        .setInstallerName(INSTALLER_1)
+                        .setInstallerCertificate(INSTALLER_1_CERT)
+                        .build();
+        assertThat(mEngine.evaluate(appInstallMetadata1, allowedInstallers).getEffect())
+                .isEqualTo(IntegrityCheckResult.Effect.ALLOW);
+
+        AppInstallMetadata appInstallMetadata2 =
+                getAppInstallMetadataBuilder()
+                        .setInstallerName(RANDOM_INSTALLER)
+                        .setInstallerCertificate(INSTALLER_1_CERT)
+                        .build();
+        assertThat(mEngine.evaluate(appInstallMetadata2, allowedInstallers).getEffect())
+                .isEqualTo(IntegrityCheckResult.Effect.DENY);
     }
 
     /** Returns a builder with all fields filled with some dummy data. */
diff --git a/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluatorTest.java b/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluatorTest.java
index eda2b70..7b53e5e 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluatorTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluatorTest.java
@@ -19,10 +19,11 @@
 import static com.android.server.integrity.model.IntegrityCheckResult.Effect.ALLOW;
 import static com.android.server.integrity.model.IntegrityCheckResult.Effect.DENY;
 
-import static org.junit.Assert.assertEquals;
+import static com.google.common.truth.Truth.assertThat;
 
 import android.content.integrity.AppInstallMetadata;
 import android.content.integrity.AtomicFormula;
+import android.content.integrity.AtomicFormula.LongAtomicFormula;
 import android.content.integrity.AtomicFormula.StringAtomicFormula;
 import android.content.integrity.CompoundFormula;
 import android.content.integrity.Rule;
@@ -57,12 +58,12 @@
 
         IntegrityCheckResult result = RuleEvaluator.evaluateRules(rules, APP_INSTALL_METADATA);
 
-        assertEquals(ALLOW, result.getEffect());
+        assertThat(result.getEffect()).isEqualTo(ALLOW);
     }
 
     @Test
     public void testEvaluateRules_noMatchedRules_allow() {
-        Rule rule1 =
+        Rule rule =
                 new Rule(
                         new StringAtomicFormula(
                                 AtomicFormula.PACKAGE_NAME,
@@ -71,9 +72,9 @@
                         Rule.DENY);
 
         IntegrityCheckResult result =
-                RuleEvaluator.evaluateRules(Collections.singletonList(rule1), APP_INSTALL_METADATA);
+                RuleEvaluator.evaluateRules(Collections.singletonList(rule), APP_INSTALL_METADATA);
 
-        assertEquals(ALLOW, result.getEffect());
+        assertThat(result.getEffect()).isEqualTo(ALLOW);
     }
 
     @Test
@@ -96,8 +97,8 @@
         IntegrityCheckResult result =
                 RuleEvaluator.evaluateRules(Arrays.asList(rule1, rule2), APP_INSTALL_METADATA);
 
-        assertEquals(DENY, result.getEffect());
-        assertEquals(rule1, result.getRule());
+        assertThat(result.getEffect()).isEqualTo(DENY);
+        assertThat(result.getMatchedRules()).containsExactly(rule1);
     }
 
     @Test
@@ -109,7 +110,7 @@
                                 PACKAGE_NAME_1,
                                 /* isHashedValue= */ false),
                         Rule.DENY);
-        CompoundFormula compoundFormula2 =
+        Rule rule2 = new Rule(
                 new CompoundFormula(
                         CompoundFormula.AND,
                         Arrays.asList(
@@ -120,53 +121,53 @@
                                 new StringAtomicFormula(
                                         AtomicFormula.APP_CERTIFICATE,
                                         APP_CERTIFICATE,
-                                        /* isHashedValue= */ false)));
-        Rule rule2 = new Rule(compoundFormula2, Rule.DENY);
+                                        /* isHashedValue= */ false))),
+                Rule.DENY);
 
         IntegrityCheckResult result =
                 RuleEvaluator.evaluateRules(Arrays.asList(rule1, rule2), APP_INSTALL_METADATA);
 
-        assertEquals(DENY, result.getEffect());
-        assertEquals(rule1, result.getRule());
+        assertThat(result.getEffect()).isEqualTo(DENY);
+        assertThat(result.getMatchedRules()).containsExactly(rule1, rule2);
     }
 
     @Test
     public void testEvaluateRules_ruleWithNot_deny() {
-        CompoundFormula compoundFormula =
+        Rule rule = new Rule(
                 new CompoundFormula(
                         CompoundFormula.NOT,
                         Collections.singletonList(
                                 new StringAtomicFormula(
                                         AtomicFormula.PACKAGE_NAME,
                                         PACKAGE_NAME_2,
-                                        /* isHashedValue= */ false)));
-        Rule rule = new Rule(compoundFormula, Rule.DENY);
+                                        /* isHashedValue= */ false))),
+                Rule.DENY);
 
         IntegrityCheckResult result =
                 RuleEvaluator.evaluateRules(Collections.singletonList(rule), APP_INSTALL_METADATA);
 
-        assertEquals(DENY, result.getEffect());
-        assertEquals(rule, result.getRule());
+        assertThat(result.getEffect()).isEqualTo(DENY);
+        assertThat(result.getMatchedRules()).containsExactly(rule);
     }
 
     @Test
     public void testEvaluateRules_ruleWithIntegerOperators_deny() {
         Rule rule =
                 new Rule(
-                        new AtomicFormula.IntAtomicFormula(
-                                AtomicFormula.VERSION_CODE, AtomicFormula.GT, 1),
+                        new LongAtomicFormula(AtomicFormula.VERSION_CODE,
+                                AtomicFormula.GT, 1),
                         Rule.DENY);
 
         IntegrityCheckResult result =
                 RuleEvaluator.evaluateRules(Collections.singletonList(rule), APP_INSTALL_METADATA);
 
-        assertEquals(DENY, result.getEffect());
-        assertEquals(rule, result.getRule());
+        assertThat(result.getEffect()).isEqualTo(DENY);
+        assertThat(result.getMatchedRules()).containsExactly(rule);
     }
 
     @Test
     public void testEvaluateRules_validForm_deny() {
-        CompoundFormula compoundFormula =
+        Rule rule = new Rule(
                 new CompoundFormula(
                         CompoundFormula.AND,
                         Arrays.asList(
@@ -177,19 +178,19 @@
                                 new StringAtomicFormula(
                                         AtomicFormula.APP_CERTIFICATE,
                                         APP_CERTIFICATE,
-                                        /* isHashedValue= */ false)));
-        Rule rule = new Rule(compoundFormula, Rule.DENY);
+                                        /* isHashedValue= */ false))),
+                Rule.DENY);
 
         IntegrityCheckResult result =
                 RuleEvaluator.evaluateRules(Collections.singletonList(rule), APP_INSTALL_METADATA);
 
-        assertEquals(DENY, result.getEffect());
-        assertEquals(rule, result.getRule());
+        assertThat(result.getEffect()).isEqualTo(DENY);
+        assertThat(result.getMatchedRules()).containsExactly(rule);
     }
 
     @Test
     public void testEvaluateRules_orRules() {
-        CompoundFormula compoundFormula =
+        Rule rule = new Rule(
                 new CompoundFormula(
                         CompoundFormula.OR,
                         Arrays.asList(
@@ -200,13 +201,14 @@
                                 new StringAtomicFormula(
                                         AtomicFormula.APP_CERTIFICATE,
                                         APP_CERTIFICATE,
-                                        /* isHashedValue= */ false)));
-        Rule rule = new Rule(compoundFormula, Rule.DENY);
+                                        /* isHashedValue= */ false))),
+                Rule.DENY);
 
         IntegrityCheckResult result =
                 RuleEvaluator.evaluateRules(Collections.singletonList(rule), APP_INSTALL_METADATA);
 
-        assertEquals(DENY, result.getEffect());
+        assertThat(result.getEffect()).isEqualTo(DENY);
+        assertThat(result.getMatchedRules()).containsExactly(rule);
     }
 
     @Test
@@ -230,7 +232,8 @@
         IntegrityCheckResult result =
                 RuleEvaluator.evaluateRules(Collections.singletonList(rule), APP_INSTALL_METADATA);
 
-        assertEquals(DENY, result.getEffect());
+        assertThat(result.getEffect()).isEqualTo(DENY);
+        assertThat(result.getMatchedRules()).containsExactly(rule);
     }
 
     @Test
@@ -242,7 +245,7 @@
                                 PACKAGE_NAME_1,
                                 /* isHashedValue= */ false),
                         Rule.FORCE_ALLOW);
-        CompoundFormula compoundFormula2 =
+        Rule rule2 = new Rule(
                 new CompoundFormula(
                         CompoundFormula.AND,
                         Arrays.asList(
@@ -253,13 +256,43 @@
                                 new StringAtomicFormula(
                                         AtomicFormula.APP_CERTIFICATE,
                                         APP_CERTIFICATE,
-                                        /* isHashedValue= */ false)));
-        Rule rule2 = new Rule(compoundFormula2, Rule.DENY);
+                                        /* isHashedValue= */ false))),
+                Rule.DENY);
 
         IntegrityCheckResult result =
                 RuleEvaluator.evaluateRules(Arrays.asList(rule1, rule2), APP_INSTALL_METADATA);
 
-        assertEquals(ALLOW, result.getEffect());
-        assertEquals(rule1, result.getRule());
+        assertThat(result.getEffect()).isEqualTo(ALLOW);
+        assertThat(result.getMatchedRules()).containsExactly(rule1);
     }
-}
+
+    @Test
+    public void testEvaluateRules_multipleMatches_forceAllow() {
+        Rule rule1 =
+                new Rule(
+                        new StringAtomicFormula(
+                                AtomicFormula.PACKAGE_NAME,
+                                PACKAGE_NAME_1,
+                                /* isHashedValue= */ false),
+                        Rule.FORCE_ALLOW);
+        Rule rule2 = new Rule(
+                new CompoundFormula(
+                        CompoundFormula.AND,
+                        Arrays.asList(
+                                new StringAtomicFormula(
+                                        AtomicFormula.PACKAGE_NAME,
+                                        PACKAGE_NAME_1,
+                                        /* isHashedValue= */ false),
+                                new StringAtomicFormula(
+                                        AtomicFormula.APP_CERTIFICATE,
+                                        APP_CERTIFICATE,
+                                        /* isHashedValue= */ false))),
+                Rule.FORCE_ALLOW);
+
+        IntegrityCheckResult result =
+                RuleEvaluator.evaluateRules(Arrays.asList(rule1, rule2), APP_INSTALL_METADATA);
+
+        assertThat(result.getEffect()).isEqualTo(ALLOW);
+        assertThat(result.getMatchedRules()).containsExactly(rule1, rule2);
+    }
+}
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/integrity/model/IntegrityCheckResultTest.java b/services/tests/servicestests/src/com/android/server/integrity/model/IntegrityCheckResultTest.java
new file mode 100644
index 0000000..9cc9f10
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/integrity/model/IntegrityCheckResultTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.model;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.integrity.AtomicFormula;
+import android.content.integrity.Rule;
+import android.util.StatsLog;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.Collections;
+
+@RunWith(JUnit4.class)
+public class IntegrityCheckResultTest {
+
+    @Test
+    public void createAllowResult() {
+        IntegrityCheckResult allowResult = IntegrityCheckResult.allow();
+
+        assertThat(allowResult.getEffect()).isEqualTo(IntegrityCheckResult.Effect.ALLOW);
+        assertThat(allowResult.getMatchedRules()).isEmpty();
+        assertThat(allowResult.getLoggingResponse())
+                .isEqualTo(StatsLog.INTEGRITY_CHECK_RESULT_REPORTED__RESPONSE__ALLOWED);
+    }
+
+    @Test
+    public void createAllowResultWithRule() {
+        String packageName = "com.test.deny";
+        Rule forceAllowRule =
+                new Rule(
+                        new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME,
+                                packageName),
+                        Rule.FORCE_ALLOW);
+
+        IntegrityCheckResult allowResult =
+                IntegrityCheckResult.allow(Collections.singletonList(forceAllowRule));
+
+        assertThat(allowResult.getEffect()).isEqualTo(IntegrityCheckResult.Effect.ALLOW);
+        assertThat(allowResult.getMatchedRules()).containsExactly(forceAllowRule);
+        assertThat(allowResult.getLoggingResponse())
+                .isEqualTo(StatsLog.INTEGRITY_CHECK_RESULT_REPORTED__RESPONSE__FORCE_ALLOWED);
+    }
+
+    @Test
+    public void createDenyResultWithRule() {
+        String packageName = "com.test.deny";
+        Rule failedRule =
+                new Rule(
+                        new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME,
+                                packageName),
+                        Rule.DENY);
+
+        IntegrityCheckResult denyResult =
+                IntegrityCheckResult.deny(Collections.singletonList(failedRule));
+
+        assertThat(denyResult.getEffect()).isEqualTo(IntegrityCheckResult.Effect.DENY);
+        assertThat(denyResult.getMatchedRules()).containsExactly(failedRule);
+        assertThat(denyResult.getLoggingResponse())
+                .isEqualTo(StatsLog.INTEGRITY_CHECK_RESULT_REPORTED__RESPONSE__REJECTED);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/integrity/parser/BinaryFileOperationsTest.java b/services/tests/servicestests/src/com/android/server/integrity/parser/BinaryFileOperationsTest.java
index cfa1de3..723b6c5 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/parser/BinaryFileOperationsTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/parser/BinaryFileOperationsTest.java
@@ -26,7 +26,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import com.android.server.integrity.IntegrityUtils;
+import android.content.integrity.IntegrityUtils;
+
 import com.android.server.integrity.model.BitInputStream;
 
 import org.junit.Test;
diff --git a/services/tests/servicestests/src/com/android/server/integrity/parser/RuleBinaryParserTest.java b/services/tests/servicestests/src/com/android/server/integrity/parser/RuleBinaryParserTest.java
index e0b2e22..38cf562 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/parser/RuleBinaryParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/parser/RuleBinaryParserTest.java
@@ -36,10 +36,9 @@
 
 import android.content.integrity.AtomicFormula;
 import android.content.integrity.CompoundFormula;
+import android.content.integrity.IntegrityUtils;
 import android.content.integrity.Rule;
 
-import com.android.server.integrity.IntegrityUtils;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -345,7 +344,7 @@
                         + ATOMIC_FORMULA_START_BITS
                         + VERSION_CODE
                         + EQ
-                        + getBits(versionCode, /* numOfBits= */ 32)
+                        + getBits(versionCode, /* numOfBits= */ 64)
                         + DENY
                         + END_BIT;
         byte[] ruleBytes = getBytes(ruleBits);
@@ -356,7 +355,7 @@
         RuleParser binaryParser = new RuleBinaryParser();
         Rule expectedRule =
                 new Rule(
-                        new AtomicFormula.IntAtomicFormula(
+                        new AtomicFormula.LongAtomicFormula(
                                 AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 1),
                         Rule.DENY);
 
@@ -384,7 +383,8 @@
         RuleParser binaryParser = new RuleBinaryParser();
         Rule expectedRule =
                 new Rule(
-                        new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
+                        new AtomicFormula.BooleanAtomicFormula(
+                                AtomicFormula.PRE_INSTALLED, true),
                         Rule.DENY);
 
         List<Rule> rules = binaryParser.parse(rule.array());
@@ -400,7 +400,7 @@
                         + ATOMIC_FORMULA_START_BITS
                         + VERSION_CODE
                         + EQ
-                        + getBits(versionCode, /* numOfBits= */ 32)
+                        + getBits(versionCode, /* numOfBits= */ 64)
                         + DENY;
         byte[] ruleBytes = getBytes(ruleBits);
         ByteBuffer rule =
@@ -488,7 +488,7 @@
                         + ATOMIC_FORMULA_START_BITS
                         + VERSION_CODE
                         + INVALID_OPERATOR
-                        + getBits(versionCode, /* numOfBits= */ 32)
+                        + getBits(versionCode, /* numOfBits= */ 64)
                         + COMPOUND_FORMULA_END_BITS
                         + DENY
                         + END_BIT;
diff --git a/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java b/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java
index 0f0dee9..c57136c 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java
@@ -46,15 +46,15 @@
         String ruleXmlCompoundFormula =
                 "<RL>"
                         + generateTagWithAttribute(
-                                /* tag= */ "R",
-                                Collections.singletonMap("E", String.valueOf(Rule.DENY)),
-                                /* closed= */ false)
+                        /* tag= */ "R",
+                        Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "OF",
-                                Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
-                                /* closed= */ false)
+                        /* tag= */ "OF",
+                        Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "AF", atomicFormulaAttrs, /* closed= */ true)
+                        /* tag= */ "AF", atomicFormulaAttrs, /* closed= */ true)
                         + "</OF>"
                         + "</R>"
                         + "</RL>";
@@ -83,15 +83,15 @@
         String ruleXmlCompoundFormula =
                 "<RL>"
                         + generateTagWithAttribute(
-                                /* tag= */ "R",
-                                Collections.singletonMap("E", String.valueOf(Rule.DENY)),
-                                /* closed= */ false)
+                        /* tag= */ "R",
+                        Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "OF",
-                                Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
-                                /* closed= */ false)
+                        /* tag= */ "OF",
+                        Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+                        /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
                         + "</OF>"
                         + "</R>"
                         + "</RL>";
@@ -123,17 +123,17 @@
         String ruleXmlCompoundFormula =
                 "<RL>"
                         + generateTagWithAttribute(
-                                /* tag= */ "R",
-                                Collections.singletonMap("E", String.valueOf(Rule.DENY)),
-                                /* closed= */ false)
+                        /* tag= */ "R",
+                        Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "OF",
-                                Collections.singletonMap("C", String.valueOf(CompoundFormula.AND)),
-                                /* closed= */ false)
+                        /* tag= */ "OF",
+                        Collections.singletonMap("C", String.valueOf(CompoundFormula.AND)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+                        /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
                         + generateTagWithAttribute(
-                                /* tag= */ "AF", appCertificateAttrs, /* closed= */ true)
+                        /* tag= */ "AF", appCertificateAttrs, /* closed= */ true)
                         + "</OF>"
                         + "</R>"
                         + "</RL>";
@@ -168,17 +168,17 @@
         String ruleXmlCompoundFormula =
                 "<RL>"
                         + generateTagWithAttribute(
-                                /* tag= */ "R",
-                                Collections.singletonMap("E", String.valueOf(Rule.DENY)),
-                                /* closed= */ false)
+                        /* tag= */ "R",
+                        Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "OF",
-                                Collections.singletonMap("C", String.valueOf(CompoundFormula.OR)),
-                                /* closed= */ false)
+                        /* tag= */ "OF",
+                        Collections.singletonMap("C", String.valueOf(CompoundFormula.OR)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+                        /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
                         + generateTagWithAttribute(
-                                /* tag= */ "AF", appCertificateAttrs, /* closed= */ true)
+                        /* tag= */ "AF", appCertificateAttrs, /* closed= */ true)
                         + "</OF>"
                         + "</R>"
                         + "</RL>";
@@ -211,15 +211,15 @@
         String ruleXmlCompoundFormula =
                 "<RL>"
                         + generateTagWithAttribute(
-                                /* tag= */ "R",
-                                Collections.singletonMap("E", String.valueOf(Rule.DENY)),
-                                /* closed= */ false)
+                        /* tag= */ "R",
+                        Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "OF",
-                                Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
-                                /* closed= */ false)
+                        /* tag= */ "OF",
+                        Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+                        /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
                         + "</OF>"
                         + "</R>"
                         + "</RL>";
@@ -252,17 +252,17 @@
         String ruleXmlCompoundFormula =
                 "<RL>"
                         + generateTagWithAttribute(
-                                /* tag= */ "R",
-                                Collections.singletonMap("E", String.valueOf(Rule.DENY)),
-                                /* closed= */ false)
+                        /* tag= */ "R",
+                        Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "OF",
-                                Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
-                                /* closed= */ false)
+                        /* tag= */ "OF",
+                        Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+                        /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
                         + generateTagWithAttribute(
-                                /* tag= */ "AF", versionCodeAttrs, /* closed= */ true)
+                        /* tag= */ "AF", versionCodeAttrs, /* closed= */ true)
                         + "</OF>"
                         + "</R>"
                         + "</RL>";
@@ -283,15 +283,15 @@
         String ruleXmlCompoundFormula =
                 "<RL>"
                         + generateTagWithAttribute(
-                                /* tag= */ "R",
-                                Collections.singletonMap("E", String.valueOf(Rule.DENY)),
-                                /* closed= */ false)
+                        /* tag= */ "R",
+                        Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "OF",
-                                Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
-                                /* closed= */ false)
+                        /* tag= */ "OF",
+                        Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+                        /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
                         + "</OF>"
                         + "</R>"
                         + "</RL>";
@@ -311,15 +311,15 @@
         String ruleXmlCompoundFormula =
                 "<RL>"
                         + generateTagWithAttribute(
-                                /* tag= */ "R",
-                                Collections.singletonMap("E", "INVALID_EFFECT"),
-                                /* closed= */ false)
+                        /* tag= */ "R",
+                        Collections.singletonMap("E", "INVALID_EFFECT"),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "OF",
-                                Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
-                                /* closed= */ false)
+                        /* tag= */ "OF",
+                        Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+                        /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
                         + "</OF>"
                         + "</R>"
                         + "</RL>";
@@ -339,17 +339,17 @@
         String ruleXmlCompoundFormula =
                 "<RL>"
                         + generateTagWithAttribute(
-                                /* tag= */ "R",
-                                Collections.singletonMap("E", String.valueOf(Rule.DENY)),
-                                /* closed= */ false)
+                        /* tag= */ "R",
+                        Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "OF",
-                                Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
-                                /* closed= */ false)
+                        /* tag= */ "OF",
+                        Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "InvalidAtomicFormula",
-                                packageNameAttrs,
-                                /* closed= */ true)
+                        /* tag= */ "InvalidAtomicFormula",
+                        packageNameAttrs,
+                        /* closed= */ true)
                         + "</OF>"
                         + "</R>"
                         + "</RL>";
@@ -369,11 +369,11 @@
         String ruleXmlAtomicFormula =
                 "<RL>"
                         + generateTagWithAttribute(
-                                /* tag= */ "R",
-                                Collections.singletonMap("E", String.valueOf(Rule.DENY)),
-                                /* closed= */ false)
+                        /* tag= */ "R",
+                        Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+                        /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
                         + "</R>"
                         + "</RL>";
         RuleParser xmlParser = new RuleXmlParser();
@@ -399,17 +399,17 @@
         String ruleXmlAtomicFormula =
                 "<RL>"
                         + generateTagWithAttribute(
-                                /* tag= */ "R",
-                                Collections.singletonMap("E", String.valueOf(Rule.DENY)),
-                                /* closed= */ false)
+                        /* tag= */ "R",
+                        Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "AF", versionCodeAttrs, /* closed= */ true)
+                        /* tag= */ "AF", versionCodeAttrs, /* closed= */ true)
                         + "</R>"
                         + "</RL>";
         RuleParser xmlParser = new RuleXmlParser();
         Rule expectedRule =
                 new Rule(
-                        new AtomicFormula.IntAtomicFormula(
+                        new AtomicFormula.LongAtomicFormula(
                                 AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 1),
                         Rule.DENY);
 
@@ -426,17 +426,18 @@
         String ruleXmlAtomicFormula =
                 "<RL>"
                         + generateTagWithAttribute(
-                                /* tag= */ "R",
-                                Collections.singletonMap("E", String.valueOf(Rule.DENY)),
-                                /* closed= */ false)
+                        /* tag= */ "R",
+                        Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "AF", preInstalledAttrs, /* closed= */ true)
+                        /* tag= */ "AF", preInstalledAttrs, /* closed= */ true)
                         + "</R>"
                         + "</RL>";
         RuleParser xmlParser = new RuleXmlParser();
         Rule expectedRule =
                 new Rule(
-                        new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
+                        new AtomicFormula.BooleanAtomicFormula(
+                                AtomicFormula.PRE_INSTALLED, true),
                         Rule.DENY);
 
         List<Rule> rules = xmlParser.parse(ruleXmlAtomicFormula.getBytes(StandardCharsets.UTF_8));
@@ -452,11 +453,11 @@
         String ruleXmlAtomicFormula =
                 "<RL>"
                         + generateTagWithAttribute(
-                                /* tag= */ "R",
-                                Collections.singletonMap("E", String.valueOf(Rule.DENY)),
-                                /* closed= */ false)
+                        /* tag= */ "R",
+                        Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+                        /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
                         + "</R>"
                         + "</RL>";
         RuleParser xmlParser = new RuleXmlParser();
@@ -481,11 +482,11 @@
         String ruleXmlAtomicFormula =
                 "<RL>"
                         + generateTagWithAttribute(
-                                /* tag= */ "R",
-                                Collections.singletonMap("E", String.valueOf(Rule.DENY)),
-                                /* closed= */ false)
+                        /* tag= */ "R",
+                        Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+                        /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
                         + "</R>"
                         + "</RL>";
         RuleParser xmlParser = new RuleXmlParser();
@@ -504,11 +505,11 @@
         String ruleXmlAtomicFormula =
                 "<RL>"
                         + generateTagWithAttribute(
-                                /* tag= */ "R",
-                                Collections.singletonMap("BadEffect", String.valueOf(Rule.DENY)),
-                                /* closed= */ false)
+                        /* tag= */ "R",
+                        Collections.singletonMap("BadEffect", String.valueOf(Rule.DENY)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+                        /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
                         + "</R>"
                         + "</RL>";
         RuleParser xmlParser = new RuleXmlParser();
@@ -526,16 +527,16 @@
         String ruleXmlCompoundFormula =
                 "<RL>"
                         + generateTagWithAttribute(
-                                /* tag= */ "R",
-                                Collections.singletonMap("E", String.valueOf(Rule.DENY)),
-                                /* closed= */ false)
+                        /* tag= */ "R",
+                        Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "OF",
-                                Collections.singletonMap(
-                                        "BadConnector", String.valueOf(CompoundFormula.NOT)),
-                                /* closed= */ false)
+                        /* tag= */ "OF",
+                        Collections.singletonMap(
+                                "BadConnector", String.valueOf(CompoundFormula.NOT)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+                        /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
                         + "</OF>"
                         + "</R>"
                         + "</RL>";
@@ -555,11 +556,11 @@
         String ruleXmlAtomicFormula =
                 "<RL>"
                         + generateTagWithAttribute(
-                                /* tag= */ "R",
-                                Collections.singletonMap("E", String.valueOf(Rule.DENY)),
-                                /* closed= */ false)
+                        /* tag= */ "R",
+                        Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+                        /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
                         + "</R>"
                         + "</RL>";
         RuleParser xmlParser = new RuleXmlParser();
@@ -577,15 +578,15 @@
         atomicFormulaAttrs.put("V", "com.app.test");
         String ruleXmlWithNoRuleList =
                 generateTagWithAttribute(
-                                /* tag= */ "R",
-                                Collections.singletonMap("E", String.valueOf(Rule.DENY)),
-                                /* closed= */ false)
+                        /* tag= */ "R",
+                        Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "OF",
-                                Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
-                                /* closed= */ false)
+                        /* tag= */ "OF",
+                        Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "AF", atomicFormulaAttrs, /* closed= */ true)
+                        /* tag= */ "AF", atomicFormulaAttrs, /* closed= */ true)
                         + "</OF>"
                         + "</R>";
         RuleParser xmlParser = new RuleXmlParser();
@@ -603,15 +604,15 @@
         atomicFormulaAttrs.put("V", "com.app.test");
         String ruleXmlWithNoRuleList =
                 generateTagWithAttribute(
-                                /* tag= */ "R",
-                                Collections.singletonMap("E", String.valueOf(Rule.DENY)),
-                                /* closed= */ false)
+                        /* tag= */ "R",
+                        Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "OF",
-                                Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
-                                /* closed= */ false)
+                        /* tag= */ "OF",
+                        Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
+                        /* closed= */ false)
                         + generateTagWithAttribute(
-                                /* tag= */ "AF", atomicFormulaAttrs, /* closed= */ true)
+                        /* tag= */ "AF", atomicFormulaAttrs, /* closed= */ true)
                         + "</OF>"
                         + "</R>";
         RuleParser xmlParser = new RuleXmlParser();
diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java
index e5cbeee..f3da286 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java
@@ -42,13 +42,12 @@
 import android.content.integrity.AppInstallMetadata;
 import android.content.integrity.AtomicFormula;
 import android.content.integrity.CompoundFormula;
-import android.content.integrity.Formula;
+import android.content.integrity.IntegrityFormula;
+import android.content.integrity.IntegrityUtils;
 import android.content.integrity.Rule;
 
 import androidx.annotation.NonNull;
 
-import com.android.server.integrity.IntegrityUtils;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -424,11 +423,12 @@
 
     @Test
     public void testBinaryString_serializeValidAtomicFormula_integerValue() throws Exception {
-        int versionCode = 1;
+        long versionCode = 1;
         Rule rule =
                 new Rule(
-                        new AtomicFormula.IntAtomicFormula(
-                                AtomicFormula.VERSION_CODE, AtomicFormula.EQ, versionCode),
+                        new AtomicFormula.LongAtomicFormula(
+                                AtomicFormula.VERSION_CODE, AtomicFormula.EQ,
+                                versionCode),
                         Rule.DENY);
         RuleSerializer binarySerializer = new RuleBinarySerializer();
         String expectedBits =
@@ -436,7 +436,7 @@
                         + ATOMIC_FORMULA_START_BITS
                         + VERSION_CODE
                         + EQ
-                        + getBits(versionCode, /* numOfBits= */ 32)
+                        + getBits(versionCode, /* numOfBits= */ 64)
                         + DENY
                         + END_BIT;
         ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
@@ -456,7 +456,8 @@
         String preInstalled = "1";
         Rule rule =
                 new Rule(
-                        new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
+                        new AtomicFormula.BooleanAtomicFormula(
+                                AtomicFormula.PRE_INSTALLED, true),
                         Rule.DENY);
         RuleSerializer binarySerializer = new RuleBinarySerializer();
         String expectedBits =
@@ -481,7 +482,7 @@
 
     @Test
     public void testBinaryString_serializeInvalidFormulaType() throws Exception {
-        Formula invalidFormula = getInvalidFormula();
+        IntegrityFormula invalidFormula = getInvalidFormula();
         Rule rule = new Rule(invalidFormula, Rule.DENY);
         RuleSerializer binarySerializer = new RuleBinarySerializer();
 
@@ -858,19 +859,19 @@
                 + END_BIT;
     }
 
-    private static Formula getInvalidFormula() {
-        return new Formula() {
-            @Override
-            public boolean isSatisfied(AppInstallMetadata appInstallMetadata) {
-                return false;
-            }
-
+    private static IntegrityFormula getInvalidFormula() {
+        return new AtomicFormula(0) {
             @Override
             public int getTag() {
                 return 0;
             }
 
             @Override
+            public boolean matches(AppInstallMetadata appInstallMetadata) {
+                return false;
+            }
+
+            @Override
             public int hashCode() {
                 return super.hashCode();
             }
diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java
index 1674422..038ab7f 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java
@@ -27,7 +27,7 @@
 import android.content.integrity.AppInstallMetadata;
 import android.content.integrity.AtomicFormula;
 import android.content.integrity.CompoundFormula;
-import android.content.integrity.Formula;
+import android.content.integrity.IntegrityFormula;
 import android.content.integrity.Rule;
 
 import androidx.annotation.NonNull;
@@ -71,9 +71,11 @@
                     SAMPLE_INSTALLER_CERTIFICATE,
                     /* isHashedValue= */ false);
     private static final AtomicFormula ATOMIC_FORMULA_WITH_VERSION_CODE =
-            new AtomicFormula.IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 12);
+            new AtomicFormula.LongAtomicFormula(AtomicFormula.VERSION_CODE,
+                    AtomicFormula.EQ, 12);
     private static final AtomicFormula ATOMIC_FORMULA_WITH_ISPREINSTALLED =
-            new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, /* booleanValue= */
+            new AtomicFormula.BooleanAtomicFormula(
+                    AtomicFormula.PRE_INSTALLED, /* booleanValue= */
                     true);
 
 
@@ -284,19 +286,19 @@
                 Rule.DENY);
     }
 
-    private Formula getInvalidFormula() {
-        return new Formula() {
-            @Override
-            public boolean isSatisfied(AppInstallMetadata appInstallMetadata) {
-                return false;
-            }
-
+    private IntegrityFormula getInvalidFormula() {
+        return new AtomicFormula(0) {
             @Override
             public int getTag() {
                 return 4;
             }
 
             @Override
+            public boolean matches(AppInstallMetadata appInstallMetadata) {
+                return false;
+            }
+
+            @Override
             public int hashCode() {
                 return super.hashCode();
             }
diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
index ff7722c..6558cd5 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
@@ -23,7 +23,7 @@
 import android.content.integrity.AppInstallMetadata;
 import android.content.integrity.AtomicFormula;
 import android.content.integrity.CompoundFormula;
-import android.content.integrity.Formula;
+import android.content.integrity.IntegrityFormula;
 import android.content.integrity.Rule;
 
 import androidx.annotation.NonNull;
@@ -328,7 +328,7 @@
     public void testXmlString_serializeValidAtomicFormula_integerValue() throws Exception {
         Rule rule =
                 new Rule(
-                        new AtomicFormula.IntAtomicFormula(
+                        new AtomicFormula.LongAtomicFormula(
                                 AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 1),
                         Rule.DENY);
         RuleSerializer xmlSerializer = new RuleXmlSerializer();
@@ -384,7 +384,7 @@
 
     @Test
     public void testXmlString_serializeInvalidFormulaType() throws Exception {
-        Formula invalidFormula = getInvalidFormula();
+        IntegrityFormula invalidFormula = getInvalidFormula();
         Rule rule = new Rule(invalidFormula, Rule.DENY);
         RuleSerializer xmlSerializer = new RuleXmlSerializer();
 
@@ -530,19 +530,19 @@
                 + "</R>";
     }
 
-    private Formula getInvalidFormula() {
-        return new Formula() {
-            @Override
-            public boolean isSatisfied(AppInstallMetadata appInstallMetadata) {
-                return false;
-            }
-
+    private IntegrityFormula getInvalidFormula() {
+        return new AtomicFormula(0) {
             @Override
             public int getTag() {
                 return 0;
             }
 
             @Override
+            public boolean matches(AppInstallMetadata appInstallMetadata) {
+                return false;
+            }
+
+            @Override
             public int hashCode() {
                 return super.hashCode();
             }
diff --git a/services/tests/servicestests/src/com/android/server/integrity/utils/TestUtils.java b/services/tests/servicestests/src/com/android/server/integrity/utils/TestUtils.java
index e54410b..55abc7c 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/utils/TestUtils.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/utils/TestUtils.java
@@ -18,8 +18,8 @@
 
 public class TestUtils {
 
-    public static String getBits(int component, int numOfBits) {
-        return String.format("%" + numOfBits + "s", Integer.toBinaryString(component))
+    public static String getBits(long component, int numOfBits) {
+        return String.format("%" + numOfBits + "s", Long.toBinaryString(component))
                 .replace(' ', '0');
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/GnssManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java
similarity index 97%
rename from services/tests/servicestests/src/com/android/server/GnssManagerServiceTest.java
rename to services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java
index 8b5444c..f262733 100644
--- a/services/tests/servicestests/src/com/android/server/GnssManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server;
+package com.android.server.location.gnss;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -52,6 +52,7 @@
 import android.os.Message;
 import android.os.RemoteException;
 
+import com.android.server.LocationManagerService;
 import com.android.server.location.GnssBatchingProvider;
 import com.android.server.location.GnssCapabilitiesProvider;
 import com.android.server.location.GnssLocationProvider;
@@ -71,11 +72,12 @@
 import org.mockito.MockitoAnnotations;
 import org.mockito.invocation.InvocationOnMock;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
 /**
- * Unit tests for {@link com.android.server.GnssManagerService}.
+ * Unit tests for {@link com.android.server.location.gnss.GnssManagerService}.
  */
 public class GnssManagerServiceTest {
 
@@ -111,7 +113,7 @@
     private Context mMockContext;
 
     // Class under test
-    private GnssManagerService mGnssManagerService;
+    private com.android.server.location.gnss.GnssManagerService mGnssManagerService;
 
     @Before
     public void setUp() {
@@ -371,7 +373,7 @@
     @Test
     public void addGnssBatchCallbackWithoutPermissionsTest() throws RemoteException {
         IBatchedLocationCallback mockBatchedLocationCallback = createMockBatchedLocationCallback();
-        List<Location> mockLocationList = (List<Location>) mock(List.class);
+        List<Location> mockLocationList = new ArrayList<>();
 
         disableLocationPermissions();
 
@@ -387,7 +389,7 @@
     @Test
     public void addGnssBatchCallbackWithPermissionsTest() throws RemoteException {
         IBatchedLocationCallback mockBatchedLocationCallback = createMockBatchedLocationCallback();
-        List<Location> mockLocationList = (List<Location>) mock(List.class);
+        List<Location> mockLocationList = new ArrayList<>();
 
         enableLocationPermissions();
 
@@ -404,7 +406,7 @@
     public void replaceGnssBatchCallbackTest() throws RemoteException {
         IBatchedLocationCallback mockBatchedLocationCallback1 = createMockBatchedLocationCallback();
         IBatchedLocationCallback mockBatchedLocationCallback2 = createMockBatchedLocationCallback();
-        List<Location> mockLocationList = (List<Location>) mock(List.class);
+        List<Location> mockLocationList = new ArrayList<>();
 
         enableLocationPermissions();
 
@@ -441,7 +443,7 @@
     @Test
     public void removeGnssBatchingCallbackWithoutPermissionsTest() throws RemoteException {
         IBatchedLocationCallback mockBatchedLocationCallback = createMockBatchedLocationCallback();
-        List<Location> mockLocationList = (List<Location>) mock(List.class);
+        List<Location> mockLocationList = new ArrayList<>();
 
         enableLocationPermissions();
 
@@ -461,7 +463,7 @@
     @Test
     public void removeGnssBatchingCallbackWithPermissionsTest() throws RemoteException {
         IBatchedLocationCallback mockBatchedLocationCallback = createMockBatchedLocationCallback();
-        List<Location> mockLocationList = (List<Location>) mock(List.class);
+        List<Location> mockLocationList = new ArrayList<>();
 
         enableLocationPermissions();
 
diff --git a/services/tests/servicestests/src/com/android/server/people/data/AggregateEventHistoryImplTest.java b/services/tests/servicestests/src/com/android/server/people/data/AggregateEventHistoryImplTest.java
new file mode 100644
index 0000000..b614a4f
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/people/data/AggregateEventHistoryImplTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.people.data;
+
+import static com.android.server.people.data.TestUtils.timestamp;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.List;
+
+@RunWith(JUnit4.class)
+public final class AggregateEventHistoryImplTest {
+
+    private static final long CURRENT_TIMESTAMP = timestamp("01-30 18:50");
+
+    private static final Event E1 = new Event(timestamp("01-06 05:26"),
+            Event.TYPE_NOTIFICATION_OPENED);
+    private static final Event E2 = new Event(timestamp("01-27 18:41"),
+            Event.TYPE_NOTIFICATION_OPENED);
+    private static final Event E3 = new Event(timestamp("01-30 03:06"),
+            Event.TYPE_SMS_OUTGOING);
+    private static final Event E4 = new Event(timestamp("01-30 18:14"),
+            Event.TYPE_SMS_INCOMING);
+
+    private EventHistoryImpl mEventHistory1;
+    private EventHistoryImpl mEventHistory2;
+
+    private AggregateEventHistoryImpl mAggEventHistory;
+
+    private EventIndex.Injector mInjector = new EventIndex.Injector() {
+        @Override
+        long currentTimeMillis() {
+            return CURRENT_TIMESTAMP;
+        }
+    };
+
+    @Before
+    public void setUp() {
+        mAggEventHistory = new AggregateEventHistoryImpl();
+
+        EventHistoryImpl.Injector injector = new EventHistoryImplInjector();
+
+        mEventHistory1 = new EventHistoryImpl(injector);
+        mEventHistory1.addEvent(E1);
+        mEventHistory1.addEvent(E2);
+
+        mEventHistory2 = new EventHistoryImpl(injector);
+        mEventHistory2.addEvent(E3);
+        mEventHistory2.addEvent(E4);
+    }
+
+    @Test
+    public void testEmptyAggregateEventHistory() {
+        assertTrue(mAggEventHistory.getEventIndex(Event.TYPE_SHORTCUT_INVOCATION).isEmpty());
+        assertTrue(mAggEventHistory.getEventIndex(Event.ALL_EVENT_TYPES).isEmpty());
+        assertTrue(mAggEventHistory.queryEvents(
+                Event.ALL_EVENT_TYPES, 0L, Long.MAX_VALUE).isEmpty());
+    }
+
+    @Test
+    public void testQueryEventIndexForSingleEventType() {
+        mAggEventHistory.addEventHistory(mEventHistory1);
+        mAggEventHistory.addEventHistory(mEventHistory2);
+
+        EventIndex eventIndex;
+
+        eventIndex = mAggEventHistory.getEventIndex(Event.TYPE_NOTIFICATION_OPENED);
+        assertEquals(2, eventIndex.getActiveTimeSlots().size());
+
+        eventIndex = mAggEventHistory.getEventIndex(Event.TYPE_SMS_OUTGOING);
+        assertEquals(1, eventIndex.getActiveTimeSlots().size());
+
+        eventIndex = mAggEventHistory.getEventIndex(Event.TYPE_SHORTCUT_INVOCATION);
+        assertTrue(eventIndex.isEmpty());
+    }
+
+    @Test
+    public void testQueryEventIndexForMultipleEventTypes() {
+        mAggEventHistory.addEventHistory(mEventHistory1);
+        mAggEventHistory.addEventHistory(mEventHistory2);
+
+        EventIndex eventIndex;
+
+        eventIndex = mAggEventHistory.getEventIndex(Event.SMS_EVENT_TYPES);
+        assertEquals(2, eventIndex.getActiveTimeSlots().size());
+
+        eventIndex = mAggEventHistory.getEventIndex(Event.ALL_EVENT_TYPES);
+        assertEquals(4, eventIndex.getActiveTimeSlots().size());
+    }
+
+    @Test
+    public void testQueryEvents() {
+        mAggEventHistory.addEventHistory(mEventHistory1);
+        mAggEventHistory.addEventHistory(mEventHistory2);
+
+        List<Event> events;
+
+        events = mAggEventHistory.queryEvents(Event.NOTIFICATION_EVENT_TYPES, 0L, Long.MAX_VALUE);
+        assertEquals(2, events.size());
+
+        events = mAggEventHistory.queryEvents(Event.ALL_EVENT_TYPES, 0L, Long.MAX_VALUE);
+        assertEquals(4, events.size());
+    }
+
+    private class EventHistoryImplInjector extends EventHistoryImpl.Injector {
+
+        EventIndex createEventIndex() {
+            return new EventIndex(mInjector);
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/ContactsQueryHelperTest.java b/services/tests/servicestests/src/com/android/server/people/data/ContactsQueryHelperTest.java
new file mode 100644
index 0000000..96302b9
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/people/data/ContactsQueryHelperTest.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.people.data;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.Contacts;
+import android.test.mock.MockContentProvider;
+import android.test.mock.MockContentResolver;
+import android.test.mock.MockContext;
+import android.util.ArrayMap;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Map;
+
+@RunWith(JUnit4.class)
+public final class ContactsQueryHelperTest {
+
+    private static final String CONTACT_LOOKUP_KEY = "123";
+    private static final String PHONE_NUMBER = "+1234567890";
+
+    private static final String[] CONTACTS_COLUMNS = new String[] {
+            Contacts._ID, Contacts.LOOKUP_KEY, Contacts.STARRED, Contacts.HAS_PHONE_NUMBER,
+            Contacts.CONTACT_LAST_UPDATED_TIMESTAMP };
+    private static final String[] CONTACTS_LOOKUP_COLUMNS = new String[] {
+            Contacts._ID, Contacts.LOOKUP_KEY, Contacts.STARRED, Contacts.HAS_PHONE_NUMBER };
+    private static final String[] PHONE_COLUMNS = new String[] {
+            ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER };
+
+    @Mock
+    private MockContext mContext;
+
+    private MatrixCursor mContactsCursor;
+    private MatrixCursor mContactsLookupCursor;
+    private MatrixCursor mPhoneCursor;
+    private ContactsQueryHelper mHelper;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mContactsCursor = new MatrixCursor(CONTACTS_COLUMNS);
+        mContactsLookupCursor = new MatrixCursor(CONTACTS_LOOKUP_COLUMNS);
+        mPhoneCursor = new MatrixCursor(PHONE_COLUMNS);
+
+        MockContentResolver contentResolver = new MockContentResolver();
+        ContactsContentProvider contentProvider = new ContactsContentProvider();
+        contentProvider.registerCursor(Contacts.CONTENT_URI, mContactsCursor);
+        contentProvider.registerCursor(
+                ContactsContract.PhoneLookup.CONTENT_FILTER_URI, mContactsLookupCursor);
+        contentProvider.registerCursor(
+                ContactsContract.CommonDataKinds.Email.CONTENT_LOOKUP_URI, mContactsLookupCursor);
+        contentProvider.registerCursor(
+                ContactsContract.CommonDataKinds.Phone.CONTENT_URI, mPhoneCursor);
+
+        contentResolver.addProvider(ContactsContract.AUTHORITY, contentProvider);
+        when(mContext.getContentResolver()).thenReturn(contentResolver);
+
+        mHelper = new ContactsQueryHelper(mContext);
+    }
+
+    @Test
+    public void testQueryWithUri() {
+        mContactsCursor.addRow(new Object[] {
+                /* id= */ 11, CONTACT_LOOKUP_KEY, /* starred= */ 1, /* hasPhoneNumber= */ 1,
+                /* lastUpdatedTimestamp= */ 100L });
+        mPhoneCursor.addRow(new String[] { PHONE_NUMBER });
+        Uri contactUri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, CONTACT_LOOKUP_KEY);
+        assertTrue(mHelper.query(contactUri.toString()));
+        assertNotNull(mHelper.getContactUri());
+        assertEquals(PHONE_NUMBER, mHelper.getPhoneNumber());
+        assertEquals(100L, mHelper.getLastUpdatedTimestamp());
+        assertTrue(mHelper.isStarred());
+    }
+
+    @Test
+    public void testQueryWithUriNotStarredNoPhoneNumber() {
+        mContactsCursor.addRow(new Object[] {
+                /* id= */ 11, CONTACT_LOOKUP_KEY, /* starred= */ 0, /* hasPhoneNumber= */ 0,
+                /* lastUpdatedTimestamp= */ 100L });
+        Uri contactUri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, CONTACT_LOOKUP_KEY);
+        assertTrue(mHelper.query(contactUri.toString()));
+        assertNotNull(mHelper.getContactUri());
+        assertNull(mHelper.getPhoneNumber());
+        assertFalse(mHelper.isStarred());
+        assertEquals(100L, mHelper.getLastUpdatedTimestamp());
+    }
+
+    @Test
+    public void testQueryWithUriNotFound() {
+        Uri contactUri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, CONTACT_LOOKUP_KEY);
+        assertFalse(mHelper.query(contactUri.toString()));
+    }
+
+    @Test
+    public void testQueryWithPhoneNumber() {
+        mContactsLookupCursor.addRow(new Object[] {
+                /* id= */ 11, CONTACT_LOOKUP_KEY, /* starred= */ 1, /* hasPhoneNumber= */ 1 });
+        mPhoneCursor.addRow(new String[] { PHONE_NUMBER });
+        String contactUri = "tel:" + PHONE_NUMBER;
+        assertTrue(mHelper.query(contactUri));
+        assertNotNull(mHelper.getContactUri());
+        assertEquals(PHONE_NUMBER, mHelper.getPhoneNumber());
+        assertTrue(mHelper.isStarred());
+    }
+
+    @Test
+    public void testQueryWithEmail() {
+        mContactsLookupCursor.addRow(new Object[] {
+                /* id= */ 11, CONTACT_LOOKUP_KEY, /* starred= */ 1, /* hasPhoneNumber= */ 0 });
+        String contactUri = "mailto:test@gmail.com";
+        assertTrue(mHelper.query(contactUri));
+        assertNotNull(mHelper.getContactUri());
+        assertNull(mHelper.getPhoneNumber());
+        assertTrue(mHelper.isStarred());
+    }
+
+    @Test
+    public void testQueryUpdatedContactSinceTime() {
+        mContactsCursor.addRow(new Object[] {
+                /* id= */ 11, CONTACT_LOOKUP_KEY, /* starred= */ 1, /* hasPhoneNumber= */ 0,
+                /* lastUpdatedTimestamp= */ 100L });
+        assertTrue(mHelper.querySince(50L));
+        assertNotNull(mHelper.getContactUri());
+        assertNull(mHelper.getPhoneNumber());
+        assertTrue(mHelper.isStarred());
+        assertEquals(100L, mHelper.getLastUpdatedTimestamp());
+    }
+
+    @Test
+    public void testQueryWithUnsupportedScheme() {
+        mContactsLookupCursor.addRow(new Object[] {
+                /* id= */ 11, CONTACT_LOOKUP_KEY, /* starred= */ 1, /* hasPhoneNumber= */ 1 });
+        mPhoneCursor.addRow(new String[] { PHONE_NUMBER });
+        String contactUri = "unknown:test";
+        assertFalse(mHelper.query(contactUri));
+    }
+
+    private class ContactsContentProvider extends MockContentProvider {
+
+        private Map<Uri, Cursor> mUriPrefixToCursorMap = new ArrayMap<>();
+
+        @Override
+        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+                String sortOrder) {
+            for (Uri prefixUri : mUriPrefixToCursorMap.keySet()) {
+                if (uri.isPathPrefixMatch(prefixUri)) {
+                    return mUriPrefixToCursorMap.get(prefixUri);
+                }
+            }
+            return mUriPrefixToCursorMap.get(uri);
+        }
+
+        private void registerCursor(Uri uriPrefix, Cursor cursor) {
+            mUriPrefixToCursorMap.put(uriPrefix, cursor);
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/ConversationInfoTest.java b/services/tests/servicestests/src/com/android/server/people/data/ConversationInfoTest.java
new file mode 100644
index 0000000..05a9a80
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/people/data/ConversationInfoTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.people.data;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.content.LocusId;
+import android.content.pm.ShortcutInfo;
+import android.net.Uri;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class ConversationInfoTest {
+
+    private static final String SHORTCUT_ID = "abc";
+    private static final LocusId LOCUS_ID = new LocusId("def");
+    private static final Uri CONTACT_URI = Uri.parse("tel:+1234567890");
+    private static final String PHONE_NUMBER = "+1234567890";
+    private static final String NOTIFICATION_CHANNEL_ID = "test : abc";
+
+    @Test
+    public void testBuild() {
+        ConversationInfo conversationInfo = new ConversationInfo.Builder()
+                .setShortcutId(SHORTCUT_ID)
+                .setLocusId(LOCUS_ID)
+                .setContactUri(CONTACT_URI)
+                .setContactPhoneNumber(PHONE_NUMBER)
+                .setNotificationChannelId(NOTIFICATION_CHANNEL_ID)
+                .setShortcutFlags(ShortcutInfo.FLAG_LONG_LIVED)
+                .setVip(true)
+                .setNotificationSilenced(true)
+                .setBubbled(true)
+                .setDemoted(true)
+                .setPersonImportant(true)
+                .setPersonBot(true)
+                .setContactStarred(true)
+                .build();
+
+        assertEquals(SHORTCUT_ID, conversationInfo.getShortcutId());
+        assertEquals(LOCUS_ID, conversationInfo.getLocusId());
+        assertEquals(CONTACT_URI, conversationInfo.getContactUri());
+        assertEquals(PHONE_NUMBER, conversationInfo.getContactPhoneNumber());
+        assertEquals(NOTIFICATION_CHANNEL_ID, conversationInfo.getNotificationChannelId());
+        assertTrue(conversationInfo.isShortcutLongLived());
+        assertTrue(conversationInfo.isVip());
+        assertTrue(conversationInfo.isNotificationSilenced());
+        assertTrue(conversationInfo.isBubbled());
+        assertTrue(conversationInfo.isDemoted());
+        assertTrue(conversationInfo.isPersonImportant());
+        assertTrue(conversationInfo.isPersonBot());
+        assertTrue(conversationInfo.isContactStarred());
+    }
+
+    @Test
+    public void testBuildEmpty() {
+        ConversationInfo conversationInfo = new ConversationInfo.Builder()
+                .setShortcutId(SHORTCUT_ID)
+                .build();
+
+        assertEquals(SHORTCUT_ID, conversationInfo.getShortcutId());
+        assertNull(conversationInfo.getLocusId());
+        assertNull(conversationInfo.getContactUri());
+        assertNull(conversationInfo.getContactPhoneNumber());
+        assertNull(conversationInfo.getNotificationChannelId());
+        assertFalse(conversationInfo.isShortcutLongLived());
+        assertFalse(conversationInfo.isVip());
+        assertFalse(conversationInfo.isNotificationSilenced());
+        assertFalse(conversationInfo.isBubbled());
+        assertFalse(conversationInfo.isDemoted());
+        assertFalse(conversationInfo.isPersonImportant());
+        assertFalse(conversationInfo.isPersonBot());
+        assertFalse(conversationInfo.isContactStarred());
+    }
+
+    @Test
+    public void testBuildFromAnotherConversationInfo() {
+        ConversationInfo source = new ConversationInfo.Builder()
+                .setShortcutId(SHORTCUT_ID)
+                .setLocusId(LOCUS_ID)
+                .setContactUri(CONTACT_URI)
+                .setContactPhoneNumber(PHONE_NUMBER)
+                .setNotificationChannelId(NOTIFICATION_CHANNEL_ID)
+                .setShortcutFlags(ShortcutInfo.FLAG_LONG_LIVED)
+                .setVip(true)
+                .setNotificationSilenced(true)
+                .setBubbled(true)
+                .setPersonImportant(true)
+                .setPersonBot(true)
+                .setContactStarred(true)
+                .build();
+
+        ConversationInfo destination = new ConversationInfo.Builder(source)
+                .setVip(false)
+                .setContactStarred(false)
+                .build();
+
+        assertEquals(SHORTCUT_ID, destination.getShortcutId());
+        assertEquals(LOCUS_ID, destination.getLocusId());
+        assertEquals(CONTACT_URI, destination.getContactUri());
+        assertEquals(PHONE_NUMBER, destination.getContactPhoneNumber());
+        assertEquals(NOTIFICATION_CHANNEL_ID, destination.getNotificationChannelId());
+        assertTrue(destination.isShortcutLongLived());
+        assertFalse(destination.isVip());
+        assertTrue(destination.isNotificationSilenced());
+        assertTrue(destination.isBubbled());
+        assertTrue(destination.isPersonImportant());
+        assertTrue(destination.isPersonBot());
+        assertFalse(destination.isContactStarred());
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/ConversationStoreTest.java b/services/tests/servicestests/src/com/android/server/people/data/ConversationStoreTest.java
new file mode 100644
index 0000000..a40c6ab
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/people/data/ConversationStoreTest.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.people.data;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.content.LocusId;
+import android.content.pm.ShortcutInfo;
+import android.net.Uri;
+import android.util.ArraySet;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.Set;
+
+@RunWith(JUnit4.class)
+public final class ConversationStoreTest {
+
+    private static final String SHORTCUT_ID = "abc";
+    private static final LocusId LOCUS_ID = new LocusId("def");
+    private static final Uri CONTACT_URI = Uri.parse("tel:+1234567890");
+    private static final String PHONE_NUMBER = "+1234567890";
+
+    private ConversationStore mConversationStore;
+
+    @Before
+    public void setUp() {
+        mConversationStore = new ConversationStore();
+    }
+
+    @Test
+    public void testAddConversation() {
+        mConversationStore.addOrUpdate(buildConversationInfo(SHORTCUT_ID));
+
+        ConversationInfo out = mConversationStore.getConversation(SHORTCUT_ID);
+        assertNotNull(out);
+        assertEquals(SHORTCUT_ID, out.getShortcutId());
+    }
+
+    @Test
+    public void testUpdateConversation() {
+        ConversationInfo original =
+                buildConversationInfo(SHORTCUT_ID, LOCUS_ID, CONTACT_URI, PHONE_NUMBER);
+        mConversationStore.addOrUpdate(original);
+        assertEquals(LOCUS_ID, mConversationStore.getConversation(SHORTCUT_ID).getLocusId());
+
+        LocusId newLocusId = new LocusId("ghi");
+        ConversationInfo update = buildConversationInfo(
+                SHORTCUT_ID, newLocusId, CONTACT_URI, PHONE_NUMBER);
+        mConversationStore.addOrUpdate(update);
+        assertEquals(newLocusId, mConversationStore.getConversation(SHORTCUT_ID).getLocusId());
+    }
+
+    @Test
+    public void testDeleteConversation() {
+        mConversationStore.addOrUpdate(buildConversationInfo(SHORTCUT_ID));
+        assertNotNull(mConversationStore.getConversation(SHORTCUT_ID));
+
+        mConversationStore.deleteConversation(SHORTCUT_ID);
+        assertNull(mConversationStore.getConversation(SHORTCUT_ID));
+    }
+
+    @Test
+    public void testForAllConversations() {
+        mConversationStore.addOrUpdate(buildConversationInfo("a"));
+        mConversationStore.addOrUpdate(buildConversationInfo("b"));
+        mConversationStore.addOrUpdate(buildConversationInfo("c"));
+
+        Set<String> shortcutIds = new ArraySet<>();
+
+        mConversationStore.forAllConversations(
+                conversationInfo -> shortcutIds.add(conversationInfo.getShortcutId()));
+        assertTrue(shortcutIds.contains("a"));
+        assertTrue(shortcutIds.contains("b"));
+        assertTrue(shortcutIds.contains("c"));
+    }
+
+    @Test
+    public void testGetConversationByLocusId() {
+        ConversationInfo in =
+                buildConversationInfo(SHORTCUT_ID, LOCUS_ID, CONTACT_URI, PHONE_NUMBER);
+        mConversationStore.addOrUpdate(in);
+        ConversationInfo out = mConversationStore.getConversationByLocusId(LOCUS_ID);
+        assertNotNull(out);
+        assertEquals(SHORTCUT_ID, out.getShortcutId());
+
+        mConversationStore.deleteConversation(SHORTCUT_ID);
+        assertNull(mConversationStore.getConversationByLocusId(LOCUS_ID));
+    }
+
+    @Test
+    public void testGetConversationByContactUri() {
+        ConversationInfo in =
+                buildConversationInfo(SHORTCUT_ID, LOCUS_ID, CONTACT_URI, PHONE_NUMBER);
+        mConversationStore.addOrUpdate(in);
+        ConversationInfo out = mConversationStore.getConversationByContactUri(CONTACT_URI);
+        assertNotNull(out);
+        assertEquals(SHORTCUT_ID, out.getShortcutId());
+
+        mConversationStore.deleteConversation(SHORTCUT_ID);
+        assertNull(mConversationStore.getConversationByContactUri(CONTACT_URI));
+    }
+
+    @Test
+    public void testGetConversationByPhoneNumber() {
+        ConversationInfo in =
+                buildConversationInfo(SHORTCUT_ID, LOCUS_ID, CONTACT_URI, PHONE_NUMBER);
+        mConversationStore.addOrUpdate(in);
+        ConversationInfo out = mConversationStore.getConversationByPhoneNumber(PHONE_NUMBER);
+        assertNotNull(out);
+        assertEquals(SHORTCUT_ID, out.getShortcutId());
+
+        mConversationStore.deleteConversation(SHORTCUT_ID);
+        assertNull(mConversationStore.getConversationByPhoneNumber(PHONE_NUMBER));
+    }
+
+    private static ConversationInfo buildConversationInfo(String shortcutId) {
+        return buildConversationInfo(shortcutId, null, null, null);
+    }
+
+    private static ConversationInfo buildConversationInfo(
+            String shortcutId, LocusId locusId, Uri contactUri, String phoneNumber) {
+        return new ConversationInfo.Builder()
+                .setShortcutId(shortcutId)
+                .setLocusId(locusId)
+                .setContactUri(contactUri)
+                .setContactPhoneNumber(phoneNumber)
+                .setShortcutFlags(ShortcutInfo.FLAG_LONG_LIVED)
+                .setVip(true)
+                .setBubbled(true)
+                .build();
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
new file mode 100644
index 0000000..9f3d656
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
@@ -0,0 +1,451 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.people.data;
+
+import static android.app.usage.UsageEvents.Event.SHORTCUT_INVOCATION;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.Notification;
+import android.app.Person;
+import android.app.prediction.AppTarget;
+import android.app.prediction.AppTargetEvent;
+import android.app.prediction.AppTargetId;
+import android.app.usage.UsageEvents;
+import android.app.usage.UsageStatsManagerInternal;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
+import android.content.pm.ShortcutManager.ShareShortcutInfo;
+import android.content.pm.ShortcutServiceInternal;
+import android.content.pm.UserInfo;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.ContactsContract;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.StatusBarNotification;
+import android.telephony.TelephonyManager;
+import android.util.Range;
+
+import com.android.internal.app.ChooserActivity;
+import com.android.server.LocalServices;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(JUnit4.class)
+public final class DataManagerTest {
+
+    private static final int USER_ID_PRIMARY = 0;
+    private static final int USER_ID_PRIMARY_MANAGED = 10;
+    private static final int USER_ID_SECONDARY = 11;
+    private static final String TEST_PKG_NAME = "pkg";
+    private static final String TEST_SHORTCUT_ID = "sc";
+    private static final String CONTACT_URI = "content://com.android.contacts/contacts/lookup/123";
+    private static final String PHONE_NUMBER = "+1234567890";
+
+    @Mock private Context mContext;
+    @Mock private ShortcutServiceInternal mShortcutServiceInternal;
+    @Mock private UsageStatsManagerInternal mUsageStatsManagerInternal;
+    @Mock private ShortcutManager mShortcutManager;
+    @Mock private UserManager mUserManager;
+    @Mock private TelephonyManager mTelephonyManager;
+    @Mock private ContentResolver mContentResolver;
+    @Mock private ScheduledExecutorService mExecutorService;
+    @Mock private ScheduledFuture mScheduledFuture;
+    @Mock private StatusBarNotification mStatusBarNotification;
+    @Mock private Notification mNotification;
+
+    private DataManager mDataManager;
+    private int mCallingUserId;
+    private TestInjector mInjector;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        addLocalServiceMock(ShortcutServiceInternal.class, mShortcutServiceInternal);
+
+        addLocalServiceMock(UsageStatsManagerInternal.class, mUsageStatsManagerInternal);
+
+        when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
+
+        when(mContext.getSystemService(Context.SHORTCUT_SERVICE)).thenReturn(mShortcutManager);
+        when(mContext.getSystemServiceName(ShortcutManager.class)).thenReturn(
+                Context.SHORTCUT_SERVICE);
+
+        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+        when(mContext.getSystemServiceName(UserManager.class)).thenReturn(
+                Context.USER_SERVICE);
+
+        when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
+
+        when(mExecutorService.scheduleAtFixedRate(any(Runnable.class), anyLong(), anyLong(), any(
+                TimeUnit.class))).thenReturn(mScheduledFuture);
+
+        when(mUserManager.getEnabledProfiles(USER_ID_PRIMARY))
+                .thenReturn(Arrays.asList(
+                        buildUserInfo(USER_ID_PRIMARY),
+                        buildUserInfo(USER_ID_PRIMARY_MANAGED)));
+        when(mUserManager.getEnabledProfiles(USER_ID_SECONDARY))
+                .thenReturn(Collections.singletonList(buildUserInfo(USER_ID_SECONDARY)));
+
+        when(mContext.getContentResolver()).thenReturn(mContentResolver);
+
+        when(mStatusBarNotification.getNotification()).thenReturn(mNotification);
+        when(mStatusBarNotification.getPackageName()).thenReturn(TEST_PKG_NAME);
+        when(mStatusBarNotification.getUser()).thenReturn(UserHandle.of(USER_ID_PRIMARY));
+        when(mNotification.getShortcutId()).thenReturn(TEST_SHORTCUT_ID);
+
+        mCallingUserId = USER_ID_PRIMARY;
+
+        mInjector = new TestInjector();
+        mDataManager = new DataManager(mContext, mInjector);
+        mDataManager.initialize();
+    }
+
+    @After
+    public void tearDown() {
+        LocalServices.removeServiceForTest(ShortcutServiceInternal.class);
+        LocalServices.removeServiceForTest(UsageStatsManagerInternal.class);
+    }
+
+    @Test
+    public void testAccessConversationFromTheSameProfileGroup() {
+        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+        mDataManager.onUserUnlocked(USER_ID_PRIMARY_MANAGED);
+        mDataManager.onUserUnlocked(USER_ID_SECONDARY);
+
+        mDataManager.onShortcutAddedOrUpdated(
+                buildShortcutInfo("pkg_1", USER_ID_PRIMARY, "sc_1",
+                        buildPerson(true, false)));
+        mDataManager.onShortcutAddedOrUpdated(
+                buildShortcutInfo("pkg_2", USER_ID_PRIMARY_MANAGED, "sc_2",
+                        buildPerson(false, true)));
+        mDataManager.onShortcutAddedOrUpdated(
+                buildShortcutInfo("pkg_3", USER_ID_SECONDARY, "sc_3", buildPerson()));
+
+        List<ConversationInfo> conversations = new ArrayList<>();
+        mDataManager.forAllPackages(
+                packageData -> packageData.forAllConversations(conversations::add));
+
+        // USER_ID_SECONDARY is not in the same profile group as USER_ID_PRIMARY.
+        assertEquals(2, conversations.size());
+
+        assertEquals("sc_1", conversations.get(0).getShortcutId());
+        assertTrue(conversations.get(0).isPersonImportant());
+        assertFalse(conversations.get(0).isPersonBot());
+        assertFalse(conversations.get(0).isContactStarred());
+        assertEquals(PHONE_NUMBER, conversations.get(0).getContactPhoneNumber());
+
+        assertEquals("sc_2", conversations.get(1).getShortcutId());
+        assertFalse(conversations.get(1).isPersonImportant());
+        assertTrue(conversations.get(1).isPersonBot());
+        assertFalse(conversations.get(0).isContactStarred());
+        assertEquals(PHONE_NUMBER, conversations.get(0).getContactPhoneNumber());
+    }
+
+    @Test
+    public void testAccessConversationForUnlockedUsersOnly() {
+        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+        mDataManager.onShortcutAddedOrUpdated(
+                buildShortcutInfo("pkg_1", USER_ID_PRIMARY, "sc_1", buildPerson()));
+        mDataManager.onShortcutAddedOrUpdated(
+                buildShortcutInfo("pkg_2", USER_ID_PRIMARY_MANAGED, "sc_2", buildPerson()));
+
+        List<ConversationInfo> conversations = new ArrayList<>();
+        mDataManager.forAllPackages(
+                packageData -> packageData.forAllConversations(conversations::add));
+
+        // USER_ID_PRIMARY_MANAGED is not locked, so only USER_ID_PRIMARY's conversation is stored.
+        assertEquals(1, conversations.size());
+        assertEquals("sc_1", conversations.get(0).getShortcutId());
+
+        mDataManager.onUserStopped(USER_ID_PRIMARY);
+        conversations.clear();
+        mDataManager.forAllPackages(
+                packageData -> packageData.forAllConversations(conversations::add));
+        assertTrue(conversations.isEmpty());
+    }
+
+    @Test
+    public void testGetShortcut() {
+        mDataManager.getShortcut(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID);
+        verify(mShortcutServiceInternal).getShortcuts(anyInt(), anyString(), anyLong(),
+                eq(TEST_PKG_NAME), eq(Collections.singletonList(TEST_SHORTCUT_ID)),
+                eq(null), anyInt(), eq(USER_ID_PRIMARY), anyInt(), anyInt());
+    }
+
+    @Test
+    public void testGetShareTargets() {
+        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+
+        ShortcutInfo shortcut1 =
+                buildShortcutInfo("pkg_1", USER_ID_PRIMARY, "sc_1", buildPerson());
+        ShareShortcutInfo shareShortcut1 =
+                new ShareShortcutInfo(shortcut1, new ComponentName("pkg_1", "activity"));
+
+        ShortcutInfo shortcut2 =
+                buildShortcutInfo("pkg_2", USER_ID_PRIMARY, "sc_2", buildPerson());
+        ShareShortcutInfo shareShortcut2 =
+                new ShareShortcutInfo(shortcut2, new ComponentName("pkg_2", "activity"));
+        mDataManager.onShortcutAddedOrUpdated(shortcut2);
+
+        when(mShortcutManager.getShareTargets(any(IntentFilter.class)))
+                .thenReturn(Arrays.asList(shareShortcut1, shareShortcut2));
+
+        List<ShareShortcutInfo> shareShortcuts =
+                mDataManager.getConversationShareTargets(new IntentFilter());
+        // Only "sc_2" is stored as a conversation.
+        assertEquals(1, shareShortcuts.size());
+        assertEquals("sc_2", shareShortcuts.get(0).getShortcutInfo().getId());
+    }
+
+    @Test
+    public void testReportAppTargetEvent() throws IntentFilter.MalformedMimeTypeException {
+        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
+                buildPerson());
+        mDataManager.onShortcutAddedOrUpdated(shortcut);
+
+        AppTarget appTarget = new AppTarget.Builder(new AppTargetId(TEST_SHORTCUT_ID), shortcut)
+                .build();
+        AppTargetEvent appTargetEvent =
+                new AppTargetEvent.Builder(appTarget, AppTargetEvent.ACTION_LAUNCH)
+                        .setLaunchLocation(ChooserActivity.LAUNCH_LOCATON_DIRECT_SHARE)
+                        .build();
+        IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SEND, "image/jpg");
+        mDataManager.reportAppTargetEvent(appTargetEvent, intentFilter);
+
+        List<Range<Long>> activeShareTimeSlots = new ArrayList<>();
+        mDataManager.forAllPackages(packageData ->
+                activeShareTimeSlots.addAll(
+                        packageData.getEventHistory(TEST_SHORTCUT_ID)
+                                .getEventIndex(Event.TYPE_SHARE_IMAGE)
+                                .getActiveTimeSlots()));
+        assertEquals(1, activeShareTimeSlots.size());
+    }
+
+    @Test
+    public void testContactsChanged() {
+        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+
+        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
+                buildPerson());
+        mDataManager.onShortcutAddedOrUpdated(shortcut);
+
+        final String newPhoneNumber = "+1000000000";
+        mInjector.mContactsQueryHelper.mIsStarred = true;
+        mInjector.mContactsQueryHelper.mPhoneNumber = newPhoneNumber;
+
+        ContentObserver contentObserver = mDataManager.getContactsContentObserverForTesting(
+                USER_ID_PRIMARY);
+        contentObserver.onChange(false, ContactsContract.Contacts.CONTENT_URI, USER_ID_PRIMARY);
+
+        List<ConversationInfo> conversations = new ArrayList<>();
+        mDataManager.forAllPackages(
+                packageData -> packageData.forAllConversations(conversations::add));
+        assertEquals(1, conversations.size());
+
+        assertEquals(TEST_SHORTCUT_ID, conversations.get(0).getShortcutId());
+        assertTrue(conversations.get(0).isContactStarred());
+        assertEquals(newPhoneNumber, conversations.get(0).getContactPhoneNumber());
+    }
+
+    @Test
+    public void testNotificationListener() {
+        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+
+        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
+                buildPerson());
+        mDataManager.onShortcutAddedOrUpdated(shortcut);
+
+        NotificationListenerService listenerService =
+                mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
+
+        listenerService.onNotificationRemoved(mStatusBarNotification, null,
+                NotificationListenerService.REASON_CLICK);
+
+        List<Range<Long>> activeNotificationOpenTimeSlots = new ArrayList<>();
+        mDataManager.forAllPackages(packageData ->
+                activeNotificationOpenTimeSlots.addAll(
+                        packageData.getEventHistory(TEST_SHORTCUT_ID)
+                                .getEventIndex(Event.TYPE_NOTIFICATION_OPENED)
+                                .getActiveTimeSlots()));
+        assertEquals(1, activeNotificationOpenTimeSlots.size());
+    }
+
+    @Test
+    public void testQueryUsageStatsService() {
+        UsageEvents.Event e = new UsageEvents.Event(SHORTCUT_INVOCATION,
+                System.currentTimeMillis());
+        e.mPackage = TEST_PKG_NAME;
+        e.mShortcutId = TEST_SHORTCUT_ID;
+        List<UsageEvents.Event> events = new ArrayList<>();
+        events.add(e);
+        UsageEvents usageEvents = new UsageEvents(events, new String[]{});
+        when(mUsageStatsManagerInternal.queryEventsForUser(anyInt(), anyLong(), anyLong(),
+                anyBoolean())).thenReturn(usageEvents);
+
+        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+
+        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
+                buildPerson());
+        mDataManager.onShortcutAddedOrUpdated(shortcut);
+
+        mDataManager.queryUsageStatsService(USER_ID_PRIMARY, 0L, Long.MAX_VALUE);
+
+        List<Range<Long>> activeShortcutInvocationTimeSlots = new ArrayList<>();
+        mDataManager.forAllPackages(packageData ->
+                activeShortcutInvocationTimeSlots.addAll(
+                        packageData.getEventHistory(TEST_SHORTCUT_ID)
+                                .getEventIndex(Event.TYPE_SHORTCUT_INVOCATION)
+                                .getActiveTimeSlots()));
+        assertEquals(1, activeShortcutInvocationTimeSlots.size());
+    }
+
+    private static <T> void addLocalServiceMock(Class<T> clazz, T mock) {
+        LocalServices.removeServiceForTest(clazz);
+        LocalServices.addService(clazz, mock);
+    }
+
+    private ShortcutInfo buildShortcutInfo(String packageName, int userId, String id,
+            @Nullable Person person) {
+        Context mockContext = mock(Context.class);
+        when(mockContext.getPackageName()).thenReturn(packageName);
+        when(mockContext.getUserId()).thenReturn(userId);
+        when(mockContext.getUser()).thenReturn(UserHandle.of(userId));
+        ShortcutInfo.Builder builder = new ShortcutInfo.Builder(mockContext, id)
+                .setShortLabel(id)
+                .setIntent(new Intent("TestIntent"));
+        if (person != null) {
+            builder.setPersons(new Person[] {person});
+        }
+        return builder.build();
+    }
+
+    private Person buildPerson() {
+        return buildPerson(true, false);
+    }
+
+    private Person buildPerson(boolean isImportant, boolean isBot) {
+        return new Person.Builder()
+                .setImportant(isImportant)
+                .setBot(isBot)
+                .setUri(CONTACT_URI)
+                .build();
+    }
+
+    private UserInfo buildUserInfo(int userId) {
+        return new UserInfo(userId, "", 0);
+    }
+
+    private class TestContactsQueryHelper extends ContactsQueryHelper {
+
+        private Uri mContactUri;
+        private boolean mIsStarred;
+        private String mPhoneNumber;
+
+        TestContactsQueryHelper(Context context) {
+            super(context);
+            mContactUri = Uri.parse(CONTACT_URI);
+            mIsStarred = false;
+            mPhoneNumber = PHONE_NUMBER;
+        }
+
+        @Override
+        boolean query(@NonNull String contactUri) {
+            return true;
+        }
+
+        @Override
+        boolean querySince(long sinceTime) {
+            return true;
+        }
+
+        @Override
+        @Nullable
+        Uri getContactUri() {
+            return mContactUri;
+        }
+
+        @Override
+        boolean isStarred() {
+            return mIsStarred;
+        }
+
+        @Override
+        @Nullable
+        String getPhoneNumber() {
+            return mPhoneNumber;
+        }
+    }
+
+    private class TestInjector extends DataManager.Injector {
+
+        private final TestContactsQueryHelper mContactsQueryHelper =
+                new TestContactsQueryHelper(mContext);
+
+        @Override
+        ScheduledExecutorService createScheduledExecutor() {
+            return mExecutorService;
+        }
+
+        @Override
+        ContactsQueryHelper createContactsQueryHelper(Context context) {
+            return mContactsQueryHelper;
+        }
+
+        @Override
+        int getCallingUserId() {
+            return mCallingUserId;
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/EventHistoryImplTest.java b/services/tests/servicestests/src/com/android/server/people/data/EventHistoryImplTest.java
new file mode 100644
index 0000000..43e1001
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/people/data/EventHistoryImplTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.people.data;
+
+import static com.android.server.people.data.TestUtils.timestamp;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.google.android.collect.Sets;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.List;
+
+@RunWith(JUnit4.class)
+public final class EventHistoryImplTest {
+
+    private static final long CURRENT_TIMESTAMP = timestamp("01-30 18:50");
+
+    private static final Event E1 = new Event(timestamp("01-06 05:26"),
+            Event.TYPE_NOTIFICATION_OPENED);
+    private static final Event E2 = new Event(timestamp("01-27 18:41"),
+            Event.TYPE_NOTIFICATION_OPENED);
+    private static final Event E3 = new Event(timestamp("01-30 03:06"),
+            Event.TYPE_SHARE_IMAGE);
+    private static final Event E4 = new Event(timestamp("01-30 18:14"),
+            Event.TYPE_SMS_INCOMING);
+
+    private EventHistoryImpl mEventHistory;
+
+    @Before
+    public void setUp() {
+        EventIndex.Injector eventIndexInjector = new EventIndex.Injector() {
+            @Override
+            long currentTimeMillis() {
+                return CURRENT_TIMESTAMP;
+            }
+        };
+        EventHistoryImpl.Injector eventHistoryInjector = new EventHistoryImpl.Injector() {
+            @Override
+            EventIndex createEventIndex() {
+                return new EventIndex(eventIndexInjector);
+            }
+        };
+        mEventHistory = new EventHistoryImpl(eventHistoryInjector);
+    }
+
+    @Test
+    public void testNoEvents() {
+        EventIndex eventIndex = mEventHistory.getEventIndex(Event.ALL_EVENT_TYPES);
+        assertTrue(eventIndex.isEmpty());
+
+        List<Event> events = mEventHistory.queryEvents(Event.ALL_EVENT_TYPES, 0L, 999L);
+        assertTrue(events.isEmpty());
+    }
+
+    @Test
+    public void testMultipleEvents() {
+        mEventHistory.addEvent(E1);
+        mEventHistory.addEvent(E2);
+        mEventHistory.addEvent(E3);
+        mEventHistory.addEvent(E4);
+
+        EventIndex eventIndex = mEventHistory.getEventIndex(Event.ALL_EVENT_TYPES);
+        assertEquals(4, eventIndex.getActiveTimeSlots().size());
+
+        List<Event> events = mEventHistory.queryEvents(Event.ALL_EVENT_TYPES, 0L, Long.MAX_VALUE);
+        assertEquals(4, events.size());
+    }
+
+    @Test
+    public void testQuerySomeEventTypes() {
+        mEventHistory.addEvent(E1);
+        mEventHistory.addEvent(E2);
+        mEventHistory.addEvent(E3);
+        mEventHistory.addEvent(E4);
+
+        EventIndex eventIndex = mEventHistory.getEventIndex(Event.NOTIFICATION_EVENT_TYPES);
+        assertEquals(2, eventIndex.getActiveTimeSlots().size());
+
+        List<Event> events = mEventHistory.queryEvents(
+                Event.NOTIFICATION_EVENT_TYPES, 0L, Long.MAX_VALUE);
+        assertEquals(2, events.size());
+    }
+
+    @Test
+    public void testQuerySingleEventType() {
+        mEventHistory.addEvent(E1);
+        mEventHistory.addEvent(E2);
+        mEventHistory.addEvent(E3);
+        mEventHistory.addEvent(E4);
+
+        EventIndex eventIndex = mEventHistory.getEventIndex(Event.TYPE_SHARE_IMAGE);
+        assertEquals(1, eventIndex.getActiveTimeSlots().size());
+
+        List<Event> events = mEventHistory.queryEvents(
+                Sets.newArraySet(Event.TYPE_SHARE_IMAGE), 0L, Long.MAX_VALUE);
+        assertEquals(1, events.size());
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/EventIndexTest.java b/services/tests/servicestests/src/com/android/server/people/data/EventIndexTest.java
new file mode 100644
index 0000000..e87f428
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/people/data/EventIndexTest.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.people.data;
+
+import static com.android.server.people.data.TestUtils.timestamp;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.util.Range;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.List;
+
+@RunWith(JUnit4.class)
+public final class EventIndexTest {
+
+    private static final long CURRENT_TIMESTAMP = timestamp("01-30 18:50");
+    private static final long SECONDS_PER_HOUR = 60L * 60L;
+    private static final long SECONDS_PER_DAY = SECONDS_PER_HOUR * 24L;
+
+    private TestInjector mInjector;
+    private EventIndex mEventIndex;
+
+    @Before
+    public void setUp() {
+        mInjector = new TestInjector(CURRENT_TIMESTAMP);
+        mEventIndex = new EventIndex(mInjector);
+    }
+
+    @Test
+    public void testNoEvents() {
+        assertTrue(mEventIndex.isEmpty());
+        assertNull(mEventIndex.getMostRecentActiveTimeSlot());
+        assertTrue(mEventIndex.getActiveTimeSlots().isEmpty());
+    }
+
+    @Test
+    public void testMultipleEvents() {
+        mEventIndex.addEvent(timestamp("01-06 05:26"));
+        mEventIndex.addEvent(timestamp("01-27 18:41"));
+        mEventIndex.addEvent(timestamp("01-30 03:06"));
+        mEventIndex.addEvent(timestamp("01-30 18:14"));
+
+        assertFalse(mEventIndex.isEmpty());
+        Range<Long> mostRecentSlot = mEventIndex.getMostRecentActiveTimeSlot();
+        assertNotNull(mostRecentSlot);
+        assertTimeSlot(timestamp("01-30 18:14"), timestamp("01-30 18:16"), mostRecentSlot);
+
+        List<Range<Long>> slots = mEventIndex.getActiveTimeSlots();
+        assertEquals(4, slots.size());
+        assertTimeSlot(timestamp("01-06 00:00"), timestamp("01-07 00:00"), slots.get(0));
+        assertTimeSlot(timestamp("01-27 16:00"), timestamp("01-27 20:00"), slots.get(1));
+        assertTimeSlot(timestamp("01-30 03:00"), timestamp("01-30 04:00"), slots.get(2));
+        assertTimeSlot(timestamp("01-30 18:14"), timestamp("01-30 18:16"), slots.get(3));
+    }
+
+    @Test
+    public void testBitmapShift() {
+        mEventIndex.addEvent(CURRENT_TIMESTAMP);
+        List<Range<Long>> slots;
+
+        slots = mEventIndex.getActiveTimeSlots();
+        assertEquals(1, slots.size());
+        assertTimeSlot(timestamp("01-30 18:50"), timestamp("01-30 18:52"), slots.get(0));
+
+        mInjector.moveTimeForwardSeconds(SECONDS_PER_HOUR * 3L);
+        mEventIndex.update();
+        slots = mEventIndex.getActiveTimeSlots();
+        assertEquals(1, slots.size());
+        assertTimeSlot(timestamp("01-30 18:00"), timestamp("01-30 19:00"), slots.get(0));
+
+        mInjector.moveTimeForwardSeconds(SECONDS_PER_DAY * 6L);
+        mEventIndex.update();
+        slots = mEventIndex.getActiveTimeSlots();
+        assertEquals(1, slots.size());
+        assertTimeSlot(timestamp("01-30 16:00"), timestamp("01-30 20:00"), slots.get(0));
+
+        mInjector.moveTimeForwardSeconds(SECONDS_PER_DAY * 30L);
+        mEventIndex.update();
+        slots = mEventIndex.getActiveTimeSlots();
+        assertEquals(1, slots.size());
+        assertTimeSlot(timestamp("01-30 00:00"), timestamp("01-31 00:00"), slots.get(0));
+
+        mInjector.moveTimeForwardSeconds(SECONDS_PER_DAY * 80L);
+        mEventIndex.update();
+        slots = mEventIndex.getActiveTimeSlots();
+        // The event has been shifted off the left end.
+        assertTrue(slots.isEmpty());
+    }
+
+    @Test
+    public void testCopyConstructor() {
+        mEventIndex.addEvent(timestamp("01-06 05:26"));
+        mEventIndex.addEvent(timestamp("01-27 18:41"));
+        mEventIndex.addEvent(timestamp("01-30 03:06"));
+        mEventIndex.addEvent(timestamp("01-30 18:14"));
+
+        List<Range<Long>> slots = mEventIndex.getActiveTimeSlots();
+
+        EventIndex newIndex = new EventIndex(mEventIndex);
+        List<Range<Long>> newSlots = newIndex.getActiveTimeSlots();
+
+        assertEquals(slots.size(), newSlots.size());
+        for (int i = 0; i < slots.size(); i++) {
+            assertEquals(slots.get(i), newSlots.get(i));
+        }
+    }
+
+    @Test
+    public void combineEventIndexes() {
+        EventIndex a = new EventIndex(mInjector);
+        mInjector.mCurrentTimeMillis = timestamp("01-27 18:41");
+        a.addEvent(mInjector.mCurrentTimeMillis);
+        mInjector.mCurrentTimeMillis = timestamp("01-30 03:06");
+        a.addEvent(mInjector.mCurrentTimeMillis);
+
+        mInjector.mCurrentTimeMillis = CURRENT_TIMESTAMP;
+        EventIndex b = new EventIndex(mInjector);
+        b.addEvent(timestamp("01-06 05:26"));
+        b.addEvent(timestamp("01-30 18:14"));
+
+        EventIndex combined = EventIndex.combine(a, b);
+        List<Range<Long>> slots = combined.getActiveTimeSlots();
+        assertEquals(4, slots.size());
+        assertTimeSlot(timestamp("01-06 00:00"), timestamp("01-07 00:00"), slots.get(0));
+        assertTimeSlot(timestamp("01-27 16:00"), timestamp("01-27 20:00"), slots.get(1));
+        assertTimeSlot(timestamp("01-30 03:00"), timestamp("01-30 04:00"), slots.get(2));
+        assertTimeSlot(timestamp("01-30 18:14"), timestamp("01-30 18:16"), slots.get(3));
+    }
+
+    private static void assertTimeSlot(
+            long expectedLower, long expectedUpper, Range<Long> actualSlot) {
+        assertEquals(expectedLower, actualSlot.getLower().longValue());
+        assertEquals(expectedUpper, actualSlot.getUpper().longValue());
+    }
+
+    private class TestInjector extends EventIndex.Injector {
+
+        private long mCurrentTimeMillis;
+
+        TestInjector(long currentTimeMillis) {
+            mCurrentTimeMillis = currentTimeMillis;
+        }
+
+        private void moveTimeForwardSeconds(long seconds) {
+            mCurrentTimeMillis += (seconds * 1000L);
+        }
+
+        @Override
+        long currentTimeMillis() {
+            return mCurrentTimeMillis;
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/EventListTest.java b/services/tests/servicestests/src/com/android/server/people/data/EventListTest.java
new file mode 100644
index 0000000..f2f372c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/people/data/EventListTest.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.people.data;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.google.android.collect.Lists;
+import com.google.android.collect.Sets;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.List;
+
+@RunWith(JUnit4.class)
+public final class EventListTest {
+
+    private static final Event E1 = new Event(101L, Event.TYPE_NOTIFICATION_OPENED);
+    private static final Event E2 = new Event(103L, Event.TYPE_NOTIFICATION_OPENED);
+    private static final Event E3 = new Event(107L, Event.TYPE_SHARE_IMAGE);
+    private static final Event E4 = new Event(109L, Event.TYPE_SMS_INCOMING);
+
+    private EventList mEventList;
+
+    @Before
+    public void setUp() {
+        mEventList = new EventList();
+    }
+
+    @Test
+    public void testQueryEmptyEventList() {
+        List<Event> events = mEventList.queryEvents(Event.ALL_EVENT_TYPES, 0L, 999L);
+        assertTrue(events.isEmpty());
+    }
+
+    @Test
+    public void testAddAndQueryEvents() {
+        List<Event> in = Lists.newArrayList(E1, E2, E3, E4);
+        for (Event e : in) {
+            mEventList.add(e);
+        }
+
+        List<Event> out = mEventList.queryEvents(Event.ALL_EVENT_TYPES, 0L, 999L);
+        assertEventListEquals(in, out);
+    }
+
+    @Test
+    public void testAddEventsNotInOrder() {
+        mEventList.add(E3);
+        mEventList.add(E1);
+        mEventList.add(E4);
+        mEventList.add(E2);
+
+        List<Event> out = mEventList.queryEvents(Event.ALL_EVENT_TYPES, 0L, 999L);
+        List<Event> expected = Lists.newArrayList(E1, E2, E3, E4);
+        assertEventListEquals(expected, out);
+    }
+
+    @Test
+    public void testQueryEventsByType() {
+        mEventList.add(E1);
+        mEventList.add(E2);
+        mEventList.add(E3);
+        mEventList.add(E4);
+
+        List<Event> out = mEventList.queryEvents(
+                Sets.newArraySet(Event.TYPE_NOTIFICATION_OPENED), 0L, 999L);
+        assertEventListEquals(Lists.newArrayList(E1, E2), out);
+    }
+
+    @Test
+    public void testQueryEventsByTimeRange() {
+        mEventList.add(E1);
+        mEventList.add(E2);
+        mEventList.add(E3);
+        mEventList.add(E4);
+
+        List<Event> out = mEventList.queryEvents(Event.ALL_EVENT_TYPES, 103L, 109L);
+        // Only E2 and E3 are in the time range [103L, 109L).
+        assertEventListEquals(Lists.newArrayList(E2, E3), out);
+    }
+
+    @Test
+    public void testQueryEventsOutOfRange() {
+        mEventList.add(E1);
+        mEventList.add(E2);
+        mEventList.add(E3);
+        mEventList.add(E4);
+
+        List<Event> out = mEventList.queryEvents(Event.ALL_EVENT_TYPES, 900L, 900L);
+        assertTrue(out.isEmpty());
+    }
+
+    @Test
+    public void testAddDuplicateEvents() {
+        mEventList.add(E1);
+        mEventList.add(E2);
+        mEventList.add(E2);
+        mEventList.add(E3);
+        mEventList.add(E2);
+        mEventList.add(E3);
+        mEventList.add(E3);
+        mEventList.add(E4);
+        mEventList.add(E1);
+        mEventList.add(E3);
+        mEventList.add(E2);
+
+        List<Event> out = mEventList.queryEvents(Event.ALL_EVENT_TYPES, 0L, 999L);
+        List<Event> expected = Lists.newArrayList(E1, E2, E3, E4);
+        assertEventListEquals(expected, out);
+    }
+
+    private static void assertEventListEquals(List<Event> expected, List<Event> actual) {
+        assertEquals(expected.size(), actual.size());
+        for (int i = 0; i < expected.size(); i++) {
+            assertEquals(expected.get(i).getTimestamp(), actual.get(i).getTimestamp());
+            assertEquals(expected.get(i).getType(), actual.get(i).getType());
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/PackageDataTest.java b/services/tests/servicestests/src/com/android/server/people/data/PackageDataTest.java
new file mode 100644
index 0000000..1b80d6f
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/people/data/PackageDataTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.people.data;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.content.LocusId;
+import android.content.pm.ShortcutInfo;
+import android.net.Uri;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.List;
+
+@RunWith(JUnit4.class)
+public final class PackageDataTest {
+
+    private static final String PACKAGE_NAME = "com.google.test";
+    private static final int USER_ID = 0;
+    private static final String SHORTCUT_ID = "abc";
+    private static final LocusId LOCUS_ID = new LocusId("def");
+    private static final Uri CONTACT_URI = Uri.parse("tel:+1234567890");
+    private static final String PHONE_NUMBER = "+1234567890";
+
+    private Event mE1;
+    private Event mE2;
+    private Event mE3;
+    private Event mE4;
+
+    private PackageData mPackageData;
+
+    @Before
+    public void setUp() {
+        mPackageData = new PackageData(PACKAGE_NAME, USER_ID);
+        ConversationInfo conversationInfo = new ConversationInfo.Builder()
+                .setShortcutId(SHORTCUT_ID)
+                .setLocusId(LOCUS_ID)
+                .setContactUri(CONTACT_URI)
+                .setContactPhoneNumber(PHONE_NUMBER)
+                .setShortcutFlags(ShortcutInfo.FLAG_LONG_LIVED)
+                .build();
+        mPackageData.getConversationStore().addOrUpdate(conversationInfo);
+
+        long currentTimestamp = System.currentTimeMillis();
+        mE1 = new Event(currentTimestamp - 800L, Event.TYPE_SHORTCUT_INVOCATION);
+        mE2 = new Event(currentTimestamp - 700L, Event.TYPE_NOTIFICATION_OPENED);
+        mE3 = new Event(currentTimestamp - 600L, Event.TYPE_CALL_INCOMING);
+        mE4 = new Event(currentTimestamp - 500L, Event.TYPE_SMS_OUTGOING);
+    }
+
+    @Test
+    public void testGetEventHistory() {
+        EventStore eventStore = mPackageData.getEventStore();
+        eventStore.getOrCreateShortcutEventHistory(SHORTCUT_ID).addEvent(mE1);
+        eventStore.getOrCreateLocusEventHistory(LOCUS_ID).addEvent(mE2);
+
+        EventHistory eventHistory = mPackageData.getEventHistory(SHORTCUT_ID);
+        List<Event> events = eventHistory.queryEvents(Event.ALL_EVENT_TYPES, 0L, Long.MAX_VALUE);
+        assertEquals(2, events.size());
+        assertEventEquals(mE1, events.get(0));
+        assertEventEquals(mE2, events.get(1));
+    }
+
+    @Test
+    public void testGetEventHistoryDefaultDialerAndSmsApp() {
+        mPackageData.setIsDefaultDialer(true);
+        mPackageData.setIsDefaultSmsApp(true);
+        EventStore eventStore = mPackageData.getEventStore();
+        eventStore.getOrCreateShortcutEventHistory(SHORTCUT_ID).addEvent(mE1);
+        eventStore.getOrCreateCallEventHistory(PHONE_NUMBER).addEvent(mE3);
+        eventStore.getOrCreateSmsEventHistory(PHONE_NUMBER).addEvent(mE4);
+
+        assertTrue(mPackageData.isDefaultDialer());
+        assertTrue(mPackageData.isDefaultSmsApp());
+        EventHistory eventHistory = mPackageData.getEventHistory(SHORTCUT_ID);
+        List<Event> events = eventHistory.queryEvents(Event.ALL_EVENT_TYPES, 0L, Long.MAX_VALUE);
+        assertEquals(3, events.size());
+        assertEventEquals(mE1, events.get(0));
+        assertEventEquals(mE3, events.get(1));
+        assertEventEquals(mE4, events.get(2));
+    }
+
+    @Test
+    public void testGetEventHistoryNotDefaultDialerOrSmsApp() {
+        EventStore eventStore = mPackageData.getEventStore();
+        eventStore.getOrCreateShortcutEventHistory(SHORTCUT_ID).addEvent(mE1);
+        eventStore.getOrCreateCallEventHistory(PHONE_NUMBER).addEvent(mE3);
+        eventStore.getOrCreateSmsEventHistory(PHONE_NUMBER).addEvent(mE4);
+
+        assertFalse(mPackageData.isDefaultDialer());
+        assertFalse(mPackageData.isDefaultSmsApp());
+        EventHistory eventHistory = mPackageData.getEventHistory(SHORTCUT_ID);
+        List<Event> events = eventHistory.queryEvents(Event.ALL_EVENT_TYPES, 0L, Long.MAX_VALUE);
+        assertEquals(1, events.size());
+        assertEventEquals(mE1, events.get(0));
+    }
+
+    private void assertEventEquals(Event expected, Event actual) {
+        assertEquals(expected.getTimestamp(), actual.getTimestamp());
+        assertEquals(expected.getType(), actual.getType());
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/TestUtils.java b/services/tests/servicestests/src/com/android/server/people/data/TestUtils.java
new file mode 100644
index 0000000..41889aa
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/people/data/TestUtils.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.people.data;
+
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+
+final class TestUtils {
+
+    /**
+     * Gets the epoch time in millis for the specified time string.
+     * @param timeString e.g. "01-02 15:20"
+     * @return epoch time in millis
+     */
+    static long timestamp(String timeString) {
+        String str = String.format("2020-%s", timeString);
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
+        return toEpochMilli(LocalDateTime.parse(str, formatter));
+    }
+
+    private static long toEpochMilli(LocalDateTime localDateTime) {
+        return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
+    }
+
+    private TestUtils() {
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
index 7f66f3c..3e3f40d 100644
--- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
@@ -27,6 +27,8 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageParser;
+import android.content.pm.Signature;
 import android.content.pm.parsing.AndroidPackage;
 import android.content.pm.parsing.ComponentParseUtils;
 import android.content.pm.parsing.ComponentParseUtils.ParsedActivity;
@@ -48,8 +50,10 @@
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
+import java.security.cert.CertificateException;
 import java.util.Collections;
 import java.util.Map;
 import java.util.Set;
@@ -284,6 +288,33 @@
         assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
     }
 
+
+    @Test
+    public void testSystemSignedTarget_DoesntFilter() throws CertificateException {
+        final AppsFilter appsFilter =
+                new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+        appsFilter.onSystemReady();
+
+        final Signature frameworkSignature = Mockito.mock(Signature.class);
+        final PackageParser.SigningDetails frameworkSigningDetails =
+                new PackageParser.SigningDetails(new Signature[]{frameworkSignature}, 1);
+
+        final Signature otherSignature = Mockito.mock(Signature.class);
+        final PackageParser.SigningDetails otherSigningDetails =
+                new PackageParser.SigningDetails(new Signature[]{otherSignature}, 1);
+
+        simulateAddPackage(appsFilter, pkg("android"), 1000,
+                b -> b.setSigningDetails(frameworkSigningDetails));
+        PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"),
+                DUMMY_TARGET_UID,
+                b -> b.setSigningDetails(frameworkSigningDetails));
+        PackageSetting calling = simulateAddPackage(appsFilter,
+                pkg("com.some.other.package"), DUMMY_CALLING_UID,
+                b -> b.setSigningDetails(otherSigningDetails));
+
+        assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
+    }
+
     @Test
     public void testForceQueryableByDevice_NonSystemCaller_Filters() {
         final AppsFilter appsFilter =
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
index a8674a8..bfe0c15 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
@@ -156,7 +156,8 @@
         if (isMultiPackage) {
             params.isMultiPackage = true;
         }
-        InstallSource installSource = InstallSource.create("testInstaller", null, "testInstaller");
+        InstallSource installSource = InstallSource.create("testInstallInitiator",
+                "testInstallOriginator", "testInstaller");
         return new PackageInstallerSession(
                 /* callback */ null,
                 /* context */null,
@@ -297,6 +298,8 @@
         assertEquals(expected.userId, actual.userId);
         assertSessionParamsEquivalent(expected.params, actual.params);
         assertEquals(expected.getInstallerUid(), actual.getInstallerUid());
+        assertEquals(expected.getInstallerPackageName(), actual.getInstallerPackageName());
+        assertInstallSourcesEquivalent(expected.getInstallSource(), actual.getInstallSource());
         assertEquals(expected.stageDir.getAbsolutePath(), actual.stageDir.getAbsolutePath());
         assertEquals(expected.stageCid, actual.stageCid);
         assertEquals(expected.isPrepared(), actual.isPrepared());
@@ -316,4 +319,10 @@
         assertEquals(expected.getParentSessionId(), actual.getParentSessionId());
         assertArrayEquals(expected.getChildSessionIds(), actual.getChildSessionIds());
     }
+
+    private void assertInstallSourcesEquivalent(InstallSource expected, InstallSource actual) {
+        assertEquals(expected.installerPackageName, actual.installerPackageName);
+        assertEquals(expected.initiatingPackageName, actual.initiatingPackageName);
+        assertEquals(expected.originatingPackageName, actual.originatingPackageName);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index 8329227..cf51fa3 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -20,6 +20,8 @@
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import static android.content.pm.SuspendDialogInfo.BUTTON_ACTION_MORE_DETAILS;
+import static android.content.pm.SuspendDialogInfo.BUTTON_ACTION_UNSUSPEND;
 import static android.content.res.Resources.ID_NULL;
 
 import static org.hamcrest.CoreMatchers.is;
@@ -217,6 +219,7 @@
         assertThat(params.dialogInfo.getTitleResId(), is(ID_NULL));
         assertThat(params.dialogInfo.getIconResId(), is(TEST_RESOURCE_ID));
         assertThat(params.dialogInfo.getNeutralButtonTextResId(), is(ID_NULL));
+        assertThat(params.dialogInfo.getNeutralButtonAction(), is(BUTTON_ACTION_MORE_DETAILS));
         assertThat(params.dialogInfo.getDialogMessageResId(), is(ID_NULL));
     }
 
@@ -243,12 +246,14 @@
                 .setTitle(0x11220002)
                 .setMessage("1st message")
                 .setNeutralButtonText(0x11220003)
+                .setNeutralButtonAction(BUTTON_ACTION_MORE_DETAILS)
                 .build();
         final SuspendDialogInfo dialogInfo2 = new SuspendDialogInfo.Builder()
                 .setIcon(0x22220001)
                 .setTitle(0x22220002)
                 .setMessage("2nd message")
                 .setNeutralButtonText(0x22220003)
+                .setNeutralButtonAction(BUTTON_ACTION_UNSUSPEND)
                 .build();
 
         ps1.addOrUpdateSuspension("suspendingPackage1", dialogInfo1, appExtras1, launcherExtras1,
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java b/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
index 8441494..338d5fa 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
@@ -16,6 +16,7 @@
 
 package com.android.server.pm;
 
+import android.content.pm.PackageParser;
 import android.content.pm.PackageUserState;
 import android.content.pm.parsing.AndroidPackage;
 import android.util.SparseArray;
@@ -42,6 +43,7 @@
     private AndroidPackage mPkg;
     private int mAppId;
     private InstallSource mInstallSource;
+    private PackageParser.SigningDetails mSigningDetails;
 
     public PackageSettingBuilder setPackage(AndroidPackage pkg) {
         this.mPkg = pkg;
@@ -143,12 +145,21 @@
         return this;
     }
 
+    public PackageSettingBuilder setSigningDetails(
+            PackageParser.SigningDetails signingDetails) {
+        mSigningDetails = signingDetails;
+        return this;
+    }
+
     public PackageSetting build() {
         final PackageSetting packageSetting = new PackageSetting(mName, mRealName,
                 new File(mCodePath), new File(mResourcePath),
                 mLegacyNativeLibraryPathString, mPrimaryCpuAbiString, mSecondaryCpuAbiString,
                 mCpuAbiOverrideString, mPVersionCode, mPkgFlags, mPrivateFlags, mSharedUserId,
                 mUsesStaticLibraries, mUsesStaticLibrariesVersions);
+        packageSetting.signatures = mSigningDetails != null
+                ? new PackageSignatures(mSigningDetails)
+                : new PackageSignatures();
         packageSetting.pkg = mPkg;
         packageSetting.appId = mAppId;
         packageSetting.volumeUuid = this.mVolumeUuid;
diff --git a/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java
index a0efc8a..da5986f7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java
@@ -31,6 +31,7 @@
 import java.io.File;
 import java.util.HashSet;
 import java.util.Set;
+import java.util.concurrent.ExecutorService;
 
 /**
  * Tests for {@link ParallelPackageParser}
@@ -43,7 +44,8 @@
 
     @Before
     public void setUp() {
-        mParser = new TestParallelPackageParser();
+        mParser = new TestParallelPackageParser(new PackageParser(),
+                ParallelPackageParser.makeExecutorService());
     }
 
     @Test(timeout = 1000)
@@ -68,15 +70,14 @@
         }
     }
 
-    class TestParallelPackageParser extends ParallelPackageParser {
+    private class TestParallelPackageParser extends ParallelPackageParser {
 
-        TestParallelPackageParser() {
-            super(null, false, null, null, null);
+        TestParallelPackageParser(PackageParser packageParser, ExecutorService executorService) {
+            super(packageParser, executorService);
         }
 
         @Override
-        protected ParsedPackage parsePackage(PackageParser packageParser, File scanFile,
-                int parseFlags) throws PackageParser.PackageParserException {
+        protected ParsedPackage parsePackage(File scanFile, int parseFlags) {
             // Do not actually parse the package for testing
             return null;
         }
diff --git a/services/tests/servicestests/src/com/android/server/pm/SuspendDialogInfoTest.java b/services/tests/servicestests/src/com/android/server/pm/SuspendDialogInfoTest.java
index 7eccd67..322e448 100644
--- a/services/tests/servicestests/src/com/android/server/pm/SuspendDialogInfoTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/SuspendDialogInfoTest.java
@@ -16,6 +16,9 @@
 
 package com.android.server.pm;
 
+import static android.content.pm.SuspendDialogInfo.BUTTON_ACTION_MORE_DETAILS;
+import static android.content.pm.SuspendDialogInfo.BUTTON_ACTION_UNSUSPEND;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNull;
@@ -39,7 +42,8 @@
                 .setIcon(VALID_TEST_RES_ID_1)
                 .setTitle(VALID_TEST_RES_ID_1)
                 .setMessage(VALID_TEST_RES_ID_1)
-                .setNeutralButtonText(VALID_TEST_RES_ID_1);
+                .setNeutralButtonText(VALID_TEST_RES_ID_1)
+                .setNeutralButtonAction(BUTTON_ACTION_MORE_DETAILS);
     }
 
     @Test
@@ -73,6 +77,25 @@
     }
 
     @Test
+    public void equalsComparesButtonAction() {
+        final SuspendDialogInfo.Builder dialogBuilder1 = createDefaultDialogBuilder();
+        final SuspendDialogInfo.Builder dialogBuilder2 = createDefaultDialogBuilder();
+        assertEquals(dialogBuilder1.build(), dialogBuilder2.build());
+        // Only button action is different
+        dialogBuilder2.setNeutralButtonAction(BUTTON_ACTION_UNSUSPEND);
+        assertNotEquals(dialogBuilder1.build(), dialogBuilder2.build());
+    }
+
+    @Test
+    public void defaultButtonAction() {
+        final SuspendDialogInfo.Builder dialogBuilder = new SuspendDialogInfo.Builder()
+                .setIcon(VALID_TEST_RES_ID_1)
+                .setTitle(VALID_TEST_RES_ID_1)
+                .setMessage(VALID_TEST_RES_ID_1);
+        assertEquals(BUTTON_ACTION_MORE_DETAILS, dialogBuilder.build().getNeutralButtonAction());
+    }
+
+    @Test
     public void equalsComparesMessageIds() {
         final SuspendDialogInfo.Builder dialogBuilder1 = createDefaultDialogBuilder();
         final SuspendDialogInfo.Builder dialogBuilder2 = createDefaultDialogBuilder();
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
index ac27a08..5df8568 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
@@ -153,6 +153,25 @@
         assertTrue(mUserManagerService.isUserOfType(testId, typeName));
     }
 
+    /** Test UserInfo.supportsSwitchTo() for precreated users. */
+    @Test
+    public void testSupportSwitchTo_preCreated() throws Exception {
+        UserInfo userInfo = createUser(100, FLAG_FULL, null);
+        userInfo.preCreated = true;
+        assertFalse("Switching to a precreated user should be disabled",
+                userInfo.supportsSwitchTo());
+
+        userInfo.preCreated = false;
+        assertTrue("Switching to a full, real user should be allowed", userInfo.supportsSwitchTo());
+    }
+
+    /** Test UserInfo.supportsSwitchTo() for profiles. */
+    @Test
+    public void testSupportSwitchTo_profile() throws Exception {
+        UserInfo userInfo = createUser(100, FLAG_PROFILE, null);
+        assertFalse("Switching to a profiles should be disabled", userInfo.supportsSwitchTo());
+    }
+
     /** Tests upgradeIfNecessaryLP (but without locking) for upgrading from version 8 to 9+. */
     @Test
     public void testUpgradeIfNecessaryLP_9() {
diff --git a/services/tests/servicestests/src/com/android/server/power/WakeLockLogTest.java b/services/tests/servicestests/src/com/android/server/power/WakeLockLogTest.java
new file mode 100644
index 0000000..a03ba9c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/power/WakeLockLogTest.java
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.power;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.os.Looper;
+import android.os.PowerManager;
+import android.os.test.TestLooper;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.text.SimpleDateFormat;
+import java.util.TimeZone;
+
+/**
+ * Tests for {@link WakeLockLog}.
+ */
+public class WakeLockLogTest {
+
+    private TestLooper mTestLooper;
+
+    @Before
+    public void setUp() throws Exception {
+        mTestLooper = new TestLooper();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    @Test
+    public void testAddTwoItems() {
+        final int tagDatabaseSize = 128;
+        final int logSize = 20;
+        TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
+        WakeLockLog log = new WakeLockLog(injectorSpy);
+
+        when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
+        log.onWakeLockAcquired("TagPartial", 101,
+                PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE);
+
+        when(injectorSpy.currentTimeMillis()).thenReturn(1150L);
+        log.onWakeLockAcquired("TagFull", 102,
+                PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP);
+
+        assertEquals("Wake Lock Log\n"
+                + "  01-01 00:00:01.000 - 101 - ACQ TagPartial (partial,on-after-release)\n"
+                + "  01-01 00:00:01.150 - 102 - ACQ TagFull (full,acq-causes-wake)\n"
+                + "  -\n"
+                + "  Events: 2, Time-Resets: 0\n"
+                + "  Buffer, Bytes used: 6\n",
+                dispatchAndDump(log, false));
+    }
+
+    @Test
+    public void testAddTwoItemsWithTimeReset() {
+        final int tagDatabaseSize = 128;
+        final int logSize = 20;
+        TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
+        WakeLockLog log = new WakeLockLog(injectorSpy);
+
+        when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
+        log.onWakeLockAcquired("TagPartial", 101, PowerManager.PARTIAL_WAKE_LOCK);
+
+        when(injectorSpy.currentTimeMillis()).thenReturn(1350L);
+        log.onWakeLockAcquired("TagFull", 102, PowerManager.FULL_WAKE_LOCK);
+
+        assertEquals("Wake Lock Log\n"
+                + "  01-01 00:00:01.000 - 101 - ACQ TagPartial (partial)\n"
+                + "  01-01 00:00:01.350 - 102 - ACQ TagFull (full)\n"
+                + "  -\n"
+                + "  Events: 2, Time-Resets: 1\n"
+                + "  Buffer, Bytes used: 15\n",
+                dispatchAndDump(log, false));
+    }
+
+    @Test
+    public void testAddTwoItemsWithTagOverwrite() {
+        final int tagDatabaseSize = 2;
+        final int logSize = 20;
+        TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
+        WakeLockLog log = new WakeLockLog(injectorSpy);
+
+        when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
+        log.onWakeLockAcquired("TagPartial", 101, PowerManager.PARTIAL_WAKE_LOCK);
+
+        when(injectorSpy.currentTimeMillis()).thenReturn(1150L);
+        log.onWakeLockAcquired("TagFull", 102, PowerManager.FULL_WAKE_LOCK);
+
+        assertEquals("Wake Lock Log\n"
+                + "  01-01 00:00:01.000 - --- - ACQ UNKNOWN (partial)\n"
+                + "  01-01 00:00:01.150 - 102 - ACQ TagFull (full)\n"
+                + "  -\n"
+                + "  Events: 2, Time-Resets: 0\n"
+                + "  Buffer, Bytes used: 6\n",
+                dispatchAndDump(log, false));
+    }
+
+    @Test
+    public void testAddFourItemsWithRingBufferOverflow() {
+        final int tagDatabaseSize = 6;
+        final int logSize = 10;
+        TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
+        WakeLockLog log = new WakeLockLog(injectorSpy);
+
+        // This first item will get deleted when ring buffer loops around
+        when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
+        log.onWakeLockAcquired("TagPartial", 101, PowerManager.PARTIAL_WAKE_LOCK);
+
+        when(injectorSpy.currentTimeMillis()).thenReturn(1150L);
+        log.onWakeLockAcquired("TagFull", 102, PowerManager.FULL_WAKE_LOCK);
+        when(injectorSpy.currentTimeMillis()).thenReturn(1151L);
+        log.onWakeLockAcquired("TagThree", 101, PowerManager.PARTIAL_WAKE_LOCK);
+        when(injectorSpy.currentTimeMillis()).thenReturn(1152L);
+        log.onWakeLockAcquired("TagFour", 101, PowerManager.PARTIAL_WAKE_LOCK);
+
+        assertEquals("Wake Lock Log\n"
+                + "  01-01 00:00:01.150 - 102 - ACQ TagFull (full)\n"
+                + "  01-01 00:00:01.151 - 101 - ACQ TagThree (partial)\n"
+                + "  01-01 00:00:01.152 - 101 - ACQ TagFour (partial)\n"
+                + "  -\n"
+                + "  Events: 3, Time-Resets: 0\n"
+                + "  Buffer, Bytes used: 9\n",
+                dispatchAndDump(log, false));
+    }
+
+    @Test
+    public void testAddItemWithBadTag() {
+        final int tagDatabaseSize = 6;
+        final int logSize = 10;
+        TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
+        WakeLockLog log = new WakeLockLog(injectorSpy);
+
+        // Bad tag means it wont get written
+        when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
+        log.onWakeLockAcquired(null /* tag */, 0 /* ownerUid */, PowerManager.PARTIAL_WAKE_LOCK);
+
+        assertEquals("Wake Lock Log\n"
+                + "  -\n"
+                + "  Events: 0, Time-Resets: 0\n"
+                + "  Buffer, Bytes used: 0\n",
+                dispatchAndDump(log, false));
+    }
+
+    @Test
+    public void testAddItemWithReducedTagName() {
+        final int tagDatabaseSize = 6;
+        final int logSize = 10;
+        TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
+        WakeLockLog log = new WakeLockLog(injectorSpy);
+
+        when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
+        log.onWakeLockAcquired("*job*/com.one.two.3hree/.one..Last", 101,
+                PowerManager.PARTIAL_WAKE_LOCK);
+
+        assertEquals("Wake Lock Log\n"
+                + "  01-01 00:00:01.000 - 101 - ACQ *job*/c.o.t.3/.o..Last (partial)\n"
+                + "  -\n"
+                + "  Events: 1, Time-Resets: 0\n"
+                + "  Buffer, Bytes used: 3\n",
+                dispatchAndDump(log, false));
+    }
+
+    @Test
+    public void testAddAcquireAndReleaseWithRepeatTagName() {
+        final int tagDatabaseSize = 6;
+        final int logSize = 10;
+        TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
+        WakeLockLog log = new WakeLockLog(injectorSpy);
+
+        when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
+        log.onWakeLockAcquired("HowdyTag", 101, PowerManager.PARTIAL_WAKE_LOCK);
+        when(injectorSpy.currentTimeMillis()).thenReturn(1001L);
+        log.onWakeLockReleased("HowdyTag", 101);
+
+        assertEquals("Wake Lock Log\n"
+                + "  01-01 00:00:01.000 - 101 - ACQ HowdyTag (partial)\n"
+                + "  01-01 00:00:01.001 - 101 - REL HowdyTag\n"
+                + "  -\n"
+                + "  Events: 2, Time-Resets: 0\n"
+                + "  Buffer, Bytes used: 5\n"
+                + "  Tag Database: size(5), entries: 1, Bytes used: 80\n",
+                dispatchAndDump(log, true));
+    }
+
+    @Test
+    public void testAddAcquireAndReleaseWithTimeTravel() {
+        final int tagDatabaseSize = 6;
+        final int logSize = 10;
+        TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
+        WakeLockLog log = new WakeLockLog(injectorSpy);
+
+        when(injectorSpy.currentTimeMillis()).thenReturn(1100L);
+        log.onWakeLockAcquired("HowdyTag", 101, PowerManager.PARTIAL_WAKE_LOCK);
+
+        // New element goes back in time...should not be written to log.
+        when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
+        log.onWakeLockReleased("HowdyTag", 101);
+
+        assertEquals("Wake Lock Log\n"
+                + "  01-01 00:00:01.100 - 101 - ACQ HowdyTag (partial)\n"
+                + "  -\n"
+                + "  Events: 1, Time-Resets: 0\n"
+                + "  Buffer, Bytes used: 3\n",
+                dispatchAndDump(log, false));
+    }
+
+    private String dispatchAndDump(WakeLockLog log, boolean includeTagDb) {
+        mTestLooper.dispatchAll();
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        log.dump(pw, includeTagDb);
+        return sw.toString();
+    }
+
+    public class TestInjector extends WakeLockLog.Injector {
+        private final int mTagDatabaseSize;
+        private final int mLogSize;
+
+        public TestInjector(int tagDatabaseSize, int logSize) {
+            mTagDatabaseSize = tagDatabaseSize;
+            mLogSize = logSize;
+        }
+
+        @Override
+        public Looper getLooper() {
+            return mTestLooper.getLooper();
+        }
+
+        @Override
+        public int getTagDatabaseSize() {
+            return mTagDatabaseSize;
+        }
+
+        @Override
+        public int getLogSize() {
+            return mLogSize;
+        }
+
+        @Override
+        public SimpleDateFormat getDateFormat() {
+            SimpleDateFormat format = new SimpleDateFormat(super.getDateFormat().toPattern());
+            format.setTimeZone(TimeZone.getTimeZone("UTC"));
+            return format;
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/usage/IntervalStatsTests.java b/services/tests/servicestests/src/com/android/server/usage/IntervalStatsTests.java
index f1b2ef8..5d849c1 100644
--- a/services/tests/servicestests/src/com/android/server/usage/IntervalStatsTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/IntervalStatsTests.java
@@ -92,6 +92,9 @@
                 case UsageEvents.Event.NOTIFICATION_INTERRUPTION:
                     event.mNotificationChannelId = "channel" + (i % 5); //"random" channel
                     break;
+                case UsageEvents.Event.LOCUS_ID_SET:
+                    event.mLocusId = "locus" + (i % 7); //"random" locus
+                    break;
             }
 
             intervalStats.addEvent(event);
diff --git a/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
index e6bb244..f1c3906 100644
--- a/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
+++ b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
@@ -52,6 +52,7 @@
 public class UsageStatsDatabaseTest {
 
     private static final int MAX_TESTED_VERSION = 5;
+    private static final int OLDER_VERSION_MAX_EVENT_TYPE = 29;
     protected Context mContext;
     private UsageStatsDatabase mUsageStatsDatabase;
     private File mTestDir;
@@ -79,7 +80,7 @@
         mUsageStatsDatabase = new UsageStatsDatabase(mTestDir);
         mUsageStatsDatabase.readMappingsLocked();
         mUsageStatsDatabase.init(1);
-        populateIntervalStats();
+        populateIntervalStats(MAX_TESTED_VERSION);
         clearUsageStatsFiles();
     }
 
@@ -117,7 +118,7 @@
         return sb.toString();
     }
 
-    private void populateIntervalStats() {
+    private void populateIntervalStats(int minVersion) {
         final int numberOfEvents = 3000;
         final int timeProgression = 23;
         long time = System.currentTimeMillis() - (numberOfEvents*timeProgression);
@@ -147,9 +148,12 @@
             final int instanceId = i % 11;
             event.mClass = ".fake.class.name" + instanceId;
             event.mTimeStamp = time;
-            event.mEventType = i % (MAX_EVENT_TYPE + 1); //"random" event type
             event.mInstanceId = instanceId;
 
+            int maxEventType = (minVersion < 5) ? OLDER_VERSION_MAX_EVENT_TYPE : MAX_EVENT_TYPE;
+            event.mEventType = i % (maxEventType + 1); //"random" event type
+
+
 
             final int rootPackageInt = (i % 5); // 5 "apps" start each task
             event.mTaskRootPackage = "fake.package.name" + rootPackageInt;
@@ -174,6 +178,9 @@
                     //"random" channel
                     event.mNotificationChannelId = "channel" + (i % 5);
                     break;
+                case Event.LOCUS_ID_SET:
+                    event.mLocusId = "locus" + (i % 7); //"random" locus
+                    break;
             }
 
             mIntervalStats.addEvent(event);
@@ -281,6 +288,10 @@
                         assertEquals(e1.mNotificationChannelIdToken, e2.mNotificationChannelIdToken,
                                 "Usage event " + debugId);
                         break;
+                    case Event.LOCUS_ID_SET:
+                        assertEquals(e1.mLocusIdToken, e2.mLocusIdToken,
+                                "Usage event " + debugId);
+                        break;
                 }
                 // fallthrough
             case 4: // test fields added in version 4
@@ -392,6 +403,7 @@
      * version and read the automatically upgraded files on disk in the new file format.
      */
     void runVersionChangeTest(int oldVersion, int newVersion, int interval) throws IOException {
+        populateIntervalStats(oldVersion);
         // Write IntervalStats to disk in old version format
         UsageStatsDatabase prevDB = new UsageStatsDatabase(mTestDir, oldVersion);
         prevDB.readMappingsLocked();
diff --git a/services/tests/servicestests/src/com/android/server/utils/TraceBufferTest.java b/services/tests/servicestests/src/com/android/server/utils/TraceBufferTest.java
index 09b75e7..0e50f2a 100644
--- a/services/tests/servicestests/src/com/android/server/utils/TraceBufferTest.java
+++ b/services/tests/servicestests/src/com/android/server/utils/TraceBufferTest.java
@@ -30,6 +30,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.util.Preconditions;
+import com.android.internal.util.TraceBuffer;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 587cfbf..651ad40 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -98,6 +98,7 @@
     NotificationUsageStats mUsageStats;
     @Mock
     IAccessibilityManager mAccessibilityService;
+    NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake();
 
     private NotificationManagerService mService;
     private String mPkg = "com.android.server.notification";
@@ -148,7 +149,7 @@
         verify(mAccessibilityService).addClient(any(IAccessibilityManagerClient.class), anyInt());
         assertTrue(accessibilityManager.isEnabled());
 
-        mService = spy(new NotificationManagerService(getContext()));
+        mService = spy(new NotificationManagerService(getContext(), mNotificationRecordLogger));
         mService.setAudioManager(mAudioManager);
         mService.setVibrator(mVibrator);
         mService.setSystemReady(true);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 93e09df..768b472 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -256,6 +256,8 @@
     UserManager mUm;
     @Mock
     NotificationHistoryManager mHistoryManager;
+    NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake();
+
 
     // Use a Testable subclass so we can simulate calls from the system without failing.
     private static class TestableNotificationManagerService extends NotificationManagerService {
@@ -265,8 +267,8 @@
         @Nullable
         NotificationAssistantAccessGrantedCallback mNotificationAssistantAccessGrantedCallback;
 
-        TestableNotificationManagerService(Context context) {
-            super(context);
+        TestableNotificationManagerService(Context context, NotificationRecordLogger logger) {
+            super(context, logger);
         }
 
         @Override
@@ -353,7 +355,7 @@
 
         doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
 
-        mService = new TestableNotificationManagerService(mContext);
+        mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger);
 
         // Use this testable looper.
         mTestableLooper = TestableLooper.get(this);
@@ -1118,6 +1120,61 @@
     }
 
     @Test
+    public void testEnqueueNotificationWithTag_WritesExpectedLog() throws Exception {
+        final String tag = "testEnqueueNotificationWithTag_WritesExpectedLog";
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
+                generateNotificationRecord(null).getNotification(), 0);
+        waitForIdle();
+        assertEquals(1, mNotificationRecordLogger.getCalls().size());
+        NotificationRecordLoggerFake.CallRecord call = mNotificationRecordLogger.get(0);
+        assertTrue(call.shouldLog());
+        assertNotNull(call.r);
+        assertNull(call.old);
+        assertEquals(0, call.position);
+        assertEquals(0, call.buzzBeepBlink);
+        assertEquals(PKG, call.r.sbn.getPackageName());
+        assertEquals(0, call.r.sbn.getId());
+        assertEquals(tag, call.r.sbn.getTag());
+    }
+
+    @Test
+    public void testEnqueueNotificationWithTag_LogsOnMajorUpdates() throws Exception {
+        final String tag = "testEnqueueNotificationWithTag_LogsOnMajorUpdates";
+        Notification original = new Notification.Builder(mContext,
+                mTestNotificationChannel.getId())
+                .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, original, 0);
+        Notification update = new Notification.Builder(mContext,
+                mTestNotificationChannel.getId())
+                .setSmallIcon(android.R.drawable.sym_def_app_icon)
+                .setCategory(Notification.CATEGORY_ALARM).build();
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, update, 0);
+        waitForIdle();
+        assertEquals(2, mNotificationRecordLogger.getCalls().size());
+        assertTrue(mNotificationRecordLogger.get(0).shouldLog());
+        assertEquals(
+                NotificationRecordLogger.NotificationReportedEvents.NOTIFICATION_POSTED,
+                mNotificationRecordLogger.get(0).getUiEvent());
+        assertEquals(
+                NotificationRecordLogger.NotificationReportedEvents.NOTIFICATION_UPDATED,
+                mNotificationRecordLogger.get(1).getUiEvent());
+        assertTrue(mNotificationRecordLogger.get(1).shouldLog());
+    }
+
+    @Test
+    public void testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdates() throws Exception {
+        final String tag = "testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdates";
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
+                generateNotificationRecord(null).getNotification(), 0);
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
+                generateNotificationRecord(null).getNotification(), 0);
+        waitForIdle();
+        assertEquals(2, mNotificationRecordLogger.getCalls().size());
+        assertTrue(mNotificationRecordLogger.get(0).shouldLog());
+        assertFalse(mNotificationRecordLogger.get(1).shouldLog());
+    }
+
+    @Test
     public void testCancelNotificationImmediatelyAfterEnqueue() throws Exception {
         mBinderService.enqueueNotificationWithTag(PKG, PKG,
                 "testCancelNotificationImmediatelyAfterEnqueue", 0,
@@ -2252,7 +2309,7 @@
 
     @Test
     public void testHasCompanionDevice_noService() {
-        mService = new TestableNotificationManagerService(mContext);
+        mService = new TestableNotificationManagerService(mContext,  mNotificationRecordLogger);
 
         assertFalse(mService.hasCompanionDevice(mListener));
     }
@@ -5381,6 +5438,46 @@
     }
 
     @Test
+    public void testOnBubbleNotificationSuppressionChanged() throws Exception {
+        // Bubble notification
+        NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, "tag");
+
+        // Bubbles are allowed!
+        setUpPrefsForBubbles(PKG, nr.sbn.getUserId(), true /* global */,
+                true /* app */, true /* channel */);
+
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
+                nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
+        waitForIdle();
+
+        // NOT suppressed
+        Notification n =  mBinderService.getActiveNotifications(PKG)[0].getNotification();
+        assertFalse(n.getBubbleMetadata().isNotificationSuppressed());
+
+        // Reset as this is called when the notif is first sent
+        reset(mListeners);
+
+        // Test: update suppression to true
+        mService.mNotificationDelegate.onBubbleNotificationSuppressionChanged(nr.getKey(), true);
+        waitForIdle();
+
+        // Check
+        n =  mBinderService.getActiveNotifications(PKG)[0].getNotification();
+        assertTrue(n.getBubbleMetadata().isNotificationSuppressed());
+
+        // Reset to check again
+        reset(mListeners);
+
+        // Test: update suppression to false
+        mService.mNotificationDelegate.onBubbleNotificationSuppressionChanged(nr.getKey(), false);
+        waitForIdle();
+
+        // Check
+        n = mBinderService.getActiveNotifications(PKG)[0].getNotification();
+        assertFalse(n.getBubbleMetadata().isNotificationSuppressed());
+    }
+
+    @Test
     public void testGrantInlineReplyUriPermission_recordExists() throws Exception {
         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerFake.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerFake.java
new file mode 100644
index 0000000..11972fd6
--- /dev/null
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerFake.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.notification;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Fake implementation of NotificationRecordLogger, for testing.
+ */
+class NotificationRecordLoggerFake implements NotificationRecordLogger {
+    class CallRecord extends NotificationRecordPair {
+        public int position, buzzBeepBlink;
+        CallRecord(NotificationRecord r, NotificationRecord old, int position,
+                int buzzBeepBlink) {
+            super(r, old);
+            this.position = position;
+            this.buzzBeepBlink = buzzBeepBlink;
+        }
+        boolean shouldLog() {
+            return shouldLog(buzzBeepBlink);
+        }
+    }
+    List<CallRecord> mCalls = new ArrayList<CallRecord>();
+
+    List<CallRecord> getCalls() {
+        return mCalls;
+    }
+
+    CallRecord get(int index) {
+        return mCalls.get(index);
+    }
+
+    @Override
+    public void logNotificationReported(NotificationRecord r, NotificationRecord old,
+            int position, int buzzBeepBlink) {
+        mCalls.add(new CallRecord(r, old, position, buzzBeepBlink));
+    }
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
index c828f02..e18c891 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
@@ -18,7 +18,6 @@
 
 import static android.app.role.RoleManager.ROLE_DIALER;
 import static android.app.role.RoleManager.ROLE_EMERGENCY;
-import static android.app.role.RoleManager.ROLE_SMS;
 import static android.content.pm.PackageManager.MATCH_ALL;
 
 import static junit.framework.Assert.assertFalse;
@@ -92,24 +91,20 @@
     private Executor mExecutor;
     @Mock
     private RoleManager mRoleManager;
+    NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake();
 
     private List<UserInfo> mUsers;
 
     private static class TestableNotificationManagerService extends NotificationManagerService {
-
-        TestableNotificationManagerService(Context context) {
-            super(context);
+        TestableNotificationManagerService(Context context, NotificationRecordLogger logger) {
+            super(context, logger);
         }
 
         @Override
-        protected void handleSavePolicyFile() {
-            return;
-        }
+        protected void handleSavePolicyFile() { }
 
         @Override
-        protected void loadPolicyFile() {
-            return;
-        }
+        protected void loadPolicyFile() { }
     }
 
     @Before
@@ -125,7 +120,7 @@
         mUsers.add(new UserInfo(10, "second", 0));
         when(mUm.getUsers()).thenReturn(mUsers);
 
-        mService = new TestableNotificationManagerService(mContext);
+        mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger);
         mRoleObserver = mService.new RoleObserver(mRoleManager, mPm, mExecutor);
 
         try {
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
index 135d005..399cf49 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
@@ -16,7 +16,6 @@
 
 package com.android.server.wm;
 
-import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
 import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
@@ -45,7 +44,6 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.internal.app.BlockedAppActivity;
 import com.android.internal.app.HarmfulAppWarningActivity;
 import com.android.internal.app.SuspendedAppActivity;
 import com.android.internal.app.UnlaunchableAppActivity;
@@ -107,8 +105,6 @@
     private PackageManagerService mPackageManager;
     @Mock
     private ActivityManagerInternal mAmInternal;
-    @Mock
-    private LockTaskController mLockTaskController;
 
     private ActivityStartInterceptor mInterceptor;
     private ActivityInfo mAInfo = new ActivityInfo();
@@ -149,13 +145,6 @@
         when(mPackageManager.getHarmfulAppWarning(TEST_PACKAGE_NAME, TEST_USER_ID))
                 .thenReturn(null);
 
-        // Mock LockTaskController
-        mAInfo.lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_DEFAULT;
-        when(mService.getLockTaskController()).thenReturn(mLockTaskController);
-        when(mLockTaskController.isActivityAllowed(
-                TEST_USER_ID, TEST_PACKAGE_NAME, LOCK_TASK_LAUNCH_MODE_DEFAULT))
-                .thenReturn(true);
-
         // Initialise activity info
         mAInfo.applicationInfo = new ApplicationInfo();
         mAInfo.packageName = mAInfo.applicationInfo.packageName = TEST_PACKAGE_NAME;
@@ -207,18 +196,6 @@
     }
 
     @Test
-    public void testInterceptLockTaskModeViolationPackage() {
-        when(mLockTaskController.isActivityAllowed(
-                TEST_USER_ID, TEST_PACKAGE_NAME, LOCK_TASK_LAUNCH_MODE_DEFAULT))
-                .thenReturn(false);
-
-        assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null));
-
-        assertTrue(BlockedAppActivity.createIntent(TEST_USER_ID, TEST_PACKAGE_NAME)
-                .filterEquals(mInterceptor.mIntent));
-    }
-
-    @Test
     public void testInterceptQuietProfile() {
         // GIVEN that the user the activity is starting as is currently in quiet mode
         when(mUserManager.isQuietModeEnabled(eq(UserHandle.of(TEST_USER_ID)))).thenReturn(true);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 0fc2bc5..bab877e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -1008,4 +1008,18 @@
                 .setOutActivity(outActivity).execute();
         assertThat(outActivity[0].inSplitScreenSecondaryWindowingMode()).isTrue();
     }
+
+    @Test
+    public void testActivityStart_expectAddedToRecentTask() {
+        RecentTasks recentTasks = mock(RecentTasks.class);
+        mService.mStackSupervisor.setRecentTasks(recentTasks);
+        doReturn(true).when(recentTasks).isCallerRecents(anyInt());
+
+        final ActivityStarter starter = prepareStarter(0 /* flags */);
+
+        starter.setReason("testAddToTaskListOnActivityStart")
+                .execute();
+
+        verify(recentTasks, times(1)).add(any());
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
index 75ec53d..039ff60 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
@@ -29,9 +29,6 @@
 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD;
 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NONE;
 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS;
-import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
-import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
-import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
 import static android.os.Process.SYSTEM_UID;
 import static android.telecom.TelecomManager.EMERGENCY_DIALER_COMPONENT;
 
@@ -696,38 +693,6 @@
         assertTrue((StatusBarManager.DISABLE2_QUICK_SETTINGS & flags.second) != 0);
     }
 
-    @Test
-    public void testIsActivityAllowed() {
-        // WHEN lock task mode is not enabled
-        assertTrue(mLockTaskController.isActivityAllowed(
-                TEST_USER_ID, TEST_PACKAGE_NAME, LOCK_TASK_LAUNCH_MODE_DEFAULT));
-
-        // WHEN lock task mode is enabled
-        Task tr = getTask(Task.LOCK_TASK_AUTH_WHITELISTED);
-        mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
-
-
-        // package with LOCK_TASK_LAUNCH_MODE_ALWAYS should always be allowed
-        assertTrue(mLockTaskController.isActivityAllowed(
-                TEST_USER_ID, TEST_PACKAGE_NAME, LOCK_TASK_LAUNCH_MODE_ALWAYS));
-
-        // unwhitelisted package should not be allowed
-        assertFalse(mLockTaskController.isActivityAllowed(
-                TEST_USER_ID, TEST_PACKAGE_NAME, LOCK_TASK_LAUNCH_MODE_DEFAULT));
-
-        // update the whitelist
-        String[] whitelist = new String[] { TEST_PACKAGE_NAME };
-        mLockTaskController.updateLockTaskPackages(TEST_USER_ID, whitelist);
-
-        // whitelisted package should be allowed
-        assertTrue(mLockTaskController.isActivityAllowed(
-                TEST_USER_ID, TEST_PACKAGE_NAME, LOCK_TASK_LAUNCH_MODE_DEFAULT));
-
-        // package with LOCK_TASK_LAUNCH_MODE_NEVER should never be allowed
-        assertFalse(mLockTaskController.isActivityAllowed(
-                TEST_USER_ID, TEST_PACKAGE_NAME, LOCK_TASK_LAUNCH_MODE_NEVER));
-    }
-
     private Task getTask(int lockTaskAuth) {
         return getTask(TEST_PACKAGE_NAME, lockTaskAuth);
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index b5e7dd5..a672a95 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -39,6 +39,8 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -83,6 +85,7 @@
 import java.util.List;
 import java.util.Random;
 import java.util.Set;
+import java.util.function.Function;
 
 /**
  * Build/Install/Run:
@@ -419,6 +422,36 @@
     }
 
     @Test
+    public void testAddTasksHomeClearUntrackedTasks_expectFinish() {
+        // There may be multiple tasks with the same base intent by flags (FLAG_ACTIVITY_NEW_TASK |
+        // FLAG_ACTIVITY_MULTIPLE_TASK). If the previous task is still active, it should be removed
+        // because user may not be able to return to the task.
+        final String className = ".PermissionsReview";
+        final Function<Boolean, Task> taskBuilder = visible -> {
+            final Task task = createTaskBuilder(className).build();
+            // Make the task non-empty.
+            final ActivityRecord r = new ActivityBuilder(mService).setTask(task).build();
+            r.setVisibility(visible);
+            return task;
+        };
+
+        final Task task1 = taskBuilder.apply(false /* visible */);
+        mRecentTasks.add(task1);
+        final Task task2 = taskBuilder.apply(true /* visible */);
+        mRecentTasks.add(task2);
+        // Only the last task is kept in recents and the previous 2 tasks will becomes untracked
+        // tasks because their intents are identical.
+        mRecentTasks.add(createTaskBuilder(className).build());
+        // Go home to trigger the removal of untracked tasks.
+        mRecentTasks.add(createTaskBuilder(".Home").setStack(mDisplay.getRootHomeTask()).build());
+
+        // All activities in the invisible task should be finishing or removed.
+        assertNull(task1.getTopNonFinishingActivity());
+        // The visible task should not be affected.
+        assertNotNull(task2.getTopNonFinishingActivity());
+    }
+
+    @Test
     public void testUsersTasks() {
         mRecentTasks.setOnlyTestVisibleRange();
         mRecentTasks.unloadUserDataFromMemoryLocked(TEST_USER_0_ID);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
index 8d2da1e..c9fd79f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
@@ -80,7 +80,6 @@
 
         task.setTaskOrganizer(organizer);
         verify(organizer).taskAppeared(any(), any());
-        assertTrue(task.isControlledByTaskOrganizer());
 
         task.removeImmediately();
         verify(organizer).taskVanished(any());
@@ -106,48 +105,13 @@
         final Task task = createTaskInStack(stack, 0 /* userId */);
         final ITaskOrganizer organizer = makeAndRegisterMockOrganizer();
 
-        task.setTaskOrganizer(organizer);
+        stack.setTaskOrganizer(organizer);
         verify(organizer).taskAppeared(any(), any());
-        assertTrue(task.isControlledByTaskOrganizer());
+        assertTrue(stack.isControlledByTaskOrganizer());
 
-        task.setTaskOrganizer(null);
+        stack.setTaskOrganizer(null);
         verify(organizer).taskVanished(any());
-        assertFalse(task.isControlledByTaskOrganizer());
-    }
-
-    @Test
-    public void testTransferStackToOrganizer() throws RemoteException {
-        final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
-        final Task task = createTaskInStack(stack, 0 /* userId */);
-        final Task task2 = createTaskInStack(stack, 0 /* userId */);
-        final ITaskOrganizer organizer = makeAndRegisterMockOrganizer();
-
-        stack.transferToTaskOrganizer(organizer);
-
-        verify(organizer, times(2)).taskAppeared(any(), any());
-        assertTrue(task.isControlledByTaskOrganizer());
-        assertTrue(task2.isControlledByTaskOrganizer());
-
-        stack.transferToTaskOrganizer(null);
-
-        verify(organizer, times(2)).taskVanished(any());
-        assertFalse(task.isControlledByTaskOrganizer());
-        assertFalse(task2.isControlledByTaskOrganizer());
-    }
-
-    @Test
-    public void testRegisterTaskOrganizerTaskWindowingModeChanges() throws RemoteException {
-        final ITaskOrganizer organizer = makeAndRegisterMockOrganizer();
-
-        final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
-        final Task task = createTaskInStack(stack, 0 /* userId */);
-        task.setWindowingMode(WINDOWING_MODE_PINNED);
-        verify(organizer).taskAppeared(any(), any());
-        assertTrue(task.isControlledByTaskOrganizer());
-
-        task.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
-        verify(organizer).taskVanished(any());
-        assertFalse(task.isControlledByTaskOrganizer());
+        assertFalse(stack.isControlledByTaskOrganizer());
     }
 
     @Test
@@ -158,13 +122,9 @@
         final Task task = createTaskInStack(stack, 0 /* userId */);
         final Task task2 = createTaskInStack(stack, 0 /* userId */);
         stack.setWindowingMode(WINDOWING_MODE_PINNED);
-        verify(organizer, times(2)).taskAppeared(any(), any());
-        assertTrue(task.isControlledByTaskOrganizer());
-        assertTrue(task2.isControlledByTaskOrganizer());
+        verify(organizer, times(1)).taskAppeared(any(), any());
 
         stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
-        verify(organizer, times(2)).taskVanished(any());
-        assertFalse(task.isControlledByTaskOrganizer());
-        assertFalse(task2.isControlledByTaskOrganizer());
+        verify(organizer, times(1)).taskVanished(any());
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
index eb8eb98..d738304 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
@@ -31,6 +31,7 @@
 import android.os.SystemClock;
 import android.platform.test.annotations.Presubmit;
 import android.util.ArraySet;
+import android.view.Surface;
 import android.view.View;
 
 import androidx.test.filters.MediumTest;
@@ -47,7 +48,7 @@
  * Test class for {@link TaskSnapshotPersister} and {@link TaskSnapshotLoader}
  *
  * Build/Install/Run:
- *  atest WmTests:TaskSnapshotPersisterLoaderTest
+ *  atest TaskSnapshotPersisterLoaderTest
  */
 @MediumTest
 @Presubmit
@@ -316,4 +317,18 @@
                 new File(FILES_DIR.getPath() + "/snapshots/2_reduced.jpg")};
         assertTrueForFiles(existsFiles, File::exists, " must exist");
     }
+
+    @Test
+    public void testRotationPersistAndLoadSnapshot() {
+        TaskSnapshot a = new TaskSnapshotBuilder()
+                .setRotation(Surface.ROTATION_270)
+                .build();
+        mPersister.persistSnapshot(1 , mTestUserId, createSnapshot());
+        mPersister.persistSnapshot(2 , mTestUserId, a);
+        mPersister.waitForQueueEmpty();
+        final TaskSnapshot snapshotA = mLoader.loadTask(1, mTestUserId, false /* reduced */);
+        final TaskSnapshot snapshotB = mLoader.loadTask(2, mTestUserId, false /* reduced */);
+        assertEquals(Surface.ROTATION_0, snapshotA.getRotation());
+        assertEquals(Surface.ROTATION_270, snapshotB.getRotation());
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
index f749622..f86c9e6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
@@ -32,6 +32,7 @@
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.os.UserManager;
+import android.view.Surface;
 
 import org.junit.After;
 import org.junit.Before;
@@ -93,6 +94,7 @@
         private boolean mIsTranslucent = false;
         private int mWindowingMode = WINDOWING_MODE_FULLSCREEN;
         private int mSystemUiVisibility = 0;
+        private int mRotation = Surface.ROTATION_0;
 
         TaskSnapshotBuilder setScale(float scale) {
             mScale = scale;
@@ -124,6 +126,11 @@
             return this;
         }
 
+        TaskSnapshotBuilder setRotation(int rotation) {
+            mRotation = rotation;
+            return this;
+        }
+
         TaskSnapshot build() {
             final GraphicBuffer buffer = GraphicBuffer.create(100, 100, PixelFormat.RGBA_8888,
                     USAGE_HW_TEXTURE | USAGE_SW_READ_RARELY | USAGE_SW_READ_RARELY);
@@ -131,7 +138,8 @@
             c.drawColor(Color.RED);
             buffer.unlockCanvasAndPost(c);
             return new TaskSnapshot(MOCK_SNAPSHOT_ID, new ComponentName("", ""), buffer,
-                    ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT, TEST_INSETS,
+                    ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT,
+                    mRotation, TEST_INSETS,
                     mReducedResolution, mScale, mIsRealSnapshot,
                     mWindowingMode, mSystemUiVisibility, mIsTranslucent);
         }
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
index ed87f3a..bb0e5ae 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
@@ -40,6 +40,7 @@
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
+import android.view.Surface;
 import android.view.SurfaceControl;
 
 import androidx.test.filters.SmallTest;
@@ -69,7 +70,8 @@
         final TaskSnapshot snapshot = new TaskSnapshot(
                 System.currentTimeMillis(),
                 new ComponentName("", ""), buffer,
-                ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT, contentInsets, false,
+                ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT,
+                Surface.ROTATION_0, contentInsets, false,
                 1.0f, true /* isRealSnapshot */, WINDOWING_MODE_FULLSCREEN,
                 0 /* systemUiVisibility */, false /* isTranslucent */);
         mSurface = new TaskSnapshotSurface(mWm, new Window(), new SurfaceControl(), snapshot, "Test",
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 9f45044..3a68924 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -406,10 +406,6 @@
     }
 
     @Override
-    public void requestUserActivityNotification() {
-    }
-
-    @Override
     public boolean setAodShowing(boolean aodShowing) {
         return false;
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 5cf9c44..186ff6b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -323,11 +323,18 @@
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
         final WindowState first = createWindow(null, TYPE_APPLICATION, activity, "first");
         final WindowState second = createWindow(null, TYPE_APPLICATION, activity, "second");
-        second.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
 
         testPrepareWindowToDisplayDuringRelayout(first, false /* expectedWakeupCalled */,
                 true /* expectedCurrentLaunchCanTurnScreenOn */);
-        testPrepareWindowToDisplayDuringRelayout(second, true /* expectedWakeupCalled */,
+        testPrepareWindowToDisplayDuringRelayout(second, false /* expectedWakeupCalled */,
+                true /* expectedCurrentLaunchCanTurnScreenOn */);
+
+        // Call prepareWindowToDisplayDuringRelayout for two windows from the same activity, one of
+        // which has FLAG_TURN_SCREEN_ON. The first processed one should trigger the wakeup.
+        second.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
+        testPrepareWindowToDisplayDuringRelayout(first, true /* expectedWakeupCalled */,
+                false /* expectedCurrentLaunchCanTurnScreenOn */);
+        testPrepareWindowToDisplayDuringRelayout(second, false /* expectedWakeupCalled */,
                 false /* expectedCurrentLaunchCanTurnScreenOn */);
 
         // Call prepareWindowToDisplayDuringRelayout for two window that have FLAG_TURN_SCREEN_ON
diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java
index 8fb283a..8fadf5e 100644
--- a/services/usage/java/com/android/server/usage/IntervalStats.java
+++ b/services/usage/java/com/android/server/usage/IntervalStats.java
@@ -28,6 +28,7 @@
 import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_STOP;
 import static android.app.usage.UsageEvents.Event.KEYGUARD_HIDDEN;
 import static android.app.usage.UsageEvents.Event.KEYGUARD_SHOWN;
+import static android.app.usage.UsageEvents.Event.LOCUS_ID_SET;
 import static android.app.usage.UsageEvents.Event.NOTIFICATION_INTERRUPTION;
 import static android.app.usage.UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE;
 import static android.app.usage.UsageEvents.Event.SCREEN_INTERACTIVE;
@@ -568,6 +569,16 @@
                         continue;
                     }
                     break;
+                case LOCUS_ID_SET:
+                    event.mLocusId = packagesTokenData.getString(packageToken, event.mLocusIdToken);
+                    if (event.mLocusId == null) {
+                        Slog.e(TAG, "Unable to parse locus " + event.mLocusIdToken
+                                + " for package " + packageToken);
+                        this.events.remove(i);
+                        dataOmitted = true;
+                        continue;
+                    }
+                    break;
             }
         }
         return dataOmitted;
@@ -675,6 +686,12 @@
                                 packageToken, event.mPackage, event.mNotificationChannelId);
                     }
                     break;
+                case LOCUS_ID_SET:
+                    if (!TextUtils.isEmpty(event.mLocusId)) {
+                        event.mLocusIdToken = packagesTokenData.getTokenOrAdd(packageToken,
+                                event.mPackage, event.mLocusId);
+                    }
+                    break;
             }
         }
     }
diff --git a/services/usage/java/com/android/server/usage/UsageStatsProtoV2.java b/services/usage/java/com/android/server/usage/UsageStatsProtoV2.java
index fe5da92..e4aa9fe 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsProtoV2.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsProtoV2.java
@@ -277,6 +277,10 @@
                     event.mTaskRootClassToken = proto.readInt(
                             EventObfuscatedProto.TASK_ROOT_CLASS_TOKEN) - 1;
                     break;
+                case (int) EventObfuscatedProto.LOCUS_ID_TOKEN:
+                    event.mLocusIdToken = proto.readInt(
+                            EventObfuscatedProto.LOCUS_ID_TOKEN) - 1;
+                    break;
                 case ProtoInputStream.NO_MORE_FIELDS:
                     // timeStamp was not read, assume default value 0 plus beginTime
                     if (event.mTimeStamp == 0) {
@@ -398,6 +402,11 @@
                     proto.write(EventObfuscatedProto.SHORTCUT_ID_TOKEN, event.mShortcutIdToken + 1);
                 }
                 break;
+            case UsageEvents.Event.LOCUS_ID_SET:
+                if (event.mLocusIdToken != PackagesTokenData.UNASSIGNED_TOKEN) {
+                    proto.write(EventObfuscatedProto.LOCUS_ID_TOKEN, event.mLocusIdToken + 1);
+                }
+                break;
             case UsageEvents.Event.NOTIFICATION_INTERRUPTION:
                 if (event.mNotificationChannelIdToken != PackagesTokenData.UNASSIGNED_TOKEN) {
                     proto.write(EventObfuscatedProto.NOTIFICATION_CHANNEL_ID_TOKEN,
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index b8cd378..9a18f8c 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -21,6 +21,7 @@
 import static android.app.usage.UsageEvents.Event.DEVICE_EVENT_PACKAGE_NAME;
 import static android.app.usage.UsageEvents.Event.DEVICE_SHUTDOWN;
 import static android.app.usage.UsageEvents.Event.FLUSH_TO_DISK;
+import static android.app.usage.UsageEvents.Event.LOCUS_ID_SET;
 import static android.app.usage.UsageEvents.Event.NOTIFICATION_INTERRUPTION;
 import static android.app.usage.UsageEvents.Event.SHORTCUT_INVOCATION;
 import static android.app.usage.UsageEvents.Event.USER_STOPPED;
@@ -30,6 +31,8 @@
 
 import android.Manifest;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
 import android.app.IUidObserver;
@@ -52,6 +55,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.LocusId;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
@@ -369,7 +373,7 @@
     /**
      * Fetches a map (package_name:install_time) of installed packages for the given user. This
      * map contains all installed packages, including those packages which have been uninstalled
-     * with the DONT_DELETE_DATA flag.
+     * with the DELETE_KEEP_DATA flag.
      * This is a helper method which should only be called when the given user's usage stats service
      * is initialized; it performs a heavy query to package manager so do not call it otherwise.
      * <br/>
@@ -1987,6 +1991,17 @@
         }
 
         @Override
+        public void reportLocusUpdate(@NonNull ComponentName activity, @UserIdInt int userId,
+                @Nullable LocusId locusId, @NonNull  IBinder appToken) {
+            Event event = new Event(LOCUS_ID_SET, SystemClock.elapsedRealtime());
+            event.mLocusId = locusId.getId();
+            event.mPackage = activity.getPackageName();
+            event.mClass = activity.getClassName();
+            event.mInstanceId = appToken.hashCode();
+            reportEventOrAddToQueue(userId, event);
+        }
+
+        @Override
         public void reportContentProviderUsage(String name, String packageName, int userId) {
             mAppStandby.postReportContentProviderUsage(name, packageName, userId);
         }
diff --git a/services/usb/java/com/android/server/usb/UsbPermissionManager.java b/services/usb/java/com/android/server/usb/UsbPermissionManager.java
index 1e46f98..5d3ed4f 100644
--- a/services/usb/java/com/android/server/usb/UsbPermissionManager.java
+++ b/services/usb/java/com/android/server/usb/UsbPermissionManager.java
@@ -58,8 +58,8 @@
         synchronized (mPermissionsByUser) {
             UsbUserPermissionManager permissions = mPermissionsByUser.get(userId);
             if (permissions == null) {
-                permissions = new UsbUserPermissionManager(mContext, UserHandle.of(userId),
-                        mUsbService.getSettingsForUser(userId));
+                permissions = new UsbUserPermissionManager(mContext.createContextAsUser(
+                        UserHandle.of(userId), 0), mUsbService.getSettingsForUser(userId));
                 mPermissionsByUser.put(userId, permissions);
             }
             return permissions;
diff --git a/services/usb/java/com/android/server/usb/UsbUserPermissionManager.java b/services/usb/java/com/android/server/usb/UsbUserPermissionManager.java
index 2a94393..333edfd9 100644
--- a/services/usb/java/com/android/server/usb/UsbUserPermissionManager.java
+++ b/services/usb/java/com/android/server/usb/UsbUserPermissionManager.java
@@ -109,16 +109,16 @@
     @GuardedBy("mLock")
     private boolean mIsCopyPermissionsScheduled;
 
-    UsbUserPermissionManager(@NonNull Context context, @NonNull UserHandle user,
+    UsbUserPermissionManager(@NonNull Context context,
             @NonNull UsbUserSettingsManager usbUserSettingsManager) {
         mContext = context;
-        mUser = user;
+        mUser = context.getUser();
         mUsbUserSettingsManager = usbUserSettingsManager;
         mDisablePermissionDialogs = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_disableUsbPermissionDialogs);
 
         mPermissionsFile = new AtomicFile(new File(
-                Environment.getUserSystemDirectory(user.getIdentifier()),
+                Environment.getUserSystemDirectory(mUser.getIdentifier()),
                 "usb_permissions.xml"), "usb-permissions");
 
         synchronized (mLock) {
diff --git a/startop/scripts/app_startup/metrics/com.google.android.GoogleCamera b/startop/scripts/app_startup/metrics/com.google.android.GoogleCamera
deleted file mode 100755
index d95fa32..0000000
--- a/startop/scripts/app_startup/metrics/com.google.android.GoogleCamera
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2019, The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# 05-06 14:51:17.688 29691 29897 I CAM_Timing: CameraActivity: START -> ACTIVITY_FIRST_PREVIEW_FRAME_RECEIVED: 385ms
-pattern="CAM_Timing: CameraActivity: START -> ACTIVITY_FIRST_PREVIEW_FRAME_RECEIVED:"
-re_pattern='.*ACTIVITY_FIRST_PREVIEW_FRAME_RECEIVED: \([[:digit:]]\+\)ms'
-parse_metric_from_logcat "ACTIVITY_FIRST_PREVIEW_FRAME_RECEIVED_ms" "$pattern" "$re_pattern"
-
-# 05-06 14:51:17.724 29691 29691 I CAM_Timing: CameraActivity: START -> ACTIVITY_FIRST_PREVIEW_FRAME_RENDERED: 421ms
-pattern="CAM_Timing: CameraActivity: START -> ACTIVITY_FIRST_PREVIEW_FRAME_RENDERED:"
-re_pattern='.*ACTIVITY_FIRST_PREVIEW_FRAME_RENDERED: \([[:digit:]]\+\)ms'
-parse_metric_from_logcat "ACTIVITY_FIRST_PREVIEW_FRAME_RENDERED_ms" "$pattern" "$re_pattern"
diff --git a/startop/scripts/app_startup/parse_metrics b/startop/scripts/app_startup/parse_metrics
index c6bf08e..036609f 100755
--- a/startop/scripts/app_startup/parse_metrics
+++ b/startop/scripts/app_startup/parse_metrics
@@ -50,7 +50,7 @@
 
 package=""
 activity=""
-timeout=10
+timeout=5
 simulate="n"
 parse_arguments() {
   while [[ $# -gt 0 ]]; do
@@ -123,6 +123,9 @@
   local pattern="$2"
   local re_pattern="$3"
   local retcode
+  local result
+  local sec
+  local ms
 
   # parse logcat for 'Displayed...' and that other one...
 
@@ -137,14 +140,28 @@
     return 0
   fi
 
-  logcat_extract_pattern "$timeout" "$timestamp" "$pattern" "$re_pattern"
+  result="$(logcat_extract_pattern "$timeout" "$timestamp" "$pattern" "$re_pattern")"
   retcode=$?
 
   if [[ $retcode -ne 0 ]]; then
     # Timed out before finding the pattern. Could also mean the pattern is wrong.
+    echo "Parse $re_pattern from logcat TIMED OUT after $timeout seconds." >&2
     echo "-$?"
+    return $retcode
   fi
 
+  # "10s123ms" -> "10s123"
+  result=${result/ms/}
+  if [[ $result =~ s ]]; then
+    ms=${result/*s/}
+    sec=${result/s*/}
+  else
+    sec=0
+    ms=$result
+  fi
+  ((result=sec*1000+ms))
+
+  echo "$result"
   return $retcode
 }
 
@@ -169,10 +186,17 @@
 
 # 05-06 14:34:08.854 29460 29481 I ActivityTaskManager: Displayed com.google.android.dialer/.extensions.GoogleDialtactsActivity: +361ms
 pattern="ActivityTaskManager: Displayed ${package}"
-re_pattern='.*Displayed[[:blank:]]\+'"${package}"'[/][^[:blank:]]\+[[:blank:]]+\([[:digit:]]\+\).*'
+re_pattern='.*Displayed[[:blank:]]\+'"${package}"'[/][^[:blank:]]\+[[:blank:]]+\([[:digit:]]\+ms\|[[:digit:]]\+s[[:digit:]]\+ms\).*'
 
 parse_metric_from_logcat "Displayed_ms" "$pattern" "$re_pattern"
 
+# 01-16 17:31:44.550 11172 11204 I ActivityTaskManager: Fully drawn com.google.android.GoogleCamera/com.android.camera.CameraLauncher: +10s897ms
+pattern="ActivityTaskManager: Fully drawn ${package}"
+#re_pattern='.*Fully drawn[[:blank:]]\+'"${package}"'[/][^[:blank:]]\+[[:blank:]]+\([[:digit:]]\+\).*'
+re_pattern='.*Fully drawn[[:blank:]]\+'"${package}"'[/][^[:blank:]]\+[[:blank:]]+\([[:digit:]]\+ms\|[[:digit:]]\+s[[:digit:]]\+ms\).*'
+
+parse_metric_from_logcat "Fully_drawn_ms" "$pattern" "$re_pattern"
+
 # also call into package-specific scripts if there are additional metrics
 if [[ -x "$DIR/metrics/$package" ]]; then
   source "$DIR/metrics/$package" "$timestamp"
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index acf51f3..f54f8d1 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -265,6 +265,29 @@
     public static final String EVENT_HANDOVER_FAILED =
             "android.telecom.event.HANDOVER_FAILED";
 
+
+    /**
+     * Reject reason used with {@link #reject(int)} to indicate that the user is rejecting this
+     * call because they have declined to answer it.  This typically means that they are unable
+     * to answer the call at this time and would prefer it be sent to voicemail.
+     */
+    public static final int REJECT_REASON_DECLINED = 1;
+
+    /**
+     * Reject reason used with {@link #reject(int)} to indicate that the user is rejecting this
+     * call because it is an unwanted call.  This allows the user to indicate that they are
+     * rejecting a call because it is likely a nuisance call.
+     */
+    public static final int REJECT_REASON_UNWANTED = 2;
+
+    /**
+     * @hide
+     */
+    @IntDef(prefix = { "REJECT_REASON_" },
+            value = {REJECT_REASON_DECLINED, REJECT_REASON_UNWANTED})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface RejectReason {};
+
     public static class Details {
         /** @hide */
         @Retention(RetentionPolicy.SOURCE)
@@ -1520,6 +1543,16 @@
     }
 
     /**
+     * Instructs the {@link ConnectionService} providing this {@link #STATE_RINGING} call that the
+     * user has chosen to reject the call and has indicated a reason why the call is being rejected.
+     *
+     * @param rejectReason the reason the call is being rejected.
+     */
+    public void reject(@RejectReason int rejectReason) {
+        mInCallAdapter.rejectCall(mTelecomCallId, rejectReason);
+    }
+
+    /**
      * Instructs this {@code Call} to disconnect.
      */
     public void disconnect() {
diff --git a/telecomm/java/android/telecom/CallerInfoAsyncQuery.java b/telecomm/java/android/telecom/CallerInfoAsyncQuery.java
index 4a50e98..4a81a8e 100644
--- a/telecomm/java/android/telecom/CallerInfoAsyncQuery.java
+++ b/telecomm/java/android/telecom/CallerInfoAsyncQuery.java
@@ -17,6 +17,7 @@
 package android.telecom;
 
 import android.app.ActivityManager;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.AsyncQueryHandler;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -35,8 +36,6 @@
 import android.telephony.SubscriptionManager;
 import android.text.TextUtils;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
 import java.util.ArrayList;
 import java.util.List;
 
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index c934625..72c66d2 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -3037,6 +3037,17 @@
     public void onReject() {}
 
     /**
+     * Notifies this Connection, which is in {@link #STATE_RINGING}, of a request to reject.
+     * <p>
+     * For managed {@link ConnectionService}s, this will be called when the user rejects a call via
+     * the default dialer's {@link InCallService} using {@link Call#reject(int)}.
+     * @param rejectReason the reason the user provided for rejecting the call.
+     */
+    public void onReject(@android.telecom.Call.RejectReason int rejectReason) {
+        // to be implemented by ConnectionService.
+    }
+
+    /**
      * Notifies this Connection, which is in {@link #STATE_RINGING}, of
      * a request to reject with a message.
      */
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 440f044..00c2918 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -194,6 +194,7 @@
     private static final int MSG_CREATE_CONFERENCE = 35;
     private static final int MSG_CREATE_CONFERENCE_COMPLETE = 36;
     private static final int MSG_CREATE_CONFERENCE_FAILED = 37;
+    private static final int MSG_REJECT_WITH_REASON = 38;
 
     private static Connection sNullConnection;
 
@@ -450,6 +451,21 @@
         }
 
         @Override
+        public void rejectWithReason(String callId,
+                @android.telecom.Call.RejectReason int rejectReason, Session.Info sessionInfo) {
+            Log.startSession(sessionInfo, SESSION_REJECT);
+            try {
+                SomeArgs args = SomeArgs.obtain();
+                args.arg1 = callId;
+                args.argi1 = rejectReason;
+                args.arg2 = Log.createSubsession();
+                mHandler.obtainMessage(MSG_REJECT_WITH_REASON, args).sendToTarget();
+            } finally {
+                Log.endSession();
+            }
+        }
+
+        @Override
         public void rejectWithMessage(String callId, String message, Session.Info sessionInfo) {
             Log.startSession(sessionInfo, SESSION_REJECT_MESSAGE);
             try {
@@ -1053,6 +1069,17 @@
                     }
                     break;
                 }
+                case MSG_REJECT_WITH_REASON: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_REJECT);
+                    try {
+                        reject((String) args.arg1, args.argi1);
+                    } finally {
+                        args.recycle();
+                        Log.endSession();
+                    }
+                    break;
+                }
                 case MSG_REJECT_WITH_MESSAGE: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     Log.continueSession((Session) args.arg3,
@@ -1981,6 +2008,11 @@
         findConnectionForAction(callId, "reject").onReject(rejectWithMessage);
     }
 
+    private void reject(String callId, @android.telecom.Call.RejectReason int rejectReason) {
+        Log.d(this, "reject %s with reason %d", callId, rejectReason);
+        findConnectionForAction(callId, "reject").onReject(rejectReason);
+    }
+
     private void silence(String callId) {
         Log.d(this, "silence %s", callId);
         findConnectionForAction(callId, "silence").onSilence();
diff --git a/telecomm/java/android/telecom/DisconnectCause.java b/telecomm/java/android/telecom/DisconnectCause.java
index bebbbd0..0093843 100644
--- a/telecomm/java/android/telecom/DisconnectCause.java
+++ b/telecomm/java/android/telecom/DisconnectCause.java
@@ -80,20 +80,17 @@
      * Reason code (returned via {@link #getReason()}) which indicates that a call could not be
      * completed because the cellular radio is off or out of service, the device is connected to
      * a wifi network, but the user has not enabled wifi calling.
-     * @hide
      */
     public static final String REASON_WIFI_ON_BUT_WFC_OFF = "REASON_WIFI_ON_BUT_WFC_OFF";
 
     /**
      * Reason code (returned via {@link #getReason()}), which indicates that the video telephony
      * call was disconnected because IMS access is blocked.
-     * @hide
      */
     public static final String REASON_IMS_ACCESS_BLOCKED = "REASON_IMS_ACCESS_BLOCKED";
 
     /**
      * Reason code, which indicates that the conference call is simulating single party conference.
-     * @hide
      */
     public static final String REASON_EMULATING_SINGLE_CALL = "EMULATING_SINGLE_CALL";
 
diff --git a/telecomm/java/android/telecom/InCallAdapter.java b/telecomm/java/android/telecom/InCallAdapter.java
index 2612468..594c1eb 100644
--- a/telecomm/java/android/telecom/InCallAdapter.java
+++ b/telecomm/java/android/telecom/InCallAdapter.java
@@ -89,6 +89,19 @@
     }
 
     /**
+     * Instructs Telecom to reject the specified call.
+     *
+     * @param callId The identifier of the call to reject.
+     * @param rejectReason The reason the call was rejected.
+     */
+    public void rejectCall(String callId, @Call.RejectReason int rejectReason) {
+        try {
+            mAdapter.rejectCallWithReason(callId, rejectReason);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
      * Instructs Telecom to disconnect the specified call.
      *
      * @param callId The identifier of the call to disconnect.
diff --git a/telecomm/java/android/telecom/ParcelableCallAnalytics.java b/telecomm/java/android/telecom/ParcelableCallAnalytics.java
index 2b9213b..b8ad9e2 100644
--- a/telecomm/java/android/telecom/ParcelableCallAnalytics.java
+++ b/telecomm/java/android/telecom/ParcelableCallAnalytics.java
@@ -258,27 +258,6 @@
     public static final int SIP_PHONE = 0x8;
     public static final int THIRD_PARTY_PHONE = 0x10;
 
-    /**
-     * Indicating the call source is not specified.
-     *
-     * @hide
-     */
-    public static final int CALL_SOURCE_UNSPECIFIED = 0;
-
-    /**
-     * Indicating the call is initiated via emergency dialer's dialpad.
-     *
-     * @hide
-     */
-    public static final int CALL_SOURCE_EMERGENCY_DIALPAD = 1;
-
-    /**
-     * Indicating the call is initiated via emergency dialer's shortcut button.
-     *
-     * @hide
-     */
-    public static final int CALL_SOURCE_EMERGENCY_SHORTCUT = 2;
-
     public static final long MILLIS_IN_5_MINUTES = 1000 * 60 * 5;
     public static final long MILLIS_IN_1_SECOND = 1000;
 
@@ -343,7 +322,7 @@
     private List<VideoEvent> videoEvents;
 
     // The source where user initiated this call. ONE OF the CALL_SOURCE_* constants.
-    private int callSource = CALL_SOURCE_UNSPECIFIED;
+    private int callSource = TelecomManager.CALL_SOURCE_UNSPECIFIED;
 
     public ParcelableCallAnalytics(long startTimeMillis, long callDurationMillis, int callType,
             boolean isAdditionalCall, boolean isInterrupted, int callTechnologies,
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index abb210f..f00432b 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -50,6 +50,7 @@
      * {@link android.telecom.ConnectionService}.
      * @hide
      */
+    @SystemApi
     public static final String EXTRA_SORT_ORDER =
             "android.telecom.extra.SORT_ORDER";
 
@@ -79,10 +80,13 @@
     public static final String EXTRA_CALL_SUBJECT_CHARACTER_ENCODING =
             "android.telecom.extra.CALL_SUBJECT_CHARACTER_ENCODING";
 
-     /**
-     * Indicating flag for phone account whether to use voip audio mode for voip calls
+    /**
+     * Boolean {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which
+     * indicates that all calls from this {@link PhoneAccount} should be treated as VoIP calls
+     * rather than cellular calls.
      * @hide
      */
+    @SystemApi
     public static final String EXTRA_ALWAYS_USE_VOIP_AUDIO_MODE =
             "android.telecom.extra.ALWAYS_USE_VOIP_AUDIO_MODE";
 
@@ -107,6 +111,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final String EXTRA_SUPPORTS_VIDEO_CALLING_FALLBACK =
             "android.telecom.extra.SUPPORTS_VIDEO_CALLING_FALLBACK";
 
@@ -155,6 +160,7 @@
      * in progress.
      * @hide
      */
+    @SystemApi
     public static final String EXTRA_PLAY_CALL_RECORDING_TONE =
             "android.telecom.extra.PLAY_CALL_RECORDING_TONE";
 
@@ -249,6 +255,7 @@
      * See {@link #getCapabilities}
      * @hide
      */
+    @SystemApi
     public static final int CAPABILITY_EMERGENCY_CALLS_ONLY = 0x80;
 
     /**
@@ -272,6 +279,7 @@
      * convert all outgoing video calls to emergency numbers to audio-only.
      * @hide
      */
+    @SystemApi
     public static final int CAPABILITY_EMERGENCY_VIDEO_CALLING = 0x200;
 
     /**
@@ -329,6 +337,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final int CAPABILITY_EMERGENCY_PREFERRED = 0x2000;
 
     /**
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 49b74c6..bf4dee2 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -313,15 +313,18 @@
             "android.telecom.extra.IS_USER_INTENT_EMERGENCY_CALL";
 
     /**
+     * A mandatory extra containing a {@link Uri} to be passed in when calling
+     * {@link #addNewUnknownCall(PhoneAccountHandle, Bundle)}. The {@link Uri} value indicates
+     * the remote handle of the new call.
      * @hide
      */
+    @SystemApi
     public static final String EXTRA_UNKNOWN_CALL_HANDLE =
             "android.telecom.extra.UNKNOWN_CALL_HANDLE";
 
     /**
      * Optional extra for incoming and outgoing calls containing a long which specifies the time the
      * call was created. This value is in milliseconds since boot.
-     * @hide
      */
     public static final String EXTRA_CALL_CREATED_TIME_MILLIS =
             "android.telecom.extra.CALL_CREATED_TIME_MILLIS";
@@ -366,10 +369,18 @@
             "android.telecom.extra.CONNECTION_SERVICE";
 
     /**
-     * Optional extra for communicating the call technology used by a
-     * {@link com.android.internal.telephony.Connection} to Telecom
+     * Optional extra for communicating the call technology used by a {@link ConnectionService}
+     * to Telecom. Valid values are:
+     * <ul>
+     *     <li>{@link TelephonyManager#PHONE_TYPE_CDMA}</li>
+     *     <li>{@link TelephonyManager#PHONE_TYPE_GSM}</li>
+     *     <li>{@link TelephonyManager#PHONE_TYPE_IMS}</li>
+     *     <li>{@link TelephonyManager#PHONE_TYPE_THIRD_PARTY}</li>
+     *     <li>{@link TelephonyManager#PHONE_TYPE_SIP}</li>
+     * </ul>
      * @hide
      */
+    @SystemApi
     public static final String EXTRA_CALL_TECHNOLOGY_TYPE =
             "android.telecom.extra.CALL_TECHNOLOGY_TYPE";
 
@@ -712,21 +723,24 @@
      * @see #EXTRA_CURRENT_TTY_MODE
      * @hide
      */
+    @SystemApi
     public static final String ACTION_CURRENT_TTY_MODE_CHANGED =
             "android.telecom.action.CURRENT_TTY_MODE_CHANGED";
 
     /**
      * The lookup key for an int that indicates the current TTY mode.
      * Valid modes are:
-     * - {@link #TTY_MODE_OFF}
-     * - {@link #TTY_MODE_FULL}
-     * - {@link #TTY_MODE_HCO}
-     * - {@link #TTY_MODE_VCO}
-     *
+     * <ul>
+     *     <li>{@link #TTY_MODE_OFF}</li>
+     *     <li>{@link #TTY_MODE_FULL}</li>
+     *     <li>{@link #TTY_MODE_HCO}</li>
+     *     <li>{@link #TTY_MODE_VCO}</li>
+     * </ul>
      * @hide
      */
+    @SystemApi
     public static final String EXTRA_CURRENT_TTY_MODE =
-            "android.telecom.intent.extra.CURRENT_TTY_MODE";
+            "android.telecom.extra.CURRENT_TTY_MODE";
 
     /**
      * Broadcast intent action indicating that the TTY preferred operating mode has changed. An
@@ -735,6 +749,7 @@
      * @see #EXTRA_TTY_PREFERRED_MODE
      * @hide
      */
+    @SystemApi
     public static final String ACTION_TTY_PREFERRED_MODE_CHANGED =
             "android.telecom.action.TTY_PREFERRED_MODE_CHANGED";
 
@@ -745,8 +760,9 @@
      *
      * @hide
      */
+    @SystemApi
     public static final String EXTRA_TTY_PREFERRED_MODE =
-            "android.telecom.intent.extra.TTY_PREFERRED";
+            "android.telecom.extra.TTY_PREFERRED_MODE";
 
     /**
      * Broadcast intent action for letting custom component know to show the missed call
@@ -815,16 +831,41 @@
     /**
      * Optional extra for {@link #placeCall(Uri, Bundle)} containing an integer that specifies
      * the source where user initiated this call. This data is used in metrics.
-     * Valid source are:
-     * {@link ParcelableCallAnalytics#CALL_SOURCE_UNSPECIFIED},
-     * {@link ParcelableCallAnalytics#CALL_SOURCE_EMERGENCY_DIALPAD},
-     * {@link ParcelableCallAnalytics#CALL_SOURCE_EMERGENCY_SHORTCUT}.
+     * Valid sources are:
+     * {@link TelecomManager#CALL_SOURCE_UNSPECIFIED},
+     * {@link TelecomManager#CALL_SOURCE_EMERGENCY_DIALPAD},
+     * {@link TelecomManager#CALL_SOURCE_EMERGENCY_SHORTCUT}.
      *
      * @hide
      */
+    @SystemApi
     public static final String EXTRA_CALL_SOURCE = "android.telecom.extra.CALL_SOURCE";
 
     /**
+     * Indicating the call is initiated via emergency dialer's shortcut button.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int CALL_SOURCE_EMERGENCY_SHORTCUT = 2;
+
+    /**
+     * Indicating the call is initiated via emergency dialer's dialpad.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int CALL_SOURCE_EMERGENCY_DIALPAD = 1;
+
+    /**
+     * Indicating the call source is not specified.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int CALL_SOURCE_UNSPECIFIED = 0;
+
+    /**
      * The following 4 constants define how properties such as phone numbers and names are
      * displayed to the user.
      */
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
index 96f2483..4249dff 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
@@ -77,6 +77,8 @@
 
     void reject(String callId, in Session.Info sessionInfo);
 
+    void rejectWithReason(String callId, int rejectReason, in Session.Info sessionInfo);
+
     void rejectWithMessage(String callId, String message, in Session.Info sessionInfo);
 
     void disconnect(String callId, in Session.Info sessionInfo);
diff --git a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
index 60745e4..eb2d714 100644
--- a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
@@ -34,6 +34,8 @@
 
     void rejectCall(String callId, boolean rejectWithMessage, String textMessage);
 
+    void rejectCallWithReason(String callId, int rejectReason);
+
     void disconnectCall(String callId);
 
     void holdCall(String callId);
diff --git a/telephony/OWNERS b/telephony/OWNERS
index 58a7ea0..628c480 100644
--- a/telephony/OWNERS
+++ b/telephony/OWNERS
@@ -1,18 +1,16 @@
 set noparent
 
-tgunn@google.com
-breadley@google.com
-hallliu@google.com
-rgreenwalt@google.com
-mpq@google.com
 amitmahajan@google.com
+breadley@google.com
 fionaxu@google.com
 jackyu@google.com
+hallliu@google.com
+rgreenwalt@google.com
+tgunn@google.com
 jminjie@google.com
-satk@google.com
 shuoq@google.com
 refuhoo@google.com
-paulye@google.com
 nazaninb@google.com
 sarahchin@google.com
 dbright@google.com
+xiaotonj@google.com
diff --git a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
index 9bc534c..553bcff 100644
--- a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
+++ b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
@@ -20,19 +20,16 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
-import android.os.RemoteException;
 import android.os.UserHandle;
-import android.permission.IPermissionManager;
+import android.permission.PermissionManager;
 import android.provider.Settings;
 import android.telephony.TelephonyManager;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
 
-import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.util.ArrayUtils;
 import com.android.server.SystemConfig;
@@ -77,7 +74,6 @@
      * privileged apps may have changed.
      */
     public static synchronized void disableCarrierAppsUntilPrivileged(String callingPackage,
-            IPackageManager packageManager, IPermissionManager permissionManager,
             TelephonyManager telephonyManager, int userId, Context context) {
         if (DEBUG) {
             Log.d(TAG, "disableCarrierAppsUntilPrivileged");
@@ -88,14 +84,14 @@
         ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed =
                 config.getDisabledUntilUsedPreinstalledCarrierAssociatedApps();
         ContentResolver contentResolver = getContentResolverForUser(context, userId);
-        disableCarrierAppsUntilPrivileged(callingPackage, packageManager, permissionManager,
-                telephonyManager, contentResolver, userId, systemCarrierAppsDisabledUntilUsed,
-                systemCarrierAssociatedAppsDisabledUntilUsed);
+        disableCarrierAppsUntilPrivileged(callingPackage, telephonyManager, contentResolver,
+                userId, systemCarrierAppsDisabledUntilUsed,
+                systemCarrierAssociatedAppsDisabledUntilUsed, context);
     }
 
     /**
-     * Like {@link #disableCarrierAppsUntilPrivileged(String, IPackageManager, TelephonyManager,
-     * ContentResolver, int)}, but assumes that no carrier apps have carrier privileges.
+     * Like {@link #disableCarrierAppsUntilPrivileged(String, TelephonyManager, int, Context)},
+     * but assumes that no carrier apps have carrier privileges.
      *
      * This prevents a potential race condition on first boot - since the app's default state is
      * enabled, we will initially disable it when the telephony stack is first initialized as it has
@@ -105,8 +101,7 @@
      * Manager can kill it, and this can lead to crashes as the app is in an unexpected state.
      */
     public static synchronized void disableCarrierAppsUntilPrivileged(String callingPackage,
-            IPackageManager packageManager, IPermissionManager permissionManager, int userId,
-            Context context) {
+            int userId, Context context) {
         if (DEBUG) {
             Log.d(TAG, "disableCarrierAppsUntilPrivileged");
         }
@@ -114,13 +109,12 @@
         ArraySet<String> systemCarrierAppsDisabledUntilUsed =
                 config.getDisabledUntilUsedPreinstalledCarrierApps();
 
-
         ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed =
                 config.getDisabledUntilUsedPreinstalledCarrierAssociatedApps();
         ContentResolver contentResolver = getContentResolverForUser(context, userId);
-        disableCarrierAppsUntilPrivileged(callingPackage, packageManager, permissionManager,
-                null /* telephonyManager */, contentResolver, userId,
-                systemCarrierAppsDisabledUntilUsed, systemCarrierAssociatedAppsDisabledUntilUsed);
+        disableCarrierAppsUntilPrivileged(callingPackage, null /* telephonyManager */,
+                contentResolver, userId, systemCarrierAppsDisabledUntilUsed,
+                systemCarrierAssociatedAppsDisabledUntilUsed, context);
     }
 
     private static ContentResolver getContentResolverForUser(Context context, int userId) {
@@ -136,21 +130,21 @@
     // Must be public b/c framework unit tests can't access package-private methods.
     @VisibleForTesting
     public static void disableCarrierAppsUntilPrivileged(String callingPackage,
-            IPackageManager packageManager, IPermissionManager permissionManager,
-            @Nullable TelephonyManager telephonyManager,
-            ContentResolver contentResolver, int userId,
-            ArraySet<String> systemCarrierAppsDisabledUntilUsed,
-            ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed) {
+            @Nullable TelephonyManager telephonyManager, ContentResolver contentResolver,
+            int userId, ArraySet<String> systemCarrierAppsDisabledUntilUsed,
+            ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed,
+            Context context) {
+        PackageManager packageManager = context.getPackageManager();
+        PermissionManager permissionManager =
+                (PermissionManager) context.getSystemService(Context.PERMISSION_SERVICE);
         List<ApplicationInfo> candidates = getDefaultNotUpdatedCarrierAppCandidatesHelper(
-                packageManager, userId, systemCarrierAppsDisabledUntilUsed);
+                userId, systemCarrierAppsDisabledUntilUsed, context);
         if (candidates == null || candidates.isEmpty()) {
             return;
         }
 
         Map<String, List<ApplicationInfo>> associatedApps = getDefaultCarrierAssociatedAppsHelper(
-                packageManager,
-                userId,
-                systemCarrierAssociatedAppsDisabledUntilUsed);
+                userId, systemCarrierAssociatedAppsDisabledUntilUsed, context);
 
         List<String> enabledCarrierPackages = new ArrayList<>();
         boolean hasRunOnce = Settings.Secure.getInt(contentResolver,
@@ -160,26 +154,25 @@
             for (ApplicationInfo ai : candidates) {
                 String packageName = ai.packageName;
                 String[] restrictedCarrierApps = Resources.getSystem().getStringArray(
-                        R.array.config_restrictedPreinstalledCarrierApps);
+                        android.R.array.config_restrictedPreinstalledCarrierApps);
                 boolean hasPrivileges = telephonyManager != null
                         && telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName)
                                 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS
                         && !ArrayUtils.contains(restrictedCarrierApps, packageName);
 
                 // add hiddenUntilInstalled flag for carrier apps and associated apps
-                packageManager.setSystemAppHiddenUntilInstalled(packageName, true);
+                packageManager.setSystemAppState(
+                        packageName, PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
                 List<ApplicationInfo> associatedAppList = associatedApps.get(packageName);
                 if (associatedAppList != null) {
                     for (ApplicationInfo associatedApp : associatedAppList) {
-                        packageManager.setSystemAppHiddenUntilInstalled(
-                                associatedApp.packageName,
-                                true
-                        );
+                        packageManager.setSystemAppState(associatedApp.packageName,
+                                PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
                     }
                 }
 
-                int enabledSetting = packageManager.getApplicationEnabledSetting(packageName,
-                        userId);
+                int enabledSetting = context.createContextAsUser(UserHandle.of(userId), 0)
+                        .getPackageManager().getApplicationEnabledSetting(packageName);
                 if (hasPrivileges) {
                     // Only update enabled state for the app on /system. Once it has been
                     // updated we shouldn't touch it.
@@ -190,24 +183,25 @@
                             || (ai.flags & ApplicationInfo.FLAG_INSTALLED) == 0) {
                         Log.i(TAG, "Update state(" + packageName + "): ENABLED for user "
                                 + userId);
-                        packageManager.setSystemAppInstallState(
-                                packageName,
-                                true /*installed*/,
-                                userId);
-                        packageManager.setApplicationEnabledSetting(
-                                packageName,
-                                PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
-                                PackageManager.DONT_KILL_APP,
-                                userId,
-                                callingPackage);
+                        context.createContextAsUser(UserHandle.of(userId), 0)
+                                .getPackageManager()
+                                .setSystemAppState(
+                                        packageName, PackageManager.SYSTEM_APP_STATE_INSTALLED);
+                        context.createPackageContextAsUser(callingPackage, 0, UserHandle.of(userId))
+                                .getPackageManager()
+                                .setApplicationEnabledSetting(
+                                        packageName,
+                                        PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+                                        PackageManager.DONT_KILL_APP);
                     }
 
                     // Also enable any associated apps for this carrier app.
                     if (associatedAppList != null) {
                         for (ApplicationInfo associatedApp : associatedAppList) {
-                            int associatedAppEnabledSetting =
-                                    packageManager.getApplicationEnabledSetting(
-                                    associatedApp.packageName, userId);
+                            int associatedAppEnabledSetting = context
+                                    .createContextAsUser(UserHandle.of(userId), 0)
+                                    .getPackageManager()
+                                    .getApplicationEnabledSetting(associatedApp.packageName);
                             if (associatedAppEnabledSetting
                                     == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
                                     || associatedAppEnabledSetting
@@ -216,16 +210,17 @@
                                     & ApplicationInfo.FLAG_INSTALLED) == 0) {
                                 Log.i(TAG, "Update associated state(" + associatedApp.packageName
                                         + "): ENABLED for user " + userId);
-                                packageManager.setSystemAppInstallState(
-                                        associatedApp.packageName,
-                                        true /*installed*/,
-                                        userId);
-                                packageManager.setApplicationEnabledSetting(
-                                        associatedApp.packageName,
-                                        PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
-                                        PackageManager.DONT_KILL_APP,
-                                        userId,
-                                        callingPackage);
+                                context.createContextAsUser(UserHandle.of(userId), 0)
+                                        .getPackageManager()
+                                        .setSystemAppState(associatedApp.packageName,
+                                                PackageManager.SYSTEM_APP_STATE_INSTALLED);
+                                context.createPackageContextAsUser(
+                                        callingPackage, 0, UserHandle.of(userId))
+                                        .getPackageManager()
+                                        .setApplicationEnabledSetting(
+                                                associatedApp.packageName,
+                                                PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+                                                PackageManager.DONT_KILL_APP);
                             }
                         }
                     }
@@ -240,10 +235,10 @@
                             && (ai.flags & ApplicationInfo.FLAG_INSTALLED) != 0) {
                         Log.i(TAG, "Update state(" + packageName
                                 + "): DISABLED_UNTIL_USED for user " + userId);
-                        packageManager.setSystemAppInstallState(
-                                packageName,
-                                false /*installed*/,
-                                userId);
+                        context.createContextAsUser(UserHandle.of(userId), 0)
+                                .getPackageManager()
+                                .setSystemAppState(
+                                        packageName, PackageManager.SYSTEM_APP_STATE_UNINSTALLED);
                     }
 
                     // Also disable any associated apps for this carrier app if this is the first
@@ -252,9 +247,10 @@
                     if (!hasRunOnce) {
                         if (associatedAppList != null) {
                             for (ApplicationInfo associatedApp : associatedAppList) {
-                                int associatedAppEnabledSetting =
-                                        packageManager.getApplicationEnabledSetting(
-                                        associatedApp.packageName, userId);
+                                int associatedAppEnabledSetting = context
+                                        .createContextAsUser(UserHandle.of(userId), 0)
+                                        .getPackageManager()
+                                        .getApplicationEnabledSetting(associatedApp.packageName);
                                 if (associatedAppEnabledSetting
                                         == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
                                         && (associatedApp.flags
@@ -262,10 +258,10 @@
                                     Log.i(TAG,
                                             "Update associated state(" + associatedApp.packageName
                                                     + "): DISABLED_UNTIL_USED for user " + userId);
-                                    packageManager.setSystemAppInstallState(
-                                            associatedApp.packageName,
-                                            false /*installed*/,
-                                            userId);
+                                    context.createContextAsUser(UserHandle.of(userId), 0)
+                                            .getPackageManager()
+                                            .setSystemAppState(associatedApp.packageName,
+                                                    PackageManager.SYSTEM_APP_STATE_UNINSTALLED);
                                 }
                             }
                         }
@@ -283,9 +279,10 @@
                 // apps.
                 String[] packageNames = new String[enabledCarrierPackages.size()];
                 enabledCarrierPackages.toArray(packageNames);
-                permissionManager.grantDefaultPermissionsToEnabledCarrierApps(packageNames, userId);
+                permissionManager.grantDefaultPermissionsToEnabledCarrierApps(packageNames,
+                        UserHandle.of(userId), Runnable::run, isSuccess -> { });
             }
-        } catch (RemoteException e) {
+        } catch (PackageManager.NameNotFoundException e) {
             Log.w(TAG, "Could not reach PackageManager", e);
         }
     }
@@ -294,13 +291,13 @@
      * Returns the list of "default" carrier apps.
      *
      * This is the subset of apps returned by
-     * {@link #getDefaultCarrierAppCandidates(IPackageManager, int)} which currently have carrier
+     * {@link #getDefaultCarrierAppCandidates(int, Context)} which currently have carrier
      * privileges per the SIM(s) inserted in the device.
      */
-    public static List<ApplicationInfo> getDefaultCarrierApps(IPackageManager packageManager,
-            TelephonyManager telephonyManager, int userId) {
+    public static List<ApplicationInfo> getDefaultCarrierApps(
+            TelephonyManager telephonyManager, int userId, Context context) {
         // Get all system apps from the default list.
-        List<ApplicationInfo> candidates = getDefaultCarrierAppCandidates(packageManager, userId);
+        List<ApplicationInfo> candidates = getDefaultCarrierAppCandidates(userId, context);
         if (candidates == null || candidates.isEmpty()) {
             return null;
         }
@@ -326,25 +323,23 @@
      * Returns the list of "default" carrier app candidates.
      *
      * These are the apps subject to the hiding/showing logic in
-     * {@link CarrierAppUtils#disableCarrierAppsUntilPrivileged(String, IPackageManager,
-     * TelephonyManager, ContentResolver, int)}, as well as the apps which should have default
+     * {@link CarrierAppUtils#disableCarrierAppsUntilPrivileged(String, TelephonyManager, int,
+     * Context)}, as well as the apps which should have default
      * permissions granted, when a matching SIM is inserted.
      *
      * Whether or not the app is actually considered a default app depends on whether the app has
      * carrier privileges as determined by the SIMs in the device.
      */
     public static List<ApplicationInfo> getDefaultCarrierAppCandidates(
-            IPackageManager packageManager, int userId) {
+            int userId, Context context) {
         ArraySet<String> systemCarrierAppsDisabledUntilUsed =
                 SystemConfig.getInstance().getDisabledUntilUsedPreinstalledCarrierApps();
-        return getDefaultCarrierAppCandidatesHelper(packageManager, userId,
-                systemCarrierAppsDisabledUntilUsed);
+        return getDefaultCarrierAppCandidatesHelper(userId, systemCarrierAppsDisabledUntilUsed,
+                context);
     }
 
     private static List<ApplicationInfo> getDefaultCarrierAppCandidatesHelper(
-            IPackageManager packageManager,
-            int userId,
-            ArraySet<String> systemCarrierAppsDisabledUntilUsed) {
+            int userId, ArraySet<String> systemCarrierAppsDisabledUntilUsed, Context context) {
         if (systemCarrierAppsDisabledUntilUsed == null) {
             return null;
         }
@@ -358,7 +353,7 @@
         for (int i = 0; i < size; i++) {
             String packageName = systemCarrierAppsDisabledUntilUsed.valueAt(i);
             ApplicationInfo ai =
-                    getApplicationInfoIfSystemApp(packageManager, userId, packageName);
+                    getApplicationInfoIfSystemApp(userId, packageName, context);
             if (ai != null) {
                 apps.add(ai);
             }
@@ -367,9 +362,7 @@
     }
 
     private static List<ApplicationInfo> getDefaultNotUpdatedCarrierAppCandidatesHelper(
-            IPackageManager packageManager,
-            int userId,
-            ArraySet<String> systemCarrierAppsDisabledUntilUsed) {
+            int userId, ArraySet<String> systemCarrierAppsDisabledUntilUsed, Context context) {
         if (systemCarrierAppsDisabledUntilUsed == null) {
             return null;
         }
@@ -383,7 +376,7 @@
         for (int i = 0; i < size; i++) {
             String packageName = systemCarrierAppsDisabledUntilUsed.valueAt(i);
             ApplicationInfo ai =
-                    getApplicationInfoIfNotUpdatedSystemApp(packageManager, userId, packageName);
+                    getApplicationInfoIfNotUpdatedSystemApp(userId, packageName, context);
             if (ai != null) {
                 apps.add(ai);
             }
@@ -392,9 +385,8 @@
     }
 
     private static Map<String, List<ApplicationInfo>> getDefaultCarrierAssociatedAppsHelper(
-            IPackageManager packageManager,
-            int userId,
-            ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed) {
+            int userId, ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed,
+            Context context) {
         int size = systemCarrierAssociatedAppsDisabledUntilUsed.size();
         Map<String, List<ApplicationInfo>> associatedApps = new ArrayMap<>(size);
         for (int i = 0; i < size; i++) {
@@ -404,7 +396,7 @@
             for (int j = 0; j < associatedAppPackages.size(); j++) {
                 ApplicationInfo ai =
                         getApplicationInfoIfNotUpdatedSystemApp(
-                                packageManager, userId, associatedAppPackages.get(j));
+                                userId, associatedAppPackages.get(j), context);
                 // Only update enabled state for the app on /system. Once it has been updated we
                 // shouldn't touch it.
                 if (ai != null) {
@@ -422,19 +414,19 @@
 
     @Nullable
     private static ApplicationInfo getApplicationInfoIfNotUpdatedSystemApp(
-            IPackageManager packageManager,
-            int userId,
-            String packageName) {
+            int userId, String packageName, Context context) {
         try {
-            ApplicationInfo ai = packageManager.getApplicationInfo(packageName,
-                    PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
-                            | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS
-                            | PackageManager.MATCH_SYSTEM_ONLY
-                            | PackageManager.MATCH_FACTORY_ONLY, userId);
+            ApplicationInfo ai = context.createContextAsUser(UserHandle.of(userId), 0)
+                    .getPackageManager()
+                    .getApplicationInfo(packageName,
+                            PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
+                                    | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS
+                                    | PackageManager.MATCH_SYSTEM_ONLY
+                                    | PackageManager.MATCH_FACTORY_ONLY);
             if (ai != null) {
                 return ai;
             }
-        } catch (RemoteException e) {
+        } catch (PackageManager.NameNotFoundException e) {
             Log.w(TAG, "Could not reach PackageManager", e);
         }
         return null;
@@ -442,18 +434,18 @@
 
     @Nullable
     private static ApplicationInfo getApplicationInfoIfSystemApp(
-            IPackageManager packageManager,
-            int userId,
-            String packageName) {
+            int userId, String packageName, Context context) {
         try {
-            ApplicationInfo ai = packageManager.getApplicationInfo(packageName,
-                    PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
-                    | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS
-                    | PackageManager.MATCH_SYSTEM_ONLY, userId);
+            ApplicationInfo ai = context.createContextAsUser(UserHandle.of(userId), 0)
+                    .getPackageManager()
+                    .getApplicationInfo(packageName,
+                            PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
+                                    | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS
+                                    | PackageManager.MATCH_SYSTEM_ONLY);
             if (ai != null) {
                 return ai;
             }
-        } catch (RemoteException e) {
+        } catch (PackageManager.NameNotFoundException e) {
             Log.w(TAG, "Could not reach PackageManager", e);
         }
         return null;
diff --git a/telephony/common/com/android/internal/telephony/GsmAlphabet.java b/telephony/common/com/android/internal/telephony/GsmAlphabet.java
index 5c53f7e..c62cec2 100644
--- a/telephony/common/com/android/internal/telephony/GsmAlphabet.java
+++ b/telephony/common/com/android/internal/telephony/GsmAlphabet.java
@@ -19,12 +19,10 @@
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.res.Resources;
 import android.os.Build;
-import android.util.Log;
 import android.text.TextUtils;
+import android.util.Log;
 import android.util.SparseIntArray;
 
-import com.android.internal.R;
-
 import java.nio.ByteBuffer;
 import java.nio.charset.Charset;
 import java.util.ArrayList;
@@ -1089,8 +1087,10 @@
     private static void enableCountrySpecificEncodings() {
         Resources r = Resources.getSystem();
         // See comments in frameworks/base/core/res/res/values/config.xml for allowed values
-        sEnabledSingleShiftTables = r.getIntArray(R.array.config_sms_enabled_single_shift_tables);
-        sEnabledLockingShiftTables = r.getIntArray(R.array.config_sms_enabled_locking_shift_tables);
+        sEnabledSingleShiftTables = r.getIntArray(
+                android.R.array.config_sms_enabled_single_shift_tables);
+        sEnabledLockingShiftTables = r.getIntArray(
+                android.R.array.config_sms_enabled_locking_shift_tables);
 
         if (sEnabledSingleShiftTables.length > 0) {
             sHighestEnabledSingleShiftCode =
diff --git a/telephony/common/com/android/internal/telephony/SmsApplication.java b/telephony/common/com/android/internal/telephony/SmsApplication.java
index ffb3cb1..bb6f154 100644
--- a/telephony/common/com/android/internal/telephony/SmsApplication.java
+++ b/telephony/common/com/android/internal/telephony/SmsApplication.java
@@ -20,6 +20,7 @@
 import android.annotation.Nullable;
 import android.app.AppOpsManager;
 import android.app.role.RoleManager;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -34,21 +35,15 @@
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Binder;
-import android.os.Debug;
 import android.os.Process;
 import android.os.UserHandle;
 import android.provider.Telephony;
 import android.provider.Telephony.Sms.Intents;
 import android.telephony.PackageChangeReceiver;
-import android.util.Log;
 import android.telephony.TelephonyManager;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
-import dalvik.annotation.compat.UnsupportedAppUsage;
 
 import java.util.Collection;
 import java.util.HashMap;
@@ -199,7 +194,7 @@
         final int callingUid = Binder.getCallingUid();
         if (DEBUG_MULTIUSER) {
             Log.i(LOG_TAG, "getIncomingUserHandle caller=" + callingUid + ", myuid="
-                    + android.os.Process.myUid() + "\n\t" + Debug.getCallers(4));
+                    + android.os.Process.myUid());
         }
         if (UserHandle.getAppId(callingUid)
                 < android.os.Process.FIRST_APPLICATION_UID) {
@@ -671,9 +666,21 @@
     }
 
     /**
+     * Broadcast action:
+     * Same as {@link Intent#ACTION_DEFAULT_SMS_PACKAGE_CHANGED} but it's implicit (e.g. sent to
+     * all apps) and requires
+     * {@link #PERMISSION_MONITOR_DEFAULT_SMS_PACKAGE} to receive.
+     */
+    public static final String ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL =
+            "android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL";
+
+    public static final String PERMISSION_MONITOR_DEFAULT_SMS_PACKAGE =
+            "android.permission.MONITOR_DEFAULT_SMS_PACKAGE";
+
+    /**
      * Sends broadcasts on sms app change:
      * {@link Intent#ACTION_DEFAULT_SMS_PACKAGE_CHANGED}
-     * {@link Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL}
+     * {@link #ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL}
      */
     public static void broadcastSmsAppChange(Context context,
             UserHandle userHandle, @Nullable String oldPackage, @Nullable String newPackage) {
@@ -723,16 +730,11 @@
         }
 
         // Send an implicit broadcast for the system server.
-        // (or anyone with MONITOR_DEFAULT_SMS_PACKAGE, really.)
+        // (or anyone with PERMISSION_MONITOR_DEFAULT_SMS_PACKAGE, really.)
         final Intent intent =
-                new Intent(Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL);
+                new Intent(ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL);
         context.sendBroadcastAsUser(intent, userHandle,
-                permission.MONITOR_DEFAULT_SMS_PACKAGE);
-
-        if (applicationData != null) {
-            MetricsLogger.action(context, MetricsEvent.ACTION_DEFAULT_SMS_APP_CHANGED,
-                    applicationData.mPackageName);
-        }
+                PERMISSION_MONITOR_DEFAULT_SMS_PACKAGE);
     }
 
     /**
diff --git a/telephony/common/com/android/internal/telephony/SmsNumberUtils.java b/telephony/common/com/android/internal/telephony/SmsNumberUtils.java
index cd365a1..95098e8 100644
--- a/telephony/common/com/android/internal/telephony/SmsNumberUtils.java
+++ b/telephony/common/com/android/internal/telephony/SmsNumberUtils.java
@@ -31,6 +31,7 @@
 
 import com.android.internal.telephony.HbpcdLookup.MccIdd;
 import com.android.internal.telephony.HbpcdLookup.MccLookup;
+import com.android.internal.telephony.util.TelephonyUtils;
 
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
@@ -677,7 +678,7 @@
      */
     private static String secureHash(byte[] input) {
         // Refrain from logging user personal information in user build.
-        if (android.os.Build.IS_USER) {
+        if (TelephonyUtils.IS_USER) {
             return "****";
         }
 
diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index 89cd461..7b3aace7 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -31,7 +31,6 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.util.Log;
-import android.util.StatsLog;
 
 import com.android.internal.annotations.VisibleForTesting;
 
@@ -393,8 +392,8 @@
                 invokedMethods = sReportedDeviceIDPackages.get(callingPackage);
             }
             invokedMethods.add(message);
-            StatsLog.write(StatsLog.DEVICE_IDENTIFIER_ACCESS_DENIED, callingPackage, message,
-                    isPreinstalled, false);
+            TelephonyCommonStatsLog.write(TelephonyCommonStatsLog.DEVICE_IDENTIFIER_ACCESS_DENIED,
+                    callingPackage, message, isPreinstalled, false);
         }
         Log.w(LOG_TAG, "reportAccessDeniedToReadIdentifiers:" + callingPackage + ":" + message
                 + ":isPreinstalled=" + isPreinstalled);
diff --git a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
index a7ad884..6826974 100644
--- a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
+++ b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
@@ -28,6 +28,8 @@
 import android.os.SystemProperties;
 
 import java.io.PrintWriter;
+import java.util.Collections;
+import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Supplier;
@@ -61,6 +63,11 @@
         return str == null ? "" : str;
     }
 
+    /** Returns an empty list if the input is {@code null}. */
+    public static @NonNull <T> List<T> emptyIfNull(@Nullable List<T> cur) {
+        return cur == null ? Collections.emptyList() : cur;
+    }
+
     /** Throws a {@link RuntimeException} that wrapps the {@link RemoteException}. */
     public static RuntimeException rethrowAsRuntimeException(RemoteException remoteException) {
         throw new RuntimeException(remoteException);
diff --git a/telephony/common/com/google/android/mms/ContentType.java b/telephony/common/com/google/android/mms/ContentType.java
index 12e4b7e..4a971dd 100644
--- a/telephony/common/com/google/android/mms/ContentType.java
+++ b/telephony/common/com/google/android/mms/ContentType.java
@@ -17,7 +17,7 @@
 
 package com.google.android.mms;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 
 import java.util.ArrayList;
 
diff --git a/telephony/common/com/google/android/mms/InvalidHeaderValueException.java b/telephony/common/com/google/android/mms/InvalidHeaderValueException.java
index 2836c30..55087ff 100644
--- a/telephony/common/com/google/android/mms/InvalidHeaderValueException.java
+++ b/telephony/common/com/google/android/mms/InvalidHeaderValueException.java
@@ -17,7 +17,7 @@
 
 package com.google.android.mms;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 
 /**
  * Thrown when an invalid header value was set.
diff --git a/telephony/common/com/google/android/mms/MmsException.java b/telephony/common/com/google/android/mms/MmsException.java
index 5be33ed..24bceb3 100644
--- a/telephony/common/com/google/android/mms/MmsException.java
+++ b/telephony/common/com/google/android/mms/MmsException.java
@@ -17,7 +17,7 @@
 
 package com.google.android.mms;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 
 /**
  * A generic exception that is thrown by the Mms client.
diff --git a/telephony/common/com/google/android/mms/pdu/AcknowledgeInd.java b/telephony/common/com/google/android/mms/pdu/AcknowledgeInd.java
index ae447d7..8693385 100644
--- a/telephony/common/com/google/android/mms/pdu/AcknowledgeInd.java
+++ b/telephony/common/com/google/android/mms/pdu/AcknowledgeInd.java
@@ -17,7 +17,7 @@
 
 package com.google.android.mms.pdu;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 
 import com.google.android.mms.InvalidHeaderValueException;
 
diff --git a/telephony/common/com/google/android/mms/pdu/Base64.java b/telephony/common/com/google/android/mms/pdu/Base64.java
index 483fa7f..0d6a46a 100644
--- a/telephony/common/com/google/android/mms/pdu/Base64.java
+++ b/telephony/common/com/google/android/mms/pdu/Base64.java
@@ -17,7 +17,7 @@
 
 package com.google.android.mms.pdu;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 
 public class Base64 {
     /**
diff --git a/telephony/common/com/google/android/mms/pdu/CharacterSets.java b/telephony/common/com/google/android/mms/pdu/CharacterSets.java
index 27da35e..5172b7b 100644
--- a/telephony/common/com/google/android/mms/pdu/CharacterSets.java
+++ b/telephony/common/com/google/android/mms/pdu/CharacterSets.java
@@ -17,7 +17,7 @@
 
 package com.google.android.mms.pdu;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 
 import java.io.UnsupportedEncodingException;
 import java.util.HashMap;
diff --git a/telephony/common/com/google/android/mms/pdu/DeliveryInd.java b/telephony/common/com/google/android/mms/pdu/DeliveryInd.java
index 7093ac6..8fb6a75 100644
--- a/telephony/common/com/google/android/mms/pdu/DeliveryInd.java
+++ b/telephony/common/com/google/android/mms/pdu/DeliveryInd.java
@@ -17,7 +17,7 @@
 
 package com.google.android.mms.pdu;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 
 import com.google.android.mms.InvalidHeaderValueException;
 
diff --git a/telephony/common/com/google/android/mms/pdu/EncodedStringValue.java b/telephony/common/com/google/android/mms/pdu/EncodedStringValue.java
index 4166275..8c0380f 100644
--- a/telephony/common/com/google/android/mms/pdu/EncodedStringValue.java
+++ b/telephony/common/com/google/android/mms/pdu/EncodedStringValue.java
@@ -17,10 +17,9 @@
 
 package com.google.android.mms.pdu;
 
+import android.compat.annotation.UnsupportedAppUsage;
 import android.util.Log;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
diff --git a/telephony/common/com/google/android/mms/pdu/GenericPdu.java b/telephony/common/com/google/android/mms/pdu/GenericPdu.java
index ebf16ac..320b13f 100644
--- a/telephony/common/com/google/android/mms/pdu/GenericPdu.java
+++ b/telephony/common/com/google/android/mms/pdu/GenericPdu.java
@@ -17,7 +17,7 @@
 
 package com.google.android.mms.pdu;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 
 import com.google.android.mms.InvalidHeaderValueException;
 
diff --git a/telephony/common/com/google/android/mms/pdu/MultimediaMessagePdu.java b/telephony/common/com/google/android/mms/pdu/MultimediaMessagePdu.java
index e108f76..42a89c6 100644
--- a/telephony/common/com/google/android/mms/pdu/MultimediaMessagePdu.java
+++ b/telephony/common/com/google/android/mms/pdu/MultimediaMessagePdu.java
@@ -17,7 +17,7 @@
 
 package com.google.android.mms.pdu;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 
 import com.google.android.mms.InvalidHeaderValueException;
 
diff --git a/telephony/common/com/google/android/mms/pdu/NotificationInd.java b/telephony/common/com/google/android/mms/pdu/NotificationInd.java
index b561bd4..ca4615c 100644
--- a/telephony/common/com/google/android/mms/pdu/NotificationInd.java
+++ b/telephony/common/com/google/android/mms/pdu/NotificationInd.java
@@ -17,7 +17,7 @@
 
 package com.google.android.mms.pdu;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 
 import com.google.android.mms.InvalidHeaderValueException;
 
diff --git a/telephony/common/com/google/android/mms/pdu/NotifyRespInd.java b/telephony/common/com/google/android/mms/pdu/NotifyRespInd.java
index 3c70f86..ebd81af 100644
--- a/telephony/common/com/google/android/mms/pdu/NotifyRespInd.java
+++ b/telephony/common/com/google/android/mms/pdu/NotifyRespInd.java
@@ -17,7 +17,7 @@
 
 package com.google.android.mms.pdu;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 
 import com.google.android.mms.InvalidHeaderValueException;
 
diff --git a/telephony/common/com/google/android/mms/pdu/PduBody.java b/telephony/common/com/google/android/mms/pdu/PduBody.java
index 51914e4..f7f285f 100644
--- a/telephony/common/com/google/android/mms/pdu/PduBody.java
+++ b/telephony/common/com/google/android/mms/pdu/PduBody.java
@@ -17,7 +17,7 @@
 
 package com.google.android.mms.pdu;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 
 import java.util.HashMap;
 import java.util.Map;
diff --git a/telephony/common/com/google/android/mms/pdu/PduComposer.java b/telephony/common/com/google/android/mms/pdu/PduComposer.java
index e24bf21..b8b212c 100644
--- a/telephony/common/com/google/android/mms/pdu/PduComposer.java
+++ b/telephony/common/com/google/android/mms/pdu/PduComposer.java
@@ -17,12 +17,11 @@
 
 package com.google.android.mms.pdu;
 
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.text.TextUtils;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
 import java.io.ByteArrayOutputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
diff --git a/telephony/common/com/google/android/mms/pdu/PduContentTypes.java b/telephony/common/com/google/android/mms/pdu/PduContentTypes.java
index 8551b2f..57141fe 100644
--- a/telephony/common/com/google/android/mms/pdu/PduContentTypes.java
+++ b/telephony/common/com/google/android/mms/pdu/PduContentTypes.java
@@ -17,7 +17,7 @@
 
 package com.google.android.mms.pdu;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 
 public class PduContentTypes {
     /**
diff --git a/telephony/common/com/google/android/mms/pdu/PduHeaders.java b/telephony/common/com/google/android/mms/pdu/PduHeaders.java
index b524464..3e62184 100644
--- a/telephony/common/com/google/android/mms/pdu/PduHeaders.java
+++ b/telephony/common/com/google/android/mms/pdu/PduHeaders.java
@@ -17,7 +17,7 @@
 
 package com.google.android.mms.pdu;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 
 import com.google.android.mms.InvalidHeaderValueException;
 
diff --git a/telephony/common/com/google/android/mms/pdu/PduParser.java b/telephony/common/com/google/android/mms/pdu/PduParser.java
index f483994..5340245 100755
--- a/telephony/common/com/google/android/mms/pdu/PduParser.java
+++ b/telephony/common/com/google/android/mms/pdu/PduParser.java
@@ -17,10 +17,9 @@
 
 package com.google.android.mms.pdu;
 
+import android.compat.annotation.UnsupportedAppUsage;
 import android.util.Log;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
 import com.google.android.mms.ContentType;
 import com.google.android.mms.InvalidHeaderValueException;
 
diff --git a/telephony/common/com/google/android/mms/pdu/PduPart.java b/telephony/common/com/google/android/mms/pdu/PduPart.java
index 09b7751..8dd976b 100644
--- a/telephony/common/com/google/android/mms/pdu/PduPart.java
+++ b/telephony/common/com/google/android/mms/pdu/PduPart.java
@@ -17,10 +17,9 @@
 
 package com.google.android.mms.pdu;
 
+import android.compat.annotation.UnsupportedAppUsage;
 import android.net.Uri;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
 import java.util.HashMap;
 import java.util.Map;
 
diff --git a/telephony/common/com/google/android/mms/pdu/PduPersister.java b/telephony/common/com/google/android/mms/pdu/PduPersister.java
index 8efca0e..fcd5b8f 100755
--- a/telephony/common/com/google/android/mms/pdu/PduPersister.java
+++ b/telephony/common/com/google/android/mms/pdu/PduPersister.java
@@ -17,6 +17,7 @@
 
 package com.google.android.mms.pdu;
 
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
@@ -40,8 +41,6 @@
 import android.text.TextUtils;
 import android.util.Log;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
 import com.google.android.mms.ContentType;
 import com.google.android.mms.InvalidHeaderValueException;
 import com.google.android.mms.MmsException;
diff --git a/telephony/common/com/google/android/mms/pdu/QuotedPrintable.java b/telephony/common/com/google/android/mms/pdu/QuotedPrintable.java
index 9d6535c..4e1d7f5 100644
--- a/telephony/common/com/google/android/mms/pdu/QuotedPrintable.java
+++ b/telephony/common/com/google/android/mms/pdu/QuotedPrintable.java
@@ -17,7 +17,7 @@
 
 package com.google.android.mms.pdu;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 
 import java.io.ByteArrayOutputStream;
 
diff --git a/telephony/common/com/google/android/mms/pdu/ReadOrigInd.java b/telephony/common/com/google/android/mms/pdu/ReadOrigInd.java
index e38c62d..4ba3c71 100644
--- a/telephony/common/com/google/android/mms/pdu/ReadOrigInd.java
+++ b/telephony/common/com/google/android/mms/pdu/ReadOrigInd.java
@@ -17,7 +17,7 @@
 
 package com.google.android.mms.pdu;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 
 import com.google.android.mms.InvalidHeaderValueException;
 
diff --git a/telephony/common/com/google/android/mms/pdu/ReadRecInd.java b/telephony/common/com/google/android/mms/pdu/ReadRecInd.java
index 9696bc2..37ccfb9 100644
--- a/telephony/common/com/google/android/mms/pdu/ReadRecInd.java
+++ b/telephony/common/com/google/android/mms/pdu/ReadRecInd.java
@@ -17,7 +17,7 @@
 
 package com.google.android.mms.pdu;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 
 import com.google.android.mms.InvalidHeaderValueException;
 
diff --git a/telephony/common/com/google/android/mms/pdu/RetrieveConf.java b/telephony/common/com/google/android/mms/pdu/RetrieveConf.java
index 03755af..260adfc 100644
--- a/telephony/common/com/google/android/mms/pdu/RetrieveConf.java
+++ b/telephony/common/com/google/android/mms/pdu/RetrieveConf.java
@@ -17,7 +17,7 @@
 
 package com.google.android.mms.pdu;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 
 import com.google.android.mms.InvalidHeaderValueException;
 
diff --git a/telephony/common/com/google/android/mms/pdu/SendConf.java b/telephony/common/com/google/android/mms/pdu/SendConf.java
index b859827..7799238 100644
--- a/telephony/common/com/google/android/mms/pdu/SendConf.java
+++ b/telephony/common/com/google/android/mms/pdu/SendConf.java
@@ -17,7 +17,7 @@
 
 package com.google.android.mms.pdu;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 
 import com.google.android.mms.InvalidHeaderValueException;
 
diff --git a/telephony/common/com/google/android/mms/pdu/SendReq.java b/telephony/common/com/google/android/mms/pdu/SendReq.java
index c1b7f93..6e2f2da 100644
--- a/telephony/common/com/google/android/mms/pdu/SendReq.java
+++ b/telephony/common/com/google/android/mms/pdu/SendReq.java
@@ -17,10 +17,9 @@
 
 package com.google.android.mms.pdu;
 
+import android.compat.annotation.UnsupportedAppUsage;
 import android.util.Log;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
 import com.google.android.mms.InvalidHeaderValueException;
 
 public class SendReq extends MultimediaMessagePdu {
diff --git a/telephony/common/com/google/android/mms/util/AbstractCache.java b/telephony/common/com/google/android/mms/util/AbstractCache.java
index ab5d48a..25862e7 100644
--- a/telephony/common/com/google/android/mms/util/AbstractCache.java
+++ b/telephony/common/com/google/android/mms/util/AbstractCache.java
@@ -17,10 +17,9 @@
 
 package com.google.android.mms.util;
 
+import android.compat.annotation.UnsupportedAppUsage;
 import android.util.Log;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
 import java.util.HashMap;
 
 public abstract class AbstractCache<K, V> {
diff --git a/telephony/common/com/google/android/mms/util/DownloadDrmHelper.java b/telephony/common/com/google/android/mms/util/DownloadDrmHelper.java
index 118de46..0f9390d 100644
--- a/telephony/common/com/google/android/mms/util/DownloadDrmHelper.java
+++ b/telephony/common/com/google/android/mms/util/DownloadDrmHelper.java
@@ -17,12 +17,11 @@
 
 package com.google.android.mms.util;
 
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.drm.DrmManagerClient;
 import android.util.Log;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
 public class DownloadDrmHelper {
     private static final String TAG = "DownloadDrmHelper";
 
diff --git a/telephony/common/com/google/android/mms/util/DrmConvertSession.java b/telephony/common/com/google/android/mms/util/DrmConvertSession.java
index 0e8ec91..17ab1547 100644
--- a/telephony/common/com/google/android/mms/util/DrmConvertSession.java
+++ b/telephony/common/com/google/android/mms/util/DrmConvertSession.java
@@ -16,14 +16,12 @@
  */
 package com.google.android.mms.util;
 
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.drm.DrmConvertedStatus;
 import android.drm.DrmManagerClient;
-import android.provider.Downloads;
 import android.util.Log;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.RandomAccessFile;
@@ -34,6 +32,13 @@
     private int mConvertSessionId;
     private static final String TAG = "DrmConvertSession";
 
+    // These values are copied from Downloads.Impl.* for backward compatibility since
+    // {@link #close()} that uses it is marked @UnsupportedAppUsage.
+    public static final int STATUS_SUCCESS = 200;
+    public static final int STATUS_NOT_ACCEPTABLE = 406;
+    public static final int STATUS_UNKNOWN_ERROR = 491;
+    public static final int STATUS_FILE_ERROR = 492;
+
     private DrmConvertSession(DrmManagerClient drmClient, int convertSessionId) {
         mDrmClient = drmClient;
         mConvertSessionId = convertSessionId;
@@ -119,38 +124,38 @@
      * Ends a conversion session of a file.
      *
      * @param fileName The filename of the converted file.
-     * @return Downloads.Impl.STATUS_SUCCESS if execution is ok.
-     *         Downloads.Impl.STATUS_FILE_ERROR in case converted file can not
-     *         be accessed. Downloads.Impl.STATUS_NOT_ACCEPTABLE if a problem
+     * @return STATUS_SUCCESS if execution is ok.
+     *         STATUS_FILE_ERROR in case converted file can not
+     *         be accessed. STATUS_NOT_ACCEPTABLE if a problem
      *         occurs when accessing drm framework.
-     *         Downloads.Impl.STATUS_UNKNOWN_ERROR if a general error occurred.
+     *         STATUS_UNKNOWN_ERROR if a general error occurred.
      */
     @UnsupportedAppUsage
     public int close(String filename) {
         DrmConvertedStatus convertedStatus = null;
-        int result = Downloads.Impl.STATUS_UNKNOWN_ERROR;
+        int result = STATUS_UNKNOWN_ERROR;
         if (mDrmClient != null && mConvertSessionId >= 0) {
             try {
                 convertedStatus = mDrmClient.closeConvertSession(mConvertSessionId);
                 if (convertedStatus == null ||
                         convertedStatus.statusCode != DrmConvertedStatus.STATUS_OK ||
                         convertedStatus.convertedData == null) {
-                    result = Downloads.Impl.STATUS_NOT_ACCEPTABLE;
+                    result = STATUS_NOT_ACCEPTABLE;
                 } else {
                     RandomAccessFile rndAccessFile = null;
                     try {
                         rndAccessFile = new RandomAccessFile(filename, "rw");
                         rndAccessFile.seek(convertedStatus.offset);
                         rndAccessFile.write(convertedStatus.convertedData);
-                        result = Downloads.Impl.STATUS_SUCCESS;
+                        result = STATUS_SUCCESS;
                     } catch (FileNotFoundException e) {
-                        result = Downloads.Impl.STATUS_FILE_ERROR;
+                        result = STATUS_FILE_ERROR;
                         Log.w(TAG, "File: " + filename + " could not be found.", e);
                     } catch (IOException e) {
-                        result = Downloads.Impl.STATUS_FILE_ERROR;
+                        result = STATUS_FILE_ERROR;
                         Log.w(TAG, "Could not access File: " + filename + " .", e);
                     } catch (IllegalArgumentException e) {
-                        result = Downloads.Impl.STATUS_FILE_ERROR;
+                        result = STATUS_FILE_ERROR;
                         Log.w(TAG, "Could not open file in mode: rw", e);
                     } catch (SecurityException e) {
                         Log.w(TAG, "Access to File: " + filename +
@@ -160,7 +165,7 @@
                             try {
                                 rndAccessFile.close();
                             } catch (IOException e) {
-                                result = Downloads.Impl.STATUS_FILE_ERROR;
+                                result = STATUS_FILE_ERROR;
                                 Log.w(TAG, "Failed to close File:" + filename
                                         + ".", e);
                             }
diff --git a/telephony/common/com/google/android/mms/util/PduCache.java b/telephony/common/com/google/android/mms/util/PduCache.java
index 94e3894..c380d6b 100644
--- a/telephony/common/com/google/android/mms/util/PduCache.java
+++ b/telephony/common/com/google/android/mms/util/PduCache.java
@@ -17,14 +17,13 @@
 
 package com.google.android.mms.util;
 
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ContentUris;
 import android.content.UriMatcher;
 import android.net.Uri;
 import android.provider.Telephony.Mms;
 import android.util.Log;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
 import java.util.HashMap;
 import java.util.HashSet;
 
diff --git a/telephony/common/com/google/android/mms/util/PduCacheEntry.java b/telephony/common/com/google/android/mms/util/PduCacheEntry.java
index 1ecd1bf..a4a25d2 100644
--- a/telephony/common/com/google/android/mms/util/PduCacheEntry.java
+++ b/telephony/common/com/google/android/mms/util/PduCacheEntry.java
@@ -17,7 +17,7 @@
 
 package com.google.android.mms.util;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 
 import com.google.android.mms.pdu.GenericPdu;
 
diff --git a/telephony/common/com/google/android/mms/util/SqliteWrapper.java b/telephony/common/com/google/android/mms/util/SqliteWrapper.java
index 2dd1dc1..4871434 100644
--- a/telephony/common/com/google/android/mms/util/SqliteWrapper.java
+++ b/telephony/common/com/google/android/mms/util/SqliteWrapper.java
@@ -18,6 +18,7 @@
 package com.google.android.mms.util;
 
 import android.app.ActivityManager;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
@@ -27,8 +28,6 @@
 import android.util.Log;
 import android.widget.Toast;
 
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
 public final class SqliteWrapper {
     private static final String TAG = "SqliteWrapper";
     private static final String SQLITE_EXCEPTION_DETAIL_MESSAGE
@@ -61,8 +60,7 @@
     @UnsupportedAppUsage
     public static void checkSQLiteException(Context context, SQLiteException e) {
         if (isLowMemory(e)) {
-            Toast.makeText(context, com.android.internal.R.string.low_memory,
-                    Toast.LENGTH_SHORT).show();
+            Toast.makeText(context, android.R.string.low_memory, Toast.LENGTH_SHORT).show();
         } else {
             throw e;
         }
diff --git a/core/java/android/service/euicc/IEuiccServiceDumpResultCallback.aidl b/telephony/java/android/service/euicc/IEuiccServiceDumpResultCallback.aidl
similarity index 100%
rename from core/java/android/service/euicc/IEuiccServiceDumpResultCallback.aidl
rename to telephony/java/android/service/euicc/IEuiccServiceDumpResultCallback.aidl
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java
index 9e6dfef..d2a5905 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -1,6 +1,7 @@
 package android.telephony;
 
 import android.annotation.IntDef;
+import android.provider.Telephony;
 import android.telecom.Connection;
 import android.telephony.data.ApnSetting;
 
@@ -598,6 +599,48 @@
     }
 
     /**
+     * Call forwarding function status
+     */
+    @IntDef(prefix = { "STATUS_" }, value = {
+        CallForwardingInfo.STATUS_ACTIVE,
+        CallForwardingInfo.STATUS_INACTIVE,
+        CallForwardingInfo.STATUS_UNKNOWN_ERROR,
+        CallForwardingInfo.STATUS_NOT_SUPPORTED,
+        CallForwardingInfo.STATUS_FDN_CHECK_FAILURE
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface CallForwardingStatus {
+    }
+
+    /**
+     * Call forwarding reason types
+     */
+    @IntDef(flag = true, prefix = { "REASON_" }, value = {
+        CallForwardingInfo.REASON_UNCONDITIONAL,
+        CallForwardingInfo.REASON_BUSY,
+        CallForwardingInfo.REASON_NO_REPLY,
+        CallForwardingInfo.REASON_NOT_REACHABLE,
+        CallForwardingInfo.REASON_ALL,
+        CallForwardingInfo.REASON_ALL_CONDITIONAL
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface CallForwardingReason {
+    }
+
+    /**
+     * Call waiting function status
+     */
+    @IntDef(prefix = { "CALL_WAITING_STATUS_" }, value = {
+        TelephonyManager.CALL_WAITING_STATUS_ACTIVE,
+        TelephonyManager.CALL_WAITING_STATUS_INACTIVE,
+        TelephonyManager.CALL_WAITING_STATUS_NOT_SUPPORTED,
+        TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface CallWaitingStatus {
+    }
+
+    /**
      * UICC SIM Application Types
      */
     @IntDef(prefix = { "APPTYPE_" }, value = {
@@ -609,4 +652,13 @@
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface UiccAppType{}
+
+    /** @hide */
+    @IntDef({
+            Telephony.Carriers.SKIP_464XLAT_DEFAULT,
+            Telephony.Carriers.SKIP_464XLAT_DISABLE,
+            Telephony.Carriers.SKIP_464XLAT_ENABLE,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Skip464XlatStatus {}
 }
diff --git a/telephony/java/android/telephony/CallAttributes.java b/telephony/java/android/telephony/CallAttributes.java
index cd830ad..0c258f4 100644
--- a/telephony/java/android/telephony/CallAttributes.java
+++ b/telephony/java/android/telephony/CallAttributes.java
@@ -21,8 +21,8 @@
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
-
 import android.telephony.Annotation.NetworkType;
+
 import java.util.Objects;
 
 /**
@@ -130,14 +130,14 @@
     /**
      * {@link Parcelable#describeContents}
      */
-    public @Parcelable.ContentsFlags int describeContents() {
+    public int describeContents() {
         return 0;
     }
 
     /**
      * {@link Parcelable#writeToParcel}
      */
-    public void writeToParcel(Parcel dest, @Parcelable.WriteFlags int flags) {
+    public void writeToParcel(Parcel dest, int flags) {
         dest.writeParcelable(mPreciseCallState, flags);
         dest.writeInt(mNetworkType);
         dest.writeParcelable(mCallQuality, flags);
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl b/telephony/java/android/telephony/CallForwardingInfo.aidl
similarity index 82%
rename from telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl
rename to telephony/java/android/telephony/CallForwardingInfo.aidl
index e9cbd9c..2019e07 100644
--- a/telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl
+++ b/telephony/java/android/telephony/CallForwardingInfo.aidl
@@ -1,6 +1,5 @@
 /*
- *
- * Copyright 2019, The Android Open Source Project
+ * Copyright (c) 2020, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,6 +14,6 @@
  * limitations under the License.
  */
 
-package android.telephony.ims;
+package android.telephony;
 
-parcelable RcsMessageQueryParams;
+parcelable CallForwardingInfo;
\ No newline at end of file
diff --git a/telephony/java/android/telephony/CallForwardingInfo.java b/telephony/java/android/telephony/CallForwardingInfo.java
new file mode 100644
index 0000000..33ad5e8
--- /dev/null
+++ b/telephony/java/android/telephony/CallForwardingInfo.java
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.telephony.Annotation.CallForwardingReason;
+import android.telephony.Annotation.CallForwardingStatus;
+
+import java.util.Objects;
+
+/**
+ * Defines the call forwarding information.
+ * @hide
+ */
+@SystemApi
+public final class CallForwardingInfo implements Parcelable {
+    private static final String TAG = "CallForwardingInfo";
+
+    /**
+     * Indicates the call forwarding status is inactive.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int STATUS_INACTIVE = 0;
+
+    /**
+     * Indicates the call forwarding status is active.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int STATUS_ACTIVE = 1;
+
+    /**
+     * Indicates the call forwarding could not be enabled because the recipient is not on
+     * Fixed Dialing Number (FDN) list.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int STATUS_FDN_CHECK_FAILURE = 2;
+
+    /**
+     * Indicates the call forwarding status is with an unknown error.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int STATUS_UNKNOWN_ERROR = 3;
+
+    /**
+     * Indicates the call forwarding is not supported (e.g. called via CDMA).
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int STATUS_NOT_SUPPORTED = 4;
+
+    /**
+     * Indicates the call forwarding reason is "unconditional".
+     * Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number
+     *            and conditions +CCFC
+     * @hide
+     */
+    @SystemApi
+    public static final int REASON_UNCONDITIONAL = 0;
+
+    /**
+     * Indicates the call forwarding status is "busy".
+     * Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number
+     *            and conditions +CCFC
+     * @hide
+     */
+    @SystemApi
+    public static final int REASON_BUSY = 1;
+
+    /**
+     * Indicates the call forwarding reason is "no reply".
+     * Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number
+     *            and conditions +CCFC
+     * @hide
+     */
+    @SystemApi
+    public static final int REASON_NO_REPLY = 2;
+
+    /**
+     * Indicates the call forwarding reason is "not reachable".
+     * Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number
+     *            and conditions +CCFC
+     * @hide
+     */
+    @SystemApi
+    public static final int REASON_NOT_REACHABLE = 3;
+
+    /**
+     * Indicates the call forwarding reason is "all", for setting all call forwarding reasons
+     * simultaneously (unconditional, busy, no reply, and not reachable).
+     * Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number
+     *            and conditions +CCFC
+     * @hide
+     */
+    @SystemApi
+    public static final int REASON_ALL = 4;
+
+    /**
+     * Indicates the call forwarding reason is "all_conditional", for setting all conditional call
+     * forwarding reasons simultaneously (busy, no reply, and not reachable).
+     * Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number
+     *            and conditions +CCFC
+     * @hide
+     */
+    @SystemApi
+    public static final int REASON_ALL_CONDITIONAL = 5;
+
+    /**
+     * The call forwarding status.
+     */
+    private @CallForwardingStatus int mStatus;
+
+    /**
+     * The call forwarding reason indicates the condition under which calls will be forwarded.
+     * Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number
+     *            and conditions +CCFC
+     */
+    private @CallForwardingReason int mReason;
+
+    /**
+     * The phone number to which calls will be forwarded.
+     * Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number
+     *            and conditions +CCFC
+     */
+    private String mNumber;
+
+    /**
+     * Gets the timeout (in seconds) before the forwarding is attempted.
+     */
+    private int mTimeSeconds;
+
+    /**
+     * Construct a CallForwardingInfo.
+     *
+     * @param status the call forwarding status
+     * @param reason the call forwarding reason
+     * @param number the phone number to which calls will be forwarded
+     * @param timeSeconds the timeout (in seconds) before the forwarding is attempted
+     * @hide
+     */
+    @SystemApi
+    public CallForwardingInfo(@CallForwardingStatus int status, @CallForwardingReason int reason,
+            @Nullable String number, int timeSeconds) {
+        mStatus = status;
+        mReason = reason;
+        mNumber = number;
+        mTimeSeconds = timeSeconds;
+    }
+
+    /**
+     * Returns the call forwarding status.
+     *
+     * @return the call forwarding status.
+     *
+     * @hide
+     */
+    @SystemApi
+    public @CallForwardingStatus int getStatus() {
+        return mStatus;
+    }
+
+    /**
+     * Returns the call forwarding reason. The call forwarding reason indicates the condition
+     * under which calls will be forwarded.  For example, {@link #REASON_NO_REPLY} indicates
+     * that calls will be forward to {@link #getNumber()} when the user fails to answer the call.
+     *
+     * @return the call forwarding reason.
+     *
+     * @hide
+     */
+    @SystemApi
+    public @CallForwardingReason int getReason() {
+        return mReason;
+    }
+
+    /**
+     * Returns the phone number to which calls will be forwarded.
+     *
+     * @return the number calls will be forwarded to, or {@code null} if call forwarding
+     * is being disabled.
+     *
+     * @hide
+     */
+    @SystemApi
+    @Nullable
+    public String getNumber() {
+        return mNumber;
+    }
+
+    /**
+     * Gets the timeout (in seconds) before the forwarding is attempted. For example,
+     * if {@link #REASON_NO_REPLY} is the call forwarding reason, the device will wait this
+     * duration of time before forwarding the call to {@link #getNumber()}.
+     *
+     * Reference: 3GPP TS 27.007 version 10.3.0 Release 10
+     *            7.11 Call forwarding number and conditions +CCFC
+     *
+     * @return the timeout (in seconds) before the forwarding is attempted.
+     *
+     * @hide
+     */
+    @SystemApi
+    @SuppressLint("MethodNameUnits")
+    public int getTimeoutSeconds() {
+        return mTimeSeconds;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString(mNumber);
+        out.writeInt(mStatus);
+        out.writeInt(mReason);
+        out.writeInt(mTimeSeconds);
+    }
+
+    private CallForwardingInfo(Parcel in) {
+        mNumber = in.readString();
+        mStatus = in.readInt();
+        mReason = in.readInt();
+        mTimeSeconds = in.readInt();
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+
+        if (!(o instanceof CallForwardingInfo)) {
+            return false;
+        }
+
+        CallForwardingInfo other = (CallForwardingInfo) o;
+        return mStatus == other.mStatus
+                && mNumber == other.mNumber
+                && mReason == other.mReason
+                && mTimeSeconds == other.mTimeSeconds;
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public int hashCode() {
+        return Objects.hash(mStatus, mNumber, mReason, mTimeSeconds);
+    }
+
+    public static final @NonNull Parcelable.Creator<CallForwardingInfo> CREATOR =
+            new Parcelable.Creator<CallForwardingInfo>() {
+                @Override
+                public CallForwardingInfo createFromParcel(Parcel in) {
+                    return new CallForwardingInfo(in);
+                }
+
+                @Override
+                public CallForwardingInfo[] newArray(int size) {
+                    return new CallForwardingInfo[size];
+                }
+            };
+
+    /**
+     * @hide
+     */
+    @Override
+    public String toString() {
+        return "[CallForwardingInfo: status=" + mStatus
+                + ", reason= " + mReason
+                + ", timeSec= " + mTimeSeconds + " seconds"
+                + ", number=" + Rlog.pii(TAG, mNumber) + "]";
+    }
+}
diff --git a/telephony/java/android/telephony/CallQuality.java b/telephony/java/android/telephony/CallQuality.java
index 1e1cdba..428a515 100644
--- a/telephony/java/android/telephony/CallQuality.java
+++ b/telephony/java/android/telephony/CallQuality.java
@@ -400,14 +400,14 @@
     /**
      * {@link Parcelable#describeContents}
      */
-    public @Parcelable.ContentsFlags int describeContents() {
+    public int describeContents() {
         return 0;
     }
 
     /**
      * {@link Parcelable#writeToParcel}
      */
-    public void writeToParcel(Parcel dest, @Parcelable.WriteFlags int flags) {
+    public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(mDownlinkCallQualityLevel);
         dest.writeInt(mUplinkCallQualityLevel);
         dest.writeInt(mCallDuration);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index b30f586..945c888 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -4230,26 +4230,26 @@
         sDefaults.putIntArray(KEY_5G_NR_SSRSRP_THRESHOLDS_INT_ARRAY,
                 // Boundaries: [-140 dB, -44 dB]
                 new int[] {
-                    -125, /* SIGNAL_STRENGTH_POOR */
-                    -115, /* SIGNAL_STRENGTH_MODERATE */
-                    -105, /* SIGNAL_STRENGTH_GOOD */
-                    -95,  /* SIGNAL_STRENGTH_GREAT */
+                    -110, /* SIGNAL_STRENGTH_POOR */
+                    -90, /* SIGNAL_STRENGTH_MODERATE */
+                    -80, /* SIGNAL_STRENGTH_GOOD */
+                    -65,  /* SIGNAL_STRENGTH_GREAT */
                 });
         sDefaults.putIntArray(KEY_5G_NR_SSRSRQ_THRESHOLDS_INT_ARRAY,
                 // Boundaries: [-20 dB, -3 dB]
                 new int[] {
-                    -14, /* SIGNAL_STRENGTH_POOR */
-                    -12, /* SIGNAL_STRENGTH_MODERATE */
-                    -10, /* SIGNAL_STRENGTH_GOOD */
-                    -8  /* SIGNAL_STRENGTH_GREAT */
+                    -16, /* SIGNAL_STRENGTH_POOR */
+                    -11, /* SIGNAL_STRENGTH_MODERATE */
+                    -9, /* SIGNAL_STRENGTH_GOOD */
+                    -7  /* SIGNAL_STRENGTH_GREAT */
                 });
         sDefaults.putIntArray(KEY_5G_NR_SSSINR_THRESHOLDS_INT_ARRAY,
                 // Boundaries: [-23 dB, 40 dB]
                 new int[] {
-                    -8, /* SIGNAL_STRENGTH_POOR */
-                    0, /* SIGNAL_STRENGTH_MODERATE */
-                    8, /* SIGNAL_STRENGTH_GOOD */
-                    16  /* SIGNAL_STRENGTH_GREAT */
+                    -5, /* SIGNAL_STRENGTH_POOR */
+                    5, /* SIGNAL_STRENGTH_MODERATE */
+                    15, /* SIGNAL_STRENGTH_GOOD */
+                    30  /* SIGNAL_STRENGTH_GREAT */
                 });
         sDefaults.putInt(KEY_PARAMETERS_USE_FOR_5G_NR_SIGNAL_BAR_INT,
                 CellSignalStrengthNr.USE_SSRSRP);
diff --git a/telephony/java/android/telephony/CellSignalStrengthNr.java b/telephony/java/android/telephony/CellSignalStrengthNr.java
index 4d67bcf..f4c13ff 100644
--- a/telephony/java/android/telephony/CellSignalStrengthNr.java
+++ b/telephony/java/android/telephony/CellSignalStrengthNr.java
@@ -45,28 +45,28 @@
     // Lifted from Default carrier configs and max range of SSRSRP
     // Boundaries: [-140 dB, -44 dB]
     private int[] mSsRsrpThresholds = new int[] {
-            -125, /* SIGNAL_STRENGTH_POOR */
-            -115, /* SIGNAL_STRENGTH_MODERATE */
-            -105, /* SIGNAL_STRENGTH_GOOD */
-            -95,  /* SIGNAL_STRENGTH_GREAT */
+            -110, /* SIGNAL_STRENGTH_POOR */
+            -90, /* SIGNAL_STRENGTH_MODERATE */
+            -80, /* SIGNAL_STRENGTH_GOOD */
+            -65,  /* SIGNAL_STRENGTH_GREAT */
     };
 
     // Lifted from Default carrier configs and max range of SSRSRQ
     // Boundaries: [-20 dB, -3 dB]
     private int[] mSsRsrqThresholds = new int[] {
-            -14, /* SIGNAL_STRENGTH_POOR */
-            -12, /* SIGNAL_STRENGTH_MODERATE */
-            -10, /* SIGNAL_STRENGTH_GOOD */
-            -8  /* SIGNAL_STRENGTH_GREAT */
+            -16, /* SIGNAL_STRENGTH_POOR */
+            -11, /* SIGNAL_STRENGTH_MODERATE */
+            -9, /* SIGNAL_STRENGTH_GOOD */
+            -7  /* SIGNAL_STRENGTH_GREAT */
     };
 
     // Lifted from Default carrier configs and max range of SSSINR
     // Boundaries: [-23 dB, 40 dB]
     private int[] mSsSinrThresholds = new int[] {
-            -8, /* SIGNAL_STRENGTH_POOR */
-            0, /* SIGNAL_STRENGTH_MODERATE */
-            8, /* SIGNAL_STRENGTH_GOOD */
-            16  /* SIGNAL_STRENGTH_GREAT */
+            -5, /* SIGNAL_STRENGTH_POOR */
+            5, /* SIGNAL_STRENGTH_MODERATE */
+            15, /* SIGNAL_STRENGTH_GOOD */
+            30  /* SIGNAL_STRENGTH_GREAT */
     };
 
     /**
diff --git a/telephony/java/android/telephony/ImsManager.java b/telephony/java/android/telephony/ImsManager.java
index 9b4292f..704e5aa 100644
--- a/telephony/java/android/telephony/ImsManager.java
+++ b/telephony/java/android/telephony/ImsManager.java
@@ -27,11 +27,7 @@
 
 /**
  * Provides access to information about Telephony IMS services on the device.
- *
- * @hide
  */
-@SystemApi
-@TestApi
 @SystemService(Context.TELEPHONY_IMS_SERVICE)
 public class ImsManager {
 
@@ -45,7 +41,10 @@
      * <p class="note">
      * Carrier applications may listen to this broadcast to be notified of possible IMS provisioning
      * issues.
+     * @hide
      */
+    @SystemApi
+    @TestApi
     // Moved from TelephonyIntents, need to keep backwards compatibility with OEM apps that have
     // this value hard-coded in BroadcastReceiver.
     @SuppressLint("ActionValue")
@@ -104,7 +103,10 @@
      * @param subscriptionId The ID of the subscription that this ImsRcsManager will use.
      * @throws IllegalArgumentException if the subscription is invalid.
      * @return a ImsRcsManager instance with the specific subscription ID.
+     * @hide
      */
+    @SystemApi
+    @TestApi
     @NonNull
     public ImsRcsManager getImsRcsManager(int subscriptionId) {
         if (!SubscriptionManager.isValidSubscriptionId(subscriptionId)) {
diff --git a/telephony/java/android/telephony/ModemActivityInfo.java b/telephony/java/android/telephony/ModemActivityInfo.java
index aebe780..1ba21f2 100644
--- a/telephony/java/android/telephony/ModemActivityInfo.java
+++ b/telephony/java/android/telephony/ModemActivityInfo.java
@@ -17,7 +17,6 @@
 package android.telephony;
 
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -60,7 +59,7 @@
     private int mRxTimeMs;
 
     public ModemActivityInfo(long timestamp, int sleepTimeMs, int idleTimeMs,
-                        @Nullable int[] txTimeMs, int rxTimeMs) {
+                        @NonNull int[] txTimeMs, int rxTimeMs) {
         mTimestamp = timestamp;
         mSleepTimeMs = sleepTimeMs;
         mIdleTimeMs = idleTimeMs;
@@ -69,13 +68,10 @@
     }
 
     /** helper API to populate tx power range for each bucket **/
-    private void populateTransmitPowerRange(@Nullable int[] transmitPowerMs) {
+    private void populateTransmitPowerRange(@NonNull int[] transmitPowerMs) {
         int i = 0;
-        if (transmitPowerMs != null) {
-            for ( ; i < Math.min(transmitPowerMs.length, TX_POWER_LEVELS); i++) {
-                mTransmitPowerInfo.add(i,
-                        new TransmitPower(TX_POWER_RANGES[i], transmitPowerMs[i]));
-            }
+        for ( ; i < Math.min(transmitPowerMs.length, TX_POWER_LEVELS); i++) {
+            mTransmitPowerInfo.add(i, new TransmitPower(TX_POWER_RANGES[i], transmitPowerMs[i]));
         }
         // Make sure that mTransmitPowerInfo is fully initialized.
         for ( ; i < TX_POWER_LEVELS; i++) {
@@ -98,7 +94,7 @@
         return 0;
     }
 
-    public static final @NonNull Parcelable.Creator<ModemActivityInfo> CREATOR =
+    public static final @android.annotation.NonNull Parcelable.Creator<ModemActivityInfo> CREATOR =
             new Parcelable.Creator<ModemActivityInfo>() {
         public ModemActivityInfo createFromParcel(Parcel in) {
             long timestamp = in.readLong();
@@ -153,7 +149,7 @@
     }
 
     /** @hide */
-    public void setTransmitTimeMillis(@Nullable int[] txTimeMs) {
+    public void setTransmitTimeMillis(int[] txTimeMs) {
         populateTransmitPowerRange(txTimeMs);
     }
 
diff --git a/telephony/java/android/telephony/PhoneCapability.java b/telephony/java/android/telephony/PhoneCapability.java
index 90244b3..a537928 100644
--- a/telephony/java/android/telephony/PhoneCapability.java
+++ b/telephony/java/android/telephony/PhoneCapability.java
@@ -25,7 +25,7 @@
 import android.telephony.AccessNetworkConstants.RadioAccessNetworkType;
 import android.telephony.TelephonyManager.NetworkTypeBitMask;
 
-import com.android.internal.util.CollectionUtils;
+import com.android.internal.telephony.util.TelephonyUtils;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -181,13 +181,13 @@
         this.mEutranUeCategoryUl = eutranUeCategoryUl;
         this.mPsDataConnectionLingerTimeMillis = psDataConnectionLingerTimeMillis;
         this.mSupportedRats = supportedRats;
-        this.mGeranBands = CollectionUtils.emptyIfNull(geranBands);
-        this.mUtranBands = CollectionUtils.emptyIfNull(utranBands);
-        this.mEutranBands = CollectionUtils.emptyIfNull(eutranBands);
-        this.mNgranBands = CollectionUtils.emptyIfNull(ngranBands);
-        this.mLogicalModemUuids = CollectionUtils.emptyIfNull(logicalModemUuids);
-        this.mSimSlotCapabilities = CollectionUtils.emptyIfNull(simSlotCapabilities);
-        this.mConcurrentFeaturesSupport = CollectionUtils.emptyIfNull(concurrentFeaturesSupport);
+        this.mGeranBands = TelephonyUtils.emptyIfNull(geranBands);
+        this.mUtranBands = TelephonyUtils.emptyIfNull(utranBands);
+        this.mEutranBands = TelephonyUtils.emptyIfNull(eutranBands);
+        this.mNgranBands = TelephonyUtils.emptyIfNull(ngranBands);
+        this.mLogicalModemUuids = TelephonyUtils.emptyIfNull(logicalModemUuids);
+        this.mSimSlotCapabilities = TelephonyUtils.emptyIfNull(simSlotCapabilities);
+        this.mConcurrentFeaturesSupport = TelephonyUtils.emptyIfNull(concurrentFeaturesSupport);
     }
 
     private PhoneCapability(Parcel in) {
@@ -429,14 +429,14 @@
     /**
      * {@link Parcelable#describeContents}
      */
-    public @Parcelable.ContentsFlags int describeContents() {
+    public int describeContents() {
         return 0;
     }
 
     /**
      * {@link Parcelable#writeToParcel}
      */
-    public void writeToParcel(@NonNull Parcel dest, @Parcelable.WriteFlags int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeInt(mUtranUeCategoryDl);
         dest.writeInt(mUtranUeCategoryUl);
         dest.writeInt(mEutranUeCategoryDl);
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 1e64a81..5b09cd9 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -317,6 +317,14 @@
      */
     public static final int UNKNOWN_ID = -1;
 
+    /**
+     * A parcelable extra used with {@link Intent#ACTION_SERVICE_STATE} representing the service
+     * state.
+     * @hide
+     */
+    private static final String EXTRA_SERVICE_STATE = "android.intent.extra.SERVICE_STATE";
+
+
     private String mOperatorAlphaLong;
     private String mOperatorAlphaShort;
     private String mOperatorNumeric;
@@ -1292,7 +1300,7 @@
      */
     @UnsupportedAppUsage
     private void setFromNotifierBundle(Bundle m) {
-        ServiceState ssFromBundle = m.getParcelable(Intent.EXTRA_SERVICE_STATE);
+        ServiceState ssFromBundle = m.getParcelable(EXTRA_SERVICE_STATE);
         if (ssFromBundle != null) {
             copyFrom(ssFromBundle);
         }
@@ -1310,7 +1318,7 @@
      */
     @SystemApi
     public void fillInNotifierBundle(@NonNull Bundle m) {
-        m.putParcelable(Intent.EXTRA_SERVICE_STATE, this);
+        m.putParcelable(EXTRA_SERVICE_STATE, this);
         // serviceState already consists of below entries.
         // for backward compatibility, we continue fill in below entries.
         m.putInt("voiceRegState", mVoiceRegState);
diff --git a/telephony/java/android/telephony/SimSlotCapability.java b/telephony/java/android/telephony/SimSlotCapability.java
index 3d38d04..b4fef46 100644
--- a/telephony/java/android/telephony/SimSlotCapability.java
+++ b/telephony/java/android/telephony/SimSlotCapability.java
@@ -105,14 +105,14 @@
     /**
      * {@link Parcelable#describeContents}
      */
-    public @ContentsFlags int describeContents() {
+    public int describeContents() {
         return 0;
     }
 
     /**
      * {@link Parcelable#writeToParcel}
      */
-    public void writeToParcel(@NonNull Parcel dest, @WriteFlags int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeInt(mPhysicalSlotIndex);
         dest.writeInt(mSlotType);
     }
diff --git a/telephony/java/android/telephony/SmsCbMessage.java b/telephony/java/android/telephony/SmsCbMessage.java
index 3c67094..c0dfec9 100644
--- a/telephony/java/android/telephony/SmsCbMessage.java
+++ b/telephony/java/android/telephony/SmsCbMessage.java
@@ -177,6 +177,9 @@
     @Nullable
     private final String mLanguage;
 
+    /** The 8-bit data coding scheme defined in 3GPP TS 23.038 section 4. */
+    private final int mDataCodingScheme;
+
     /** Message body, as a String. */
     @Nullable
     private final String mBody;
@@ -220,7 +223,7 @@
             @Nullable SmsCbCmasInfo cmasWarningInfo, int slotIndex, int subId) {
 
         this(messageFormat, geographicalScope, serialNumber, location, serviceCategory, language,
-                body, priority, etwsWarningInfo, cmasWarningInfo, 0 /* maximumWaitingTime */,
+                0, body, priority, etwsWarningInfo, cmasWarningInfo, 0 /* maximumWaitingTime */,
                 null /* geometries */, System.currentTimeMillis(), slotIndex, subId);
     }
 
@@ -230,8 +233,8 @@
      */
     public SmsCbMessage(int messageFormat, int geographicalScope, int serialNumber,
                         @NonNull SmsCbLocation location, int serviceCategory,
-                        @Nullable String language, @Nullable String body, int priority,
-                        @Nullable SmsCbEtwsInfo etwsWarningInfo,
+                        @Nullable String language, int dataCodingScheme, @Nullable String body,
+                        int priority, @Nullable SmsCbEtwsInfo etwsWarningInfo,
                         @Nullable SmsCbCmasInfo cmasWarningInfo, int maximumWaitTimeSec,
                         @Nullable List<Geometry> geometries, long receivedTimeMillis, int slotIndex,
                         int subId) {
@@ -241,6 +244,7 @@
         mLocation = location;
         mServiceCategory = serviceCategory;
         mLanguage = language;
+        mDataCodingScheme = dataCodingScheme;
         mBody = body;
         mPriority = priority;
         mEtwsWarningInfo = etwsWarningInfo;
@@ -263,6 +267,7 @@
         mLocation = new SmsCbLocation(in);
         mServiceCategory = in.readInt();
         mLanguage = in.readString();
+        mDataCodingScheme = in.readInt();
         mBody = in.readString();
         mPriority = in.readInt();
         int type = in.readInt();
@@ -305,6 +310,7 @@
         mLocation.writeToParcel(dest, flags);
         dest.writeInt(mServiceCategory);
         dest.writeString(mLanguage);
+        dest.writeInt(mDataCodingScheme);
         dest.writeString(mBody);
         dest.writeInt(mPriority);
         if (mEtwsWarningInfo != null) {
@@ -398,6 +404,15 @@
     }
 
     /**
+     * Get data coding scheme of the message
+     *
+     * @return The 8-bit data coding scheme defined in 3GPP TS 23.038 section 4.
+     */
+    public int getDataCodingScheme() {
+        return mDataCodingScheme;
+    }
+
+    /**
      * Get the body of this message, or null if no body available
      *
      * @return Body, or null
@@ -718,7 +733,7 @@
                 cursor.getColumnIndexOrThrow(CellBroadcasts.MAXIMUM_WAIT_TIME));
 
         return new SmsCbMessage(format, geoScope, serialNum, location, category,
-                language, body, priority, etwsInfo, cmasInfo, maximumWaitTimeSec, geometries,
+                language, 0, body, priority, etwsInfo, cmasInfo, maximumWaitTimeSec, geometries,
                 receivedTimeMillis, slotIndex, subId);
     }
 
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 63a85fa2..4da3a54 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -54,6 +54,7 @@
 import android.os.ParcelUuid;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.provider.Telephony.SimInfo;
 import android.telephony.euicc.EuiccManager;
 import android.telephony.ims.ImsMmTelManager;
@@ -515,13 +516,6 @@
     public static final String ISO_COUNTRY_CODE = SimInfo.ISO_COUNTRY_CODE;
 
     /**
-     * TelephonyProvider column name for the sim provisioning status associated with a SIM.
-     * <P>Type: INTEGER (int)</P>
-     * @hide
-     */
-    public static final String SIM_PROVISIONING_STATUS = SimInfo.SIM_PROVISIONING_STATUS;
-
-    /**
      * TelephonyProvider column name for whether a subscription is embedded (that is, present on an
      * eSIM).
      * <p>Type: INTEGER (int), 1 for embedded or 0 for non-embedded.
@@ -677,6 +671,13 @@
     public static final String WFC_IMS_ROAMING_ENABLED = SimInfo.WFC_IMS_ROAMING_ENABLED;
 
     /**
+     * Determines if the user has enabled IMS RCS User Capability Exchange (UCE) for this
+     * subscription.
+     * @hide
+     */
+    public static final String IMS_RCS_UCE_ENABLED = SimInfo.IMS_RCS_UCE_ENABLED;
+
+    /**
      * TelephonyProvider column name for whether a subscription is opportunistic, that is,
      * whether the network it connects to is limited in functionality or coverage.
      * For example, CBRS.
@@ -976,10 +977,7 @@
     private INetworkPolicyManager getINetworkPolicyManager() {
         if (mNetworkPolicy == null) {
             mNetworkPolicy = INetworkPolicyManager.Stub.asInterface(
-                    TelephonyFrameworkInitializer
-                            .getTelephonyServiceManager()
-                            .getNetworkPolicyServiceRegisterer()
-                            .get());
+                    ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
         }
         return mNetworkPolicy;
     }
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 903be6f..26dc5f0 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -69,7 +69,9 @@
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
 import android.telephony.Annotation.ApnType;
+import android.telephony.Annotation.CallForwardingReason;
 import android.telephony.Annotation.CallState;
+import android.telephony.Annotation.CallWaitingStatus;
 import android.telephony.Annotation.NetworkType;
 import android.telephony.Annotation.RadioPowerState;
 import android.telephony.Annotation.SimActivationState;
@@ -99,7 +101,6 @@
 import com.android.internal.telephony.IPhoneSubInfo;
 import com.android.internal.telephony.ISetOpportunisticDataCallback;
 import com.android.internal.telephony.ITelephony;
-import com.android.internal.telephony.ITelephonyRegistry;
 import com.android.internal.telephony.IUpdateAvailableNetworksCallback;
 import com.android.internal.telephony.OperatorInfo;
 import com.android.internal.telephony.PhoneConstants;
@@ -5624,14 +5625,6 @@
                 .getTelephonyServiceManager().getTelephonyServiceRegisterer().get());
     }
 
-    private ITelephonyRegistry getTelephonyRegistry() {
-        return ITelephonyRegistry.Stub.asInterface(
-                TelephonyFrameworkInitializer
-                        .getTelephonyServiceManager()
-                        .getTelephonyRegistryServiceRegisterer()
-                        .get());
-    }
-
     private IOns getIOns() {
         return IOns.Stub.asInterface(
                 TelephonyFrameworkInitializer
@@ -5647,13 +5640,6 @@
     //
 
     /**
-     * To check the SDK version for {@link TelephonyManager#listen}.
-     */
-    @ChangeId
-    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.P)
-    private static final long LISTEN_CODE_CHANGE = 147600208L;
-
-    /**
      * Registers a listener object to receive notification of changes
      * in specified telephony states.
      * <p>
@@ -5685,29 +5671,15 @@
      */
     public void listen(PhoneStateListener listener, int events) {
         if (mContext == null) return;
-        try {
-            boolean notifyNow = (getITelephony() != null);
-            ITelephonyRegistry registry = getTelephonyRegistry();
-            if (registry != null) {
-                // subId from PhoneStateListener is deprecated Q on forward, use the subId from
-                // TelephonyManager instance. keep using subId from PhoneStateListener for pre-Q.
-                int subId = mSubId;
-                if (Compatibility.isChangeEnabled(LISTEN_CODE_CHANGE)) {
-                    // since mSubId in PhoneStateListener is deprecated from Q on forward, this is
-                    // the only place to set mSubId and its for "informational" only.
-                    //  TODO: remove this once we completely get rid of mSubId in PhoneStateListener
-                    listener.mSubId = (events == PhoneStateListener.LISTEN_NONE)
-                            ? SubscriptionManager.INVALID_SUBSCRIPTION_ID : subId;
-                } else if (listener.mSubId != null) {
-                    subId = listener.mSubId;
-                }
-                registry.listenForSubscriber(subId, getOpPackageName(), getFeatureId(),
-                        listener.callback, events, notifyNow);
-            } else {
-                Rlog.w(TAG, "telephony registry not ready.");
-            }
-        } catch (RemoteException ex) {
-            // system process dead
+        boolean notifyNow = (getITelephony() != null);
+        TelephonyRegistryManager telephonyRegistry =
+                (TelephonyRegistryManager)
+                        mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
+        if (telephonyRegistry != null) {
+            telephonyRegistry.listenForSubscriber(mSubId, getOpPackageName(), getFeatureId(),
+                    listener, events, notifyNow);
+        } else {
+            Rlog.w(TAG, "telephony registry not ready.");
         }
     }
 
@@ -5723,7 +5695,7 @@
     @NonNull
     public CdmaEriInformation getCdmaEriInformation() {
         return new CdmaEriInformation(
-               getCdmaEriIconMode(getSubId()), getCdmaEriIconIndex(getSubId()));
+               getCdmaEriIconIndex(getSubId()), getCdmaEriIconMode(getSubId()));
     }
 
     /**
@@ -7359,6 +7331,30 @@
         }
     }
 
+
+    /**
+     * Resets the {@link android.telephony.ims.ImsService} associated with the specified sim slot.
+     * Used by diagnostic apps to force the IMS stack to be disabled and re-enabled in an effort to
+     * recover from scenarios where the {@link android.telephony.ims.ImsService} gets in to a bad
+     * state.
+     *
+     * @param slotIndex the sim slot to reset the IMS stack on.
+     * @hide */
+    @SystemApi
+    @WorkerThread
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public void resetIms(int slotIndex) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                telephony.resetIms(slotIndex);
+            }
+        } catch (RemoteException e) {
+            Rlog.e(TAG, "toggleImsOnOff, RemoteException: "
+                    + e.getMessage());
+        }
+    }
+
     /**
      * Enables IMS for the framework. This will trigger IMS registration and ImsFeature capability
      * status updates, if not already enabled.
@@ -12752,6 +12748,191 @@
     }
 
     /**
+     * Gets the voice call forwarding info {@link CallForwardingInfo}, given the call forward
+     * reason.
+     *
+     * @param callForwardingReason the call forwarding reasons
+     *
+     * @throws IllegalArgumentException if callForwardingReason is not any of
+     * {@link CallForwardingInfo.REASON_UNCONDITIONAL}, {@link CallForwardingInfo.REASON_BUSY},
+     * {@link CallForwardingInfo.REASON_NO_REPLY}, {@link CallForwardingInfo.REASON_NOT_REACHABLE},
+     * {@link CallForwardingInfo.REASON_ALL}, {@link CallForwardingInfo.REASON_ALL_CONDITIONAL}
+     *
+     * @return {@link CallForwardingInfo} with the status {@link CallForwardingInfo#STATUS_ACTIVE}
+     * or {@link CallForwardingInfo#STATUS_INACTIVE} and the target phone number to forward calls
+     * to, if it's available. Otherwise, it will return a {@link CallForwardingInfo} with status
+     * {@link CallForwardingInfo#STATUS_UNKNOWN_ERROR},
+     * {@link CallForwardingInfo#STATUS_NOT_SUPPORTED},
+     * or {@link CallForwardingInfo#STATUS_FDN_CHECK_FAILURE} depending on the situation.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    @NonNull
+    public CallForwardingInfo getCallForwarding(@CallForwardingReason int callForwardingReason) {
+        if (callForwardingReason < CallForwardingInfo.REASON_UNCONDITIONAL
+                || callForwardingReason > CallForwardingInfo.REASON_ALL_CONDITIONAL) {
+            throw new IllegalArgumentException("callForwardingReason is out of range");
+        }
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.getCallForwarding(getSubId(), callForwardingReason);
+            }
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "getCallForwarding RemoteException", ex);
+        } catch (NullPointerException ex) {
+            Rlog.e(TAG, "getCallForwarding NPE", ex);
+        }
+        return new CallForwardingInfo(
+                CallForwardingInfo.STATUS_UNKNOWN_ERROR, 0 /* reason */, null /* number */,
+                        0 /* timeout */);
+    }
+
+    /**
+     * Sets the voice call forwarding info including status (enable/disable), call forwarding
+     * reason, the number to forward, and the timeout before the forwarding is attempted.
+     *
+     * @param callForwardingInfo {@link CallForwardingInfo} to setup the call forwarding.
+     * Enabling if {@link CallForwardingInfo#getStatus()} returns
+     * {@link CallForwardingInfo#STATUS_ACTIVE}; Disabling if
+     * {@link CallForwardingInfo#getStatus()} returns {@link CallForwardingInfo#STATUS_INACTIVE}.
+     *
+     * @throws IllegalArgumentException if any of the following for parameter callForwardingInfo:
+     * 0) it is {@code null}.
+     * 1) {@link CallForwardingInfo#getStatus()} returns neither
+     * {@link CallForwardingInfo#STATUS_ACTIVE} nor {@link CallForwardingInfo#STATUS_INACTIVE}.
+     * 2) {@link CallForwardingInfo#getReason()} is not any of
+     * {@link CallForwardingInfo.REASON_UNCONDITIONAL}, {@link CallForwardingInfo.REASON_BUSY},
+     * {@link CallForwardingInfo.REASON_NO_REPLY}, {@link CallForwardingInfo.REASON_NOT_REACHABLE},
+     * {@link CallForwardingInfo.REASON_ALL}, {@link CallForwardingInfo.REASON_ALL_CONDITIONAL}
+     * 3) {@link CallForwardingInfo#getNumber()} returns {@code null}.
+     * 4) {@link CallForwardingInfo#getTimeoutSeconds()} doesn't return a positive value.
+     *
+     * @return {@code true} to indicate it was set successfully; {@code false} otherwise.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public boolean setCallForwarding(@NonNull CallForwardingInfo callForwardingInfo) {
+        if (callForwardingInfo == null) {
+            throw new IllegalArgumentException("callForwardingInfo is null");
+        }
+        int callForwardingStatus = callForwardingInfo.getStatus();
+        if (callForwardingStatus != CallForwardingInfo.STATUS_ACTIVE
+                && callForwardingStatus != CallForwardingInfo.STATUS_INACTIVE) {
+            throw new IllegalArgumentException(
+                    "callForwardingStatus is neither active nor inactive");
+        }
+        int callForwardingReason = callForwardingInfo.getReason();
+        if (callForwardingReason < CallForwardingInfo.REASON_UNCONDITIONAL
+                || callForwardingReason > CallForwardingInfo.REASON_ALL_CONDITIONAL) {
+            throw new IllegalArgumentException("callForwardingReason is out of range");
+        }
+        if (callForwardingInfo.getNumber() == null) {
+            throw new IllegalArgumentException("callForwarding number is null");
+        }
+        if (callForwardingInfo.getTimeoutSeconds() <= 0) {
+            throw new IllegalArgumentException("callForwarding timeout isn't positive");
+        }
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.setCallForwarding(getSubId(), callForwardingInfo);
+            }
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "setCallForwarding RemoteException", ex);
+        } catch (NullPointerException ex) {
+            Rlog.e(TAG, "setCallForwarding NPE", ex);
+        }
+        return false;
+    }
+
+    /**
+     * Indicates the call waiting status is active.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int CALL_WAITING_STATUS_ACTIVE = 1;
+
+    /**
+     * Indicates the call waiting status is inactive.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int CALL_WAITING_STATUS_INACTIVE = 2;
+
+    /**
+     * Indicates the call waiting status is with an unknown error.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int CALL_WAITING_STATUS_UNKNOWN_ERROR = 3;
+
+    /**
+     * Indicates the call waiting is not supported (e.g. called via CDMA).
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int CALL_WAITING_STATUS_NOT_SUPPORTED = 4;
+
+    /**
+     * Gets the status of voice call waiting function. Call waiting function enables the waiting
+     * for the incoming call when it reaches the user who is busy to make another call and allows
+     * users to decide whether to switch to the incoming call.
+     *
+     * @return the status of call waiting function.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public @CallWaitingStatus int getCallWaitingStatus() {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.getCallWaitingStatus(getSubId());
+            }
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "getCallWaitingStatus RemoteException", ex);
+        } catch (NullPointerException ex) {
+            Rlog.e(TAG, "getCallWaitingStatus NPE", ex);
+        }
+        return CALL_WAITING_STATUS_UNKNOWN_ERROR;
+    }
+
+    /**
+     * Sets the status for voice call waiting function. Call waiting function enables the waiting
+     * for the incoming call when it reaches the user who is busy to make another call and allows
+     * users to decide whether to switch to the incoming call.
+     *
+     * @param isEnable {@code true} to enable; {@code false} to disable.
+     * @return {@code true} to indicate it was set successfully; {@code false} otherwise.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public boolean setCallWaitingStatus(boolean isEnable) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.setCallWaitingStatus(getSubId(), isEnable);
+            }
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "setCallWaitingStatus RemoteException", ex);
+        } catch (NullPointerException ex) {
+            Rlog.e(TAG, "setCallWaitingStatus NPE", ex);
+        }
+        return false;
+    }
+
+    /**
      * Set allowing mobile data during voice call. This is used for allowing data on the non-default
      * data SIM. When a voice call is placed on the non-default data SIM on DSDS devices, users will
      * not be able to use mobile data. By calling this API, data will be temporarily enabled on the
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index 7896320..f5dfacc6 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -27,6 +27,7 @@
 import android.os.Parcelable;
 import android.provider.Telephony;
 import android.provider.Telephony.Carriers;
+import android.telephony.Annotation;
 import android.telephony.Annotation.ApnType;
 import android.telephony.Annotation.NetworkType;
 import android.telephony.ServiceState;
@@ -744,7 +745,7 @@
      * @return SKIP_464XLAT_DEFAULT, SKIP_464XLAT_DISABLE or SKIP_464XLAT_ENABLE
      * @hide
      */
-    @Carriers.Skip464XlatStatus
+    @Annotation.Skip464XlatStatus
     public int getSkip464Xlat() {
         return mSkip464Xlat;
     }
@@ -2061,10 +2062,10 @@
         /**
          * Sets skip464xlat flag for this APN.
          *
-         * @param skip464xlat skip464xlat for this APN
+         * @param skip464xlat skip464xlat for this APN.
          * @hide
          */
-        public Builder setSkip464Xlat(@Carriers.Skip464XlatStatus int skip464xlat) {
+        public Builder setSkip464Xlat(@Annotation.Skip464XlatStatus int skip464xlat) {
             this.mSkip464Xlat = skip464xlat;
             return this;
         }
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index 27a7022..7488a1a 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -38,6 +38,9 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * EuiccManager is the application interface to eUICCs, or eSIMs/embedded SIMs.
@@ -254,27 +257,38 @@
      * the error is related to download.Since the OperationCode only uses at most one byte, the
      * maximum allowed quantity is 255(0xFF).
      *
-     * ErrorCode is the remaing three bytes of the result code, and it denotes what happened.
+     * ErrorCode is the remaining three bytes of the result code, and it denotes what happened.
      * e.g a combination of {@link #OPERATION_DOWNLOAD} and {@link #ERROR_TIME_OUT} will suggest the
      * download operation has timed out. The only exception here is
      * {@link #OPERATION_SMDX_SUBJECT_REASON_CODE}, where instead of ErrorCode, SubjectCode[5.2.6.1
      * from GSMA (SGP.22 v2.2) and ReasonCode[5.2.6.2] from GSMA (SGP.22 v2.2) are encoded. @see
      * {@link #EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_SUBJECT_CODE} and
      * {@link #EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_REASON_CODE}
+     *
+     * In the case where ErrorCode contains a value of 0, it means it's an unknown error. E.g Intent
+     * only contains {@link #OPERATION_DOWNLOAD} and ErrorCode is 0 implies this is an unknown
+     * Download error.
+     *
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_OPERATION_CODE}
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_ERROR_CODE}
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_SUBJECT_CODE}
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_REASON_CODE}
      */
     public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE =
             "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DETAILED_CODE";
 
     /**
      * Key for an extra set on {@link PendingIntent} result callbacks providing a
-     * OperationCode of {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE}.
+     * OperationCode of {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE},
+     * value will be an int.
      */
     public static final String EXTRA_EMBEDDED_SUBSCRIPTION_OPERATION_CODE =
             "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_OPERATION_CODE";
 
     /**
      * Key for an extra set on {@link PendingIntent} result callbacks providing a
-     * ErrorCode of {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE}.
+     * ErrorCode of {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE},
+     * value will be an int.
      */
     public static final String EXTRA_EMBEDDED_SUBSCRIPTION_ERROR_CODE =
             "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_ERROR_CODE";
@@ -283,6 +297,7 @@
      * Key for an extra set on {@link PendingIntent} result callbacks providing a
      * SubjectCode[5.2.6.1] from GSMA (SGP.22 v2.2) decoded from
      * {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE}.
+     * The value of this extra will be a String.
      */
     public static final String EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_SUBJECT_CODE =
             "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_SMDX_SUBJECT_CODE";
@@ -291,6 +306,7 @@
      * Key for an extra set on {@link PendingIntent} result callbacks providing a
      * ReasonCode[5.2.6.2] from GSMA (SGP.22 v2.2) decoded from
      * {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE}.
+     * The value of this extra will be a String.
      */
     public static final String EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_REASON_CODE =
             "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_SMDX_REASON_CODE";
@@ -665,7 +681,7 @@
             ERROR_EUICC_MISSING,
             ERROR_UNSUPPORTED_VERSION,
             ERROR_SIM_MISSING,
-            ERROR_EUICC_GSMA_INSTALL_ERROR,
+            ERROR_INSTALL_PROFILE,
             ERROR_DISALLOWED_BY_PPR,
             ERROR_ADDRESS_MISSING,
             ERROR_CERTIFICATE_ERROR,
@@ -733,14 +749,14 @@
     public static final int ERROR_SIM_MISSING = 10008;
 
     /**
-     * Failure to load the profile onto the eUICC card. i.e
+     * Failure to load the profile onto the eUICC card. e.g
      * 1. iccid of the profile already exists on the eUICC.
      * 2. GSMA(.22 v2.2) Profile Install Result - installFailedDueToDataMismatch
      * 3. operation was interrupted
      * 4. SIMalliance error in PEStatus(SGP.22 v2.2 section 2.5.6.1)
      * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
      */
-    public static final int ERROR_EUICC_GSMA_INSTALL_ERROR = 10009;
+    public static final int ERROR_INSTALL_PROFILE = 10009;
 
     /**
      * Failed to load profile onto eUICC due to Profile Poicly Rules.
@@ -1235,6 +1251,138 @@
     }
 
     /**
+     * Sets the supported countries for eUICC.
+     *
+     * <p>Requires that the calling app has the
+     * {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
+     *
+     * <p>The supported country list will be replaced by {@code supportedCountries}. For how we
+     * determine whether a country is supported please check {@link #isSupportedCountry}.
+     *
+     * @param supportedCountries is a list of strings contains country ISO codes in uppercase.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
+    public void setSupportedCountries(@NonNull List<String> supportedCountries) {
+        if (!isEnabled()) {
+            return;
+        }
+        try {
+            getIEuiccController().setSupportedCountries(
+                    true /* isSupported */,
+                    supportedCountries.stream()
+                        .map(String::toUpperCase).collect(Collectors.toList()));
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Sets the unsupported countries for eUICC.
+     *
+     * <p>Requires that the calling app has the
+     * {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
+     *
+     * <p>The unsupported country list will be replaced by {@code unsupportedCountries}. For how we
+     * determine whether a country is supported please check {@link #isSupportedCountry}.
+     *
+     * @param unsupportedCountries is a list of strings contains country ISO codes in uppercase.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
+    public void setUnsupportedCountries(@NonNull List<String> unsupportedCountries) {
+        if (!isEnabled()) {
+            return;
+        }
+        try {
+            getIEuiccController().setSupportedCountries(
+                    false /* isSupported */,
+                    unsupportedCountries.stream()
+                        .map(String::toUpperCase).collect(Collectors.toList()));
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Gets the supported countries for eUICC.
+     *
+     * <p>Requires that the calling app has the
+     * {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
+     *
+     * @return list of strings contains country ISO codes in uppercase.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
+    @NonNull
+    public List<String> getSupportedCountries() {
+        if (!isEnabled()) {
+            return Collections.emptyList();
+        }
+        try {
+            return getIEuiccController().getSupportedCountries(true /* isSupported */);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Gets the unsupported countries for eUICC.
+     *
+     * <p>Requires that the calling app has the
+     * {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
+     *
+     * @return list of strings contains country ISO codes in uppercase.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
+    @NonNull
+    public List<String> getUnsupportedCountries() {
+        if (!isEnabled()) {
+            return Collections.emptyList();
+        }
+        try {
+            return getIEuiccController().getSupportedCountries(false /* isSupported */);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns whether the given country supports eUICC.
+     *
+     * <p>Supported country list has a higher prority than unsupported country list. If the
+     * supported country list is not empty, {@code countryIso} will be considered as supported when
+     * it exists in the supported country list. Otherwise {@code countryIso} is not supported. If
+     * the supported country list is empty, {@code countryIso} will be considered as supported if it
+     * does not exist in the unsupported country list. Otherwise {@code countryIso} is not
+     * supported. If both supported and unsupported country lists are empty, then all countries are
+     * consider be supported. For how to set supported and unsupported country list, please check
+     * {@link #setSupportedCountries} and {@link #setUnsupportedCountries}.
+     *
+     * @param countryIso should be the ISO-3166 country code is provided in uppercase 2 character
+     * format.
+     * @return whether the given country supports eUICC or not.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
+    public boolean isSupportedCountry(@NonNull String countryIso) {
+        if (!isEnabled()) {
+            return false;
+        }
+        try {
+            return getIEuiccController().isSupportedCountry(countryIso.toUpperCase());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Refreshes the cardId if its uninitialized, and returns whether we should continue the
      * operation.
      * <p>
diff --git a/telephony/java/android/telephony/ims/ImsException.java b/telephony/java/android/telephony/ims/ImsException.java
index cb3f0f9..643f452 100644
--- a/telephony/java/android/telephony/ims/ImsException.java
+++ b/telephony/java/android/telephony/ims/ImsException.java
@@ -61,7 +61,6 @@
      * This is a configuration error and there should be no retry. The subscription used for this
      * operation is either invalid or has become inactive. The active subscriptions can be queried
      * with {@link SubscriptionManager#getActiveSubscriptionInfoList()}.
-     * @hide
      */
     public static final int CODE_ERROR_INVALID_SUBSCRIPTION = 3;
 
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index 5fdef83..3341fa7 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -56,7 +56,8 @@
  * registration and MmTel capability status callbacks, as well as query/modify user settings for the
  * associated subscription.
  *
- * @see #createForSubscriptionId(int)
+ * Use {@link android.telephony.ims.ImsManager#getImsMmTelManager(int)} to get an instance of this
+ * manager.
  */
 public class ImsMmTelManager implements RegistrationManager {
 
@@ -228,8 +229,13 @@
      * (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}).
      *
      * @throws IllegalArgumentException if the subscription is invalid.
-     *
+     * @deprecated Use {@link android.telephony.ims.ImsManager#getImsMmTelManager(int)} to get an
+     * instance of this class.
+     * @hide
      */
+    @SystemApi
+    @TestApi
+    @Deprecated
     @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
     @RequiresPermission(anyOf = {
             android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
@@ -245,7 +251,7 @@
     }
 
     /**
-     * Only visible for testing, use {@link #createForSubscriptionId(int)} instead.
+     * Only visible for testing, use {@link ImsManager#getImsMmTelManager(int)} instead.
      * @hide
      */
     @VisibleForTesting
@@ -255,7 +261,7 @@
 
     /**
      * Registers a {@link RegistrationCallback} with the system, which will provide registration
-     * updates for the subscription specified in {@link #createForSubscriptionId(int)}. Use
+     * updates for the subscription specified in {@link ImsManager#getImsMmTelManager(int)}. Use
      * {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to Subscription changed
      * events and call {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up.
      *
@@ -453,7 +459,7 @@
     /**
      * Registers a {@link CapabilityCallback} with the system, which will provide MmTel service
      * availability updates for the subscription specified in
-     * {@link #createForSubscriptionId(int)}. The method {@see #isAvailable(int, int)}
+     * {@link ImsManager#getImsMmTelManager(int)}. The method {@see #isAvailable(int, int)}
      * can also be used to query this information at any time.
      *
      * Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to
diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java
index 62bc2ae..2b3072e 100644
--- a/telephony/java/android/telephony/ims/ImsService.java
+++ b/telephony/java/android/telephony/ims/ImsService.java
@@ -60,9 +60,10 @@
  * The telephony framework will then bind to the ImsService you have defined in your manifest
  * if you are either:
  * 1) Defined as the default ImsService for the device in the device overlay using
- *    "config_ims_package".
+ *    "config_ims_mmtel_package" or "config_ims_rcs_package".
  * 2) Defined as a Carrier Provided ImsService in the Carrier Configuration using
- *    {@link CarrierConfigManager#KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING}.
+ *    {@link CarrierConfigManager#KEY_CONFIG_IMS_MMTEL_PACKAGE_OVERRIDE_STRING} or
+ *    {@link CarrierConfigManager#KEY_CONFIG_IMS_RCS_PACKAGE_OVERRIDE_STRING}.
  *
  * There are two ways to define to the platform which {@link ImsFeature}s this {@link ImsService}
  * supports, dynamic or static definitions.
diff --git a/telephony/java/android/telephony/ims/Rcs1To1Thread.java b/telephony/java/android/telephony/ims/Rcs1To1Thread.java
deleted file mode 100644
index e90548a..0000000
--- a/telephony/java/android/telephony/ims/Rcs1To1Thread.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.telephony.ims;
-
-import android.annotation.NonNull;
-import android.annotation.WorkerThread;
-
-/**
- * Rcs1To1Thread represents a single RCS conversation thread with a total of two
- * {@link RcsParticipant}s. Please see Section 5 (1-to-1 Messaging) - GSMA RCC.71 (RCS Universal
- * Profile Service Definition Document)
- *
- * @hide
- */
-public class Rcs1To1Thread extends RcsThread {
-    private int mThreadId;
-
-    /**
-     * Public constructor only for RcsMessageStoreController to initialize new threads.
-     *
-     * @hide
-     */
-    public Rcs1To1Thread(RcsControllerCall rcsControllerCall, int threadId) {
-        super(rcsControllerCall, threadId);
-        mThreadId = threadId;
-    }
-
-    /**
-     * @return Returns {@code false} as this is always a 1 to 1 thread.
-     */
-    @Override
-    public boolean isGroup() {
-        return false;
-    }
-
-    /**
-     * {@link Rcs1To1Thread}s can fall back to SMS as a back-up protocol. This function returns the
-     * thread id to be used to query {@code content://mms-sms/conversation/#} to get the fallback
-     * thread.
-     *
-     * @return The thread id to be used to query the mms-sms authority
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @WorkerThread
-    public long getFallbackThreadId() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.get1To1ThreadFallbackThreadId(mThreadId,
-                        callingPackage));
-    }
-
-    /**
-     * If the RCS client allows falling back to SMS, it needs to create an MMS-SMS thread in the
-     * SMS/MMS Provider( see {@link android.provider.Telephony.MmsSms#CONTENT_CONVERSATIONS_URI}.
-     * Use this function to link the {@link Rcs1To1Thread} to the MMS-SMS thread. This function
-     * also updates the storage.
-     *
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @WorkerThread
-    public void setFallbackThreadId(long fallbackThreadId) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.set1To1ThreadFallbackThreadId(mThreadId,
-                        fallbackThreadId, callingPackage));
-    }
-
-    /**
-     * @return Returns the {@link RcsParticipant} that receives the messages sent in this thread.
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @NonNull
-    @WorkerThread
-    public RcsParticipant getRecipient() throws RcsMessageStoreException {
-        return new RcsParticipant(
-                mRcsControllerCall,
-                mRcsControllerCall.call(
-                        (iRcs, callingPackage) -> iRcs.get1To1ThreadOtherParticipantId(mThreadId,
-                                callingPackage)));
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsContactUceCapability.java b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
index 3e2903f..57b9b7a 100644
--- a/telephony/java/android/telephony/ims/RcsContactUceCapability.java
+++ b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
@@ -16,10 +16,11 @@
 
 package android.telephony.ims;
 
-import android.annotation.IntDef;
+import android.annotation.LongDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -37,6 +38,7 @@
  * @hide
  */
 @SystemApi
+@TestApi
 public final class RcsContactUceCapability implements Parcelable {
 
     /** Supports 1-to-1 chat */
@@ -99,11 +101,16 @@
     public static final int CAPABILITY_CHAT_BOT_ROLE = (1 << 27);
     /** Supports the unidirectional plug-ins framework. */
     public static final int CAPABILITY_PLUG_IN = (1 << 28);
+    /** Supports standalone Chatbot communication. */
+    public static final int CAPABILITY_STANDALONE_CHAT_BOT = (1 << 29);
+    /** Supports MMTEL based call composer. */
+    public static final int CAPABILITY_MMTEL_CALL_COMPOSER = (1 << 30);
+
 
 
     /** @hide*/
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = "CAPABILITY_", flag = true, value = {
+    @LongDef(prefix = "CAPABILITY_", flag = true, value = {
             CAPABILITY_CHAT_STANDALONE,
             CAPABILITY_CHAT_SESSION,
             CAPABILITY_CHAT_SESSION_STORE_FORWARD,
@@ -132,7 +139,9 @@
             CAPABILITY_SHARED_SKETCH,
             CAPABILITY_CHAT_BOT,
             CAPABILITY_CHAT_BOT_ROLE,
-            CAPABILITY_PLUG_IN
+            CAPABILITY_PLUG_IN,
+            CAPABILITY_STANDALONE_CHAT_BOT,
+            CAPABILITY_MMTEL_CALL_COMPOSER
     })
     public @interface CapabilityFlag {}
 
@@ -159,11 +168,11 @@
          * @param type The capability to map to a service URI that is different from the contact's
          *         URI.
          */
-        public @NonNull Builder add(@CapabilityFlag int type, @NonNull Uri serviceUri) {
+        public @NonNull Builder add(@CapabilityFlag long type, @NonNull Uri serviceUri) {
             mCapabilities.mCapabilities |= type;
             // Put each of these capabilities into the map separately.
-            for (int shift = 0; shift < Integer.SIZE; shift++) {
-                int cap = type & (1 << shift);
+            for (long shift = 0; shift < Integer.SIZE; shift++) {
+                long cap = type & (1 << shift);
                 if (cap != 0) {
                     mCapabilities.mServiceMap.put(cap, serviceUri);
                     // remove that capability from the field.
@@ -181,7 +190,7 @@
          * Add a UCE capability flag that this contact supports.
          * @param type the capability that the contact supports.
          */
-        public @NonNull Builder add(@CapabilityFlag int type) {
+        public @NonNull Builder add(@CapabilityFlag long type) {
             mCapabilities.mCapabilities |= type;
             return this;
         }
@@ -207,7 +216,7 @@
     private final Uri mContactUri;
     private long mCapabilities;
     private List<String> mExtensionTags = new ArrayList<>();
-    private Map<Integer, Uri> mServiceMap = new HashMap<>();
+    private Map<Long, Uri> mServiceMap = new HashMap<>();
 
     /**
      * Use {@link Builder} to build an instance of this interface.
@@ -225,7 +234,7 @@
         // read mServiceMap as key,value pair
         int mapSize = in.readInt();
         for (int i = 0; i < mapSize; i++) {
-            mServiceMap.put(in.readInt(), in.readParcelable(Uri.class.getClassLoader()));
+            mServiceMap.put(in.readLong(), in.readParcelable(Uri.class.getClassLoader()));
         }
     }
 
@@ -250,8 +259,8 @@
         // write mServiceMap as key,value pairs
         int mapSize = mServiceMap.keySet().size();
         out.writeInt(mapSize);
-        for (int key : mServiceMap.keySet()) {
-            out.writeInt(key);
+        for (long key : mServiceMap.keySet()) {
+            out.writeLong(key);
             out.writeParcelable(mServiceMap.get(key), 0);
         }
     }
@@ -266,7 +275,7 @@
      * @param type The capability flag to query.
      * @return true if the capability flag specified is set, false otherwise.
      */
-    public boolean isCapable(@CapabilityFlag int type) {
+    public boolean isCapable(@CapabilityFlag long type) {
         return (mCapabilities & type) > 0;
     }
 
@@ -290,13 +299,13 @@
      * <p>
      * This will typically be the contact {@link Uri} available via {@link #getContactUri()} unless
      * a different service {@link Uri} was associated with this capability using
-     * {@link Builder#add(int, Uri)}.
+     * {@link Builder#add(long, Uri)}.
      *
      * @return a String containing the {@link Uri} associated with the service tag or
      * {@code null} if this capability is not set as capable.
-     * @see #isCapable(int)
+     * @see #isCapable(long)
      */
-    public @Nullable Uri getServiceUri(@CapabilityFlag int type) {
+    public @Nullable Uri getServiceUri(@CapabilityFlag long type) {
         Uri result = mServiceMap.getOrDefault(type, null);
         // If the capability is capable, but does not have a service URI associated, use the default
         // contact URI.
diff --git a/telephony/java/android/telephony/ims/RcsControllerCall.java b/telephony/java/android/telephony/ims/RcsControllerCall.java
deleted file mode 100644
index 1e93437..0000000
--- a/telephony/java/android/telephony/ims/RcsControllerCall.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-import android.content.Context;
-import android.os.RemoteException;
-import android.telephony.TelephonyFrameworkInitializer;
-import android.telephony.ims.aidl.IRcsMessage;
-
-/**
- * A wrapper class around RPC calls that {@link RcsMessageManager} APIs to minimize boilerplate
- * code.
- *
- * @hide - not meant for public use
- */
-class RcsControllerCall {
-    private final Context mContext;
-
-    RcsControllerCall(Context context) {
-        mContext = context;
-    }
-
-    <R> R call(RcsServiceCall<R> serviceCall) throws RcsMessageStoreException {
-        IRcsMessage iRcsMessage = IRcsMessage.Stub.asInterface(
-                TelephonyFrameworkInitializer
-                        .getTelephonyServiceManager()
-                        .getTelephonyRcsMessageServiceRegisterer()
-                        .get());
-        if (iRcsMessage == null) {
-            throw new RcsMessageStoreException("Could not connect to RCS storage service");
-        }
-
-        try {
-            return serviceCall.methodOnIRcs(iRcsMessage, mContext.getOpPackageName());
-        } catch (RemoteException exception) {
-            throw new RcsMessageStoreException(exception.getMessage());
-        }
-    }
-
-    void callWithNoReturn(RcsServiceCallWithNoReturn serviceCall)
-            throws RcsMessageStoreException {
-        call((iRcsMessage, callingPackage) -> {
-            serviceCall.methodOnIRcs(iRcsMessage, callingPackage);
-            return null;
-        });
-    }
-
-    interface RcsServiceCall<R> {
-        R methodOnIRcs(IRcsMessage iRcs, String callingPackage) throws RemoteException;
-    }
-
-    interface RcsServiceCallWithNoReturn {
-        void methodOnIRcs(IRcsMessage iRcs, String callingPackage) throws RemoteException;
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsEvent.java b/telephony/java/android/telephony/ims/RcsEvent.java
deleted file mode 100644
index 9dd0720..0000000
--- a/telephony/java/android/telephony/ims/RcsEvent.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.telephony.ims;
-
-/**
- * The base class for events that can happen on {@link RcsParticipant}s and {@link RcsThread}s.
- *
- * @hide
- */
-public abstract class RcsEvent {
-    private final long mTimestamp;
-
-    protected RcsEvent(long timestamp) {
-        mTimestamp = timestamp;
-    }
-
-    /**
-     * @return Returns the time of when this event happened. The timestamp is defined as
-     * milliseconds passed after midnight, January 1, 1970 UTC
-     */
-    public long getTimestamp() {
-        return mTimestamp;
-    }
-
-    /**
-     * Persists the event to the data store
-     *
-     * @hide
-     */
-    abstract void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException;
-}
diff --git a/telephony/java/android/telephony/ims/RcsEventDescriptor.aidl b/telephony/java/android/telephony/ims/RcsEventDescriptor.aidl
deleted file mode 100644
index ab1c55e..0000000
--- a/telephony/java/android/telephony/ims/RcsEventDescriptor.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsEventDescriptor;
diff --git a/telephony/java/android/telephony/ims/RcsEventDescriptor.java b/telephony/java/android/telephony/ims/RcsEventDescriptor.java
deleted file mode 100644
index b44adea..0000000
--- a/telephony/java/android/telephony/ims/RcsEventDescriptor.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.telephony.ims;
-
-import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * @hide - used only for internal communication with the ircs service
- */
-public abstract class RcsEventDescriptor implements Parcelable {
-    protected final long mTimestamp;
-
-    RcsEventDescriptor(long timestamp) {
-        mTimestamp = timestamp;
-    }
-
-    /**
-     * Creates an RcsEvent based on this RcsEventDescriptor. Overriding this method practically
-     * allows an injection point for RcsEvent dependencies outside of the values contained in the
-     * descriptor.
-     */
-    @VisibleForTesting(visibility = PROTECTED)
-    public abstract RcsEvent createRcsEvent(RcsControllerCall rcsControllerCall);
-
-    RcsEventDescriptor(Parcel in) {
-        mTimestamp = in.readLong();
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeLong(mTimestamp);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsEventQueryParams.aidl b/telephony/java/android/telephony/ims/RcsEventQueryParams.aidl
deleted file mode 100644
index f18c4df..0000000
--- a/telephony/java/android/telephony/ims/RcsEventQueryParams.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsEventQueryParams;
diff --git a/telephony/java/android/telephony/ims/RcsEventQueryParams.java b/telephony/java/android/telephony/ims/RcsEventQueryParams.java
deleted file mode 100644
index 0024cf7..0000000
--- a/telephony/java/android/telephony/ims/RcsEventQueryParams.java
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-import static android.provider.Telephony.RcsColumns.RcsEventTypes.ICON_CHANGED_EVENT_TYPE;
-import static android.provider.Telephony.RcsColumns.RcsEventTypes.NAME_CHANGED_EVENT_TYPE;
-import static android.provider.Telephony.RcsColumns.RcsEventTypes.PARTICIPANT_ALIAS_CHANGED_EVENT_TYPE;
-import static android.provider.Telephony.RcsColumns.RcsEventTypes.PARTICIPANT_JOINED_EVENT_TYPE;
-import static android.provider.Telephony.RcsColumns.RcsEventTypes.PARTICIPANT_LEFT_EVENT_TYPE;
-
-import android.annotation.CheckResult;
-import android.annotation.IntDef;
-import android.annotation.IntRange;
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.security.InvalidParameterException;
-
-/**
- * The parameters to pass into
- * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)} in order to select a
- * subset of {@link RcsEvent}s present in the message store.
- *
- * @hide
- */
-public final class RcsEventQueryParams implements Parcelable {
-    /**
-     * Flag to be used with {@link Builder#setEventType(int)} to make
-     * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)} return all types of
-     * {@link RcsEvent}s
-     */
-    public static final int ALL_EVENTS = -1;
-
-    /**
-     * Flag to be used with {@link Builder#setEventType(int)} to make
-     * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)} return sub-types of
-     * {@link RcsGroupThreadEvent}s
-     */
-    public static final int ALL_GROUP_THREAD_EVENTS = 0;
-
-    /**
-     * Flag to be used with {@link Builder#setEventType(int)} to make
-     * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)} return only
-     * {@link RcsParticipantAliasChangedEvent}s
-     */
-    public static final int PARTICIPANT_ALIAS_CHANGED_EVENT =
-            PARTICIPANT_ALIAS_CHANGED_EVENT_TYPE;
-
-    /**
-     * Flag to be used with {@link Builder#setEventType(int)} to make
-     * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)} return only
-     * {@link RcsGroupThreadParticipantJoinedEvent}s
-     */
-    public static final int GROUP_THREAD_PARTICIPANT_JOINED_EVENT =
-            PARTICIPANT_JOINED_EVENT_TYPE;
-
-    /**
-     * Flag to be used with {@link Builder#setEventType(int)} to make
-     * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)} return only
-     * {@link RcsGroupThreadParticipantLeftEvent}s
-     */
-    public static final int GROUP_THREAD_PARTICIPANT_LEFT_EVENT =
-            PARTICIPANT_LEFT_EVENT_TYPE;
-
-    /**
-     * Flag to be used with {@link Builder#setEventType(int)} to make
-     * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)} return only
-     * {@link RcsGroupThreadNameChangedEvent}s
-     */
-    public static final int GROUP_THREAD_NAME_CHANGED_EVENT = NAME_CHANGED_EVENT_TYPE;
-
-    /**
-     * Flag to be used with {@link Builder#setEventType(int)} to make
-     * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)} return only
-     * {@link RcsGroupThreadIconChangedEvent}s
-     */
-    public static final int GROUP_THREAD_ICON_CHANGED_EVENT = ICON_CHANGED_EVENT_TYPE;
-
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({ALL_EVENTS, ALL_GROUP_THREAD_EVENTS, PARTICIPANT_ALIAS_CHANGED_EVENT,
-            GROUP_THREAD_PARTICIPANT_JOINED_EVENT, GROUP_THREAD_PARTICIPANT_LEFT_EVENT,
-            GROUP_THREAD_NAME_CHANGED_EVENT, GROUP_THREAD_ICON_CHANGED_EVENT})
-    public @interface EventType {
-    }
-
-    /**
-     * Flag to be used with {@link Builder#setSortProperty(int)} that makes the result set sorted
-     * in the order of creation for faster query results.
-     */
-    public static final int SORT_BY_CREATION_ORDER = 0;
-
-    /**
-     * Flag to be used with {@link Builder#setSortProperty(int)} that makes the result set sorted
-     * with respect to {@link RcsEvent#getTimestamp()}
-     */
-    public static final int SORT_BY_TIMESTAMP = 1;
-
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({SORT_BY_CREATION_ORDER, SORT_BY_TIMESTAMP})
-    public @interface SortingProperty {
-    }
-
-    /**
-     * The key to pass into a Bundle, for usage in RcsProvider.query(Bundle)
-     * @hide - not meant for public use
-     */
-    public static final String EVENT_QUERY_PARAMETERS_KEY = "event_query_parameters";
-
-    // Which types of events the results should be limited to
-    private @EventType int mEventType;
-    // The property which the results should be sorted against
-    private int mSortingProperty;
-    // Whether the results should be sorted in ascending order
-    private boolean mIsAscending;
-    // The number of results that should be returned with this query
-    private int mLimit;
-    // The thread that the results are limited to
-    private int mThreadId;
-
-    RcsEventQueryParams(@EventType int eventType, int threadId,
-            @SortingProperty int sortingProperty, boolean isAscending, int limit) {
-        mEventType = eventType;
-        mSortingProperty = sortingProperty;
-        mIsAscending = isAscending;
-        mLimit = limit;
-        mThreadId = threadId;
-    }
-
-    /**
-     * @return Returns the type of {@link RcsEvent}s that this {@link RcsEventQueryParams} is
-     * set to query for.
-     */
-    public @EventType int getEventType() {
-        return mEventType;
-    }
-
-    /**
-     * @return Returns the number of {@link RcsEvent}s to be returned from the query. A value of
-     * 0 means there is no set limit.
-     */
-    public int getLimit() {
-        return mLimit;
-    }
-
-    /**
-     * @return Returns the property where the results should be sorted against.
-     * @see SortingProperty
-     */
-    public int getSortingProperty() {
-        return mSortingProperty;
-    }
-
-    /**
-     * @return Returns {@code true} if the result set will be sorted in ascending order,
-     * {@code false} if it will be sorted in descending order.
-     */
-    public boolean getSortDirection() {
-        return mIsAscending;
-    }
-
-    /**
-     * @return Returns the ID of the {@link RcsGroupThread} that the results are limited to. As this
-     * API exposes an ID, it should stay hidden.
-     *
-     * @hide
-     */
-    public int getThreadId() {
-        return mThreadId;
-    }
-
-    /**
-     * A helper class to build the {@link RcsEventQueryParams}.
-     */
-    public static class Builder {
-        private @EventType int mEventType;
-        private @SortingProperty int mSortingProperty;
-        private boolean mIsAscending;
-        private int mLimit = 100;
-        private int mThreadId;
-
-        /**
-         * Creates a new builder for {@link RcsEventQueryParams} to be used in
-         * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)}
-         */
-        public Builder() {
-            // empty implementation
-        }
-
-        /**
-         * Desired number of events to be returned from the query. Passing in 0 will return all
-         * existing events at once. The limit defaults to 100.
-         *
-         * @param limit The number to limit the query result to.
-         * @return The same instance of the builder to chain parameters.
-         * @throws InvalidParameterException If the given limit is negative.
-         */
-        @CheckResult
-        public Builder setResultLimit(@IntRange(from = 0) int limit)
-                throws InvalidParameterException {
-            if (limit < 0) {
-                throw new InvalidParameterException("The query limit must be non-negative");
-            }
-
-            mLimit = limit;
-            return this;
-        }
-
-        /**
-         * Sets the type of events to be returned from the query.
-         *
-         * @param eventType The type of event to be returned.
-         * @return The same instance of the builder to chain parameters.
-         */
-        @CheckResult
-        public Builder setEventType(@EventType int eventType) {
-            mEventType = eventType;
-            return this;
-        }
-
-        /**
-         * Sets the property where the results should be sorted against. Defaults to
-         * {@link RcsEventQueryParams.SortingProperty#SORT_BY_CREATION_ORDER}
-         *
-         * @param sortingProperty against which property the results should be sorted
-         * @return The same instance of the builder to chain parameters.
-         */
-        @CheckResult
-        public Builder setSortProperty(@SortingProperty int sortingProperty) {
-            mSortingProperty = sortingProperty;
-            return this;
-        }
-
-        /**
-         * Sets whether the results should be sorted ascending or descending
-         *
-         * @param isAscending whether the results should be sorted ascending
-         * @return The same instance of the builder to chain parameters.
-         */
-        @CheckResult
-        public Builder setSortDirection(boolean isAscending) {
-            mIsAscending = isAscending;
-            return this;
-        }
-
-        /**
-         * Limits the results to the given {@link RcsGroupThread}. Setting this value prevents
-         * returning any instances of {@link RcsParticipantAliasChangedEvent}.
-         *
-         * @param groupThread The thread to limit the results to.
-         * @return The same instance of the builder to chain parameters.
-         */
-        @CheckResult
-        public Builder setGroupThread(@NonNull RcsGroupThread groupThread) {
-            mThreadId = groupThread.getThreadId();
-            return this;
-        }
-
-        /**
-         * Builds the {@link RcsEventQueryParams} to use in
-         * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)}
-         *
-         * @return An instance of {@link RcsEventQueryParams} to use with the event query.
-         */
-        public RcsEventQueryParams build() {
-            return new RcsEventQueryParams(mEventType, mThreadId, mSortingProperty,
-                    mIsAscending, mLimit);
-        }
-    }
-
-    private RcsEventQueryParams(Parcel in) {
-        mEventType = in.readInt();
-        mThreadId = in.readInt();
-        mSortingProperty = in.readInt();
-        mIsAscending = in.readBoolean();
-        mLimit = in.readInt();
-    }
-
-    public static final @android.annotation.NonNull Creator<RcsEventQueryParams> CREATOR =
-            new Creator<RcsEventQueryParams>() {
-                @Override
-                public RcsEventQueryParams createFromParcel(Parcel in) {
-                    return new RcsEventQueryParams(in);
-                }
-
-                @Override
-                public RcsEventQueryParams[] newArray(int size) {
-                    return new RcsEventQueryParams[size];
-                }
-            };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mEventType);
-        dest.writeInt(mThreadId);
-        dest.writeInt(mSortingProperty);
-        dest.writeBoolean(mIsAscending);
-        dest.writeInt(mLimit);
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsEventQueryResult.java b/telephony/java/android/telephony/ims/RcsEventQueryResult.java
deleted file mode 100644
index d6347e3..0000000
--- a/telephony/java/android/telephony/ims/RcsEventQueryResult.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-import java.util.List;
-
-/**
- * The result of a {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)}
- * call. This class allows getting the token for querying the next batch of events in order to
- * prevent handling large amounts of data at once.
- *
- * @hide
- */
-public class RcsEventQueryResult {
-    private RcsQueryContinuationToken mContinuationToken;
-    private List<RcsEvent> mEvents;
-
-    /**
-     * Internal constructor for {@link com.android.internal.telephony.ims.RcsMessageStoreController}
-     * to create query results
-     *
-     * @hide
-     */
-    public RcsEventQueryResult(
-            RcsQueryContinuationToken continuationToken,
-            List<RcsEvent> events) {
-        mContinuationToken = continuationToken;
-        mEvents = events;
-    }
-
-    /**
-     * Returns a token to call
-     * {@link RcsMessageStore#getRcsEvents(RcsQueryContinuationToken)}
-     * to get the next batch of {@link RcsEvent}s.
-     */
-    public RcsQueryContinuationToken getContinuationToken() {
-        return mContinuationToken;
-    }
-
-    /**
-     * Returns all the {@link RcsEvent}s in the current query result. Call {@link
-     * RcsMessageStore#getRcsEvents(RcsQueryContinuationToken)} to get the next batch
-     * of {@link RcsEvent}s.
-     */
-    public List<RcsEvent> getEvents() {
-        return mEvents;
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.aidl b/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.aidl
deleted file mode 100644
index 0beaaab..0000000
--- a/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsEventQueryResultDescriptor;
diff --git a/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.java b/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.java
deleted file mode 100644
index b972d55..0000000
--- a/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * Contains the raw data backing a {@link RcsEventQueryResult}.
- *
- * @hide - used only for internal communication with the ircs service
- */
-public class RcsEventQueryResultDescriptor implements Parcelable {
-    private final RcsQueryContinuationToken mContinuationToken;
-    private final List<RcsEventDescriptor> mEvents;
-
-    public RcsEventQueryResultDescriptor(
-            RcsQueryContinuationToken continuationToken,
-            List<RcsEventDescriptor> events) {
-        mContinuationToken = continuationToken;
-        mEvents = events;
-    }
-
-    protected RcsEventQueryResult getRcsEventQueryResult(RcsControllerCall rcsControllerCall) {
-        List<RcsEvent> rcsEvents = mEvents.stream()
-                .map(rcsEvent -> rcsEvent.createRcsEvent(rcsControllerCall))
-                .collect(Collectors.toList());
-
-        return new RcsEventQueryResult(mContinuationToken, rcsEvents);
-    }
-
-    protected RcsEventQueryResultDescriptor(Parcel in) {
-        mContinuationToken = in.readParcelable(RcsQueryContinuationToken.class.getClassLoader());
-        mEvents = new LinkedList<>();
-        in.readList(mEvents, null);
-    }
-
-    public static final @android.annotation.NonNull Creator<RcsEventQueryResultDescriptor> CREATOR =
-            new Creator<RcsEventQueryResultDescriptor>() {
-        @Override
-        public RcsEventQueryResultDescriptor createFromParcel(Parcel in) {
-            return new RcsEventQueryResultDescriptor(in);
-        }
-
-        @Override
-        public RcsEventQueryResultDescriptor[] newArray(int size) {
-            return new RcsEventQueryResultDescriptor[size];
-        }
-    };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeParcelable(mContinuationToken, flags);
-        dest.writeList(mEvents);
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsFileTransferCreationParams.aidl b/telephony/java/android/telephony/ims/RcsFileTransferCreationParams.aidl
deleted file mode 100644
index 1552190..0000000
--- a/telephony/java/android/telephony/ims/RcsFileTransferCreationParams.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsFileTransferCreationParams;
diff --git a/telephony/java/android/telephony/ims/RcsFileTransferCreationParams.java b/telephony/java/android/telephony/ims/RcsFileTransferCreationParams.java
deleted file mode 100644
index e43552d..0000000
--- a/telephony/java/android/telephony/ims/RcsFileTransferCreationParams.java
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.telephony.ims;
-
-import android.annotation.CheckResult;
-import android.net.Uri;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Pass an instance of this class to
- * {@link RcsMessage#insertFileTransfer(RcsFileTransferCreationParams)} create an
- * {@link RcsFileTransferPart} and save it into storage.
- *
- * @hide
- */
-public final class RcsFileTransferCreationParams implements Parcelable {
-    private String mRcsFileTransferSessionId;
-    private Uri mContentUri;
-    private String mContentMimeType;
-    private long mFileSize;
-    private long mTransferOffset;
-    private int mWidth;
-    private int mHeight;
-    private long mMediaDuration;
-    private Uri mPreviewUri;
-    private String mPreviewMimeType;
-    private @RcsFileTransferPart.RcsFileTransferStatus int mFileTransferStatus;
-
-    /**
-     * @return Returns the globally unique RCS file transfer session ID for the
-     * {@link RcsFileTransferPart} to be created
-     */
-    public String getRcsFileTransferSessionId() {
-        return mRcsFileTransferSessionId;
-    }
-
-    /**
-     * @return Returns the URI for the content of the {@link RcsFileTransferPart} to be created
-     */
-    public Uri getContentUri() {
-        return mContentUri;
-    }
-
-    /**
-     * @return Returns the MIME type for the content of the {@link RcsFileTransferPart} to be
-     * created
-     */
-    public String getContentMimeType() {
-        return mContentMimeType;
-    }
-
-    /**
-     * @return Returns the file size in bytes for the {@link RcsFileTransferPart} to be created
-     */
-    public long getFileSize() {
-        return mFileSize;
-    }
-
-    /**
-     * @return Returns the transfer offset for the {@link RcsFileTransferPart} to be created. The
-     * file transfer offset is defined as how many bytes have been successfully transferred to the
-     * receiver of this file transfer.
-     */
-    public long getTransferOffset() {
-        return mTransferOffset;
-    }
-
-    /**
-     * @return Returns the width of the {@link RcsFileTransferPart} to be created. The value is in
-     * pixels.
-     */
-    public int getWidth() {
-        return mWidth;
-    }
-
-    /**
-     * @return Returns the height of the {@link RcsFileTransferPart} to be created. The value is in
-     * pixels.
-     */
-    public int getHeight() {
-        return mHeight;
-    }
-
-    /**
-     * @return Returns the duration of the {@link RcsFileTransferPart} to be created.
-     */
-    public long getMediaDuration() {
-        return mMediaDuration;
-    }
-
-    /**
-     * @return Returns the URI of the preview of the content of the {@link RcsFileTransferPart} to
-     * be created. This should only be used for multi-media files.
-     */
-    public Uri getPreviewUri() {
-        return mPreviewUri;
-    }
-
-    /**
-     * @return Returns the MIME type of the preview of the content of the
-     * {@link RcsFileTransferPart} to be created. This should only be used for multi-media files.
-     */
-    public String getPreviewMimeType() {
-        return mPreviewMimeType;
-    }
-
-    /**
-     * @return Returns the status of the {@link RcsFileTransferPart} to be created.
-     */
-    public @RcsFileTransferPart.RcsFileTransferStatus int getFileTransferStatus() {
-        return mFileTransferStatus;
-    }
-
-    /**
-     * @hide
-     */
-    RcsFileTransferCreationParams(Builder builder) {
-        mRcsFileTransferSessionId = builder.mRcsFileTransferSessionId;
-        mContentUri = builder.mContentUri;
-        mContentMimeType = builder.mContentMimeType;
-        mFileSize = builder.mFileSize;
-        mTransferOffset = builder.mTransferOffset;
-        mWidth = builder.mWidth;
-        mHeight = builder.mHeight;
-        mMediaDuration = builder.mLength;
-        mPreviewUri = builder.mPreviewUri;
-        mPreviewMimeType = builder.mPreviewMimeType;
-        mFileTransferStatus = builder.mFileTransferStatus;
-    }
-
-    /**
-     * A builder to create instances of {@link RcsFileTransferCreationParams}
-     */
-    public class Builder {
-        private String mRcsFileTransferSessionId;
-        private Uri mContentUri;
-        private String mContentMimeType;
-        private long mFileSize;
-        private long mTransferOffset;
-        private int mWidth;
-        private int mHeight;
-        private long mLength;
-        private Uri mPreviewUri;
-        private String mPreviewMimeType;
-        private @RcsFileTransferPart.RcsFileTransferStatus int mFileTransferStatus;
-
-        /**
-         * Sets the globally unique RCS file transfer session ID for the {@link RcsFileTransferPart}
-         * to be created
-         *
-         * @param sessionId The RCS file transfer session ID
-         * @return The same instance of {@link Builder} to chain methods
-         */
-        @CheckResult
-        public Builder setFileTransferSessionId(String sessionId) {
-            mRcsFileTransferSessionId = sessionId;
-            return this;
-        }
-
-        /**
-         * Sets the URI for the content of the {@link RcsFileTransferPart} to be created
-         *
-         * @param contentUri The URI for the file
-         * @return The same instance of {@link Builder} to chain methods
-         */
-        @CheckResult
-        public Builder setContentUri(Uri contentUri) {
-            mContentUri = contentUri;
-            return this;
-        }
-
-        /**
-         * Sets the MIME type for the content of the {@link RcsFileTransferPart} to be created
-         *
-         * @param contentType The MIME type of the file
-         * @return The same instance of {@link Builder} to chain methods
-         */
-        @CheckResult
-        public Builder setContentMimeType(String contentType) {
-            mContentMimeType = contentType;
-            return this;
-        }
-
-        /**
-         * Sets the file size for the {@link RcsFileTransferPart} to be created
-         *
-         * @param size The size of the file in bytes
-         * @return The same instance of {@link Builder} to chain methods
-         */
-        @CheckResult
-        public Builder setFileSize(long size) {
-            mFileSize = size;
-            return this;
-        }
-
-        /**
-         * Sets the transfer offset for the {@link RcsFileTransferPart} to be created. The file
-         * transfer offset is defined as how many bytes have been successfully transferred to the
-         * receiver of this file transfer.
-         *
-         * @param offset The transfer offset in bytes
-         * @return The same instance of {@link Builder} to chain methods
-         */
-        @CheckResult
-        public Builder setTransferOffset(long offset) {
-            mTransferOffset = offset;
-            return this;
-        }
-
-        /**
-         * Sets the width of the {@link RcsFileTransferPart} to be created. This should only be used
-         * for multi-media files.
-         *
-         * @param width The width of the multi-media file in pixels.
-         * @return The same instance of {@link Builder} to chain methods
-         */
-        @CheckResult
-        public Builder setWidth(int width) {
-            mWidth = width;
-            return this;
-        }
-
-        /**
-         * Sets the height of the {@link RcsFileTransferPart} to be created. This should only be
-         * used for multi-media files.
-         *
-         * @param height The height of the multi-media file in pixels.
-         * @return The same instance of {@link Builder} to chain methods
-         */
-        @CheckResult
-        public Builder setHeight(int height) {
-            mHeight = height;
-            return this;
-        }
-
-        /**
-         * Sets the length of the {@link RcsFileTransferPart} to be created. This should only be
-         * used for multi-media files such as audio or video.
-         *
-         * @param length The length of the multi-media file in milliseconds
-         * @return The same instance of {@link Builder} to chain methods
-         */
-        @CheckResult
-        public Builder setMediaDuration(long length) {
-            mLength = length;
-            return this;
-        }
-
-        /**
-         * Sets the URI of the preview of the content of the {@link RcsFileTransferPart} to be
-         * created. This should only be used for multi-media files.
-         *
-         * @param previewUri The URI of the preview of the file transfer
-         * @return The same instance of {@link Builder} to chain methods
-         */
-        @CheckResult
-        public Builder setPreviewUri(Uri previewUri) {
-            mPreviewUri = previewUri;
-            return this;
-        }
-
-        /**
-         * Sets the MIME type of the preview of the content of the {@link RcsFileTransferPart} to
-         * be created. This should only be used for multi-media files.
-         *
-         * @param previewType The MIME type of the preview of the file transfer
-         * @return The same instance of {@link Builder} to chain methods
-         */
-        @CheckResult
-        public Builder setPreviewMimeType(String previewType) {
-            mPreviewMimeType = previewType;
-            return this;
-        }
-
-        /**
-         * Sets the status of the {@link RcsFileTransferPart} to be created.
-         *
-         * @param status The status of the file transfer
-         * @return The same instance of {@link Builder} to chain methods
-         */
-        @CheckResult
-        public Builder setFileTransferStatus(
-                @RcsFileTransferPart.RcsFileTransferStatus int status) {
-            mFileTransferStatus = status;
-            return this;
-        }
-
-        /**
-         * Creates an instance of {@link RcsFileTransferCreationParams} with the given
-         * parameters.
-         *
-         * @return The same instance of {@link Builder} to chain methods
-         * @see RcsMessage#insertFileTransfer(RcsFileTransferCreationParams)
-         */
-        public RcsFileTransferCreationParams build() {
-            return new RcsFileTransferCreationParams(this);
-        }
-    }
-
-    private RcsFileTransferCreationParams(Parcel in) {
-        mRcsFileTransferSessionId = in.readString();
-        mContentUri = in.readParcelable(Uri.class.getClassLoader());
-        mContentMimeType = in.readString();
-        mFileSize = in.readLong();
-        mTransferOffset = in.readLong();
-        mWidth = in.readInt();
-        mHeight = in.readInt();
-        mMediaDuration = in.readLong();
-        mPreviewUri = in.readParcelable(Uri.class.getClassLoader());
-        mPreviewMimeType = in.readString();
-        mFileTransferStatus = in.readInt();
-    }
-
-    public static final @android.annotation.NonNull Creator<RcsFileTransferCreationParams> CREATOR =
-            new Creator<RcsFileTransferCreationParams>() {
-                @Override
-                public RcsFileTransferCreationParams createFromParcel(Parcel in) {
-                    return new RcsFileTransferCreationParams(in);
-                }
-
-                @Override
-                public RcsFileTransferCreationParams[] newArray(int size) {
-                    return new RcsFileTransferCreationParams[size];
-                }
-            };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeString(mRcsFileTransferSessionId);
-        dest.writeParcelable(mContentUri, flags);
-        dest.writeString(mContentMimeType);
-        dest.writeLong(mFileSize);
-        dest.writeLong(mTransferOffset);
-        dest.writeInt(mWidth);
-        dest.writeInt(mHeight);
-        dest.writeLong(mMediaDuration);
-        dest.writeParcelable(mPreviewUri, flags);
-        dest.writeString(mPreviewMimeType);
-        dest.writeInt(mFileTransferStatus);
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsFileTransferPart.java b/telephony/java/android/telephony/ims/RcsFileTransferPart.java
deleted file mode 100644
index ef66a76..0000000
--- a/telephony/java/android/telephony/ims/RcsFileTransferPart.java
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.telephony.ims;
-
-import android.annotation.IntDef;
-import android.annotation.Nullable;
-import android.annotation.WorkerThread;
-import android.net.Uri;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * A part of a composite {@link RcsMessage} that holds a file transfer. Please see Section 7
- * (File Transfer) - GSMA RCC.71 (RCS Universal Profile Service Definition Document)
- *
- * @hide
- */
-public class RcsFileTransferPart {
-    /**
-     * The status to indicate that this {@link RcsFileTransferPart} is not set yet.
-     */
-    public static final int NOT_SET = 0;
-
-    /**
-     * The status to indicate that this {@link RcsFileTransferPart} is a draft and is not in the
-     * process of sending yet.
-     */
-    public static final int DRAFT = 1;
-
-    /**
-     * The status to indicate that this {@link RcsFileTransferPart} is actively being sent right
-     * now.
-     */
-    public static final int SENDING = 2;
-
-    /**
-     * The status to indicate that this {@link RcsFileTransferPart} was being sent, but the user has
-     * paused the sending process.
-     */
-    public static final int SENDING_PAUSED = 3;
-
-    /**
-     * The status to indicate that this {@link RcsFileTransferPart} was attempted, but failed to
-     * send.
-     */
-    public static final int SENDING_FAILED = 4;
-
-    /**
-     * The status to indicate that this {@link RcsFileTransferPart} is permanently cancelled to
-     * send.
-     */
-    public static final int SENDING_CANCELLED = 5;
-
-    /**
-     * The status to indicate that this {@link RcsFileTransferPart} is actively being downloaded
-     * right now.
-     */
-    public static final int DOWNLOADING = 6;
-
-    /**
-     * The status to indicate that this {@link RcsFileTransferPart} was being downloaded, but the
-     * user paused the downloading process.
-     */
-    public static final int DOWNLOADING_PAUSED = 7;
-
-    /**
-     * The status to indicate that this {@link RcsFileTransferPart} was attempted, but failed to
-     * download.
-     */
-    public static final int DOWNLOADING_FAILED = 8;
-
-    /**
-     * The status to indicate that this {@link RcsFileTransferPart} is permanently cancelled to
-     * download.
-     */
-    public static final int DOWNLOADING_CANCELLED = 9;
-
-    /**
-     * The status to indicate that this {@link RcsFileTransferPart} was successfully sent or
-     * received.
-     */
-    public static final int SUCCEEDED = 10;
-
-    @IntDef({
-            DRAFT, SENDING, SENDING_PAUSED, SENDING_FAILED, SENDING_CANCELLED, DOWNLOADING,
-            DOWNLOADING_PAUSED, DOWNLOADING_FAILED, DOWNLOADING_CANCELLED, SUCCEEDED
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface RcsFileTransferStatus {
-    }
-
-    private final RcsControllerCall mRcsControllerCall;
-
-    private int mId;
-
-    /**
-     * @hide
-     */
-    RcsFileTransferPart(RcsControllerCall rcsControllerCall, int id) {
-        mRcsControllerCall = rcsControllerCall;
-        mId = id;
-    }
-
-    /**
-     * @hide
-     */
-    public void setId(int id) {
-        mId = id;
-    }
-
-    /**
-     * @hide
-     */
-    public int getId() {
-        return mId;
-    }
-
-    /**
-     * Sets the RCS file transfer session ID for this file transfer and persists into storage.
-     *
-     * @param sessionId The session ID to be used for this file transfer.
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @WorkerThread
-    public void setFileTransferSessionId(String sessionId) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setFileTransferSessionId(mId, sessionId,
-                        callingPackage));
-    }
-
-    /**
-     * @return Returns the file transfer session ID.
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @WorkerThread
-    public String getFileTransferSessionId() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getFileTransferSessionId(mId, callingPackage));
-    }
-
-    /**
-     * Sets the content URI for this file transfer and persists into storage. The file transfer
-     * should be reachable using this URI.
-     *
-     * @param contentUri The URI for this file transfer.
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @WorkerThread
-    public void setContentUri(Uri contentUri) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setFileTransferContentUri(mId, contentUri,
-                        callingPackage));
-    }
-
-    /**
-     * @return Returns the URI for this file transfer
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @Nullable
-    @WorkerThread
-    public Uri getContentUri() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getFileTransferContentUri(mId, callingPackage));
-    }
-
-    /**
-     * Sets the MIME type of this file transfer and persists into storage. Whether this type
-     * actually matches any known or supported types is not checked.
-     *
-     * @param contentMimeType The type of this file transfer.
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @WorkerThread
-    public void setContentMimeType(String contentMimeType) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setFileTransferContentType(mId, contentMimeType,
-                        callingPackage));
-    }
-
-    /**
-     * @return Returns the content type of this file transfer
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @WorkerThread
-    @Nullable
-    public String getContentMimeType() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getFileTransferContentType(mId, callingPackage));
-    }
-
-    /**
-     * Sets the content length (i.e. file size) for this file transfer and persists into storage.
-     *
-     * @param contentLength The content length of this file transfer
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @WorkerThread
-    public void setFileSize(long contentLength) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setFileTransferFileSize(mId, contentLength,
-                        callingPackage));
-    }
-
-    /**
-     * @return Returns the content length (i.e. file size) for this file transfer.
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @WorkerThread
-    public long getFileSize() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getFileTransferFileSize(mId, callingPackage));
-    }
-
-    /**
-     * Sets the transfer offset for this file transfer and persists into storage. The file transfer
-     * offset is defined as how many bytes have been successfully transferred to the receiver of
-     * this file transfer.
-     *
-     * @param transferOffset The transfer offset for this file transfer.
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @WorkerThread
-    public void setTransferOffset(long transferOffset) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setFileTransferTransferOffset(mId, transferOffset,
-                        callingPackage));
-    }
-
-    /**
-     * @return Returns the number of bytes that have successfully transferred.
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @WorkerThread
-    public long getTransferOffset() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getFileTransferTransferOffset(mId, callingPackage));
-    }
-
-    /**
-     * Sets the status for this file transfer and persists into storage.
-     *
-     * @param status The status of this file transfer.
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @WorkerThread
-    public void setFileTransferStatus(@RcsFileTransferStatus int status)
-            throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setFileTransferStatus(mId, status, callingPackage));
-    }
-
-    /**
-     * @return Returns the status of this file transfer.
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @WorkerThread
-    public @RcsFileTransferStatus int getFileTransferStatus() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getFileTransferStatus(mId, callingPackage));
-    }
-
-    /**
-     * @return Returns the width of this multi-media message part in pixels.
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @WorkerThread
-    public int getWidth() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getFileTransferWidth(mId, callingPackage));
-    }
-
-    /**
-     * Sets the width of this RCS multi-media message part and persists into storage.
-     *
-     * @param width The width value in pixels
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @WorkerThread
-    public void setWidth(int width) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setFileTransferWidth(mId, width, callingPackage));
-    }
-
-    /**
-     * @return Returns the height of this multi-media message part in pixels.
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @WorkerThread
-    public int getHeight() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getFileTransferHeight(mId, callingPackage));
-    }
-
-    /**
-     * Sets the height of this RCS multi-media message part and persists into storage.
-     *
-     * @param height The height value in pixels
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @WorkerThread
-    public void setHeight(int height) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setFileTransferHeight(mId, height, callingPackage));
-    }
-
-    /**
-     * @return Returns the length of this multi-media file (e.g. video or audio) in milliseconds.
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @WorkerThread
-    public long getLength() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getFileTransferLength(mId, callingPackage));
-    }
-
-    /**
-     * Sets the length of this multi-media file (e.g. video or audio) and persists into storage.
-     *
-     * @param length The length of the file in milliseconds.
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @WorkerThread
-    public void setLength(long length) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setFileTransferLength(mId, length, callingPackage));
-    }
-
-    /**
-     * @return Returns the URI for the preview of this multi-media file (e.g. an image thumbnail for
-     * a video)
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @WorkerThread
-    public Uri getPreviewUri() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getFileTransferPreviewUri(mId, callingPackage));
-    }
-
-    /**
-     * Sets the URI for the preview of this multi-media file and persists into storage.
-     *
-     * @param previewUri The URI to access to the preview file.
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @WorkerThread
-    public void setPreviewUri(Uri previewUri) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setFileTransferPreviewUri(mId, previewUri,
-                        callingPackage));
-    }
-
-    /**
-     * @return Returns the MIME type of this multi-media file's preview.
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @WorkerThread
-    public String getPreviewMimeType() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getFileTransferPreviewType(mId, callingPackage));
-    }
-
-    /**
-     * Sets the MIME type for this multi-media file's preview and persists into storage.
-     *
-     * @param previewMimeType The MIME type for the preview
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @WorkerThread
-    public void setPreviewMimeType(String previewMimeType) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setFileTransferPreviewType(mId, previewMimeType,
-                        callingPackage));
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThread.java b/telephony/java/android/telephony/ims/RcsGroupThread.java
deleted file mode 100644
index 30abcb4..0000000
--- a/telephony/java/android/telephony/ims/RcsGroupThread.java
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.telephony.ims;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.WorkerThread;
-import android.net.Uri;
-
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * RcsGroupThread represents a single RCS conversation thread where {@link RcsParticipant}s can join
- * or leave. Please see Section 6 (Group Chat) - GSMA RCC.71 (RCS Universal Profile Service
- * Definition Document)
- *
- * @hide
- */
-public class RcsGroupThread extends RcsThread {
-    /**
-     * Public constructor only for RcsMessageStoreController to initialize new threads.
-     *
-     * @hide
-     */
-    public RcsGroupThread(RcsControllerCall rcsControllerCall, int threadId) {
-        super(rcsControllerCall, threadId);
-    }
-
-    /**
-     * @return Returns {@code true} as this is always a group thread
-     */
-    @Override
-    public boolean isGroup() {
-        return true;
-    }
-
-    /**
-     * @return Returns the given name of this {@link RcsGroupThread}. Please see US6-2 - GSMA RCC.71
-     * (RCS Universal Profile Service Definition Document)
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @Nullable
-    @WorkerThread
-    public String getGroupName() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getGroupThreadName(mThreadId, callingPackage));
-    }
-
-    /**
-     * Sets the name of this {@link RcsGroupThread} and saves it into storage. Please see US6-2 -
-     * GSMA RCC.71 (RCS Universal Profile Service Definition Document)
-     *
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @WorkerThread
-    public void setGroupName(String groupName) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setGroupThreadName(mThreadId, groupName,
-                        callingPackage));
-    }
-
-    /**
-     * @return Returns a URI that points to the group's icon {@link RcsGroupThread}. Please see
-     * US6-2 - GSMA RCC.71 (RCS Universal Profile Service Definition Document)
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @Nullable
-    public Uri getGroupIcon() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getGroupThreadIcon(mThreadId, callingPackage));
-    }
-
-    /**
-     * Sets the icon for this {@link RcsGroupThread} and saves it into storage. Please see US6-2 -
-     * GSMA RCC.71 (RCS Universal Profile Service Definition Document)
-     *
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @WorkerThread
-    public void setGroupIcon(@Nullable Uri groupIcon) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setGroupThreadIcon(mThreadId, groupIcon,
-                        callingPackage));
-    }
-
-    /**
-     * @return Returns the owner of this thread or {@code null} if there doesn't exist an owner
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @Nullable
-    @WorkerThread
-    public RcsParticipant getOwner() throws RcsMessageStoreException {
-        return new RcsParticipant(
-                mRcsControllerCall,
-                mRcsControllerCall.call(
-                        (iRcs, callingPackage) -> iRcs.getGroupThreadOwner(mThreadId,
-                                callingPackage)));
-    }
-
-    /**
-     * Sets the owner of this {@link RcsGroupThread} and saves it into storage. This is intended to
-     * be used for selecting a new owner for a group thread if the owner leaves the thread. The
-     * owner needs to be in the list of existing participants.
-     *
-     * @param participant The new owner of the thread. {@code null} values are allowed.
-     * @throws RcsMessageStoreException if the operation could not be persisted into storage
-     */
-    @WorkerThread
-    public void setOwner(@Nullable RcsParticipant participant) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setGroupThreadOwner(mThreadId, participant.getId(),
-                        callingPackage));
-    }
-
-    /**
-     * Adds a new {@link RcsParticipant} to this group thread and persists into storage. If the user
-     * is actively participating in this {@link RcsGroupThread}, an {@link RcsParticipant} on behalf
-     * of them should be added.
-     *
-     * @param participant The new participant to be added to the thread.
-     * @throws RcsMessageStoreException if the operation could not be persisted into storage
-     */
-    @WorkerThread
-    public void addParticipant(@NonNull RcsParticipant participant)
-            throws RcsMessageStoreException {
-        if (participant == null) {
-            return;
-        }
-
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.addParticipantToGroupThread(mThreadId,
-                        participant.getId(), callingPackage));
-    }
-
-    /**
-     * Removes an {@link RcsParticipant} from this group thread and persists into storage. If the
-     * removed participant was the owner of this group, the owner will become null.
-     *
-     * @throws RcsMessageStoreException if the operation could not be persisted into storage
-     */
-    @WorkerThread
-    public void removeParticipant(@NonNull RcsParticipant participant)
-            throws RcsMessageStoreException {
-        if (participant == null) {
-            return;
-        }
-
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.removeParticipantFromGroupThread(mThreadId,
-                        participant.getId(), callingPackage));
-    }
-
-    /**
-     * Returns the set of {@link RcsParticipant}s that contribute to this group thread. The
-     * returned set does not support modifications, please use
-     * {@link RcsGroupThread#addParticipant(RcsParticipant)}
-     * and {@link RcsGroupThread#removeParticipant(RcsParticipant)} instead.
-     *
-     * @return the immutable set of {@link RcsParticipant} in this group thread.
-     * @throws RcsMessageStoreException if the values could not be read from the storage
-     */
-    @WorkerThread
-    @NonNull
-    public Set<RcsParticipant> getParticipants() throws RcsMessageStoreException {
-        RcsParticipantQueryParams queryParameters =
-                new RcsParticipantQueryParams.Builder().setThread(this).build();
-
-        RcsParticipantQueryResult queryResult = new RcsParticipantQueryResult(
-                mRcsControllerCall,
-                mRcsControllerCall.call(
-                        (iRcs, callingPackage) -> iRcs.getParticipants(queryParameters,
-                                callingPackage)));
-
-        List<RcsParticipant> participantList = queryResult.getParticipants();
-        Set<RcsParticipant> participantSet = new LinkedHashSet<>(participantList);
-        return Collections.unmodifiableSet(participantSet);
-    }
-
-    /**
-     * Returns the conference URI for this {@link RcsGroupThread}. Please see 4.4.5.2 - GSMA RCC.53
-     * (RCS Device API 1.6 Specification
-     *
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @Nullable
-    @WorkerThread
-    public Uri getConferenceUri() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getGroupThreadConferenceUri(mThreadId,
-                        callingPackage));
-    }
-
-    /**
-     * Sets the conference URI for this {@link RcsGroupThread} and persists into storage. Please see
-     * 4.4.5.2 - GSMA RCC.53 (RCS Device API 1.6 Specification
-     *
-     * @param conferenceUri The URI as String to be used as the conference URI.
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @Nullable
-    @WorkerThread
-    public void setConferenceUri(Uri conferenceUri) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setGroupThreadConferenceUri(mThreadId, conferenceUri,
-                        callingPackage));
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java
deleted file mode 100644
index f4beef7f..0000000
--- a/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.telephony.ims;
-
-import android.annotation.NonNull;
-
-/**
- * An event that happened on an {@link RcsGroupThread}.
- *
- * @hide
- */
-public abstract class RcsGroupThreadEvent extends RcsEvent {
-    private final RcsGroupThread mRcsGroupThread;
-    private final RcsParticipant mOriginatingParticipant;
-
-    RcsGroupThreadEvent(long timestamp, RcsGroupThread rcsGroupThread,
-            RcsParticipant originatingParticipant) {
-        super(timestamp);
-        mRcsGroupThread = rcsGroupThread;
-        mOriginatingParticipant = originatingParticipant;
-    }
-
-    /**
-     * @return Returns the {@link RcsGroupThread} that this event happened on.
-     */
-    @NonNull
-    public RcsGroupThread getRcsGroupThread() {
-        return mRcsGroupThread;
-    }
-
-    /**
-     * @return Returns the {@link RcsParticipant} that performed the event.
-     */
-    @NonNull
-    public RcsParticipant getOriginatingParticipant() {
-        return mOriginatingParticipant;
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadEventDescriptor.aidl b/telephony/java/android/telephony/ims/RcsGroupThreadEventDescriptor.aidl
deleted file mode 100644
index 6299d8a..0000000
--- a/telephony/java/android/telephony/ims/RcsGroupThreadEventDescriptor.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsGroupThreadEventDescriptor;
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadEventDescriptor.java
deleted file mode 100644
index 662a264..0000000
--- a/telephony/java/android/telephony/ims/RcsGroupThreadEventDescriptor.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.telephony.ims;
-
-import android.os.Parcel;
-
-/**
- * @hide - used only for internal communication with the ircs service
- */
-public abstract class RcsGroupThreadEventDescriptor extends RcsEventDescriptor {
-    protected final int mRcsGroupThreadId;
-    protected final int mOriginatingParticipantId;
-
-    RcsGroupThreadEventDescriptor(long timestamp, int rcsGroupThreadId,
-            int originatingParticipantId) {
-        super(timestamp);
-        mRcsGroupThreadId = rcsGroupThreadId;
-        mOriginatingParticipantId = originatingParticipantId;
-    }
-
-    RcsGroupThreadEventDescriptor(Parcel in) {
-        super(in);
-        mRcsGroupThreadId = in.readInt();
-        mOriginatingParticipantId = in.readInt();
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        super.writeToParcel(dest, flags);
-        dest.writeInt(mRcsGroupThreadId);
-        dest.writeInt(mOriginatingParticipantId);
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java
deleted file mode 100644
index 23e39ff..0000000
--- a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.telephony.ims;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.net.Uri;
-
-/**
- * An event that indicates an {@link RcsGroupThread}'s icon was changed. Please see R6-2-5 - GSMA
- * RCC.71 (RCS Universal Profile Service Definition Document)
- *
- * @hide
- */
-public final class RcsGroupThreadIconChangedEvent extends RcsGroupThreadEvent {
-    private final Uri mNewIcon;
-
-    /**
-     * Creates a new {@link RcsGroupThreadIconChangedEvent}. This event is not persisted into
-     * storage until {@link RcsMessageStore#persistRcsEvent(RcsEvent)} is called.
-     *
-     * @param timestamp The timestamp of when this event happened, in milliseconds passed after
-     *                  midnight, January 1st, 1970 UTC
-     * @param rcsGroupThread The {@link RcsGroupThread} that this event happened on
-     * @param originatingParticipant The {@link RcsParticipant} that changed the
-     *                               {@link RcsGroupThread}'s icon.
-     * @param newIcon {@link Uri} to the new icon of this {@link RcsGroupThread}
-     * @see RcsMessageStore#persistRcsEvent(RcsEvent)
-     */
-    public RcsGroupThreadIconChangedEvent(long timestamp,
-            @NonNull RcsGroupThread rcsGroupThread, @NonNull RcsParticipant originatingParticipant,
-            @Nullable Uri newIcon) {
-        super(timestamp, rcsGroupThread, originatingParticipant);
-        mNewIcon = newIcon;
-    }
-
-    /**
-     * @return Returns the {@link Uri} to the icon of the {@link RcsGroupThread} after this
-     * {@link RcsGroupThreadIconChangedEvent} occured.
-     */
-    @Nullable
-    public Uri getNewIcon() {
-        return mNewIcon;
-    }
-
-    /**
-     * Persists the event to the data store.
-     *
-     * @hide - not meant for public use.
-     */
-    @Override
-    void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException {
-        // TODO ensure failure throws
-        rcsControllerCall.call((iRcs, callingPackage) -> iRcs.createGroupThreadIconChangedEvent(
-                getTimestamp(), getRcsGroupThread().getThreadId(),
-                getOriginatingParticipant().getId(), mNewIcon, callingPackage));
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.aidl b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.aidl
deleted file mode 100644
index 4bcc5a0..0000000
--- a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsGroupThreadIconChangedEventDescriptor;
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java
deleted file mode 100644
index 9350e40..0000000
--- a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.telephony.ims;
-
-import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.net.Uri;
-import android.os.Parcel;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * @hide - used only for internal communication with the ircs service
- */
-public class RcsGroupThreadIconChangedEventDescriptor extends RcsGroupThreadEventDescriptor {
-    private final Uri mNewIcon;
-
-    public RcsGroupThreadIconChangedEventDescriptor(long timestamp, int rcsGroupThreadId,
-            int originatingParticipantId, @Nullable Uri newIcon) {
-        super(timestamp, rcsGroupThreadId, originatingParticipantId);
-        mNewIcon = newIcon;
-    }
-
-    @Override
-    @VisibleForTesting(visibility = PROTECTED)
-    public RcsGroupThreadIconChangedEvent createRcsEvent(RcsControllerCall rcsControllerCall) {
-        return new RcsGroupThreadIconChangedEvent(mTimestamp,
-                new RcsGroupThread(rcsControllerCall, mRcsGroupThreadId),
-                new RcsParticipant(rcsControllerCall, mOriginatingParticipantId), mNewIcon);
-    }
-
-    public static final @NonNull Creator<RcsGroupThreadIconChangedEventDescriptor> CREATOR =
-            new Creator<RcsGroupThreadIconChangedEventDescriptor>() {
-                @Override
-                public RcsGroupThreadIconChangedEventDescriptor createFromParcel(Parcel in) {
-                    return new RcsGroupThreadIconChangedEventDescriptor(in);
-                }
-
-                @Override
-                public RcsGroupThreadIconChangedEventDescriptor[] newArray(int size) {
-                    return new RcsGroupThreadIconChangedEventDescriptor[size];
-                }
-            };
-
-    protected RcsGroupThreadIconChangedEventDescriptor(Parcel in) {
-        super(in);
-        mNewIcon = in.readParcelable(Uri.class.getClassLoader());
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        super.writeToParcel(dest, flags);
-        dest.writeParcelable(mNewIcon, flags);
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java
deleted file mode 100644
index a6a0867..0000000
--- a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.telephony.ims;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-
-/**
- * An event that indicates an {@link RcsGroupThread}'s name was changed. Please see R6-2-5 - GSMA
- * RCC.71 (RCS Universal Profile Service Definition Document)
- *
- * @hide
- */
-public final class RcsGroupThreadNameChangedEvent extends RcsGroupThreadEvent {
-    private final String mNewName;
-
-    /**
-     * Creates a new {@link RcsGroupThreadNameChangedEvent}. This event is not persisted into
-     * storage until {@link RcsMessageStore#persistRcsEvent(RcsEvent)} is called.
-     *
-     * @param timestamp The timestamp of when this event happened, in milliseconds passed after
-     *                  midnight, January 1st, 1970 UTC
-     * @param rcsGroupThread The {@link RcsGroupThread} that this event happened on
-     * @param originatingParticipant The {@link RcsParticipant} that changed the
-     *                               {@link RcsGroupThread}'s icon.
-     * @param newName The new name of the {@link RcsGroupThread}
-     * @see RcsMessageStore#persistRcsEvent(RcsEvent)
-     */
-    public RcsGroupThreadNameChangedEvent(long timestamp, @NonNull RcsGroupThread rcsGroupThread,
-            @NonNull RcsParticipant originatingParticipant, @Nullable String newName) {
-        super(timestamp, rcsGroupThread, originatingParticipant);
-        mNewName = newName;
-    }
-
-    /**
-     * @return Returns the name of this {@link RcsGroupThread} after this
-     * {@link RcsGroupThreadNameChangedEvent} happened.
-     */
-    @Nullable
-    public String getNewName() {
-        return mNewName;
-    }
-
-    /**
-     * Persists the event to the data store.
-     *
-     * @hide - not meant for public use.
-     */
-    @Override
-    void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException {
-        rcsControllerCall.call((iRcs, callingPackage) -> iRcs.createGroupThreadNameChangedEvent(
-                getTimestamp(), getRcsGroupThread().getThreadId(),
-                getOriginatingParticipant().getId(), mNewName, callingPackage));
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.aidl b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.aidl
deleted file mode 100644
index 480e86b..0000000
--- a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsGroupThreadNameChangedEventDescriptor;
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java
deleted file mode 100644
index f9ccdd5..0000000
--- a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.telephony.ims;
-
-import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * @hide - used only for internal communication with the ircs service
- */
-public class RcsGroupThreadNameChangedEventDescriptor extends RcsGroupThreadEventDescriptor {
-    private final String mNewName;
-
-    public RcsGroupThreadNameChangedEventDescriptor(long timestamp, int rcsGroupThreadId,
-            int originatingParticipantId, @Nullable String newName) {
-        super(timestamp, rcsGroupThreadId, originatingParticipantId);
-        mNewName = newName;
-    }
-
-    @Override
-    @VisibleForTesting(visibility = PROTECTED)
-    public RcsGroupThreadNameChangedEvent createRcsEvent(RcsControllerCall rcsControllerCall) {
-        return new RcsGroupThreadNameChangedEvent(
-                mTimestamp,
-                new RcsGroupThread(rcsControllerCall, mRcsGroupThreadId),
-                new RcsParticipant(rcsControllerCall, mOriginatingParticipantId),
-                mNewName);
-    }
-
-    public static final @NonNull Creator<RcsGroupThreadNameChangedEventDescriptor> CREATOR =
-            new Creator<RcsGroupThreadNameChangedEventDescriptor>() {
-                @Override
-                public RcsGroupThreadNameChangedEventDescriptor createFromParcel(Parcel in) {
-                    return new RcsGroupThreadNameChangedEventDescriptor(in);
-                }
-
-                @Override
-                public RcsGroupThreadNameChangedEventDescriptor[] newArray(int size) {
-                    return new RcsGroupThreadNameChangedEventDescriptor[size];
-                }
-            };
-
-    protected RcsGroupThreadNameChangedEventDescriptor(Parcel in) {
-        super(in);
-        mNewName = in.readString();
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        super.writeToParcel(dest, flags);
-        dest.writeString(mNewName);
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java
deleted file mode 100644
index 694c7de..0000000
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.telephony.ims;
-
-import android.annotation.NonNull;
-
-/**
- * An event that indicates an RCS participant has joined an {@link RcsThread}. Please see US6-3 -
- * GSMA RCC.71 (RCS Universal Profile Service Definition Document)
- *
- * @hide
- */
-public final class RcsGroupThreadParticipantJoinedEvent extends RcsGroupThreadEvent {
-    private final RcsParticipant mJoinedParticipantId;
-
-    /**
-     * Creates a new {@link RcsGroupThreadParticipantJoinedEvent}. This event is not persisted into
-     * storage until {@link RcsMessageStore#persistRcsEvent(RcsEvent)} is called.
-     *
-     * @param timestamp              The timestamp of when this event happened, in milliseconds
-     *                               passed after
-     *                               midnight, January 1st, 1970 UTC
-     * @param rcsGroupThread         The {@link RcsGroupThread} that this event happened on
-     * @param originatingParticipant The {@link RcsParticipant} that added or invited the new
-     *                               {@link RcsParticipant} into the {@link RcsGroupThread}
-     * @param joinedParticipant      The new {@link RcsParticipant} that joined the
-     *                               {@link RcsGroupThread}
-     * @see RcsMessageStore#persistRcsEvent(RcsEvent)
-     */
-    public RcsGroupThreadParticipantJoinedEvent(long timestamp,
-            @NonNull RcsGroupThread rcsGroupThread, @NonNull RcsParticipant originatingParticipant,
-            @NonNull RcsParticipant joinedParticipant) {
-        super(timestamp, rcsGroupThread, originatingParticipant);
-        mJoinedParticipantId = joinedParticipant;
-    }
-
-    /**
-     * @return Returns the {@link RcsParticipant} that joined the associated {@link RcsGroupThread}
-     */
-    public RcsParticipant getJoinedParticipant() {
-        return mJoinedParticipantId;
-    }
-
-    /**
-     * Persists the event to the data store.
-     *
-     * @hide - not meant for public use.
-     */
-    @Override
-    void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException {
-        rcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.createGroupThreadParticipantJoinedEvent(
-                        getTimestamp(),
-                        getRcsGroupThread().getThreadId(), getOriginatingParticipant().getId(),
-                        getJoinedParticipant().getId(), callingPackage));
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.aidl b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.aidl
deleted file mode 100644
index 7210b9f..0000000
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsGroupThreadParticipantJoinedEventDescriptor;
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java
deleted file mode 100644
index 4a6803e..0000000
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.telephony.ims;
-
-import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED;
-
-import android.annotation.NonNull;
-import android.os.Parcel;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * @hide - used only for internal communication with the ircs service
- */
-public class RcsGroupThreadParticipantJoinedEventDescriptor extends RcsGroupThreadEventDescriptor {
-    private final int mJoinedParticipantId;
-
-    public RcsGroupThreadParticipantJoinedEventDescriptor(long timestamp, int rcsGroupThreadId,
-            int originatingParticipantId, int joinedParticipantId) {
-        super(timestamp, rcsGroupThreadId, originatingParticipantId);
-        mJoinedParticipantId = joinedParticipantId;
-    }
-
-    @Override
-    @VisibleForTesting(visibility = PROTECTED)
-    public RcsGroupThreadParticipantJoinedEvent createRcsEvent(
-            RcsControllerCall rcsControllerCall) {
-        return new RcsGroupThreadParticipantJoinedEvent(
-                mTimestamp,
-                new RcsGroupThread(rcsControllerCall, mRcsGroupThreadId),
-                new RcsParticipant(rcsControllerCall, mOriginatingParticipantId),
-                new RcsParticipant(rcsControllerCall, mJoinedParticipantId));
-    }
-
-    public static final @NonNull Creator<RcsGroupThreadParticipantJoinedEventDescriptor> CREATOR =
-            new Creator<RcsGroupThreadParticipantJoinedEventDescriptor>() {
-                @Override
-                public RcsGroupThreadParticipantJoinedEventDescriptor createFromParcel(Parcel in) {
-                    return new RcsGroupThreadParticipantJoinedEventDescriptor(in);
-                }
-
-                @Override
-                public RcsGroupThreadParticipantJoinedEventDescriptor[] newArray(int size) {
-                    return new RcsGroupThreadParticipantJoinedEventDescriptor[size];
-                }
-            };
-
-    protected RcsGroupThreadParticipantJoinedEventDescriptor(Parcel in) {
-        super(in);
-        mJoinedParticipantId = in.readInt();
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        super.writeToParcel(dest, flags);
-        dest.writeInt(mJoinedParticipantId);
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java
deleted file mode 100644
index fec4354..0000000
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.telephony.ims;
-
-import android.annotation.NonNull;
-
-/**
- * An event that indicates an RCS participant has left an {@link RcsThread}. Please see US6-23 -
- * GSMA RCC.71 (RCS Universal Profile Service Definition Document)
- *
- * @hide
- */
-public final class RcsGroupThreadParticipantLeftEvent extends RcsGroupThreadEvent {
-    private RcsParticipant mLeavingParticipant;
-
-    /**
-     * Creates a new {@link RcsGroupThreadParticipantLeftEvent}. his event is not persisted into
-     * storage until {@link RcsMessageStore#persistRcsEvent(RcsEvent)} is called.
-     *
-     * @param timestamp The timestamp of when this event happened, in milliseconds passed after
-     *                  midnight, January 1st, 1970 UTC
-     * @param rcsGroupThread The {@link RcsGroupThread} that this event happened on
-     * @param originatingParticipant The {@link RcsParticipant} that removed the
-     *                               {@link RcsParticipant} from the {@link RcsGroupThread}. It is
-     *                               possible that originatingParticipant and leavingParticipant are
-     *                               the same (i.e. {@link RcsParticipant} left the group
-     *                               themselves)
-     * @param leavingParticipant The {@link RcsParticipant} that left the {@link RcsGroupThread}
-     * @see RcsMessageStore#persistRcsEvent(RcsEvent)
-     */
-    public RcsGroupThreadParticipantLeftEvent(long timestamp,
-            @NonNull RcsGroupThread rcsGroupThread, @NonNull RcsParticipant originatingParticipant,
-            @NonNull RcsParticipant leavingParticipant) {
-        super(timestamp, rcsGroupThread, originatingParticipant);
-        mLeavingParticipant = leavingParticipant;
-    }
-
-    /**
-     * @return Returns the {@link RcsParticipant} that left the associated {@link RcsGroupThread}
-     * after this {@link RcsGroupThreadParticipantLeftEvent} happened.
-     */
-    @NonNull
-    public RcsParticipant getLeavingParticipant() {
-        return mLeavingParticipant;
-    }
-
-    @Override
-    void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException {
-        rcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.createGroupThreadParticipantLeftEvent(getTimestamp(),
-                        getRcsGroupThread().getThreadId(), getOriginatingParticipant().getId(),
-                        getLeavingParticipant().getId(), callingPackage));
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.aidl b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.aidl
deleted file mode 100644
index 3ef92100..0000000
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsGroupThreadParticipantLeftEventDescriptor;
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java
deleted file mode 100644
index 9b1085c..0000000
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.telephony.ims;
-
-import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED;
-
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * @hide - used only for internal communication with the ircs service
- */
-public class RcsGroupThreadParticipantLeftEventDescriptor extends RcsGroupThreadEventDescriptor {
-    private int mLeavingParticipantId;
-
-    public RcsGroupThreadParticipantLeftEventDescriptor(long timestamp, int rcsGroupThreadId,
-            int originatingParticipantId, int leavingParticipantId) {
-        super(timestamp, rcsGroupThreadId, originatingParticipantId);
-        mLeavingParticipantId = leavingParticipantId;
-    }
-
-    @Override
-    @VisibleForTesting(visibility = PROTECTED)
-    public RcsGroupThreadParticipantLeftEvent createRcsEvent(RcsControllerCall rcsControllerCall) {
-        return new RcsGroupThreadParticipantLeftEvent(
-                mTimestamp,
-                new RcsGroupThread(rcsControllerCall, mRcsGroupThreadId),
-                new RcsParticipant(rcsControllerCall, mOriginatingParticipantId),
-                new RcsParticipant(rcsControllerCall, mLeavingParticipantId));
-    }
-
-    @NonNull
-    public static final Parcelable.Creator<RcsGroupThreadParticipantLeftEventDescriptor> CREATOR =
-            new Creator<RcsGroupThreadParticipantLeftEventDescriptor>() {
-                @Override
-                public RcsGroupThreadParticipantLeftEventDescriptor createFromParcel(Parcel in) {
-                    return new RcsGroupThreadParticipantLeftEventDescriptor(in);
-                }
-
-                @Override
-                public RcsGroupThreadParticipantLeftEventDescriptor[] newArray(int size) {
-                    return new RcsGroupThreadParticipantLeftEventDescriptor[size];
-                }
-            };
-
-    protected RcsGroupThreadParticipantLeftEventDescriptor(Parcel in) {
-        super(in);
-        mLeavingParticipantId = in.readInt();
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        super.writeToParcel(dest, flags);
-        dest.writeInt(mLeavingParticipantId);
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsIncomingMessage.java b/telephony/java/android/telephony/ims/RcsIncomingMessage.java
deleted file mode 100644
index 2810a49..0000000
--- a/telephony/java/android/telephony/ims/RcsIncomingMessage.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.telephony.ims;
-
-import android.annotation.WorkerThread;
-
-/**
- * This is a single instance of a message received over RCS.
- *
- * @hide
- */
-public class RcsIncomingMessage extends RcsMessage {
-    /**
-     * @hide
-     */
-    RcsIncomingMessage(RcsControllerCall rcsControllerCall, int id) {
-        super(rcsControllerCall, id);
-    }
-
-    /**
-     * Sets the timestamp of arrival for this message and persists into storage. The timestamp is
-     * defined as milliseconds passed after midnight, January 1, 1970 UTC
-     *
-     * @param arrivalTimestamp The timestamp to set to.
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @WorkerThread
-    public void setArrivalTimestamp(long arrivalTimestamp) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setMessageArrivalTimestamp(mId, true,
-                        arrivalTimestamp, callingPackage));
-    }
-
-    /**
-     * @return Returns the timestamp of arrival for this message. The timestamp is defined as
-     * milliseconds passed after midnight, January 1, 1970 UTC
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @WorkerThread
-    public long getArrivalTimestamp() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getMessageArrivalTimestamp(mId, true,
-                        callingPackage));
-    }
-
-    /**
-     * Sets the timestamp of when the user saw this message and persists into storage. The timestamp
-     * is defined as milliseconds passed after midnight, January 1, 1970 UTC
-     *
-     * @param notifiedTimestamp The timestamp to set to.
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @WorkerThread
-    public void setSeenTimestamp(long notifiedTimestamp) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setMessageSeenTimestamp(mId, true, notifiedTimestamp,
-                        callingPackage));
-    }
-
-    /**
-     * @return Returns the timestamp of when the user saw this message. The timestamp is defined as
-     * milliseconds passed after midnight, January 1, 1970 UTC
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @WorkerThread
-    public long getSeenTimestamp() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getMessageSeenTimestamp(mId, true, callingPackage));
-    }
-
-    /**
-     * @return Returns the sender of this incoming message.
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @WorkerThread
-    public RcsParticipant getSenderParticipant() throws RcsMessageStoreException {
-        return new RcsParticipant(
-                mRcsControllerCall,
-                mRcsControllerCall.call(
-                        (iRcs, callingPackage) -> iRcs.getSenderParticipant(mId, callingPackage)));
-    }
-
-    /**
-     * @return Returns {@code true} as this is an incoming message
-     */
-    @Override
-    public boolean isIncoming() {
-        return true;
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParams.aidl b/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParams.aidl
deleted file mode 100644
index 1f1d4f6..0000000
--- a/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParams.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsIncomingMessageCreationParams;
diff --git a/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParams.java b/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParams.java
deleted file mode 100644
index d95dc4f..0000000
--- a/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParams.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-import android.annotation.CheckResult;
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * {@link RcsIncomingMessageCreationParams} is a collection of parameters that should be passed
- * into {@link RcsThread#addIncomingMessage(RcsIncomingMessageCreationParams)} to generate an
- * {@link RcsIncomingMessage} on that {@link RcsThread}
- *
- * @hide
- */
-public final class RcsIncomingMessageCreationParams extends RcsMessageCreationParams implements
-        Parcelable {
-    // The arrival timestamp for the RcsIncomingMessage to be created
-    private final long mArrivalTimestamp;
-    // The seen timestamp for the RcsIncomingMessage to be created
-    private final long mSeenTimestamp;
-    // The participant that sent this incoming message
-    private final int mSenderParticipantId;
-
-    /**
-     * Builder to help create an {@link RcsIncomingMessageCreationParams}
-     *
-     * @see RcsThread#addIncomingMessage(RcsIncomingMessageCreationParams)
-     */
-    public static class Builder extends RcsMessageCreationParams.Builder {
-        private RcsParticipant mSenderParticipant;
-        private long mArrivalTimestamp;
-        private long mSeenTimestamp;
-
-        /**
-         * Creates a {@link Builder} to create an instance of
-         * {@link RcsIncomingMessageCreationParams}
-         *
-         * @param originationTimestamp The timestamp of {@link RcsMessage} creation. The origination
-         *                             timestamp value in milliseconds passed after midnight,
-         *                             January 1, 1970 UTC
-         * @param arrivalTimestamp The timestamp of arrival, defined as milliseconds passed after
-         *                         midnight, January 1, 1970 UTC
-         * @param subscriptionId The subscription ID that was used to send or receive this
-         *                       {@link RcsMessage}
-         */
-        public Builder(long originationTimestamp, long arrivalTimestamp, int subscriptionId) {
-            super(originationTimestamp, subscriptionId);
-            mArrivalTimestamp = arrivalTimestamp;
-        }
-
-        /**
-         * Sets the {@link RcsParticipant} that send this {@link RcsIncomingMessage}
-         *
-         * @param senderParticipant The {@link RcsParticipant} that sent this
-         * {@link RcsIncomingMessage}
-         * @return The same instance of {@link Builder} to chain methods.
-         */
-        @CheckResult
-        public Builder setSenderParticipant(RcsParticipant senderParticipant) {
-            mSenderParticipant = senderParticipant;
-            return this;
-        }
-
-        /**
-         * Sets the time of the arrival of this {@link RcsIncomingMessage}
-
-         * @return The same instance of {@link Builder} to chain methods.
-         * @see RcsIncomingMessage#setArrivalTimestamp(long)
-         */
-        @CheckResult
-        public Builder setArrivalTimestamp(long arrivalTimestamp) {
-            mArrivalTimestamp = arrivalTimestamp;
-            return this;
-        }
-
-        /**
-         * Sets the time of the when this user saw the {@link RcsIncomingMessage}
-         * @param seenTimestamp The seen timestamp , defined as milliseconds passed after midnight,
-         *                      January 1, 1970 UTC
-         * @return The same instance of {@link Builder} to chain methods.
-         * @see RcsIncomingMessage#setSeenTimestamp(long)
-         */
-        @CheckResult
-        public Builder setSeenTimestamp(long seenTimestamp) {
-            mSeenTimestamp = seenTimestamp;
-            return this;
-        }
-
-        /**
-         * Creates parameters for creating a new incoming message.
-         * @return A new instance of {@link RcsIncomingMessageCreationParams} to create a new
-         * {@link RcsIncomingMessage}
-         */
-        public RcsIncomingMessageCreationParams build() {
-            return new RcsIncomingMessageCreationParams(this);
-        }
-    }
-
-    private RcsIncomingMessageCreationParams(Builder builder) {
-        super(builder);
-        mArrivalTimestamp = builder.mArrivalTimestamp;
-        mSeenTimestamp = builder.mSeenTimestamp;
-        mSenderParticipantId = builder.mSenderParticipant.getId();
-    }
-
-    private RcsIncomingMessageCreationParams(Parcel in) {
-        super(in);
-        mArrivalTimestamp = in.readLong();
-        mSeenTimestamp = in.readLong();
-        mSenderParticipantId = in.readInt();
-    }
-
-    /**
-     * @return Returns the arrival timestamp for the {@link RcsIncomingMessage} to be created.
-     * Timestamp is defined as milliseconds passed after midnight, January 1, 1970 UTC
-     */
-    public long getArrivalTimestamp() {
-        return mArrivalTimestamp;
-    }
-
-    /**
-     * @return Returns the seen timestamp for the {@link RcsIncomingMessage} to be created.
-     * Timestamp is defined as milliseconds passed after midnight, January 1, 1970 UTC
-     */
-    public long getSeenTimestamp() {
-        return mSeenTimestamp;
-    }
-
-    /**
-     * Helper getter for {@link com.android.internal.telephony.ims.RcsMessageStoreController} to
-     * create {@link RcsIncomingMessage}s
-     *
-     * Since the API doesn't expose any ID's to API users, this should be hidden.
-     * @hide
-     */
-    public int getSenderParticipantId() {
-        return mSenderParticipantId;
-    }
-
-    public static final @NonNull Creator<RcsIncomingMessageCreationParams> CREATOR =
-            new Creator<RcsIncomingMessageCreationParams>() {
-                @Override
-                public RcsIncomingMessageCreationParams createFromParcel(Parcel in) {
-                    return new RcsIncomingMessageCreationParams(in);
-                }
-
-                @Override
-                public RcsIncomingMessageCreationParams[] newArray(int size) {
-                    return new RcsIncomingMessageCreationParams[size];
-                }
-            };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        super.writeToParcel(dest);
-        dest.writeLong(mArrivalTimestamp);
-        dest.writeLong(mSeenTimestamp);
-        dest.writeInt(mSenderParticipantId);
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsMessage.java b/telephony/java/android/telephony/ims/RcsMessage.java
deleted file mode 100644
index 4601bfd..0000000
--- a/telephony/java/android/telephony/ims/RcsMessage.java
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.telephony.ims;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.WorkerThread;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * This is a single instance of a message sent or received over RCS.
- *
- * @hide
- */
-public abstract class RcsMessage {
-    /**
-     * The value to indicate that this {@link RcsMessage} does not have any location information.
-     */
-    public static final double LOCATION_NOT_SET = Double.MIN_VALUE;
-
-    /**
-     * The status to indicate that this {@link RcsMessage}s status is not set yet.
-     */
-    public static final int NOT_SET = 0;
-
-    /**
-     * The status to indicate that this {@link RcsMessage} is a draft and is not in the process of
-     * sending yet.
-     */
-    public static final int DRAFT = 1;
-
-    /**
-     * The status to indicate that this {@link RcsMessage} was successfully sent.
-     */
-    public static final int QUEUED = 2;
-
-    /**
-     * The status to indicate that this {@link RcsMessage} is actively being sent.
-     */
-    public static final int SENDING = 3;
-
-    /**
-     * The status to indicate that this {@link RcsMessage} was successfully sent.
-     */
-    public static final int SENT = 4;
-
-    /**
-     * The status to indicate that this {@link RcsMessage} failed to send in an attempt before, and
-     * now being retried.
-     */
-    public static final int RETRYING = 5;
-
-    /**
-     * The status to indicate that this {@link RcsMessage} has permanently failed to send.
-     */
-    public static final int FAILED = 6;
-
-    /**
-     * The status to indicate that this {@link RcsMessage} was successfully received.
-     */
-    public static final int RECEIVED = 7;
-
-    /**
-     * The status to indicate that this {@link RcsMessage} was seen.
-     */
-    public static final int SEEN = 9;
-
-    /**
-     * @hide
-     */
-    protected final RcsControllerCall mRcsControllerCall;
-
-    /**
-     * @hide
-     */
-    protected final int mId;
-
-    @IntDef({
-            DRAFT, QUEUED, SENDING, SENT, RETRYING, FAILED, RECEIVED, SEEN
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface RcsMessageStatus {
-    }
-
-    RcsMessage(RcsControllerCall rcsControllerCall, int id) {
-        mRcsControllerCall = rcsControllerCall;
-        mId = id;
-    }
-
-    /**
-     * Returns the row Id from the common message.
-     *
-     * @hide
-     */
-    public int getId() {
-        return mId;
-    }
-
-    /**
-     * @return Returns the subscription ID that this {@link RcsMessage} was sent from, or delivered
-     * to.
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     * @see android.telephony.SubscriptionInfo#getSubscriptionId
-     */
-    public int getSubscriptionId() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getMessageSubId(mId, isIncoming(), callingPackage));
-    }
-
-    /**
-     * Sets the subscription ID that this {@link RcsMessage} was sent from, or delivered to and
-     * persists it into storage.
-     *
-     * @param subId The subscription ID to persists into storage.
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     * @see android.telephony.SubscriptionInfo#getSubscriptionId
-     */
-    @WorkerThread
-    public void setSubscriptionId(int subId) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setMessageSubId(mId, isIncoming(), subId,
-                        callingPackage));
-    }
-
-    /**
-     * Sets the status of this message and persists it into storage. Please see
-     * {@link RcsFileTransferPart#setFileTransferStatus(int)} to set statuses around file transfers.
-     *
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @WorkerThread
-    public void setStatus(@RcsMessageStatus int rcsMessageStatus) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setMessageStatus(mId, isIncoming(), rcsMessageStatus,
-                        callingPackage));
-    }
-
-    /**
-     * @return Returns the status of this message. Please see
-     * {@link RcsFileTransferPart#setFileTransferStatus(int)} to set statuses around file transfers.
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @WorkerThread
-    public @RcsMessageStatus int getStatus() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getMessageStatus(mId, isIncoming(), callingPackage));
-    }
-
-    /**
-     * Sets the origination timestamp of this message and persists it into storage. Origination is
-     * defined as when the sender tapped the send button.
-     *
-     * @param timestamp The origination timestamp value in milliseconds passed after midnight,
-     *                  January 1, 1970 UTC
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @WorkerThread
-    public void setOriginationTimestamp(long timestamp) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setMessageOriginationTimestamp(mId, isIncoming(),
-                        timestamp, callingPackage));
-    }
-
-    /**
-     * @return Returns the origination timestamp of this message in milliseconds passed after
-     * midnight, January 1, 1970 UTC. Origination is defined as when the sender tapped the send
-     * button.
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @WorkerThread
-    public long getOriginationTimestamp() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getMessageOriginationTimestamp(mId, isIncoming(),
-                        callingPackage));
-    }
-
-    /**
-     * Sets the globally unique RCS message identifier for this message and persists it into
-     * storage. This function does not confirm that this message id is unique. Please see 4.4.5.2
-     * - GSMA RCC.53 (RCS Device API 1.6 Specification
-     *
-     * @param rcsMessageGlobalId The globally RCS message identifier
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @WorkerThread
-    public void setRcsMessageId(String rcsMessageGlobalId) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setGlobalMessageIdForMessage(mId, isIncoming(),
-                        rcsMessageGlobalId, callingPackage));
-    }
-
-    /**
-     * @return Returns the globally unique RCS message identifier for this message. Please see
-     * 4.4.5.2 - GSMA RCC.53 (RCS Device API 1.6 Specification
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @WorkerThread
-    public String getRcsMessageId() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getGlobalMessageIdForMessage(mId, isIncoming(),
-                        callingPackage));
-    }
-
-    /**
-     * @return Returns the user visible text included in this message.
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @WorkerThread
-    public String getText() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getTextForMessage(mId, isIncoming(),
-                        callingPackage));
-    }
-
-    /**
-     * Sets the user visible text for this message and persists in storage.
-     *
-     * @param text The text this message now has
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @WorkerThread
-    public void setText(String text) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setTextForMessage(mId, isIncoming(), text,
-                        callingPackage));
-    }
-
-    /**
-     * @return Returns the associated latitude for this message, or
-     * {@link RcsMessage#LOCATION_NOT_SET} if it does not contain a location.
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @WorkerThread
-    public double getLatitude() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getLatitudeForMessage(mId, isIncoming(),
-                        callingPackage));
-    }
-
-    /**
-     * Sets the latitude for this message and persists in storage.
-     *
-     * @param latitude The latitude for this location message.
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @WorkerThread
-    public void setLatitude(double latitude) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setLatitudeForMessage(mId, isIncoming(), latitude,
-                        callingPackage));
-    }
-
-    /**
-     * @return Returns the associated longitude for this message, or
-     * {@link RcsMessage#LOCATION_NOT_SET} if it does not contain a location.
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @WorkerThread
-    public double getLongitude() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getLongitudeForMessage(mId, isIncoming(),
-                        callingPackage));
-    }
-
-    /**
-     * Sets the longitude for this message and persists in storage.
-     *
-     * @param longitude The longitude for this location message.
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @WorkerThread
-    public void setLongitude(double longitude) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setLongitudeForMessage(mId, isIncoming(), longitude,
-                        callingPackage));
-    }
-
-    /**
-     * Attaches an {@link RcsFileTransferPart} to this message and persists into storage.
-     *
-     * @param fileTransferCreationParameters The parameters to be used to create the
-     *                                       {@link RcsFileTransferPart}
-     * @return A new instance of {@link RcsFileTransferPart}
-     * @throws RcsMessageStoreException if the file transfer could not be persisted into storage.
-     */
-    @NonNull
-    @WorkerThread
-    public RcsFileTransferPart insertFileTransfer(
-            RcsFileTransferCreationParams fileTransferCreationParameters)
-            throws RcsMessageStoreException {
-        return new RcsFileTransferPart(mRcsControllerCall, mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.storeFileTransfer(mId, isIncoming(),
-                        fileTransferCreationParameters, callingPackage)));
-    }
-
-    /**
-     * @return Returns all the {@link RcsFileTransferPart}s associated with this message in an
-     * unmodifiable set.
-     * @throws RcsMessageStoreException if the file transfers could not be read from the storage
-     */
-    @NonNull
-    @WorkerThread
-    public Set<RcsFileTransferPart> getFileTransferParts() throws RcsMessageStoreException {
-        Set<RcsFileTransferPart> fileTransferParts = new HashSet<>();
-
-        int[] fileTransferIds = mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getFileTransfersAttachedToMessage(mId, isIncoming(),
-                        callingPackage));
-
-        for (int fileTransfer : fileTransferIds) {
-            fileTransferParts.add(new RcsFileTransferPart(mRcsControllerCall, fileTransfer));
-        }
-
-        return Collections.unmodifiableSet(fileTransferParts);
-    }
-
-    /**
-     * Removes a {@link RcsFileTransferPart} from this message, and deletes it in storage.
-     *
-     * @param fileTransferPart The part to delete.
-     * @throws RcsMessageStoreException if the file transfer could not be removed from storage
-     */
-    @WorkerThread
-    public void removeFileTransferPart(@NonNull RcsFileTransferPart fileTransferPart)
-            throws RcsMessageStoreException {
-        if (fileTransferPart == null) {
-            return;
-        }
-
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.deleteFileTransfer(fileTransferPart.getId(),
-                        callingPackage));
-    }
-
-    /**
-     * @return Returns {@code true} if this message was received on this device, {@code false} if it
-     * was sent.
-     */
-    public abstract boolean isIncoming();
-}
diff --git a/telephony/java/android/telephony/ims/RcsMessageCreationParams.java b/telephony/java/android/telephony/ims/RcsMessageCreationParams.java
deleted file mode 100644
index f0eea88..0000000
--- a/telephony/java/android/telephony/ims/RcsMessageCreationParams.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-import static android.telephony.ims.RcsMessage.LOCATION_NOT_SET;
-
-import android.annotation.CheckResult;
-import android.annotation.Nullable;
-import android.os.Parcel;
-
-/**
- * The collection of parameters to be passed into
- * {@link RcsThread#addIncomingMessage(RcsIncomingMessageCreationParams)} and
- * {@link RcsThread#addOutgoingMessage(RcsOutgoingMessageCreationParams)} to create and persist
- * {@link RcsMessage}s on an {@link RcsThread}
- *
- * @hide
- */
-public class RcsMessageCreationParams {
-    // The globally unique id of the RcsMessage to be created.
-    private final String mRcsMessageGlobalId;
-
-    // The subscription that this message was/will be received/sent from.
-    private final int mSubId;
-    // The sending/receiving status of the message
-    private final @RcsMessage.RcsMessageStatus int mMessageStatus;
-    // The timestamp of message creation
-    private final long mOriginationTimestamp;
-    // The user visible content of the message
-    private final String mText;
-    // The latitude of the message if this is a location message
-    private final double mLatitude;
-    // The longitude of the message if this is a location message
-    private final double mLongitude;
-
-    /**
-     * @return Returns the globally unique RCS Message ID for the {@link RcsMessage} to be created.
-     * Please see 4.4.5.2 - GSMA RCC.53 (RCS Device API 1.6 Specification
-     */
-    @Nullable
-    public String getRcsMessageGlobalId() {
-        return mRcsMessageGlobalId;
-    }
-
-    /**
-     * @return Returns the subscription ID that was used to send or receive the {@link RcsMessage}
-     * to be created.
-     */
-    public int getSubId() {
-        return mSubId;
-    }
-
-    /**
-     * @return Returns the status for the {@link RcsMessage} to be created.
-     * @see RcsMessage.RcsMessageStatus
-     */
-    public int getMessageStatus() {
-        return mMessageStatus;
-    }
-
-    /**
-     * @return Returns the origination timestamp of the {@link RcsMessage} to be created in
-     * milliseconds passed after midnight, January 1, 1970 UTC. Origination is defined as when
-     * the sender tapped the send button.
-     */
-    public long getOriginationTimestamp() {
-        return mOriginationTimestamp;
-    }
-
-    /**
-     * @return Returns the user visible text contained in the {@link RcsMessage} to be created
-     */
-    @Nullable
-    public String getText() {
-        return mText;
-    }
-
-    /**
-     * @return Returns the latitude of the {@link RcsMessage} to be created, or
-     * {@link RcsMessage#LOCATION_NOT_SET} if the message does not contain a location.
-     */
-    public double getLatitude() {
-        return mLatitude;
-    }
-
-    /**
-     * @return Returns the longitude of the {@link RcsMessage} to be created, or
-     * {@link RcsMessage#LOCATION_NOT_SET} if the message does not contain a location.
-     */
-    public double getLongitude() {
-        return mLongitude;
-    }
-
-    /**
-     * The base builder for creating {@link RcsMessage}s on {@link RcsThread}s.
-     *
-     * @see RcsIncomingMessageCreationParams
-     */
-    public static class Builder {
-        private String mRcsMessageGlobalId;
-        private int mSubId;
-        private @RcsMessage.RcsMessageStatus int mMessageStatus;
-        private long mOriginationTimestamp;
-        private String mText;
-        private double mLatitude = LOCATION_NOT_SET;
-        private double mLongitude = LOCATION_NOT_SET;
-
-        /**
-         * @hide
-         */
-        public Builder(long originationTimestamp, int subscriptionId) {
-            mOriginationTimestamp = originationTimestamp;
-            mSubId = subscriptionId;
-        }
-
-        /**
-         * Sets the status of the {@link RcsMessage} to be built.
-         *
-         * @param rcsMessageStatus The status to be set
-         * @return The same instance of {@link Builder} to chain methods
-         * @see RcsMessage#setStatus(int)
-         */
-        @CheckResult
-        public Builder setStatus(@RcsMessage.RcsMessageStatus int rcsMessageStatus) {
-            mMessageStatus = rcsMessageStatus;
-            return this;
-        }
-
-        /**
-         * Sets the globally unique RCS message identifier for the {@link RcsMessage} to be built.
-         * This function does not confirm that this message id is unique. Please see 4.4.5.2 - GSMA
-         * RCC.53 (RCS Device API 1.6 Specification)
-         *
-         * @param rcsMessageId The ID to be set
-         * @return The same instance of {@link Builder} to chain methods
-         * @see RcsMessage#setRcsMessageId(String)
-         */
-        @CheckResult
-        public Builder setRcsMessageId(String rcsMessageId) {
-            mRcsMessageGlobalId = rcsMessageId;
-            return this;
-        }
-
-        /**
-         * Sets the text of the {@link RcsMessage} to be built.
-         *
-         * @param text The user visible text of the message
-         * @return The same instance of {@link Builder} to chain methods
-         * @see RcsMessage#setText(String)
-         */
-        @CheckResult
-        public Builder setText(String text) {
-            mText = text;
-            return this;
-        }
-
-        /**
-         * Sets the latitude of the {@link RcsMessage} to be built. Please see US5-24 - GSMA RCC.71
-         * (RCS Universal Profile Service Definition Document)
-         *
-         * @param latitude The latitude of the location information associated with this message.
-         * @return The same instance of {@link Builder} to chain methods
-         * @see RcsMessage#setLatitude(double)
-         */
-        @CheckResult
-        public Builder setLatitude(double latitude) {
-            mLatitude = latitude;
-            return this;
-        }
-
-        /**
-         * Sets the longitude of the {@link RcsMessage} to be built. Please see US5-24 - GSMA RCC.71
-         * (RCS Universal Profile Service Definition Document)
-         *
-         * @param longitude The longitude of the location information associated with this message.
-         * @return The same instance of {@link Builder} to chain methods
-         * @see RcsMessage#setLongitude(double)
-         */
-        @CheckResult
-        public Builder setLongitude(double longitude) {
-            mLongitude = longitude;
-            return this;
-        }
-
-        /**
-         * @return Builds and returns a newly created {@link RcsMessageCreationParams}
-         */
-        public RcsMessageCreationParams build() {
-            return new RcsMessageCreationParams(this);
-        }
-    }
-
-    protected RcsMessageCreationParams(Builder builder) {
-        mRcsMessageGlobalId = builder.mRcsMessageGlobalId;
-        mSubId = builder.mSubId;
-        mMessageStatus = builder.mMessageStatus;
-        mOriginationTimestamp = builder.mOriginationTimestamp;
-        mText = builder.mText;
-        mLatitude = builder.mLatitude;
-        mLongitude = builder.mLongitude;
-    }
-
-    /**
-     * @hide
-     */
-    RcsMessageCreationParams(Parcel in) {
-        mRcsMessageGlobalId = in.readString();
-        mSubId = in.readInt();
-        mMessageStatus = in.readInt();
-        mOriginationTimestamp = in.readLong();
-        mText = in.readString();
-        mLatitude = in.readDouble();
-        mLongitude = in.readDouble();
-    }
-
-    /**
-     * @hide
-     */
-    public void writeToParcel(Parcel dest) {
-        dest.writeString(mRcsMessageGlobalId);
-        dest.writeInt(mSubId);
-        dest.writeInt(mMessageStatus);
-        dest.writeLong(mOriginationTimestamp);
-        dest.writeString(mText);
-        dest.writeDouble(mLatitude);
-        dest.writeDouble(mLongitude);
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsMessageManager.java b/telephony/java/android/telephony/ims/RcsMessageManager.java
deleted file mode 100644
index a1c7c0f..0000000
--- a/telephony/java/android/telephony/ims/RcsMessageManager.java
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemService;
-import android.annotation.WorkerThread;
-import android.content.Context;
-import android.net.Uri;
-
-import java.util.List;
-
-/**
- * RcsMessageManager is the application interface to RcsProvider and provides access methods to
- * RCS related database tables.
- *
- * @hide
- */
-@SystemService(Context.TELEPHONY_RCS_MESSAGE_SERVICE)
-public class RcsMessageManager {
-    RcsControllerCall mRcsControllerCall;
-
-    /**
-     * Use {@link Context#getSystemService(String)} to get an instance of this service.
-     * @hide
-     */
-    public RcsMessageManager(Context context) {
-        mRcsControllerCall = new RcsControllerCall(context);
-    }
-
-    /**
-     * Returns the first chunk of existing {@link RcsThread}s in the common storage.
-     *
-     * @param queryParameters Parameters to specify to return a subset of all RcsThreads.
-     *                        Passing a value of null will return all threads.
-     * @throws RcsMessageStoreException if the query could not be completed on the storage
-     */
-    @WorkerThread
-    @NonNull
-    public RcsThreadQueryResult getRcsThreads(@Nullable RcsThreadQueryParams queryParameters)
-            throws RcsMessageStoreException {
-        return new RcsThreadQueryResult(mRcsControllerCall,
-                mRcsControllerCall.call(
-                        (iRcs, callingPackage) -> iRcs.getRcsThreads(queryParameters,
-                                callingPackage)));
-    }
-
-    /**
-     * Returns the next chunk of {@link RcsThread}s in the common storage.
-     *
-     * @param continuationToken A token to continue the query to get the next chunk. This is
-     *                          obtained through {@link RcsThreadQueryResult#getContinuationToken}.
-     * @throws RcsMessageStoreException if the query could not be completed on the storage
-     */
-    @WorkerThread
-    @NonNull
-    public RcsThreadQueryResult getRcsThreads(@NonNull RcsQueryContinuationToken continuationToken)
-            throws RcsMessageStoreException {
-        return new RcsThreadQueryResult(mRcsControllerCall,
-                mRcsControllerCall.call(
-                        (iRcs, callingPackage) -> iRcs.getRcsThreadsWithToken(continuationToken,
-                                callingPackage)));
-    }
-
-    /**
-     * Returns the first chunk of existing {@link RcsParticipant}s in the common storage.
-     *
-     * @param queryParameters Parameters to specify to return a subset of all RcsParticipants.
-     *                        Passing a value of null will return all participants.
-     * @throws RcsMessageStoreException if the query could not be completed on the storage
-     */
-    @WorkerThread
-    @NonNull
-    public RcsParticipantQueryResult getRcsParticipants(
-            @Nullable RcsParticipantQueryParams queryParameters)
-            throws RcsMessageStoreException {
-        return new RcsParticipantQueryResult(mRcsControllerCall,
-                mRcsControllerCall.call(
-                        (iRcs, callingPackage) -> iRcs.getParticipants(queryParameters,
-                                callingPackage)));
-    }
-
-    /**
-     * Returns the next chunk of {@link RcsParticipant}s in the common storage.
-     *
-     * @param continuationToken A token to continue the query to get the next chunk. This is
-     *                          obtained through
-     *                          {@link RcsParticipantQueryResult#getContinuationToken}
-     * @throws RcsMessageStoreException if the query could not be completed on the storage
-     */
-    @WorkerThread
-    @NonNull
-    public RcsParticipantQueryResult getRcsParticipants(
-            @NonNull RcsQueryContinuationToken continuationToken)
-            throws RcsMessageStoreException {
-        return new RcsParticipantQueryResult(mRcsControllerCall,
-                mRcsControllerCall.call(
-                        (iRcs, callingPackage) -> iRcs.getParticipantsWithToken(continuationToken,
-                                callingPackage)));
-    }
-
-    /**
-     * Returns the first chunk of existing {@link RcsMessage}s in the common storage.
-     *
-     * @param queryParams Parameters to specify to return a subset of all RcsMessages.
-     *                    Passing a value of null will return all messages.
-     * @throws RcsMessageStoreException if the query could not be completed on the storage
-     */
-    @WorkerThread
-    @NonNull
-    public RcsMessageQueryResult getRcsMessages(
-            @Nullable RcsMessageQueryParams queryParams) throws RcsMessageStoreException {
-        return new RcsMessageQueryResult(mRcsControllerCall,
-                mRcsControllerCall.call(
-                        (iRcs, callingPackage) -> iRcs.getMessages(queryParams, callingPackage)));
-    }
-
-    /**
-     * Returns the next chunk of {@link RcsMessage}s in the common storage.
-     *
-     * @param continuationToken A token to continue the query to get the next chunk. This is
-     *                          obtained through {@link RcsMessageQueryResult#getContinuationToken}
-     * @throws RcsMessageStoreException if the query could not be completed on the storage
-     */
-    @WorkerThread
-    @NonNull
-    public RcsMessageQueryResult getRcsMessages(
-            @NonNull RcsQueryContinuationToken continuationToken) throws RcsMessageStoreException {
-        return new RcsMessageQueryResult(mRcsControllerCall,
-                mRcsControllerCall.call(
-                        (iRcs, callingPackage) -> iRcs.getMessagesWithToken(continuationToken,
-                                callingPackage)));
-    }
-
-    /**
-     * Returns the first chunk of existing {@link RcsEvent}s in the common storage.
-     *
-     * @param queryParams Parameters to specify to return a subset of all RcsEvents.
-     *                    Passing a value of null will return all events.
-     * @throws RcsMessageStoreException if the query could not be completed on the storage
-     */
-    @WorkerThread
-    @NonNull
-    public RcsEventQueryResult getRcsEvents(
-            @Nullable RcsEventQueryParams queryParams) throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getEvents(queryParams, callingPackage))
-                .getRcsEventQueryResult(mRcsControllerCall);
-    }
-
-    /**
-     * Returns the next chunk of {@link RcsEvent}s in the common storage.
-     *
-     * @param continuationToken A token to continue the query to get the next chunk. This is
-     *                          obtained through {@link RcsEventQueryResult#getContinuationToken}.
-     * @throws RcsMessageStoreException if the query could not be completed on the storage
-     */
-    @WorkerThread
-    @NonNull
-    public RcsEventQueryResult getRcsEvents(
-            @NonNull RcsQueryContinuationToken continuationToken) throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getEventsWithToken(continuationToken,
-                        callingPackage))
-                .getRcsEventQueryResult(mRcsControllerCall);
-    }
-
-    /**
-     * Persists an {@link RcsEvent} to common storage.
-     *
-     * @param rcsEvent The {@link RcsEvent} to persist into storage.
-     * @throws RcsMessageStoreException if the query could not be completed on the storage
-     * @see RcsGroupThreadNameChangedEvent
-     * @see RcsGroupThreadIconChangedEvent
-     * @see RcsGroupThreadParticipantJoinedEvent
-     * @see RcsGroupThreadParticipantLeftEvent
-     * @see RcsParticipantAliasChangedEvent
-     */
-    @WorkerThread
-    @NonNull
-    public void persistRcsEvent(RcsEvent rcsEvent) throws RcsMessageStoreException {
-        rcsEvent.persist(mRcsControllerCall);
-    }
-
-    /**
-     * Creates a new 1 to 1 thread with the given participant and persists it in the storage.
-     *
-     * @param recipient The {@link RcsParticipant} that will receive the messages in this thread.
-     * @return The newly created {@link Rcs1To1Thread}
-     * @throws RcsMessageStoreException if the thread could not be persisted in the storage
-     */
-    @WorkerThread
-    @NonNull
-    public Rcs1To1Thread createRcs1To1Thread(@NonNull RcsParticipant recipient)
-            throws RcsMessageStoreException {
-        return new Rcs1To1Thread(
-                mRcsControllerCall,
-                mRcsControllerCall.call(
-                        (iRcs, callingPackage) -> iRcs.createRcs1To1Thread(recipient.getId(),
-                                callingPackage)));
-    }
-
-    /**
-     * Creates a new group thread with the given participants and persists it in the storage.
-     *
-     * @throws RcsMessageStoreException if the thread could not be persisted in the storage
-     */
-    @WorkerThread
-    @NonNull
-    public RcsGroupThread createGroupThread(@Nullable List<RcsParticipant> recipients,
-            @Nullable String groupName, @Nullable Uri groupIcon) throws RcsMessageStoreException {
-        int[] recipientIds = null;
-        if (recipients != null) {
-            recipientIds = new int[recipients.size()];
-
-            for (int i = 0; i < recipients.size(); i++) {
-                recipientIds[i] = recipients.get(i).getId();
-            }
-        }
-
-        int[] finalRecipientIds = recipientIds;
-
-        int threadId = mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.createGroupThread(finalRecipientIds, groupName,
-                        groupIcon, callingPackage));
-
-        return new RcsGroupThread(mRcsControllerCall, threadId);
-    }
-
-    /**
-     * Delete the given {@link RcsThread} from the storage.
-     *
-     * @param thread The thread to be deleted.
-     * @throws RcsMessageStoreException if the thread could not be deleted from the storage
-     */
-    @WorkerThread
-    public void deleteThread(@NonNull RcsThread thread) throws RcsMessageStoreException {
-        if (thread == null) {
-            return;
-        }
-
-        boolean isDeleteSucceeded = mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.deleteThread(thread.getThreadId(),
-                        thread.getThreadType(), callingPackage));
-
-        if (!isDeleteSucceeded) {
-            throw new RcsMessageStoreException("Could not delete RcsThread");
-        }
-    }
-
-    /**
-     * Creates a new participant and persists it in the storage.
-     *
-     * @param canonicalAddress The defining address (e.g. phone number) of the participant.
-     * @param alias            The RCS alias for the participant.
-     * @throws RcsMessageStoreException if the participant could not be created on the storage
-     */
-    @WorkerThread
-    @NonNull
-    public RcsParticipant createRcsParticipant(String canonicalAddress, @Nullable String alias)
-            throws RcsMessageStoreException {
-        return new RcsParticipant(mRcsControllerCall, mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.createRcsParticipant(canonicalAddress, alias,
-                        callingPackage)));
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryParams.java b/telephony/java/android/telephony/ims/RcsMessageQueryParams.java
deleted file mode 100644
index 9f9eafb..0000000
--- a/telephony/java/android/telephony/ims/RcsMessageQueryParams.java
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-import android.annotation.CheckResult;
-import android.annotation.IntDef;
-import android.annotation.IntRange;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.security.InvalidParameterException;
-
-/**
- * The parameters to pass into
- * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)} in order to select a
- * subset of {@link RcsMessage}s present in the message store.
- *
- * @hide
- */
-public final class RcsMessageQueryParams implements Parcelable {
-    /**
-     * @hide - not meant for public use
-     */
-    public static final int THREAD_ID_NOT_SET = -1;
-
-    /**
-     * Flag to be used with {@link Builder#setSortProperty(int)} to denote that the results should
-     * be sorted in the same order of {@link RcsMessage}s that got persisted into storage for faster
-     * results.
-     */
-    public static final int SORT_BY_CREATION_ORDER = 0;
-
-    /**
-     * Flag to be used with {@link Builder#setSortProperty(int)} to denote that the results should
-     * be sorted according to the timestamp of {@link RcsMessage#getOriginationTimestamp()}
-     */
-    public static final int SORT_BY_TIMESTAMP = 1;
-
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({SORT_BY_CREATION_ORDER, SORT_BY_TIMESTAMP})
-    public @interface SortingProperty {
-    }
-
-    /**
-     * Bitmask flag to be used with {@link Builder#setMessageType(int)} to make
-     * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)} return
-     * {@link RcsIncomingMessage}s.
-     */
-    public static final int MESSAGE_TYPE_INCOMING = 0x0001;
-
-    /**
-     * Bitmask flag to be used with {@link Builder#setMessageType(int)} to make
-     * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)} return
-     * {@link RcsOutgoingMessage}s.
-     */
-    public static final int MESSAGE_TYPE_OUTGOING = 0x0002;
-
-    /**
-     * Bitmask flag to be used with {@link Builder#setFileTransferPresence(int)} to make
-     * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)} return {@link RcsMessage}s
-     * that have an {@link RcsFileTransferPart} attached.
-     */
-    public static final int MESSAGES_WITH_FILE_TRANSFERS = 0x0004;
-
-    /**
-     * Bitmask flag to be used with {@link Builder#setFileTransferPresence(int)} to make
-     * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)} return {@link RcsMessage}s
-     * that don't have an {@link RcsFileTransferPart} attached.
-     */
-    public static final int MESSAGES_WITHOUT_FILE_TRANSFERS = 0x0008;
-
-    /**
-     * @hide - not meant for public use
-     */
-    public static final String MESSAGE_QUERY_PARAMETERS_KEY = "message_query_parameters";
-
-    // Whether the result should be filtered against incoming or outgoing messages
-    private int mMessageType;
-    // Whether the result should have file transfer messages attached or not
-    private int mFileTransferPresence;
-    // The SQL "Like" clause to filter messages
-    private String mMessageLike;
-    // The property the messages should be sorted against
-    private @SortingProperty int mSortingProperty;
-    // Whether the messages should be sorted in ascending order
-    private boolean mIsAscending;
-    // The number of results that should be returned with this query
-    private int mLimit;
-    // The thread that the results should be limited to
-    private int mThreadId;
-
-    RcsMessageQueryParams(int messageType, int fileTransferPresence, String messageLike,
-            int threadId, @SortingProperty int sortingProperty, boolean isAscending, int limit) {
-        mMessageType = messageType;
-        mFileTransferPresence = fileTransferPresence;
-        mMessageLike = messageLike;
-        mSortingProperty = sortingProperty;
-        mIsAscending = isAscending;
-        mLimit = limit;
-        mThreadId = threadId;
-    }
-
-    /**
-     * @return Returns the type of {@link RcsMessage}s that this {@link RcsMessageQueryParams}
-     * is set to query for.
-     */
-    public int getMessageType() {
-        return mMessageType;
-    }
-
-    /**
-     * @return Returns whether the result query should return {@link RcsMessage}s with
-     * {@link RcsFileTransferPart}s or not
-     */
-    public int getFileTransferPresence() {
-        return mFileTransferPresence;
-    }
-
-    /**
-     * @return Returns the SQL-inspired "LIKE" clause that will be used to match {@link RcsMessage}s
-     */
-    public String getMessageLike() {
-        return mMessageLike;
-    }
-
-    /**
-     * @return Returns the number of {@link RcsThread}s to be returned from the query. A value of
-     * 0 means there is no set limit.
-     */
-    public int getLimit() {
-        return mLimit;
-    }
-
-    /**
-     * @return Returns the property that will be used to sort the result against.
-     * @see SortingProperty
-     */
-    public @SortingProperty int getSortingProperty() {
-        return mSortingProperty;
-    }
-
-    /**
-     * @return Returns {@code true} if the result set will be sorted in ascending order,
-     * {@code false} if it will be sorted in descending order.
-     */
-    public boolean getSortDirection() {
-        return mIsAscending;
-    }
-
-    /**
-     * This is used in {@link com.android.internal.telephony.ims.RcsMessageStoreController} to get
-     * the thread that the result query should be limited to.
-     *
-     * As we do not expose any sort of integer ID's to public usage, this should be hidden.
-     *
-     * @hide - not meant for public use
-     */
-    public int getThreadId() {
-        return mThreadId;
-    }
-
-    /**
-     * A helper class to build the {@link RcsMessageQueryParams}.
-     */
-    public static class Builder {
-        private @SortingProperty int mSortingProperty;
-        private int mMessageType;
-        private int mFileTransferPresence;
-        private String mMessageLike;
-        private boolean mIsAscending;
-        private int mLimit = 100;
-        private int mThreadId = THREAD_ID_NOT_SET;
-
-        /**
-         * Creates a new builder for {@link RcsMessageQueryParams} to be used in
-         * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)}
-         *
-         */
-        public Builder() {
-            // empty implementation
-        }
-
-        /**
-         * Desired number of threads to be returned from the query. Passing in 0 will return all
-         * existing threads at once. The limit defaults to 100.
-         *
-         * @param limit The number to limit the query result to.
-         * @return The same instance of the builder to chain parameters.
-         * @throws InvalidParameterException If the given limit is negative.
-         */
-        @CheckResult
-        public Builder setResultLimit(@IntRange(from = 0) int limit)
-                throws InvalidParameterException {
-            if (limit < 0) {
-                throw new InvalidParameterException("The query limit must be non-negative");
-            }
-
-            mLimit = limit;
-            return this;
-        }
-
-        /**
-         * Sets the type of messages to be returned from the query.
-         *
-         * @param messageType The type of message to be returned.
-         * @return The same instance of the builder to chain parameters.
-         * @see RcsMessageQueryParams#MESSAGE_TYPE_INCOMING
-         * @see RcsMessageQueryParams#MESSAGE_TYPE_OUTGOING
-         */
-        @CheckResult
-        public Builder setMessageType(int messageType) {
-            mMessageType = messageType;
-            return this;
-        }
-
-        /**
-         * Sets whether file transfer messages should be included in the query result or not.
-         *
-         * @param fileTransferPresence Whether file transfers should be included in the result
-         * @return The same instance of the builder to chain parameters.
-         * @see RcsMessageQueryParams#MESSAGES_WITH_FILE_TRANSFERS
-         * @see RcsMessageQueryParams#MESSAGES_WITHOUT_FILE_TRANSFERS
-         */
-        @CheckResult
-        public Builder setFileTransferPresence(int fileTransferPresence) {
-            mFileTransferPresence = fileTransferPresence;
-            return this;
-        }
-
-        /**
-         * Sets an SQL-inspired "like" clause to match with messages. Using a percent sign ('%')
-         * wildcard matches any sequence of zero or more characters. Using an underscore ('_')
-         * wildcard matches any single character. Not using any wildcards would only perform a
-         * string match. The input string is case-insensitive.
-         *
-         * The input "Wh%" would match messages "who", "where" and "what", while the input "Wh_"
-         * would only match "who"
-         *
-         * @param messageLike The "like" clause for matching {@link RcsMessage}s.
-         * @return The same instance of the builder to chain parameters.
-         */
-        @CheckResult
-        public Builder setMessageLike(String messageLike) {
-            mMessageLike = messageLike;
-            return this;
-        }
-
-        /**
-         * Sets the property where the results should be sorted against. Defaults to
-         * {@link RcsMessageQueryParams.SortingProperty#SORT_BY_CREATION_ORDER}
-         *
-         * @param sortingProperty against which property the results should be sorted
-         * @return The same instance of the builder to chain parameters.
-         */
-        @CheckResult
-        public Builder setSortProperty(@SortingProperty int sortingProperty) {
-            mSortingProperty = sortingProperty;
-            return this;
-        }
-
-        /**
-         * Sets whether the results should be sorted ascending or descending
-         *
-         * @param isAscending whether the results should be sorted ascending
-         * @return The same instance of the builder to chain parameters.
-         */
-        @CheckResult
-        public Builder setSortDirection(boolean isAscending) {
-            mIsAscending = isAscending;
-            return this;
-        }
-
-        /**
-         * Limits the results to the given thread.
-         *
-         * @param thread the {@link RcsThread} that results should be limited to. If set to
-         *               {@code null}, messages on all threads will be queried
-         * @return The same instance of the builder to chain parameters.
-         */
-        @CheckResult
-        public Builder setThread(@Nullable RcsThread thread) {
-            if (thread == null) {
-                mThreadId = THREAD_ID_NOT_SET;
-            } else {
-                mThreadId = thread.getThreadId();
-            }
-            return this;
-        }
-
-        /**
-         * Builds the {@link RcsMessageQueryParams} to use in
-         * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)}
-         *
-         * @return An instance of {@link RcsMessageQueryParams} to use with the message
-         * query.
-         */
-        public RcsMessageQueryParams build() {
-            return new RcsMessageQueryParams(mMessageType, mFileTransferPresence, mMessageLike,
-                    mThreadId, mSortingProperty, mIsAscending, mLimit);
-        }
-    }
-
-    /**
-     * Parcelable boilerplate below.
-     */
-    private RcsMessageQueryParams(Parcel in) {
-        mMessageType = in.readInt();
-        mFileTransferPresence = in.readInt();
-        mMessageLike = in.readString();
-        mSortingProperty = in.readInt();
-        mIsAscending = in.readBoolean();
-        mLimit = in.readInt();
-        mThreadId = in.readInt();
-    }
-
-    public static final @android.annotation.NonNull Creator<RcsMessageQueryParams> CREATOR =
-            new Creator<RcsMessageQueryParams>() {
-                @Override
-                public RcsMessageQueryParams createFromParcel(Parcel in) {
-                    return new RcsMessageQueryParams(in);
-                }
-
-                @Override
-                public RcsMessageQueryParams[] newArray(int size) {
-                    return new RcsMessageQueryParams[size];
-                }
-            };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mMessageType);
-        dest.writeInt(mFileTransferPresence);
-        dest.writeString(mMessageLike);
-        dest.writeInt(mSortingProperty);
-        dest.writeBoolean(mIsAscending);
-        dest.writeInt(mLimit);
-        dest.writeInt(mThreadId);
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryResult.java b/telephony/java/android/telephony/ims/RcsMessageQueryResult.java
deleted file mode 100644
index 36bb78a..0000000
--- a/telephony/java/android/telephony/ims/RcsMessageQueryResult.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-import static android.provider.Telephony.RcsColumns.RcsUnifiedMessageColumns.MESSAGE_TYPE_INCOMING;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * The result of a {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)}
- * call. This class allows getting the token for querying the next batch of messages in order to
- * prevent handling large amounts of data at once.
- *
- * @hide
- */
-public final class RcsMessageQueryResult {
-    private final RcsControllerCall mRcsControllerCall;
-    private final RcsMessageQueryResultParcelable mRcsMessageQueryResultParcelable;
-
-    RcsMessageQueryResult(RcsControllerCall rcsControllerCall,
-            RcsMessageQueryResultParcelable rcsMessageQueryResultParcelable) {
-        mRcsControllerCall = rcsControllerCall;
-        mRcsMessageQueryResultParcelable = rcsMessageQueryResultParcelable;
-    }
-
-    /**
-     * Returns a token to call
-     * {@link RcsMessageStore#getRcsMessages(RcsQueryContinuationToken)}
-     * to get the next batch of {@link RcsMessage}s.
-     */
-    @Nullable
-    public RcsQueryContinuationToken getContinuationToken() {
-        return mRcsMessageQueryResultParcelable.mContinuationToken;
-    }
-
-    /**
-     * Returns all the {@link RcsMessage}s in the current query result. Call {@link
-     * RcsMessageStore#getRcsMessages(RcsQueryContinuationToken)} to get the next batch
-     * of {@link RcsMessage}s.
-     */
-    @NonNull
-    public List<RcsMessage> getMessages() {
-        return mRcsMessageQueryResultParcelable.mMessageTypeIdPairs.stream()
-                .map(typeIdPair -> typeIdPair.getType() == MESSAGE_TYPE_INCOMING
-                        ? new RcsIncomingMessage(mRcsControllerCall, typeIdPair.getId())
-                        : new RcsOutgoingMessage(mRcsControllerCall, typeIdPair.getId()))
-                .collect(Collectors.toList());
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.aidl b/telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.aidl
deleted file mode 100644
index 86928bf..0000000
--- a/telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsMessageQueryResultParcelable;
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.java b/telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.java
deleted file mode 100644
index 4972f9b..0000000
--- a/telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.ims.RcsTypeIdPair;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @hide - used only for internal communication with the ircs service
- */
-public class RcsMessageQueryResultParcelable implements Parcelable {
-    // The token to continue the query to get the next batch of results
-    final RcsQueryContinuationToken mContinuationToken;
-    // The message type and message ID pairs for all the messages in this query result
-    final List<RcsTypeIdPair> mMessageTypeIdPairs;
-
-    public RcsMessageQueryResultParcelable(
-            RcsQueryContinuationToken continuationToken,
-            List<RcsTypeIdPair> messageTypeIdPairs) {
-        mContinuationToken = continuationToken;
-        mMessageTypeIdPairs = messageTypeIdPairs;
-    }
-
-    private RcsMessageQueryResultParcelable(Parcel in) {
-        mContinuationToken = in.readParcelable(
-                RcsQueryContinuationToken.class.getClassLoader());
-
-        mMessageTypeIdPairs = new ArrayList<>();
-        in.readTypedList(mMessageTypeIdPairs, RcsTypeIdPair.CREATOR);
-    }
-
-    public static final Creator<RcsMessageQueryResultParcelable> CREATOR =
-            new Creator<RcsMessageQueryResultParcelable>() {
-                @Override
-                public RcsMessageQueryResultParcelable createFromParcel(Parcel in) {
-                    return new RcsMessageQueryResultParcelable(in);
-                }
-
-                @Override
-                public RcsMessageQueryResultParcelable[] newArray(int size) {
-                    return new RcsMessageQueryResultParcelable[size];
-                }
-            };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeParcelable(mContinuationToken, flags);
-        dest.writeTypedList(mMessageTypeIdPairs);
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsMessageSnippet.aidl b/telephony/java/android/telephony/ims/RcsMessageSnippet.aidl
deleted file mode 100644
index 99b8eb7..0000000
--- a/telephony/java/android/telephony/ims/RcsMessageSnippet.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsMessageSnippet;
diff --git a/telephony/java/android/telephony/ims/RcsMessageSnippet.java b/telephony/java/android/telephony/ims/RcsMessageSnippet.java
deleted file mode 100644
index 8103160..0000000
--- a/telephony/java/android/telephony/ims/RcsMessageSnippet.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.telephony.ims.RcsMessage.RcsMessageStatus;
-
-/**
- * An immutable summary of the latest {@link RcsMessage} on an {@link RcsThread}
- *
- * @hide
- */
-public final class RcsMessageSnippet implements Parcelable {
-    private final String mText;
-    private final @RcsMessageStatus int mStatus;
-    private final long mTimestamp;
-
-    /**
-     * @hide
-     */
-    public RcsMessageSnippet(String text, @RcsMessageStatus int status, long timestamp) {
-        mText = text;
-        mStatus = status;
-        mTimestamp = timestamp;
-    }
-
-    /**
-     * @return Returns the text of the {@link RcsMessage} with highest origination timestamp value
-     * (i.e. latest) in this thread
-     */
-    @Nullable
-    public String getSnippetText() {
-        return mText;
-    }
-
-    /**
-     * @return Returns the status of the {@link RcsMessage} with highest origination timestamp value
-     * (i.e. latest) in this thread
-     */
-    public @RcsMessageStatus int getSnippetStatus() {
-        return mStatus;
-    }
-
-    /**
-     * @return Returns the timestamp of the {@link RcsMessage} with highest origination timestamp
-     * value (i.e. latest) in this thread
-     */
-    public long getSnippetTimestamp() {
-        return mTimestamp;
-    }
-
-    private RcsMessageSnippet(Parcel in) {
-        mText = in.readString();
-        mStatus = in.readInt();
-        mTimestamp = in.readLong();
-    }
-
-    public static final @android.annotation.NonNull Creator<RcsMessageSnippet> CREATOR =
-            new Creator<RcsMessageSnippet>() {
-                @Override
-                public RcsMessageSnippet createFromParcel(Parcel in) {
-                    return new RcsMessageSnippet(in);
-                }
-
-                @Override
-                public RcsMessageSnippet[] newArray(int size) {
-                    return new RcsMessageSnippet[size];
-                }
-            };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeString(mText);
-        dest.writeInt(mStatus);
-        dest.writeLong(mTimestamp);
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsMessageStoreException.java b/telephony/java/android/telephony/ims/RcsMessageStoreException.java
deleted file mode 100644
index 3b3fcf2..0000000
--- a/telephony/java/android/telephony/ims/RcsMessageStoreException.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-/**
- * An exception that happened on {@link RcsMessageStore} or one of the derived storage classes in
- * {@link android.telephony.ims}
- *
- * @hide
- */
-public class RcsMessageStoreException extends Exception {
-
-    /**
-     * Constructs an {@link RcsMessageStoreException} with the specified detail message.
-     * @param message The detail message
-     * @see Throwable#getMessage()
-     */
-    public RcsMessageStoreException(String message) {
-        super(message);
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsOutgoingMessage.java b/telephony/java/android/telephony/ims/RcsOutgoingMessage.java
deleted file mode 100644
index 7080ec6..0000000
--- a/telephony/java/android/telephony/ims/RcsOutgoingMessage.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.telephony.ims;
-
-import android.annotation.NonNull;
-import android.annotation.WorkerThread;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * This is a single instance of a message sent over RCS.
- *
- * @hide
- */
-public class RcsOutgoingMessage extends RcsMessage {
-    RcsOutgoingMessage(RcsControllerCall rcsControllerCall, int id) {
-        super(rcsControllerCall, id);
-    }
-
-    /**
-     * @return Returns the {@link RcsOutgoingMessageDelivery}s associated with this message. Please
-     * note that the deliveries returned for the {@link RcsOutgoingMessage} may not always match the
-     * {@link RcsParticipant}s on the {@link RcsGroupThread} as the group recipients may have
-     * changed.
-     * @throws RcsMessageStoreException if the outgoing deliveries could not be read from storage.
-     */
-    @NonNull
-    @WorkerThread
-    public List<RcsOutgoingMessageDelivery> getOutgoingDeliveries()
-            throws RcsMessageStoreException {
-        int[] deliveryParticipants;
-        List<RcsOutgoingMessageDelivery> messageDeliveries = new ArrayList<>();
-
-        deliveryParticipants = mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getMessageRecipients(mId, callingPackage));
-
-        if (deliveryParticipants != null) {
-            for (Integer deliveryParticipant : deliveryParticipants) {
-                messageDeliveries.add(new RcsOutgoingMessageDelivery(
-                        mRcsControllerCall, deliveryParticipant, mId));
-            }
-        }
-
-        return messageDeliveries;
-    }
-
-    /**
-     * @return Returns {@code false} as this is not an incoming message.
-     */
-    @Override
-    public boolean isIncoming() {
-        return false;
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsOutgoingMessageCreationParams.aidl b/telephony/java/android/telephony/ims/RcsOutgoingMessageCreationParams.aidl
deleted file mode 100644
index 0c38d9f..0000000
--- a/telephony/java/android/telephony/ims/RcsOutgoingMessageCreationParams.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsOutgoingMessageCreationParams;
diff --git a/telephony/java/android/telephony/ims/RcsOutgoingMessageCreationParams.java b/telephony/java/android/telephony/ims/RcsOutgoingMessageCreationParams.java
deleted file mode 100644
index c001ffb..0000000
--- a/telephony/java/android/telephony/ims/RcsOutgoingMessageCreationParams.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * {@link RcsOutgoingMessageCreationParams} is a collection of parameters that should be passed
- * into {@link RcsThread#addOutgoingMessage(RcsOutgoingMessageCreationParams)} to generate an
- * {@link RcsOutgoingMessage} on that {@link RcsThread}
- *
- * @hide
- */
-public final class RcsOutgoingMessageCreationParams extends RcsMessageCreationParams
-        implements Parcelable {
-    /**
-     * A builder to instantiate and persist an {@link RcsOutgoingMessage}
-     */
-    public static class Builder extends RcsMessageCreationParams.Builder {
-
-        /**
-         * Creates a new {@link Builder} to create an instance of
-         * {@link RcsOutgoingMessageCreationParams}.
-         *
-         * @param originationTimestamp The timestamp of {@link RcsMessage} creation. The origination
-         *                             timestamp value in milliseconds passed after midnight,
-         *                             January 1, 1970 UTC
-         * @param subscriptionId The subscription ID that was used to send or receive this
-         *                       {@link RcsMessage}
-         * @see android.telephony.SubscriptionInfo#getSubscriptionId()
-         */
-        public Builder(long originationTimestamp, int subscriptionId) {
-            super(originationTimestamp, subscriptionId);
-        }
-
-        /**
-         * Creates configuration parameters for a new message.
-         */
-        public RcsOutgoingMessageCreationParams build() {
-            return new RcsOutgoingMessageCreationParams(this);
-        }
-    }
-
-    private RcsOutgoingMessageCreationParams(Builder builder) {
-        super(builder);
-    }
-
-    private RcsOutgoingMessageCreationParams(Parcel in) {
-        super(in);
-    }
-
-    public static final @NonNull Creator<RcsOutgoingMessageCreationParams> CREATOR =
-            new Creator<RcsOutgoingMessageCreationParams>() {
-                @Override
-                public RcsOutgoingMessageCreationParams createFromParcel(Parcel in) {
-                    return new RcsOutgoingMessageCreationParams(in);
-                }
-
-                @Override
-                public RcsOutgoingMessageCreationParams[] newArray(int size) {
-                    return new RcsOutgoingMessageCreationParams[size];
-                }
-            };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        super.writeToParcel(dest);
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java b/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java
deleted file mode 100644
index df4a3e4..0000000
--- a/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.telephony.ims;
-
-import android.annotation.NonNull;
-import android.annotation.WorkerThread;
-
-/**
- * This class holds the delivery information of an {@link RcsOutgoingMessage} for each
- * {@link RcsParticipant} that the message was intended for.
- *
- * @hide
- */
-public class RcsOutgoingMessageDelivery {
-    private final RcsControllerCall mRcsControllerCall;
-    // The participant that this delivery is intended for
-    private final int mRecipientId;
-    // The message this delivery is associated with
-    private final int mRcsOutgoingMessageId;
-
-    /**
-     * Constructor to be used with RcsOutgoingMessage.getDelivery()
-     *
-     * @hide
-     */
-    RcsOutgoingMessageDelivery(
-            RcsControllerCall rcsControllerCall, int recipientId, int messageId) {
-        mRcsControllerCall = rcsControllerCall;
-        mRecipientId = recipientId;
-        mRcsOutgoingMessageId = messageId;
-    }
-
-    /**
-     * Sets the delivery time of this outgoing delivery and persists into storage.
-     *
-     * @param deliveredTimestamp The timestamp to set to delivery. It is defined as milliseconds
-     *                           passed after midnight, January 1, 1970 UTC
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @WorkerThread
-    public void setDeliveredTimestamp(long deliveredTimestamp) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setOutgoingDeliveryDeliveredTimestamp(
-                        mRcsOutgoingMessageId, mRecipientId, deliveredTimestamp, callingPackage));
-    }
-
-    /**
-     * @return Returns the delivered timestamp of the associated message to the associated
-     * participant. Timestamp is defined as milliseconds passed after midnight, January 1, 1970 UTC.
-     * Returns 0 if the {@link RcsOutgoingMessage} is not delivered yet.
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @WorkerThread
-    public long getDeliveredTimestamp() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getOutgoingDeliveryDeliveredTimestamp(
-                        mRcsOutgoingMessageId, mRecipientId, callingPackage));
-    }
-
-    /**
-     * Sets the seen time of this outgoing delivery and persists into storage.
-     *
-     * @param seenTimestamp The timestamp to set to delivery. It is defined as milliseconds
-     *                      passed after midnight, January 1, 1970 UTC
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @WorkerThread
-    public void setSeenTimestamp(long seenTimestamp) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setOutgoingDeliverySeenTimestamp(
-                        mRcsOutgoingMessageId, mRecipientId, seenTimestamp, callingPackage));
-    }
-
-    /**
-     * @return Returns the seen timestamp of the associated message by the associated
-     * participant. Timestamp is defined as milliseconds passed after midnight, January 1, 1970 UTC.
-     * Returns 0 if the {@link RcsOutgoingMessage} is not seen yet.
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @WorkerThread
-    public long getSeenTimestamp() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getOutgoingDeliverySeenTimestamp(
-                        mRcsOutgoingMessageId, mRecipientId, callingPackage));
-    }
-
-    /**
-     * Sets the status of this outgoing delivery and persists into storage.
-     *
-     * @param status The status of the associated {@link RcsMessage}s delivery to the associated
-     *               {@link RcsParticipant}
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @WorkerThread
-    public void setStatus(@RcsMessage.RcsMessageStatus int status) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setOutgoingDeliveryStatus(
-                        mRcsOutgoingMessageId, mRecipientId, status, callingPackage));
-    }
-
-    /**
-     * @return Returns the status of this outgoing delivery.
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @WorkerThread
-    public @RcsMessage.RcsMessageStatus int getStatus() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getOutgoingDeliveryStatus(mRcsOutgoingMessageId,
-                        mRecipientId, callingPackage));
-    }
-
-    /**
-     * @return Returns the recipient associated with this delivery.
-     */
-    @NonNull
-    public RcsParticipant getRecipient() {
-        return new RcsParticipant(mRcsControllerCall, mRecipientId);
-    }
-
-    /**
-     * @return Returns the {@link RcsOutgoingMessage} associated with this delivery.
-     */
-    @NonNull
-    public RcsOutgoingMessage getMessage() {
-        return new RcsOutgoingMessage(mRcsControllerCall, mRcsOutgoingMessageId);
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsParticipant.java b/telephony/java/android/telephony/ims/RcsParticipant.java
deleted file mode 100644
index 8512e96..0000000
--- a/telephony/java/android/telephony/ims/RcsParticipant.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.telephony.ims;
-
-import android.annotation.Nullable;
-import android.annotation.WorkerThread;
-
-/**
- * RcsParticipant is an RCS capable contact that can participate in {@link RcsThread}s.
- *
- * @hide
- */
-public class RcsParticipant {
-    private final RcsControllerCall mRcsControllerCall;
-    // The row ID of this participant in the database
-    private final int mId;
-
-    /**
-     * Constructor for {@link com.android.internal.telephony.ims.RcsMessageStoreController}
-     * to create instances of participants. This is not meant to be part of the SDK.
-     *
-     * @hide
-     */
-    public RcsParticipant(RcsControllerCall rcsControllerCall, int id) {
-        mRcsControllerCall = rcsControllerCall;
-        mId = id;
-    }
-
-    /**
-     * @return Returns the canonical address (i.e. normalized phone number) for this
-     * {@link RcsParticipant}
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @Nullable
-    @WorkerThread
-    public String getCanonicalAddress() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getRcsParticipantCanonicalAddress(mId,
-                        callingPackage));
-    }
-
-    /**
-     * @return Returns the alias for this {@link RcsParticipant}. Alias is usually the real name of
-     * the person themselves. Please see US5-15 - GSMA RCC.71 (RCS Universal Profile Service
-     * Definition Document)
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @Nullable
-    @WorkerThread
-    public String getAlias() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getRcsParticipantAlias(mId, callingPackage));
-    }
-
-    /**
-     * Sets the alias for this {@link RcsParticipant} and persists it in storage. Alias is usually
-     * the real name of the person themselves. Please see US5-15 - GSMA RCC.71 (RCS Universal
-     * Profile Service Definition Document)
-     *
-     * @param alias The alias to set to.
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @WorkerThread
-    public void setAlias(String alias) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setRcsParticipantAlias(mId, alias, callingPackage));
-    }
-
-    /**
-     * @return Returns the contact ID for this {@link RcsParticipant}. Contact ID is a unique ID for
-     * an {@link RcsParticipant} that is RCS provisioned. Please see 4.4.5 - GSMA RCC.53 (RCS Device
-     * API 1.6 Specification)
-     * @throws RcsMessageStoreException if the value could not be read from the storage
-     */
-    @Nullable
-    @WorkerThread
-    public String getContactId() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getRcsParticipantContactId(mId, callingPackage));
-    }
-
-    /**
-     * Sets the contact ID for this {@link RcsParticipant}. Contact ID is a unique ID for
-     * an {@link RcsParticipant} that is RCS provisioned. Please see 4.4.5 - GSMA RCC.53 (RCS Device
-     * API 1.6 Specification)
-     *
-     * @param contactId The contact ID to set to.
-     * @throws RcsMessageStoreException if the value could not be persisted into storage
-     */
-    @WorkerThread
-    public void setContactId(String contactId) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.setRcsParticipantContactId(mId, contactId,
-                        callingPackage));
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!(obj instanceof RcsParticipant)) {
-            return false;
-        }
-        RcsParticipant other = (RcsParticipant) obj;
-
-        return mId == other.mId;
-    }
-
-    @Override
-    public int hashCode() {
-        return mId;
-    }
-
-    /**
-     * Returns the row id of this participant. This is not meant to be part of the SDK
-     *
-     * @hide
-     */
-    public int getId() {
-        return mId;
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java
deleted file mode 100644
index 865bc05..0000000
--- a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.telephony.ims;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-
-/**
- * An event that indicates an {@link RcsParticipant}'s alias was changed. Please see US18-2 - GSMA
- * RCC.71 (RCS Universal Profile Service Definition Document)
- *
- * @hide
- */
-public final class RcsParticipantAliasChangedEvent extends RcsEvent {
-    // The participant that changed their alias
-    private final RcsParticipant mParticipant;
-    // The new alias of the above participant
-    private final String mNewAlias;
-
-    /**
-     * Creates a new {@link RcsParticipantAliasChangedEvent}. This event is not persisted into
-     * storage until {@link RcsMessageStore#persistRcsEvent(RcsEvent)} is called.
-     *
-     * @param timestamp The timestamp of when this event happened, in milliseconds passed after
-     *                  midnight, January 1st, 1970 UTC
-     * @param participant The {@link RcsParticipant} that got their alias changed
-     * @param newAlias The new alias the {@link RcsParticipant} has.
-     * @see RcsMessageStore#persistRcsEvent(RcsEvent)
-     */
-    public RcsParticipantAliasChangedEvent(long timestamp, @NonNull RcsParticipant participant,
-            @Nullable String newAlias) {
-        super(timestamp);
-        mParticipant = participant;
-        mNewAlias = newAlias;
-    }
-
-    /**
-     * @return Returns the {@link RcsParticipant} whose alias was changed.
-     */
-    @NonNull
-    public RcsParticipant getParticipant() {
-        return mParticipant;
-    }
-
-    /**
-     * @return Returns the alias of the associated {@link RcsParticipant} after this event happened
-     */
-    @Nullable
-    public String getNewAlias() {
-        return mNewAlias;
-    }
-
-    /**
-     * Persists the event to the data store.
-     *
-     * @hide - not meant for public use.
-     */
-    @Override
-    void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException {
-        rcsControllerCall.call((iRcs, callingPackage) -> iRcs.createParticipantAliasChangedEvent(
-                getTimestamp(), getParticipant().getId(), getNewAlias(), callingPackage));
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.aidl b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.aidl
deleted file mode 100644
index 64fe3b8..0000000
--- a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsParticipantAliasChangedEventDescriptor;
diff --git a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java
deleted file mode 100644
index 43b918c..0000000
--- a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.telephony.ims;
-
-import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * @hide - used only for internal communication with the ircs service
- */
-public class RcsParticipantAliasChangedEventDescriptor extends RcsEventDescriptor {
-    // The ID of the participant that changed their alias
-    protected int mParticipantId;
-    // The new alias of the above participant
-    protected String mNewAlias;
-
-    public RcsParticipantAliasChangedEventDescriptor(long timestamp, int participantId,
-            @Nullable String newAlias) {
-        super(timestamp);
-        mParticipantId = participantId;
-        mNewAlias = newAlias;
-    }
-
-    @Override
-    @VisibleForTesting(visibility = PROTECTED)
-    public RcsParticipantAliasChangedEvent createRcsEvent(RcsControllerCall rcsControllerCall) {
-        return new RcsParticipantAliasChangedEvent(
-                mTimestamp, new RcsParticipant(rcsControllerCall, mParticipantId), mNewAlias);
-    }
-
-    public static final @NonNull Creator<RcsParticipantAliasChangedEventDescriptor> CREATOR =
-            new Creator<RcsParticipantAliasChangedEventDescriptor>() {
-                @Override
-                public RcsParticipantAliasChangedEventDescriptor createFromParcel(Parcel in) {
-                    return new RcsParticipantAliasChangedEventDescriptor(in);
-                }
-
-                @Override
-                public RcsParticipantAliasChangedEventDescriptor[] newArray(int size) {
-                    return new RcsParticipantAliasChangedEventDescriptor[size];
-                }
-            };
-
-    protected RcsParticipantAliasChangedEventDescriptor(Parcel in) {
-        super(in);
-        mNewAlias = in.readString();
-        mParticipantId = in.readInt();
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        super.writeToParcel(dest, flags);
-        dest.writeString(mNewAlias);
-        dest.writeInt(mParticipantId);
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsParticipantQueryParams.aidl b/telephony/java/android/telephony/ims/RcsParticipantQueryParams.aidl
deleted file mode 100644
index b7c0f93..0000000
--- a/telephony/java/android/telephony/ims/RcsParticipantQueryParams.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsParticipantQueryParams;
diff --git a/telephony/java/android/telephony/ims/RcsParticipantQueryParams.java b/telephony/java/android/telephony/ims/RcsParticipantQueryParams.java
deleted file mode 100644
index 21107a2..0000000
--- a/telephony/java/android/telephony/ims/RcsParticipantQueryParams.java
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-import android.annotation.CheckResult;
-import android.annotation.IntDef;
-import android.annotation.IntRange;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.security.InvalidParameterException;
-
-/**
- * The parameters to pass into
- * {@link RcsMessageStore#getRcsParticipants(RcsParticipantQueryParams)} in order to select a
- * subset of {@link RcsThread}s present in the message store.
- *
- * @hide
- */
-public final class RcsParticipantQueryParams implements Parcelable {
-    /**
-     * Flag to set with {@link Builder#setSortProperty(int)} to sort the results in the order of
-     * creation time for faster query results
-     */
-    public static final int SORT_BY_CREATION_ORDER = 0;
-
-    /**
-     * Flag to set with {@link Builder#setSortProperty(int)} to sort depending on the
-     * {@link RcsParticipant} aliases
-     */
-    public static final int SORT_BY_ALIAS = 1;
-
-    /**
-     * Flag to set with {@link Builder#setSortProperty(int)} to sort depending on the
-     * {@link RcsParticipant} canonical addresses
-     */
-    public static final int SORT_BY_CANONICAL_ADDRESS = 2;
-
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({SORT_BY_CREATION_ORDER, SORT_BY_ALIAS, SORT_BY_CANONICAL_ADDRESS})
-    public @interface SortingProperty {
-    }
-
-    // The SQL "like" statement to filter against participant aliases
-    private String mAliasLike;
-    // The SQL "like" statement to filter against canonical addresses
-    private String mCanonicalAddressLike;
-    // The property to sort the result against
-    private @SortingProperty int mSortingProperty;
-    // Whether to sort the result in ascending order
-    private boolean mIsAscending;
-    // The number of results to be returned from the query
-    private int mLimit;
-    // Used to limit the results to participants of a single thread
-    private int mThreadId;
-
-    /**
-     * @hide
-     */
-    public static final String PARTICIPANT_QUERY_PARAMETERS_KEY = "participant_query_parameters";
-
-    RcsParticipantQueryParams(int rcsThreadId, String aliasLike, String canonicalAddressLike,
-            @SortingProperty int sortingProperty, boolean isAscending,
-            int limit) {
-        mThreadId = rcsThreadId;
-        mAliasLike = aliasLike;
-        mCanonicalAddressLike = canonicalAddressLike;
-        mSortingProperty = sortingProperty;
-        mIsAscending = isAscending;
-        mLimit = limit;
-    }
-
-    /**
-     * This is used in {@link com.android.internal.telephony.ims.RcsMessageStoreController} to get
-     * the thread that the result query should be limited to.
-     *
-     * As we do not expose any sort of integer ID's to public usage, this should be hidden.
-     *
-     * @hide - not meant for public use
-     */
-    public int getThreadId() {
-        return mThreadId;
-    }
-
-    /**
-     * @return Returns the SQL-inspired "LIKE" clause that will be used to match
-     * {@link RcsParticipant}s with respect to their aliases
-     *
-     * @see RcsParticipant#getAlias()
-     */
-    public String getAliasLike() {
-        return mAliasLike;
-    }
-
-    /**
-     * @return Returns the SQL-inspired "LIKE" clause that will be used to match
-     * {@link RcsParticipant}s with respect to their canonical addresses.
-     *
-     * @see RcsParticipant#getCanonicalAddress()
-     */
-    public String getCanonicalAddressLike() {
-        return mCanonicalAddressLike;
-    }
-
-    /**
-     * @return Returns the number of {@link RcsParticipant}s to be returned from the query. A value
-     * of 0 means there is no set limit.
-     */
-    public int getLimit() {
-        return mLimit;
-    }
-
-    /**
-     * @return Returns the property that will be used to sort the result against.
-     * @see SortingProperty
-     */
-    public int getSortingProperty() {
-        return mSortingProperty;
-    }
-
-    /**
-     * @return Returns {@code true} if the result set will be sorted in ascending order,
-     * {@code false} if it will be sorted in descending order.
-     */
-    public boolean getSortDirection() {
-        return mIsAscending;
-    }
-
-    /**
-     * A helper class to build the {@link RcsParticipantQueryParams}.
-     */
-    public static class Builder {
-        private String mAliasLike;
-        private String mCanonicalAddressLike;
-        private @SortingProperty int mSortingProperty;
-        private boolean mIsAscending;
-        private int mLimit = 100;
-        private int mThreadId;
-
-        /**
-         * Creates a new builder for {@link RcsParticipantQueryParams} to be used in
-         * {@link RcsMessageStore#getRcsParticipants(RcsParticipantQueryParams)}
-         */
-        public Builder() {
-            // empty implementation
-        }
-
-        /**
-         * Limits the resulting {@link RcsParticipant}s to only the given {@link RcsThread}
-         *
-         * @param rcsThread The thread that the participants should be searched in.
-         * @return The same {@link Builder} to chain methods.
-         */
-        @CheckResult
-        public Builder setThread(RcsThread rcsThread) {
-            mThreadId = rcsThread.getThreadId();
-            return this;
-        }
-
-        /**
-         * Sets an SQL-inspired "like" clause to match with participant aliases. Using a percent
-         * sign ('%') wildcard matches any sequence of zero or more characters. Using an underscore
-         * ('_') wildcard matches any single character. Not using any wildcards would only perform a
-         * string match.The input string is case-insensitive.
-         *
-         * The input "An%e" would match {@link RcsParticipant}s with names Anne, Annie, Antonie,
-         * while the input "An_e" would only match Anne.
-         *
-         * @param likeClause The like clause to use for matching {@link RcsParticipant} aliases.
-         * @return The same {@link Builder} to chain methods
-         */
-        @CheckResult
-        public Builder setAliasLike(String likeClause) {
-            mAliasLike = likeClause;
-            return this;
-        }
-
-        /**
-         * Sets an SQL-inspired "like" clause to match with participant addresses. Using a percent
-         * sign ('%') wildcard matches any sequence of zero or more characters. Using an underscore
-         * ('_') wildcard matches any single character. Not using any wildcards would only perform a
-         * string match. The input string is case-insensitive.
-         *
-         * The input "+999%111" would match {@link RcsParticipant}s with addresses like "+9995111"
-         * or "+99955555111", while the input "+999_111" would only match "+9995111".
-         *
-         * @param likeClause The like clause to use for matching {@link RcsParticipant} canonical
-         *                   addresses.
-         * @return The same {@link Builder} to chain methods
-         */
-        @CheckResult
-        public Builder setCanonicalAddressLike(String likeClause) {
-            mCanonicalAddressLike = likeClause;
-            return this;
-        }
-
-        /**
-         * Desired number of threads to be returned from the query. Passing in 0 will return all
-         * existing threads at once. The limit defaults to 100.
-         *
-         * @param limit The number to limit the query result to.
-         * @return The same instance of the builder to chain parameters.
-         * @throws InvalidParameterException If the given limit is negative.
-         */
-        @CheckResult
-        public Builder setResultLimit(@IntRange(from = 0) int limit)
-                throws InvalidParameterException {
-            if (limit < 0) {
-                throw new InvalidParameterException("The query limit must be non-negative");
-            }
-
-            mLimit = limit;
-            return this;
-        }
-
-        /**
-         * Sets the property where the results should be sorted against. Defaults to
-         * {@link RcsParticipantQueryParams.SortingProperty#SORT_BY_CREATION_ORDER}
-         *
-         * @param sortingProperty against which property the results should be sorted
-         * @return The same instance of the builder to chain parameters.
-         */
-        @CheckResult
-        public Builder setSortProperty(@SortingProperty int sortingProperty) {
-            mSortingProperty = sortingProperty;
-            return this;
-        }
-
-        /**
-         * Sets whether the results should be sorted ascending or descending
-         *
-         * @param isAscending whether the results should be sorted ascending
-         * @return The same instance of the builder to chain parameters.
-         */
-        @CheckResult
-        public Builder setSortDirection(boolean isAscending) {
-            mIsAscending = isAscending;
-            return this;
-        }
-
-        /**
-         * Builds the {@link RcsParticipantQueryParams} to use in
-         * {@link RcsMessageStore#getRcsParticipants(RcsParticipantQueryParams)}
-         *
-         * @return An instance of {@link RcsParticipantQueryParams} to use with the participant
-         * query.
-         */
-        public RcsParticipantQueryParams build() {
-            return new RcsParticipantQueryParams(mThreadId, mAliasLike, mCanonicalAddressLike,
-                    mSortingProperty, mIsAscending, mLimit);
-        }
-    }
-
-    /**
-     * Parcelable boilerplate below.
-     */
-    private RcsParticipantQueryParams(Parcel in) {
-        mAliasLike = in.readString();
-        mCanonicalAddressLike = in.readString();
-        mSortingProperty = in.readInt();
-        mIsAscending = in.readByte() == 1;
-        mLimit = in.readInt();
-        mThreadId = in.readInt();
-    }
-
-    public static final @android.annotation.NonNull Creator<RcsParticipantQueryParams> CREATOR =
-            new Creator<RcsParticipantQueryParams>() {
-                @Override
-                public RcsParticipantQueryParams createFromParcel(Parcel in) {
-                    return new RcsParticipantQueryParams(in);
-                }
-
-                @Override
-                public RcsParticipantQueryParams[] newArray(int size) {
-                    return new RcsParticipantQueryParams[size];
-                }
-            };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeString(mAliasLike);
-        dest.writeString(mCanonicalAddressLike);
-        dest.writeInt(mSortingProperty);
-        dest.writeByte((byte) (mIsAscending ? 1 : 0));
-        dest.writeInt(mLimit);
-        dest.writeInt(mThreadId);
-    }
-
-}
diff --git a/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java b/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java
deleted file mode 100644
index 0721dfd..0000000
--- a/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * The result of a {@link RcsMessageStore#getRcsParticipants(RcsParticipantQueryParams)}
- * call. This class allows getting the token for querying the next batch of participants in order to
- * prevent handling large amounts of data at once.
- *
- * @hide
- */
-public final class RcsParticipantQueryResult {
-    private final RcsControllerCall mRcsControllerCall;
-    private final RcsParticipantQueryResultParcelable mRcsParticipantQueryResultParcelable;
-
-    RcsParticipantQueryResult(
-            RcsControllerCall rcsControllerCall,
-            RcsParticipantQueryResultParcelable rcsParticipantQueryResultParcelable) {
-        mRcsControllerCall = rcsControllerCall;
-        mRcsParticipantQueryResultParcelable = rcsParticipantQueryResultParcelable;
-    }
-
-    /**
-     * Returns a token to call
-     * {@link RcsMessageStore#getRcsParticipants(RcsQueryContinuationToken)}
-     * to get the next batch of {@link RcsParticipant}s.
-     */
-    @Nullable
-    public RcsQueryContinuationToken getContinuationToken() {
-        return mRcsParticipantQueryResultParcelable.mContinuationToken;
-    }
-
-    /**
-     * Returns all the {@link RcsParticipant}s in the current query result. Call {@link
-     * RcsMessageStore#getRcsParticipants(RcsQueryContinuationToken)} to get the next
-     * batch of {@link RcsParticipant}s.
-     */
-    @NonNull
-    public List<RcsParticipant> getParticipants() {
-        return mRcsParticipantQueryResultParcelable.mParticipantIds.stream()
-                .map(participantId -> new RcsParticipant(mRcsControllerCall, participantId))
-                .collect(Collectors.toList());
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsParticipantQueryResultParcelable.aidl b/telephony/java/android/telephony/ims/RcsParticipantQueryResultParcelable.aidl
deleted file mode 100644
index 54c72e7..0000000
--- a/telephony/java/android/telephony/ims/RcsParticipantQueryResultParcelable.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsParticipantQueryResultParcelable;
diff --git a/telephony/java/android/telephony/ims/RcsParticipantQueryResultParcelable.java b/telephony/java/android/telephony/ims/RcsParticipantQueryResultParcelable.java
deleted file mode 100644
index 239b0e9..0000000
--- a/telephony/java/android/telephony/ims/RcsParticipantQueryResultParcelable.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @hide
- */
-public final class RcsParticipantQueryResultParcelable implements Parcelable {
-    final RcsQueryContinuationToken mContinuationToken;
-    final List<Integer> mParticipantIds;
-
-    public RcsParticipantQueryResultParcelable(
-            RcsQueryContinuationToken continuationToken,
-            List<Integer> participantIds) {
-        mContinuationToken = continuationToken;
-        mParticipantIds = participantIds;
-    }
-
-    private RcsParticipantQueryResultParcelable(Parcel in) {
-        mContinuationToken = in.readParcelable(RcsQueryContinuationToken.class.getClassLoader());
-        mParticipantIds = new ArrayList<>();
-        in.readList(mParticipantIds, Integer.class.getClassLoader());
-    }
-
-    public static final Parcelable.Creator<RcsParticipantQueryResultParcelable> CREATOR =
-            new Parcelable.Creator<RcsParticipantQueryResultParcelable>() {
-                @Override
-                public RcsParticipantQueryResultParcelable createFromParcel(Parcel in) {
-                    return new RcsParticipantQueryResultParcelable(in);
-                }
-
-                @Override
-                public RcsParticipantQueryResultParcelable[] newArray(int size) {
-                    return new RcsParticipantQueryResultParcelable[size];
-                }
-            };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeParcelable(mContinuationToken, flags);
-        dest.writeList(mParticipantIds);
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsQueryContinuationToken.aidl b/telephony/java/android/telephony/ims/RcsQueryContinuationToken.aidl
deleted file mode 100644
index 319379a..0000000
--- a/telephony/java/android/telephony/ims/RcsQueryContinuationToken.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsQueryContinuationToken;
diff --git a/telephony/java/android/telephony/ims/RcsQueryContinuationToken.java b/telephony/java/android/telephony/ims/RcsQueryContinuationToken.java
deleted file mode 100644
index 982263a..0000000
--- a/telephony/java/android/telephony/ims/RcsQueryContinuationToken.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-import android.annotation.IntDef;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * A token for enabling continuation queries. Instances are acquired through
- * {@code getContinuationToken} on result objects after initial query is done.
- *
- * @see RcsEventQueryResult#getContinuationToken()
- * @see RcsMessageQueryResult#getContinuationToken()
- * @see RcsParticipantQueryResult#getContinuationToken()
- * @see RcsThreadQueryResult#getContinuationToken()
- *
- * @hide
- */
-public final class RcsQueryContinuationToken implements Parcelable {
-    /**
-     * Denotes that this {@link RcsQueryContinuationToken} token is meant to allow continuing
-     * {@link RcsEvent} queries
-     */
-    public static final int EVENT_QUERY_CONTINUATION_TOKEN_TYPE = 0;
-
-    /**
-     * Denotes that this {@link RcsQueryContinuationToken} token is meant to allow continuing
-     * {@link RcsMessage} queries
-     */
-    public static final int MESSAGE_QUERY_CONTINUATION_TOKEN_TYPE = 1;
-
-    /**
-     * Denotes that this {@link RcsQueryContinuationToken} token is meant to allow continuing
-     * {@link RcsParticipant} queries
-     */
-    public static final int PARTICIPANT_QUERY_CONTINUATION_TOKEN_TYPE = 2;
-
-    /**
-     * Denotes that this {@link RcsQueryContinuationToken} token is meant to allow continuing
-     * {@link RcsThread} queries
-     */
-    public static final int THREAD_QUERY_CONTINUATION_TOKEN_TYPE = 3;
-
-    /**
-     * @hide - not meant for public use
-     */
-    public static final String QUERY_CONTINUATION_TOKEN = "query_continuation_token";
-
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({EVENT_QUERY_CONTINUATION_TOKEN_TYPE, MESSAGE_QUERY_CONTINUATION_TOKEN_TYPE,
-        PARTICIPANT_QUERY_CONTINUATION_TOKEN_TYPE, THREAD_QUERY_CONTINUATION_TOKEN_TYPE})
-    public @interface ContinuationTokenType {}
-
-    // The type of query this token should allow to continue
-    private @ContinuationTokenType int mQueryType;
-    // The raw query string for the initial query
-    private final String mRawQuery;
-    // The number of results that is returned with each query
-    private final int mLimit;
-    // The offset value that this query should start the query from
-    private int mOffset;
-
-    /**
-     * @hide
-     */
-    public RcsQueryContinuationToken(@ContinuationTokenType int queryType, String rawQuery,
-            int limit, int offset) {
-        mQueryType = queryType;
-        mRawQuery = rawQuery;
-        mLimit = limit;
-        mOffset = offset;
-    }
-
-    /**
-     * Returns the original raw query used on {@link com.android.providers.telephony.RcsProvider}
-     * @hide
-     */
-    public String getRawQuery() {
-        return mRawQuery;
-    }
-
-    /**
-     * Returns which index this continuation query should start from
-     * @hide
-     */
-    public int getOffset() {
-        return mOffset;
-    }
-
-    /**
-     * Increments the offset by the amount of result rows returned with the continuation query for
-     * the next query.
-     * @hide
-     */
-    public void incrementOffset() {
-        mOffset += mLimit;
-    }
-
-    /**
-     * Returns the type of query that this {@link RcsQueryContinuationToken} is intended to be used
-     * to continue.
-     */
-    public @ContinuationTokenType int getQueryType() {
-        return mQueryType;
-    }
-
-    private RcsQueryContinuationToken(Parcel in) {
-        mQueryType = in.readInt();
-        mRawQuery = in.readString();
-        mLimit = in.readInt();
-        mOffset = in.readInt();
-    }
-
-    public static final @android.annotation.NonNull Creator<RcsQueryContinuationToken> CREATOR =
-            new Creator<RcsQueryContinuationToken>() {
-                @Override
-                public RcsQueryContinuationToken createFromParcel(Parcel in) {
-                    return new RcsQueryContinuationToken(in);
-                }
-
-                @Override
-                public RcsQueryContinuationToken[] newArray(int size) {
-                    return new RcsQueryContinuationToken[size];
-                }
-            };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mQueryType);
-        dest.writeString(mRawQuery);
-        dest.writeInt(mLimit);
-        dest.writeInt(mOffset);
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsThread.java b/telephony/java/android/telephony/ims/RcsThread.java
deleted file mode 100644
index efb2cca..0000000
--- a/telephony/java/android/telephony/ims/RcsThread.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-import static android.provider.Telephony.RcsColumns.RcsUnifiedThreadColumns.THREAD_TYPE_1_TO_1;
-import static android.provider.Telephony.RcsColumns.RcsUnifiedThreadColumns.THREAD_TYPE_GROUP;
-
-import android.annotation.NonNull;
-import android.annotation.WorkerThread;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * RcsThread represents a single RCS conversation thread. It holds messages that were sent and
- * received and events that occurred on that thread.
- *
- * @hide
- */
-public abstract class RcsThread {
-    /**
-     * The rcs_participant_thread_id that represents this thread in the database
-     *
-     * @hide
-     */
-    protected int mThreadId;
-
-    /**
-     * @hide
-     */
-    protected final RcsControllerCall mRcsControllerCall;
-
-    /**
-     * @hide
-     */
-    protected RcsThread(RcsControllerCall rcsControllerCall, int threadId) {
-        mThreadId = threadId;
-        mRcsControllerCall = rcsControllerCall;
-    }
-
-    /**
-     * @return Returns the summary of the latest message in this {@link RcsThread} packaged in an
-     * {@link RcsMessageSnippet} object
-     */
-    @WorkerThread
-    @NonNull
-    public RcsMessageSnippet getSnippet() throws RcsMessageStoreException {
-        return mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.getMessageSnippet(mThreadId, callingPackage));
-    }
-
-    /**
-     * Adds a new {@link RcsIncomingMessage} to this RcsThread and persists it in storage.
-     *
-     * @throws RcsMessageStoreException if the message could not be persisted into storage.
-     */
-    @WorkerThread
-    @NonNull
-    public RcsIncomingMessage addIncomingMessage(
-            @NonNull RcsIncomingMessageCreationParams rcsIncomingMessageCreationParams)
-            throws RcsMessageStoreException {
-        int messageId = mRcsControllerCall.call(
-                (iRcs, callingPackage) -> iRcs.addIncomingMessage(mThreadId,
-                        rcsIncomingMessageCreationParams, callingPackage));
-        return new RcsIncomingMessage(mRcsControllerCall, messageId);
-    }
-
-    /**
-     * Adds a new {@link RcsOutgoingMessage} to this RcsThread and persists it in storage.
-     *
-     * @throws RcsMessageStoreException if the message could not be persisted into storage.
-     */
-    @WorkerThread
-    @NonNull
-    public RcsOutgoingMessage addOutgoingMessage(
-            @NonNull RcsOutgoingMessageCreationParams rcsOutgoingMessageCreationParams)
-            throws RcsMessageStoreException {
-        int messageId = mRcsControllerCall.call((iRcs, callingPackage) -> iRcs.addOutgoingMessage(
-                mThreadId, rcsOutgoingMessageCreationParams, callingPackage));
-
-        return new RcsOutgoingMessage(mRcsControllerCall, messageId);
-    }
-
-    /**
-     * Deletes an {@link RcsMessage} from this RcsThread and updates the storage.
-     *
-     * @param rcsMessage The message to delete from the thread
-     * @throws RcsMessageStoreException if the message could not be deleted
-     */
-    @WorkerThread
-    public void deleteMessage(@NonNull RcsMessage rcsMessage) throws RcsMessageStoreException {
-        mRcsControllerCall.callWithNoReturn(
-                (iRcs, callingPackage) -> iRcs.deleteMessage(rcsMessage.getId(),
-                        rcsMessage.isIncoming(), mThreadId,
-                        isGroup(), callingPackage));
-    }
-
-    /**
-     * Convenience function for loading all the {@link RcsMessage}s in this {@link RcsThread}. For
-     * a more detailed and paginated query, please use
-     * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)}
-     *
-     * @return Loads the {@link RcsMessage}s in this thread and returns them in an immutable list.
-     * @throws RcsMessageStoreException if the messages could not be read from the storage
-     */
-    @WorkerThread
-    @NonNull
-    public RcsMessageQueryResult getMessages() throws RcsMessageStoreException {
-        RcsMessageQueryParams queryParams =
-                new RcsMessageQueryParams.Builder().setThread(this).build();
-        return new RcsMessageQueryResult(mRcsControllerCall,
-                mRcsControllerCall.call(
-                        (iRcs, callingPackage) -> iRcs.getMessages(queryParams, callingPackage)));
-    }
-
-    /**
-     * @return Returns whether this is a group thread or not
-     */
-    public abstract boolean isGroup();
-
-    /**
-     * @hide
-     */
-    @VisibleForTesting
-    public int getThreadId() {
-        return mThreadId;
-    }
-
-    /**
-     * @hide
-     */
-    public int getThreadType() {
-        return isGroup() ? THREAD_TYPE_GROUP : THREAD_TYPE_1_TO_1;
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryParams.aidl b/telephony/java/android/telephony/ims/RcsThreadQueryParams.aidl
deleted file mode 100644
index 3f351dc..0000000
--- a/telephony/java/android/telephony/ims/RcsThreadQueryParams.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsThreadQueryParams;
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryParams.java b/telephony/java/android/telephony/ims/RcsThreadQueryParams.java
deleted file mode 100644
index da7cdb0..0000000
--- a/telephony/java/android/telephony/ims/RcsThreadQueryParams.java
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-import android.annotation.CheckResult;
-import android.annotation.IntDef;
-import android.annotation.IntRange;
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.security.InvalidParameterException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * The parameters to pass into {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParams)} in
- * order to select a subset of {@link RcsThread}s present in the message store.
- *
- * @hide
- */
-public final class RcsThreadQueryParams implements Parcelable {
-    /**
-     * Bitmask flag to be used with {@link Builder#setThreadType(int)} to make
-     * {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParams)} return
-     * {@link RcsGroupThread}s.
-     */
-    public static final int THREAD_TYPE_GROUP = 0x0001;
-
-    /**
-     * Bitmask flag to be used with {@link Builder#setThreadType(int)} to make
-     * {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParams)} return
-     * {@link Rcs1To1Thread}s.
-     */
-    public static final int THREAD_TYPE_1_TO_1 = 0x0002;
-
-    // The type of threads to be filtered with the query
-    private final int mThreadType;
-    // The list of participants that are expected in the resulting threads
-    private final List<Integer> mRcsParticipantIds;
-    // The number of RcsThread's that should be returned with this query
-    private final int mLimit;
-    // The property which the result of the query should be sorted against
-    private final @SortingProperty int mSortingProperty;
-    // Whether the sorting should be done in ascending
-    private final boolean mIsAscending;
-
-    /**
-     * Flag to be used with {@link Builder#setSortProperty(int)} to denote that the results should
-     * be sorted in the order of {@link RcsThread} creation time for faster results.
-     */
-    public static final int SORT_BY_CREATION_ORDER = 0;
-
-    /**
-     * Flag to be used with {@link Builder#setSortProperty(int)} to denote that the results should
-     * be sorted according to the timestamp of {@link RcsThread#getSnippet()}
-     */
-    public static final int SORT_BY_TIMESTAMP = 1;
-
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({SORT_BY_CREATION_ORDER, SORT_BY_TIMESTAMP})
-    public @interface SortingProperty {
-    }
-
-    /**
-     * @hide
-     */
-    public static final String THREAD_QUERY_PARAMETERS_KEY = "thread_query_parameters";
-
-    RcsThreadQueryParams(int threadType, Set<RcsParticipant> participants,
-            int limit, int sortingProperty, boolean isAscending) {
-        mThreadType = threadType;
-        mRcsParticipantIds = convertParticipantSetToIdList(participants);
-        mLimit = limit;
-        mSortingProperty = sortingProperty;
-        mIsAscending = isAscending;
-    }
-
-    private static List<Integer> convertParticipantSetToIdList(Set<RcsParticipant> participants) {
-        List<Integer> ids = new ArrayList<>(participants.size());
-        for (RcsParticipant participant : participants) {
-            ids.add(participant.getId());
-        }
-        return ids;
-    }
-
-    /**
-     * This is used in {@link com.android.internal.telephony.ims.RcsMessageStoreController} to get
-     * the list of participant IDs.
-     *
-     * As we don't expose any integer ID's to API users, this should stay hidden
-     *
-     * @hide - not meant for public use
-     */
-    public List<Integer> getRcsParticipantsIds() {
-        return Collections.unmodifiableList(mRcsParticipantIds);
-    }
-
-    /**
-     * @return Returns the bitmask flag for types of {@link RcsThread}s that this query should
-     * return.
-     */
-    public int getThreadType() {
-        return mThreadType;
-    }
-
-    /**
-     * @return Returns the number of {@link RcsThread}s to be returned from the query. A value
-     * of 0 means there is no set limit.
-     */
-    public int getLimit() {
-        return mLimit;
-    }
-
-    /**
-     * @return Returns the property that will be used to sort the result against.
-     * @see SortingProperty
-     */
-    public @SortingProperty int getSortingProperty() {
-        return mSortingProperty;
-    }
-
-    /**
-     * @return Returns {@code true} if the result set will be sorted in ascending order,
-     * {@code false} if it will be sorted in descending order.
-     */
-    public boolean getSortDirection() {
-        return mIsAscending;
-    }
-
-    /**
-     * A helper class to build the {@link RcsThreadQueryParams}.
-     */
-    public static class Builder {
-        private int mThreadType;
-        private Set<RcsParticipant> mParticipants;
-        private int mLimit = 100;
-        private @SortingProperty int mSortingProperty;
-        private boolean mIsAscending;
-
-        /**
-         * Constructs a {@link RcsThreadQueryParams.Builder} to help build an
-         * {@link RcsThreadQueryParams}
-         */
-        public Builder() {
-            mParticipants = new HashSet<>();
-        }
-
-        /**
-         * Limits the query to only return group threads.
-         *
-         * @param threadType Whether to limit the query result to group threads.
-         * @return The same instance of the builder to chain parameters.
-         * @see RcsThreadQueryParams#THREAD_TYPE_GROUP
-         * @see RcsThreadQueryParams#THREAD_TYPE_1_TO_1
-         */
-        @CheckResult
-        public Builder setThreadType(int threadType) {
-            mThreadType = threadType;
-            return this;
-        }
-
-        /**
-         * Limits the query to only return threads that contain the given participant. If this
-         * property was not set, participants will not be taken into account while querying for
-         * threads.
-         *
-         * @param participant The participant that must be included in all of the returned threads.
-         * @return The same instance of the builder to chain parameters.
-         */
-        @CheckResult
-        public Builder setParticipant(@NonNull RcsParticipant participant) {
-            mParticipants.add(participant);
-            return this;
-        }
-
-        /**
-         * Limits the query to only return threads that contain the given list of participants. If
-         * this property was not set, participants will not be taken into account while querying
-         * for threads.
-         *
-         * @param participants An iterable list of participants that must be included in all of the
-         *                     returned threads.
-         * @return The same instance of the builder to chain parameters.
-         */
-        @CheckResult
-        public Builder setParticipants(@NonNull List<RcsParticipant> participants) {
-            mParticipants.addAll(participants);
-            return this;
-        }
-
-        /**
-         * Desired number of threads to be returned from the query. Passing in 0 will return all
-         * existing threads at once. The limit defaults to 100.
-         *
-         * @param limit The number to limit the query result to.
-         * @return The same instance of the builder to chain parameters.
-         * @throws InvalidParameterException If the given limit is negative.
-         */
-        @CheckResult
-        public Builder setResultLimit(@IntRange(from = 0) int limit)
-                throws InvalidParameterException {
-            if (limit < 0) {
-                throw new InvalidParameterException("The query limit must be non-negative");
-            }
-
-            mLimit = limit;
-            return this;
-        }
-
-        /**
-         * Sets the property where the results should be sorted against. Defaults to
-         * {@link SortingProperty#SORT_BY_CREATION_ORDER}
-         *
-         * @param sortingProperty whether to sort in ascending order or not
-         * @return The same instance of the builder to chain parameters.
-         */
-        @CheckResult
-        public Builder setSortProperty(@SortingProperty int sortingProperty) {
-            mSortingProperty = sortingProperty;
-            return this;
-        }
-
-        /**
-         * Sets whether the results should be sorted ascending or descending
-         *
-         * @param isAscending whether the results should be sorted ascending
-         * @return The same instance of the builder to chain parameters.
-         */
-        @CheckResult
-        public Builder setSortDirection(boolean isAscending) {
-            mIsAscending = isAscending;
-            return this;
-        }
-
-        /**
-         * Builds the {@link RcsThreadQueryParams} to use in
-         * {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParams)}
-         *
-         * @return An instance of {@link RcsThreadQueryParams} to use with the thread query.
-         */
-        public RcsThreadQueryParams build() {
-            return new RcsThreadQueryParams(mThreadType, mParticipants, mLimit,
-                    mSortingProperty, mIsAscending);
-        }
-    }
-
-    /**
-     * Parcelable boilerplate below.
-     */
-    private RcsThreadQueryParams(Parcel in) {
-        mThreadType = in.readInt();
-        mRcsParticipantIds = new ArrayList<>();
-        in.readList(mRcsParticipantIds, Integer.class.getClassLoader());
-        mLimit = in.readInt();
-        mSortingProperty = in.readInt();
-        mIsAscending = in.readByte() == 1;
-    }
-
-    public static final @android.annotation.NonNull Creator<RcsThreadQueryParams> CREATOR =
-            new Creator<RcsThreadQueryParams>() {
-                @Override
-                public RcsThreadQueryParams createFromParcel(Parcel in) {
-                    return new RcsThreadQueryParams(in);
-                }
-
-                @Override
-                public RcsThreadQueryParams[] newArray(int size) {
-                    return new RcsThreadQueryParams[size];
-                }
-            };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mThreadType);
-        dest.writeList(mRcsParticipantIds);
-        dest.writeInt(mLimit);
-        dest.writeInt(mSortingProperty);
-        dest.writeByte((byte) (mIsAscending ? 1 : 0));
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryResult.java b/telephony/java/android/telephony/ims/RcsThreadQueryResult.java
deleted file mode 100644
index 3de25de..0000000
--- a/telephony/java/android/telephony/ims/RcsThreadQueryResult.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-import static android.provider.Telephony.RcsColumns.RcsUnifiedThreadColumns.THREAD_TYPE_1_TO_1;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-
-/**
- * The result of a {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParams)}
- * call. This class allows getting the token for querying the next batch of threads in order to
- * prevent handling large amounts of data at once.
- *
- * @hide
- */
-public final class RcsThreadQueryResult {
-    private final RcsControllerCall mRcsControllerCall;
-    private final RcsThreadQueryResultParcelable mRcsThreadQueryResultParcelable;
-
-    RcsThreadQueryResult(RcsControllerCall rcsControllerCall,
-            RcsThreadQueryResultParcelable rcsThreadQueryResultParcelable) {
-        mRcsControllerCall = rcsControllerCall;
-        mRcsThreadQueryResultParcelable = rcsThreadQueryResultParcelable;
-    }
-
-    /**
-     * Returns a token to call
-     * {@link RcsMessageStore#getRcsThreads(RcsQueryContinuationToken)}
-     * to get the next batch of {@link RcsThread}s.
-     */
-    @Nullable
-    public RcsQueryContinuationToken getContinuationToken() {
-        return mRcsThreadQueryResultParcelable.mContinuationToken;
-    }
-
-    /**
-     * Returns all the RcsThreads in the current query result. Call {@link
-     * RcsMessageStore#getRcsThreads(RcsQueryContinuationToken)} to get the next batch of
-     * {@link RcsThread}s.
-     */
-    @NonNull
-    public List<RcsThread> getThreads() {
-        return mRcsThreadQueryResultParcelable.mRcsThreadIds.stream()
-                .map(typeIdPair -> typeIdPair.getType() == THREAD_TYPE_1_TO_1
-                        ? new Rcs1To1Thread(mRcsControllerCall, typeIdPair.getId())
-                        : new RcsGroupThread(mRcsControllerCall, typeIdPair.getId()))
-                .collect(Collectors.toList());
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryResultParcelable.aidl b/telephony/java/android/telephony/ims/RcsThreadQueryResultParcelable.aidl
deleted file mode 100644
index 05bd61d..0000000
--- a/telephony/java/android/telephony/ims/RcsThreadQueryResultParcelable.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsThreadQueryResultParcelable;
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryResultParcelable.java b/telephony/java/android/telephony/ims/RcsThreadQueryResultParcelable.java
deleted file mode 100644
index 89dd1d4..0000000
--- a/telephony/java/android/telephony/ims/RcsThreadQueryResultParcelable.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.ims.RcsTypeIdPair;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @hide
- */
-public final class RcsThreadQueryResultParcelable implements Parcelable {
-    final RcsQueryContinuationToken mContinuationToken;
-    final List<RcsTypeIdPair> mRcsThreadIds;
-
-    public RcsThreadQueryResultParcelable(
-            RcsQueryContinuationToken continuationToken,
-            List<RcsTypeIdPair> rcsThreadIds) {
-        mContinuationToken = continuationToken;
-        mRcsThreadIds = rcsThreadIds;
-    }
-
-    private RcsThreadQueryResultParcelable(Parcel in) {
-        mContinuationToken = in.readParcelable(RcsQueryContinuationToken.class.getClassLoader());
-        mRcsThreadIds = new ArrayList<>();
-        in.readList(mRcsThreadIds, RcsTypeIdPair.class.getClassLoader());
-    }
-
-    public static final Parcelable.Creator<RcsThreadQueryResultParcelable> CREATOR =
-            new Parcelable.Creator<RcsThreadQueryResultParcelable>() {
-                @Override
-                public RcsThreadQueryResultParcelable createFromParcel(Parcel in) {
-                    return new RcsThreadQueryResultParcelable(in);
-                }
-
-                @Override
-                public RcsThreadQueryResultParcelable[] newArray(int size) {
-                    return new RcsThreadQueryResultParcelable[size];
-                }
-            };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeParcelable(mContinuationToken, flags);
-        dest.writeList(mRcsThreadIds);
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java
index 2e3f59a..72a00ce 100644
--- a/telephony/java/android/telephony/ims/RcsUceAdapter.java
+++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java
@@ -21,6 +21,8 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.IBinder;
@@ -28,6 +30,7 @@
 import android.telephony.TelephonyFrameworkInitializer;
 import android.telephony.ims.aidl.IImsRcsController;
 import android.telephony.ims.aidl.IRcsUceControllerCallback;
+import android.telephony.ims.feature.RcsFeature;
 import android.util.Log;
 
 import java.lang.annotation.Retention;
@@ -41,6 +44,8 @@
  * @see ImsRcsManager#getUceAdapter() for information on creating an instance of this class.
  * @hide
  */
+@SystemApi
+@TestApi
 public class RcsUceAdapter {
     private static final String TAG = "RcsUceAdapter";
 
@@ -196,6 +201,7 @@
     /**
      * Not to be instantiated directly, use
      * {@link ImsRcsManager#getUceAdapter()} to instantiate this manager class.
+     * @hide
      */
     RcsUceAdapter(int subId) {
         mSubId = subId;
@@ -221,7 +227,7 @@
      * becomes inactive. See {@link ImsException#getCode()} for more information on the error codes.
      */
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
-    public void requestCapabilities(@CallbackExecutor Executor executor,
+    public void requestCapabilities(@NonNull @CallbackExecutor Executor executor,
             @NonNull List<Uri> contactNumbers,
             @NonNull CapabilitiesCallback c) throws ImsException {
         if (c == null) {
@@ -305,7 +311,7 @@
      * for the associated subscription.
      *
      * @return true if the user’s setting for UCE is enabled, false otherwise. If false,
-     * {@link ImsRcsManager#isCapable(int)} will return false for
+     * {@link ImsRcsManager#isCapable(int, int)} will return false for
      * {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE} and
      * {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_PRESENCE_UCE}
      * @see #setUceSettingEnabled(boolean)
diff --git a/telephony/java/android/telephony/ims/aidl/IRcsMessage.aidl b/telephony/java/android/telephony/ims/aidl/IRcsMessage.aidl
deleted file mode 100644
index 0ae6303..0000000
--- a/telephony/java/android/telephony/ims/aidl/IRcsMessage.aidl
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims.aidl;
-
-import android.net.Uri;
-import android.telephony.ims.RcsEventQueryParams;
-import android.telephony.ims.RcsEventQueryResultDescriptor;
-import android.telephony.ims.RcsFileTransferCreationParams;
-import android.telephony.ims.RcsIncomingMessageCreationParams;
-import android.telephony.ims.RcsMessageSnippet;
-import android.telephony.ims.RcsMessageQueryParams;
-import android.telephony.ims.RcsMessageQueryResultParcelable;
-import android.telephony.ims.RcsOutgoingMessageCreationParams;
-import android.telephony.ims.RcsParticipantQueryParams;
-import android.telephony.ims.RcsParticipantQueryResultParcelable;
-import android.telephony.ims.RcsQueryContinuationToken;
-import android.telephony.ims.RcsThreadQueryParams;
-import android.telephony.ims.RcsThreadQueryResultParcelable;
-
-/**
- * RPC definition between RCS storage APIs and phone process.
- * {@hide}
- */
-interface IRcsMessage {
-    /////////////////////////
-    // RcsMessageStore APIs
-    /////////////////////////
-    RcsThreadQueryResultParcelable getRcsThreads(in RcsThreadQueryParams queryParams, String callingPackage);
-
-    RcsThreadQueryResultParcelable getRcsThreadsWithToken(
-        in RcsQueryContinuationToken continuationToken, String callingPackage);
-
-    RcsParticipantQueryResultParcelable getParticipants(in RcsParticipantQueryParams queryParams, String callingPackage);
-
-    RcsParticipantQueryResultParcelable getParticipantsWithToken(
-        in RcsQueryContinuationToken continuationToken, String callingPackage);
-
-    RcsMessageQueryResultParcelable getMessages(in RcsMessageQueryParams queryParams, String callingPackage);
-
-    RcsMessageQueryResultParcelable getMessagesWithToken(
-        in RcsQueryContinuationToken continuationToken, String callingPackage);
-
-    RcsEventQueryResultDescriptor getEvents(in RcsEventQueryParams queryParams, String callingPackage);
-
-    RcsEventQueryResultDescriptor getEventsWithToken(
-        in RcsQueryContinuationToken continuationToken, String callingPackage);
-
-    // returns true if the thread was successfully deleted
-    boolean deleteThread(int threadId, int threadType, String callingPackage);
-
-    // Creates an Rcs1To1Thread and returns its row ID
-    int createRcs1To1Thread(int participantId, String callingPackage);
-
-    // Creates an RcsGroupThread and returns its row ID
-    int createGroupThread(in int[] participantIds, String groupName, in Uri groupIcon, String callingPackage);
-
-    /////////////////////////
-    // RcsThread APIs
-    /////////////////////////
-
-    // Creates a new RcsIncomingMessage on the given thread and returns its row ID
-    int addIncomingMessage(int rcsThreadId,
-            in RcsIncomingMessageCreationParams rcsIncomingMessageCreationParams, String callingPackage);
-
-    // Creates a new RcsOutgoingMessage on the given thread and returns its row ID
-    int addOutgoingMessage(int rcsThreadId,
-            in RcsOutgoingMessageCreationParams rcsOutgoingMessageCreationParams, String callingPackage);
-
-    // TODO: modify RcsProvider URI's to allow deleting a message without specifying its thread
-    void deleteMessage(int rcsMessageId, boolean isIncoming, int rcsThreadId, boolean isGroup, String callingPackage);
-
-    RcsMessageSnippet getMessageSnippet(int rcsThreadId, String callingPackage);
-
-    /////////////////////////
-    // Rcs1To1Thread APIs
-    /////////////////////////
-    void set1To1ThreadFallbackThreadId(int rcsThreadId, long fallbackId, String callingPackage);
-
-    long get1To1ThreadFallbackThreadId(int rcsThreadId, String callingPackage);
-
-    int get1To1ThreadOtherParticipantId(int rcsThreadId, String callingPackage);
-
-    /////////////////////////
-    // RcsGroupThread APIs
-    /////////////////////////
-    void setGroupThreadName(int rcsThreadId, String groupName, String callingPackage);
-
-    String getGroupThreadName(int rcsThreadId, String callingPackage);
-
-    void setGroupThreadIcon(int rcsThreadId, in Uri groupIcon, String callingPackage);
-
-    Uri getGroupThreadIcon(int rcsThreadId, String callingPackage);
-
-    void setGroupThreadOwner(int rcsThreadId, int participantId, String callingPackage);
-
-    int getGroupThreadOwner(int rcsThreadId, String callingPackage);
-
-    void setGroupThreadConferenceUri(int rcsThreadId, in Uri conferenceUri, String callingPackage);
-
-    Uri getGroupThreadConferenceUri(int rcsThreadId, String callingPackage);
-
-    void addParticipantToGroupThread(int rcsThreadId, int participantId, String callingPackage);
-
-    void removeParticipantFromGroupThread(int rcsThreadId, int participantId, String callingPackage);
-
-    /////////////////////////
-    // RcsParticipant APIs
-    /////////////////////////
-
-    // Creates a new RcsParticipant and returns its rowId
-    int createRcsParticipant(String canonicalAddress, String alias, String callingPackage);
-
-    String getRcsParticipantCanonicalAddress(int participantId, String callingPackage);
-
-    String getRcsParticipantAlias(int participantId, String callingPackage);
-
-    void setRcsParticipantAlias(int id, String alias, String callingPackage);
-
-    String getRcsParticipantContactId(int participantId, String callingPackage);
-
-    void setRcsParticipantContactId(int participantId, String contactId, String callingPackage);
-
-    /////////////////////////
-    // RcsMessage APIs
-    /////////////////////////
-    void setMessageSubId(int messageId, boolean isIncoming, int subId, String callingPackage);
-
-    int getMessageSubId(int messageId, boolean isIncoming, String callingPackage);
-
-    void setMessageStatus(int messageId, boolean isIncoming, int status, String callingPackage);
-
-    int getMessageStatus(int messageId, boolean isIncoming, String callingPackage);
-
-    void setMessageOriginationTimestamp(int messageId, boolean isIncoming, long originationTimestamp, String callingPackage);
-
-    long getMessageOriginationTimestamp(int messageId, boolean isIncoming, String callingPackage);
-
-    void setGlobalMessageIdForMessage(int messageId, boolean isIncoming, String globalId, String callingPackage);
-
-    String getGlobalMessageIdForMessage(int messageId, boolean isIncoming, String callingPackage);
-
-    void setMessageArrivalTimestamp(int messageId, boolean isIncoming, long arrivalTimestamp, String callingPackage);
-
-    long getMessageArrivalTimestamp(int messageId, boolean isIncoming, String callingPackage);
-
-    void setMessageSeenTimestamp(int messageId, boolean isIncoming, long seenTimestamp, String callingPackage);
-
-    long getMessageSeenTimestamp(int messageId, boolean isIncoming, String callingPackage);
-
-    void setTextForMessage(int messageId, boolean isIncoming, String text, String callingPackage);
-
-    String getTextForMessage(int messageId, boolean isIncoming, String callingPackage);
-
-    void setLatitudeForMessage(int messageId, boolean isIncoming, double latitude, String callingPackage);
-
-    double getLatitudeForMessage(int messageId, boolean isIncoming, String callingPackage);
-
-    void setLongitudeForMessage(int messageId, boolean isIncoming, double longitude, String callingPackage);
-
-    double getLongitudeForMessage(int messageId, boolean isIncoming, String callingPackage);
-
-    // Returns the ID's of the file transfers attached to the given message
-    int[] getFileTransfersAttachedToMessage(int messageId, boolean isIncoming, String callingPackage);
-
-    int getSenderParticipant(int messageId, String callingPackage);
-
-    /////////////////////////
-    // RcsOutgoingMessageDelivery APIs
-    /////////////////////////
-
-    // Returns the participant ID's that this message is intended to be delivered to
-    int[] getMessageRecipients(int messageId, String callingPackage);
-
-    long getOutgoingDeliveryDeliveredTimestamp(int messageId, int participantId, String callingPackage);
-
-    void setOutgoingDeliveryDeliveredTimestamp(int messageId, int participantId, long deliveredTimestamp, String callingPackage);
-
-    long getOutgoingDeliverySeenTimestamp(int messageId, int participantId, String callingPackage);
-
-    void setOutgoingDeliverySeenTimestamp(int messageId, int participantId, long seenTimestamp, String callingPackage);
-
-    int getOutgoingDeliveryStatus(int messageId, int participantId, String callingPackage);
-
-    void setOutgoingDeliveryStatus(int messageId, int participantId, int status, String callingPackage);
-
-    /////////////////////////
-    // RcsFileTransferPart APIs
-    /////////////////////////
-
-    // Performs the initial write to storage and returns the row ID.
-    int storeFileTransfer(int messageId, boolean isIncoming,
-            in RcsFileTransferCreationParams fileTransferCreationParams, String callingPackage);
-
-    void deleteFileTransfer(int partId, String callingPackage);
-
-    void setFileTransferSessionId(int partId, String sessionId, String callingPackage);
-
-    String getFileTransferSessionId(int partId, String callingPackage);
-
-    void setFileTransferContentUri(int partId, in Uri contentUri, String callingPackage);
-
-    Uri getFileTransferContentUri(int partId, String callingPackage);
-
-    void setFileTransferContentType(int partId, String contentType, String callingPackage);
-
-    String getFileTransferContentType(int partId, String callingPackage);
-
-    void setFileTransferFileSize(int partId, long fileSize, String callingPackage);
-
-    long getFileTransferFileSize(int partId, String callingPackage);
-
-    void setFileTransferTransferOffset(int partId, long transferOffset, String callingPackage);
-
-    long getFileTransferTransferOffset(int partId, String callingPackage);
-
-    void setFileTransferStatus(int partId, int transferStatus, String callingPackage);
-
-    int getFileTransferStatus(int partId, String callingPackage);
-
-    void setFileTransferWidth(int partId, int width, String callingPackage);
-
-    int getFileTransferWidth(int partId, String callingPackage);
-
-    void setFileTransferHeight(int partId, int height, String callingPackage);
-
-    int getFileTransferHeight(int partId, String callingPackage);
-
-    void setFileTransferLength(int partId, long length, String callingPackage);
-
-    long getFileTransferLength(int partId, String callingPackage);
-
-    void setFileTransferPreviewUri(int partId, in Uri uri, String callingPackage);
-
-    Uri getFileTransferPreviewUri(int partId, String callingPackage);
-
-    void setFileTransferPreviewType(int partId, String type, String callingPackage);
-
-    String getFileTransferPreviewType(int partId, String callingPackage);
-
-    /////////////////////////
-    // RcsEvent APIs
-    /////////////////////////
-    int createGroupThreadNameChangedEvent(long timestamp, int threadId, int originationParticipantId, String newName, String callingPackage);
-
-    int createGroupThreadIconChangedEvent(long timestamp, int threadId, int originationParticipantId, in Uri newIcon, String callingPackage);
-
-    int createGroupThreadParticipantJoinedEvent(long timestamp, int threadId, int originationParticipantId, int participantId, String callingPackage);
-
-    int createGroupThreadParticipantLeftEvent(long timestamp, int threadId, int originationParticipantId, int participantId, String callingPackage);
-
-    int createParticipantAliasChangedEvent(long timestamp, int participantId, String newAlias, String callingPackage);
-}
\ No newline at end of file
diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
index 0d5a979..7ff8735 100644
--- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
@@ -259,10 +259,7 @@
             super(capabilities);
         }
 
-        /**
-         * @hide
-         */
-        @SystemApi @TestApi
+        /** @hide */
         @IntDef(flag = true,
                 value = {
                         CAPABILITY_TYPE_VOICE,
@@ -325,7 +322,6 @@
         */
         @NonNull
         @Override
-        @SystemApi @TestApi
         public String toString() {
             StringBuilder builder = new StringBuilder("MmTel Capabilities - [");
             builder.append("Voice: ");
@@ -397,10 +393,7 @@
     @SystemApi @TestApi
     public static final int PROCESS_CALL_CSFB = 1;
 
-    /**
-    * @hide
-    */
-    @SystemApi @TestApi
+    /** @hide */
     @IntDef(flag = true,
             value = {
                     PROCESS_CALL_IMS,
@@ -514,7 +507,7 @@
      * @param callProfile The {@link ImsCallProfile} IMS call profile with details.
      *        This can be null if no call information is available for the rejected call.
      * @param reason The {@link ImsReasonInfo} call rejection reason.
-     * * @hide
+     * @hide
      */
     @SystemApi @TestApi
     public final void notifyRejectedCall(@NonNull ImsCallProfile callProfile,
diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java
index 884a0bc..8e67621 100644
--- a/telephony/java/android/telephony/ims/feature/RcsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java
@@ -349,9 +349,8 @@
      *
      * @return An instance of {@link RcsSipOptionsImplBase} that implements SIP options exchange if
      * it is supported by the device.
-     * @hide
      */
-    public RcsSipOptionsImplBase getOptionsExchangeImpl() {
+    public @NonNull RcsSipOptionsImplBase getOptionsExchangeImpl() {
         // Base Implementation, override to implement functionality
         return new RcsSipOptionsImplBase();
     }
@@ -365,9 +364,8 @@
      *
      * @return An instance of {@link RcsPresenceExchangeImplBase} that implements presence
      * exchange if it is supported by the device.
-     * @hide
      */
-    public RcsPresenceExchangeImplBase getPresenceExchangeImpl() {
+    public @NonNull RcsPresenceExchangeImplBase getPresenceExchangeImpl() {
         // Base Implementation, override to implement functionality.
         return new RcsPresenceExchangeImplBase();
     }
diff --git a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
index f4367da..e8f69ea 100644
--- a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
@@ -410,6 +410,13 @@
      * Rejects an incoming call or session update.
      *
      * @param reason reason code to reject an incoming call, defined in {@link ImsReasonInfo}.
+     *               The {@link android.telecom.InCallService} (dialer app) can use the
+     *               {@link android.telecom.Call#reject(int)} API to reject a call while specifying
+     *               a user-indicated reason for rejecting the call.
+     *               Normal call declines ({@link android.telecom.Call#REJECT_REASON_DECLINED}) will
+     *               map to {@link ImsReasonInfo#CODE_USER_DECLINE}.
+     *               Unwanted calls ({@link android.telecom.Call#REJECT_REASON_UNWANTED}) will map
+     *               to {@link ImsReasonInfo#CODE_SIP_USER_MARKED_UNWANTED}.
      * {@link ImsCallSession.Listener#callSessionStartFailed}
      */
     public void reject(int reason) {
diff --git a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java
index fda295a..a24af2f 100644
--- a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java
+++ b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java
@@ -17,6 +17,8 @@
 package android.telephony.ims.stub;
 
 import android.annotation.IntDef;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.os.RemoteException;
 import android.telephony.ims.ImsException;
 import android.telephony.ims.aidl.IRcsFeatureListener;
@@ -32,6 +34,8 @@
  *
  * @hide
  */
+@SystemApi
+@TestApi
 public class RcsCapabilityExchange {
 
     /**  Service is unknown. */
diff --git a/telephony/java/android/telephony/ims/stub/RcsPresenceExchangeImplBase.java b/telephony/java/android/telephony/ims/stub/RcsPresenceExchangeImplBase.java
index bb03448..f200ea2 100644
--- a/telephony/java/android/telephony/ims/stub/RcsPresenceExchangeImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/RcsPresenceExchangeImplBase.java
@@ -18,6 +18,8 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.net.Uri;
 import android.os.RemoteException;
 import android.telephony.ims.ImsException;
@@ -37,6 +39,8 @@
  *
  * @hide
  */
+@SystemApi
+@TestApi
 public class RcsPresenceExchangeImplBase extends RcsCapabilityExchange {
 
     private static final String LOG_TAG = "RcsPresenceExchangeIB";
diff --git a/telephony/java/android/telephony/ims/stub/RcsSipOptionsImplBase.java b/telephony/java/android/telephony/ims/stub/RcsSipOptionsImplBase.java
index 1c68fc0..355c4dd 100644
--- a/telephony/java/android/telephony/ims/stub/RcsSipOptionsImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/RcsSipOptionsImplBase.java
@@ -19,6 +19,8 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.net.Uri;
 import android.os.RemoteException;
 import android.telephony.ims.ImsException;
@@ -35,6 +37,8 @@
  *
  * @hide
  */
+@SystemApi
+@TestApi
 public class RcsSipOptionsImplBase extends RcsCapabilityExchange {
 
     private static final String LOG_TAG = "RcsSipOptionsImplBase";
@@ -69,6 +73,11 @@
      */
     public static final int RESPONSE_DOES_NOT_EXIST_ANYWHERE = 4;
 
+    /**
+     * Indicates that the remote user responded with a 400 BAD REQUEST response.
+     */
+    public static final int RESPONSE_BAD_REQUEST = 5;
+
     /** @hide*/
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = "RESPONSE_", value = {
@@ -77,7 +86,8 @@
             RESPONSE_TEMPORARILY_UNAVAILABLE,
             RESPONSE_REQUEST_TIMEOUT,
             RESPONSE_NOT_FOUND,
-            RESPONSE_DOES_NOT_EXIST_ANYWHERE
+            RESPONSE_DOES_NOT_EXIST_ANYWHERE,
+            RESPONSE_BAD_REQUEST
     })
     public @interface SipResponseCode {}
 
@@ -188,7 +198,6 @@
      * @param reason A non-null String containing the reason associated with the SIP code.
      * @param operationToken The token provided by the framework when
      *         {@link #onRemoteCapabilityRequest(Uri, RcsContactUceCapability, int)} was called.
-     *
      */
     public void respondToCapabilityRequestWithError(@NonNull Uri contactUri,
             @SipResponseCode int code, @NonNull String reason, int operationToken) {
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 6aa5a52..beb3c8c 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -29,6 +29,7 @@
 import android.service.carrier.CarrierIdentifier;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
+import android.telephony.CallForwardingInfo;
 import android.telephony.CarrierRestrictionRules;
 import android.telephony.CellIdentity;
 import android.telephony.CellInfo;
@@ -831,6 +832,11 @@
     void disableIms(int slotId);
 
     /**
+    * Toggle framework IMS disables and enables.
+    */
+    void resetIms(int slotIndex);
+
+    /**
      *  Get IImsMmTelFeature binder from ImsResolver that corresponds to the subId and MMTel feature
      *  as well as registering the MmTelFeature for callbacks using the IImsServiceFeatureCallback
      *  interface.
@@ -1628,6 +1634,79 @@
     NetworkStats getVtDataUsage(int subId, boolean perUidStats);
 
     /**
+     * Gets the voice call forwarding info {@link CallForwardingInfo}, given the call forward
+     * reason.
+     *
+     * @param callForwardingReason the call forwarding reasons which are the bitwise-OR combination
+     * of the following constants:
+     * <ol>
+     * <li>{@link CallForwardingInfo#REASON_BUSY} </li>
+     * <li>{@link CallForwardingInfo#REASON_NO_REPLY} </li>
+     * <li>{@link CallForwardingInfo#REASON_NOT_REACHABLE} </li>
+     * </ol>
+     *
+     * @throws IllegalArgumentException if callForwardingReason is not a bitwise-OR combination
+     * of {@link CallForwardingInfo.REASON_BUSY}, {@link CallForwardingInfo.REASON_BUSY},
+     * {@link CallForwardingInfo.REASON_NOT_REACHABLE}
+     *
+     * @return {@link CallForwardingInfo} with the status {@link CallForwardingInfo#STATUS_ACTIVE}
+     * or {@link CallForwardingInfo#STATUS_INACTIVE} and the target phone number to forward calls
+     * to, if it's available. Otherwise, it will return a {@link CallForwardingInfo} with status
+     * {@link CallForwardingInfo#STATUS_NOT_SUPPORTED} or
+     * {@link CallForwardingInfo#STATUS_FDN_CHECK_FAILURE} depending on the situation.
+     *
+     * @hide
+     */
+    CallForwardingInfo getCallForwarding(int subId, int callForwardingReason);
+
+    /**
+     * Sets the voice call forwarding info including status (enable/disable), call forwarding
+     * reason, the number to forward, and the timeout before the forwarding is attempted.
+     *
+     * @param callForwardingInfo {@link CallForwardingInfo} to setup the call forwarding.
+     * Enabling if {@link CallForwardingInfo#getStatus()} returns
+     * {@link CallForwardingInfo#STATUS_ACTIVE}; Disabling if
+     * {@link CallForwardingInfo#getStatus()} returns {@link CallForwardingInfo#STATUS_INACTIVE}.
+     *
+     * @throws IllegalArgumentException if any of the following:
+     * 0) callForwardingInfo is null.
+     * 1) {@link CallForwardingInfo#getStatus()} for callForwardingInfo returns neither
+     * {@link CallForwardingInfo#STATUS_ACTIVE} nor {@link CallForwardingInfo#STATUS_INACTIVE}.
+     * 2) {@link CallForwardingInfo#getReason()} for callForwardingInfo doesn't return the
+     * bitwise-OR combination of {@link CallForwardingInfo.REASON_BUSY},
+     * {@link CallForwardingInfo.REASON_BUSY}, {@link CallForwardingInfo.REASON_NOT_REACHABLE}
+     * 3) {@link CallForwardingInfo#getNumber()} for callForwardingInfo returns null.
+     * 4) {@link CallForwardingInfo#getTimeout()} for callForwardingInfo returns nagetive value.
+     *
+     * @return {@code true} to indicate it was set successfully; {@code false} otherwise.
+     *
+     * @hide
+     */
+    boolean setCallForwarding(int subId, in CallForwardingInfo callForwardingInfo);
+
+    /**
+     * Gets the status of voice call waiting function. Call waiting function enables the waiting
+     * for the incoming call when it reaches the user who is busy to make another call and allows
+     * users to decide whether to switch to the incoming call.
+     *
+     * @return the status of call waiting function.
+     * @hide
+     */
+    int getCallWaitingStatus(int subId);
+
+    /**
+     * Sets the status for voice call waiting function. Call waiting function enables the waiting
+     * for the incoming call when it reaches the user who is busy to make another call and allows
+     * users to decide whether to switch to the incoming call.
+     *
+     * @param isEnable {@code true} to enable; {@code false} to disable.
+     * @return {@code true} to indicate it was set successfully; {@code false} otherwise.
+     *
+     * @hide
+     */
+    boolean setCallWaitingStatus(int subId, boolean isEnable);
+
+    /**
      * Policy control of data connection. Usually used when data limit is passed.
      * @param enabled True if enabling the data, otherwise disabling.
      * @param subId Subscription index
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 0db86d6..9ac8cb1 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -480,6 +480,7 @@
     int RIL_REQUEST_STOP_KEEPALIVE = 145;
     int RIL_REQUEST_ENABLE_MODEM = 146;
     int RIL_REQUEST_GET_MODEM_STATUS = 147;
+    int RIL_REQUEST_CDMA_SEND_SMS_EXPECT_MORE = 148;
 
     /* The following requests are not defined in RIL.h */
     int RIL_REQUEST_HAL_NON_RIL_BASE = 200;
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index 48f7850..d41a6c8 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -317,16 +317,8 @@
             "com.android.internal.telephony.ACTION_LINE1_NUMBER_ERROR_DETECTED";
 
     /**
-     * Broadcast action to notify radio bug.
-     *
-     * Requires the READ_PRIVILEGED_PHONE_STATE permission.
-     *
-     * @hide
+     * Broadcast sent when a user activity is detected.
      */
-    public static final String ACTION_REPORT_RADIO_BUG =
-            "com.android.internal.telephony.ACTION_REPORT_RADIO_BUG";
-
-    // ACTION_REPORT_RADIO_BUG extra keys
-    public static final String EXTRA_SLOT_ID = "slotId";
-    public static final String EXTRA_RADIO_BUG_TYPE = "radioBugType";
+    public static final String ACTION_USER_ACTIVITY_NOTIFICATION =
+            "android.intent.action.USER_ACTIVITY_NOTIFICATION";
 }
diff --git a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
index 7422863..35e8a12 100644
--- a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
@@ -21,6 +21,7 @@
 import android.os.Bundle;
 import android.telephony.euicc.DownloadableSubscription;
 import android.telephony.euicc.EuiccInfo;
+import java.util.List;
 
 /** @hide */
 interface IEuiccController {
@@ -47,4 +48,7 @@
     oneway void eraseSubscriptionsWithOptions(
         int cardId, int options, in PendingIntent callbackIntent);
     oneway void retainSubscriptionsForFactoryReset(int cardId, in PendingIntent callbackIntent);
+    void setSupportedCountries(boolean isSupported, in List<String> countriesList);
+    List<String> getSupportedCountries(boolean isSupported);
+    boolean isSupportedCountry(String countryIso);
 }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ChangeAppRotationTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/ChangeAppRotationTest.java
index 42cafd4..5a66e80 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ChangeAppRotationTest.java
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ChangeAppRotationTest.java
@@ -66,7 +66,7 @@
     @Parameters(name = "{0}-{1}")
     public static Collection<Object[]> getParams() {
         int[] supportedRotations =
-                {Surface.ROTATION_0, Surface.ROTATION_90, Surface.ROTATION_270};
+                {Surface.ROTATION_0, Surface.ROTATION_90};
         Collection<Object[]> params = new ArrayList<>();
         for (int begin : supportedRotations) {
             for (int end : supportedRotations) {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CloseImeWindowToHomeTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/CloseImeWindowToHomeTest.java
index fc6719e..f740af9 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/CloseImeWindowToHomeTest.java
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CloseImeWindowToHomeTest.java
@@ -25,6 +25,7 @@
 
 import org.junit.Before;
 import org.junit.FixMethodOrder;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.MethodSorters;
@@ -62,6 +63,7 @@
                 .forAllEntries());
     }
 
+    @Ignore("Flaky")
     @Test
     public void checkVisibility_imeLayerBecomesInvisible() {
         checkResults(result -> LayersTraceSubject.assertThat(result)
@@ -71,6 +73,7 @@
                 .forAllEntries());
     }
 
+    @Ignore("Flaky")
     @Test
     public void checkVisibility_imeAppLayerBecomesInvisible() {
         checkResults(result -> LayersTraceSubject.assertThat(result)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/SeamlessAppRotationTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/SeamlessAppRotationTest.java
index ae55a75..37d7c4c 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/SeamlessAppRotationTest.java
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/SeamlessAppRotationTest.java
@@ -30,10 +30,12 @@
 import android.view.Surface;
 
 import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.FlakyTest;
 import androidx.test.filters.LargeTest;
 
 import org.junit.Before;
 import org.junit.FixMethodOrder;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.MethodSorters;
@@ -50,6 +52,8 @@
 @LargeTest
 @RunWith(Parameterized.class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@FlakyTest(bugId = 147659548)
+@Ignore("Waiting bug feedback")
 public class SeamlessAppRotationTest extends FlickerTestBase {
     private int mBeginRotation;
     private int mEndRotation;
@@ -65,7 +69,7 @@
     @Parameters(name = "{0}")
     public static Collection<Object[]> getParams() {
         int[] supportedRotations =
-                {Surface.ROTATION_0, Surface.ROTATION_90, Surface.ROTATION_270};
+                {Surface.ROTATION_0, Surface.ROTATION_90};
         Collection<Object[]> params = new ArrayList<>();
 
         ArrayList<Intent> testIntents = new ArrayList<>();
@@ -108,7 +112,7 @@
 
         super.runTransition(
                 changeAppRotation(mIntent, intentId, InstrumentationRegistry.getContext(),
-                        mUiDevice, mBeginRotation, mEndRotation).repeat(5).build());
+                        mUiDevice, mBeginRotation, mEndRotation).build());
     }
 
     @Test
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/AlphaLayersActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/AlphaLayersActivity.java
index 1a68a93..3766182 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/AlphaLayersActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/AlphaLayersActivity.java
@@ -50,7 +50,7 @@
 
         setContentView(container);
     }
-    
+
     @SuppressWarnings({"UnusedDeclaration"})
     static int dipToPx(Context c, int dip) {
         return (int) (c.getResources().getDisplayMetrics().density * dip + 0.5f);
@@ -86,30 +86,24 @@
             canvas.save();
             canvas.clipRect(20.0f, 0.0f, 40.0f, 20.0f);
             Log.d(LOG_TAG, "clipRect = " + canvas.getClipBounds());
-            Log.d(LOG_TAG, "rejected = " + canvas.quickReject(100.0f, 100.0f, 110.0f, 110.0f,
-                    Canvas.EdgeType.BW));
-            Log.d(LOG_TAG, "rejected = " + canvas.quickReject(25.0f, 5.0f, 30.0f, 10.0f,
-                    Canvas.EdgeType.BW));
+            Log.d(LOG_TAG, "rejected = " + canvas.quickReject(100.0f, 100.0f, 110.0f, 110.0f));
+            Log.d(LOG_TAG, "rejected = " + canvas.quickReject(25.0f, 5.0f, 30.0f, 10.0f));
             canvas.restore();
-            
+
             canvas.save();
             canvas.scale(2.0f, 2.0f);
             canvas.clipRect(20.0f, 0.0f, 40.0f, 20.0f);
             Log.d(LOG_TAG, "clipRect = " + canvas.getClipBounds());
-            Log.d(LOG_TAG, "rejected = " + canvas.quickReject(50.0f, 50.0f, 60.0f, 60.0f,
-                    Canvas.EdgeType.BW));
-            Log.d(LOG_TAG, "rejected = " + canvas.quickReject(25.0f, 5.0f, 30.0f, 10.0f,
-                    Canvas.EdgeType.BW));
+            Log.d(LOG_TAG, "rejected = " + canvas.quickReject(50.0f, 50.0f, 60.0f, 60.0f));
+            Log.d(LOG_TAG, "rejected = " + canvas.quickReject(25.0f, 5.0f, 30.0f, 10.0f));
             canvas.restore();
 
             canvas.save();
             canvas.translate(20.0f, 20.0f);
             canvas.clipRect(20.0f, 0.0f, 40.0f, 20.0f);
             Log.d(LOG_TAG, "clipRect = " + canvas.getClipBounds());
-            Log.d(LOG_TAG, "rejected = " + canvas.quickReject(80.0f, 80.0f, 90.0f, 90.0f,
-                    Canvas.EdgeType.BW));
-            Log.d(LOG_TAG, "rejected = " + canvas.quickReject(25.0f, 5.0f, 30.0f, 10.0f,
-                    Canvas.EdgeType.BW));
+            Log.d(LOG_TAG, "rejected = " + canvas.quickReject(80.0f, 80.0f, 90.0f, 90.0f));
+            Log.d(LOG_TAG, "rejected = " + canvas.quickReject(25.0f, 5.0f, 30.0f, 10.0f));
             canvas.restore();
 
             canvas.save();
diff --git a/tests/PlatformCompatGating/Android.bp b/tests/PlatformCompatGating/Android.bp
index 5e9ef8e..609896e 100644
--- a/tests/PlatformCompatGating/Android.bp
+++ b/tests/PlatformCompatGating/Android.bp
@@ -18,7 +18,6 @@
     name: "PlatformCompatGating",
     // Only compile source java files in this apk.
     srcs: ["src/**/*.java"],
-    certificate: "platform",
     libs: [
         "android.test.runner",
         "android.test.base",
diff --git a/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java b/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java
index 932ec64..c00aa2a 100644
--- a/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java
+++ b/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java
@@ -16,7 +16,9 @@
 
 package android.compat.testing;
 
+import android.Manifest;
 import android.app.Instrumentation;
+import android.app.UiAutomation;
 import android.compat.Compatibility;
 import android.compat.Compatibility.ChangeConfig;
 import android.content.Context;
@@ -83,12 +85,16 @@
         @Override
         public void evaluate() throws Throwable {
             Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+            UiAutomation uiAutomation = instrumentation.getUiAutomation();
             String packageName = instrumentation.getTargetContext().getPackageName();
             IPlatformCompat platformCompat = IPlatformCompat.Stub
                     .asInterface(ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
             if (platformCompat == null) {
                 throw new IllegalStateException("Could not get IPlatformCompat service!");
             }
+            uiAutomation.adoptShellPermissionIdentity(
+                    Manifest.permission.READ_COMPAT_CHANGE_CONFIG,
+                    Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG);
             Compatibility.setOverrides(mConfig);
             try {
                 platformCompat.setOverridesForTest(new CompatibilityChangeConfig(mConfig),
@@ -101,6 +107,7 @@
             } catch (RemoteException e) {
                 throw new RuntimeException("Could not call IPlatformCompat binder method!", e);
             } finally {
+                uiAutomation.dropShellPermissionIdentity();
                 Compatibility.clearOverrides();
             }
         }
diff --git a/tests/RcsTests/Android.bp b/tests/RcsTests/Android.bp
deleted file mode 100644
index 8ee4960..0000000
--- a/tests/RcsTests/Android.bp
+++ /dev/null
@@ -1,17 +0,0 @@
-android_test {
-    name: "RcsTests",
-    // Only compile source java files in this apk.
-    srcs: ["src/**/*.java"],
-    platform_apis: true,
-    certificate: "platform",
-    libs: [
-        "android.test.runner",
-        "android.test.base",
-    ],
-    static_libs: [
-        "junit",
-        "androidx.test.rules",
-        "mockito-target-minus-junit4",
-        "truth-prebuilt",
-    ],
-}
diff --git a/tests/RcsTests/AndroidManifest.xml b/tests/RcsTests/AndroidManifest.xml
deleted file mode 100644
index b1706a0..0000000
--- a/tests/RcsTests/AndroidManifest.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.tests.rcs">
-    <application android:label="RCS Test">
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
-                     android:targetPackage="com.android.tests.rcs"/>
-</manifest>
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadIconChangedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadIconChangedEventTest.java
deleted file mode 100644
index 6c311f9..0000000
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadIconChangedEventTest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.tests.ims;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.net.Uri;
-import android.os.Parcel;
-import android.telephony.ims.RcsGroupThreadIconChangedEvent;
-import android.telephony.ims.RcsGroupThreadIconChangedEventDescriptor;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class RcsGroupThreadIconChangedEventTest {
-
-    @Test
-    public void testCanUnparcel() {
-        int rcsGroupThreadId = 1;
-        int rcsParticipantId = 2;
-        Uri newIconUri = Uri.parse("content://new_icon");
-
-        RcsGroupThreadIconChangedEventDescriptor iconChangedEventDescriptor =
-                new RcsGroupThreadIconChangedEventDescriptor(1234567890, rcsGroupThreadId,
-                        rcsParticipantId, newIconUri);
-
-        Parcel parcel = Parcel.obtain();
-        iconChangedEventDescriptor.writeToParcel(
-                parcel, iconChangedEventDescriptor.describeContents());
-
-        parcel.setDataPosition(0);
-
-        iconChangedEventDescriptor =
-                RcsGroupThreadIconChangedEventDescriptor.CREATOR.createFromParcel(parcel);
-
-        RcsGroupThreadIconChangedEvent iconChangedEvent =
-                iconChangedEventDescriptor.createRcsEvent(null);
-
-        assertThat(iconChangedEvent.getNewIcon()).isEqualTo(newIconUri);
-        assertThat(iconChangedEvent.getRcsGroupThread().getThreadId()).isEqualTo(1);
-        assertThat(iconChangedEvent.getOriginatingParticipant().getId()).isEqualTo(2);
-        assertThat(iconChangedEvent.getTimestamp()).isEqualTo(1234567890);
-    }
-}
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadNameChangedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadNameChangedEventTest.java
deleted file mode 100644
index a60dabb..0000000
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadNameChangedEventTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.tests.ims;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.os.Parcel;
-import android.telephony.ims.RcsGroupThreadNameChangedEvent;
-import android.telephony.ims.RcsGroupThreadNameChangedEventDescriptor;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class RcsGroupThreadNameChangedEventTest {
-    @Test
-    public void testCanUnparcel() {
-        String newName = "new name";
-
-        int rcsGroupThreadId = 1;
-        int rcsParticipantId = 2;
-
-        RcsGroupThreadNameChangedEventDescriptor nameChangedEventDescriptor =
-                new RcsGroupThreadNameChangedEventDescriptor(
-                        1234567890, rcsGroupThreadId, rcsParticipantId, newName);
-
-        Parcel parcel = Parcel.obtain();
-        nameChangedEventDescriptor.writeToParcel(
-                parcel, nameChangedEventDescriptor.describeContents());
-
-        parcel.setDataPosition(0);
-
-        nameChangedEventDescriptor = RcsGroupThreadNameChangedEventDescriptor.CREATOR
-                .createFromParcel(parcel);
-
-        RcsGroupThreadNameChangedEvent nameChangedEvent =
-                nameChangedEventDescriptor.createRcsEvent(null);
-
-        assertThat(nameChangedEvent.getNewName()).isEqualTo(newName);
-        assertThat(nameChangedEvent.getRcsGroupThread().getThreadId()).isEqualTo(1);
-        assertThat(nameChangedEvent.getOriginatingParticipant().getId()).isEqualTo(2);
-        assertThat(nameChangedEvent.getTimestamp()).isEqualTo(1234567890);
-    }
-}
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantJoinedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantJoinedEventTest.java
deleted file mode 100644
index 7b02cb1..0000000
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantJoinedEventTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.tests.ims;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.os.Parcel;
-import android.telephony.ims.RcsGroupThreadParticipantJoinedEvent;
-import android.telephony.ims.RcsGroupThreadParticipantJoinedEventDescriptor;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class RcsGroupThreadParticipantJoinedEventTest {
-
-    @Test
-    public void testCanUnparcel() {
-        int rcsGroupThreadId = 1;
-        int rcsParticipantId = 2;
-
-        RcsGroupThreadParticipantJoinedEventDescriptor participantJoinedEventDescriptor =
-                new RcsGroupThreadParticipantJoinedEventDescriptor(
-                        1234567890, rcsGroupThreadId, rcsParticipantId, rcsParticipantId);
-
-        Parcel parcel = Parcel.obtain();
-        participantJoinedEventDescriptor.writeToParcel(
-                parcel, participantJoinedEventDescriptor.describeContents());
-
-        parcel.setDataPosition(0);
-
-        participantJoinedEventDescriptor = RcsGroupThreadParticipantJoinedEventDescriptor.CREATOR
-                .createFromParcel(parcel);
-
-        RcsGroupThreadParticipantJoinedEvent participantJoinedEvent =
-                participantJoinedEventDescriptor.createRcsEvent(null);
-
-        assertThat(participantJoinedEvent.getJoinedParticipant().getId()).isEqualTo(2);
-        assertThat(participantJoinedEvent.getRcsGroupThread().getThreadId()).isEqualTo(1);
-        assertThat(participantJoinedEvent.getOriginatingParticipant().getId()).isEqualTo(2);
-        assertThat(participantJoinedEvent.getTimestamp()).isEqualTo(1234567890);
-    }
-}
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantLeftEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantLeftEventTest.java
deleted file mode 100644
index 51466bd..0000000
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantLeftEventTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.tests.ims;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.os.Parcel;
-import android.telephony.ims.RcsGroupThreadParticipantLeftEvent;
-import android.telephony.ims.RcsGroupThreadParticipantLeftEventDescriptor;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class RcsGroupThreadParticipantLeftEventTest {
-    @Test
-    public void testCanUnparcel() {
-        int rcsGroupThreadId = 1;
-        int rcsParticipantId = 2;
-
-        RcsGroupThreadParticipantLeftEventDescriptor participantLeftEventDescriptor =
-                new RcsGroupThreadParticipantLeftEventDescriptor(
-                        1234567890, rcsGroupThreadId, rcsParticipantId, rcsParticipantId);
-
-        Parcel parcel = Parcel.obtain();
-        participantLeftEventDescriptor.writeToParcel(
-                parcel, participantLeftEventDescriptor.describeContents());
-
-        parcel.setDataPosition(0);
-
-        // create from parcel
-        parcel.setDataPosition(0);
-        participantLeftEventDescriptor = RcsGroupThreadParticipantLeftEventDescriptor.CREATOR
-                .createFromParcel(parcel);
-
-        RcsGroupThreadParticipantLeftEvent participantLeftEvent =
-                participantLeftEventDescriptor.createRcsEvent(null);
-
-        assertThat(participantLeftEvent.getRcsGroupThread().getThreadId()).isEqualTo(1);
-        assertThat(participantLeftEvent.getLeavingParticipant().getId()).isEqualTo(2);
-        assertThat(participantLeftEvent.getTimestamp()).isEqualTo(1234567890);
-    }
-}
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsParticipantAliasChangedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsParticipantAliasChangedEventTest.java
deleted file mode 100644
index 56830df..0000000
--- a/tests/RcsTests/src/com/android/tests/ims/RcsParticipantAliasChangedEventTest.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.tests.ims;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.os.Parcel;
-import android.telephony.ims.RcsParticipantAliasChangedEvent;
-import android.telephony.ims.RcsParticipantAliasChangedEventDescriptor;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class RcsParticipantAliasChangedEventTest {
-    private static final String OLD_ALIAS = "old alias";
-    private static final String NEW_ALIAS = "new alias";
-    private int mParticipantId = 3;
-
-    @Test
-    public void testCanUnparcel() {
-        RcsParticipantAliasChangedEventDescriptor aliasChangedEventDescriptor =
-                new RcsParticipantAliasChangedEventDescriptor(
-                        1234567890, mParticipantId, NEW_ALIAS);
-
-        Parcel parcel = Parcel.obtain();
-        aliasChangedEventDescriptor.writeToParcel(
-                parcel, aliasChangedEventDescriptor.describeContents());
-
-        parcel.setDataPosition(0);
-
-        aliasChangedEventDescriptor = RcsParticipantAliasChangedEventDescriptor.CREATOR
-                .createFromParcel(parcel);
-
-        RcsParticipantAliasChangedEvent aliasChangedEvent =
-                aliasChangedEventDescriptor.createRcsEvent(null);
-
-        assertThat(aliasChangedEvent.getParticipant().getId()).isEqualTo(mParticipantId);
-        assertThat(aliasChangedEvent.getNewAlias()).isEqualTo(NEW_ALIAS);
-        assertThat(aliasChangedEvent.getTimestamp()).isEqualTo(1234567890);
-    }
-}
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsParticipantQueryParamsTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsParticipantQueryParamsTest.java
deleted file mode 100644
index 2d95513..0000000
--- a/tests/RcsTests/src/com/android/tests/ims/RcsParticipantQueryParamsTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.tests.ims;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.os.Parcel;
-import android.telephony.ims.RcsParticipantQueryParams;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class RcsParticipantQueryParamsTest {
-
-    @Test
-    public void testCanUnparcel() {
-        RcsParticipantQueryParams rcsParticipantQueryParams =
-                new RcsParticipantQueryParams.Builder()
-                        .setAliasLike("%alias_")
-                        .setCanonicalAddressLike("_canonical%")
-                        .setSortProperty(RcsParticipantQueryParams.SORT_BY_CANONICAL_ADDRESS)
-                        .setSortDirection(true)
-                        .setResultLimit(432)
-                        .build();
-
-
-        Parcel parcel = Parcel.obtain();
-        rcsParticipantQueryParams.writeToParcel(parcel,
-                rcsParticipantQueryParams.describeContents());
-
-        parcel.setDataPosition(0);
-        rcsParticipantQueryParams = RcsParticipantQueryParams.CREATOR.createFromParcel(
-                parcel);
-
-        assertThat(rcsParticipantQueryParams.getAliasLike()).isEqualTo("%alias_");
-        assertThat(rcsParticipantQueryParams.getCanonicalAddressLike()).contains("_canonical%");
-        assertThat(rcsParticipantQueryParams.getLimit()).isEqualTo(432);
-        assertThat(rcsParticipantQueryParams.getSortingProperty()).isEqualTo(
-                RcsParticipantQueryParams.SORT_BY_CANONICAL_ADDRESS);
-        assertThat(rcsParticipantQueryParams.getSortDirection()).isTrue();
-    }
-}
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java
deleted file mode 100644
index 7a3e384..0000000
--- a/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.tests.ims;
-
-import static android.telephony.ims.RcsThreadQueryParams.SORT_BY_TIMESTAMP;
-import static android.telephony.ims.RcsThreadQueryParams.THREAD_TYPE_GROUP;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.os.Parcel;
-import android.telephony.ims.RcsParticipant;
-import android.telephony.ims.RcsThreadQueryParams;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class RcsThreadQueryParamsTest {
-
-    @Test
-    public void testCanUnparcel() {
-        RcsParticipant rcsParticipant = new RcsParticipant(null, 1);
-        RcsThreadQueryParams rcsThreadQueryParams = new RcsThreadQueryParams.Builder()
-                .setThreadType(THREAD_TYPE_GROUP)
-                .setParticipant(rcsParticipant)
-                .setResultLimit(50)
-                .setSortProperty(SORT_BY_TIMESTAMP)
-                .setSortDirection(true)
-                .build();
-
-        Parcel parcel = Parcel.obtain();
-        rcsThreadQueryParams.writeToParcel(parcel, rcsThreadQueryParams.describeContents());
-
-        parcel.setDataPosition(0);
-        rcsThreadQueryParams = RcsThreadQueryParams.CREATOR.createFromParcel(parcel);
-
-        assertThat(rcsThreadQueryParams.getThreadType()).isEqualTo(THREAD_TYPE_GROUP);
-        assertThat(rcsThreadQueryParams.getRcsParticipantsIds())
-                .contains(rcsParticipant.getId());
-        assertThat(rcsThreadQueryParams.getLimit()).isEqualTo(50);
-        assertThat(rcsThreadQueryParams.getSortingProperty()).isEqualTo(SORT_BY_TIMESTAMP);
-        assertThat(rcsThreadQueryParams.getSortDirection()).isTrue();
-    }
-}
diff --git a/tests/net/common/java/android/net/LinkAddressTest.java b/tests/net/common/java/android/net/LinkAddressTest.java
index b2e573b..06c6301 100644
--- a/tests/net/common/java/android/net/LinkAddressTest.java
+++ b/tests/net/common/java/android/net/LinkAddressTest.java
@@ -38,6 +38,8 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import android.os.SystemClock;
+
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
@@ -316,9 +318,76 @@
 
         l = new LinkAddress(V6_ADDRESS, 64, 123, 456);
         assertParcelingIsLossless(l);
+        l = new LinkAddress(V6_ADDRESS, 64, 123, 456,
+                1L, 3600000L);
+        assertParcelingIsLossless(l);
 
         l = new LinkAddress(V4 + "/28", IFA_F_PERMANENT, RT_SCOPE_LINK);
-        assertParcelSane(l, 4);
+        assertParcelSane(l, 6);
+    }
+
+    @Test
+    public void testDeprecationTime() {
+        try {
+            new LinkAddress(V6_ADDRESS, 64, 0, 456,
+                    LinkAddress.LIFETIME_UNKNOWN, 100000L);
+            fail("Only one time provided should cause exception");
+        } catch (IllegalArgumentException expected) { }
+
+        try {
+            new LinkAddress(V6_ADDRESS, 64, 0, 456,
+                    200000L, 100000L);
+            fail("deprecation time later than expiration time should cause exception");
+        } catch (IllegalArgumentException expected) { }
+
+        try {
+            new LinkAddress(V6_ADDRESS, 64, 0, 456,
+                    -2, 100000L);
+            fail("negative deprecation time should cause exception");
+        } catch (IllegalArgumentException expected) { }
+    }
+
+    @Test
+    public void testExpirationTime() {
+        try {
+            new LinkAddress(V6_ADDRESS, 64, 0, 456,
+                    200000L, LinkAddress.LIFETIME_UNKNOWN);
+            fail("Only one time provided should cause exception");
+        } catch (IllegalArgumentException expected) { }
+
+        try {
+            new LinkAddress(V6_ADDRESS, 64, 0, 456,
+                    100000L, -2);
+            fail("negative expiration time should cause exception");
+        } catch (IllegalArgumentException expected) { }
+    }
+
+    @Test
+    public void testGetFlags() {
+        LinkAddress l = new LinkAddress(V6_ADDRESS, 64, 123, RT_SCOPE_HOST);
+        assertEquals(123, l.getFlags());
+
+        // Test if deprecated bit was added/remove automatically based on the provided deprecation
+        // time
+        l = new LinkAddress(V6_ADDRESS, 64, 0, RT_SCOPE_HOST,
+                1L, LinkAddress.LIFETIME_PERMANENT);
+        // Check if the flag is added automatically.
+        assertTrue((l.getFlags() & IFA_F_DEPRECATED) != 0);
+
+        l = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED, RT_SCOPE_HOST,
+                SystemClock.elapsedRealtime() + 100000L, LinkAddress.LIFETIME_PERMANENT);
+        // Check if the flag is removed automatically.
+        assertTrue((l.getFlags() & IFA_F_DEPRECATED) == 0);
+
+        l = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED, RT_SCOPE_HOST,
+                LinkAddress.LIFETIME_PERMANENT, LinkAddress.LIFETIME_PERMANENT);
+        // Check if the permanent flag is added.
+        assertTrue((l.getFlags() & IFA_F_PERMANENT) != 0);
+
+        l = new LinkAddress(V6_ADDRESS, 64, IFA_F_PERMANENT, RT_SCOPE_HOST,
+                1000L, SystemClock.elapsedRealtime() + 100000L);
+        // Check if the permanent flag is removed
+        assertTrue((l.getFlags() & IFA_F_PERMANENT) == 0);
     }
 
     private void assertGlobalPreferred(LinkAddress l, String msg) {
@@ -389,5 +458,12 @@
                             (IFA_F_TEMPORARY|IFA_F_TENTATIVE|IFA_F_OPTIMISTIC),
                             RT_SCOPE_UNIVERSE);
         assertGlobalPreferred(l, "v6,global,tempaddr+optimistic");
+
+        l = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED,
+                RT_SCOPE_UNIVERSE, SystemClock.elapsedRealtime() + 100000,
+                SystemClock.elapsedRealtime() + 200000);
+        // Although the deprecated bit is set, but the deprecation time is in the future, test
+        // if the flag is removed automatically.
+        assertGlobalPreferred(l, "v6,global,tempaddr+deprecated in the future");
     }
 }
diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
index 1569112..3e4f3d8 100644
--- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
@@ -269,9 +269,10 @@
             .setUids(uids)
             .addCapability(NET_CAPABILITY_EIMS)
             .addCapability(NET_CAPABILITY_NOT_METERED);
+        netCap.setOwnerUid(123);
         assertParcelingIsLossless(netCap);
         netCap.setSSID(TEST_SSID);
-        assertParcelSane(netCap, 12);
+        assertParcelSane(netCap, 13);
     }
 
     @Test
diff --git a/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java b/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java
index 065add4..7ab4b56 100644
--- a/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java
+++ b/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java
@@ -16,6 +16,8 @@
 
 package android.net;
 
+import static android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsBinder;
+import static android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback;
 import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport;
 import static android.net.ConnectivityDiagnosticsManager.DataStallReport;
 
@@ -25,12 +27,19 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
 
 import android.os.PersistableBundle;
 
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+
+import java.util.concurrent.Executor;
 
 @RunWith(JUnit4.class)
 public class ConnectivityDiagnosticsManagerTest {
@@ -41,6 +50,19 @@
     private static final String BUNDLE_KEY = "key";
     private static final String BUNDLE_VALUE = "value";
 
+    private static final Executor INLINE_EXECUTOR = x -> x.run();
+
+    @Mock private ConnectivityDiagnosticsCallback mCb;
+
+    private ConnectivityDiagnosticsBinder mBinder;
+
+    @Before
+    public void setUp() {
+        mCb = mock(ConnectivityDiagnosticsCallback.class);
+
+        mBinder = new ConnectivityDiagnosticsBinder(mCb, INLINE_EXECUTOR);
+    }
+
     private ConnectivityReport createSampleConnectivityReport() {
         final LinkProperties linkProperties = new LinkProperties();
         linkProperties.setInterfaceName(INTERFACE_NAME);
@@ -193,4 +215,34 @@
     public void testDataStallReportParcelUnparcel() {
         assertParcelSane(createSampleDataStallReport(), 4);
     }
+
+    @Test
+    public void testConnectivityDiagnosticsCallbackOnConnectivityReport() {
+        mBinder.onConnectivityReport(createSampleConnectivityReport());
+
+        // The callback will be invoked synchronously by inline executor. Immediately check the
+        // latch without waiting.
+        verify(mCb).onConnectivityReport(eq(createSampleConnectivityReport()));
+    }
+
+    @Test
+    public void testConnectivityDiagnosticsCallbackOnDataStallSuspected() {
+        mBinder.onDataStallSuspected(createSampleDataStallReport());
+
+        // The callback will be invoked synchronously by inline executor. Immediately check the
+        // latch without waiting.
+        verify(mCb).onDataStallSuspected(eq(createSampleDataStallReport()));
+    }
+
+    @Test
+    public void testConnectivityDiagnosticsCallbackOnNetworkConnectivityReported() {
+        final Network n = new Network(NET_ID);
+        final boolean connectivity = true;
+
+        mBinder.onNetworkConnectivityReported(n, connectivity);
+
+        // The callback will be invoked synchronously by inline executor. Immediately check the
+        // latch without waiting.
+        verify(mCb).onNetworkConnectivityReported(eq(n), eq(connectivity));
+    }
 }
diff --git a/tests/net/java/android/net/Ikev2VpnProfileTest.java b/tests/net/java/android/net/Ikev2VpnProfileTest.java
new file mode 100644
index 0000000..d6a2176
--- /dev/null
+++ b/tests/net/java/android/net/Ikev2VpnProfileTest.java
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+
+import android.test.mock.MockContext;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.net.VpnProfile;
+import com.android.org.bouncycastle.x509.X509V1CertificateGenerator;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+
+import javax.security.auth.x500.X500Principal;
+
+/** Unit tests for {@link Ikev2VpnProfile.Builder}. */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class Ikev2VpnProfileTest {
+    private static final String SERVER_ADDR_STRING = "1.2.3.4";
+    private static final String IDENTITY_STRING = "Identity";
+    private static final String USERNAME_STRING = "username";
+    private static final String PASSWORD_STRING = "pa55w0rd";
+    private static final String EXCL_LIST = "exclList";
+    private static final byte[] PSK_BYTES = "preSharedKey".getBytes();
+    private static final int TEST_MTU = 1300;
+
+    private final MockContext mMockContext =
+            new MockContext() {
+                @Override
+                public String getOpPackageName() {
+                    return "fooPackage";
+                }
+            };
+    private final ProxyInfo mProxy = new ProxyInfo(SERVER_ADDR_STRING, -1, EXCL_LIST);
+
+    private X509Certificate mUserCert;
+    private X509Certificate mServerRootCa;
+    private PrivateKey mPrivateKey;
+
+    @Before
+    public void setUp() throws Exception {
+        mServerRootCa = generateRandomCertAndKeyPair().cert;
+
+        final CertificateAndKey userCertKey = generateRandomCertAndKeyPair();
+        mUserCert = userCertKey.cert;
+        mPrivateKey = userCertKey.key;
+    }
+
+    private Ikev2VpnProfile.Builder getBuilderWithDefaultOptions() {
+        final Ikev2VpnProfile.Builder builder =
+                new Ikev2VpnProfile.Builder(SERVER_ADDR_STRING, IDENTITY_STRING);
+
+        builder.setBypassable(true);
+        builder.setProxy(mProxy);
+        builder.setMaxMtu(TEST_MTU);
+        builder.setMetered(true);
+
+        return builder;
+    }
+
+    @Test
+    public void testBuildValidProfileWithOptions() throws Exception {
+        final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+        builder.setAuthUsernamePassword(USERNAME_STRING, PASSWORD_STRING, mServerRootCa);
+        final Ikev2VpnProfile profile = builder.build();
+        assertNotNull(profile);
+
+        // Check non-auth parameters correctly stored
+        assertEquals(SERVER_ADDR_STRING, profile.getServerAddr());
+        assertEquals(IDENTITY_STRING, profile.getUserIdentity());
+        assertEquals(mProxy, profile.getProxyInfo());
+        assertTrue(profile.isBypassable());
+        assertTrue(profile.isMetered());
+        assertEquals(TEST_MTU, profile.getMaxMtu());
+    }
+
+    @Test
+    public void testBuildUsernamePasswordProfile() throws Exception {
+        final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+        builder.setAuthUsernamePassword(USERNAME_STRING, PASSWORD_STRING, mServerRootCa);
+        final Ikev2VpnProfile profile = builder.build();
+        assertNotNull(profile);
+
+        assertEquals(USERNAME_STRING, profile.getUsername());
+        assertEquals(PASSWORD_STRING, profile.getPassword());
+        assertEquals(mServerRootCa, profile.getServerRootCaCert());
+
+        assertNull(profile.getPresharedKey());
+        assertNull(profile.getRsaPrivateKey());
+        assertNull(profile.getUserCert());
+    }
+
+    @Test
+    public void testBuildDigitalSignatureProfile() throws Exception {
+        final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+        builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa);
+        final Ikev2VpnProfile profile = builder.build();
+        assertNotNull(profile);
+
+        assertEquals(profile.getUserCert(), mUserCert);
+        assertEquals(mPrivateKey, profile.getRsaPrivateKey());
+        assertEquals(profile.getServerRootCaCert(), mServerRootCa);
+
+        assertNull(profile.getPresharedKey());
+        assertNull(profile.getUsername());
+        assertNull(profile.getPassword());
+    }
+
+    @Test
+    public void testBuildPresharedKeyProfile() throws Exception {
+        final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+        builder.setAuthPsk(PSK_BYTES);
+        final Ikev2VpnProfile profile = builder.build();
+        assertNotNull(profile);
+
+        assertArrayEquals(PSK_BYTES, profile.getPresharedKey());
+
+        assertNull(profile.getServerRootCaCert());
+        assertNull(profile.getUsername());
+        assertNull(profile.getPassword());
+        assertNull(profile.getRsaPrivateKey());
+        assertNull(profile.getUserCert());
+    }
+
+    @Test
+    public void testBuildNoAuthMethodSet() throws Exception {
+        final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+        try {
+            builder.build();
+            fail("Expected exception due to lack of auth method");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    @Test
+    public void testBuildInvalidMtu() throws Exception {
+        final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+        try {
+            builder.setMaxMtu(500);
+            fail("Expected exception due to too-small MTU");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    private void verifyVpnProfileCommon(VpnProfile profile) {
+        assertEquals(SERVER_ADDR_STRING, profile.server);
+        assertEquals(IDENTITY_STRING, profile.ipsecIdentifier);
+        assertEquals(mProxy, profile.proxy);
+        assertTrue(profile.isBypassable);
+        assertTrue(profile.isMetered);
+        assertEquals(TEST_MTU, profile.maxMtu);
+    }
+
+    @Test
+    public void testPskConvertToVpnProfile() throws Exception {
+        final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+        builder.setAuthPsk(PSK_BYTES);
+        final VpnProfile profile = builder.build().toVpnProfile();
+
+        verifyVpnProfileCommon(profile);
+        assertEquals(Ikev2VpnProfile.encodeForIpsecSecret(PSK_BYTES), profile.ipsecSecret);
+
+        // Check nothing else is set
+        assertEquals("", profile.username);
+        assertEquals("", profile.password);
+        assertEquals("", profile.ipsecUserCert);
+        assertEquals("", profile.ipsecCaCert);
+    }
+
+    @Test
+    public void testUsernamePasswordConvertToVpnProfile() throws Exception {
+        final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+        builder.setAuthUsernamePassword(USERNAME_STRING, PASSWORD_STRING, mServerRootCa);
+        final VpnProfile profile = builder.build().toVpnProfile();
+
+        verifyVpnProfileCommon(profile);
+        assertEquals(USERNAME_STRING, profile.username);
+        assertEquals(PASSWORD_STRING, profile.password);
+        assertEquals(Ikev2VpnProfile.certificateToPemString(mServerRootCa), profile.ipsecCaCert);
+
+        // Check nothing else is set
+        assertEquals("", profile.ipsecUserCert);
+        assertEquals("", profile.ipsecSecret);
+    }
+
+    @Test
+    public void testRsaConvertToVpnProfile() throws Exception {
+        final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+        builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa);
+        final VpnProfile profile = builder.build().toVpnProfile();
+
+        verifyVpnProfileCommon(profile);
+        assertEquals(Ikev2VpnProfile.certificateToPemString(mUserCert), profile.ipsecUserCert);
+        assertEquals(
+                Ikev2VpnProfile.encodeForIpsecSecret(mPrivateKey.getEncoded()),
+                profile.ipsecSecret);
+        assertEquals(Ikev2VpnProfile.certificateToPemString(mServerRootCa), profile.ipsecCaCert);
+
+        // Check nothing else is set
+        assertEquals("", profile.username);
+        assertEquals("", profile.password);
+    }
+
+    @Test
+    public void testPskFromVpnProfileDiscardsIrrelevantValues() throws Exception {
+        final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+        builder.setAuthPsk(PSK_BYTES);
+        final VpnProfile profile = builder.build().toVpnProfile();
+        profile.username = USERNAME_STRING;
+        profile.password = PASSWORD_STRING;
+        profile.ipsecCaCert = Ikev2VpnProfile.certificateToPemString(mServerRootCa);
+        profile.ipsecUserCert = Ikev2VpnProfile.certificateToPemString(mUserCert);
+
+        final Ikev2VpnProfile result = Ikev2VpnProfile.fromVpnProfile(profile);
+        assertNull(result.getUsername());
+        assertNull(result.getPassword());
+        assertNull(result.getUserCert());
+        assertNull(result.getRsaPrivateKey());
+        assertNull(result.getServerRootCaCert());
+    }
+
+    @Test
+    public void testUsernamePasswordFromVpnProfileDiscardsIrrelevantValues() throws Exception {
+        final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+        builder.setAuthUsernamePassword(USERNAME_STRING, PASSWORD_STRING, mServerRootCa);
+        final VpnProfile profile = builder.build().toVpnProfile();
+        profile.ipsecSecret = new String(PSK_BYTES);
+        profile.ipsecUserCert = Ikev2VpnProfile.certificateToPemString(mUserCert);
+
+        final Ikev2VpnProfile result = Ikev2VpnProfile.fromVpnProfile(profile);
+        assertNull(result.getPresharedKey());
+        assertNull(result.getUserCert());
+        assertNull(result.getRsaPrivateKey());
+    }
+
+    @Test
+    public void testRsaFromVpnProfileDiscardsIrrelevantValues() throws Exception {
+        final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+        builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa);
+        final VpnProfile profile = builder.build().toVpnProfile();
+        profile.username = USERNAME_STRING;
+        profile.password = PASSWORD_STRING;
+
+        final Ikev2VpnProfile result = Ikev2VpnProfile.fromVpnProfile(profile);
+        assertNull(result.getUsername());
+        assertNull(result.getPassword());
+        assertNull(result.getPresharedKey());
+    }
+
+    @Test
+    public void testPskConversionIsLossless() throws Exception {
+        final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+        builder.setAuthPsk(PSK_BYTES);
+        final Ikev2VpnProfile ikeProfile = builder.build();
+
+        assertEquals(ikeProfile, Ikev2VpnProfile.fromVpnProfile(ikeProfile.toVpnProfile()));
+    }
+
+    @Test
+    public void testUsernamePasswordConversionIsLossless() throws Exception {
+        final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+        builder.setAuthUsernamePassword(USERNAME_STRING, PASSWORD_STRING, mServerRootCa);
+        final Ikev2VpnProfile ikeProfile = builder.build();
+
+        assertEquals(ikeProfile, Ikev2VpnProfile.fromVpnProfile(ikeProfile.toVpnProfile()));
+    }
+
+    @Test
+    public void testRsaConversionIsLossless() throws Exception {
+        final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+        builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa);
+        final Ikev2VpnProfile ikeProfile = builder.build();
+
+        assertEquals(ikeProfile, Ikev2VpnProfile.fromVpnProfile(ikeProfile.toVpnProfile()));
+    }
+
+    private static class CertificateAndKey {
+        public final X509Certificate cert;
+        public final PrivateKey key;
+
+        CertificateAndKey(X509Certificate cert, PrivateKey key) {
+            this.cert = cert;
+            this.key = key;
+        }
+    }
+
+    private static CertificateAndKey generateRandomCertAndKeyPair() throws Exception {
+        final Date validityBeginDate =
+                new Date(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1L));
+        final Date validityEndDate =
+                new Date(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(1L));
+
+        // Generate a keypair
+        final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
+        keyPairGenerator.initialize(512);
+        final KeyPair keyPair = keyPairGenerator.generateKeyPair();
+
+        final X500Principal dnName = new X500Principal("CN=test.android.com");
+        final X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
+        certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
+        certGen.setSubjectDN(dnName);
+        certGen.setIssuerDN(dnName);
+        certGen.setNotBefore(validityBeginDate);
+        certGen.setNotAfter(validityEndDate);
+        certGen.setPublicKey(keyPair.getPublic());
+        certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
+
+        final X509Certificate cert = certGen.generate(keyPair.getPrivate(), "AndroidOpenSSL");
+        return new CertificateAndKey(cert, keyPair.getPrivate());
+    }
+}
diff --git a/tests/net/java/android/net/VpnManagerTest.java b/tests/net/java/android/net/VpnManagerTest.java
new file mode 100644
index 0000000..655c4d1
--- /dev/null
+++ b/tests/net/java/android/net/VpnManagerTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import static org.mockito.Mockito.mock;
+
+import android.test.mock.MockContext;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** Unit tests for {@link VpnManager}. */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class VpnManagerTest {
+    private static final String VPN_PROFILE_KEY = "KEY";
+
+    private IConnectivityManager mMockCs;
+    private VpnManager mVpnManager;
+    private final MockContext mMockContext =
+            new MockContext() {
+                @Override
+                public String getOpPackageName() {
+                    return "fooPackage";
+                }
+            };
+
+    @Before
+    public void setUp() throws Exception {
+        mMockCs = mock(IConnectivityManager.class);
+        mVpnManager = new VpnManager(mMockContext, mMockCs);
+    }
+
+    @Test
+    public void testProvisionVpnProfile() throws Exception {
+        try {
+            mVpnManager.provisionVpnProfile(mock(PlatformVpnProfile.class));
+        } catch (UnsupportedOperationException expected) {
+        }
+    }
+
+    @Test
+    public void testDeleteProvisionedVpnProfile() throws Exception {
+        try {
+            mVpnManager.deleteProvisionedVpnProfile();
+        } catch (UnsupportedOperationException expected) {
+        }
+    }
+
+    @Test
+    public void testStartProvisionedVpnProfile() throws Exception {
+        try {
+            mVpnManager.startProvisionedVpnProfile();
+        } catch (UnsupportedOperationException expected) {
+        }
+    }
+
+    @Test
+    public void testStopProvisionedVpnProfile() throws Exception {
+        try {
+            mVpnManager.stopProvisionedVpnProfile();
+        } catch (UnsupportedOperationException expected) {
+        }
+    }
+}
diff --git a/tests/net/java/com/android/internal/net/VpnProfileTest.java b/tests/net/java/com/android/internal/net/VpnProfileTest.java
new file mode 100644
index 0000000..8a4b533
--- /dev/null
+++ b/tests/net/java/com/android/internal/net/VpnProfileTest.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.net;
+
+import static com.android.testutils.ParcelUtilsKt.assertParcelSane;
+
+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 android.net.IpSecAlgorithm;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.Arrays;
+
+/** Unit tests for {@link VpnProfile}. */
+@SmallTest
+@RunWith(JUnit4.class)
+public class VpnProfileTest {
+    private static final String DUMMY_PROFILE_KEY = "Test";
+
+    @Test
+    public void testDefaults() throws Exception {
+        final VpnProfile p = new VpnProfile(DUMMY_PROFILE_KEY);
+
+        assertEquals(DUMMY_PROFILE_KEY, p.key);
+        assertEquals("", p.name);
+        assertEquals(VpnProfile.TYPE_PPTP, p.type);
+        assertEquals("", p.server);
+        assertEquals("", p.username);
+        assertEquals("", p.password);
+        assertEquals("", p.dnsServers);
+        assertEquals("", p.searchDomains);
+        assertEquals("", p.routes);
+        assertTrue(p.mppe);
+        assertEquals("", p.l2tpSecret);
+        assertEquals("", p.ipsecIdentifier);
+        assertEquals("", p.ipsecSecret);
+        assertEquals("", p.ipsecUserCert);
+        assertEquals("", p.ipsecCaCert);
+        assertEquals("", p.ipsecServerCert);
+        assertEquals(null, p.proxy);
+        assertTrue(p.getAllowedAlgorithms() != null && p.getAllowedAlgorithms().isEmpty());
+        assertFalse(p.isBypassable);
+        assertFalse(p.isMetered);
+        assertEquals(1400, p.maxMtu);
+        assertFalse(p.areAuthParamsInline);
+    }
+
+    private VpnProfile getSampleIkev2Profile(String key) {
+        final VpnProfile p = new VpnProfile(key);
+
+        p.name = "foo";
+        p.type = VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS;
+        p.server = "bar";
+        p.username = "baz";
+        p.password = "qux";
+        p.dnsServers = "8.8.8.8";
+        p.searchDomains = "";
+        p.routes = "0.0.0.0/0";
+        p.mppe = false;
+        p.l2tpSecret = "";
+        p.ipsecIdentifier = "quux";
+        p.ipsecSecret = "quuz";
+        p.ipsecUserCert = "corge";
+        p.ipsecCaCert = "grault";
+        p.ipsecServerCert = "garply";
+        p.proxy = null;
+        p.setAllowedAlgorithms(
+                Arrays.asList(
+                        IpSecAlgorithm.AUTH_CRYPT_AES_GCM,
+                        IpSecAlgorithm.AUTH_HMAC_SHA512,
+                        IpSecAlgorithm.CRYPT_AES_CBC));
+        p.isBypassable = true;
+        p.isMetered = true;
+        p.maxMtu = 1350;
+        p.areAuthParamsInline = true;
+
+        // Not saved, but also not compared.
+        p.saveLogin = true;
+
+        return p;
+    }
+
+    @Test
+    public void testEquals() {
+        assertEquals(
+                getSampleIkev2Profile(DUMMY_PROFILE_KEY), getSampleIkev2Profile(DUMMY_PROFILE_KEY));
+
+        final VpnProfile modified = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
+        modified.maxMtu--;
+        assertNotEquals(getSampleIkev2Profile(DUMMY_PROFILE_KEY), modified);
+    }
+
+    @Test
+    public void testParcelUnparcel() {
+        assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 22);
+    }
+
+    @Test
+    public void testSetInvalidAlgorithmValueDelimiter() {
+        final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
+
+        try {
+            profile.setAllowedAlgorithms(
+                    Arrays.asList("test" + VpnProfile.VALUE_DELIMITER + "test"));
+            fail("Expected failure due to value separator in algorithm name");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    @Test
+    public void testSetInvalidAlgorithmListDelimiter() {
+        final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
+
+        try {
+            profile.setAllowedAlgorithms(
+                    Arrays.asList("test" + VpnProfile.LIST_DELIMITER + "test"));
+            fail("Expected failure due to value separator in algorithm name");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    @Test
+    public void testEncodeDecode() {
+        final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
+        final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, profile.encode());
+        assertEquals(profile, decoded);
+    }
+
+    @Test
+    public void testEncodeDecodeTooManyValues() {
+        final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
+        final byte[] tooManyValues =
+                (new String(profile.encode()) + VpnProfile.VALUE_DELIMITER + "invalid").getBytes();
+
+        assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooManyValues));
+    }
+
+    @Test
+    public void testEncodeDecodeInvalidNumberOfValues() {
+        final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
+        final String encoded = new String(profile.encode());
+        final byte[] tooFewValues =
+                encoded.substring(0, encoded.lastIndexOf(VpnProfile.VALUE_DELIMITER)).getBytes();
+
+        assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues));
+    }
+
+    @Test
+    public void testEncodeDecodeLoginsNotSaved() {
+        final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
+        profile.saveLogin = false;
+
+        final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, profile.encode());
+        assertNotEquals(profile, decoded);
+
+        // Add the username/password back, everything else must be equal.
+        decoded.username = profile.username;
+        decoded.password = profile.password;
+        assertEquals(profile, decoded);
+    }
+}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 09cc69e..a0a1352 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -6313,12 +6313,24 @@
         assertEquals(wifiLp, mService.getActiveLinkProperties());
     }
 
+    @Test
+    public void testNetworkCapabilitiesRestrictedForCallerPermissions() {
+        int callerUid = Process.myUid();
+        final NetworkCapabilities originalNc = new NetworkCapabilities();
+        originalNc.setOwnerUid(callerUid);
 
-    private TestNetworkAgentWrapper establishVpn(LinkProperties lp, int establishingUid,
-            Set<UidRange> vpnRange) throws Exception {
+        final NetworkCapabilities newNc =
+                mService.networkCapabilitiesRestrictedForCallerPermissions(
+                        originalNc, Process.myPid(), callerUid);
+
+        assertEquals(Process.INVALID_UID, newNc.getOwnerUid());
+    }
+
+    private TestNetworkAgentWrapper establishVpn(
+            LinkProperties lp, int ownerUid, Set<UidRange> vpnRange) throws Exception {
         final TestNetworkAgentWrapper
                 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp);
-        vpnNetworkAgent.getNetworkCapabilities().setEstablishingVpnAppUid(establishingUid);
+        vpnNetworkAgent.getNetworkCapabilities().setOwnerUid(ownerUid);
         mMockVpn.setNetworkAgent(vpnNetworkAgent);
         mMockVpn.connect();
         mMockVpn.setUids(vpnRange);
diff --git a/tools/stats_log_api_gen/java_writer_q.cpp b/tools/stats_log_api_gen/java_writer_q.cpp
index f866129..1259a68 100644
--- a/tools/stats_log_api_gen/java_writer_q.cpp
+++ b/tools/stats_log_api_gen/java_writer_q.cpp
@@ -75,9 +75,7 @@
                         java_type_name(chainField.javaType), chainField.name.c_str());
                 }
             } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
-                // Module logging does not yet support key value pair.
-                fprintf(stderr, "Module logging does not yet support key value pair.\n");
-                continue;
+                fprintf(out, ", android.util.SparseArray<Object> valueMap");
             } else {
                 fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
             }
@@ -161,9 +159,114 @@
                 fprintf(out, "%s    needed += attrSize;\n", indent.c_str());
                 break;
             }
+            case JAVA_TYPE_KEY_VALUE_PAIR:
+            {
+                fprintf(out,
+                        "%s    // Calculate bytes needed by Key Value Pairs.\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s    final int count = valueMap.size();\n", indent.c_str());
+                fprintf(out,
+                        "%s    android.util.SparseIntArray intMap = null;\n", indent.c_str());
+                fprintf(out,
+                        "%s    android.util.SparseLongArray longMap = null;\n", indent.c_str());
+                fprintf(out,
+                        "%s    android.util.SparseArray<String> stringMap = null;\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s    android.util.SparseArray<Float> floatMap = null;\n", indent.c_str());
+                fprintf(out,
+                        "%s    int keyValuePairSize = LIST_TYPE_OVERHEAD * 5;\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s    for (int i = 0; i < count; i++) {\n", indent.c_str());
+                fprintf(out,
+                        "%s        final int key = valueMap.keyAt(i);\n", indent.c_str());
+                fprintf(out,
+                        "%s        final Object value = valueMap.valueAt(i);\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s        if (value instanceof Integer) {\n", indent.c_str());
+                fprintf(out,
+                        "%s            keyValuePairSize += LIST_TYPE_OVERHEAD\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s                    + INT_TYPE_SIZE + INT_TYPE_SIZE;\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s            if (null == intMap) {\n", indent.c_str());
+                fprintf(out,
+                        "%s                intMap = new android.util.SparseIntArray();\n", indent.c_str());
+                fprintf(out,
+                        "%s            }\n", indent.c_str());
+                fprintf(out,
+                        "%s            intMap.put(key, (Integer) value);\n", indent.c_str());
+                fprintf(out,
+                        "%s        } else if (value instanceof Long) {\n", indent.c_str());
+                fprintf(out,
+                        "%s            keyValuePairSize += LIST_TYPE_OVERHEAD\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s                    + INT_TYPE_SIZE + LONG_TYPE_SIZE;\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s            if (null == longMap) {\n", indent.c_str());
+                fprintf(out,
+                        "%s                longMap = new android.util.SparseLongArray();\n", indent.c_str());
+                fprintf(out,
+                        "%s            }\n", indent.c_str());
+                fprintf(out,
+                        "%s            longMap.put(key, (Long) value);\n", indent.c_str());
+                fprintf(out,
+                        "%s        } else if (value instanceof String) {\n", indent.c_str());
+                fprintf(out,
+                        "%s            final String str = (value == null) ? \"\" : "
+                        "(String) value;\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s            final int len = "
+                        "str.getBytes(java.nio.charset.StandardCharsets.UTF_8).length;\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s            keyValuePairSize += LIST_TYPE_OVERHEAD + INT_TYPE_SIZE\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s                    + STRING_TYPE_OVERHEAD + len;\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s            if (null == stringMap) {\n", indent.c_str());
+                fprintf(out,
+                        "%s                stringMap = new android.util.SparseArray<>();\n", indent.c_str());
+                fprintf(out,
+                        "%s            }\n", indent.c_str());
+                fprintf(out,
+                        "%s            stringMap.put(key, str);\n", indent.c_str());
+                fprintf(out,
+                        "%s        } else if (value instanceof Float) {\n", indent.c_str());
+                fprintf(out,
+                        "%s            keyValuePairSize += LIST_TYPE_OVERHEAD\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s                    + INT_TYPE_SIZE + FLOAT_TYPE_SIZE;\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s            if (null == floatMap) {\n", indent.c_str());
+                fprintf(out,
+                        "%s                floatMap = new android.util.SparseArray<>();\n", indent.c_str());
+                fprintf(out,
+                        "%s            }\n", indent.c_str());
+                fprintf(out,
+                        "%s            floatMap.put(key, (Float) value);\n", indent.c_str());
+                fprintf(out,
+                        "%s        }\n", indent.c_str());
+                fprintf(out,
+                        "%s    }\n", indent.c_str());
+                fprintf(out, "%s    needed += keyValuePairSize;\n", indent.c_str());
+                break;
+            }
             default:
-                // Unsupported types: OBJECT, DOUBLE, KEY_VALUE_PAIR.
-                fprintf(stderr, "Module logging does not yet support key value pair.\n");
+                // Unsupported types: OBJECT, DOUBLE.
+                fprintf(stderr, "Module logging does not yet support Object and Double.\n");
                 return 1;
             }
             argIndex++;
@@ -253,10 +356,18 @@
                 fprintf(out, "%s    pos += attrSize;\n", indent.c_str());
                 break;
             }
+            case JAVA_TYPE_KEY_VALUE_PAIR:
+                requiredHelpers |= JAVA_MODULE_REQUIRES_FLOAT;
+                requiredHelpers |= JAVA_MODULE_REQUIRES_KEY_VALUE_PAIRS;
+                fprintf(out,
+                        "%s    writeKeyValuePairs(buff, pos, intMap, longMap, stringMap, "
+                        "floatMap);\n", indent.c_str());
+                fprintf(out, "%s    pos += keyValuePairSize;\n", indent.c_str());
+                break;
             default:
-                // Unsupported types: OBJECT, DOUBLE, KEY_VALUE_PAIR.
+                // Unsupported types: OBJECT, DOUBLE.
                 fprintf(stderr,
-                        "Object, Double, and KeyValuePairs are not supported in module logging");
+                        "Object and Double are not supported in module logging");
                 return 1;
             }
             argIndex++;
@@ -359,6 +470,111 @@
         fprintf(out, "%s}\n", indent.c_str());
         fprintf(out, "\n");
     }
+
+    if (requiredHelpers & JAVA_MODULE_REQUIRES_KEY_VALUE_PAIRS) {
+        fprintf(out, "%sprivate static void writeKeyValuePairs(byte[] buff, int pos,\n",
+                indent.c_str());
+        fprintf(out, "%s        final android.util.SparseIntArray intMap,\n", indent.c_str());
+        fprintf(out, "%s        final android.util.SparseLongArray longMap,\n", indent.c_str());
+        fprintf(out, "%s        final android.util.SparseArray<String> stringMap,\n",
+                indent.c_str());
+        fprintf(out, "%s        final android.util.SparseArray<Float> floatMap) {\n",
+                indent.c_str());
+
+        // Start list of lists.
+        fprintf(out, "%s    buff[pos] = LIST_TYPE;\n", indent.c_str());
+        fprintf(out, "%s    buff[pos + 1] = (byte) 4;\n", indent.c_str());
+        fprintf(out, "%s    pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
+
+        // Write integers.
+        fprintf(out, "%s    final int intMapSize = null == intMap ? 0 : intMap.size();\n",
+                indent.c_str());
+        fprintf(out, "%s    buff[pos] = LIST_TYPE;\n", indent.c_str());
+        fprintf(out, "%s    buff[pos + 1] = (byte) intMapSize;\n", indent.c_str());
+        fprintf(out, "%s    pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
+        fprintf(out, "%s    for (int i = 0; i < intMapSize; i++) {\n", indent.c_str());
+        fprintf(out, "%s        buff[pos] = LIST_TYPE;\n", indent.c_str());
+        fprintf(out, "%s        buff[pos + 1] = (byte) 2;\n", indent.c_str());
+        fprintf(out, "%s        pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
+        fprintf(out, "%s        final int key = intMap.keyAt(i);\n", indent.c_str());
+        fprintf(out, "%s        final int value = intMap.valueAt(i);\n", indent.c_str());
+        fprintf(out, "%s        buff[pos] = INT_TYPE;\n", indent.c_str());
+        fprintf(out, "%s        copyInt(buff, pos + 1, key);\n", indent.c_str());
+        fprintf(out, "%s        pos += INT_TYPE_SIZE;\n", indent.c_str());
+        fprintf(out, "%s        buff[pos] = INT_TYPE;\n", indent.c_str());
+        fprintf(out, "%s        copyInt(buff, pos + 1, value);\n", indent.c_str());
+        fprintf(out, "%s        pos += INT_TYPE_SIZE;\n", indent.c_str());
+        fprintf(out, "%s    }\n", indent.c_str());
+
+        // Write longs.
+        fprintf(out, "%s    final int longMapSize = null == longMap ? 0 : longMap.size();\n",
+                indent.c_str());
+        fprintf(out, "%s    buff[pos] = LIST_TYPE;\n", indent.c_str());
+        fprintf(out, "%s    buff[pos + 1] = (byte) longMapSize;\n", indent.c_str());
+        fprintf(out, "%s    pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
+        fprintf(out, "%s    for (int i = 0; i < longMapSize; i++) {\n", indent.c_str());
+        fprintf(out, "%s        buff[pos] = LIST_TYPE;\n", indent.c_str());
+        fprintf(out, "%s        buff[pos + 1] = (byte) 2;\n", indent.c_str());
+        fprintf(out, "%s        pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
+        fprintf(out, "%s        final int key = longMap.keyAt(i);\n", indent.c_str());
+        fprintf(out, "%s        final long value = longMap.valueAt(i);\n", indent.c_str());
+        fprintf(out, "%s        buff[pos] = INT_TYPE;\n", indent.c_str());
+        fprintf(out, "%s        copyInt(buff, pos + 1, key);\n", indent.c_str());
+        fprintf(out, "%s        pos += INT_TYPE_SIZE;\n", indent.c_str());
+        fprintf(out, "%s        buff[pos] = LONG_TYPE;\n", indent.c_str());
+        fprintf(out, "%s        copyLong(buff, pos + 1, value);\n", indent.c_str());
+        fprintf(out, "%s        pos += LONG_TYPE_SIZE;\n", indent.c_str());
+        fprintf(out, "%s    }\n", indent.c_str());
+
+        // Write Strings.
+        fprintf(out, "%s    final int stringMapSize = null == stringMap ? 0 : stringMap.size();\n",
+                indent.c_str());
+        fprintf(out, "%s    buff[pos] = LIST_TYPE;\n", indent.c_str());
+        fprintf(out, "%s    buff[pos + 1] = (byte) stringMapSize;\n", indent.c_str());
+        fprintf(out, "%s    pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
+        fprintf(out, "%s    for (int i = 0; i < stringMapSize; i++) {\n", indent.c_str());
+        fprintf(out, "%s        buff[pos] = LIST_TYPE;\n", indent.c_str());
+        fprintf(out, "%s        buff[pos + 1] = (byte) 2;\n", indent.c_str());
+        fprintf(out, "%s        pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
+        fprintf(out, "%s        final int key = stringMap.keyAt(i);\n", indent.c_str());
+        fprintf(out, "%s        final String value = stringMap.valueAt(i);\n", indent.c_str());
+        fprintf(out, "%s        final byte[] valueBytes = "
+                "value.getBytes(java.nio.charset.StandardCharsets.UTF_8);\n",
+                indent.c_str());
+        fprintf(out, "%s        buff[pos] = INT_TYPE;\n", indent.c_str());
+        fprintf(out, "%s        copyInt(buff, pos + 1, key);\n", indent.c_str());
+        fprintf(out, "%s        pos += INT_TYPE_SIZE;\n", indent.c_str());
+        fprintf(out, "%s        buff[pos] = STRING_TYPE;\n", indent.c_str());
+        fprintf(out, "%s        copyInt(buff, pos + 1, valueBytes.length);\n", indent.c_str());
+        fprintf(out, "%s        System.arraycopy("
+                "valueBytes, 0, buff, pos + STRING_TYPE_OVERHEAD, valueBytes.length);\n",
+                indent.c_str());
+        fprintf(out, "%s        pos += STRING_TYPE_OVERHEAD + valueBytes.length;\n",
+                indent.c_str());
+        fprintf(out, "%s    }\n", indent.c_str());
+
+        // Write floats.
+        fprintf(out, "%s    final int floatMapSize = null == floatMap ? 0 : floatMap.size();\n",
+                indent.c_str());
+        fprintf(out, "%s    buff[pos] = LIST_TYPE;\n", indent.c_str());
+        fprintf(out, "%s    buff[pos + 1] = (byte) floatMapSize;\n", indent.c_str());
+        fprintf(out, "%s    pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
+        fprintf(out, "%s    for (int i = 0; i < floatMapSize; i++) {\n", indent.c_str());
+        fprintf(out, "%s        buff[pos] = LIST_TYPE;\n", indent.c_str());
+        fprintf(out, "%s        buff[pos + 1] = (byte) 2;\n", indent.c_str());
+        fprintf(out, "%s        pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
+        fprintf(out, "%s        final int key = floatMap.keyAt(i);\n", indent.c_str());
+        fprintf(out, "%s        final float value = floatMap.valueAt(i);\n", indent.c_str());
+        fprintf(out, "%s        buff[pos] = INT_TYPE;\n", indent.c_str());
+        fprintf(out, "%s        copyInt(buff, pos + 1, key);\n", indent.c_str());
+        fprintf(out, "%s        pos += INT_TYPE_SIZE;\n", indent.c_str());
+        fprintf(out, "%s        buff[pos] = FLOAT_TYPE;\n", indent.c_str());
+        fprintf(out, "%s        copyFloat(buff, pos + 1, value);\n", indent.c_str());
+        fprintf(out, "%s        pos += FLOAT_TYPE_SIZE;\n", indent.c_str());
+        fprintf(out, "%s    }\n", indent.c_str());
+        fprintf(out, "%s}\n", indent.c_str());
+        fprintf(out, "\n");
+    }
 }
 
 #if defined(STATS_SCHEMA_LEGACY)
@@ -382,7 +598,7 @@
                         java_type_name(chainField.javaType), chainField.name.c_str());
                 }
             } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
-                fprintf(out, ", android.util.SparseArray<Object> value_map");
+                fprintf(out, ", android.util.SparseArray<Object> valueMap");
             } else {
                 fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
             }
diff --git a/tools/stats_log_api_gen/utils.h b/tools/stats_log_api_gen/utils.h
index 50737a6..cd602e5 100644
--- a/tools/stats_log_api_gen/utils.h
+++ b/tools/stats_log_api_gen/utils.h
@@ -39,6 +39,7 @@
 
 const int JAVA_MODULE_REQUIRES_FLOAT = 0x01;
 const int JAVA_MODULE_REQUIRES_ATTRIBUTION = 0x02;
+const int JAVA_MODULE_REQUIRES_KEY_VALUE_PAIRS = 0x04;
 
 string make_constant_name(const string& str);
 
diff --git a/wifi/java/android/net/wifi/INetworkRequestMatchCallback.aidl b/wifi/java/android/net/wifi/INetworkRequestMatchCallback.aidl
index 51d74f0..d14ec57 100644
--- a/wifi/java/android/net/wifi/INetworkRequestMatchCallback.aidl
+++ b/wifi/java/android/net/wifi/INetworkRequestMatchCallback.aidl
@@ -17,6 +17,7 @@
 package android.net.wifi;
 
 import android.net.wifi.INetworkRequestUserSelectionCallback;
+import android.net.wifi.ScanResult;
 import android.net.wifi.WifiConfiguration;
 
 /**
@@ -30,7 +31,7 @@
 
    void onAbort();
 
-   void onMatch(in List<android.net.wifi.ScanResult> scanResults);
+   void onMatch(in List<ScanResult> scanResults);
 
    void onUserSelectionConnectSuccess(in WifiConfiguration wificonfiguration);
 
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 62bb2db..31b3a50 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -36,6 +36,7 @@
 import android.net.wifi.ITrafficStateCallback;
 import android.net.wifi.ITxPacketCountListener;
 import android.net.wifi.IWifiConnectedNetworkScorer;
+import android.net.wifi.ScanResult;
 import android.net.wifi.SoftApConfiguration;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiInfo;
@@ -60,9 +61,9 @@
 
     ParceledListSlice getPrivilegedConfiguredNetworks(String packageName, String featureId);
 
-    Map getAllMatchingFqdnsForScanResults(in List<android.net.wifi.ScanResult> scanResult);
+    Map getAllMatchingFqdnsForScanResults(in List<ScanResult> scanResult);
 
-    Map getMatchingOsuProviders(in List<android.net.wifi.ScanResult> scanResult);
+    Map getMatchingOsuProviders(in List<ScanResult> scanResult);
 
     Map getMatchingPasspointConfigsForOsuProviders(in List<OsuProvider> osuProviders);
 
@@ -96,9 +97,11 @@
 
     void setMacRandomizationSettingPasspointEnabled(String fqdn, boolean enable);
 
+    void setMeteredOverridePasspoint(String fqdn, int meteredOverride);
+
     boolean startScan(String packageName, String featureId);
 
-    List<android.net.wifi.ScanResult> getScanResults(String callingPackage, String callingFeatureId);
+    List<ScanResult> getScanResults(String callingPackage, String callingFeatureId);
 
     boolean disconnect(String packageName);
 
@@ -255,7 +258,7 @@
 
     int calculateSignalLevel(int rssi);
 
-    List<WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(in List<android.net.wifi.ScanResult> scanResults);
+    List<WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(in List<ScanResult> scanResults);
 
     boolean setWifiConnectedNetworkScorer(in IBinder binder, in IWifiConnectedNetworkScorer scorer);
 
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 114e0fa..0ef224a 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -481,12 +481,14 @@
                 allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
                 break;
             case SECURITY_TYPE_SAE:
+                allowedProtocols.set(WifiConfiguration.Protocol.RSN);
                 allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE);
                 allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
                 allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
                 requirePMF = true;
                 break;
             case SECURITY_TYPE_EAP_SUITE_B:
+                allowedProtocols.set(WifiConfiguration.Protocol.RSN);
                 allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192);
                 allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256);
                 allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
@@ -496,6 +498,7 @@
                 requirePMF = true;
                 break;
             case SECURITY_TYPE_OWE:
+                allowedProtocols.set(WifiConfiguration.Protocol.RSN);
                 allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE);
                 allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
                 allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 5edcc2d..04016b6 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -856,11 +856,11 @@
      * like /etc/ssl/certs. If configured, these certificates are added to the
      * list of trusted CAs. ca_cert may also be included in that case, but it is
      * not required.
-     * @param path The path for CA certificate files, or null/empty string to clear.
+     * @param path The path for CA certificate files, or empty string to clear.
      * @hide
      */
     @SystemApi
-    public void setCaPath(@Nullable String path) {
+    public void setCaPath(@NonNull String path) {
         setFieldValue(CA_PATH_KEY, path);
     }
 
@@ -881,11 +881,11 @@
      * <p> See the {@link android.security.KeyChain} for details on installing or choosing
      * a certificate
      * </p>
-     * @param alias identifies the certificate, or null/empty string to clear.
+     * @param alias identifies the certificate, or empty string to clear.
      * @hide
      */
     @SystemApi
-    public void setClientCertificateAlias(@Nullable String alias) {
+    public void setClientCertificateAlias(@NonNull String alias) {
         setFieldValue(CLIENT_CERT_KEY, alias, CLIENT_CERT_PREFIX);
         setFieldValue(PRIVATE_KEY_ID_KEY, alias, USER_PRIVATE_KEY);
         // Also, set engine parameters
@@ -1360,11 +1360,11 @@
      * If this field is not specified, WAPI-CERT uses ASU ID from WAI packet
      * as the certificate suite name automatically.
      *
-     * @param wapiCertSuite The name for WAPI certificate suite, or null/empty string to clear.
+     * @param wapiCertSuite The name for WAPI certificate suite, or empty string to clear.
      * @hide
      */
     @SystemApi
-    public void setWapiCertSuite(@Nullable String wapiCertSuite) {
+    public void setWapiCertSuite(@NonNull String wapiCertSuite) {
         setFieldValue(WAPI_CERT_SUITE_KEY, wapiCertSuite);
     }
 
@@ -1373,7 +1373,7 @@
      * @return the certificate suite name
      * @hide
      */
-    @Nullable
+    @NonNull
     @SystemApi
     public String getWapiCertSuite() {
         return getFieldValue(WAPI_CERT_SUITE_KEY);
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 419bcb1..f8d48c5 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -178,7 +178,7 @@
      * If connected to a network suggestion or specifier, store the package name of the app,
      * else null.
      */
-    private String mAppPackageName;
+    private String mRequestingPackageName;
 
     /**
      * Running total count of lost (not ACKed) transmitted unicast data packets.
@@ -201,68 +201,68 @@
      */
     public long rxSuccess;
 
-    private double mTxBadRate;
+    private double mLostTxPacketsPerSecond;
 
     /**
      * Average rate of lost transmitted packets, in units of packets per second.
      * @hide
      */
     @SystemApi
-    public double getTxBadRate() {
-        return mTxBadRate;
+    public double getLostTxPacketsPerSecond() {
+        return mLostTxPacketsPerSecond;
     }
 
     /** @hide */
-    public void setTxBadRate(double txBadRate) {
-        mTxBadRate = txBadRate;
+    public void setLostTxPacketsPerSecond(double lostTxPacketsPerSecond) {
+        mLostTxPacketsPerSecond = lostTxPacketsPerSecond;
     }
 
-    private double mTxRetriesRate;
+    private double mTxRetriedTxPacketsPerSecond;
 
     /**
      * Average rate of transmitted retry packets, in units of packets per second.
      * @hide
      */
     @SystemApi
-    public double getTxRetriesRate() {
-        return mTxRetriesRate;
+    public double getRetriedTxPacketsPerSecond() {
+        return mTxRetriedTxPacketsPerSecond;
     }
 
     /** @hide */
-    public void setTxRetriesRate(double txRetriesRate) {
-        mTxRetriesRate = txRetriesRate;
+    public void setRetriedTxPacketsRate(double txRetriedTxPacketsPerSecond) {
+        mTxRetriedTxPacketsPerSecond = txRetriedTxPacketsPerSecond;
     }
 
-    private double mTxSuccessRate;
+    private double mSuccessfulTxPacketsPerSecond;
 
     /**
      * Average rate of successfully transmitted unicast packets, in units of packets per second.
      * @hide
      */
     @SystemApi
-    public double getTxSuccessRate() {
-        return mTxSuccessRate;
+    public double getSuccessfulTxPacketsPerSecond() {
+        return mSuccessfulTxPacketsPerSecond;
     }
 
     /** @hide */
-    public void setTxSuccessRate(double txSuccessRate) {
-        mTxSuccessRate = txSuccessRate;
+    public void setSuccessfulTxPacketsPerSecond(double successfulTxPacketsPerSecond) {
+        mSuccessfulTxPacketsPerSecond = successfulTxPacketsPerSecond;
     }
 
-    private double mRxSuccessRate;
+    private double mSuccessfulRxPacketsPerSecond;
 
     /**
      * Average rate of received unicast data packets, in units of packets per second.
      * @hide
      */
     @SystemApi
-    public double getRxSuccessRate() {
-        return mRxSuccessRate;
+    public double getSuccessfulRxPacketsPerSecond() {
+        return mSuccessfulRxPacketsPerSecond;
     }
 
     /** @hide */
-    public void setRxSuccessRate(double rxSuccessRate) {
-        mRxSuccessRate = rxSuccessRate;
+    public void setSuccessfulRxPacketsPerSecond(double successfulRxPacketsPerSecond) {
+        mSuccessfulRxPacketsPerSecond = successfulRxPacketsPerSecond;
     }
 
     /** @hide */
@@ -319,17 +319,17 @@
         setMeteredHint(false);
         setEphemeral(false);
         setOsuAp(false);
-        setAppPackageName(null);
+        setRequestingPackageName(null);
         setFQDN(null);
         setProviderFriendlyName(null);
         txBad = 0;
         txSuccess = 0;
         rxSuccess = 0;
         txRetries = 0;
-        mTxBadRate = 0;
-        mTxSuccessRate = 0;
-        mRxSuccessRate = 0;
-        mTxRetriesRate = 0;
+        mLostTxPacketsPerSecond = 0;
+        mSuccessfulTxPacketsPerSecond = 0;
+        mSuccessfulRxPacketsPerSecond = 0;
+        mTxRetriedTxPacketsPerSecond = 0;
         score = 0;
     }
 
@@ -353,8 +353,8 @@
             mMeteredHint = source.mMeteredHint;
             mEphemeral = source.mEphemeral;
             mTrusted = source.mTrusted;
-            mAppPackageName =
-                    source.mAppPackageName;
+            mRequestingPackageName =
+                    source.mRequestingPackageName;
             mOsuAp = source.mOsuAp;
             mFqdn = source.mFqdn;
             mProviderFriendlyName = source.mProviderFriendlyName;
@@ -362,10 +362,10 @@
             txRetries = source.txRetries;
             txSuccess = source.txSuccess;
             rxSuccess = source.rxSuccess;
-            mTxBadRate = source.mTxBadRate;
-            mTxRetriesRate = source.mTxRetriesRate;
-            mTxSuccessRate = source.mTxSuccessRate;
-            mRxSuccessRate = source.mRxSuccessRate;
+            mLostTxPacketsPerSecond = source.mLostTxPacketsPerSecond;
+            mTxRetriedTxPacketsPerSecond = source.mTxRetriedTxPacketsPerSecond;
+            mSuccessfulTxPacketsPerSecond = source.mSuccessfulTxPacketsPerSecond;
+            mSuccessfulRxPacketsPerSecond = source.mSuccessfulRxPacketsPerSecond;
             score = source.score;
             mWifiStandard = source.mWifiStandard;
             mMaxSupportedTxLinkSpeed = source.mMaxSupportedTxLinkSpeed;
@@ -777,8 +777,8 @@
     }
 
     /** {@hide} */
-    public void setAppPackageName(@Nullable String packageName) {
-        mAppPackageName = packageName;
+    public void setRequestingPackageName(@Nullable String packageName) {
+        mRequestingPackageName = packageName;
     }
 
     /**
@@ -788,8 +788,8 @@
      * @hide
      */
     @SystemApi
-    public @Nullable String getAppPackageName() {
-        return mAppPackageName;
+    public @Nullable String getRequestingPackageName() {
+        return mRequestingPackageName;
     }
 
 
@@ -956,16 +956,16 @@
         dest.writeInt(mTrusted ? 1 : 0);
         dest.writeInt(score);
         dest.writeLong(txSuccess);
-        dest.writeDouble(mTxSuccessRate);
+        dest.writeDouble(mSuccessfulTxPacketsPerSecond);
         dest.writeLong(txRetries);
-        dest.writeDouble(mTxRetriesRate);
+        dest.writeDouble(mTxRetriedTxPacketsPerSecond);
         dest.writeLong(txBad);
-        dest.writeDouble(mTxBadRate);
+        dest.writeDouble(mLostTxPacketsPerSecond);
         dest.writeLong(rxSuccess);
-        dest.writeDouble(mRxSuccessRate);
+        dest.writeDouble(mSuccessfulRxPacketsPerSecond);
         mSupplicantState.writeToParcel(dest, flags);
         dest.writeInt(mOsuAp ? 1 : 0);
-        dest.writeString(mAppPackageName);
+        dest.writeString(mRequestingPackageName);
         dest.writeString(mFqdn);
         dest.writeString(mProviderFriendlyName);
         dest.writeInt(mWifiStandard);
@@ -1000,16 +1000,16 @@
                 info.mTrusted = in.readInt() != 0;
                 info.score = in.readInt();
                 info.txSuccess = in.readLong();
-                info.mTxSuccessRate = in.readDouble();
+                info.mSuccessfulTxPacketsPerSecond = in.readDouble();
                 info.txRetries = in.readLong();
-                info.mTxRetriesRate = in.readDouble();
+                info.mTxRetriedTxPacketsPerSecond = in.readDouble();
                 info.txBad = in.readLong();
-                info.mTxBadRate = in.readDouble();
+                info.mLostTxPacketsPerSecond = in.readDouble();
                 info.rxSuccess = in.readLong();
-                info.mRxSuccessRate = in.readDouble();
+                info.mSuccessfulRxPacketsPerSecond = in.readDouble();
                 info.mSupplicantState = SupplicantState.CREATOR.createFromParcel(in);
                 info.mOsuAp = in.readInt() != 0;
-                info.mAppPackageName = in.readString();
+                info.mRequestingPackageName = in.readString();
                 info.mFqdn = in.readString();
                 info.mProviderFriendlyName = in.readString();
                 info.mWifiStandard = in.readInt();
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index f1ebf6b5..1d71cf9 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -22,6 +22,7 @@
 
 import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -1792,18 +1793,6 @@
     }
 
     /**
-     * Same as {@link #registerNetworkRequestMatchCallback(Executor, NetworkRequestMatchCallback)},
-     * except that the callback will be executed on the application's main thread.
-     * @param callback Callback for network match events to register.
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
-    public void registerNetworkRequestMatchCallback(@NonNull NetworkRequestMatchCallback callback) {
-        registerNetworkRequestMatchCallback(mContext.getMainExecutor(), callback);
-    }
-
-    /**
      * Registers a callback for NetworkRequest matches. See {@link NetworkRequestMatchCallback}.
      * Caller can unregister a previously registered callback using
      * {@link #unregisterNetworkRequestMatchCallback(NetworkRequestMatchCallback)}
@@ -2353,7 +2342,7 @@
         return (getSupportedFeatures() & feature) == feature;
     }
 
-   /**
+    /**
      * @return true if this adapter supports Passpoint
      * @hide
      */
@@ -2905,6 +2894,7 @@
      * [0, {@link #getMaxSignalLevel()}], where 0 is the lowest (worst signal) RSSI
      * rating and {@link #getMaxSignalLevel()} is the highest (best signal) RSSI rating.
      */
+    @IntRange(from = 0)
     public int calculateSignalLevel(int rssi) {
         try {
             return mService.calculateSignalLevel(rssi);
@@ -2917,6 +2907,7 @@
      * Get the system default maximum signal level.
      * This is the maximum RSSI level returned by {@link #calculateSignalLevel(int)}.
      */
+    @IntRange(from = 0)
     public int getMaxSignalLevel() {
         return calculateSignalLevel(Integer.MAX_VALUE);
     }
@@ -3716,18 +3707,6 @@
     }
 
     /**
-     * Same as {@link #registerSoftApCallback(Executor, SoftApCallback)},
-     * except that the callback will be executed on the application's main thread.
-     * @param callback Callback for soft AP events
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
-    public void registerSoftApCallback(@NonNull SoftApCallback callback) {
-        registerSoftApCallback(mContext.getMainExecutor(), callback);
-    }
-
-    /**
      * Registers a callback for Soft AP. See {@link SoftApCallback}. Caller will receive the current
      * soft AP state and number of connected devices immediately after a successful call to this API
      * via callback. Note that receiving an immediate WIFI_AP_STATE_FAILED value for soft AP state
@@ -4370,6 +4349,25 @@
     }
 
     /**
+     * Sets the user's choice of metered override for a Passpoint profile.
+     *
+     * @param fqdn the FQDN (fully qualified domain name) of the passpoint profile.
+     * @param meteredOverride One of three values: {@link WifiConfiguration#METERED_OVERRIDE_NONE},
+     *                        {@link WifiConfiguration#METERED_OVERRIDE_METERED},
+     *                        {@link WifiConfiguration#METERED_OVERRIDE_NOT_METERED}
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+    public void setMeteredOverridePasspoint(@NonNull String fqdn, int meteredOverride) {
+        try {
+            mService.setMeteredOverridePasspoint(fqdn, meteredOverride);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Disable an ephemeral network.
      *
      * @param ssid in the format of WifiConfiguration's SSID.
@@ -4856,13 +4854,19 @@
     /**
      * Set Wi-Fi verbose logging level from developer settings.
      *
-     * @param verbose the verbose logging level to set. 0 will disable verbose logging, a positive
-     *                integer will enable verbose logging.
+     * @param enable true to enable verbose logging, false to disable.
      *
      * @hide
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+    public void setVerboseLoggingEnabled(boolean enable) {
+        enableVerboseLogging(enable ? 1 : 0);
+    }
+
+    /** @hide */
+    @UnsupportedAppUsage
+    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
     public void enableVerboseLogging (int verbose) {
         try {
             mService.enableVerboseLogging(verbose);
@@ -4873,15 +4877,23 @@
     }
 
     /**
-     * Get the persisted WiFi verbose logging level, set by {@link #enableVerboseLogging(int)}.
+     * Get the persisted Wi-Fi verbose logging level, set by
+     * {@link #setVerboseLoggingEnabled(boolean)}.
      * No permissions are required to call this method.
      *
-     * @return 0 to indicate that verbose logging is disabled, a positive integer to indicate that
-     * verbose logging is enabled.
+     * @return true to indicate that verbose logging is enabled, false to indicate that verbose
+     * logging is disabled.
      *
      * @hide
      */
     @SystemApi
+    public boolean isVerboseLoggingEnabled() {
+        return getVerboseLoggingLevel() > 0;
+    }
+
+    /** @hide */
+    // TODO(b/145484145): remove once SUW stops calling this via reflection
+    @UnsupportedAppUsage
     public int getVerboseLoggingLevel() {
         try {
             return mService.getVerboseLoggingLevel();
@@ -4912,7 +4924,10 @@
      */
     @Nullable
     @SystemApi
-    @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD
+    })
     public Network getCurrentNetwork() {
         try {
             return mService.getCurrentNetwork();
@@ -5014,10 +5029,8 @@
      * and ipconfig.txt file.
      * @param supplicantData bytes representing wpa_supplicant.conf
      * @param ipConfigData bytes representing ipconfig.txt
-     * @deprecated this is no longer supported.
      * @hide
      */
-    @Deprecated
     @SystemApi
     @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
     public void restoreSupplicantBackupData(
@@ -5149,18 +5162,6 @@
     }
 
     /**
-     * Same as {@link #registerTrafficStateCallback(Executor, TrafficStateCallback)},
-     * except that the callback will be executed on the application's main thread.
-     * @param callback Callback for traffic state events
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
-    public void registerTrafficStateCallback(@NonNull TrafficStateCallback callback) {
-        registerTrafficStateCallback(mContext.getMainExecutor(), callback);
-    }
-
-    /**
      * Registers a callback for monitoring traffic state. See {@link TrafficStateCallback}. These
      * callbacks will be invoked periodically by platform to inform clients about the current
      * traffic state. Caller can unregister a previously registered callback using
@@ -5218,7 +5219,7 @@
      * level from wifi service.
      */
     private void updateVerboseLoggingEnabledFromService() {
-        mVerboseLoggingEnabled = getVerboseLoggingLevel() > 0;
+        mVerboseLoggingEnabled = isVerboseLoggingEnabled();
     }
 
     /**
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 18533ef..6f01350 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -1037,10 +1037,8 @@
 
     /**
      * Retrieve the most recent scan results from a single scan request.
-     * {@hide}
      */
     @NonNull
-    @SystemApi
     @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public List<ScanResult> getSingleScanResults() {
         validateChannel();
diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index 7c335fc..3a0d080 100644
--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -16,6 +16,9 @@
 
 package android.net.wifi.hotspot2;
 
+import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_NONE;
+import static android.net.wifi.WifiConfiguration.MeteredOverride;
+
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.net.wifi.hotspot2.pps.Credential;
@@ -438,6 +441,18 @@
     private boolean mIsMacRandomizationEnabled = true;
 
     /**
+     * Indicates if the end user has expressed an explicit opinion about the
+     * meteredness of this network, such as through the Settings app.
+     * This value is one of {@link #METERED_OVERRIDE_NONE}, {@link #METERED_OVERRIDE_METERED},
+     * or {@link #METERED_OVERRIDE_NOT_METERED}.
+     * <p>
+     * This should always override any values from {@link WifiInfo#getMeteredHint()}.
+     *
+     * By default this field is set to {@link #METERED_OVERRIDE_NONE}.
+     */
+    private int mMeteredOverride = METERED_OVERRIDE_NONE;
+
+    /**
      * Configures the auto-association status of this Passpoint configuration. A value of true
      * indicates that the configuration will be considered for auto-connection, a value of false
      * indicates that only manual connection will work - the framework will not auto-associate to
@@ -463,6 +478,16 @@
     }
 
     /**
+     * Sets the metered override setting for this Passpoint configuration.
+     *
+     * @param meteredOverride One of the values in {@link MeteredOverride}
+     * @hide
+     */
+    public void setMeteredOverride(@MeteredOverride int meteredOverride) {
+        mMeteredOverride = meteredOverride;
+    }
+
+    /**
      * Indicates whether the Passpoint configuration may be auto-connected to by the framework. A
      * value of true indicates that auto-connection can happen, a value of false indicates that it
      * cannot. However, even when auto-connection is not possible manual connection by the user is
@@ -478,6 +503,18 @@
     }
 
     /**
+     * Indicates whether the user chose this configuration to be treated as metered or not.
+     *
+     * @return One of the values in {@link MeteredOverride}
+     * @hide
+     */
+    @SystemApi
+    @MeteredOverride
+    public int getMeteredOverride() {
+        return mMeteredOverride;
+    }
+
+    /**
      * Indicates whether a randomized MAC address or device MAC address will be used for
      * connections to this Passpoint network. If true, a randomized MAC address will be used.
      * Otherwise, the device MAC address will be used.
@@ -534,6 +571,7 @@
         mCarrierId = source.mCarrierId;
         mIsAutoJoinEnabled = source.mIsAutoJoinEnabled;
         mIsMacRandomizationEnabled = source.mIsMacRandomizationEnabled;
+        mMeteredOverride = source.mMeteredOverride;
     }
 
     @Override
@@ -565,6 +603,7 @@
         dest.writeInt(mCarrierId);
         dest.writeBoolean(mIsAutoJoinEnabled);
         dest.writeBoolean(mIsMacRandomizationEnabled);
+        dest.writeInt(mMeteredOverride);
     }
 
     @Override
@@ -597,6 +636,7 @@
                 && mCarrierId == that.mCarrierId
                 && mIsAutoJoinEnabled == that.mIsAutoJoinEnabled
                 && mIsMacRandomizationEnabled == that.mIsMacRandomizationEnabled
+                && mMeteredOverride == that.mMeteredOverride
                 && (mServiceFriendlyNames == null ? that.mServiceFriendlyNames == null
                 : mServiceFriendlyNames.equals(that.mServiceFriendlyNames));
     }
@@ -607,7 +647,8 @@
                 mUpdateIdentifier, mCredentialPriority, mSubscriptionCreationTimeInMillis,
                 mSubscriptionExpirationTimeInMillis, mUsageLimitUsageTimePeriodInMinutes,
                 mUsageLimitStartTimeInMillis, mUsageLimitDataLimit, mUsageLimitTimeLimitInMinutes,
-                mServiceFriendlyNames, mCarrierId, mIsAutoJoinEnabled, mIsMacRandomizationEnabled);
+                mServiceFriendlyNames, mCarrierId, mIsAutoJoinEnabled, mIsMacRandomizationEnabled,
+                mMeteredOverride);
     }
 
     @Override
@@ -663,6 +704,7 @@
         builder.append("CarrierId:" + mCarrierId);
         builder.append("IsAutoJoinEnabled:" + mIsAutoJoinEnabled);
         builder.append("mIsMacRandomizationEnabled:" + mIsMacRandomizationEnabled);
+        builder.append("mMeteredOverride:" + mMeteredOverride);
         return builder.toString();
     }
 
@@ -770,6 +812,7 @@
                 config.mCarrierId = in.readInt();
                 config.mIsAutoJoinEnabled = in.readBoolean();
                 config.mIsMacRandomizationEnabled = in.readBoolean();
+                config.mMeteredOverride = in.readInt();
                 return config;
             }
 
diff --git a/wifi/java/com/android/server/wifi/BaseWifiService.java b/wifi/java/com/android/server/wifi/BaseWifiService.java
index 080c6c7..b467553 100644
--- a/wifi/java/com/android/server/wifi/BaseWifiService.java
+++ b/wifi/java/com/android/server/wifi/BaseWifiService.java
@@ -198,6 +198,11 @@
     }
 
     @Override
+    public void setMeteredOverridePasspoint(String fqdn, int meteredOverride) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public boolean startScan(String packageName, String featureId) {
         throw new UnsupportedOperationException();
     }
diff --git a/wifi/tests/README.md b/wifi/tests/README.md
index b0594f2..f909404 100644
--- a/wifi/tests/README.md
+++ b/wifi/tests/README.md
@@ -8,12 +8,9 @@
 The easiest way to run tests is simply run
 
 ```
-frameworks/base/wifi/tests/runtests.sh
+atest android.net.wifi
 ```
 
-`runtests.sh` will build the test project and all of its dependencies and push the APK to the
-connected device. It will then run the tests on the device.
-
 To pick up changes in framework/base, you will need to:
 1. rebuild the framework library 'make -j32'
 2. sync over the updated library to the device 'adb sync'
@@ -24,22 +21,6 @@
 2. adb reboot
 3. adb remount
 
-See below for a few example of options to limit which tests are run.
-See the
-[AndroidJUnitRunner Documentation](https://developer.android.com/reference/android/support/test/runner/AndroidJUnitRunner.html)
-for more details on the supported options.
-
-```
-runtests.sh -e package android.net.wifi
-runtests.sh -e class android.net.wifi.WifiScannerTest
-```
-
-If you manually build and push the test APK to the device you can run tests using
-
-```
-adb shell am instrument -w 'android.net.wifi.test/androidx.test.runner.AndroidJUnitRunner'
-```
-
 ## Adding Tests
 Tests can be added by adding classes to the src directory. JUnit4 style test cases can
 be written by simply annotating test methods with `org.junit.Test`.
diff --git a/wifi/tests/runtests.sh b/wifi/tests/runtests.sh
deleted file mode 100755
index 4024371..0000000
--- a/wifi/tests/runtests.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/usr/bin/env bash
-
-if [ -z $ANDROID_BUILD_TOP ]; then
-  echo "You need to source and lunch before you can use this script"
-  exit 1
-fi
-
-echo "Running tests"
-
-set -e # fail early
-
-echo "+ mmma -j32 $ANDROID_BUILD_TOP/frameworks/base/wifi/tests"
-# NOTE Don't actually run the command above since this shell doesn't inherit functions from the
-#      caller.
-$ANDROID_BUILD_TOP/build/soong/soong_ui.bash --make-mode MODULES-IN-frameworks-base-wifi-tests
-
-set -x # print commands
-
-adb wait-for-device
-
-TARGET_ARCH=$($ANDROID_BUILD_TOP/build/soong/soong_ui.bash --dumpvar-mode TARGET_ARCH)
-adb install -r -g "$OUT/testcases/FrameworksWifiApiTests/$TARGET_ARCH/FrameworksWifiApiTests.apk"
-
-adb shell am instrument --no-hidden-api-checks -w "$@" \
-  'android.net.wifi.test/androidx.test.runner.AndroidJUnitRunner'
diff --git a/wifi/tests/src/android/net/wifi/WifiInfoTest.java b/wifi/tests/src/android/net/wifi/WifiInfoTest.java
index 04759ac..311bbc4 100644
--- a/wifi/tests/src/android/net/wifi/WifiInfoTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiInfoTest.java
@@ -64,7 +64,7 @@
         writeWifiInfo.setOsuAp(true);
         writeWifiInfo.setFQDN(TEST_FQDN);
         writeWifiInfo.setProviderFriendlyName(TEST_PROVIDER_NAME);
-        writeWifiInfo.setAppPackageName(TEST_PACKAGE_NAME);
+        writeWifiInfo.setRequestingPackageName(TEST_PACKAGE_NAME);
         writeWifiInfo.setWifiStandard(TEST_WIFI_STANDARD);
         writeWifiInfo.setMaxSupportedTxLinkSpeedMbps(TEST_MAX_SUPPORTED_TX_LINK_SPEED_MBPS);
         writeWifiInfo.setMaxSupportedRxLinkSpeedMbps(TEST_MAX_SUPPORTED_RX_LINK_SPEED_MBPS);
@@ -83,7 +83,7 @@
         assertTrue(readWifiInfo.isTrusted());
         assertTrue(readWifiInfo.isOsuAp());
         assertTrue(readWifiInfo.isPasspointAp());
-        assertEquals(TEST_PACKAGE_NAME, readWifiInfo.getAppPackageName());
+        assertEquals(TEST_PACKAGE_NAME, readWifiInfo.getRequestingPackageName());
         assertEquals(TEST_FQDN, readWifiInfo.getPasspointFqdn());
         assertEquals(TEST_PROVIDER_NAME, readWifiInfo.getPasspointProviderFriendlyName());
         assertEquals(TEST_WIFI_STANDARD, readWifiInfo.getWifiStandard());
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index f369203..0c2876e 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -16,6 +16,7 @@
 
 package android.net.wifi;
 
+import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_METERED;
 import static android.net.wifi.WifiManager.ActionListener;
 import static android.net.wifi.WifiManager.BUSY;
 import static android.net.wifi.WifiManager.ERROR;
@@ -881,17 +882,6 @@
     }
 
     /**
-     * Verify main looper is used when handler is not provided.
-     */
-    @Test
-    public void registerSoftApCallbackUsesMainExecutorOnNoExecutorProvided() {
-        when(mContext.getMainExecutor()).thenReturn(
-                new HandlerExecutor(new Handler(mLooper.getLooper())));
-        mWifiManager.registerSoftApCallback(mSoftApCallback);
-        verify(mContext).getMainExecutor();
-    }
-
-    /**
      * Verify the call to registerSoftApCallback goes to WifiServiceImpl.
      */
     @Test
@@ -1389,11 +1379,10 @@
     @Test
     public void registerTrafficStateCallbackUsesMainLooperOnNullArgumentForHandler()
             throws Exception {
-        when(mContext.getMainExecutor()).thenReturn(
-                new HandlerExecutor(new Handler(mLooper.getLooper())));
         ArgumentCaptor<ITrafficStateCallback.Stub> callbackCaptor =
                 ArgumentCaptor.forClass(ITrafficStateCallback.Stub.class);
-        mWifiManager.registerTrafficStateCallback(mTrafficStateCallback);
+        mWifiManager.registerTrafficStateCallback(
+                new HandlerExecutor(new Handler(mLooper.getLooper())), mTrafficStateCallback);
         verify(mWifiService).registerTrafficStateCallback(
                 any(IBinder.class), callbackCaptor.capture(), anyInt());
 
@@ -1474,11 +1463,11 @@
     @Test
     public void registerNetworkRequestMatchCallbackCallGoesToWifiServiceImpl()
             throws Exception {
-        when(mContext.getMainExecutor()).thenReturn(
-                new HandlerExecutor(new Handler(mLooper.getLooper())));
         ArgumentCaptor<INetworkRequestMatchCallback.Stub> callbackCaptor =
                 ArgumentCaptor.forClass(INetworkRequestMatchCallback.Stub.class);
-        mWifiManager.registerNetworkRequestMatchCallback(mNetworkRequestMatchCallback);
+        mWifiManager.registerNetworkRequestMatchCallback(
+                new HandlerExecutor(new Handler(mLooper.getLooper())),
+                mNetworkRequestMatchCallback);
         verify(mWifiService).registerNetworkRequestMatchCallback(
                 any(IBinder.class), callbackCaptor.capture(), anyInt());
 
@@ -1530,11 +1519,11 @@
     @Test
     public void networkRequestUserSelectionCallbackCallGoesToWifiServiceImpl()
             throws Exception {
-        when(mContext.getMainExecutor()).thenReturn(
-                new HandlerExecutor(new Handler(mLooper.getLooper())));
         ArgumentCaptor<INetworkRequestMatchCallback.Stub> callbackCaptor =
                 ArgumentCaptor.forClass(INetworkRequestMatchCallback.Stub.class);
-        mWifiManager.registerNetworkRequestMatchCallback(mNetworkRequestMatchCallback);
+        mWifiManager.registerNetworkRequestMatchCallback(
+                new HandlerExecutor(new Handler(mLooper.getLooper())),
+                mNetworkRequestMatchCallback);
         verify(mWifiService).registerNetworkRequestMatchCallback(
                 any(IBinder.class), callbackCaptor.capture(), anyInt());
 
@@ -1808,6 +1797,16 @@
         verify(mWifiService).setMacRandomizationSettingPasspointEnabled(fqdn, true);
     }
 
+    /**
+     * Test behavior of
+     * {@link WifiManager#setMacRandomizationSettingPasspointEnabled(String, boolean)}
+     */
+    @Test
+    public void testSetMeteredOverridePasspoint() throws Exception {
+        final String fqdn = "FullyQualifiedDomainName";
+        mWifiManager.setMeteredOverridePasspoint(fqdn, METERED_OVERRIDE_METERED);
+        verify(mWifiService).setMeteredOverridePasspoint(fqdn, METERED_OVERRIDE_METERED);
+    }
 
     /**
      * Test behavior of {@link WifiManager#disconnect()}
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
index 603e78b..654154d 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
@@ -16,6 +16,8 @@
 
 package android.net.wifi.hotspot2;
 
+import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_NONE;
+
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
@@ -173,6 +175,7 @@
         assertFalse(config.validateForR2());
         assertTrue(config.isAutoJoinEnabled());
         assertTrue(config.isMacRandomizationEnabled());
+        assertTrue(config.getMeteredOverride() == METERED_OVERRIDE_NONE);
     }
 
     /**